App-Greple
view release on metacpan or search on metacpan
script/greple view on Meta::CPAN
use App::Greple::Filter;
my $version = $App::Greple::VERSION;
=encoding utf8
=head1 NAME
greple - extensible grep with lexical expression and region control
=head1 VERSION
Version 10.04
=head1 SYNOPSIS
B<greple> [B<-M>I<module>] [ B<-options> ] pattern [ file... ]
PATTERN
pattern 'and +must -not ?optional &function'
-x, --le pattern lexical expression (same as bare pattern)
-e, --and pattern pattern match across line boundary
-r, --must pattern pattern cannot be compromised
-t, --may pattern pattern may exist
-v, --not pattern pattern not to be matched
-E, --re pattern regular expression
--fe pattern fixed expression
-f, --file file file contains search pattern
--select index select indexed pattern from -f file
MATCH
-i, --ignore-case ignore case
-G, --capture-group match capture groups rather than the whole pattern
-S, --stretch stretch the matched area to the enclosing block
--need=[+-]n required positive match count
--allow=[+-]n acceptable negative match count
--matchcount=n[,m] required match count for each block
STYLE
-l list filename only
-c print count of matched block only
-n print line number
-b print block number
-H, -h do or do not display filenames
-o print only the matching part
--all print entire data
-F, --filter use as a filter (implies --all --need=0 --exit=0)
-m, --max=n[,m] max count of blocks to be shown
-A,-B,-C [n] after/before/both match context
--join remove newline in the matched part
--joinby=string replace newline in the matched text with a string
--nonewline do not add newline character at the end of block
--filestyle=style how filenames are printed (once, separate, line)
--linestyle=style how line numbers are printed (separate, line)
--blockstyle=style how block numbers are printed (separate, line)
--separate set filestyle, linestyle, blockstyle "separate"
--format LABEL=... define the format for line number and file name
--frame-top top frame line
--frame-middle middle frame line
--frame-bottom bottom frame line
FILE
--glob=glob glob target files
--chdir=dir change directory before search
--readlist get filenames from stdin
COLOR
--color=when use terminal colors (auto, always, never)
--nocolor same as --color=never
--colormap=color R, G, B, C, M, Y, etc.
--colorsub=... shortcut for --colormap="sub{...}"
--colorful use default multiple colors
--colorindex=flags color index method: Ascend/Descend/Block/Random/Unique/Group/GP
--random use a random color each time (--colorindex=R)
--uniqcolor use a different color for each unique string (--colorindex=U)
--uniqsub=func preprocess function to check uniqueness
--ansicolor=s ANSI color 16, 256 or 24bit
--[no]256 same as --ansicolor 256 or 16
--regioncolor use different color for inside and outside regions
--face enable or disable visual effects
BLOCK
-p, --paragraph enable paragraph mode
--border=pattern specify a border pattern
--block=pattern specify a block of records
--blockend=s block-end mark (Default: "--")
--join-blocks join consecutive blocks that are back-to-back
REGION
--inside=pattern select matches inside of pattern
--outside=pattern select matches outside of pattern
--include=pattern limit matches to the area
--exclude=pattern limit matches to outside of the area
--strict enable strict mode for --inside/outside --block
CHARACTER CODE
--icode=name input file encoding
--ocode=name output file encoding
FILTER
--if,--of=filter input/output filter command
--pf=filter post-process filter command
--noif disable the default input filter
RUNTIME FUNCTION
--begin=func call a function before starting the search
--end=func call a function after completing the search
--prologue=func call a function before executing the command
--epilogue=func call a function after executing the command
--postgrep=func call a function after each grep operation
--callback=func callback function for each matched string
OTHER
--usage[=expand] show this help message
--version show version
--exit=n set the command exit status
--norc skip reading startup file
--man display the manual page for the command or module
--show display the module file contents
--path display the path to the module file
--error=action action to take after a read error occurs
--warn=type runtime error handling type
--alert [name=#] set alert parameters (size/time)
-d flags display info (f:file d:dir c:color m:misc s:stat)
=cut
my @baseclass = qw( App::Greple Getopt::EX );
script/greple view on Meta::CPAN
my @opt_colormap;
sub opt_colormap { push @opt_colormap, $_[1] }
sub opt_colorsub { push @opt_colormap, "sub{ $_[1] }" }
my %opt_format = (LINE => '%d:', FILE => '%s:', BLOCK => '%s:');
my %opt_alert = (size => 512 * 1024, time => 2);
my %opt_warn = (read => 0, skip => 1, retry => 0, begin => 0);
newopt
##
## PATTERN
##
' and |e =s ' => \&opt_pattern ,
' must |r =s ' => \&opt_pattern ,
' may |t =s ' => \&opt_pattern ,
' not |v =s ' => \&opt_pattern ,
' le |x =s ' => \&opt_pattern ,
' re |E =s ' => \&opt_pattern ,
' fe =s ' => \&opt_pattern ,
' file |f =s ' => \ my @opt_f ,
' select =s ' => \ my $opt_select ,
##
## MATCH
##
' ignore-case |i ! ' => \ my $opt_i ,
' need =s ' => \ my @opt_need ,
' allow =s ' => \ my @opt_allow ,
' matchcount |mc =s ' => \ my $opt_matchcount ,
' capture-group |G ! ' => \ my $opt_capture_group ,
' stretch |S ! ' => \ my $opt_stretch ,
##
## STYLE
##
' files-with-matches |l ' => \ my $opt_l ,
' count |c ' => \ my $opt_c ,
' line-number |n ! ' => \ my $opt_n ,
' block-number |b ! ' => \ my $opt_b ,
' filename |H ' => \ my $opt_H ,
' no-filename |h ' => \ my $opt_h ,
' only-matching |o ! ' => \ my $opt_o ,
' all ! ' => \ my $opt_all ,
' filter |F ! ' => \ my $opt_filter ,
' max-count |m =s ' => \ my $opt_m ,
' after-context |A :2 ' => \(my $opt_A = 0) ,
' before-context |B :2 ' => \(my $opt_B = 0) ,
' context |C :2 ' => \(my $opt_C = 0) ,
' join ! ' => \ my $opt_join ,
' joinby =s ' => \(my $opt_joinby = "") ,
' newline ! ' => \(my $opt_newline = 1) ,
' filestyle |fs =s ' => \(my $opt_filestyle = 'line') ,
' linestyle |ls =s ' => \(my $opt_linestyle = 'line') ,
' blockstyle |bs =s ' => \(my $opt_blockstyle = 'line') ,
' separate ' => sub {
opt('filestyle') = opt('linestyle') = opt('blockstyle') = $_[0];
},
' format =s ' => \ %opt_format ,
' frame-top :s ' => \(my $opt_frame_top = '') ,
' frame-middle :s ' => \(my $opt_frame_middle = '') ,
' frame-bottom :s ' => \(my $opt_frame_bottom = '') ,
##
## FILE
##
' glob =s ' => \ my @opt_glob ,
' chdir =s ' => \ my @opt_chdir ,
' readlist ! ' => \ my $opt_readlist ,
##
## COLOR
##
' color =s ' => \(my $opt_color = 'auto') ,
' colormap |cm =s ' => \&opt_colormap ,
' colorsub |cs =s ' => \&opt_colorsub ,
' colorful ! ' => \(my $opt_colorful = 1) ,
' colorindex |ci =s ' => \(my $opt_colorindex = '') ,
' ansicolor =s ' => \(my $opt_ansicolor = '256') ,
' regioncolor |rc ! ' => \ my $opt_regioncolor ,
' uniqsub |us =s ' => \ my @opt_uniqsub ,
' face =s ' => \ my @opt_face ,
' nocolor | no-color ' => sub {
opt('color') = 'never';
},
' 256! ' => sub {
opt('ansicolor') = $_[1] ? '256' : '16';
},
' random! ' => sub {
if ($_[1]) { opt('colorindex') .= 'R' }
else { opt('colorindex') =~ s/R//gi }
},
' uniqcolor |uc ' => sub {
opt('colorindex') = 'U';
},
##
## BLOCK
##
' paragraph |p ! ' => \ my $opt_p ,
' border =s ' => \ my $opt_border ,
' block =s ' => \ my @opt_block ,
' blockend :s ' => \(my $opt_blockend) ,
' join-blocks ! ' => \(my $opt_join_blocks = 0) ,
##
## REGION
##
' inside =s ' => \ my @opt_inside ,
' outside =s ' => \ my @opt_outside ,
' include =s ' => \ my @opt_include ,
' exclude =s ' => \ my @opt_exclude ,
' strict ! ' => \(my $opt_strict = 0) ,
##
## CHARACTER CODE
##
' icode =s ' => \ my @opt_icode ,
' ocode =s ' => \ my $opt_ocode ,
##
## FILTER
script/greple view on Meta::CPAN
: qw(000D/544 000D/454 000D/445
000D/455 000D/545 000D/554
000D/543 000D/453 000D/435
000D/534 000D/354 000D/345
000D/444
000D/433 000D/343 000D/334
000D/344 000D/434 000D/443
000D/333)
;
if ($color_handler->list == 0) {
$color_handler->append
($opt_colorful ? @default_color : $default_color[0]);
}
if ($opt_ansicolor eq '24bit') {
no warnings 'once';
$Getopt::EX::Colormap::RGB24 = 1;
}
for my $opt (@opt_face) {
while ($opt =~ /(?<mk>[-+=]) (?<s>[^-+=]*) | (?<s>[^-+=]+) /xg) {
my($mk, $s) = ($+{mk} // '', $+{s});
for my $c (@colors) {
if ($mk eq '-') {
$c =~ s/[\Q$s\E]//g if $s ne '';
} elsif ($mk eq '=') {
$c = $s;
} elsif ($s ne '') {
$c .= "^" if $c ne '';
$c .= $s;
}
}
}
}
my $need_color = (($opt_color eq 'always')
or (($opt_color eq 'auto') and (!$opt_o and -t STDOUT)));
if (!$need_color) {
$Getopt::EX::Colormap::NO_COLOR = 1;
}
my %_esc = ( t => "\t", n => "\n", r => "\r", f => "\f" );
sub expand_escape {
$_[0] =~ s{\\(.)}{$_esc{$1} // $1}egr;
}
$_ = expand_escape($_) for values %opt_format;
my $blockend = "--";
if (defined $opt_blockend) {
$blockend = expand_escape($opt_blockend);
}
my $_file = sub { $color_handler->color('FILE' , sprintf($opt_format{FILE}, $_[0])) };
my $_line = sub { $color_handler->color('LINE' , sprintf($opt_format{LINE}, $_[0])) };
my $_block = sub { $color_handler->color('BLOCK', sprintf($opt_format{BLOCK}, $_[0])) };
my $_text = sub { $color_handler->color('TEXT' , $_[0]) };
my $_blockend = $color_handler->color('BLOCKEND', $blockend);
my $_top = $color_handler->color('TOP' , $opt_frame_top);
my $_middle = $color_handler->color('MIDDLE' , $opt_frame_middle);
my $_bottom = $color_handler->color('BOTTOM' , $opt_frame_bottom);
sub index_color {
$color_handler->index_color(@_);
}
sub color {
$color_handler->color(@_);
}
my $uniq_color = UniqIndex->new(
ignore_newline => 1,
prepare => \@opt_uniqsub,
);
sub dump_uniqcolor {
my $list = $uniq_color->list;
my $count = $uniq_color->count;
for my $i (keys @$list) {
warn sprintf("%3d (%3d) %s\n",
$i, $count->[$i],
index_color($i, $list->[$i]));
}
}
# --colorindex
my %color_index = map { uc $_ => 1 } $opt_colorindex =~ /\w/g;
my $indexer = do {
if ($color_index{S}) {
@colors = shuffle @colors;
}
if ($color_index{A} or $color_index{D}) {
my $i = 0;
Indexer->new(
index => sub { $i++ },
reset => sub { $i = 0 },
block => $color_index{B},
reverse => $color_index{D},
);
}
elsif ($color_index{R}) {
Indexer->new(index => sub { int rand @colors });
}
else { undef }
};
my $opt_uniqcolor = $color_index{U};
# -dc
if ($opt_d{c}) {
my $dump = sub {
local $_ = Dumper shift;
s/^\s*'\K([^'\s]+)(?=')/color($1, $1)/mge;
$_;
};
warn 'colormap = ', $dump->(\%colormap);
warn 'colors = ', $dump->(\@colors);
}
##
## border regex
##
script/greple view on Meta::CPAN
greple -ho --join '\p{InKatakana}+(\n\p{InKatakana}+)*'
Space separated word sequence can be processed with C<--joinby>
option. Next example prints all C<for *something*> pattern in pod
documents within Perl script.
greple -Mperl --pod -ioe '\bfor \w+' --joinby ' '
=item B<--[no]newline>
Since B<greple> can handle arbitrary blocks other than normal text
lines, they sometimes do not end with newline character. Option C<-o>
makes similar situation. In that case, extra newline is appended at
the end of block to be shown. Option C<--no-newline> disables this
behavior.
=item B<--filestyle>=[C<line>,C<once>,C<separate>], B<--fs>
Default style is I<line>, and B<greple> prints filename at the
beginning of each line. Style I<once> prints the filename only once
at the first time. Style I<separate> prints filename in the separate
line before each line or block.
=item B<--linestyle>=[C<line>,C<separate>], B<--ls>
Default style is I<line>, and B<greple> prints line numbers at the
beginning of each line. Style I<separate> prints line number in the
separate line before each line or block.
=item B<--blockstyle>=[C<line>,C<separate>], B<--bs>
Default style is I<line>, and B<greple> prints block numbers at the
beginning of each line. Style I<separate> prints block number in the
separate line before each line or block.
=item B<--separate>
Shortcut for C<--filestyle=separate> C<--linestyle=separate>
C<--blockstyle=separate>. This is convenient to use block mode search
and visiting each location from supporting tool, such as Emacs.
=item B<--format> B<LABEL>=I<format>
Define the format string of line number (LINE), file name (FILE) and
block number (BLOCK) to be displayed. Default is:
--format LINE='%d:'
--format FILE='%s:'
--format BLOCK='%s:'
Format string is passed to C<sprintf> function. Escape sequences
C<\t>, C<\n>, C<\r>, and C<\f> are recognized.
Next example will show line numbers in five digits with tab space:
--format LINE='%05d\t'
=item B<--frame-top>=I<string>
=item B<--frame-middle>=I<string>
=item B<--frame-bottom>=I<string>
Print surrounding frames before and after each block. C<top> frame is
printed at the beginning, C<bottom> frame at the end, C<middle> frame
between blocks.
=back
B<Related options:>
B<--block>/B<-p> (L</BLOCKS>),
B<--color>/B<--colormap> (L</COLORS>)
=head2 FILES
=over 7
=item B<--glob>=I<pattern>
Get files matches to specified pattern and use them as a target files.
Using C<--chdir> and C<--glob> makes easy to use B<greple> for fixed
common job.
=item B<--chdir>=I<directory>
Change directory before processing files. When multiple directories
are specified in C<--chdir> option, by using wildcard form or
repeating option, C<--glob> file expansion will be done for every
directories.
greple --chdir '/usr/share/man/man?' --glob '*.[0-9]' ...
=item B<--readlist>
Get filenames from standard input. Read standard input and use each
line as a filename for searching. You can feed the output from other
command like L<find(1)> for B<greple> with this option. Next example
searches string from files modified within 7 days:
find . -mtime -7 -print | greple --readlist pattern
Using B<find> module, this can be done like:
greple -Mfind . -mtime -7 -- pattern
=back
=head2 COLORS
=over 7
=item B<--color>=[C<auto>,C<always>,C<never>], B<--nocolor>
Use terminal color capability to emphasize the matched text. Default
is C<auto>: effective when STDOUT is a terminal and option C<-o> is
not given, not otherwise. Option value C<always> and C<never> will
work as expected.
Option B<--nocolor> is alias for B<--color>=I<never>.
When color output is disabled, ANSI terminal sequence is not produced,
( run in 0.677 second using v1.01-cache-2.11-cpan-e1769b4cff6 )