File Coverage

blib/lib/Text/Glob/Expand.pm
Criterion Covered Total %
statement 126 146 86.3
branch 18 30 60.0
condition 3 5 60.0
subroutine 25 29 86.2
pod 3 3 100.0
total 175 213 82.1


line stmt bran cond sub pod time code
1             package Text::Glob::Expand;
2 2     2   36662 use Text::Glob::Expand::Segment;
  2         7  
  2         64  
3 2     2   7448 use Text::Glob::Expand::Permutation;
  2         6  
  2         60  
4 2     2   12 use warnings;
  2         4  
  2         60  
5 2     2   9 use strict;
  2         3  
  2         53  
6 2     2   10 use Carp;
  2         7  
  2         125  
7 2     2   11 use Scalar::Util qw(refaddr);
  2         5  
  2         329  
8             use Sub::Exporter -setup => {
9             exports => {
10 1         116 explode => sub { \&_explode_list },
11 0         0 explode_format => sub { \&_explode_format_list },
12             },
13 2     2   13506 };
  2         53874  
  2         32  
14              
15              
16             our $VERSION = '1.1.1'; # VERSION
17              
18             # Cache ->_explode results here
19             our %CACHE;
20              
21             # and queue cached items for deletion
22             our @CACHE_QUEUE;
23              
24             # when the number of cached items exceeds this.
25             our $MAX_CACHING = 100;
26              
27             ######################################################################
28             # Private functions - read the POD to understand the terms.
29              
30              
31             # @partitions = _partition $depth, @segments;
32             #
33             # This function groups a list of segments (Text::Glob::Expand::Segment
34             # instances) by the brace-expression they came from, using their depth
35             # attributes to infer which segments go together.
36             #
37             # It works by discarding elements below the desired $depth value,
38             # and using the gaps to split the remainder into groups.
39             #
40             # For example, if we ignore the segments' string attribute for the
41             # moment and just consider their depths, given an expression like
42             # this:
43             #
44             # a{a{a,a}a}a{a}a{a{a}a}a
45             #
46             # We get depths like this:
47             #
48             # @segments = (0, 1, 2, 2, 1, 0, 1, 0, 1, 2, 1, 0)
49             #
50             # and results like this:
51             #
52             # _partition 0, @segments # -> ([1, 2, 2, 1], [1], [1, 2, 1])
53             # _partition 1, @segments # -> ([2, 2], [2])
54             # _partition 2, @segments # -> ()
55             #
56             # Note, this is designed to be used internally by the ->_transform
57             # method, and so it does not try to check the validity and consistency
58             # of the data.
59             sub _partition {
60 94     94   125 my $depth = shift;
61              
62 94         98 my @partitions; # An accumulator for partitions
63 94         138 my $partition = []; # The current partition under construction
64              
65 94         180 foreach my $elem (@_) {
66 250 100       625 if ($elem->depth > $depth) {
67             # Add element this to the current partition
68 96         250 push @$partition, $elem;
69             }
70             else {
71             # Start a new partition. If there is a non-empty
72             # partition in construction, save it, then empty it.
73 154 100 66     709 push @partitions, $partition
74             if $partition
75             && @$partition;
76 154         523 $partition = [];
77             }
78             }
79              
80             # Save the last partition, if not empty
81 94 50       325 push @partitions, $partition
82             if @$partition;
83              
84 94         1061 return @partitions;
85             }
86              
87             ######################################################################
88             # Private methods
89              
90             # $permutations = $obj->_traverse(@expression)
91             #
92             # This method traverses a sub-expression and recursively expands them
93             # into all possible permutations, returning an arrayref to the
94             # resulting list of lists (of Text::Glob::Expand::Segment instances).
95             #
96             # If no arguments are given, it returns an empty arrayref.
97             sub _traverse {
98 146     146   261 my $self = shift;
99              
100             # Trivial case.
101 146 50       293 return [] unless @_;
102              
103             # Since @expression contains the elements of a glob expression,
104             # each parameter param can be one of two things: a string segment
105             # or a brace-expression.
106              
107             # Take the first element, and process the rest recursively.
108 146         164 my $first = shift;
109              
110 146 100       487 if (ref $first eq 'Text::Glob::Expand::Segment') {
111             # $first is a string segment - in which case we recursively
112             # expand the the remaining arguments (if any) into their
113             # permutations and prepend $first to each of the permutations.
114              
115 118 100       307 return [[$first]] unless @_;
116              
117 84         286 my $exploded = $self->_traverse(@_);
118 84         309 unshift @$_, $first for @$exploded;
119 84         181 return $exploded;
120             }
121             else {
122             # $first is an brace-expression (an arrayref of alternative
123             # sub-expressions) - in which case we take out each
124             # alternative sub-expression $seq, concatenate it with with
125             # the remaining arguments into a new expression, and
126             # recursively expand the permutations of that expression.
127             #
128             # After processing them all, we return a concatenated list of
129             # all the permutations.
130 28         33 my @exploded;
131 28         54 foreach my $seq (@$first) {
132 48 50       109 die "unexpected scalar '$seq'" if !ref $seq;
133 48         115 my $exploded2 = $self->_traverse(@$seq, @_);
134 48         123 push @exploded, @$exploded2;
135             }
136 28         70 return \@exploded;
137             }
138             }
139              
140              
141             # $root = $obj->_transform($depth, $permutation)
142             #
143             # $permutation is an arrayref of segments (Text::Glob::Expand::Segment
144             # instances) representing a permutation generated from a
145             # Text::Glob::Expand expression (i.e. one of the elements in the
146             # result from from _traverse).
147             #
148             # $depth is a depth to partition it by (in hindsight, perhaps this
149             # could be computed from the first element's depth?).
150             #
151             # The result $root is the root node of a tree structure describing the
152             # structure of the permutation (a Text::Glob::Expand::Permutation
153             # instance), by using the segments' depth attribute. This tree is
154             # designed to allow the placeholders in formats to be mapped to
155             # expansions.
156             #
157             # See the POD within Text::Glob::Expand::Permutation for a description of
158             # the structure of this result.
159             #
160             # For example, this glob expression:
161             #
162             # "a{b{c,d,}e,f}g"
163             #
164             # Generates this set of permutations:
165             #
166             # "abceg", "abdeg", "abeg", "afg"
167             #
168             # Permutations are generated by _traverse in terms of arrays of
169             # Text::Glob::Expand::Segment instances. The first permutation above
170             # would look like this (omitting blessings):
171             #
172             # $permutation = [['a', 0], ['b', 1], ['c', 2], ['e', 1], ['g', 0]]
173             #
174             # This then gets passed to _transform to turn it into a
175             # Text::Glob::Expand::Permutation instance:
176             #
177             # $root = $glob->_transform(0, $permutation)
178             #
179             # The structure of $root would be:
180             #
181             # ["abceg", ["bce", ["c"]]]
182             #
183             # This is then relatively easily used to expand a format like "%1 %1.1
184             # %1.1.1" into "abcdeg bce c".
185             #
186             sub _transform {
187 94     94   124 my $self = shift;
188 94         158 my $depth = shift;
189 94         139 my $permutation = shift;
190              
191             # Concatenate the strings from all the Text::Glob::Expand::Segment
192             # instances in $permutation into one.
193 94         150 my $flat = join '', map { $_->[0] } @$permutation;
  250         1127  
194              
195             # Group the segments deeper than $depth recursively
196 94 100       978 if (my @deeper = _partition $depth, @$permutation) {
197 60         147 return bless (
198 50         80 [$flat, map { $self->_transform($depth+1, $_)} @deeper],
199             'Text::Glob::Expand::Permutation',
200             );
201             }
202              
203             # Bless the result, to add convenience methods for the user.
204 44         438 return bless [$flat], 'Text::Glob::Expand::Permutation';
205             }
206              
207              
208             # $permutations = $obj->_explode
209             #
210             # This generates all the permutations implied by the parsed glob
211             # expression.
212             #
213             # The return value is an array of Text::Glob::Expand::Permutation
214             # instances.
215             sub _explode {
216 14     14   22 my $self = shift;
217              
218             # Permute all the alternatives in the parsed glob expression
219             # into a giant list of permutations of segments.
220 14         40 my $exploded = $self->_traverse(@$self);
221              
222             # Transform that into an array of tree descriptions of each
223             # permutation's composition (i.e. Text::Glob::Expand::Permutation
224             # instances).
225 14         33 return [map { $self->_transform(0, $_) } @$exploded];
  34         80  
226             }
227              
228              
229             ######################################################################
230             # Public methods - see POD for documentation.
231              
232              
233             sub parse {
234 7     7 1 14716 my $class = shift;
235 7         16 my $str = shift; # The expression to parse
236              
237             # This function defines a simple state-machine to parse
238             # expressions. See the documentation for an explanation of the
239             # parsing rules. The comments below assume you have read that.
240              
241             # Each character in the expression is examined in turn in a
242             # for-loop. The current value is stored in $_, and the character
243             # index in $pos.
244 7         8 my $pos;
245              
246             # The depth of brace-nesting at $pos is stored in $depth.
247 7         10 my $depth = 0;
248              
249             # Empty Text::Glob::Expand::Segment instances are created using
250             # this closure. (We use a closure simply as it more convenient
251             # than a constructor method.)
252 7     42   37 my $new_segment = sub { bless ['', $depth], 'Text::Glob::Expand::Segment' };
  42         205  
253              
254              
255             # (Note, expressions and brace-expressions are implemented as
256             # arrayrefs, and so the [] constructor is used for them.)
257              
258              
259             # The implementation is stack-based. It uses three stacks as follows.
260              
261             # First: a stack @c_stack to store intermediate parsed values. We
262             # construct new string segments on the top of this stack as they
263             # are encountered. At the end of an expression the top N are
264             # popped off and used to construct the expression data structure.
265             #
266             # We initialise it with a single empty segment, since the
267             # top-level expression always contains at least one.
268 7         18 my @c_stack = $new_segment->();
269              
270             # Second: a stack called @alt_count is used to count how many
271             # alternatives have been parsed in the current brace
272             # (i.e. comma-delimited sub-expressions). It determines how many
273             # elements on @c_stack belong to it.
274 7         27 my @alt_count = ();
275              
276             # Third and final: a stack called @seq_count is used to count how
277             # many sequential elements (segments or brace-expressions) have
278             # been parsed in the current sub-expression. As above, it
279             # determines how many of the top elements on @c_stack belong to
280             # it.
281             #
282             # We initialise it to 1, since there is always at least one
283             # segment in the top level expression.
284 7         13 my @seq_count = (1);
285              
286              
287             # Some helper closures follow. These are invoked by the state
288             # machine to build the data as a side-effect.
289              
290             my $add_char = sub {
291             # Append the current character ($_) to the segment under
292             # construction on the top of @c_stack. (The string is the
293             # zeroth element of the segment array.)
294              
295 33     33   99 $c_stack[-1][0] .= $_;
296 7         29 };
297              
298              
299             my $start_brace = sub {
300             # Called when an opening brace is seen.
301              
302 13     13   21 ++$depth;
303 13         18 ++$seq_count[-1]; # Increment the current sequence counter,
304              
305 13         22 push @alt_count, 1; # Start a new alternative list
306 13         24 push @c_stack, $new_segment->(); # Start a new sub-expression
307 13         26 push @seq_count, 1;
308 7         31 };
309              
310              
311             my $new_alternative = sub {
312             # Called when a comma delimiter is seen.
313              
314             # Finish the last alternative: replace the appropriate number
315             # of elements from @c_stack with a sub-expression arrayref
316             # created from them.
317 9     9   26 my $num_elems = pop @seq_count;
318 9         25 push @c_stack, [splice @c_stack, -$num_elems];
319              
320 9         16 ++$alt_count[-1]; # Increment the number of alternatives seen
321 9         12 push @seq_count, 1; # and start a new sub-expression
322 9         22 push @c_stack, $new_segment->();
323 7         30 };
324              
325              
326             my $end_brace = sub {
327             # Called when a closing brace is seen.
328              
329 13     13   15 --$depth;
330              
331             # Finish the current alternative: replace the appropriate
332             # number of elements from @c_stack with a sub-expression
333             # arrayref created from them.
334 13         25 my $num_elems = pop @seq_count;
335 13         32 push @c_stack, [splice @c_stack, -$num_elems];
336              
337             # Finish the current brace: replace the appropriate
338             # number of elements from @c_stack with a brace-expression
339             # arrayref created from them.
340 13         23 $num_elems = pop @alt_count;
341 13         37 push @c_stack, [splice @c_stack, -$num_elems], $new_segment->();
342              
343             # Increment the sequence counter
344 13         23 ++$seq_count[-1];
345 7         30 };
346              
347              
348             # Define the states in our parser as a hash.
349             #
350             # State names are mapped to a hash of transition definitions for
351             # that state.
352             #
353             # Each transition has a single character which triggers it,
354             # mapped to a code-ref which returns the name of the next state
355             # (and optionally performs some side effect).
356             #
357             # Except for '' which is the default transition, used when none of
358             # the others match.
359             #
360             # Since the whole expression muse be parsed, there is no terminal
361             # state. Termination is implicit when the end of the string is
362             # reached. FIXME this means brace-matching is not properly
363             # handled.
364             my $states = {
365             start => {
366             '\\' => sub {
367 0     0   0 'escape'
368             },
369             '{' => sub {
370 13     13   26 $start_brace->();
371 13         54 'start';
372             },
373             '}' => sub {
374 13     13   25 $end_brace->();
375 13         59 'start';
376             },
377             ',' => sub {
378             @alt_count # This has a value added at the start of each brace
379 9 50   9   23 or die "unexpected comma outside of a brace-expression";
380 9         17 $new_alternative->();
381 9         36 'start';
382             },
383             '' => sub {
384 33     33   130 $add_char->();
385 33         134 'start';
386             }
387             },
388              
389             # This state is purely to handle escaping.
390             escape => {
391             '' => sub {
392 0     0   0 $add_char->();
393 0         0 'start';
394             },
395             }
396 7         147 };
397              
398              
399 7         18 my $state = 'start'; # Set the initial state.
400              
401             # Iterate over the length of the string
402 7         27 for $pos (0..length($str)-1) { ## no critic RequireLexicalLoopIterators
403 68 50       194 my $table = $states->{$state}
404             or die "no such state '$state'";
405              
406             # We use this for-loop as a mechanism to alias $_ to the
407             # character at $pos
408 68         158 for (substr $str, $pos, 1) {
409              
410             # Get the action for this transition
411 68   50     319 my $action =
412             $table->{$_} ||
413             $table->{''} ||
414             die "no handler for state '$state' looking at '$_' pos $pos";
415              
416             # Invoke it
417 68         124 $state = $action->();
418             }
419             }
420              
421             # When we get here, @c_stack will contain the fully-parsed expression.
422 7         160 return bless \@c_stack, __PACKAGE__;
423             };
424              
425              
426              
427             # This is a wrapper around the real implementation in ->_explode. It
428             # caches the results and re-uses them when possible.
429             sub explode {
430 14     14 1 7399 my $self = shift;
431              
432             # This clause handles caching of results from ->_explode
433 14 50       50 if ($MAX_CACHING > 0) {
434             # Look ourselves up in the cache, are we there?
435 14         42 my $id = refaddr $self;
436 14         26 my $exploded = $CACHE{$id};
437              
438             # If yes, just return the same as last time.
439 14 50       39 return $exploded
440             if $exploded;
441              
442             # Otherwise delegate to the full implementation
443 14         51 $exploded = $self->_explode(@$self);
444              
445             # And add the results to the cache, unless we've surpassed the
446             # limit on caching.
447 14         44 unshift @CACHE_QUEUE, $id;
448 14 50       63 if (@CACHE_QUEUE > $MAX_CACHING) {
449 0         0 delete @CACHE{splice @CACHE_QUEUE, $MAX_CACHING};
450             }
451              
452             # Finally, return the new results.
453 14         34 return $exploded;
454             }
455              
456             # If we get here, there is no caching, so empty the cache (in case
457             # $MAX_CACHING just changed).
458 0         0 %CACHE = ();
459 0         0 @CACHE_QUEUE = ();
460              
461             # And merely delegate to the full implementation.
462 0         0 return $self->_explode(@$self);
463             }
464              
465              
466             # A convenience method which explodes and expands in one step.
467             sub explode_format {
468 7     7 1 7523 my $self = shift;
469 7         13 my $format = shift;
470              
471             # Get the exploded result, and expand all the values using $format
472 7         21 my $exploded = $self->explode;
473 7         26 return {map { $_->text => $_->expand($format) } @$exploded};
  17         48  
474             }
475              
476              
477              
478             ######################################################################
479             # Exportable functions
480              
481             # FIXME document
482             # FIXME test these
483              
484             # A convenience function which explodes to a list of strings
485             sub _explode_list {
486              
487 0           return map {
488 0     0     my $glob = __PACKAGE__->parse($_);
489 0           map {
490 0           $_->text;
491 0           } @{ $glob->explode };
492             } @_;
493             }
494              
495              
496             # A convenience function which explodes to a list of formatted strings
497             sub _explode_format_list {
498 0 0   0     @_ or croak "you must supply a format parameter";
499              
500 0 0         defined (my $format = shift)
501             or croak "format parameter is undefined";
502              
503 0           return map {
504 0           my $glob = __PACKAGE__->parse($_);
505 0           map {
506 0           $_->expand($format);
507 0           } @{ $glob->explode };
508             } @_;
509             }
510              
511              
512 2     2   4184 no Scalar::Util;
  2         5  
  2         69  
