App-Greple
view release on metacpan or search on metacpan
script/greple view on Meta::CPAN
my $default_icode = 'utf8'; # default input encoding
my @default_icode_list = qw(euc-jp 7bit-jis);
my $output_code;
my $default_ocode = 'utf8'; # default output encoding
$output_code = $opt_ocode || $default_ocode;
binmode STDOUT, ":encoding($output_code)";
## show unused option characters
if ($opt_d{u}) {
my $s = join('','0'..'9',"\n",'a'..'z',"\n",'A'..'Z',"\n");
map { /\|([0-9a-zA-Z])\b/ && $s =~ s/$1/./ } @optargs;
die $s;
}
## show man pages
if ($opt_man or $opt_show or $opt_path) {
my @module = map {
/^-M(\w+(::\w++(?![=(]))*)/ ? "App::Greple::$1" : ()
} @ORIG_ARGV;
if (@module) {
my $module = $module[-1];
my $jp = first { -x "$_/perldocjp" } split /:/, $ENV{PATH};
my $perldoc = $jp ? "perldocjp" : "perldoc";
$ENV{PERL5LIB} = join ':', @INC;
my $file = $module =~ s[::][/]gr . '.pm';
die unless $INC{$file};
if ($opt_man) {
exec "$perldoc $module" or die $!;
} else {
chomp(my $file = `$perldoc -ml $module`);
if ($opt_path) {
say $file;
} else {
my $pager = $ENV{PAGER} || 'less';
exec "$pager $file" or die $!;
}
}
exit;
}
pod2usage({-verbose => 2});
die;
}
sub default_module {
my $mod = shift;
my $module = $mod->module;
return 1 if $module =~ /\b \.greplerc $/x;
return 1 if $module =~ /\b default $/x;
return 0;
}
## setup file encoding
if (@opt_icode) {
@opt_icode = map { split /[,\s]+/ } @opt_icode;
if (grep { s/^\+// } @opt_icode) {
unshift @opt_icode, @default_icode_list;
}
@opt_icode = uniq @opt_icode;
if (@opt_icode > 1) {
@opt_icode = grep { !/(?:auto|guess)$/i } @opt_icode;
Encode::Guess->set_suspects(@opt_icode);
$file_code = 'Guess';
}
elsif ($opt_icode[0] =~ /^(?:guess|auto)$/i) {
Encode::Guess->set_suspects(@default_icode_list);
$file_code = 'Guess';
} else {
$file_code = $opt_icode[0];
}
}
else {
$file_code = $default_icode;
}
##
## --filter
##
if ($opt_filter) {
$opt_all = 1;
push @opt_need, '0';
$opt_exit //= 0;
}
##
## Patterns
##
my $pat_holder = App::Greple::Pattern::Holder->new;
my $FLAG_BASE = FLAG_NONE;
$FLAG_BASE |= FLAG_IGNORECASE if $opt_i;
if (@opt_f) {
for my $opt_f (@opt_f) {
$pat_holder->append({ flag => $FLAG_BASE, type => 'file',
$opt_select ? (select => $opt_select) : (),
},
$opt_f);
}
} else {
unless ($opt_filter or grep { $_->[0] !~ /^(not|may)/ } @opt_pattern) {
unshift @opt_pattern, [ le => shift @ARGV // &usage ];
}
}
my %pat_flag = (
must => FLAG_REGEX | FLAG_COOK | FLAG_REQUIRED,
not => FLAG_REGEX | FLAG_COOK | FLAG_NEGATIVE,
may => FLAG_REGEX | FLAG_COOK | FLAG_OPTIONAL,
le => FLAG_REGEX | FLAG_COOK | FLAG_LEXICAL,
and => FLAG_REGEX | FLAG_COOK,
re => FLAG_REGEX,
fe => FLAG_NONE,
);
for (@opt_pattern) {
my($attr, @opt) = @$_;
my $flag = $FLAG_BASE | $pat_flag{$attr};
$pat_holder->append({ flag => $flag, type => 'pattern' }, @opt);
}
# $pat_holder->optimize;
##
## if optional pattern exist, make all non-optional pattern as required
##
script/greple view on Meta::CPAN
C<--include>/C<--exclude> option behave exactly same as
C<--inside>/C<--outside> when used alone.
When used in combination, C<--include>/C<--exclude> are mixed in AND
manner, while C<--inside>/C<--outside> are in OR.
Thus, in the next example, first line prints all matches, and second
does none.
greple --inside PATTERN --outside PATTERN
greple --include PATTERN --exclude PATTERN
You can make up desired matches using C<--inside>/C<--outside> option,
then remove unnecessary part by C<--include>/C<--exclude>
=item B<--strict>
Limit the match area strictly.
By default, C<--block>, C<--inside>/C<outside>,
C<--include>/C<--exclude> option allows partial match within the
specified area. For instance,
greple --inside and command
matches pattern C<command> because the part of matched string is
included in specified inside-area. Partial match fails when option
C<--strict> provided, and longer string never matches within shorter
area.
Interestingly enough, above example
greple --include PATTERN --exclude PATTERN
produces output, as a matter of fact. Think of the situation
searching, say, C<' PATTERN '> with this condition. Matched area
includes surrounding spaces, and satisfies both conditions partially.
This match does not occur when option C<--strict> is given, either.
=back
B<Related options:>
B<--block> (L</BLOCKS>),
B<--regioncolor> (L</COLORS>),
B<-e>/B<-v> (L</PATTERNS>)
=head2 CHARACTER CODE
=over 7
=item B<--icode>=I<code>
Target file is assumed to be encoded in utf8 by default. Use this
option to set specific encoding. When handling Japanese text, you may
choose from 7bit-jis (jis), euc-jp or shiftjis (sjis). Multiple code
can be supplied using multiple option or combined code names with
space or comma, then file encoding is guessed from those code sets.
Use encoding name C<guess> for automatic recognition from default code
list which is euc-jp and 7bit-jis. Following commands are all
equivalent.
greple --icode=guess ...
greple --icode=euc-jp,7bit-jis ...
greple --icode=euc-jp --icode=7bit-jis ...
Default code set are always included suspect code list. If you have
just one code adding to suspect list, put + mark before the code name.
Next example does automatic code detection from euc-kr, ascii, utf8
and UTF-16/32.
greple --icode=+euc-kr ...
If the string "B<binary>" is given as encoding name, no character
encoding is expected and all files are processed as binary data.
=item B<--ocode>=I<code>
Specify output code. Default is utf8.
=back
=head2 FILTER
=over 7
=item B<--if>=I<filter>, B<--if>=I<EXP>:I<filter>
You can specify filter command which is applied to each file before
search. If only one filter command is specified, it is applied to all
files. If filter information include colon, first field will be perl
expression to check the filename saved in variable $_. If it
successes, next filter command is pushed.
greple --if=rev perg
greple --if='/\.tar$/:tar tvf -'
If the command doesn't accept standard input as processing data, you
may be able to use special device:
greple --if='nm /dev/stdin' crypt /usr/lib/lib*
Filters for compressed and gzipped file is set by default unless
C<--noif> option is given. Default action is like this:
greple --if='s/\.Z$//:zcat' --if='s/\.g?z$//:gunzip -c'
File with C<.gpg> suffix is filtered by B<gpg> command. In that case,
pass-phrase is asked for each file. If you want to input pass-phrase
only once to find from multiple files, use C<-Mpgp> module.
If the filter starts with C<&>, perl subroutine is called instead of
external command. You can define the subroutine in F<.greplerc> or
modules. B<Greple> simply call the subroutine, so it should be
responsible for process control. It may have to use C<POSIX::_exit()>
to avoid executing an C<END> block on exit or calling destructor on
the object.
=item B<--noif>
Disable default input filter. Which means compressed files will not
( run in 1.142 second using v1.01-cache-2.11-cpan-39bf76dae61 )