Add bin/colordump
[dotfiles.git] / bin / ack
diff --git a/bin/ack b/bin/ack
index 7cc459cdd69e9613aefbcd39f0dcdb996008b139..bf687091e35387dd5ac1ca4222bc113c434503c4 100755 (executable)
--- a/bin/ack
+++ b/bin/ack
@@ -12,7 +12,7 @@
 use warnings;
 use strict;
 
-our $VERSION = '1.92';
+our $VERSION = '1.96';
 # Check http://betterthangrep.com/ for updates
 
 # These are all our globals.
@@ -32,13 +32,17 @@ MAIN: {
         /^--th[pt]+t+$/ && App::Ack::_thpppt($_);
 
         # See if we want to ignore the environment. (Don't tell Al Gore.)
-        if ( $_ eq '--noenv' ) {
-            my @keys = ( 'ACKRC', grep { /^ACK_/ } keys %ENV );
-            delete @ENV{@keys};
-            $env_is_usable = 0;
+        if ( /^--(no)?env$/ ) {
+            $env_is_usable = defined $1 ? 0 : 1;
         }
     }
-    unshift( @ARGV, App::Ack::read_ackrc() ) if $env_is_usable;
+    if ( $env_is_usable ) {
+        unshift( @ARGV, App::Ack::read_ackrc() );
+    }
+    else {
+        my @keys = ( 'ACKRC', grep { /^ACK_/ } keys %ENV );
+        delete @ENV{@keys};
+    }
     App::Ack::load_colors();
 
     if ( exists $ENV{ACK_SWITCHES} ) {
@@ -69,15 +73,25 @@ sub main {
             my $s = $nargs == 1 ? '' : 's';
             App::Ack::warn( "Ignoring $nargs argument$s on the command-line while acting as a filter." );
         }
+
         my $res = App::Ack::Resource::Basic->new( '-' );
-        App::Ack::search_resource( $res, $opt );
+        my $nmatches;
+        if ( $opt->{count} ) {
+            $nmatches = App::Ack::search_and_list( $res, $opt );
+        }
+        else {
+            # normal searching
+            $nmatches = App::Ack::search_resource( $res, $opt );
+        }
         $res->close();
-        exit 0;
+        App::Ack::exit_from_ack( $nmatches );
     }
 
     my $file_matching = $opt->{f} || $opt->{lines};
-    if ( !$file_matching ) {
-        @ARGV or App::Ack::die( 'No regular expression found.' );
+    if ( $file_matching ) {
+        App::Ack::die( "Can't specify both a regex ($opt->{regex}) and use one of --line, -f or -g." ) if $opt->{regex};
+    }
+    else {
         $opt->{regex} = App::Ack::build_regex( defined $opt->{regex} ? $opt->{regex} : shift @ARGV, $opt );
     }
 
@@ -101,7 +115,7 @@ sub main {
         $nmatches = App::Ack::print_matches( $iter, $opt );
     }
     close $App::Ack::fh;
-    exit ($nmatches ? 0 : 1);
+    App::Ack::exit_from_ack( $nmatches );
 }
 
 =head1 NAME
@@ -204,6 +218,8 @@ each input file.  If B<-l> is in effect, it will only show the
 number of lines for each file that has lines matching.  Without
 B<-l>, some line counts may be zeroes.
 
+If combined with B<-h> (B<--no-filename>) ack outputs only one total count.
+
 =item B<--color>, B<--nocolor>
 
 B<--color> highlights the matching text.  B<--nocolor> supresses
@@ -221,6 +237,10 @@ Sets the color to be used for filenames.
 
 Sets the color to be used for matches.
 
+=item B<--color-lineno=I<color>>
+
+Sets the color to be used for line numbers.
+
 =item B<--column>
 
 Show the column number of the first match.  This is helpful for editors
@@ -294,7 +314,7 @@ Ignore case in the search strings.
 This applies only to the PATTERN, not to the regexes given for the B<-g>
 and B<-G> options.
 
-=item B<--[no]ignore-dir=DIRNAME>
+=item B<--[no]ignore-dir=I<DIRNAME>>
 
 Ignore directory (as CVS, .svn, etc are ignored). May be used multiple times
 to ignore multiple directories. For example, mason users may wish to include
@@ -302,6 +322,11 @@ B<--ignore-dir=data>. The B<--noignore-dir> option allows users to search
 directories which would normally be ignored (perhaps to research the contents
 of F<.svn/props> directories).
 
+The I<DIRNAME> must always be a simple directory name. Nested directories like
+F<foo/bar> are NOT supported. You would need to specify B<--ignore-dir=foo> and
+then no files from any foo directory are taken into account by ack unless given
+explicitly on the command line.
+
 =item B<--line=I<NUM>>
 
 Only print line I<NUM> of each file. Multiple lines can be given with multiple
@@ -336,7 +361,7 @@ Stop reading a file after I<NUM> matches.
 
 Print this manual page.
 
-=item B<-n>
+=item B<-n>, B<--no-recurse>
 
 No descending into subdirectories.
 
@@ -383,6 +408,11 @@ Quote all metacharacters in PATTERN, it is treated as a literal.
 This applies only to the PATTERN, not to the regexes given for the B<-g>
 and B<-G> options.
 
+=item B<-r>, B<-R>, B<--recurse>
+
+Recurse into sub-directories. This is the default and just here for
+compatibility with grep. You can also use it for turning B<--no-recurse> off.
+
 =item B<--smart-case>, B<--no-smart-case>
 
 Ignore case in the search strings if PATTERN contains no uppercase
@@ -399,6 +429,12 @@ B<-g> and B<-G> options.
 Sorts the found files lexically.  Use this if you want your file
 listings to be deterministic between runs of I<ack>.
 
+=item B<--show-types>
+
+Outputs the filetypes that ack associates with each file.
+
+Works with B<-f> and B<-g> options.
+
 =item B<--thpppt>
 
 Display the all-important Bill The Cat logo.  Note that the exact
@@ -597,6 +633,15 @@ This option can also be set with B<--color-match>.
 
 See B<ACK_COLOR_FILENAME> for the color specifications.
 
+=item ACK_COLOR_LINENO
+
+Specifies the color of the line number when printed in B<--color>
+mode.  By default, it's "bold yellow".
+
+This option can also be set with B<--color-lineno>.
+
+See B<ACK_COLOR_FILENAME> for the color specifications.
+
 =item ACK_PAGER
 
 Specifies a pager program, such as C<more>, C<less> or C<most>, to which
@@ -731,10 +776,12 @@ them here.
 
 =head2 Why isn't ack finding a match in (some file)?
 
-Probably because it's of a type that ack doesn't recognize.
+Probably because it's of a type that ack doesn't recognize.  ack's
+searching behavior is driven by filetype.  B<If ack doesn't know
+what kind of file it is, ack ignores the file.>
 
-ack's searching behavior is driven by filetype.  If ack doesn't
-know what kind of file it is, ack ignores it.
+Use the C<-f> switch to see a list of files that ack will search
+for you.
 
 If you want ack to search files that it doesn't recognize, use the
 C<-a> switch.
@@ -762,7 +809,7 @@ switches.
 
 You can certainly use ack to select your files to update.  For
 example, to change all "foo" to "bar" in all PHP files, you can do
-this form the Unix shell:
+this from the Unix shell:
 
     $ perl -i -p -e's/foo/bar/g' $(ack -f --php)
 
@@ -781,9 +828,26 @@ The name of the program is "ack".  Some packagers have called it
 "ack-grep" when creating packages because there's already a package
 out there called "ack" that has nothing to do with this ack.
 
-I suggest you rename your ack-grep install to "ack" because one of
-the crucial benefits of ack is having a name that's so short and
-simple to type.
+I suggest you make a symlink named F<ack> that points to F<ack-grep>
+because one of the crucial benefits of ack is having a name that's
+so short and simple to type.
+
+To do that, run this with F<sudo> or as root:
+
+   ln -s /usr/bin/ack-grep /usr/bin/ack
+
+=head2 What does F<ack> mean?
+
+Nothing.  I wanted a name that was easy to type and that you could
+pronounce as a single syllable.
+
+=head2 Can I do multi-line regexes?
+
+No, ack does not support regexes that match multiple lines.  Doing
+so would require reading in the entire file at a time.
+
+If you want to see lines near your match, use the C<--A>, C<--B>
+and C<--C> switches for displaying context.
 
 =head1 AUTHOR
 
@@ -844,6 +908,12 @@ L<http://github.com/petdance/ack>
 How appropriate to have I<ack>nowledgements!
 
 Thanks to everyone who has contributed to ack in any way, including
+Matthew Wild,
+Scott Kyle,
+Nick Hooey,
+Bo Borgerson,
+Mark Szymanski,
+Marq Schneider,
 Packy Anderson,
 JR Boyens,
 Dan Sully,
@@ -905,20 +975,10 @@ and Pete Krawczyk.
 
 =head1 COPYRIGHT & LICENSE
 
-Copyright 2005-2009 Andy Lester.
+Copyright 2005-2011 Andy Lester.
 
 This program is free software; you can redistribute it and/or modify
-it under the terms of either:
-
-=over 4
-
-=item * the GNU General Public License as published by the Free
-Software Foundation; either version 1, or (at your option) any later
-version, or
-
-=item * the Artistic License version 2.0.
-
-=back
+it under the terms of the Artistic License v2.0.
 
 =cut
 package File::Next;
@@ -1101,8 +1161,8 @@ use strict;
 our $VERSION;
 our $COPYRIGHT;
 BEGIN {
-    $VERSION = '1.92';
-    $COPYRIGHT = 'Copyright 2005-2009 Andy Lester.';
+    $VERSION = '1.96';
+    $COPYRIGHT = 'Copyright 2005-2011 Andy Lester.';
 }
 
 our $fh;
@@ -1140,6 +1200,7 @@ BEGIN {
         '.hg'               => 'Mercurial',
         '.pc'               => 'quilt',
         '.svn'              => 'Subversion',
+        _MTN                => 'Monotone',
         blib                => 'Perl module building',
         CVS                 => 'CVS',
         RCS                 => 'RCS',
@@ -1159,12 +1220,16 @@ BEGIN {
         binary      => q{Binary files, as defined by Perl's -B op (default: off)},
         cc          => [qw( c h xs )],
         cfmx        => [qw( cfc cfm cfml )],
+        clojure     => [qw( clj )],
         cpp         => [qw( cpp cc cxx m hpp hh h hxx )],
         csharp      => [qw( cs )],
         css         => [qw( css )],
+        delphi      => [qw( pas int dfm nfm dof dpk dproj groupproj bdsgroup bdsproj )],
         elisp       => [qw( el )],
         erlang      => [qw( erl hrl )],
         fortran     => [qw( f f77 f90 f95 f03 for ftn fpp )],
+        go          => [qw( go )],
+        groovy      => [qw( groovy gtmpl gpp grunit )],
         haskell     => [qw( hs lhs )],
         hh          => [qw( h )],
         html        => [qw( htm html shtml xhtml )],
@@ -1173,18 +1238,18 @@ BEGIN {
         jsp         => [qw( jsp jspx jhtm jhtml )],
         lisp        => [qw( lisp lsp )],
         lua         => [qw( lua )],
-        make        => q{Makefiles},
+        make        => q{Makefiles (including *.mk and *.mak)},
         mason       => [qw( mas mhtml mpl mtxt )],
         objc        => [qw( m h )],
         objcpp      => [qw( mm h )],
         ocaml       => [qw( ml mli )],
         parrot      => [qw( pir pasm pmc ops pod pg tg )],
-        perl        => [qw( pl pm pod t )],
+        perl        => [qw( pl pm pm6 pod t )],
         php         => [qw( php phpt php3 php4 php5 phtml)],
         plone       => [qw( pt cpt metadata cpy py )],
         python      => [qw( py )],
         rake        => q{Rakefiles},
-        ruby        => [qw( rb rhtml rjs rxml erb rake )],
+        ruby        => [qw( rb rhtml rjs rxml erb rake spec )],
         scala       => [qw( scala )],
         scheme      => [qw( scm ss )],
         shell       => [qw( sh bash csh tcsh ksh zsh )],
@@ -1196,9 +1261,11 @@ BEGIN {
         text        => q{Text files, as defined by Perl's -T op (default: off)},
         tt          => [qw( tt tt2 ttml )],
         vb          => [qw( bas cls frm ctl vb resx )],
+        verilog     => [qw( v vh sv )],
+        vhdl        => [qw( vhd vhdl )],
         vim         => [qw( vim )],
         yaml        => [qw( yaml yml )],
-        xml         => [qw( xml dtd xslt ent )],
+        xml         => [qw( xml dtd xsl xslt ent )],
     );
 
     while ( my ($type,$exts) = each %mappings ) {
@@ -1208,6 +1275,8 @@ BEGIN {
             }
         }
     }
+    # add manually Makefile extensions
+    push @{$types{$_}}, 'make' for qw{ mk mak };
 
     # These have to be checked before any filehandle diddling.
     $output_to_pipe  = not -t *STDOUT;
@@ -1237,6 +1306,12 @@ sub read_ackrc {
             chomp @lines;
             close $fh or App::Ack::die( "$filename: $!\n" );
 
+            # get rid of leading and trailing whitespaces
+            for ( @lines ) {
+               s/^\s+//;
+               s/\s+$//;
+            }
+
             return @lines;
         }
     }
@@ -1261,6 +1336,7 @@ sub get_command_line_options {
         'color|colour!'         => \$opt{color},
         'color-match=s'         => \$ENV{ACK_COLOR_MATCH},
         'color-filename=s'      => \$ENV{ACK_COLOR_FILENAME},
+        'color-lineno=s'        => \$ENV{ACK_COLOR_LINENO},
         'column!'               => \$opt{column},
         count                   => \$opt{count},
         'env!'                  => sub { }, # ignore this option, it is handled beforehand
@@ -1274,6 +1350,7 @@ sub get_command_line_options {
         'h|no-filename'         => \$opt{h},
         'H|with-filename'       => \$opt{H},
         'i|ignore-case'         => \$opt{i},
+        'invert-file-match'     => \$opt{invert_file_match},
         'lines=s'               => sub { shift; my $val = shift; push @{$opt{lines}}, $val },
         'l|files-with-matches'  => \$opt{l},
         'L|files-without-matches' => sub { $opt{l} = $opt{v} = 1 },
@@ -1287,7 +1364,8 @@ sub get_command_line_options {
         'passthru'              => \$opt{passthru},
         'print0'                => \$opt{print0},
         'Q|literal'             => \$opt{Q},
-        'r|R|recurse'           => sub {},
+        'r|R|recurse'           => sub { $opt{n} = 0 },
+        'show-types'            => \$opt{show_types},
         'smart-case!'           => \$opt{smart_case},
         'sort-files'            => \$opt{sort_files},
         'u|unrestricted'        => \$opt{u},
@@ -1297,10 +1375,16 @@ sub get_command_line_options {
         'ignore-dirs=s'         => sub { shift; my $dir = remove_dir_sep( shift ); $ignore_dirs{$dir} = '--ignore-dirs' },
         'noignore-dirs=s'       => sub { shift; my $dir = remove_dir_sep( shift ); delete $ignore_dirs{$dir} },
 
-        'version'   => sub { print_version_statement(); exit 1; },
+        'version'   => sub { print_version_statement(); exit; },
         'help|?:s'  => sub { shift; show_help(@_); exit; },
         'help-types'=> sub { show_help_types(); exit; },
-        'man'       => sub { require Pod::Usage; Pod::Usage::pod2usage({-verbose => 2}); exit; },
+        'man'       => sub {
+            require Pod::Usage;
+            Pod::Usage::pod2usage({
+                -verbose => 2,
+                -exitval => 0,
+            });
+        },
 
         'type=s'    => sub {
             # Whatever --type=xxx they specify, set it manually in the hash
@@ -1479,7 +1563,7 @@ sub delete_type {
 
 
 sub ignoredir_filter {
-    return !exists $ignore_dirs{$_};
+    return !exists $ignore_dirs{$_} && !exists $ignore_dirs{$File::Next::dir};
 }
 
 
@@ -1502,7 +1586,7 @@ sub filetypes {
     return 'skipped' unless is_searchable( $basename );
 
     my $lc_basename = lc $basename;
-    return ('make',TEXT)        if $lc_basename eq 'makefile';
+    return ('make',TEXT)        if $lc_basename eq 'makefile' || $lc_basename eq 'gnumakefile';
     return ('rake','ruby',TEXT) if $lc_basename eq 'rakefile';
 
     # If there's an extension, look it up
@@ -1540,7 +1624,7 @@ sub filetypes {
     close $fh;
 
     if ( $header =~ /^#!/ ) {
-        return ($1,TEXT)       if $header =~ /\b(ruby|p(?:erl|hp|ython))\b/;
+        return ($1,TEXT)       if $header =~ /\b(ruby|lua|p(?:erl|hp|ython))-?(\d[\d.]*)?\b/;
         return ('shell',TEXT)  if $header =~ /\b(?:ba|t?c|k|z)?sh\b/;
     }
     else {
@@ -1560,6 +1644,7 @@ sub is_searchable {
     return if $filename =~ m{^#.*#$}o;
     return if $filename =~ m{^core\.\d+$}o;
     return if $filename =~ m{[._].*\.swp$}o;
+    return if $filename =~ /[.-]min\.js$/;
 
     return 1;
 }
@@ -1569,6 +1654,8 @@ sub build_regex {
     my $str = shift;
     my $opt = shift;
 
+    defined $str or App::Ack::die( 'No regular expression found.' );
+
     $str = quotemeta( $str ) if $opt->{Q};
     if ( $opt->{w} ) {
         $str = "\\b$str" if $str =~ /^\w/;
@@ -1718,7 +1805,8 @@ File presentation:
                         output is redirected, or on Windows)
   --[no]colour          Same as --[no]color
   --color-filename=COLOR
-  --color-match=COLOR   Set the color for matches and filenames.
+  --color-match=COLOR
+  --color-lineno=COLOR  Set the color for filenames, matches, and line numbers.
   --flush               Flush output immediately, even when ack is used
                         non-interactively (when output goes to a pipe or
                         file).
@@ -1728,6 +1816,8 @@ File finding:
                         The PATTERN must not be specified.
   -g REGEX              Same as -f, but only print files matching REGEX.
   --sort-files          Sort the found files lexically.
+  --invert-file-match   Print/search handle files that do not match -g/-G.
+  --show-types          Show which types each file has.
 
 File inclusion/exclusion:
   -a, --all-types       All file types searched;
@@ -1758,10 +1848,11 @@ File inclusion/exclusion:
     $ignore_dirs
 
   Files not checked for type:
-    /~\$/           - Unix backup files
-    /#.+#\$/        - Emacs swap files
+    /~\$/            - Unix backup files
+    /#.+#\$/         - Emacs swap files
     /[._].*\\.swp\$/ - Vi(m) swap files
-    /core\\.\\d+\$/   - core dumps
+    /core\\.\\d+\$/  - core dumps
+    /[.-]min\\.js\$/  - Minified javascript files
 
 Miscellaneous:
   --noenv               Ignore environment variables and ~/.ackrc
@@ -1843,9 +1934,8 @@ Running under Perl $ver at $this_perl
 
 $copyright
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of either: the GNU General Public License as
-published by the Free Software Foundation; or the Artistic License.
+This program is free software.  You may modify or distribute it
+under the terms of the Artistic License v2.0.
 END_OF_VERSION
 }
 
@@ -1867,6 +1957,7 @@ sub load_colors {
 
     $ENV{ACK_COLOR_MATCH}    ||= 'black on_yellow';
     $ENV{ACK_COLOR_FILENAME} ||= 'bold green';
+    $ENV{ACK_COLOR_LINENO}   ||= 'bold yellow';
 
     return;
 }
@@ -1908,17 +1999,29 @@ sub print_count {
     my $nmatches = shift;
     my $ors = shift;
     my $count = shift;
+    my $show_filename = shift;
 
-    App::Ack::print( $filename );
-    App::Ack::print( ':', $nmatches ) if $count;
+    if ($show_filename) {
+        App::Ack::print( $filename );
+        App::Ack::print( ':', $nmatches ) if $count;
+    }
+    else {
+        App::Ack::print( $nmatches ) if $count;
+    }
     App::Ack::print( $ors );
 }
 
 sub print_count0 {
     my $filename = shift;
     my $ors = shift;
+    my $show_filename = shift;
 
-    App::Ack::print( $filename, ':0', $ors );
+    if ($show_filename) {
+        App::Ack::print( $filename, ':0', $ors );
+    }
+    else {
+        App::Ack::print( '0', $ors );
+    }
 }
 
 
@@ -2079,7 +2182,11 @@ sub print_match_or_context {
 
         if ( $show_filename ) {
             App::Ack::print_filename($display_filename, $sep) if not $heading;
-            App::Ack::print_line_no($line_no, $sep);
+            my $display_line_no =
+                $color
+                    ? Term::ANSIColor::colored( $line_no, $ENV{ACK_COLOR_LINENO} )
+                    : $line_no;
+            App::Ack::print_line_no($display_line_no, $sep);
         }
 
         if ( $output_func ) {
@@ -2113,6 +2220,17 @@ sub print_match_or_context {
 } # scope around search_resource() and print_match_or_context()
 
 
+TOTAL_COUNT_SCOPE: {
+my $total_count;
+
+sub get_total_count {
+    return $total_count;
+}
+
+sub reset_total_count {
+    $total_count = 0;
+}
+
 
 sub search_and_list {
     my $res = shift;
@@ -2121,6 +2239,7 @@ sub search_and_list {
     my $nmatches = 0;
     my $count = $opt->{count};
     my $ors = $opt->{print0} ? "\0" : "\n"; # output record separator
+    my $show_filename = $opt->{show_filename};
 
     my $regex = qr/$opt->{regex}/;
 
@@ -2143,16 +2262,23 @@ sub search_and_list {
         }
     }
 
-    if ( $nmatches ) {
-        App::Ack::print_count( $res->name, $nmatches, $ors, $count );
+    if ( $opt->{show_total} ) {
+        $total_count += $nmatches;
     }
-    elsif ( $count && !$opt->{l} ) {
-        App::Ack::print_count0( $res->name, $ors );
+    else {
+        if ( $nmatches ) {
+            App::Ack::print_count( $res->name, $nmatches, $ors, $count, $show_filename );
+        }
+        elsif ( $count && !$opt->{l} ) {
+            App::Ack::print_count0( $res->name, $ors, $show_filename );
+        }
     }
 
     return $nmatches ? 1 : 0;
 }   # search_and_list()
 
+} # scope around $total_count
+
 
 
 sub filetypes_supported_set {
@@ -2169,7 +2295,7 @@ sub print_files {
 
     my $nmatches = 0;
     while ( defined ( my $file = $iter->() ) ) {
-        App::Ack::print $file, $ors;
+        App::Ack::print $file, $opt->{show_types} ? " => " . join( ',', filetypes( $file ) ) : (),  $ors;
         $nmatches++;
         last if $opt->{1};
     }
@@ -2182,6 +2308,17 @@ sub print_files_with_matches {
     my $iter = shift;
     my $opt = shift;
 
+    # if we have -l and only 1 file given on command line (this means
+    # show_filename is set to 0), we want to see the filename nevertheless
+    $opt->{show_filename} = 1 if $opt->{l};
+
+    $opt->{show_filename} = 0 if $opt->{h};
+    $opt->{show_filename} = 1 if $opt->{H};
+
+    # abuse options to hand in the show_total parameter to search_and_list
+    $opt->{show_total} = $opt->{count} && !$opt->{show_filename};
+    reset_total_count();
+
     my $nmatches = 0;
     while ( defined ( my $filename = $iter->() ) ) {
         my $repo = App::Ack::Repository::Basic->new( $filename );
@@ -2194,6 +2331,10 @@ sub print_files_with_matches {
         $repo->close();
     }
 
+    if ( $nmatches && $opt->{show_total} ) {
+        App::Ack::print_count('', get_total_count(), "\n", 1, 0  )
+    }
+
     return $nmatches;
 }
 
@@ -2319,6 +2460,16 @@ sub get_starting_points {
     return \@what;
 }
 
+sub _match {
+    my ( $target, $expression, $invert_flag ) = @_;
+
+    if ( $invert_flag ) {
+        return $target !~ $expression;
+    }
+    else {
+        return $target =~ $expression;
+    }
+}
 
 
 sub get_iterator {
@@ -2333,9 +2484,9 @@ sub get_iterator {
 
     if ( $g_regex ) {
         $file_filter
-            = $opt->{u}   ? sub { $File::Next::name =~ /$g_regex/ } # XXX Maybe this should be a 1, no?
-            : $opt->{all} ? sub { $starting_point{ $File::Next::name } || ( $File::Next::name =~ /$g_regex/ && is_searchable( $_ ) ) }
-            :               sub { $starting_point{ $File::Next::name } || ( $File::Next::name =~ /$g_regex/ && is_interesting( @_ ) ) }
+            = $opt->{u}   ? sub { _match( $File::Next::name, qr/$g_regex/, $opt->{invert_file_match} ) }    # XXX Maybe this should be a 1, no?
+            : $opt->{all} ? sub { $starting_point{ $File::Next::name } || ( _match( $File::Next::name, qr/$g_regex/, $opt->{invert_file_match} ) && is_searchable( $_ ) ) }
+            :               sub { $starting_point{ $File::Next::name } || ( _match( $File::Next::name, qr/$g_regex/, $opt->{invert_file_match} ) && is_interesting( @ _) ) }
             ;
     }
     else {
@@ -2389,6 +2540,14 @@ sub output_to_pipe {
 }
 
 
+sub exit_from_ack {
+    my $nmatches = shift;
+
+    my $rc = $nmatches ? 0 : 1;
+    exit $rc;
+}
+
+
 
 1; # End of App::Ack
 package App::Ack::Repository;