1#!/usr/local/bin/perl
2##
3## greple: grep with multiple keywords
4##
5## Copyright (c) 1991-2017 Kazumasa Utashiro
6##
7## Original: Mar 29 1991
8##
9;; our($VERSION) = q$Revision: greple,v 7.1$ =~ /(\d+\.\d+)/g;
10;; my $rcsid = q$Id: greple,v 7.1 2017/03/06 03:29:33 utashiro Exp $;
11##
12## Use and redistribution for ANY PURPOSE are granted as long as all
13## copyright notices are retained.  Redistribution with modification
14## is allowed provided that you make your modified version obviously
15## distinguishable from the original one.  THIS SOFTWARE IS PROVIDED
16## BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES ARE
17## DISCLAIMED.
18##
19
20use strict;
21use warnings;
22
23require 5.010;
24
25use File::stat;
26use IO::Handle;
27use Pod::Usage;
28use Text::ParseWords qw(shellwords);
29use List::Util qw(min max first sum);
30use Scalar::Util qw(blessed);
31use Cwd qw(getcwd abs_path);
32use Data::Dumper;
33use Carp;
34
35use utf8;
36use Encode;
37use Encode::Guess;
38
39##
40## Setting utf8 warnings fatal makes it easy to find code conversion
41## error, so you can choose appropreate file code or automatic code
42## recognition, but loose a chance to find string in unrelated area.
43##
44use warnings FATAL => 'utf8';
45
46use Getopt::EX::Loader;
47use Getopt::EX::Func qw(parse_func);
48
49use App::Greple::Common;
50use App::Greple::Util;
51use App::Greple::Grep;
52use App::Greple::Regions;
53use App::Greple::Pattern;
54use App::Greple::Pattern::Holder;
55use App::Greple::Filter;
56
57
58=head1 NAME
59
60
61greple - grep with multiple keywords
62
63
64=head1 SYNOPSIS
65
66
67B<greple> [B<-M>I<module>] [ B<-options> ] pattern [ file... ]
68
69  PATTERN
70    pattern              'and +must -not ?alternative &function'
71    -e pattern           regex pattern match across line boundary
72    -r pattern           regex pattern cannot be compromised
73    -v pattern           regex pattern not to be matched
74    --le pattern         lexical expression (same as bare pattern)
75    --re pattern         regular expression
76    --fe pattern         fixed expression
77    --file file          file contains search pattern
78  MATCH
79    -i                   ignore case
80    --need=[+-]n         required positive match count
81    --allow=[+-]n        acceptable negative match count
82  STYLE
83    -l                   list filename only
84    -c                   print count of matched block only
85    -n                   print line number
86    -h                   do not display filenames
87    -H                   always display filenames
88    -o                   print only the matching part
89    -m n[,m]             max count of blocks to be shown
90    -A[n]                after match context
91    -B[n]                before match context
92    -C[n]                after and before match context
93    --join               delete newline in the matched part
94    --joinby=string      replace newline in the matched text by string
95    --nonewline          do not add newline character at block end
96    --filestyle=style    how filename printed (once, separate, line)
97    --linestyle=style    how line number printed (separate, line)
98    --separate           set filestyle and linestyle both "separate"
99  FILE
100    --glob=glob          glob target files
101    --chdir              change directory before search
102    --readlist           get filenames from stdin
103  COLOR
104    --color=when         use terminal color (auto, always, never)
105    --nocolor            same as --color=never
106    --colormap=color     R, G, B, C, M, Y etc.
107    --colorful           use default multiple colors
108    --ansicolor=s        ANSI color 16, 256 or 24bit
109    --[no]256            same as --ansicolor 256 or 16
110    --regioncolor        use different color for inside/outside regions
111    --uniqcolor          use different color for unique string
112    --random             use random color each time
113    --face               set/unset vidual effects
114  BLOCK
115    -p                   paragraph mode
116    --all                print whole data
117    --block=pattern      specify the block of records
118    --blockend=s         specify the block end mark (Default: "--\n")
119  REGION
120    --inside=pattern     select matches inside of pattern
121    --outside=pattern    select matches outside of pattern
122    --include=pattern    reduce matches to the area
123    --exclude=pattern    reduce matches to outside of the area
124    --strict             strict mode for --inside/outside --block
125  CHARACTER CODE
126    --icode=name         specify file encoding
127    --ocode=name         specify output encoding
128  FILTER
129    --if=filter          input filter command
130    --of=filter          output filter command
131    --pf=filter          post process filter command
132    --noif               disable default input filter
133  RUNTIME FUNCTION
134    --print=func         print function
135    --continue           continue after print function
136    --begin=func         call function before search
137    --end=func           call function after search
138  OTHER
139    --norc               skip reading startup file
140    --man                display command or module manual page
141    --show               display module file
142    --require=file       include perl program
143    --conceal=type       conceal run time errors
144    --persist            continue even after encoding error
145    -d flags             display info (f:file d:dir c:color m:misc s:stat)
146
147=cut
148
149my $rcloader = new Getopt::EX::Loader
150    BASECLASS => 'App::Greple';
151
152my @opt_e;
153my @opt_v;
154my @opt_r;
155my @opt_re;
156my @opt_le;
157my @opt_fe;
158my @opt_or;
159
160my @opt_if;
161my @opt_of;
162my @opt_pf;
163my @opt_glob;
164my @opt_icode;
165my @opt_block;
166my @opt_inside;
167my @opt_outside;
168my @opt_include;
169my @opt_exclude;
170my @opt_chdir;
171my @opt_begin;
172my @opt_end;
173my $opt_noif;
174my $opt_all;
175my $opt_blockend;
176my $opt_color = 'auto';
177my $opt_ansicolor = '256';
178my @opt_colormap;
179my $opt_colorful = 1;
180my @opt_face;
181my $opt_uniqcolor;
182my $opt_random;
183my $opt_regioncolor;
184my $opt_icode;
185my $opt_ocode;
186my $opt_man;
187my $opt_show;
188my $opt_join;
189my $opt_joinby = "";
190my $opt_newline = 1;
191my $opt_clean;
192my $opt_readlist;
193my $opt_need;
194my $opt_allow = 0;
195my @opt_need;
196my @opt_allow;
197my $opt_strict = 0;
198my @opt_print;
199my $opt_continue;
200my $opt_filestyle = 'line';
201my $opt_linestyle = 'line';
202my %opt_conceal = (read => 1, skip => 0);
203my $opt_persist = 0;
204my $opt_usage;
205
206my $opt_c;
207my @opt_d = ();
208my @opt_f;
209my $opt_h;
210my $opt_i;
211my $opt_n;
212my $opt_o;
213my $opt_m;
214my $opt_p;
215my $opt_l;
216my $opt_A = 0;
217my $opt_B = 0;
218my $opt_C = 0;
219my $opt_H;
220#my $opt_M;
221
222my @optargs = (
223    'e|and=s'            => \@opt_e,
224    'r|must=s'           => \@opt_r,
225    'v|not=s'            => \@opt_v,
226    'or=s'               => \@opt_or,
227    'le=s'               => \@opt_le,
228    're=s'               => \@opt_re,
229    'fe=s'               => \@opt_fe,
230    'need=s'             => \@opt_need,
231    'allow=s'            => \@opt_allow,
232    'i|ignore-case!'     => \$opt_i,
233    'l'                  => \$opt_l,
234    'c|count'            => \$opt_c,
235    'n|line-number!'     => \$opt_n,
236    'h|no-filename'      => \$opt_h,
237    'H'                  => \$opt_H,
238    'filestyle|fs=s'     => \$opt_filestyle,
239    'linestyle|ls=s'     => \$opt_linestyle,
240    'separate',          => sub {
241	$opt_filestyle = $opt_linestyle = $_[0]
242    },
243    'o|only-matching!'   => \$opt_o,
244    'm|max-count=s'      => \$opt_m,
245    'p|paragraph!'       => \$opt_p,
246    'A|after-context:2'  => \$opt_A,
247    'B|before-context:2' => \$opt_B,
248    'C|context:2'        => \$opt_C,
249    'all'                => \$opt_all,
250    'f|file=s'           => \@opt_f,
251    'readlist!'          => \$opt_readlist,
252    'd=s'                => \@opt_d,
253    'man'                => \$opt_man,
254    'show'               => \$opt_show,
255    'icode=s'            => \@opt_icode,
256    'ocode=s'            => \$opt_ocode,
257    'join!'              => \$opt_join,
258    'joinby=s'           => \$opt_joinby,
259    'newline!'           => \$opt_newline,
260    'if=s'               => \@opt_if,
261    'of=s'               => \@opt_of,
262    'pf=s'               => \@opt_pf,
263    'noif'               => \$opt_noif,
264    'block=s'            => \@opt_block,
265    'blockend:s'         => \$opt_blockend,
266    'inside=s'           => \@opt_inside,
267    'outside=s'          => \@opt_outside,
268    'include=s'          => \@opt_include,
269    'exclude=s'          => \@opt_exclude,
270    'strict!'            => \$opt_strict,
271    'chdir=s'            => \@opt_chdir,
272    'glob=s'             => \@opt_glob,
273    'begin=s'            => \@opt_begin,
274    'end=s'              => \@opt_end,
275    'clean!'             => \$opt_clean,
276    'color=s'            => \$opt_color,
277    'colormap|colormode|addcolor|cm:s'
278                         => \@opt_colormap,
279    'nocolor|nocolour'   => sub { $opt_color = 'never' },
280    'colorful!'          => \$opt_colorful,
281    'face=s'             => \@opt_face,
282    'uniqcolor|uc!'      => \$opt_uniqcolor,
283    'random!'            => \$opt_random,
284    'ansicolor=s'        => \$opt_ansicolor,
285    '256!'               => sub { $opt_ansicolor = $_[1] ? '256' : '16' },
286    'regioncolor|rc!'    => \$opt_regioncolor,
287    'print=s'            => \@opt_print,
288    'continue!'          => \$opt_continue,
289    'conceal=i'          => \%opt_conceal,
290    'persist!'           => \$opt_persist,
291    'usage:s'            => \$opt_usage,
292    'M:s'                => sub {
293	warn "Use -M option at the beginning with module name.\n";
294	if (my @modules = uniq($rcloader->modules())) {
295	    warn "Available modules:\n";
296	    warn "\t", join("\n\t", @modules), "\n";
297	}
298	exit 2;
299    },
300);
301
302sub newopt {
303    push @optargs, @_;
304}
305
306my %optargs;
307sub setopt {
308    unless (%optargs) {
309	for (my $i = 0; $i <= $#optargs; $i += 2) {
310	    my($spec, $ref) = @optargs[$i, $i + 1];
311	    while ($spec =~ /\G(\w+)\|?/g) {
312		$optargs{$1} = $ref;
313	    }
314	}
315    }
316    my $opt = ref $_[0] eq 'HASH' ? shift : {};
317    my $name = shift;
318    if (exists $optargs{$name}) {
319	my $ref = $optargs{$name};
320	if (ref $ref eq 'ARRAY') {
321	    if ($opt->{append}) {
322		push @$ref, @_;
323	    } else {
324		@$ref = @_;
325	    }
326	}
327	elsif (ref $ref eq 'CODE') {
328	    &$ref($name, @_);
329	}
330	elsif (ref $ref eq 'SCALAR') {
331	    $$ref = shift;
332	}
333	else {
334	    die "Object error.";
335	}
336    }
337}
338
339binmode STDERR, ":encoding(utf8)";
340
341
342##
343## @ARGV staff
344##
345
346require Getopt::Long;
347my $parser = new Getopt::Long::Parser
348    config => [ qw(bundling no_getopt_compat) ] ;
349sub configure_getopt { $parser->configure(@_) }
350
351configure_getopt qw(debug) if $ENV{DEBUG_GETOPT};
352$Getopt::EX::Loader::debug = 1 if $ENV{DEBUG_GETOPTEX};
353
354## decode
355map { $_ = decode 'utf8', $_ unless utf8::is_utf8($_) } @ARGV;
356
357## ~/.greplerc
358(@ARGV and $ARGV[0] eq "--norc" and shift) or
359    $rcloader->load(FILE => "$ENV{HOME}/.greplerc");
360
361## modules
362$rcloader->deal_with(\@ARGV);
363
364push @optargs, $rcloader->builtins;
365
366## ENV
367$ENV{'GREPLEOPTS'} and unshift @ARGV, shellwords($ENV{'GREPLEOPTS'});
368
369
370## GetOptions
371my @SAVEDARGV = @ARGV;
372$parser->getoptions(@optargs) || pod2usage;
373
374our %opt_d;
375@opt_d = map { split // } @opt_d;
376@opt_d{@opt_d} = @opt_d;
377
378if ($opt_d{o}) {
379    warn "\@ARGV = ", join(' ', shellquote(@SAVEDARGV)), "\n";
380}
381
382if (exists $opt_conceal{all}) {
383    $opt_conceal{$_} = $opt_conceal{all} for keys %opt_conceal;
384}
385
386## -m option
387my $splicer = do {
388    my($offset, $length);
389    if (not defined $opt_m) {
390	undef;
391    } elsif (($offset) = $opt_m =~ /^(-?\d+)$/) {
392	sub { splice @{+shift}, $offset }
393    } elsif (($offset, $length) = $opt_m =~ /^(-?\d+),(-?\d+)?$/) {
394	sub { splice @{+shift}, $offset, $length }
395    } else {
396	die "$opt_m: option format error.\n";
397    }
398};
399
400my $file_code;
401my $default_icode = 'utf8';	# default input encoding
402my @default_icode_list = qw(euc-jp 7bit-jis);
403my $output_code;
404my $default_ocode = 'utf8';	# default output encoding
405
406$output_code = $opt_ocode || $default_ocode;
407binmode STDOUT, ":encoding($output_code)";
408
409## show unused option characters
410if ($opt_d{u}) {
411    my $s = join('','0'..'9',"\n",'a'..'z',"\n",'A'..'Z',"\n");
412    map { /^([0-9a-zA-Z])(?:\|[^=]+)*(?:=[is])?$/ && $s =~ s/$1/./ } @optargs;
413    die $s;
414}
415
416## show man pages
417if ($opt_man or $opt_show) {
418    my @bucket = $rcloader->buckets;
419    if (@bucket and (my $mod = $bucket[-1]->title) ne ".greplerc") {
420	my @perldocopt = $opt_show ? '-m' : () ;
421	my $jp = first { -x "$_/perldocjp" } split /:/, $ENV{PATH};
422	my $perldoc = $jp ? "perldocjp" : "perldoc";
423	$ENV{PERL5LIB} = join ':', @INC;
424	my $command = "$perldoc @perldocopt App::Greple::$mod";
425	warn $command, "\n" if $opt_d{m};
426	exec $command or die $!;
427    }
428    pod2usage({-verbose => 2});
429    die;
430}
431
432## setup file encoding
433if (@opt_icode) {
434    @opt_icode = map { split /[,\s]+/ } @opt_icode;
435    if (grep { s/^\+// } @opt_icode) {
436	unshift @opt_icode, @default_icode_list;
437    }
438    @opt_icode = uniq(@opt_icode);
439    if (@opt_icode > 1) {
440	@opt_icode = grep { !/(?:auto|guess)$/i } @opt_icode;
441	Encode::Guess->set_suspects(@opt_icode);
442	$file_code = 'Guess';
443    }
444    elsif ($opt_icode[0] =~ /^(?:guess|auto)$/i) {
445	Encode::Guess->set_suspects(@default_icode_list);
446	$file_code = 'Guess';
447    } else {
448	$file_code = $opt_icode[0];
449    }
450}
451else {
452    $file_code = $default_icode;
453}
454
455##
456## Patterns
457##
458
459my $pat_holder = new App::Greple::Pattern::Holder;
460
461my $FLAG_BASE = FLAG_NONE;
462$FLAG_BASE |= FLAG_IGNORECASE if $opt_i;
463
464if (@opt_f) {
465    for my $opt_f (@opt_f) {
466	$pat_holder->append({ flag => $FLAG_BASE, type => 'file' },
467			    $opt_f);
468    }
469} else {
470    if (@opt_le + @opt_re + @opt_fe + @opt_or + @opt_e + @opt_r == 0) {
471	&usage if @ARGV == 0;
472	unshift @opt_le, shift @ARGV;
473    }
474}
475
476for ([ \@opt_r,  FLAG_REGEX | FLAG_COOK | FLAG_REQUIRED ],
477     [ \@opt_v,  FLAG_REGEX | FLAG_COOK | FLAG_NEGATIVE ],
478     [ \@opt_le, FLAG_REGEX | FLAG_COOK | FLAG_LEXICAL  ],
479     [ \@opt_or, FLAG_REGEX | FLAG_COOK | FLAG_OR       ],
480     [ \@opt_e,  FLAG_REGEX | FLAG_COOK                 ],
481     [ \@opt_re, FLAG_REGEX                             ],
482     [ \@opt_fe, FLAG_NONE                              ])
483{
484    my($opt, $flag) = @$_;
485    $pat_holder->append({ flag => $FLAG_BASE | $flag, type => 'pattern' },
486			@$opt) if @$opt;
487}
488
489##
490## set $opt_need and $opt_alow
491##
492{
493    my $must = grep({ $_->is_required } $pat_holder->patterns);
494    my $posi = grep({ $_->is_positive } $pat_holder->patterns) - $must;
495    my $nega = grep({ $_->is_negative } $pat_holder->patterns);
496
497    $opt_need = $must ? 0 : $posi;
498    for (@opt_need) {
499	if (/^-(\d+)$/) {	# --need -n
500	    $opt_need = $posi - $1;
501	}
502	elsif (/^\+(\d+)$/) {	# --need +n
503	    $opt_need += $1;
504	}
505	elsif (/^(\d+)$/) {	# --need n
506	    $opt_need = $1 - $must;
507	}
508	else {
509	    die "$_ is not valid count.\n"
510	}
511    }
512
513    $opt_allow = 0;
514    for (@opt_allow) {
515	if (/^-(\d+)$/) {	# --allow -n
516	    $opt_allow = $nega - $1;
517	}
518	elsif (/^\+(\d+)$/) {	# --allow +n
519	    $opt_allow += $1;
520	}
521	elsif (/^(\d+)$/) {	# --allow n
522	    $opt_allow = $1;
523	}
524	else {
525	    die "$_ is not valid count.\n"
526	}
527    }
528}
529
530##
531## setup input/output filter
532##
533my $filter_d = new App::Greple::Filter;
534$filter_d->parse(@opt_if);
535unless ($opt_noif) {
536    $filter_d->append(
537	[ sub { s/\.Z$//   }, 'zcat' ],
538	[ sub { s/\.g?z$// }, 'gunzip -c' ],
539	[ sub { m/\.pdf$/i }, 'pdftotext -nopgbrk - -' ],
540	[ sub { s/\.gpg$// }, 'gpg --quiet --no-mdc-warning --decrypt' ]);
541}
542
543##------------------------------------------------------------
544## miscellaneous setups
545##
546
547my @argv_files;
548my $start_directory;
549my $need_filename = ($opt_H or $opt_l);
550my $current_file;
551
552if (@opt_chdir) {
553    $start_directory = getcwd;
554    @opt_chdir = uniq(map { glob $_ } @opt_chdir);
555    push @argv_files, splice(@ARGV);
556    unless ($opt_h or
557	    (@opt_chdir == 1 and @argv_files == 1 and @opt_glob == 0)) {
558	$need_filename++;
559    }
560}
561elsif (@opt_glob) {
562    push @ARGV, map(glob, @opt_glob);
563}
564
565push(@ARGV, '-') unless @ARGV || @argv_files || @opt_glob || $opt_readlist;
566if ((@ARGV > 1 or $opt_readlist) and not $opt_h) {
567    $need_filename++;
568}
569
570$opt_join = 1 if $opt_joinby ne "";
571
572##------------------------------------------------------------
573## colors
574##
575my %colormap = (
576    FILE     => "G",
577    LINE     => "Y",
578    BLOCKEND => "",
579    );
580
581my @colors;
582
583require Getopt::EX::Colormap;
584my $color_handler = new Getopt::EX::Colormap
585    HASH => \%colormap,
586    LIST => \@colors,
587    ;
588$color_handler->load_params(@opt_colormap);
589
590my @default_color =
591    $opt_ansicolor eq '16'
592    ? qw(RD GD BD CD MD YD)
593    : qw(DK/544 DK/454 DK/445
594	 DK/455 DK/545 DK/554
595	 DK/543 DK/453 DK/435
596	 DK/534 DK/354 DK/345
597	 DK/444
598	 DK/433 DK/343 DK/334
599	 DK/344 DK/434 DK/443
600	 DK/333)
601    ;
602
603if ($color_handler->list == 0) {
604    $color_handler->append
605	($opt_colorful ? @default_color : $default_color[0]);
606}
607
608if ($opt_ansicolor eq '24bit') {
609    no warnings 'once';
610    $Getopt::EX::Colormap::COLOR_RGB24 = 1;
611}
612
613if (@opt_face) {
614    my $remove = 0;
615    for my $flag (map { split // } @opt_face) {
616	if ($flag eq '-' or $flag eq '+') {
617	    $remove = $flag eq '-';
618	    next;
619	}
620	map { $remove ? s/$flag//g : s/^/$flag/ } @colors;
621    }
622}
623
624my $need_color = (($opt_color eq 'always')
625		  or (($opt_color eq 'auto') and (!$opt_o and -t STDOUT)));
626
627if ($opt_d{c}) {
628    my $dump = sub {
629	local $_ = Dumper shift;
630	s/(?<=')([\w\/]+)(?=')/color($1, $1)/ge;
631	$_;
632    };
633    warn 'colormap = ', $dump->(\%colormap);
634    warn 'colors = ', $dump->(\@colors);
635}
636
637sub _file     { $color_handler->color('FILE'    , @_) }
638sub _line     { $color_handler->color('LINE'    , @_) }
639sub _delim    { $color_handler->color('DELIM'   , @_) }
640sub _blockend { $color_handler->color('BLOCKEND', @_) }
641
642sub index_color {
643    $color_handler->index_color(@_);
644}
645
646sub color {
647    $color_handler->color(@_);
648}
649
650my $uniq_color = new UniqIndex
651    ignore_newline => 1;
652
653sub dump_uniqcolor {
654    my $list = $uniq_color->list;
655    for my $i (0 .. $#{ $list }) {
656	warn sprintf "%d %s\n", $i, index_color($i, $list->[$i]);
657    }
658}
659
660
661my $blockend = "--\n";
662if (defined $opt_blockend) {
663    ($blockend = $opt_blockend) =~ s/(?<=.)$/\n/;
664}
665if ($opt_C) {
666    $opt_A ||= $opt_C;
667    $opt_B ||= $opt_C;
668}
669my %stat = (
670    files => 0,
671    match_effective => 0,
672    match_positive => 0,
673    match_negative => 0,
674    match_block => 0,
675    time_start => [],
676    time_end => [],
677    );
678
679##
680## Setup functions
681##
682for my $set (
683    [ "print"  , \@opt_print  , 0 ],
684    [ "begin"  , \@opt_begin  , 0 ],
685    [ "end"    , \@opt_end    , 0 ],
686    [ "block"  , \@opt_block  , 1 ], # need &
687    [ "inside" , \@opt_inside , 1 ], # need &
688    [ "outside", \@opt_outside, 1 ], # need &
689    [ "include", \@opt_include, 1 ], # need &
690    [ "exclude", \@opt_exclude, 1 ], # need &
691    ) {
692    my($cat, $opt, $pattern) = @$set;
693    for (@{$opt}) {
694	next if $_->can('call');
695	/^&\w+/ or next if $pattern;
696	$_ = parse_func($_) or die "$cat function format error: $_\n";
697    }
698}
699
700my $regions = new App::Greple::Regions::Holder;
701for my $set (
702    [ \@opt_inside,  REGION_INSIDE  | REGION_UNION     ],
703    [ \@opt_outside, REGION_OUTSIDE | REGION_UNION     ],
704    [ \@opt_include, REGION_INSIDE  | REGION_INTERSECT ],
705    [ \@opt_exclude, REGION_OUTSIDE | REGION_INTERSECT ])
706{
707    my($opt, $flag) = @$set;
708    for my $spec (@$opt) {
709	append $regions FLAG => $flag, SPEC => $spec;
710    }
711}
712
713##------------------------------------------------------------
714
715if ($opt_d{m}) {
716    warn "Search pattern:\n";
717    my $i;
718    for my $pat ($pat_holder->patterns) {
719	my $type =
720	    $pat->is_function ? 'func' :
721	    $pat->is_required ? 'must' :
722	    $pat->is_negative ? 'not ' :
723	    $pat->is_positive ? 'and ' : 'unknown';
724	my $target = $pat->cooked;
725	warn sprintf("  %s %s\n",
726		     $type,
727		     @colors > 1 ? index_color($i++, $target) : $target);
728    }
729    warn sprintf "need = %d, allow = %d\n", $opt_need, $opt_allow;
730}
731
732## push post-process filter
733if (@opt_pf) {
734    push_output_filter(\*STDOUT, @opt_pf);
735}
736
737usage() and exit if defined $opt_usage;
738
739open SAVESTDIN,  '<&', \*STDIN  or die "open: $!";
740open SAVESTDOUT, '>&', \*STDOUT or die "open: $!";
741open SAVESTDERR, '>&', \*STDERR or die "open: $!";
742
743sub recover_stdin {
744    open STDIN, '<&', \*SAVESTDIN or die "open: $!";
745}
746sub recover_stderr {
747    open STDERR, '>&', \*SAVESTDERR or die "open: $!";
748    binmode STDERR, ':encoding(utf8)';
749}
750sub recover_stdout {
751    close STDOUT;
752    open STDOUT, '>&', \*SAVESTDOUT or die "open: $!";
753}
754sub close_stdout {
755    close SAVESTDOUT;
756    close STDOUT;
757}
758
759sub read_stdin { <SAVESTDIN> }
760
761my($before_read, $after_read);
762if ($opt_conceal{read}) {
763    $before_read = sub { close STDERR };
764    $after_read  = sub { recover_stderr };
765}
766
767##------------------------------------------------------------
768## now ready to run.
769##
770
771## record start time
772if ($opt_d{s}) {
773    $stat{time_start} = [times];
774}
775
776grep_files();
777
778if ($opt_uniqcolor and $opt_d{m}) {
779    dump_uniqcolor();
780}
781
782## show statistic info
783if ($opt_d{s}) {
784
785    $stat{time_end} = [times];
786    my @s = @{$stat{time_start}};
787    my @e = @{$stat{time_end}};
788    printf(STDERR "cpu %.3fu %.3fs\n", $e[0]-$s[0], $e[1]-$s[1]);
789
790    local $" = ', ';
791    for my $k (sort keys %stat) {
792	my $v = $stat{$k};
793	print STDERR
794	    "$k: ",
795	    ref $v eq 'ARRAY' ? "(@$v)" : $v,
796	    "\n";
797    }
798}
799
800close_stdout;
801
802if ($opt_d{p}) {
803    open STDOUT, ">&STDERR";
804    system "ps -lww -p $$";
805    system "lsof -p $$";
806}
807
808exit($stat{match_effective} == 0);
809
810######################################################################
811
812sub grep_files {
813  FILE:
814    while (defined($current_file = open_nextfile())) {
815
816	&$before_read() if $before_read;
817	my $content = eval { local $/; <STDIN> };
818	&$after_read() if $after_read;
819
820	if (not defined $content) {
821	    warn $@ if $@;
822	    if (not $opt_persist) {
823		warn "SKIP $current_file\n" unless $opt_conceal{skip};
824		next FILE;
825	    }
826
827	    # Try again
828	    binmode STDIN, ':raw';
829	    $content = eval { local $/; <STDIN> };
830	    if (not defined $content) {
831		warn "SKIP* $current_file\n" unless $opt_conceal{skip};
832		next FILE;
833	    }
834	    binmode STDOUT, ':raw';
835	}
836
837	warn $current_file, ":\n" if $opt_d{f};
838
839	my $matched = grep_data(\$content);
840
841	no warnings 'uninitialized'; # why ?
842	$stat{match_effective} += $matched;
843	$stat{files}++;
844    } continue {
845	close STDIN; # wait;	# wait for 4.019 or earlier?
846	# recover STDIN for opening '-' and some weird command which needs
847	# STDIN opened (like unzip)
848	recover_stdin;
849    }
850}
851
852sub usage {
853    pod2usage(-verbose => 0, -exitval => "NOEXIT");
854
855    my $quote = qr/[\\(){}\|\*?]/;
856    for my $bucket ($rcloader->buckets) {
857	my $title = $bucket->title;
858	print "    $title options:\n";
859	for my $name ($bucket->options) {
860	    my $help = $opt_usage ? "" : $bucket->help($name) // "";
861	    next if $help eq 'ignore';
862	    my @option = $bucket->getopt($name, ALL => 1);
863	    printf("        %-20s %s\n", $name,
864		   $help || join(' ', shellquote(@option)));
865	}
866	print "\n";
867    }
868
869    print "$rcsid\n" if $rcsid =~ /:/;
870
871    exit 2;
872}
873
874sub open_nextfile {
875
876    ##
877    ## --chdir
878    ##
879    while (@ARGV == 0 and @opt_chdir and (@argv_files or @opt_glob)) {
880	my $dir = shift @opt_chdir;
881	warn "chdir $dir/\n" if $opt_d{d};
882	chdir $start_directory or die "$!: $start_directory\n";
883	chdir $dir or die "$!: $dir\n";
884	push @ARGV, @argv_files, map(glob, @opt_glob);
885    }
886
887    my $file;
888    while (defined($file = shift(@ARGV)) ||
889	   defined($file = $opt_readlist && read_stdin)) {
890	$file =~ s/\n+$//;
891
892	if (0) {}
893	elsif ($file =~ /^http:\/\//) {
894	    open(STDIN, '-|') || exec("w3m -dump $file") || die "w3m: $!\n";
895	}
896	else {
897	    open(STDIN, $file) or do {
898		warn "$file: $!\n" unless -l $file;
899		next;
900	    };
901	}
902
903	if (my @filters = $filter_d->get_filters($file)) {
904	    push_input_filter(@filters);
905	}
906
907	if ($file_code eq 'binary') {
908	    # binmode STDIN, ":raw";
909	} else {
910	    binmode STDIN, ":encoding($file_code)";
911	}
912
913	return $file;
914    }
915    undef;
916}
917
918######################################################################
919
920sub grep_data {
921    local *_ = shift;
922
923    ##
924    ## --begin
925    ##
926    for my $f (@opt_begin) {
927	$f->call(&FILELABEL => $current_file);
928    }
929
930    my $grep = new App::Greple::Grep (
931	text         => \$_,
932	filename     => $current_file,
933	pattern      => $pat_holder,
934	regions      => $regions,
935	after        => $opt_A,
936	before       => $opt_B,
937	paragraph    => $opt_p,
938	only         => $opt_o,
939	all          => $opt_all,
940	block        => \@opt_block,
941	need         => $opt_need,
942	allow        => $opt_allow,
943	strict       => $opt_strict,
944	region_index => $opt_regioncolor,
945	stat         => \%stat,
946	)->run;
947    my $matched = $grep->matched;
948
949    $splicer->($grep->result_ref) if $splicer;
950
951    if ($opt_l) {
952	print "$current_file\n" if $matched;
953    }
954    elsif ($opt_c) {
955	print "$current_file:" if $need_filename;
956	print scalar $grep->blocks, "\n";
957    }
958    elsif (@{$grep->result_ref}) {
959	# open output filter
960	@opt_of && push_output_filter(\*STDOUT, @opt_of);
961	display_result($grep);
962	@opt_of && recover_stdout;
963    }
964
965    ##
966    ## --end
967    ##
968    for my $f (@opt_end) {
969	$f->call(&FILELABEL => $current_file);
970    }
971
972    s/./\000/gs if $opt_clean;
973
974    $matched;
975}
976
977sub display_result {
978    my $grep = shift;
979    my $file = $grep->{filename};
980
981    if ($need_filename and $opt_filestyle eq 'once') {
982	print $file, ":\n";
983    }
984
985    my $need_blockend =
986	$opt_blockend || $opt_p || $opt_A || $opt_B || @opt_block;
987
988    my $line = 1;
989    my $lastpos = 0;
990    for my $result ($grep->result) {
991
992	my($block_start, $block_end) = @{shift @$result};
993	my $block = $grep->cut($block_start, $block_end);
994
995	for my $func (@opt_print) {
996	    for ($block) {
997		$_ = $func->call(&FILELABEL => $file, matched => $result);
998	    }
999	}
1000	if (@opt_print and not $opt_continue) {
1001	    print $block if defined $block;
1002	    next;
1003	}
1004
1005	if ($opt_n) {
1006	    my $gap = $grep->cut($lastpos, $block_start);
1007	    $line += $gap =~ tr/\n/\n/;
1008	}
1009	$lastpos = $block_end;
1010
1011	if (my $nl = 0, 1) {
1012	    if ($need_filename and $opt_filestyle eq 'separate') {
1013		print _file("$current_file:");
1014		$nl++;
1015	    }
1016	    if ($opt_n and $opt_linestyle eq 'separate') {
1017		print _line("$line:");
1018		$nl++;
1019	    }
1020	    print "\n" if $nl;
1021	}
1022
1023	my $mark = "\001";
1024	for my $matched (reverse @$result) {
1025	    my($ms, $me, $pi) = @$matched;
1026	    next if $ms == $me;
1027
1028	    $ms = max($ms - $block_start, 0);
1029	    $me -= $block_start;
1030	    my $s = substr($block, $ms, $me - $ms);
1031
1032	    if ($opt_join) {
1033		if ($opt_n and $opt_linestyle eq 'line') {
1034		    $s =~ s/(?<!\A)\n(?!\z)/$mark/g;
1035		} else {
1036		    $s =~ s/(?<!\A)\n(?!\z)/$opt_joinby/g;
1037		}
1038	    }
1039
1040	    # --random
1041	    if ($opt_random) {
1042		$pi = rand(@colors);
1043	    }
1044	    # --uniqcolor
1045	    elsif ($opt_uniqcolor) {
1046		$pi = $uniq_color->index($s);
1047	    }
1048
1049	    substr($block, $ms, $me - $ms,
1050		   $need_color ? index_color($pi, $s) : $s);
1051	}
1052	if ($opt_n) {
1053	    if ($opt_linestyle eq 'line') {
1054		my $increment = $block =~ /[\n$mark]/ ? 1 : 0;
1055		$block =~ s{(?:($mark)|(?<=\n)|\A)(?=.)}{
1056			    my $s = $1 ? $opt_joinby
1057				       : _line("$line:");
1058			    $line += $increment;
1059			    $s;
1060			   }gse;
1061	    } else {
1062		$line += $block =~ tr/\n/\n/;
1063	    }
1064	}
1065
1066	if ($need_filename and $opt_filestyle eq 'line') {
1067	    my $s = _file("$file:");
1068	    $block =~ s/^/$s/mg;
1069	}
1070
1071	print $block;
1072	print "\n" if $opt_newline and not $block =~ /\n\z/;
1073	print _blockend($blockend) if $need_blockend;
1074    }
1075}
1076
1077
1078__END__
1079
1080
1081=head1 DESCRIPTION
1082
1083
1084=head2 MULTIPLE KEYWORDS
1085
1086
1087B<greple> has almost the same function as Unix command L<egrep(1)> but
1088the search is done in the manner similar to search engine.  For
1089example, next command print lines those contain all of `foo' and `bar'
1090and `baz'.
1091
1092    greple 'foo bar baz' ...
1093
1094Each word can be found in any order and/or any place in the string.
1095So this command find all of following texts.
1096
1097    foo bar baz
1098    baz bar foo
1099    the foo, bar and baz
1100
1101If you want to use OR syntax, prepend question (`?') mark on each
1102token, or use regular expression.
1103
1104    greple 'foo bar baz ?yabba ?dabba ?doo'
1105    greple 'foo bar baz yabba|dabba|doo'
1106
1107This command will print the line which contains all of `foo', `bar'
1108and `baz' and one or more from `yabba', `dabba' or `doo'.
1109
1110NOT operator can be specified by prefixing the token by minus (`-')
1111sign.  Next example will show the line which contain both `foo' and
1112bar' but none of `yabba' or `dabba' or `doo'.
1113
1114    greple 'foo bar -yabba -dabba -doo'
1115
1116This can be written as this using B<-e> and B<-v> option.
1117
1118    greple -e foo -e bar -v yabba -v dabba -v doo
1119    greple -e foo -e bar -v 'yabba|dabba|doo'
1120
1121If `+' is placed to positive matching pattern, that pattern is marked
1122as required, and match required count is automatically set to the
1123number of required pattern.  So
1124
1125    greple '+foo bar baz'
1126
1127commands implicitly set the option C<--need 1>, and consequently print
1128all lines including `foo'.  If you want to search lines which includes
1129either or both of `bar' and `baz', use like this:
1130
1131    greple '+foo bar baz' --need 2
1132    greple '+foo bar baz' --need +1
1133
1134=head2 LINE ACROSS MATCH
1135
1136
1137B<greple> also search the pattern across the line boundaries.  This is
1138especially useful to handle Asian multi-byte text.  Japanese text can
1139be separated by newline almost any place of the text.  So the search
1140pattern may spread out on multiple lines.
1141
1142As for ascii text, space character in the pattern matches any kind of
1143space including newline.  Next example will search the word sequence
1144of `foo', `bar' and 'baz', even they spread out to multiple lines.
1145
1146    greple -e 'foo bar baz'
1147
1148Option B<-e> is necessary because space is taken as a token separator
1149in the bare or B<--le> pattern.
1150
1151
1152=head1 OPTIONS
1153
1154
1155=head2 PATTERNS
1156
1157
1158If no specific option is given, B<greple> takes the first argument as
1159a search pattern specified by B<--le> option.  All of these patterns
1160can be specified multiple times.
1161
1162Command itself is written in Perl, and any kind of Perl style regular
1163expression can be used in patterns.  See L<perlre(1)> for detail.
1164
1165Note that multiple line modifier (C<m>) is set when executed, so put
1166C<(?-m)> at the beginning of regex if you want to explicitly disable
1167it.
1168
1169Order of capture group in the pattern is not guaranteed.  Please avoid
1170to use direct index, and use relative or named capture group instead.
1171For example, repeated character can be written as S<C<(\w)\g{-1}>>
1172or S<C<(?E<lt>cE<gt>\w)\g{c}>>.
1173
1174=over 7
1175
1176=item B<--le>=I<pattern>
1177
1178Treat the string as a collection of tokens separated by spaces.  Each
1179token is interpreted by the first character.  Token start with `-'
1180means negative pattern, `?' means alternative, and `+' does required.
1181
1182Next example print lines which contains `foo' and `bar', and one or
1183more of `yabba' and 'dabba', and none of `baz' and `doo'.
1184
1185    greple --le='foo bar -baz ?yabba ?dabba -doo'
1186
1187Multiple `?' preceded tokens are treated all mixed together.  That
1188means `?A|B ?C|D' is equivalent to `?A|B|C|D'.  If you want to mean
1189`(A or B) and (C or D)', use AND syntax instead: `A|B C|D'.
1190
1191If the pattern start with ampersand (`&'), it is treated as a
1192function, and the function is called instead of searching pattern.
1193Function call interface is same as the one for block/region options.
1194
1195If you have a definition of I<odd_line> function in you F<.greplerc>,
1196which is described in this manual later, you can print odd number
1197lines like this:
1198
1199    greple -n '&odd_line' file
1200
1201This is the summary of start character for B<--le> option:
1202
1203    +  Required pattern
1204    -  Negative match pattern
1205    ?  Alternative pattern
1206    &  Function call
1207
1208=item B<-e> I<pattern>, B<--and>=I<pattern>
1209
1210Specify positive match token.  Next two commands are equivalent.
1211
1212    greple 'foo bar baz'
1213    greple -e foo -e bar -e baz
1214
1215First character is not interpreted, so next commands will search the
1216pattern `-baz'.
1217
1218    greple -e -baz
1219
1220Space characters are treated specially by B<-e> and B<-v> options.
1221They are replaced by the pattern which matches any number of
1222white spaces including newline.  So the pattern can be expand to
1223multiple lines.  Next commands search the series of word `foo', `bar'
1224and `baz' even if they are separated by newlines.
1225
1226    greple -e 'foo bar baz'
1227
1228=item B<-r> I<pattern>, B<--must>=I<pattern>
1229
1230Specify required match token.  Next two commands are equivalent.
1231
1232    greple '+foo bar baz'
1233    greple -r foo -e bar -e baz
1234
1235=item B<-v> I<pattern>, B<--not>=I<pattern>
1236
1237Specify negative match token.  Because it does not affect to the bare
1238pattern argument, you can narrow down the search result like this.
1239
1240    greple foo file
1241    greple foo file -v bar
1242    greple foo file -v bar -v baz
1243
1244=item B<--re>=I<pattern>
1245
1246Specify regular expression.  No special treatment for space and wide
1247characters.
1248
1249=item B<--fe>=I<pattern>
1250
1251Specify fixed string pattern, like fgrep.
1252
1253=item B<-i>, B<--ignore-case>
1254
1255Ignore case.
1256
1257=item B<--need>=I<n>
1258
1259=item B<--allow>=I<n>
1260
1261Option to compromise matching condition.  Option B<--need> specifies
1262the required match count, and B<--allow> the number of negative
1263condition to be overlooked.
1264
1265    greple --need=2 --allow=1 'foo bar baz -yabba -dabba -doo'
1266
1267Above command prints the line which contains two or more from `foo',
1268`bar' and `baz', and does not include more than one of `yabba',
1269`dabba' or `doo'.
1270
1271Using option B<--need>=I<1>, B<greple> produces same result as B<grep>
1272command.
1273
1274    grep -e foo -e bar -e baz
1275    greple --need=1 -e foo -e bar -e baz
1276
1277When the count I<n> is negative value, it is subtracted from default
1278value.
1279
1280=item B<-f> I<file>, B<--file>=I<file>
1281
1282Specify the file which contains search pattern.  When file contains
1283multiple lines, patterns on each lines are search in OR context.
1284
1285Blank line and the line starting with sharp (#) character is ignored.
1286Two slashes (//) and following string are taken as a comment and
1287removed with preceding spaces.
1288
1289Multiple file can be specified, but they will be mixed into single
1290pattern.
1291
1292=back
1293
1294
1295=head2 STYLES
1296
1297
1298=over 7
1299
1300=item B<-l>
1301
1302List filename only.
1303
1304=item B<-c>, B<--count>
1305
1306Print count of matched block.
1307
1308=item B<-n>, B<--line-number>
1309
1310Show line number.
1311
1312=item B<-h>, B<--no-filename>
1313
1314Do not display filename.
1315
1316=item B<-H>
1317
1318Display filename always.
1319
1320=item B<-o>, B<--only-matching>
1321
1322Print matched string only.
1323
1324=item B<-m> I<n>[,I<m>], B<--max-count>=I<n>[,I<m>]
1325
1326Set the maximum count of blocks to be shown to I<n>.
1327
1328Actually I<n> and I<m> are simply passed to perl L<splice> function as
1329I<offset> and I<length>.  Works like this:
1330
1331    greple -m  10      # get first 10 blocks
1332    greple -m   0,-10  # get last 10 blocks
1333    greple -m   0,10   # remove first 10 blocks
1334    greple -m -10      # remove last 10 blocks
1335    greple -m  10,10   # remove 10 blocks from 10th (10-19)
1336
1337This option does not affect to search performance and command exit
1338status.
1339
1340=item B<-A>[I<n>], B<--after-context>[=I<n>]
1341
1342=item B<-B>[I<n>], B<--before-context>[=I<n>]
1343
1344=item B<-C>[I<n>], B<--context>[=I<n>]
1345
1346Print I<n>-blocks before/after matched string.  The value I<n> can be
1347omitted and the default is 2.  When used with B<--paragraph> or
1348B<--block> option, I<n> means number of paragraph or block.
1349
1350Actually, these options expand the area of logical operation.  It
1351means
1352
1353    grep -C1 'foo bar baz'
1354
1355matches following text.
1356
1357    foo
1358    bar
1359    baz
1360
1361Moreover
1362
1363    greple -C1 'foo baz'
1364
1365also matches this text, because matching blocks around `foo' and `bar'
1366overlaps each other and makes single block.
1367
1368=item B<--join>
1369
1370=item B<--joinby>=I<string>
1371
1372Convert newline character found in matched string to empty or specified
1373I<string>.  Using B<--join> with B<-o> (only-matching) option, you can
1374collect searching sentence list in one per line form.  This is
1375sometimes useful for Japanese text processing.  For example, next
1376command prints the list of KATAKANA words, including those spread
1377across multiple lines.
1378
1379    greple -ho --join '\p{InKatakana}+(\n\p{InKatakana}+)*'
1380
1381Space separated word sequence can be processed with B<--joinby>
1382option.  Next example prints all `for *something*' pattern in pod
1383documents within Perl script.
1384
1385    greple -Mperl --pod -ioe '\bfor \w+' --joinby ' '
1386
1387=item B<--[no]newline>
1388
1389Since B<greple> can handle arbitrary blocks other than normal text
1390lines, they sometimes do not end by newline character.  In that case,
1391extra newline is appended at the end of block to be shown.  Option
1392B<--nonewline> disables this behaviour.
1393
1394=item B<--filestyle>=I<line>|I<once>|I<separate>, B<--fs>
1395
1396Default style is I<line>, and B<greple> prints filename at the
1397beginning of each line.  Style I<once> prints the filename only once
1398at the first time.  Style I<separate> prints filename in the separate
1399line before each line or block.
1400
1401=item B<--linestyle>=I<line>|I<separate>, B<--ls>
1402
1403Default style is I<line>, and B<greple> prints line numbers at the
1404beginning of each line.  Style I<separate> prints line number in the
1405separate line before each line or block.
1406
1407=item B<--separate>
1408
1409Shortcut for B<--filestyle>=I<separate> B<--linestyle>=I<separate>.
1410This is convenient to use block mode search and visiting each location
1411from supporting tool, such as Emacs.
1412
1413=back
1414
1415
1416=head2 FILES
1417
1418
1419=over 7
1420
1421=item B<--glob>=I<pattern>
1422
1423Get files matches to specified pattern and use them as a target files.
1424Using B<--chdir> and B<--glob> makes easy to use B<greple> for fixed
1425common job.
1426
1427=item B<--chdir>=I<directory>
1428
1429Change directory before processing files.  When multiple directories
1430are specified in B<--chdir> option, by using wildcard form or
1431repeating option, B<--glob> file expansion will be done for every
1432directories.
1433
1434    greple --chdir '/usr/man/man?' --glob '*.[0-9]' ...
1435
1436=item B<--readlist>
1437
1438Get filenames from standard input.  Read standard input and use each
1439line as a filename for searching.  You can feed the output from other
1440command like L<find(1)> for B<greple> with this option.  Next example
1441searches string from files modified within 7 days:
1442
1443    find . -mtime -7 -print | greple --readlist pattern
1444
1445Using B<find> module, this can be done like:
1446
1447    greple -Mfind . -mtime -7 -- pattern
1448
1449=back
1450
1451
1452=head2 COLORS
1453
1454
1455=over 7
1456
1457=item B<--color>=I<auto>|I<always>|I<never>, B<--nocolor>
1458
1459Use terminal color capability to emphasize the matched text.  Default
1460is `auto': effective when STDOUT is a terminal and option B<-o> is not
1461given, not otherwise.  Option value `always' and `never' will work as
1462expected.
1463
1464Option B<--nocolor> is alias for B<--color>=I<never>.
1465
1466=item B<--colormap>=I<spec>
1467
1468Specify color map.  Default is RD: RED and BOLD.
1469
1470Color specification is combination of single uppercase character
1471representing 8 colors :
1472
1473    R  Red
1474    G  Green
1475    B  Blue
1476    C  Cyan
1477    M  Magenta
1478    Y  Yellow
1479    K  Black
1480    W  White
1481
1482and alternative (usually brighter) colors in lowercase:
1483
1484    r, g, b, c, m, y, k, w
1485
1486or RGB value and 24 grey levels if using ANSI 256 color terminal :
1487
1488    000000 .. FFFFFF : 24bit RGB colors
1489    000 .. 555       : 6x6x6 RGB 216 colors
1490    L00 .. L23       : 24 grey levels
1491
1492=over 4
1493
1494Note that, when values are all same in 24bit RGB, it is converted to
149524 grey level, otherwise 6x6x6 216 color.
1496
1497=back
1498
1499with other special effects :
1500
1501    Z  Zero (reset)
1502    D  Double-struck (boldface)
1503    P  Pale (dark)
1504    I  Italic
1505    S  Stand-out (reverse video)
1506    V  Vanish (concealed)
1507    U  Underline
1508    F  Flash (blink)
1509
1510    ;  No effect
1511    X  No effect
1512
1513If the spec includes C</>, left side is considered for foreground
1514color and right side is for background.  If multiple colors are
1515given in same spec, all indicators are produced in the order of
1516their presence.  As a result, the last one takes effect.
1517
1518Effect characters are case insensitive, and can be found anywhere and
1519in any order in color spec string.  Because C<X> and C<;> takes no
1520effect, you can use them to improve readability, like C<SxD;K/544>.
1521
1522Samples:
1523
1524    RGB  6x6x6    24bit           color
1525    ===  =======  =============   ==================
1526    B    005      0000FF        : blue foreground
1527     /M     /505        /FF00FF : magenta background
1528    K/W  000/555  000000/FFFFFF : black on white
1529    R/G  500/050  FF0000/00FF00 : red on green
1530    W/w  L03/L20  303030/c6c6c6 : grey on grey
1531
1532Multiple colors can be specified separating by white space or comma,
1533or by repeating options.  Those colors will be applied for each
1534pattern keywords.  Next command will show word `foo' in red, `bar' in
1535green and `baz' in blue.
1536
1537    greple --colormap='R G B' 'foo bar baz'
1538
1539    greple --cm R -e foo --cm G -e bar --cm B -e baz
1540
1541=item B<--colormap>=I<field>=I<spec>,I<field>=I<spec>,...
1542
1543Another form of colormap option to specify the color for fields:
1544
1545    FILE      File name
1546    LINE      Line number
1547    BLOCKEND  Block end mark
1548
1549=item B<--colormap>=I<&func> B<--colormap>=I<sub{...}>
1550
1551You can also set the name of perl subroutine name or definition to be
1552called handling matched words.  Target word is passed as variable
1553C<$_>, and the return value of the subroutine will be displayed.
1554
1555Next command convert all words in C comment to upper case.
1556
1557    greple --all '/\*(?s:.*?)\*/' --cm 'sub{uc}'
1558
1559You can quote matched string instead of coloring (this emulates
1560deprecated option B<--quote>):
1561
1562    greple --cm 'sub{"<".$_.">"}' ...
1563
1564It is possible to use this definition with field names.  Next example
1565print line numbers in seven digits.
1566
1567    greple -n --cm 'LINE=sub{s/(\d+)/sprintf("%07d",$1)/e;$_}'
1568
1569Experimentally, function can be combined with other normal color
1570specifications.  Also the form I<&func;> can be repeated.
1571
1572    greple --cm 'BF/544;sub{uc}'
1573
1574    greple --cm 'R;&func1;&func2;&func3'
1575
1576=item B<--[no]colorful>
1577
1578Shortcut for B<--colormap>='I<RD GD BD CD MD YD>' in ANSI 16 colors
1579mode, and B<--colormap>='I<D/544 D/454 D/445 D/455 D/454 D/554>' and
1580other combination of 3, 4, 5 for 256 colors mode.  Enabled by default.
1581
1582=item B<--ansicolor>=I<16>|I<256>|I<24bit>
1583
1584If set as I<16>, use ANSI 16 colors as a default color set, otherwise
1585ANSI 256 colors.  When set as I<24bit>, 6 hex digits notation produces
158624bit color sequence.  Default is I<256>.
1587
1588=item B<--[no]256>
1589
1590Shortcut for B<--ansicolor>=I<256> or I<16>.
1591
1592=item B<--regioncolor>
1593
1594Use different colors for each B<--inside>/B<outside> regions.
1595Disabled by default.
1596
1597=item B<--uniqcolor>
1598
1599Use different colors for different string matched.
1600Disabled by default.
1601
1602Next example prints all words start by `color' and display them all in
1603different colors.
1604
1605    greple --uniqcolor 'colou?r\w*'
1606
1607=item B<--random>
1608
1609Use random selected color to display matched string each time.
1610Disabled by default.
1611
1612=item B<--face>=[-+]I<effect>
1613
1614Set or unset specified I<effect> for all color specs.  Use `+'
1615(optional) to set, and `-' to unset.  Effect is a single character
1616expressing: S (Stand-out), U (Underline), D (Double-struck), F (Flash).
1617
1618Next example remove D (double-struck) effect.
1619
1620    greple --face -D
1621
1622Multiple effects can be set/unset at once.
1623
1624    greple --face SF-D
1625
1626=back
1627
1628
1629=head2 BLOCKS
1630
1631
1632=over 7
1633
1634=item B<-p>, B<--paragraph>
1635
1636Print the paragraph which contains the pattern.  Each paragraph is
1637delimited by two or more successive newline characters by default.  Be
1638aware that an empty line is not paragraph delimiter if which contains
1639space characters.  Example:
1640
1641    greple -np 'setuid script' /usr/man/catl/perl.l
1642
1643    greple -pe '^struct sockaddr' /usr/include/sys/socket.h
1644
1645It changes the unit of context specified by B<-A>, B<-B>, B<-C>
1646options.
1647
1648=item B<--all>
1649
1650Treat entire file contents as a single block.  This is almost
1651identical to following command.
1652
1653    greple --block='(?s).*'
1654
1655=item B<--block>=I<pattern>, B<--block>=I<&sub>
1656
1657Specify the record block to display.  Default block is a single line.
1658
1659Next example behave almost same as B<--paragraph> option, but is less
1660efficient.
1661
1662    greple --block='(.+\n)+'
1663
1664Next command treat the data as a series of 10-line blocks.
1665
1666    greple -n --block='(.*\n){1,10}'
1667
1668When blocks are not continuous and there are gaps between them, the
1669match occurred outside blocks are ignored.
1670
1671If multiple block options are supplied, overlapping blocks are merged
1672into single block.
1673
1674Please be aware that this option is sometimes quite time consuming,
1675because it finds all blocks before processing.
1676
1677=item B<--blockend>=I<string>
1678
1679Change the end mark displayed after B<-pABC> or B<--block> options.
1680Default value is "--\n".
1681
1682=back
1683
1684
1685=head2 REGIONS
1686
1687
1688=over 7
1689
1690=item B<--inside>=I<pattern>
1691
1692=item B<--outside>=I<pattern>
1693
1694Option B<--inside> and B<--outside> limit the text area to be matched.
1695For simple example, if you want to find string `and' not in the word
1696`command', it can be done like this.
1697
1698    greple --outside=command and
1699
1700The block can be larger and expand to multiple lines.  Next command
1701searches from C source, excluding comment part.
1702
1703    greple --outside '(?s)/\*.*?\*/'
1704
1705Next command searches only from POD part of the perl script.
1706
1707    greple --inside='(?s)^=.*?(^=cut|\Z)'
1708
1709When multiple B<inside> and B<outside> regions are specified, those
1710regions are mixed up in union way.
1711
1712In multiple color environment, and if single keyword is specified,
1713matches in each B<--inside>/B<outside> regions are printed in
1714different colors.  Forcing this operation with multiple keywords, use
1715B<--regioncolor> option.
1716
1717=item B<--inside>=I<&function>
1718
1719=item B<--outside>=I<&function>
1720
1721If the pattern name begins by ampersand (&) character, it is treated
1722as a name of subroutine which returns a list of blocks.  Using this
1723option, user can use arbitrary function to determine from what part of
1724the text they want to search.  User defined function can be defined in
1725F<.greplerc> file or by module option.
1726
1727=item B<--include>=I<pattern>
1728
1729=item B<--exclude>=I<pattern>
1730
1731=item B<--include>=I<&function>
1732
1733=item B<--exclude>=I<&function>
1734
1735B<--include>/B<exclude> option behave exactly same as
1736B<--inside>/B<outside> when used alone.
1737
1738When used in combination, B<--include>/B<exclude> are mixed in AND
1739manner, while B<--inside>/B<outside> are in OR.
1740
1741Thus, in the next example, first line prints all matches, and second
1742does none.
1743
1744    greple --inside PATTERN --outside PATTERN
1745
1746    greple --include PATTERN --exclude PATTERN
1747
1748You can make up desired matches using B<--inside>/B<outside> option,
1749then remove unnecessary part by B<--include>/B<exclude>
1750
1751=item B<--strict>
1752
1753Limit the match area strictly.
1754
1755By default, B<--block>, B<--inside>/B<outside>,
1756B<--include>/B<exclude> option allows partial match within the
1757specified area.  For instance,
1758
1759    greple --inside and command
1760
1761matches pattern C<command> because the part of matched string is
1762included in specified inside-area.  Partial match fails when option
1763B<--strict> provided, and longer string never matches within shorter
1764area.
1765
1766Interestingly enough, above example
1767
1768    greple --include PATTERN --exclude PATTERN
1769
1770produces output, as a matter of fact.  Think of the situation
1771searching, say, C<' PATTERN '> with this condition.  Matched area
1772includes surrounding spaces, and meets the both condition partially.
1773This match does not occur when option B<--strict> is given, either.
1774
1775=back
1776
1777
1778=head2 CHARACTER CODE
1779
1780
1781=over 7
1782
1783=item B<--icode>=I<code>
1784
1785Target file is assumed to be encoded in utf8 by default.  Use this
1786option to set specific encoding.  When handling Japanese text, you may
1787choose from 7bit-jis (jis), euc-jp or shiftjis (sjis).  Multiple code
1788can be supplied using multiple option or combined code names with
1789space or comma, then file encoding is guessed from those code sets.
1790Use encoding name `guess' for automatic recognition from default code
1791list which is euc-jp and 7bit-jis.  Following commands are all
1792equivalent.
1793
1794    greple --icode=guess ...
1795    greple --icode=euc-jp,7bit-jis ...
1796    greple --icode=euc-jp --icode=7bit-jis ...
1797
1798Default code set are always included suspect code list.  If you have
1799just one code adding to suspect list, put + mark before the code name.
1800Next example does automatic code detection from euc-kr, ascii, utf8
1801and UTF-16/32.
1802
1803    greple --icode=+euc-kr ...
1804
1805If the string "B<binary>" is given as encoding name, no character
1806encoding is expeted and all files are processed as binary data.
1807
1808=item B<--ocode>=I<code>
1809
1810Specify output code.  Default is utf8.
1811
1812=back
1813
1814
1815=head2 FILTER
1816
1817
1818=over 7
1819
1820=item B<--if>=I<filter>, B<--if>=I<EXP>:I<filter>
1821
1822You can specify filter command which is applied to each files before
1823search.  If only one filter command is specified, it is applied to all
1824files.  If filter information include colon, first field will be perl
1825expression to check the filename saved in variable $_.  If it
1826successes, next filter command is pushed.
1827
1828    greple --if=rev perg
1829    greple --if='/\.tar$/:tar tvf -'
1830
1831If the command doesn't accept standard input as processing data, you
1832may be able to use special device:
1833
1834    greple --if='nm /dev/stdin' crypt /usr/lib/lib*
1835
1836Filters for compressed and gzipped file is set by default unless
1837B<--noif> option is given.  Default action is like this:
1838
1839    greple --if='s/\.Z$//:zcat --if='s/\.g?z$//:gunzip -c'
1840
1841File with I<.gpg> suffix is filtered by B<gpg> command.  In that case,
1842passphrase is asked for each file.  If you want to input passphrase
1843only once to find from multiple files, use B<-Mpgp> module.
1844
1845If the filter start with C<&>, perl subroutine is called instead of
1846external command.  You can define the subroutine in F<.greplerc> or
1847modules.  B<Greple> simply call the subroutine, so it should be
1848responsible for process control.
1849
1850=item B<--noif>
1851
1852Disable default input filter.  Which means compressed files will not
1853be decompressed automatically.
1854
1855=item B<--of>=I<filter>, B<--of>=I<&func>
1856
1857Specify output filter which process the output of B<greple> command.
1858Filter command can be specified in multiple times, and they are
1859invoked for each file to be processed.  So next command reset the line
1860number for each files.
1861
1862    greple --of 'cat -n' string file1 file2 ...
1863
1864If the filter start with C<&>, perl subroutine is called instead of
1865external command.  You can define the subroutine in F<.greplerc> or
1866modules.
1867
1868Output filter command is executed only when matched string exists to
1869avoid invoking many unnecessary processes.  No effect for option
1870B<-c>.
1871
1872=item B<--pf>=I<filter>, B<--pf>=I<&func>
1873
1874Similar to B<--of> filter but invoked just once and takes care of
1875entire output from B<greple> command.
1876
1877=back
1878
1879
1880=head2 RUNTIME FUNCTIONS
1881
1882
1883=over 7
1884
1885=item B<--print>=I<function>, B<--print>=I<sub{...}>
1886
1887Specify user defined function executed before data print.  Text to be
1888printed is replaced by the result of the function.  Arbitrary function
1889can be defined in F<.greplerc> file.  Matched data is placed in
1890variable C<$_>.  Other information is passed by key-value pair in the
1891arguments.  Filename is passed by C<file> key.  Matched information is
1892passed by C<matched> key, in the form of perl array reference:
1893C<[[start,end],[start,end]...]>.
1894
1895Simplest function is B<--print>='I<sub{$_}>'.  Coloring capability can
1896be used like this:
1897
1898    # ~/.greplerc
1899    __PERL__
1900    sub print_simple {
1901        my %attr = @_;
1902        for my $r (reverse @{$attr{matched}}) {
1903            my($s, $e) = @$r;
1904            substr($_, $s, $e - $s, color('B', substr($_, $s, $e - $s)));
1905        }
1906        $_;
1907    }
1908
1909Then, you can use this function in the command line.
1910
1911    greple --print=print_simple ...
1912
1913It is possible to use multiple B<--print> options.  In that case,
1914second function will get the result of the first function.  The
1915command will print the final result of the last function.
1916
1917=item B<--continue>
1918
1919When B<--print> option is given, B<greple> will immediately print the
1920result returned from print function and finish the cycle.  Option
1921B<--continue> forces to continue normal printing process after print
1922function called.  So please be sure that all data being consistent.
1923
1924=item B<--begin>=I<function>(I<...>), B<--begin>=I<function>=I<...>
1925
1926Option B<--begin> specify the function executed at the beginning of
1927each file processing.  This I<function> have to be called from B<main>
1928package.  So if you define the function in the module package, use the
1929full package name or export properly.
1930
1931=item B<--end>=I<function>(I<...>), B<--end>=I<function>=I<...>
1932
1933Option B<--end> is almost same as B<--begin>, except that the function
1934is called after the file processing.
1935
1936=item B<-M>I<module>::I<function(...)>, B<-M>I<module>::I<function=...>
1937
1938Function can be given with module option, following module name.  In
1939this form, the function will be called with module package name.  So
1940you don't have to export it.  Because it is called only once at the
1941beginning of command execution, before starting file processing,
1942C<FILELABEL> parameter is not given exceptionally.
1943
1944=back
1945
1946For these run-time functions, optional argument list can be set in the
1947form of C<key> or C<key=value>, connected by comma.  These arguments
1948will be passed to the function in key => value list.  Sole key will
1949have the value one.  Also processing file name is passed with the key
1950of C<FILELABEL> constant.  As a result, the option in the next form:
1951
1952    --begin function(key1,key2=val2)
1953    --begin function=key1,key2=val2
1954
1955will be transformed into following function call:
1956
1957    function(&FILELABEL => "filename", key1 => 1, key2 => "val2")
1958
1959As described earlier, C<FILELABEL> parameter is not given to the
1960function specified with module option. So
1961
1962    -Mmodule::function(key1,key2=val2)
1963    -Mmodule::function=key1,key2=val2
1964
1965simply becomes:
1966
1967    function(key1 => 1, key2 => "val2")
1968
1969The function can be defined in F<.greplerc> or modules.  Assign the
1970arguments into hash, then you can access argument list as member of
1971the hash.  It's safe to delete FILELABEL key if you expect random
1972parameter is given.  Content of the target file can be accessed by
1973C<$_>.  Ampersand (C<&>) is required to avoid the hash key is
1974interpreted as a bare word.
1975
1976    sub function {
1977	my %arg = @_;
1978	my $filename = delete $arg{&FILELABEL};
1979	$arg{key1};             # 1
1980	$arg{key2};             # "val2"
1981	$_;                     # contents
1982    }
1983
1984
1985=head2 OTHERS
1986
1987
1988=over 7
1989
1990=item B<--norc>
1991
1992Do not read startup file: F<~/.greplerc>.
1993
1994=item B<--usage>
1995
1996B<Greple> print usage and exit with option B<--usage>, or no valid
1997parameter is not specified.  In this case, module option is displayed
1998with help information if available.  If you want to see how they are
1999expanded, supply something not empty to B<--usage> option, like:
2000
2001    greple -Mmodule --usage=expand
2002
2003=item B<--man>
2004
2005Show manual page.
2006Display module's manual page when used with B<-M> option.
2007
2008=item B<--show>
2009
2010Show module file contents.  Use with B<-M> option.
2011
2012=item B<--require>=I<filename>
2013
2014Include arbitrary perl program.
2015
2016=begin comment
2017
2018=item B<-d> I<flags>
2019
2020Display informations.  Various kind of debug, diagnostic, monitor
2021information can be display by giving appropriate flag to -d option.
2022
2023    d: directory information
2024    e: eval string
2025    f: processing file name
2026    m: misc debug information
2027    o: option related information
2028    p: run `ps' command before termination (on Unix)
2029    s: statistic information
2030    u: unused options
2031    v: internal match information
2032
2033=end comment
2034
2035=item B<--conceal> I<type>=I<val>
2036
2037Conceal runtime errors.  Repeatable.  Types are:
2038
2039=over 4
2040
2041=item B<read>
2042
2043(Default 1) Errors occured during file read.  Mainly unicode related
2044errors when reading binary or umbiguous text file.
2045
2046=item B<skip>
2047
2048(Default 0) File skip warings produced when fatal error was occured
2049during file read.  Occurs when reading binary files with automatic
2050character code recognition.
2051
2052=item B<all>
2053
2054Set same value for all types.
2055
2056=back
2057
2058=item B<--persist>
2059
2060As B<greple> tries to read data as a character string, sometimes fails
2061to convert them into internal representation, and the file is skipped
2062without processing.  When option B<--persist> is specified, command
2063does not give up the file, and tries to read as binary data.
2064
2065Next command will show strings in binary file.
2066
2067    greple -o --re '(?a)\w{4,}' --persist --uc /bin/*
2068
2069When processing all files as binary data, use B<--icode=binary>
2070instead.
2071
2072=back
2073
2074
2075=head1 ENVIRONMENT and STARTUP FILE
2076
2077
2078Environment variable GREPLEOPTS is used as a default options.  They
2079are inserted before command line options.
2080
2081Before starting execution, I<greple> reads the file named F<.greplerc>
2082on user's home directory.  Following directives can be used.
2083
2084=over 7
2085
2086=item B<option> I<name> string
2087
2088Argument I<name> of `option' directive is user defined option name.
2089The rest are processed by I<shellwords> routine defined in
2090Text::ParseWords module.  Be sure that this module sometimes requires
2091escape backslashes.
2092
2093Any kind of string can be used for option name but it is not combined
2094with other options.
2095
2096    option --fromcode --outside='(?s)\/\*.*?\*\/'
2097    option --fromcomment --inside='(?s)\/\*.*?\*\/'
2098
2099If the option named B<default> is defined, it will be used as a
2100default option.
2101
2102For the purpose to include following arguments within replaced
2103strings, two special notations can be used in option definition.
2104String C<$E<lt>nE<gt>> is replaced by the I<n>th argument after the
2105substituted option, where I<n> is number start from one.  String
2106C<$E<lt>shiftE<gt>> is replaced by following command line argument and
2107the argument is removed from option list.
2108
2109For example, when
2110
2111    option --line --le &line=$<shift>
2112
2113is defined, command
2114
2115    greple --line 10,20-30,40
2116
2117will be evaluated as this:
2118
2119    greple --le &line=10,20-30,40
2120
2121=item B<expand> I<name> I<string>
2122
2123Define local option I<name>.  Command B<expand> is almost same as
2124command B<option> in terms of its function.  However, option defined
2125by this command is expanded in, and only in, the process of
2126definition, while option definition is expanded when command arguments
2127are processed.
2128
2129This is similar to string macro defined by following B<define>
2130command.  But macro expantion is done by simple string replacement, so
2131you have to use B<expand> to define option composed by multiple
2132arguments.
2133
2134=item B<define> I<name> string
2135
2136Define macro.  This is similar to B<option>, but argument is not
2137processed by I<shellwords> and treated just a simple text, so
2138meta-characters can be included without escape.  Macro expansion is
2139done for option definition and other macro definition.  Macro is not
2140evaluated in command line option.  Use option directive if you want to
2141use in command line,
2142
2143    define (#kana) \p{InKatakana}
2144    option --kanalist --nocolor -o --join --re '(#kana)+(\n(#kana)+)*'
2145    help   --kanalist List up Katakana string
2146
2147=item B<help> I<name>
2148
2149If `help' directive is used for same option name, it will be printed
2150in usage message.  If the help message is `ignore', corresponding line
2151won't show up in the usage.
2152
2153=item B<builtin> I<spec> I<variable>
2154
2155Define built-in option which should be processed by option parser.
2156Arguments are assumed to be L<Getopt::Long> style spec, and
2157I<variable> is string start with C<$>, C<@> or C<%>.  They will be
2158replaced by a reference to the object which the string represent.
2159
2160See B<pgp> module for example.
2161
2162=item B<autoload> I<module> I<options>
2163
2164Define module which should be loaded automatically when specified
2165option is found in the command arguments.
2166
2167For example,
2168
2169    autoload -Mdig --dig
2170
2171replaces option "I<--dig>" to "I<-Mdig --dig>", and I<dig> module is
2172loaded before processing I<--dig> option.
2173
2174=back
2175
2176Environment variable substitution is done for string specified by
2177`option' and `define' directives.  Use Perl syntax B<$ENV{NAME}> for
2178this purpose.  You can use this to make a portable module.
2179
2180When I<greple> found C<__PERL__> line in F<.greplerc> file, the rest
2181of the file is evaluated as a Perl program.  You can define your own
2182subroutines which can be used by B<--inside>/B<outside>,
2183B<--include>/B<exclude>, B<--block> options.
2184
2185For those subroutines, file content will be provided by global
2186variable C<$_>.  Expected response from the subroutine is the list of
2187array references, which is made up by start and end offset pairs.
2188
2189For example, suppose that the following function is defined in your
2190F<.greplerc> file.  Start and end offset for each pattern match can be
2191taken as array element C<$-[0]> and C<$+[0]>.
2192
2193    __PERL__
2194    sub odd_line {
2195        my @list;
2196        my $i;
2197        while (/.*\n/g) {
2198            push(@list, [ $-[0], $+[0] ]) if ++$i % 2;
2199        }
2200        @list;
2201    }
2202
2203You can use next command to search pattern included in odd number
2204lines.
2205
2206    % greple --inside '&odd_line' pattern files...
2207
2208
2209=head1 MODULE
2210
2211
2212Modules can be specified only at the beginning of command line by
2213B<-M>I<module> option.  Name I<module> is prepended by B<App::Greple>,
2214so place the module file in F<App/Greple/> directory in Perl library.
2215
2216If the package name is declared properly, C<__DATA__> section in the
2217module file will be interpreted same as F<.greplerc> file content.
2218
2219Using B<-M> without module argument will print available module list.
2220Option B<--man> will display module document when used with B<-M>
2221option.  Use B<--show> option to see the module itself.
2222
2223See this sample module code.  This sample define options to search
2224from pod, comment and other segment in Perl script.  Those capability
2225can be implemented both in function and macro.
2226
2227    package App::Greple::perl;
2228
2229    BEGIN {
2230        use Exporter   ();
2231        our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
2232
2233        $VERSION = sprintf "%d.%03d", q$Revision: 7.1 $ =~ /(\d+)/g;
2234
2235        @ISA         = qw(Exporter);
2236        @EXPORT      = qw(&pod &comment &podcomment);
2237        %EXPORT_TAGS = ( );
2238        @EXPORT_OK   = qw();
2239    }
2240    our @EXPORT_OK;
2241
2242    END { }
2243
2244    my $pod_re = qr{^=\w+(?s:.*?)(?:\Z|^=cut\s*\n)}m;
2245    my $comment_re = qr{^(?:[ \t]*#.*\n)+}m;
2246
2247    sub pod {
2248        my @list;
2249        while (/$pod_re/g) {
2250            push(@list, [ $-[0], $+[0] ] );
2251        }
2252        @list;
2253    }
2254    sub comment {
2255        my @list;
2256        while (/$comment_re/g) {
2257            push(@list, [ $-[0], $+[0] ] );
2258        }
2259        @list;
2260    }
2261    sub podcomment {
2262        my @list;
2263        while (/$pod_re|$comment_re/g) {
2264            push(@list, [ $-[0], $+[0] ] );
2265        }
2266        @list;
2267    }
2268
2269    1;
2270
2271    __DATA__
2272
2273    define :comment: ^(\s*#.*\n)+
2274    define :pod: ^=(?s:.*?)(?:\Z|^=cut\s*\n)
2275
2276    #option --pod --inside :pod:
2277    #option --comment --inside :comment:
2278    #option --code --outside :pod:|:comment:
2279
2280    option --pod --inside '&pod'
2281    option --comment --inside '&comment'
2282    option --code --outside '&podcomment'
2283
2284You can use the module like this:
2285
2286    greple -Mperl --pod default greple
2287
2288    greple -Mperl --colorful --code --comment --pod default greple
2289
2290If special subroutine B<initialize()> is defined in the module, it is
2291called at the beginning with C<Getopt::EX::Module> object as a
2292first argument.  Second argument is the reference to C<@ARGV>, and you
2293can modify actual C<@ARGV> using it.  See B<find> module as a sample.
2294
2295
2296=head1 HISTORY
2297
2298
2299Most capability of B<greple> is derived from B<mg> command, which has
2300been developing from early 1990's by the same author.  Because modern
2301standard B<grep> family command becomes to have similar capabilities,
2302it is a time to clean up entire functionalities, totally remodel the
2303option interfaces, and change the command name. (2013.11)
2304
2305
2306=head1 AUTHOR
2307
2308
2309Kazumasa Utashiro
2310
2311
2312=head1 SEE ALSO
2313
2314
2315L<grep(1)>, L<perl(1)>
2316
2317L<github|http://kaz-utashiro.github.io/greple/>
2318
2319L<Getopt::EX>
2320
2321=head1 LICENSE
2322
2323
2324Copyright (c) 1991-2017 Kazumasa Utashiro
2325
2326Use and redistribution for ANY PURPOSE are granted as long as all
2327copyright notices are retained.  Redistribution with modification is
2328allowed provided that you make your modified version obviously
2329distinguishable from the original one.  THIS SOFTWARE IS PROVIDED BY
2330THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES ARE
2331DISCLAIMED.
2332