source: main/trunk/greenstone2/perllib/cpan/Mojo/Collection.pm@ 32205

Last change on this file since 32205 was 32205, checked in by ak19, 6 years ago

First set of commits to do with implementing the new 'paged_html' output option of PDFPlugin that uses using xpdftools' new pdftohtml. So far tested only on Linux (64 bit), but things work there so I'm optimistically committing the changes since they work. 2. Committing the pre-built Linux binaries of XPDFtools for both 32 and 64 bit built by the XPDF group. 2. To use the correct bitness variant of xpdftools, setup.bash now exports the BITNESS env var, consulted by gsConvert.pl. 3. All the perl code changes to do with using xpdf tools' pdftohtml to generate paged_html and feed it in the desired form into GS(3): gsConvert.pl, PDFPlugin.pm and its parent ConvertBinaryPFile.pm have been modified to make it all work. xpdftools' pdftohtml generates a folder containing an html file and a screenshot for each page in a PDF (as well as an index.html linking to each page's html). However, we want a single html file that contains each individual 'page' html's content in a div, and need to do some further HTML style, attribute and structure modifications to massage the xpdftool output to what we want for GS. In order to parse and manipulate the HTML 'DOM' to do this, we're using the Mojo::DOM package that Dr Bainbridge found and which he's compiled up. Mojo::DOM is therefore also committed in this revision. Some further changes and some display fixes are required, but need to check with the others about that.

File size: 9.2 KB
Line 
1package Mojo::Collection;
2use Mojo::Base -strict;
3
4use Carp 'croak';
5use Exporter 'import';
6use List::Util;
7use Mojo::ByteStream;
8use Scalar::Util 'blessed';
9
10our @EXPORT_OK = ('c');
11
12sub TO_JSON { [@{shift()}] }
13
14sub c { __PACKAGE__->new(@_) }
15
16sub compact {
17 my $self = shift;
18 return $self->new(grep { defined && (ref || length) } @$self);
19}
20
21sub each {
22 my ($self, $cb) = @_;
23 return @$self unless $cb;
24 my $i = 1;
25 $_->$cb($i++) for @$self;
26 return $self;
27}
28
29sub first {
30 my ($self, $cb) = (shift, shift);
31 return $self->[0] unless $cb;
32 return List::Util::first { $_ =~ $cb } @$self if ref $cb eq 'Regexp';
33 return List::Util::first { $_->$cb(@_) } @$self;
34}
35
36sub flatten { $_[0]->new(_flatten(@{$_[0]})) }
37
38sub grep {
39 my ($self, $cb) = (shift, shift);
40 return $self->new(grep { $_ =~ $cb } @$self) if ref $cb eq 'Regexp';
41 return $self->new(grep { $_->$cb(@_) } @$self);
42}
43
44sub join {
45 Mojo::ByteStream->new(join $_[1] // '', map {"$_"} @{$_[0]});
46}
47
48sub last { shift->[-1] }
49
50sub map {
51 my ($self, $cb) = (shift, shift);
52 return $self->new(map { $_->$cb(@_) } @$self);
53}
54
55sub new {
56 my $class = shift;
57 return bless [@_], ref $class || $class;
58}
59
60sub reduce {
61 my $self = shift;
62 @_ = (@_, @$self);
63 goto &List::Util::reduce;
64}
65
66sub reverse { $_[0]->new(reverse @{$_[0]}) }
67
68sub shuffle { $_[0]->new(List::Util::shuffle @{$_[0]}) }
69
70sub size { scalar @{$_[0]} }
71
72sub slice {
73 my $self = shift;
74 return $self->new(@$self[@_]);
75}
76
77sub sort {
78 my ($self, $cb) = @_;
79
80 return $self->new(sort @$self) unless $cb;
81
82 my $caller = caller;
83 no strict 'refs';
84 my @sorted = sort {
85 local (*{"${caller}::a"}, *{"${caller}::b"}) = (\$a, \$b);
86 $a->$cb($b);
87 } @$self;
88 return $self->new(@sorted);
89}
90
91sub tap { shift->Mojo::Base::tap(@_) }
92
93sub to_array { [@{shift()}] }
94
95sub uniq {
96 my ($self, $cb) = (shift, shift);
97 my %seen;
98 return $self->new(grep { !$seen{$_->$cb(@_) // ''}++ } @$self) if $cb;
99 return $self->new(grep { !$seen{$_ // ''}++ } @$self);
100}
101
102sub with_roles { shift->Mojo::Base::with_roles(@_) }
103
104sub _flatten {
105 map { _ref($_) ? _flatten(@$_) : $_ } @_;
106}
107
108sub _ref { ref $_[0] eq 'ARRAY' || blessed $_[0] && $_[0]->isa(__PACKAGE__) }
109
1101;
111
112=encoding utf8
113
114=head1 NAME
115
116Mojo::Collection - Collection
117
118=head1 SYNOPSIS
119
120 use Mojo::Collection;
121
122 # Manipulate collection
123 my $collection = Mojo::Collection->new(qw(just works));
124 unshift @$collection, 'it';
125 say $collection->join("\n");
126
127 # Chain methods
128 $collection->map(sub { ucfirst })->shuffle->each(sub {
129 my ($word, $num) = @_;
130 say "$num: $word";
131 });
132
133 # Use the alternative constructor
134 use Mojo::Collection 'c';
135 c(qw(a b c))->join('/')->url_escape->say;
136
137=head1 DESCRIPTION
138
139L<Mojo::Collection> is an array-based container for collections.
140
141 # Access array directly to manipulate collection
142 my $collection = Mojo::Collection->new(1 .. 25);
143 $collection->[23] += 100;
144 say for @$collection;
145
146=head1 FUNCTIONS
147
148L<Mojo::Collection> implements the following functions, which can be imported
149individually.
150
151=head2 c
152
153 my $collection = c(1, 2, 3);
154
155Construct a new array-based L<Mojo::Collection> object.
156
157=head1 METHODS
158
159L<Mojo::Collection> implements the following methods.
160
161=head2 TO_JSON
162
163 my $array = $collection->TO_JSON;
164
165Alias for L</"to_array">.
166
167=head2 compact
168
169 my $new = $collection->compact;
170
171Create a new collection with all elements that are defined and not an empty
172string.
173
174 # "0, 1, 2, 3"
175 c(0, 1, undef, 2, '', 3)->compact->join(', ');
176
177=head2 each
178
179 my @elements = $collection->each;
180 $collection = $collection->each(sub {...});
181
182Evaluate callback for each element in collection, or return all elements as a
183list if none has been provided. The element will be the first argument passed
184to the callback, and is also available as C<$_>.
185
186 # Make a numbered list
187 $collection->each(sub {
188 my ($e, $num) = @_;
189 say "$num: $e";
190 });
191
192=head2 first
193
194 my $first = $collection->first;
195 my $first = $collection->first(qr/foo/);
196 my $first = $collection->first(sub {...});
197 my $first = $collection->first('some_method');
198 my $first = $collection->first('some_method', @args);
199
200Evaluate regular expression/callback for, or call method on, each element in
201collection and return the first one that matched the regular expression, or for
202which the callback/method returned true. The element will be the first argument
203passed to the callback, and is also available as C<$_>.
204
205 # Longer version
206 my $first = $collection->first(sub { $_->some_method(@args) });
207
208 # Find first value that contains the word "mojo"
209 my $interesting = $collection->first(qr/mojo/i);
210
211 # Find first value that is greater than 5
212 my $greater = $collection->first(sub { $_ > 5 });
213
214=head2 flatten
215
216 my $new = $collection->flatten;
217
218Flatten nested collections/arrays recursively and create a new collection with
219all elements.
220
221 # "1, 2, 3, 4, 5, 6, 7"
222 c(1, [2, [3, 4], 5, [6]], 7)->flatten->join(', ');
223
224=head2 grep
225
226 my $new = $collection->grep(qr/foo/);
227 my $new = $collection->grep(sub {...});
228 my $new = $collection->grep('some_method');
229 my $new = $collection->grep('some_method', @args);
230
231Evaluate regular expression/callback for, or call method on, each element in
232collection and create a new collection with all elements that matched the
233regular expression, or for which the callback/method returned true. The element
234will be the first argument passed to the callback, and is also available as
235C<$_>.
236
237 # Longer version
238 my $new = $collection->grep(sub { $_->some_method(@args) });
239
240 # Find all values that contain the word "mojo"
241 my $interesting = $collection->grep(qr/mojo/i);
242
243 # Find all values that are greater than 5
244 my $greater = $collection->grep(sub { $_ > 5 });
245
246=head2 join
247
248 my $stream = $collection->join;
249 my $stream = $collection->join("\n");
250
251Turn collection into L<Mojo::ByteStream>.
252
253 # Join all values with commas
254 $collection->join(', ')->say;
255
256=head2 last
257
258 my $last = $collection->last;
259
260Return the last element in collection.
261
262=head2 map
263
264 my $new = $collection->map(sub {...});
265 my $new = $collection->map('some_method');
266 my $new = $collection->map('some_method', @args);
267
268Evaluate callback for, or call method on, each element in collection and create
269a new collection from the results. The element will be the first argument
270passed to the callback, and is also available as C<$_>.
271
272 # Longer version
273 my $new = $collection->map(sub { $_->some_method(@args) });
274
275 # Append the word "mojo" to all values
276 my $mojoified = $collection->map(sub { $_ . 'mojo' });
277
278=head2 new
279
280 my $collection = Mojo::Collection->new(1, 2, 3);
281
282Construct a new array-based L<Mojo::Collection> object.
283
284=head2 reduce
285
286 my $result = $collection->reduce(sub {...});
287 my $result = $collection->reduce(sub {...}, $initial);
288
289Reduce elements in collection with a callback and return its final result,
290setting C<$a> and C<$b> each time the callback is executed. The first time C<$a>
291will be set to an optional initial value or the first element in the collection.
292And from then on C<$a> will be set to the return value of the callback, while
293C<$b> will always be set to the next element in the collection.
294
295 # Calculate the sum of all values
296 my $sum = $collection->reduce(sub { $a + $b });
297
298 # Count how often each value occurs in collection
299 my $hash = $collection->reduce(sub { $a->{$b}++; $a }, {});
300
301=head2 reverse
302
303 my $new = $collection->reverse;
304
305Create a new collection with all elements in reverse order.
306
307=head2 slice
308
309 my $new = $collection->slice(4 .. 7);
310
311Create a new collection with all selected elements.
312
313 # "B C E"
314 c('A', 'B', 'C', 'D', 'E')->slice(1, 2, 4)->join(' ');
315
316=head2 shuffle
317
318 my $new = $collection->shuffle;
319
320Create a new collection with all elements in random order.
321
322=head2 size
323
324 my $size = $collection->size;
325
326Number of elements in collection.
327
328=head2 sort
329
330 my $new = $collection->sort;
331 my $new = $collection->sort(sub {...});
332
333Sort elements based on return value of a callback and create a new collection
334from the results, setting C<$a> and C<$b> to the elements being compared, each
335time the callback is executed.
336
337 # Sort values case-insensitive
338 my $case_insensitive = $collection->sort(sub { uc($a) cmp uc($b) });
339
340=head2 tap
341
342 $collection = $collection->tap(sub {...});
343
344Alias for L<Mojo::Base/"tap">.
345
346=head2 to_array
347
348 my $array = $collection->to_array;
349
350Turn collection into array reference.
351
352=head2 uniq
353
354 my $new = $collection->uniq;
355 my $new = $collection->uniq(sub {...});
356 my $new = $collection->uniq('some_method');
357 my $new = $collection->uniq('some_method', @args);
358
359Create a new collection without duplicate elements, using the string
360representation of either the elements or the return value of the
361callback/method to decide uniqueness. Note that C<undef> and empty string are
362treated the same.
363
364 # Longer version
365 my $new = $collection->uniq(sub { $_->some_method(@args) });
366
367 # "foo bar baz"
368 c('foo', 'bar', 'bar', 'baz')->uniq->join(' ');
369
370 # "[[1, 2], [2, 1]]"
371 c([1, 2], [2, 1], [3, 2])->uniq(sub{ $_->[1] })->to_array;
372
373=head2 with_roles
374
375 my $new_class = Mojo::Collection->with_roles('Mojo::Collection::Role::One');
376 my $new_class = Mojo::Collection->with_roles('+One', '+Two');
377 $collection = $collection->with_roles('+One', '+Two');
378
379Alias for L<Mojo::Base/"with_roles">.
380
381=head1 SEE ALSO
382
383L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
384
385=cut
Note: See TracBrowser for help on using the repository browser.