File Coverage

blib/lib/Mojolicious/Plugin/Loop.pm
Criterion Covered Total %
statement 44 45 97.7
branch 20 24 83.3
condition n/a
subroutine 18 18 100.0
pod 15 15 100.0
total 97 102 95.1


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Loop;
2 2     2   4251 use Mojo::Base 'Mojolicious::Plugin';
  2         5  
  2         17  
3              
4             our $VERSION = '0.03';
5              
6             our $ITERATOR;
7              
8 6     6 1 14 sub count { $_[0]->{index} + 1 }
9 4 50   4 1 11 sub even { $_[0]->{index} % 2 ? 0 : 1 }
10 6     6 1 13 sub first { $_[0]->{index} == 0 }
11 9     9 1 28 sub index { $_[0]->{index} }
12 6     6 1 22 sub key { $_[0]->{key} }
13 6     6 1 9 sub last { $_[0]->{index} + 1 == @{$_[0]->{items}} }
  6         14  
14 6     6 1 17 sub max { $_[0]->size - 1 }
15              
16             sub next {
17 16     16 1 295 my $self = shift;
18 16 100       22 return 0 if @{$self->{items}} <= ++$self->{index};
  16         50  
19 12         29 $self->{item} = $self->{items}[$self->{index}];
20 12 100       32 $self->{key} = $self->{map} ? $self->{item} : $self->{index};
21 12         29 return 1;
22             }
23              
24 6 100   6 1 17 sub odd { $_[0]->{index} % 2 ? 1 : 0 }
25 6 100   6 1 19 sub parity { $_[0]->{index} % 2 ? 'odd' : 'even' }
26              
27             sub peek {
28 12     12 1 19 my ($self, $offset) = @_;
29 12         71 my $index = $_[0]->{index} + $offset;
30 12 100       37 return $index < 0 ? undef : $_[0]->{items}[$index];
31             }
32              
33 4     4 1 14 sub reset { $_[0]->{index} = -1; $_[0] }
  4         10  
34 12     12 1 16 sub size { int @{$_[0]->{items}} }
  12         39  
