File Coverage

blib/lib/Grep/Query.pm
Criterion Covered Total %
statement 96 96 100.0
branch 32 38 84.2
condition 9 14 64.2
subroutine 14 14 100.0
pod 3 3 100.0
total 154 165 93.3


line stmt bran cond sub pod time code
1             package Grep::Query;
2              
3 10     10   78412 use 5.010;
  10         73  
4              
5 10     10   42 use strict;
  10         15  
  10         159  
6 10     10   38 use warnings;
  10         14  
  10         432  
7              
8             our $VERSION = '1.010';
9             $VERSION = eval $VERSION;
10              
11 10     10   3555 use Grep::Query::Parser;
  10         25  
  10         351  
12 10     10   3987 use Grep::Query::FieldAccessor;
  10         20  
  10         410  
13              
14 10     10   53 use Scalar::Util qw(blessed);
  10         16  
  10         387  
15 10     10   45 use Carp;
  10         17  
  10         368  
16 10     10   42 use Digest::MD5;
  10         19  
  10         353  
17              
18             # allow importing the qgrep function/method
19             # to enable non-OO use
20             #
21 10     10   50 use Exporter qw(import);
  10         15  
  10         7941  
22             our @EXPORT_OK = qw(qgrep);
23              
24             ## CTOR
25             ##
26             sub new
27             {
28 452     452 1 423059 my $class = shift;
29 452         698 my $query = shift;
30            
31 452 50       980 croak("No query provided") unless defined($query);
32            
33             # parse the query right now
34             #
35 452         1367 my ($parsedQuery, $fieldRefs) = Grep::Query::Parser::parsequery($query);
36 435         7372 my $self =
37             {
38             _query => $query,
39             _parsedquery => $parsedQuery,
40             _fieldrefs => $fieldRefs
41             };
42 435         1265 bless($self, $class);
43            
44 435         1200 return $self;
45             }
46              
47             ## METHODS
48             ##
49              
50             sub qgrep
51             {
52 339 50   339 1 708583 croak("missing parameters") unless @_;
53              
54 339         653 my $arg = shift;
55            
56 339 100 100     2222 my $obj =
57             (blessed($arg) // '') eq __PACKAGE__
58             ? $arg
59             : __PACKAGE__->new($arg);
60            
61 339         1025 return $obj->__qgrep(@_);
62             }
63              
64             sub getQuery
65             {
66 1     1 1 5 my $self = shift;
67            
68 1         4 return $self->{_query};
69             }
70              
71             # don't call this directly, use the above
72             #
73             sub __qgrep
74             {
75             # why even bother if you're not interested in the result?
76             #
77 339 100   339   959 return undef unless defined(wantarray());
78            
79 337         513 my $self = shift(@_);
80              
81             # make a note of if any query value is a ref
82             #
83 337         533 my $refCount = scalar(grep { ref($_) } @_);
  6912         8511  
84            
85             # first check if the first argument is/should be a field accessor
86             #
87 337         459 my $fieldAccessor;
88 337 100 66     395 if (@{$self->{_fieldrefs}} || (@_ && !defined($_[0]) && $refCount))
  337   33     1657  
      66        
89             {
90             # the query uses fields, or there's an undef and at least one ref, there must be a field accessor first
91             #
92 186         282 $fieldAccessor = shift(@_);
93            
94 186 100       393 if (defined($fieldAccessor))
95             {
96             # verify that the field accessor is of the right sort and has the known fields
97             #
98 144 100       369 croak("field names used in query; the argument before the list must be a field accessor") unless ref($fieldAccessor) eq 'Grep::Query::FieldAccessor';
99 143         215 $fieldAccessor->assertField($_) foreach (@{$self->{_fieldrefs}});
  143         700  
100             }
101             else
102             {
103             # for laziness, the caller passed undef; if there's any fields mentioned in the query, make a field accessor
104             #
105 42 50       58 $fieldAccessor = Grep::Query::FieldAccessor->newDefault(@{$self->{_fieldrefs}}) if @{$self->{_fieldrefs}};
  42         294  
  42         112  
106             }
107             }
108             else
109             {
110             # it's weird if a field accessor is present, but the query uses no fields - flag that mistake
111             #
112 151 100       373 croak("no fields used in query, yet the first list argument is a field accessor?") if ref($_[0]) eq 'Grep::Query::FieldAccessor';
113             }
114              
115             # nothing to see here
116             #
117 335 50       852 return(wantarray() ? () : 0) unless @_;
    100          
118            
119             # try to make sure all items in the list have the same structure...
120             #
121 327 100       801 if (@_ > 1)
122             {
123 303         2305 my $fp = __fingerprint(Digest::MD5->new(), $_[0])->hexdigest();
124 303         1139 foreach my $entry (@_)
125             {
126 6696 50       15261 croak("layout of datastructures in query list are not the same") unless $fp eq __fingerprint(Digest::MD5->new(), $entry)->hexdigest();
127             }
128             }
129            
130             # a special case:
131             # if there is only one argument AND it is a hash ref, we can let loose a query on it
132             # assuming we restructure the incoming data as a list of individual key/value pairs
133             #
134             # for this, we must have a fieldaccessor
135             #
136 327         495 my $lonehash = 0;
137 327 100 66     832 if (scalar(@_) == 1 && ref($_[0]) eq 'HASH')
138             {
139 24 50       69 croak("a lone hash used in query; first argument must be a field accessor") unless $fieldAccessor;
140 24         41 my @eachList;
141 24         41 while (my @kv = each %{$_[0]})
  648         1368  
142             {
143 624         839 push(@eachList, \@kv);
144             }
145 24         100 @_ = @eachList;
146 24         56 $lonehash = 1;
147             }
148            
149             # the list we were given needs to be made into a hash with unique keys so we
150             # identify 'rows' while evaluating the query
151             #
152             # that means we can return multiple identical hits and that we can sort the return list
153             # in the same order we got it
154             #
155             # keys are simply a number, and values are refs to the individual scalars/objects to avoid copying them
156             #
157 327         428 my $id = 0;
158 327         538 my %data = map { $id++ => \$_ } @_;
  7320         12575  
159            
160             # kick off the query
161             #
162 327         871 %data = %{ $self->{_parsedquery}->xeq($fieldAccessor, \%data) };
  327         1383  
163              
164             # only return the number of matches if the full list isn't desired
165             #
166 327 100       1209 return scalar(keys(%data)) unless wantarray();
167              
168             # fix up an array with the matches
169             #
170 324         470 my @matched;
171 324 100       596 if ($lonehash)
172             {
173             # we started with a hash, so that is what should be returned
174             #
175 24         47 my %h;
176 24         88 $h{${$data{$_}}->[0]} = ${$data{$_}}->[1] foreach (keys(%data));
  240         438  
  240         296  
177 24         79 push(@matched, \%h);
178             }
179             else
180             {
181             # keep the (relative) order they we're given to us by sorting on the artificial
182             # key index we gave them
183             #
184 300         1369 foreach my $k (sort { $a <=> $b } (keys(%data)))
  7016         8147  
185             {
186 2629         2797 push(@matched, ${$data{$k}});
  2629         3677  
187             }
188             }
189            
190             # now return the result list
191             #
192 324         5885 return @matched;
193             }
194              
195             sub __fingerprint
196             {
197 18931     18931   20242 my $digest = shift;
198 18931         19448 my $obj = shift;
199              
200 18931         20271 my $type = ref($obj);
201 18931         32460 $digest->add($type);
202 18931 100       28175 if ($type eq 'ARRAY') { __fingerprint($digest, $_) foreach (@$obj) }
  100 100       165  
203 2368         6720 elsif ($type eq 'HASH') { __fingerprint($digest, $obj->{$_}) foreach (sort(keys(%$obj))) }
204 16463         34592 else { $digest->add($digest->digest()) }
205            
206 18931         44922 return $digest;
207             }
208              
209             1;
210              
211             =head1 NAME
212              
213             Grep::Query - Query logic for lists of scalars/objects
214              
215             =head1 VERSION
216              
217             Version 1.010
218              
219             =head1 SYNOPSIS
220              
221             use Grep::Query qw(qgrep);
222            
223             my @data = ( 'a' .. 'z' );
224             my @result;
225              
226             # very simple query equal to a standard "grep(/[dkob]/, @data)"
227             #
228             @result = qgrep('REGEXP([dkob])', @data);
229             #
230             # @result contains ( 'd', 'k', 'o', 'b' )
231            
232             # go more wild
233             #
234             @result = qgrep('REGEXP([dkob]) AND ( REGEXP([yaxkz]) OR REGEXP([almn]) )', @data);
235             #
236             # @result contains ( 'k' )
237              
238             # or use it in OO fashion
239             #
240             my $gq = Grep::Query->new('REGEXP([dkob]) AND ( REGEXP([yaxkz]) OR REGEXP([almn]) )');
241             @result = $gq->qgrep(@data);
242            
243             # also query a list of objects, and use numerical comparisons too
244             #
245             my @persons = ...; # assume person objects can respond to '->getName()' and '->calculateAge()'
246            
247             # create a query object - note that the syntax now references 'field' names of name/age in the query
248             #
249             my $personQuery = Grep::Query->new('name.REGEXP(^A) AND age.>=(42)');
250            
251             # set up a field accessor to teach G::Q how to match field names to whatever's needed to get data from the objects
252             #
253             my $fieldAccessor = Grep::Query::FieldAccessor->new();
254             $fieldAccessor->add('name', sub { $_[0]->getName() });
255             $fieldAccessor->add('age', sub { $_[0]->calculateAge() });
256            
257             # now execute the query by passing the field accessor before the person list
258             #
259             @result = $personQuery->qgrep($fieldAccessor, @persons);
260             #
261             # @result contains a list of person objects that has a name starting with 'A' and an age greater than or equal to 42
262            
263             # If what you have is a single hash (rather than a list of them) and you wish to query it and pick out key/values
264             # that matches, the query is special cased for passing just a single hash.
265             # A field accessor is necessary, and it will receive individual key/value pairs as small lists.
266             #
267             # Assume a %videos hash, keyed by video name, and value is another hash with at least the key 'length' holding the video
268             # length in seconds...:
269             #
270             my $fieldAccessor = Grep::Query::FieldAccessor->new();
271             $fieldAccessor->add('key', sub { $_[0]->[0] });
272             $fieldAccessor->add('length', sub { $_[0]->[1]->{length} });
273             my $videoQuery = Grep::Query->new('key.REGEXP(^Alias) AND length.gt(2500)');
274             @result = $videoQuery->qgrep($fieldAccessor, \%videos);
275             #
276             # $result[0] contains a hash ref with all videos with name starting with 'Alias' and at least 2500 seconds long
277            
278             =head1 BACKGROUND
279              
280             Why use this module when you could easily write a grep BLOCK or plain regexp
281             EXPR to select things in a list using whatever criteria you desired?
282              
283             =head2 The original use-case was this:
284              
285             Given a number of commandline tools I provide to users in my workplace, quite
286             frequently I wanted the user to be able to express, with some flag(s), a
287             selection among a list of 'somethings' computed at runtime - the most common
288             probably a list of file/directory names. It was also common to have this type
289             of filtering defined in various configuration files and persistently apply them
290             every time a command was run.
291              
292             Example: the user gives the command:
293              
294             SomeCommand /some/path
295              
296             The 'SomeCommand' may, for example, scan the given path and for all files it finds it will
297             do something useful. So, I also wanted to provide flags for the command such
298             that they can say...
299              
300             SomeCommand -exclude 'some_regexp' /some/path
301              
302             ...in order to filter the list of files that should be worked on.
303              
304             Obviously not a problem, and I also provided the reverse if that was more
305             convenient:
306              
307             SomeCommand -include 'another_regexp' /some/path
308              
309             And the idea was extended so flags could be given multiple times and
310             interweaved:
311              
312             SomeCommand -include 'rx1' -exclude 'rx2' -include 'rx3' ... /some/path
313              
314             Thus, the original set was shrunk by first selecting only those matching the
315             regexp C and then shrink that by excluding those matching C etc. - I
316             think you get the idea.
317              
318             What I found however is that it becomes hard to string together regexps to find
319             the exact subset you want when the rules are a bit more complex. In fact, while
320             regexps are powerful, they're not that suited to easily mix multiple of them
321             (and some expressions are basically impossible, e.g. 'I want this but not this'),
322             especially when you try to provide a commandline interface to them...
323              
324             Thus, instead I'd wanted to provide a more capable way for a user to give a
325             more complex query, i.e. where it'd be possible to use AND/OR/NOT as well as
326             parenthesized groups, e.g. something like this (very contrived and structured
327             on several lines for readability):
328              
329             (
330             REGEXP/some_rx_1/ AND REGEXP/some_rx_2/
331             )
332             OR
333             (
334             REGEXP/some_rx_3/ AND NOT REGEXP/some_rx_4/
335             )
336             OR
337             NOT
338             (
339             REGEXP/some_rx_5/ OR NOT REGEXP/some_rx_6/
340             )
341              
342             Basically, feed 'something' the query and a list of scalars and get back a list
343             of the subset of scalars that fulfills the query. In short, behaving like a
344             grep, you might say, but where the normal BLOCK or EXPR is a query decided by
345             the user
346              
347             As it turned out, once the basics above was functioning I added some other
348             features, such as realizing that lists were not always just simple scalars, but
349             could just as well be "objects" and also that it then was useful to use
350             numerical comparisons rather than just regular expressions.
351              
352             Hence, this module to encapsulate the mechanism.
353              
354             =head3 Is it for you?
355              
356             It may be comparatively slow and very memory-intensive depending on the
357             complexity of the query and the size of the original data set.
358              
359             If your needs can be met by a regular grep call, utilizing a regular expression
360             directly, or using a block of code you can write beforehand, this module
361             probably isn't necessary, although it might be convenient if your block is
362             complex enough.
363              
364             =head1 DESCRIPTION
365              
366             The visible API is made to be simple but also compact - the single method/function
367             C, actually. For the slightly more complex scenarios a helper class is
368             required, but generally a very simple one giving high flexibility in how to structure
369             the query itself regardless of how the list itself is laid out.
370              
371             It has a behavior similar to C - give it a list and get back a list (or
372             in scalar context, the number of matches). The main difference is that the
373             matching stuff is a query expressed in a fairly simple language.
374              
375             It can be used in both non-OO and OO styles. The latter obviously useful when
376             the query will be used multiple times so as to avoid parsing the query every
377             time.
378              
379             The basic intent is to make it easy to do the easy stuff while still making it
380             easy to move up to something more complex, without having a wide or wordy API.
381             This is a two-edged sword - I hope this will not be confusing.
382              
383             =head2 QUERY LANGUAGE
384              
385             A query effectively have two slightly different "modes", depending on if the
386             query is aimed at a list of ordinary scalars or if the list consists of objects
387             (or plain hashes, which is regarded as a special case of objects). There is
388             also a special case when you pass only a single hash ref - it can be treated
389             as a list, and a new hash ref with matching key/value pairs passed back.
390              
391             =over
392              
393             =item Scalars
394              
395             In the first case, the query doesn't use "field" names - it is implicit that
396             the comparison should be made directly on scalars in the list.
397              
398             Note that is possible to use field names if desired - just make the accessors
399             so that it properly extracts parts of each scalar.
400              
401             =item Hashes/Objects
402              
403             In the second case, the query uses field names for the comparisons and
404             therefore a "field accessor" object is required when executing the query so as
405             to provide the query engine with the mapping between a field name and the data.
406              
407             A special case occurs when the list consists of hashes with keys being exactly
408             the field names - if so, the query engine can transparently create the
409             necessary field accessor if one is not passed in.
410              
411             The default field accessor also understands 'navigation paths', i.e. handling
412             a deep structure with lists-in-lists/hashes etc. This will work to any depth.
413              
414             =back
415              
416             It's important to note that either the query uses field names everywhere, or
417             not at all. Mixing comparisons with field names and others without is illegal.
418              
419             For hashes/objects it's necessary to use field names - otherwise you will match
420             against scalar representations of hashref values for example, e.g. 'HASH(0x12345678)'.
421             Hardly useful.
422              
423             =head3 SYNTAX
424              
425             The query language syntax is fairly straightforward and can be divided in two main
426             parts: the logical connectors and the comparison atoms.
427              
428             In the tables below, note that case is irrelevant, i.e. 'AND' is equal to 'and' which is
429             equal to 'And' and so on.
430              
431             =over
432              
433             =item Comments
434              
435             Comments can be used in the query using the begin/end style like '/* some comment */'.
436              
437             =item Logical connectors
438              
439             In this category we find the basic logic operators used to tie comparisons
440             together, i.e AND/OR/NOT and parentheses to enforce order.
441              
442             =over
443              
444             =item * B or B
445              
446             Used to negate the list generated by an expression.
447              
448             =item * B or B<&&>
449              
450             Used to select the intersection of two lists formed by expressions before and
451             after.
452              
453             =item * B or B<||>
454              
455             Used to select the union of two lists formed by expressions before and
456             after.
457              
458             =item * B<()>
459              
460             Used to enforce a grouping order.
461              
462             =back
463              
464             =item Comparison atoms
465              
466             A comparison atom is how to describe a match. It can be divided in string and
467             numeric matches. A complete atom can contain the following:
468              
469             IB<.>IBIB
470              
471             The I is optional. If given, it is terminated with a period (B<.>).
472             It cannot contain a period or a space, but otherwise it can be any text that
473             can be used as a hash key.
474              
475             The rest of the expression consists of an I and a I to be used
476             by that operator delimited by B and B. To
477             accommodate values happening to use characters normally used in a delimiter,
478             choice of character(s) is very flexible. The delimiters can be of two different
479             kinds. Either common start/stop pairs like parentheses: I<()>, braces: I<{}>,
480             brackets: I<[]> or angles: IE>. Or, it can be an arbitrary character except
481             space, and the same character again after the value, e.g. I.
482              
483             The Is are:
484              
485             =over
486              
487             =item * B or B
488              
489             These operators always evaluate to true and false respectively. They take no argument.
490              
491             =item * B
492              
493             This matches if the value is defined (i.e. not 'undef'). It takes no argument.
494              
495             =item * B
496              
497             This matches if the value has the given 'size' argument, where the size depends on the
498             data type - a scalar is simply the (text) length, an array is the array size, and a hash
499             is the number of pairs.
500              
501             =item * B
502              
503             This matches if the value has the given 'type' argument, where the type can be 'scalar',
504             'array' or 'hash'.
505              
506             =item * B
507              
508             This matches if the value is a hash, and has a key with the given argument.
509              
510             =item * B or B<=~>
511              
512             This operator expects to use the I as a regular expression for use in
513             matching.
514              
515             =item * B, B, B, B, B, B
516              
517             These are B based matches, i.e. I, I, I,
518             I, I and I.
519              
520             Don't confuse these with the B comparisons - results will likely
521             be unexpected since using these means that "2" is greater than "19"...
522              
523             =item * B<==>, B, B>, B=>, B>, B=>
524              
525             These are B matches.
526              
527             =back
528              
529             =back
530              
531             =head3 EXAMPLES
532              
533             # in normal Perl code, we would for example write:
534             #
535             my $v = "abcdefgh";
536             if ($v =~ /abc/)
537             {
538             ...
539             }
540            
541             # equivalent ways to write the regexp in a query would be:
542             #
543             REGEXP(abc)
544             regexp(abc) # case doesn't matter
545             =~(abc) # in case you're more comfortable with the Perl operator
546             =~{abc} # braces as delimiters
547             =~[abc] # brackets as delimiters
548             =~ # angles as delimiters
549             =~/abc/ # Perlish
550             =~dabcd # works, but quite confusing
551            
552             # a compound query with fields
553             #
554             name.REGEXP(^A) AND age.>=(42) # field names before the operators
555              
556             =head1 METHODS/FUNCTIONS
557              
558             =head2 new( $query )
559              
560             Constructor for a Grep::Query object if using the OO interface.
561              
562             The argument query string is required.
563              
564             Croaks if a problem is discovered.
565              
566             =head3 EXAMPLE
567              
568             # create a G::Q object
569             #
570             my $gq = Grep::Query->new('==(42) OR >(100)');
571              
572             =head2 getQuery()
573              
574             Returns the original query text.
575              
576             =head2 qgrep
577              
578             Execute a query.
579              
580             This method can be called in a few different ways, depending on if it's used in
581             an OO fashion or not, or if the query contains field names or not.
582              
583             Croaks if something is wrong.
584              
585             Return value: Number of matches in the given data list if called in scalar
586             context, the matching list otherwise. The return list will keep the relative order as the
587             original data list. A notable exception: if called in void context, the query
588             is skipped altogether - seems to be no point in spending a lot of work when no
589             one's interested in the results, right?
590              
591             =over
592              
593             =item * Non-OO, no fields: qgrep( $query, @data )
594              
595             The given C<$query> string will be parsed on the fly and executed against the
596             C<@data>.
597              
598             =item * Non-OO, with fields: qgrep( $query, $fieldAccessor, @data )
599              
600             The given C<$query> string will be parsed on the fly and executed against the
601             data, using the C<$fieldAccessor> object to get values from C<@data> objects.
602              
603             Note: In a certain case, the C<$fieldAccessor> argument can be passed as
604             C and it will be auto-generated. See below for details.
605            
606              
607             =item * OO, no fields: $obj->qgrep( @data )
608              
609             The C<$obj> must first have been created using L and then it can be
610             executed against the C<@data>.
611              
612             =item * OO, with fields: $obj->qgrep( $fieldAccessor, @data )
613              
614             The C<$obj> must first have been created using L and then it can be
615             executed, using the C<$fieldAccessor> object to get values from C<@data>
616             objects.
617              
618             Note: In a certain case, the C<$fieldAccessor> argument can be passed as
619             C and it will be auto-generated. See below for details.
620              
621             =item * Passing a single hashref: qgrep($fieldAccessor, \%hash)
622              
623             In this case, the field accessor methods will be called with two-item
624             arrayrefs, e.g. the key is in the first (0) slot, and the value is in the
625             second (1) slot.
626              
627             =back
628              
629             =head3 Autogenerated field accessor
630              
631             If the C<@data> holds plain hashes with keys exactly corresponding to the field
632             names used in the query, the query engine can autogenerate a field accessor.
633              
634             This is only a convenience, a manually constructed field accessor will be used
635             if given. To take advantage of the convenience, simply pass C as the
636             C<$fieldAccessor> argument.
637              
638             If you have a deep structure, you may use 'field' names connected by '->' linkages,
639             where raw text are used as regular hash keys and array indexes are denoted using
640             []. When the end of the navigation path has been reached the object at that
641             location is returned.
642              
643             =head3 EXAMPLES
644              
645             # sample data
646             my @scalarData = ( 105, 3, 98, 100, 42, 101, 42 );
647              
648             # make sure to import the qgrep function
649             #
650             use Grep::Query qw(qgrep);
651            
652             # now call it directly
653             #
654             my $matches = qgrep('==(42) OR >(100)', @scalarData);
655             #
656             # $matches is now 4 (matching 105, 42, 101, 42)
657            
658             # or equivalently, create a G::E object and call the method on it
659             #
660             my $gq = Grep::Query->new('==(42) OR >(100)');
661             $matches = $gq->qgrep(@scalarData);
662             #
663             # $matches again 4
664            
665             # some sample fielded data in a hash
666             #
667             my @hashData =
668             (
669             { x => 52, y => 38 },
670             { x => 94, y => 42 },
671             { x => 25, y => 77 }
672             );
673            
674             # autogenerate a field accessor since the query matches the fields
675             #
676             $matches = qgrep('x.>(20) AND y.>(40)', undef, @hashData);
677             #
678             # $matches is now 2 (matching last two entries)
679            
680             # but using different field names (or if it was opaque objects used)
681             # we must provide an explicit field accessor
682             #
683             my $fieldAccessor = Grep::Query::FieldAccessor->new
684             (
685             {
686             fieldY => sub { $_[0]->{y} },
687             fieldX => sub { $_[0]->{x} },
688             }
689             );
690             $matches = qgrep('fieldX.>(20) AND fieldY.>(40)', $fieldAccessor, @hashData);
691             #
692             # $matches again 2
693            
694             # a hash with depth
695             #
696             my @hashData =
697             (
698             { x => { fee => 1, fie => 2, foo => 3 }, y => [ 2, 4, 6 ] },
699             { x => { fee => 10, fie => 20, foo => 30 }, y => [ 12, 14, 16 ] },
700             { x => { fee => 100, fie => 200, foo => 300 }, y => [ 22, 24, 26 ] },
701             );
702             $matches = qgrep('x->fie.>(30) AND y->[2].>(20)', undef, @hashData);
703             #
704             # $matches is now 1 (matching last entry)
705            
706             =head1 AUTHOR
707              
708             Kenneth Olwing, C<< >>
709              
710             =head1 BUGS
711              
712             Please report any bugs or feature requests to C,
713             or through the web interface at
714             L. I will be
715             notified, and then you'll automatically be notified of progress on your bug as
716             I make changes.
717              
718             =head1 SUPPORT
719              
720             You can find documentation for this module with the perldoc command.
721              
722             perldoc Grep::Query
723              
724             You can also look for information at:
725              
726             =over 4
727              
728             =item * RT: CPAN's request tracker (report bugs here)
729              
730             L
731              
732             =item * AnnoCPAN: Annotated CPAN documentation
733              
734             L
735              
736             =item * CPAN Ratings
737              
738             L
739              
740             =item * Search CPAN
741              
742             L
743              
744             =back
745              
746             =head1 ACKNOWLEDGEMENTS
747              
748             First and foremost, I thank my family for putting up with me!
749              
750             =over
751              
752             =item David Mertens, C<< >> for the name.
753              
754             =item Ron Savage, C<< >> for helping follow current best
755             practices for modules.
756              
757             =back
758              
759             =head1 REPOSITORY
760              
761             L.
762              
763             =head1 LICENSE AND COPYRIGHT
764              
765             Copyright 2016 Kenneth Olwing.
766              
767             This program is free software; you can redistribute it and/or modify it
768             under the terms of the the Artistic License (2.0). You may obtain a
769             copy of the full license at:
770              
771             L
772              
773             Any use, modification, and distribution of the Standard or Modified
774             Versions is governed by this Artistic License. By using, modifying or
775             distributing the Package, you accept this license. Do not use, modify,
776             or distribute the Package, if you do not accept this license.
777              
778             If your Modified Version has been derived from a Modified Version made
779             by someone other than you, you are nevertheless required to ensure that
780             your Modified Version complies with the requirements of this license.
781              
782             This license does not grant you the right to use any trademark, service
783             mark, tradename, or logo of the Copyright Holder.
784              
785             This license includes the non-exclusive, worldwide, free-of-charge
786             patent license to make, have made, use, offer to sell, sell, import and
787             otherwise transfer the Package with respect to any patent claims
788             licensable by the Copyright Holder that are necessarily infringed by the
789             Package. If you institute patent litigation (including a cross-claim or
790             counterclaim) against any party alleging that the Package constitutes
791             direct or contributory patent infringement, then this Artistic License
792             to you shall terminate on the date that such litigation is filed.
793              
794             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
795             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
796             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
797             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
798             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
799             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
800             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
801             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
802              
803             =cut