513 2     2   12 no Carp;
  2         3  
  2         78  
514             1; # Magic true value required at end of module
515             __END__
516              
517             =head1 NAME
518              
519             Text::Glob::Expand - permute and expand glob-like text patterns
520              
521             =head1 VERSION
522              
523             version 1.1.1
524              
525             =head1 SYNOPSIS
526              
527             The original use case was to specify hostname aliases and expansions
528             thereof. For example, it supports basic expansion of the glob
529             expression into its permutations like this:
530              
531             use Text::Glob::Expand;
532              
533             my $hosts = "{www{1,2,3},mail{1,2},ftp{1,2}}";
534             my $glob = Text::Glob::Expand->parse($hosts);
535              
536             my $permutations = $glob->explode;
537             # result is: [qw(www1 www2 www3 mail1 mail2 ftp1 ftp2)]
538              
539              
540             But additionally, to generate full hostnames, it supports a method to
541             expand these permutations using a format string:
542              
543             my $permutations = $glob->explode_format("%0.somewhere.co.uk");
544              
545             # result is:
546             # {
547             # www1 => 'www1.somewhere.co.uk',
548             # www2 => 'www2.somewhere.co.uk',
549             # www3 => 'www3.somewhere.co.uk',
550             # mail1 => 'mail1.somewhere.co.uk',
551             # mail2 => 'mail2.somewhere.co.uk',
552             # ftp1 => 'ftp1.somewhere.co.uk',
553             # ftp2 => 'ftp2.somewhere.co.uk',
554             # }
555              
556              
557             =head1 INTERFACE
558              
559              
560             =head2 C<< $obj = $class->parse($string) >>
561              
562             This is the constructor. It implements a simple state-machine to
563             parse the expression in C<$string>, and returns a
564             C<Text::Glob::Expand> object.
565              
566             You don't really need to understand the structure of this object, just
567             invoke methods on it. However, see L</"PARSING RULES"> for more
568             details of the expression and the internal structure of the object
569             returned.
570              
571             =head2 C<< $arrayref = $obj->explode >>
572              
573             This returns an arrayref containing all the expanded permutations
574             generated from the string parsed by the constructor.
575              
576             (The result is cached, and returned again if this is called more than
577             once. See C<$MAX_CACHING>.)
578              
579             =head2 C<< $hashref = $obj->explode_format($format) >>
580              
581             This returns a hashref mapping each expanded permutation to a string
582             generated from the C<$format> parameter.
583              
584             (The return value is not cached, since the result depends on C<$format>.)
585              
586              
587             =head1 PARSING RULES
588              
589             Using a notation based on a subset of the Backus Naur Form described
590             by the
591             L<HTTP 1.1 RFC|http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.1>
592             (with the notable exception that white-space is significant here) the
593             expression syntax expected by the C<< ->parse >> method can be defined
594             like this:
595              
596             expression =
597             segment *( brace-expression segment )
598              
599             A I<segment> is a sequence of zero or more characters or
600             escaped-characters (i.e. braces and commas must be escaped with a
601             preceding backslash).
602              
603             segment =
604             *( escaped-character | <any character except glob-characters> )
605              
606             Where:
607              
608             escaped-character =
609             "\" <any char>
610              
611             glob-character =
612             "{" | "}" | ","
613              
614             A I<brace-expression> is a sequence of one or more I<expressions>
615             (which in this context I call 'alternatives'), delimited by commas,
616             and enclosed in braces.
617              
618             brace-expression =
619             "{" expression ( "," expression )* "}"
620              
621              
622             =head1 OBJECT STRUCTURE
623              
624             An expression such as described in the previous above is parsed into
625             an arrayref of text I<segments> (represented with
626             C<Text::Glob::Expand::Segment> instances) and I<brace-expressions>
627             (represented by arrayrefs).
628              
629             An I<expression> is represented at the top level by a
630             C<Text::Glob::Expand> instance, which is a blessed arrayref containing
631             only C<Text::Glob::Expand::Segment> instances and I<brace-expression>
632             arrayrefs.
633              
634             Each I<brace-expression> array contains a list of the
635             brace-expression's 'alternatives' (the comma-delimited sub-expressions
636             within the braces). These are represented by arrayrefs. Apart
637             from being unblessed, they otherwise have the same structure as the
638             top-level expression.
639              
640             C<Text::Glob::Expand::Segment> instances are blessed arrayrefs,
641             composed of a string plus an integer (>= 0) indicating the number of
642             brace-pairs enclosing the segment. The depth is used internally to
643             preserve the expression structure, and may be ignored by the user.
644             (See also L<Text::Glob::Expand::Segment>.)
645              
646              
647             For example, an expression such as:
648              
649             "a{b,{c,d}e,}g"
650              
651             Will be parsed into something analogous to this structure (for better
652             readability I use a simplified Perl data-structure in which segments
653             are represented by simple strings instead of blessed arrays, and use
654             comments to denote types):
655              
656             [ # expression
657             'a', # segment depth 0
658             [ # brace
659             [ # expression
660             'b' # segment, depth 1
661             ],
662             [ # expression
663             '', # segment, depth 1
664             [ # brace
665             [ # expression
666             'c' # segment, depth 2
667             ],
668             [ # expression
669             'd' # segment, depth 2
670             ],
671             ],
672             'e' # segment, depth 1
673             ],
674             [ # expression
675             '' # segment, depth 1
676             ]
677             ],
678             'g', # segment, depth 0
679             ]
680              
681              
682              
683              
684             =head1 DIAGNOSTICS
685              
686             The following parsing diagnostics should never actually occur. If they
687             do it means the internal data structure or code design is
688             inconsistent. In this case, please file a bug report with details of
689             how to replicate the error.
690              
691             =over 4
692              
693             =item "unexpected scalar..."
694              
695             =item "no such state..."
696              
697             =item "no handler for state '...' looking at '...' pos '...'"
698              
699             =back
700              
701              
702             =head1 CONFIGURATION AND ENVIRONMENT
703              
704             C<Text::Glob::Expand> requires no configuration files or environment
705             variables.
706              
707             There is one configurable option in the form of a package variable, as
708             follows.
709              
710             =head2 C<$MAX_CACHING>
711              
712             The package variable C<$Text::Glob::Expand::MAX_CACHING> can be used
713             to control or disable the caching done by the C<< ->explode >> method.
714             It should be a positive integer, or zero.
715              
716             The default value is 100, which means that up to 100
717             C<Text::Glob::Expand> objects' C<< ->explode >> results will be
718             cached, but no more. You can disable caching by setting this to zero
719             or less.
720              
721             =head1 DEPENDENCIES
722              
723             The dependencies should be minimal - I aim to have none.
724              
725             For a definitive answer, see the Build.PL file included in the
726             distribution, or use the dependencies tool on
727             L<http://search.cpan.org>
728              
729              
730             =head1 BUGS AND LIMITATIONS
731              
732             Currently the parser will infer closing brackets at the end of an
733             expression if they are omitted. Probably a syntax error should be
734             thrown instead.
735              
736             Also, extra closing brackets with no matching opening bracket will
737             generate an error. This is a bug which will be addressed in future
738             versions.
739              
740             Please report any bugs or feature requests to
741             C<bug-Text-Glob-Expand@rt.cpan.org>, or through the web interface at
742             L<http://rt.cpan.org>.
743              
744              
745             =head1 SEE ALSO
746              
747             Similar libraries I am aware of are:
748              
749             =over 4
750              
751             =item L<Text::Glob>
752              
753             Wildcard matching against strings, which includes alternation (brace
754             expansion).
755              
756             =item L<String::Glob::Permute>
757              
758             A permutation generator similar to this one. Supports numbered
759             ranges, but not format string expansion.
760              
761             =back
762              
763             Plus there is of course Perl's own C<glob> function, which supports
764             brace expansions. That however can be sensitive to unusually-named
765             files in the current director - and more importantly, like
766             C<String::Glob::Permute> it does not implement format string
767             expansions.
768              
769             =head1 AUTHOR
770              
771             Nick Stokoe C<< <wulee@cpan.org> >>
772              
773              
774             =head1 LICENCE AND COPYRIGHT
775              
776             Copyright (c) 2011, Nick Stokoe C<< <wulee@cpan.org> >>. All rights reserved.
777              
778             This module is free software; you can redistribute it and/or
779             modify it under the same terms as Perl itself. See L<perlartistic>.
780              
781              
782             =head1 DISCLAIMER OF WARRANTY
783              
784             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
785             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
786             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
787             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
788             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
789             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
790             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
791             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
792             NECESSARY SERVICING, REPAIR, OR CORRECTION.
793              
794             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
795             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
796             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
797             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
798             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
799             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
800             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
801             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
802             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
803             SUCH DAMAGES.