diff --git a/AckMate.xcodeproj/project.pbxproj b/AckMate.xcodeproj/project.pbxproj
index cb80328..4eb49b5 100644
--- a/AckMate.xcodeproj/project.pbxproj
+++ b/AckMate.xcodeproj/project.pbxproj
@@ -51,7 +51,7 @@
outputFiles = (
"$(DERIVED_FILES_DIR)/$(INPUT_FILE_BASE)",
);
- script = "/usr/bin/env ragel ${INPUT_FILE_DIR}/${INPUT_FILE_BASE}.rl -o ${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}";
+ script = "/usr/local/bin/ragel ${INPUT_FILE_DIR}/${INPUT_FILE_BASE}.rl -o ${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}";
};
/* End PBXBuildRule section */
@@ -295,7 +295,11 @@
};
buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "AckMate" */;
compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
hasScannedForEncodings = 1;
+ knownRegions = (
+ en,
+ );
mainGroup = 089C166AFE841209C02AAC07 /* AckMate */;
projectDirPath = "";
projectRoot = "";
@@ -384,6 +388,7 @@
1DEB913B08733D840010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
@@ -394,6 +399,7 @@
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Bundles";
PRODUCT_NAME = AckMate;
+ SDKROOT = macosx;
WRAPPER_EXTENSION = tmplugin;
ZERO_LINK = YES;
};
@@ -402,10 +408,7 @@
1DEB913C08733D840010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = (
- ppc,
- i386,
- );
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_MODEL_TUNING = G5;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
@@ -413,6 +416,7 @@
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Bundles";
PRODUCT_NAME = AckMate;
+ SDKROOT = macosx;
WRAPPER_EXTENSION = tmplugin;
};
name = Release;
@@ -420,20 +424,22 @@
1DEB913F08733D840010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
- SDKROOT = macosx10.5;
+ SDKROOT = macosx;
};
name = Debug;
};
1DEB914008733D840010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
- SDKROOT = macosx10.5;
+ SDKROOT = macosx;
};
name = Release;
};
diff --git a/Info.plist b/Info.plist
index 58e5966..c1eafbd 100644
--- a/Info.plist
+++ b/Info.plist
@@ -6,20 +6,20 @@
English
CFBundleExecutable
${EXECUTABLE_NAME}
- CFBundleName
- ${PRODUCT_NAME}
CFBundleIconFile
CFBundleIdentifier
com.jetpackpony.AckMate
CFBundleInfoDictionaryVersion
6.0
+ CFBundleName
+ ${PRODUCT_NAME}
CFBundlePackageType
BNDL
CFBundleSignature
????
CFBundleVersion
- 1.1.2
+ 1.1.3
NSPrincipalClass
AckMatePlugin
diff --git a/README.mdown b/README.mdown
index 728c24e..a78a589 100644
--- a/README.mdown
+++ b/README.mdown
@@ -1,34 +1,38 @@
-## Description
+## Modifications
-**AckMate** is a [TextMate](http://macromates.com/) plugin for running [Ack](http://betterthangrep.com) in a Cocoa window.
+This is is a **modified version** of [AckMate](https://github.com/protocool/AckMate) Once/if [protocool](https://github.com/protocool) pulls these changes, I recommend switching back to his git repo. That said, some of my changes violate his rule about not changing ack; if they never make the cut, you'll still be able to find a copy here.
-*This plugin is only compatible with Mac OS X 10.5 and above.*
+Changes include:
+- Added standard TextMate folder references via ack -G
+- Updated the XCode build configuration for 10.6 (and modified ragel path to avoid build confusion)
+- Added better UTF-8 error output
-## Donations
+## Description
-Like many of you, I do this sort of thing to keep my family warm, clothed, and fed. Every hour I spend on AckMate is an hour that I'm not billing for.
+**AckMate** is a [TextMate](http://macromates.com/) plugin for running [Ack](http://betterthangrep.com) in a Cocoa window.
-If you find AckMate useful, a small [donation](http://pledgie.com/campaigns/9779) is a great way to show your appreciation.
+*This plugin is only compatible with Mac OS X 10.6 and above.*
## Binary Installation
-* Download the latest release from the [downloads section](http://github.com/protocool/AckMate/downloads)
-* Save any unsaved documents you have open in TextMate
-* Unpack the zip file and double-click the AckMate.tmplugin icon
+- Download the latest release from the [downloads section](http://github.com/jswartwood/AckMate/downloads)
+- Save any unsaved documents you have open in TextMate
+- Unpack the zip file and double-click the AckMate.tmplugin icon
## Usage
-Check the wiki for usage instructions.
+Check the [wiki](https://github.com/protocool/AckMate/wiki) for usage instructions.
## Building From Source
-AckMate's build process requires [Ragel](http://www.complang.org/ragel/) to be in your PATH.
+AckMate's build process requires [Ragel](http://www.complang.org/ragel/) to be in */usr/local/bin* if you have it installed elsewhere please update XCode configuration or symlink to your install location.
-## Contributing
+Installing Ragel is easiest with [Homebrew](http://mxcl.github.com/homebrew/)
-I'm always willing to look at a pull request.
+ brew install ragel
-However, **any** pull requests that include changes to the `ackmate_ack.autogenerated` file will be ignored without comment.
+## Contributing
-Changes to ack itself should be directed to Andy Lester (the author of ack) via his [github repo](http://github.com/petdance/ack). I will periodically rebase AckMate's version of ack against the offical ack release.
+I'm all ears... send pull requests if you have them.
+If you find AckMate useful, donate to [protcool](http://pledgie.com/campaigns/9779) (the original author)
diff --git a/bundle_extras/ackmate_ack.autogenerated b/bundle_extras/ackmate_ack.autogenerated
index 833897d..8a2a939 100755
--- a/bundle_extras/ackmate_ack.autogenerated
+++ b/bundle_extras/ackmate_ack.autogenerated
@@ -14,7 +14,7 @@ use strict;
use Unicode::Normalize;
use Encode;
-our $VERSION = '1.92-ackmate';
+our $VERSION = '1.94-ackmate';
# Check http://betterthangrep.com/ for updates
# These are all our globals.
@@ -34,13 +34,17 @@ MAIN: {
/^--th[pt]+t+$/ && App::Ack::_thpppt($_);
# See if we want to ignore the environment. (Don't tell Al Gore.)
- if ( $_ eq '--noenv' ) {
+ if ( /^--(no)?env$/ ) {
+ $env_is_usable = defined $1 ? 0 : 1;
+ }
+ }
+ if ( $env_is_usable ) {
+ unshift( @ARGV, App::Ack::read_ackrc() );
+ }
+ else {
my @keys = ( 'ACKRC', grep { /^ACK_/ } keys %ENV );
delete @ENV{@keys};
- $env_is_usable = 0;
}
- }
- unshift( @ARGV, App::Ack::read_ackrc() ) if $env_is_usable;
App::Ack::load_colors();
if ( exists $ENV{ACK_SWITCHES} ) {
@@ -71,15 +75,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 );
}
@@ -105,7 +119,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
@@ -208,6 +222,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
@@ -225,6 +241,10 @@ Sets the color to be used for filenames.
Sets the color to be used for matches.
+=item B<--color-lineno=I>
+
+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
@@ -298,7 +318,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>
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
@@ -306,6 +326,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 must always be a simple directory name. Nested directories like
+F 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>
Only print line I of each file. Multiple lines can be given with multiple
@@ -340,7 +365,7 @@ Stop reading a file after I matches.
Print this manual page.
-=item B<-n>
+=item B<-n>, B<--no-recurse>
No descending into subdirectories.
@@ -387,6 +412,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
@@ -403,6 +433,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.
+=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
@@ -601,6 +637,15 @@ This option can also be set with B<--color-match>.
See B 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 for the color specifications.
+
=item ACK_PAGER
Specifies a pager program, such as C, C or C, to which
@@ -735,10 +780,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
-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.
@@ -766,7 +813,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)
@@ -793,6 +840,19 @@ To do that, run this with F or as root:
ln -s /usr/bin/ack-grep /usr/bin/ack
+=head2 What does F 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
Andy Lester, C<< >>
@@ -852,6 +912,11 @@ L
How appropriate to have Inowledgements!
Thanks to everyone who has contributed to ack in any way, including
+Scott Kyle,
+Nick Hooey,
+Bo Borgerson,
+Mark Szymanski,
+Marq Schneider,
Packy Anderson,
JR Boyens,
Dan Sully,
@@ -913,20 +978,10 @@ and Pete Krawczyk.
=head1 COPYRIGHT & LICENSE
-Copyright 2005-2009 Andy Lester.
+Copyright 2005-2010 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;
@@ -1109,8 +1164,8 @@ use strict;
our $VERSION;
our $COPYRIGHT;
BEGIN {
- $VERSION = '1.92-ackmate';
- $COPYRIGHT = 'Copyright 2005-2009 Andy Lester.';
+ $VERSION = '1.94-ackmate';
+ $COPYRIGHT = 'Copyright 2005-2010 Andy Lester.';
}
our $fh;
@@ -1149,6 +1204,7 @@ BEGIN {
'.hg' => 'Mercurial',
'.pc' => 'quilt',
'.svn' => 'Subversion',
+ _MTN => 'Monotone',
blib => 'Perl module building',
CVS => 'CVS',
RCS => 'RCS',
@@ -1168,12 +1224,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 )],
@@ -1182,7 +1242,7 @@ 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 )],
@@ -1193,7 +1253,7 @@ BEGIN {
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 )],
@@ -1205,9 +1265,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 ) {
@@ -1217,6 +1279,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;
@@ -1246,6 +1310,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;
}
}
@@ -1272,6 +1342,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
@@ -1285,6 +1356,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 },
@@ -1298,7 +1370,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},
@@ -1308,11 +1381,17 @@ 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; },
'ackmate-types' => sub { show_ackmate_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
@@ -1500,7 +1579,7 @@ sub delete_type {
sub ignoredir_filter {
- return !( exists( $ignore_dirs{$_} ) || ( $ignore_dirpattern && $File::Next::dir =~ m/$ignore_dirpattern/ ) );
+ return !( exists $ignore_dirs{$_} || exists $ignore_dirs{$File::Next::dir} || ( $ignore_dirpattern && $File::Next::dir =~ m/$ignore_dirpattern/ ) );
}
@@ -1523,7 +1602,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
@@ -1557,6 +1636,13 @@ sub filetypes {
App::Ack::warn( "$filename: $!" );
return;
}
+
+ local $SIG{__WARN__} = sub {
+ my $e = shift;
+ App::Ack::warn( "\n$filename\nYou probably want to either convert this file to utf-8, ignore it in ~/.ackrc, or delete it.\n" );
+ return;
+ };
+
my $header = <$fh>;
close $fh;
@@ -1590,6 +1676,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/;
@@ -1739,7 +1827,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).
@@ -1749,6 +1838,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;
@@ -1874,9 +1965,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
}
@@ -1898,6 +1988,7 @@ sub load_colors {
$ENV{ACK_COLOR_MATCH} ||= 'black on_yellow';
$ENV{ACK_COLOR_FILENAME} ||= 'bold green';
+ $ENV{ACK_COLOR_LINENO} ||= 'bold yellow';
return;
}
@@ -1939,18 +2030,30 @@ sub print_count {
my $nmatches = shift;
my $ors = shift;
my $count = shift;
+ my $show_filename = shift;
+ 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;
+ if ($show_filename) {
App::Ack::print( $filename, ':0', $ors );
}
+ else {
+ App::Ack::print( '0', $ors );
+ }
+}
@@ -2111,7 +2214,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) if not $ackmate;
+ 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 not $ackmate;
}
if ( $output_func ) {
@@ -2157,6 +2264,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;
@@ -2165,6 +2283,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}/;
@@ -2187,16 +2306,23 @@ sub search_and_list {
}
}
+ if ( $opt->{show_total} ) {
+ $total_count += $nmatches;
+ }
+ else {
if ( $nmatches ) {
- App::Ack::print_count( $res->name, $nmatches, $ors, $count );
+ App::Ack::print_count( $res->name, $nmatches, $ors, $count, $show_filename );
}
elsif ( $count && !$opt->{l} ) {
- App::Ack::print_count0( $res->name, $ors );
+ App::Ack::print_count0( $res->name, $ors, $show_filename );
+ }
}
return $nmatches ? 1 : 0;
} # search_and_list()
+} # scope around $total_count
+
sub filetypes_supported_set {
@@ -2213,7 +2339,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};
}
@@ -2226,6 +2352,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 );
@@ -2238,6 +2375,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;
}
@@ -2379,6 +2520,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 {
@@ -2393,9 +2544,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 {
@@ -2449,6 +2600,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;
@@ -2609,6 +2768,12 @@ sub needs_line_scan {
}
return 0 unless $rc && ( $rc == $size || length(Encode::encode_utf8($buffer)) == $size );
+ local $SIG{__WARN__} = sub {
+ my $e = shift;
+ App::Ack::warn( "\n$self->{filename}\nYou probably want to either convert this file to utf-8, ignore it in ~/.ackrc, or delete it.\n" );
+ return;
+ };
+
my $regex = $opt->{regex};
return $buffer =~ /$regex/m;
}
diff --git a/source/controllers/JPAckProcess.h b/source/controllers/JPAckProcess.h
index c6db67d..af59136 100644
--- a/source/controllers/JPAckProcess.h
+++ b/source/controllers/JPAckProcess.h
@@ -15,7 +15,7 @@ extern NSString * const JPAckProcessComplete;
}
- (id)initWithResultHolder:(JPAckResultSource*)resultHolder;
-- (void)invokeWithTerm:(NSString*)term path:(NSString*)path searchFolder:(NSString*)searchFolder literal:(BOOL)literal nocase:(BOOL)nocase words:(BOOL)words context:(BOOL)context symlinks:(BOOL)symlinks folderPattern:(NSString*)folderPattern options:(NSArray*)options;
+- (void)invokeWithTerm:(NSString*)term path:(NSString*)path searchFolder:(NSString*)searchFolder literal:(BOOL)literal nocase:(BOOL)nocase words:(BOOL)words context:(BOOL)context symlinks:(BOOL)symlinks folderPattern:(NSString*)folderPattern filePattern:(NSString*)filePattern options:(NSArray*)options;
- (void)parseData:(NSData*)data;
- (void)saveTrailing:(char*)bytes length:(NSUInteger)length;
diff --git a/source/controllers/JPAckProcess.m b/source/controllers/JPAckProcess.m
index 56d9144..4e3cd36 100644
--- a/source/controllers/JPAckProcess.m
+++ b/source/controllers/JPAckProcess.m
@@ -44,7 +44,7 @@ - (id)initWithResultHolder:(JPAckResultSource*)resultHolder
return self;
}
-- (void)invokeWithTerm:(NSString*)term path:(NSString*)path searchFolder:(NSString*)searchFolder literal:(BOOL)literal nocase:(BOOL)nocase words:(BOOL)words context:(BOOL)context symlinks:(BOOL)symlinks folderPattern:(NSString*)folderPattern options:(NSArray*)options
+- (void)invokeWithTerm:(NSString*)term path:(NSString*)path searchFolder:(NSString*)searchFolder literal:(BOOL)literal nocase:(BOOL)nocase words:(BOOL)words context:(BOOL)context symlinks:(BOOL)symlinks folderPattern:(NSString*)folderPattern filePattern:(NSString*)filePattern options:(NSArray*)options
{
ackState = ackInitial;
[self.ackResult clearContents];
@@ -79,6 +79,13 @@ - (void)invokeWithTerm:(NSString*)term path:(NSString*)path searchFolder:(NSStri
[args addObject:folderPattern];
}
+ if (filePattern)
+ {
+ [args addObject:@"--invert-file-match"];
+ [args addObject:@"-G"];
+ [args addObject:filePattern];
+ }
+
for (NSString* typeOption in options)
[args addObject:[NSString stringWithFormat:@"%@%@", ([typeOption hasPrefix:@"-"]) ? @"" : @"--", typeOption]];
diff --git a/source/controllers/JPAckWindowController.m b/source/controllers/JPAckWindowController.m
index ddd1f20..1c6e030 100644
--- a/source/controllers/JPAckWindowController.m
+++ b/source/controllers/JPAckWindowController.m
@@ -243,8 +243,10 @@ - (IBAction)performSearch:(id)sender
[ackResult clearContents];
NSString* folderPattern = nil;
+ NSString* filePattern = nil;
if (folders)
folderPattern = [[[NSUserDefaults standardUserDefaults] stringForKey:@"OakFolderReferenceFolderPattern"] substringFromIndex:1];
+ filePattern = [[[NSUserDefaults standardUserDefaults] stringForKey:@"OakFolderReferenceFilePattern"] substringFromIndex:1];
self.currentProcess = [[[JPAckProcess alloc] initWithResultHolder:ackResult] autorelease];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(currentProcessCompleted:) name:JPAckProcessComplete object:self.currentProcess];
@@ -258,6 +260,7 @@ - (IBAction)performSearch:(id)sender
context:context
symlinks:symlinks
folderPattern:folderPattern
+ filePattern:filePattern
options:[optionsField objectValue]];
}