File Coverage

blib/lib/Text/Annotate/WordScan.pm
Criterion Covered Total %
statement 101 130 77.6
branch 23 40 57.5
condition 9 12 75.0
subroutine 15 21 71.4
pod 0 6 0.0
total 148 209 70.8


line stmt bran cond sub pod time code
1             package Text::Annotate::WordScan;
2 2     2   7231 use strict;
  2         5  
  2         70  
3 2     2   11 use Carp;
  2         3  
  2         3481  
4             our $VERSION;
5             $VERSION = 0.01_2;
6              
7             sub scan_words {
8 2     2 0 61 my ($class, $content, $cbk) = @_;
9 2 50       10 ($cbk) or croak "need callback";
10 2         13 my $it = $class->new_it($content);
11              
12             # moving around for speed
13             # my @pipe = (\&_findsen, \&_findwords, _gfindphrases(), \&_canon, $cbk);
14 2         21 my @pipe = (\&_findsen, \&_findwords, \&_precanon, _gfindphrases(), $cbk);
15 2         11 my $c = $class->pipe_to_code(\@pipe);
16 2         59 $c->([$content]);
17             };
18              
19              
20             sub scan_wordsx {
21 0     0 0 0 my ($class, $content, $cbk) = @_;
22 0 0       0 ($cbk) or croak "need callback";
23 0         0 my $it = $class->new_it($content);
24              
25             # a nest of while(s): semipredicate problem.
26             # bah, define "untrue" weird value.
27              
28 0         0 my @pipe = (\&_findsen, \&_findwords, \&_canon, $cbk);
29 0         0 my $c = $class->pipe_to_code(\@pipe);
30 0         0 $c->([$content]);
31             };
32              
33             sub new_it {
34 2     2 0 6 my $class = shift;
35 2         4 my $content = shift;
36 2         12 my $self = bless { c => $content }, $class;
37             };
38              
39             sub ping {
40 0     0 0 0 my $self = shift;
41 0 0       0 return ($self->{c} =~ /\s*([^\!\?\.]+)\s*/sg) ? $1 : ();
42             };
43              
44             sub pipe_to_code {
45 2     2 0 4 my ($self, $pipe) = @_;
46            
47 2         4 my $buf = 'sub {';
48 2         9 my $n = 0;
49              
50 2         5 my $vvprev = '$_[0]'; # change for OO
51              
52 2 50       7 foreach my $e (@$pipe) { $e = ref $e ? Text::Annotate::WordScan::SubWrap->new($e) : $e->new };
  10         43  
53              
54 2         6 foreach my $e (@$pipe) {
55 10         16 my $vvar = '$v'.$n;
56 10         15 my $debug = my $debug2 = "";
57             # my $debug = "warn 'pipesegment $n in:', Dumper($vvprev);";
58             # my $debug2 = "warn 'pipesegment $n out:', Dumper($vvar);";
59 10         25 $buf .= "$debug \$pipe->[$n]->add($vvprev); while (my $vvar = \$pipe->[$n]->iterate) { $debug2; ";
60 10         13 $vvprev = $vvar;
61 10         17 $n++;
62             }
63              
64 2         8 $buf .= '}' x (@$pipe+1);
65 2 50       580 (my $subref = eval $buf) or die "Didn't like that: $@";
66             }
67            
68             sub _findsen {
69 4     4   7 my $in = shift;
70 4         6 my @out;
71 4         10 foreach my $e (@$in) {
72 2         4 my $tidy = $e;
73 2         50 $tidy =~ s/\s+/ /sg;
74 2         20 push @out, split /[\.\?\!]+/, $tidy
75             };
76 4 100       16 @out ? \@out : ();
77             };
78              
79             sub _findwords {
80 4     4   8 my $in = shift;
81 4         6 my @out;
82 4         9 foreach my $sen (@$in) {
83 8         35 my @words = grep {length $_} (split /[\s\!\?\.]+/, $sen);
  29         43  
84 8 50       30 push @out, \@words if @words;
85             }
86 4 100       13 @out ? \@out : ();
87             }
88              
89             # and now, the tricky bit.
90              
91             # we are simultaneously...
92             # - splitting into words
93             # - regrouping those words into potential phrases (tricky bit, as an iterator)
94             # - confusing outselves totally
95              
96             # - MAKE SURE WE DON'T LOSE STUFF
97             # - OO may actually be tidier.
98              
99             # - This is now not spinning, but not quite working either.
100              
101             sub _gfindphrases {
102 2     2   5 my @sentences;
103 2         4 my $phl = 0;
104 2         5 my $max_phl = 4;
105 2         2 my $outmax = 10000; # TODO: MAKE CONFIGURABLE
106 2         6 my $delimiter = "";
107 2         3 my ($pos, $phraselength) = (0, 0);
108              
109             my $s =
110             sub {
111 4     4   6 my $in = shift;
112 4 100 66     26 push @sentences, @$in if ($in && @$in);
113 4         6 my @out;
114 4         18 while (@out < $outmax) {
115 64 100       115 last if (!@sentences); # needed?
116 62         77 my $foo = @sentences;
117 62         76 my $max = $pos + $phraselength;
118 62 100       59 if ($max >= @{$sentences[0]}) {
  62         130  
119 19         21 $pos = 0;
120 19         19 $phraselength++;
121 19         21 $max = $pos + $phraselength;
122             };
123 62 100 100     128 if (($phraselength > $max_phl) || ($phraselength >= @{$sentences[0]})) {
  60         171  
124 8         8 $phraselength = 0;
125 8         17 $max = $pos + $phraselength;
126 8         11 shift @sentences;
127             }
128 62 100       116 last if (!@sentences);
129 60         123 push @out, (join $delimiter, @{$sentences[0]}[$pos++..$max]);
  60         222  
130            
131             };
132 4 100       14 return @out ? \@out : ();
133 2         28 };
134 2         8 $s;
135             }
136              
137              
138             sub _findphrasesold { # TURN THIS INTO ITERATOR!
139 0     0   0 my $data = shift;
140 0         0 my @out;
141 0         0 foreach my $sentance (@$data) {
142 0         0 my @words = grep {length $_} (split /[\s\!\?\.]+/, $sentance);
  0         0  
143 0         0 my $i = 0;
144 0         0 while (1) {
145 0         0 foreach my $phraselength (qw(0 1 2 3 4)) {
146 0         0 my $max = $i + $phraselength;
147 0 0       0 last if ($max >= @words);
148 0         0 my $foo = join " ", @words[$i..$max];
149 0         0 push @out, $foo;
150             };
151 0         0 $i++;
152 0 0       0 last if ($i > @words); # hmm
153             }
154             };
155 0         0 \@out;
156             };
157              
158              
159             sub _precanon {
160 4     4   7 my $data = shift;
161 4         4 my @out;
162 4         10 foreach my $sentence (@$data) {
163 8         10 foreach my $word (@$sentence) {
164 22         26 $word = lc $word;
165 22         46 $word =~ s/[^a-z0-9]//sg;
166             }
167             }
168 4         11 $data;
169             };
170              
171             sub _canon {
172 2     2   4 my $data = shift;
173 2         3 my @out;
174 2         5 foreach my $e (@$data) {
175 2         4 $e = lc $e;
176 2         9 $e =~ s/[^a-z0-9]//sg;
177 2         6 push @out, $e;
178             }
179 2         10 \@out;
180             };
181              
182              
183             sub canonicalize_id {
184 2     2 0 4 my ($self, $word) = @_;
185 2         7 return _canon([$word])->[0];
186             };
187              
188             package Text::Annotate::WordScan::SubWrap;
189              
190             sub new {
191 10     10   13 my ($class, $sub) = @_;
192 10   33     36 $class = ref $class || $class;
193 10 50       27 (ref $sub eq "CODE") or die "'$sub' ain't a sub";
194 10         20 my $self = [$sub];
195 10         34 bless $self, $class;
196             };
197              
198             sub add {
199 10     10   17 my ($self, $data) = @_;
200 10         279 $self->[1] = $data;
201             };
202              
203             # todo: debugging is a problem.
204              
205             sub iterate {
206 18     18   28 my $self = shift;
207 18         23 my $fn = $self->[0];
208 18         36 my $out = [];
209 18         48 $out = $fn->($self->[1]);
210 18         134 $self->[1] = undef;
211 18 100 100     1331 ($out && @$out) ? $out : ();
212             };
213            
214             package CGI::Kwiki::WordScan::Buffer;
215              
216             sub new {
217 0     0     return bless [];
218             };
219              
220             sub add {
221 0     0     my ($self, $data) = @_;
222 0 0         (ref $data eq "ARRAY") or die "nay";
223 0           push @$self, @$data;
224             };
225              
226             sub iterate {
227 0     0     my $self = shift;
228 0 0         @$self ? [shift @$self] : ();
229             };
230              
231             1;