File Coverage

blib/lib/Text/Glob/Expand/Permutation.pm
Criterion Covered Total %
statement 30 33 90.9
branch 7 12 58.3
condition 1 3 33.3
subroutine 6 6 100.0
pod 2 2 100.0
total 46 56 82.1


line stmt bran cond sub pod time code
1             package Text::Glob::Expand::Permutation;
2 2     2   15 use strict;
  2         3  
  2         82  
3 2     2   13 use warnings;
  2         6  
  2         65  
4 2     2   9 use Carp qw(croak);
  2         3  
  2         1059  
5              
6             our $VERSION = '1.1.1'; # VERSION
7              
8             ######################################################################
9             # Private methods
10              
11             sub _percent_expand {
12 90     90   113 my $self = shift;
13 90         153 my $match = shift;
14              
15 90 50       205 if ($match eq "%") {
16 0         0 return "%";
17             }
18              
19 90 100       262 if ($match eq "0") {
20 34         184 return $self->[0];
21             }
22              
23 56         79 my $curr = $self;
24 56         163 my @digits = split /[.]/, $1;
25              
26 56         139 while(@digits) {
27 70         112 my $digit = shift @digits;
28              
29 70 50       167 die "invalid capture name %$1 (contains zero)"
30             unless $digit > 0;
31 70         123 $curr = $curr->[$digit];
32 70 50 33     478 die "invalid capture name %$1 (reference to non-existent brace)\n"
33             unless $curr && ref $curr;
34             }
35 56         269 return $curr->[0]
36             }
37              
38              
39             ######################################################################
40             # Public methods - see POD for documentation
41              
42 34     34 1 166 sub text { shift->[0] }
43              
44             sub expand {
45 34     34 1 7673 my ($self, $format) = @_;
46 34 50       77 croak "you must supply a format string to expand"
47             unless defined $format;
48              
49             eval {
50             # This regex-matches each capture name and replace with the
51             # appropriate string.
52 34         363 $format =~
53             s{
54             %
55             (
56             % # An an escaped % character
57             |
58             (?: \d+ [.] )* # any number of decimals followed by a period
59             \d+ # a final decimal
60             )
61             }
62             {
63 90         191 $self->_percent_expand($1)
64             }gex;
65 34         105 1;
66             }
67 34 50       43 or do {
68             # Something went wrong, report the error
69 0         0 chomp(my $error = $@);
70 0         0 croak "$error when expanding '$format' with '$self->[0]'";
71             };
72              
73 34         472 return $format;
74             }
75              
76             1; # Magic true value required at end of module
77             __END__
78              
79             =head1 NAME
80              
81             Text::Glob::Expand::Permutation - describes one possible expansion of a glob pattern
82              
83             =head1 VERSION
84              
85             version 1.1.1
86              
87             =head1 SYNOPSIS
88              
89             This is an internal class, in that there is no public
90             constructor. However, C<< Text::Glob::Expand->explode >> returns an
91             arrayref containing objects of this class which the user can access.
92              
93             An instance's methods can be used to get the permutation text, or a
94             formatted version of the permutation's components. For example:
95              
96             ($first, @rest) = Text::Glob::Expand->parse("a{b,c}");
97             print $first->text;
98             # "ab"
99              
100             print $first->expand("text is %0 and first brace is %1");
101             # "text is ab and first brace is b"
102              
103             =head1 PUBLIC INSTANCE METHODS
104              
105             In addition to the methods below, an instance can also be
106             de-referenced as an arrayref to get sub-nodes of the tree and their
107             values. See L</STRUCTURE>.
108              
109             =head2 C<< $str = $obj->text >>
110              
111             Returns the unembellished text of this permutation.
112              
113             =head2 C<< $str = $obj->expand($format) >>>
114              
115             Returns the string C<$format> expanded with the components of the permutation.
116              
117             The following expansions are made:
118              
119             =over 4
120              
121             =item C<%%>
122              
123             An escaped percent, expands to C<%>
124              
125             =item C<%0>
126              
127             Expands to the whole permutation text, the same as returned by C<< ->text >>.
128              
129             =item C<%n>
130              
131             (Where C<n> is a positive decimal number.) Expands to this permutation's
132             contribution from the nth brace (numbering starts at 1).
133              
134             This may throw an exception if the number is larger than the number of braces.
135              
136             =item C<%n.n>
137              
138             (Where C<n.n> is a sequence of positive decimal numbers, delimited by
139             periods.) Expands to this permutations contribution from a nested
140             brace, if it exists (otherwise an error will be thrown).
141              
142             So, for example, C<%1.1> is the first nested brace within the first
143             brace, and C<%10,3,2> is the second brace within the third brace
144             within the 10th brace.
145              
146             =back
147              
148              
149             =head1 STRUCTURE
150              
151             C<<Text::Glob::Expand->explode>> returns an array of
152             C<Text::Glob::Expand::Permutation> instances, one for each permutation
153             generated from the glob expression.
154              
155             A C<Text::Glob::Expand::Permutation> instance is a blessed arrayref
156             representing the root node of a tree describing the structure of a
157             single permutation. This tree is designed to allow the placeholders in
158             string formats to be mapped to expansions (see
159             L<<Text::Glob::Expand->explode_format|Text::Glob::Expand/INTERFACE>>)
160              
161             Each node of the tree is an arrayref, and represents a
162             L<brace-expression|Text::Glob::Expand/"PARSING RULES"> which
163             contributes a string to this permutation (except for the root node,
164             which corresponds to the entire
165             L<expression|Text::Glob::Expand/"PARSING RULES">).
166              
167             The first element of a node arrayref is the node value, and the rest
168             are sub-trees for any nested braces with the same recursive structure, i.e.
169              
170             [$value, @subtrees]
171              
172             Or in leaf nodes, more simply:
173              
174             [$value]
175              
176             The indexing of tree-nodes corresponds to indexing of braces in the
177             expansion. For example, this glob expression:
178              
179             $glob = Text::Glob::Expand->parse("a{b,c}d{e{f{g,h},i{j,k},},l}m");
180              
181             generates a set of permutations:
182              
183             print "$_->[0]\n" for @{ $glob->explode }
184              
185             as follows
186              
187             'abdefgm'
188             'abdefhm'
189             'abdeijm'
190             'abdeikm'
191             'abdem'
192             'abdlm'
193             'acdefgm'
194             'acdefhm'
195             'acdeijm'
196             'acdeikm'
197             'acdem'
198             'acdlm'
199              
200             The first permutation would be expressed as a
201             C<Text::Glob::Expand::Permutation> with this tree structure (omitting
202             blessings for readability):
203              
204             ["abdefgm", ["b"], ["efg" ["fg", ["g"]]]]
205              
206             You can access nodes and values using array dereferencing. To get the
207             node for the first brace in the second brace in the example, you might
208             do:
209              
210             $node = $glob->explode->[2][1] # = ["fg", ["g"]]
211              
212             And to get the value of this node, get the first element:
213              
214             $value = $glob->explode->[2][1][0] # = "fg"
215              
216             When using C<<Text::Glob::Expand->explode_format>>, you would refer to
217             this value as C<%2.1>, and it would be replaced with C<fg> for this
218             permutation. C<%2.1.1> would be replaced with the value of C<g>.
219              
220             So that a this:
221              
222             $glob->explode->[0]->expand("%0 %1 %2.1 %2.1.1")
223              
224             Evaluates to:
225              
226             'abdefgm b fg g'
227              
228             Note that not all braces contribute to all permutations, so you must
229             be careful when expanding format strings. Therefore although there is a
230             brace corresponding to C<%2.1.1> in the first permutation, there is none
231             in the final one. i.e. This will fail:
232              
233             $glob->explode->[11]->expand("%2.1.1")
234              
235             # Gets: invalid capture name %2.1.1 (reference to non-existent
236             # brace) when expanding '%2.1.1' with 'acdlm'..
237              
238             =head1 DIAGNOSTICS
239              
240             The following errors may result when invoking the C<< ->expamd >>
241             method.
242              
243             =over 4
244              
245             =item "... when expanding '...' with '...'";
246              
247             This means that the expansion mechanism failed in some way, when
248             expanding a format string with the given permutation. The reason
249             might be one of the errors below, or something else unanticipated.
250              
251             =item "invalid capture name %... (contains zero)"
252              
253             Capture names must have the form described above - and in particular
254             cannot contain zeros except in the special case C<%0>.
255              
256             =item "invalid capture name %... (reference to non-existent brace)"
257              
258             Capture names may be invalid because there is no contribution from the
259             corresponding brace in this permutation. See L</STRUCTURE>
260              
261             =item "you must supply a format string to expand"
262              
263             This means you've not supplied a value to C<< ->expand >>.
264              
265             =back
266              
267             =head1 AUTHOR
268              
269             Nick Stokoe C<< <wulee@cpan.org> >>
270              
271              
272             =head1 LICENCE AND COPYRIGHT
273              
274             Copyright (c) 2011, Nick Stokoe C<< <wulee@cpan.org> >>. All rights reserved.
275              
276             This module is free software; you can redistribute it and/or
277             modify it under the same terms as Perl itself. See L<perlartistic>.
278              
279              
280             =head1 DISCLAIMER OF WARRANTY
281              
282             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
283             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
284             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
285             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
286             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
287             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
288             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
289             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
290             NECESSARY SERVICING, REPAIR, OR CORRECTION.
291              
292             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
293             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
294             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
295             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
296             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
297             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
298             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
299             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
300             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
301             SUCH DAMAGES.