35 9 100   9 1 32 sub val { $_[0]->{map} ? $_[0]->{map}{$_[0]->{item}} : $_[0]->{item} }
36              
37             sub register {
38 2     2 1 98 my ($self, $app, $config) = @_;
39              
40             $app->helper(
41             loop => sub {
42 80     80   62687 my ($c, $data, $cb) = @_;
43 80 100       235 return $ITERATOR if @_ == 1;
44 4         40 return Mojolicious::Plugin::Loop->_iterate($data, $cb);
45             }
46 2         24 );
47             }
48              
49             sub _iterate {
50 4     4   14 my ($class, $data, $cb) = @_;
51 4         37 my $bs = Mojo::ByteStream->new;
52 4         48 my $self = bless {cb => $cb}, $class;
53              
54 4 100       39 if (UNIVERSAL::isa($data, 'ARRAY')) {
    50          
    0          
55 3         31 @$self{qw(items)} = ($data);
56             }
57             elsif (UNIVERSAL::isa($data, 'HASH')) {
58 1         8 @$self{qw(items map)} = ([sort keys %$data], $data);
59             }
60             elsif (UNIVERSAL::can($data, 'to_array')) {
61 0         0 @$self{qw(items)} = $data->to_array;
62             }
63              
64 4         25 $self->reset;
65 4 100       16 return $self unless $cb;
66 3         9 local $ITERATOR = $self;
67              
68             LOOP:
69 3         18 while ($self->next) {
70 9         29 $bs .= $cb->($self->{item}, $self->{index});
71             }
72              
73 3         17 return $bs;
74             }
75              
76             1;
77              
78             =encoding utf8
79              
80             =head1 NAME
81              
82             Mojolicious::Plugin::Loop - Loop plugin for Mojolicious
83              
84             =head1 SYNOPSIS
85              
86             =head2 Application
87              
88             use Mojolicious::Lite;
89             plugin 'loop';
90              
91             =head2 Template
92              
93             %= loop [1,2,3,4], begin
94             ---
95             key/val: <%= loop->key %>/<%= loop->val %>
96             count: <%= loop->index %> + 1 = <%= loop->count %> (index + 1)
97             size: <%= loop->max %> + 1 = <%= loop->size %> (max + 1)
98             prev: <%= loop->peek(-1) // 'undef' %> (peek -1)
99             next: <%= loop->peek(1) // 'undef' %> (peek +1)
100             parity: <%= loop->parity %>
101             odd/even: <%= loop->odd ? 'odd' : loop->even ? 'even' : 'unknown' %>
102             first: <%= loop->first ? 'yes' : 'no' %>
103             last: <%= loop->last ? 'yes' : 'no' %>
104             % end
105              
106             %= loop {a => 1, b => 2, c => 3}, begin
107             ---
108             key/val: <%= loop->key %>/<%= loop->val %>
109             count: <%= loop->index %> + 1 = <%= loop->count %> (index + 1)
110             size: <%= loop->max %> + 1 = <%= loop->size %> (max + 1)
111             prev: <%= loop->peek(-1) // 'undef' %> (peek -1)
112             next: <%= loop->peek(1) // 'undef' %> (peek +1)
113             parity: <%= loop->parity %>
114             odd/even: <%= loop->odd ? 'odd' : loop->even ? 'even' : 'unknown' %>
115             first: <%= loop->first ? 'yes' : 'no' %>
116             last: <%= loop->last ? 'yes' : 'no' %>
117             % end
118              
119             =head1 DESCRIPTION
120              
121             L is a plugin with helpers for iterating over either array,
122             hashes or array/hash-like structures.
123              
124             NOTE: THIS MODULE IS EXPERIMENTAL AND THE API MAY CHANGE AT ANY TIME
125              
126             =head1 TEMPLATE METHODS
127              
128             =head2 count
129              
130             $int = $loop->count;
131              
132             Returns L + 1.
133              
134             =head2 even
135              
136             $bool = $loop->even;
137              
138             Returns true if L is 2, 4, 6, ...
139              
140             =head2 first
141              
142             $bool = $loop->first;
143              
144             Returns true if L is zero.
145              
146             =head2 index
147              
148             $int = $loop->index;
149              
150             Returns the index number, starting on 0.
151              
152             =head2 key
153              
154             $str = $self->key; # hash
155             $int = $self->key; # array
156              
157             Returns L if iterating over an array or the current key if iterating
158             over a hash.
159              
160             =head2 last
161              
162             $bool = $loop->last;
163              
164             Returns true if L is L.
165              
166             =head2 max
167              
168             $int = $loop->max;
169              
170             Returns L - 1.
171              
172             =head2 next
173              
174             $bool = $self->next;
175              
176             Move the iterator forward one step. Example:
177              
178             % my $i = loop [1, 2, 3];
179             % while ($i->next) {
180             %= $i->val;
181             % }
182              
183             =head2 odd
184              
185             $bool = $loop->odd;
186              
187             Returns true if L is 1, 3, 5, ...
188              
189             =head2 parity
190              
191             $str = $loop->parity;
192              
193             Returns either the string "odd" or "even".
194              
195             =head2 peek
196              
197             $any = $loop->peek($index);
198             $any = $loop->peek(-3);
199              
200             Returns either the value in the array, or the key in the hash, relative to the
201             current item. Examples:
202              
203             # [24, 25, 26]
204             $loop->index == 2
205             $loop->peek(-1) == 25
206              
207             # {a => 24, b => 25, c => 26}
208             $loop->index == 1
209             $loop->peek(1) == "c"
210              
211             =head2 reset
212              
213             $self = $self->reset;
214              
215             Used to reset the iterator.
216              
217             =head2 size
218              
219             $int = $loop->size;
220              
221             Returns the number of items in the array, or number of keys in the hash.
222              
223             =head2 val
224              
225             $any = $loop->val;
226              
227             Returns the value of the current item in the array or hash.
228              
229             =head1 METHODS
230              
231             =head2 register
232              
233             Used to register the plugin in the L application.
234              
235             =head1 AUTHOR
236              
237             Jan Henning Thorsen
238              
239             Marcus Ramberg
240              
241             =head1 COPYRIGHT AND LICENSE
242              
243             This program is free software, you can redistribute it and/or modify it under
244             the terms of the Artistic License version 2.0.
245              
246             =head1 SEE ALSO
247              
248             L.
249              
250             =cut