use strict;
use warnings;
-our $VERSION = 'v3.8.1'; # Check https://beyondgrep.com/ for updates
+our $VERSION = 'v3.9.0'; # Check https://beyondgrep.com/ for updates
use 5.010001;
sub file_loop_c {
my $files = shift;
+ my $nmatched_files = 0;
+
my $total_count = 0;
while ( defined( my $file = $files->next ) ) {
my $matches_for_this_file = count_matches_in_file( $file );
+ if ( $matches_for_this_file ) {
+ ++$nmatched_files;
+ }
if ( not $opt_show_filename ) {
$total_count += $matches_for_this_file;
App::Ack::say( $total_count );
}
- return;
+ return $nmatched_files;
}
return sub {
if ( $opt_g ) {
- if ( $File::Next::name =~ /$re_match/o ) {
+ my $match = ($File::Next::name =~ /$re_match/o);
+ if ( $match && $re_not ) {
+ $match = ($File::Next::name !~ /$re_not/o);
+ }
+
+ if ( $match ) {
return 0 if $opt_v;
}
else {
my @line_parts;
if ( $opt_show_filename && defined($filename) ) {
- my $colno;
- $colno = get_match_colno() if $opt_column;
+ my $disp_filename;
+ my $disp_lineno;
if ( $opt_color ) {
- $filename = Term::ANSIColor::colored( $filename, $ENV{ACK_COLOR_FILENAME} );
- $lineno = Term::ANSIColor::colored( $lineno, $ENV{ACK_COLOR_LINENO} );
- $colno = Term::ANSIColor::colored( $colno, $ENV{ACK_COLOR_COLNO} ) if $opt_column;
+ $disp_filename = Term::ANSIColor::colored( $filename, $ENV{ACK_COLOR_FILENAME} );
+ $disp_lineno = Term::ANSIColor::colored( $lineno, $ENV{ACK_COLOR_LINENO} );
+ }
+ else {
+ $disp_filename = $filename;
+ $disp_lineno = $lineno;
}
+
if ( $opt_heading ) {
- push @line_parts, $lineno;
+ push @line_parts, $disp_lineno;
}
else {
- push @line_parts, $filename, $lineno;
+ push @line_parts, $disp_filename, $disp_lineno;
+ }
+
+ if ( $opt_column ) {
+ my $colno = get_match_colno();
+ $colno = Term::ANSIColor::colored( $colno, $ENV{ACK_COLOR_COLNO} ) if $opt_color;
+ push @line_parts, $colno;
}
- push @line_parts, $colno if $opt_column;
}
if ( $opt_output ) {
then the search for both "dogs" and "cats" will be case-insensitive and be
word-limited.
-See also the other two boolean options C<--or> and C<--not>, neither of
-which can be used with C<--and>.
+C<--and> cannot be used with C<--or>.
=item B<-A I<NUM>>, B<--after-context=I<NUM>>
then the search for both "dogs" and "cats" will be case-insensitive and be
word-limited.
-See also the other two boolean options C<--and> and C<--or>, neither of
-which can be used with C<--not>.
-
=item B<-o>
Show only the part of each line matching PATTERN (turns off text
then the search for both "dogs" and "cats" will be case-insensitive and be
word-limited.
-See also the other two boolean options C<--and> and C<--not>, neither of
-which can be used with C<--or>.
+C<--or> cannot be used with C<--and>.
=item B<--output=I<expr>>
=head1 COPYRIGHT & LICENSE
-Copyright 2005-2024 Andy Lester.
+Copyright 2005-2025 Andy Lester.
This program is free software; you can redistribute it and/or modify
it under the terms of the Artistic License v2.0.
our $VERSION;
our $COPYRIGHT;
BEGIN {
- $VERSION = 'v3.8.1'; # Check https://beyondgrep.com/ for updates
- $COPYRIGHT = 'Copyright 2005-2024 Andy Lester.';
+ $VERSION = 'v3.9.0'; # Check https://beyondgrep.com/ for updates
+ $COPYRIGHT = 'Copyright 2005-2025 Andy Lester.';
}
our $STANDALONE = 0;
our $ORIGINAL_PROGRAM_NAME;
my @parts;
- # AND: alpha and beta
+ # AND: alpha AND beta
if ( @parts = @{$opt->{and}} ) {
my @match_parts;
my @hilite_parts;
$re_hilite = $re_match;
$re_scan = join( '|', @scan_parts );
}
- # NOT: alpha NOT beta
- elsif ( @parts = @{$opt->{not}} ) {
+ else {
($re_match, $re_scan) = build_regex( $opt_regex, $opt );
$re_hilite = $re_match;
+ }
+ # The --not does not affect the main regex. It is checked separately.
+ # NOT: alpha NOT beta
+ if ( @parts = @{$opt->{not}} ) {
my @not_parts;
for my $part ( @parts ) {
(my $re, undef) = build_regex( $part, $opt );
}
$re_not = join( '|', @not_parts );
}
- # No booleans.
- else {
- ($re_match, $re_scan) = build_regex( $opt_regex, $opt );
- $re_hilite = $re_match;
- }
return ($re_match, $re_not, $re_hilite, $re_scan);
}
'with-filename' => 1,
},
and => {
- g => 1,
- not => 1,
or => 1,
},
break => {
C => 1,
H => 1,
L => 1,
- and => 1,
break => 1,
c => 1,
column => 1,
l => 1,
m => 1,
match => 1,
- not => 1,
o => 1,
- or => 1,
output => 1,
p => 1,
passthru => 1,
L => 1,
l => 1,
},
- not => {
- and => 1,
- g => 1,
- },
o => {
A => 1,
B => 1,
},
or => {
and => 1,
- g => 1,
},
output => {
A => 1,