Permalink
Browse files

Merge pull request #44 from ggreer/more_options

More options
  • Loading branch information...
2 parents 3165aa8 + 159d5f3 commit 7c81685d4b1b179312b872dc918c6e0f98db9486 @ggreer committed Jul 3, 2012
Showing with 39 additions and 7 deletions.
  1. +7 −1 doc/ag.1
  2. +4 −0 doc/ag.1.md
  3. +2 −2 src/ignore.c
  4. +20 −4 src/options.c
  5. +1 −0 src/options.h
  6. +5 −0 src/search.c
View
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "AG" "1" "April 2012" "" ""
+.TH "AG" "1" "July 2012" "" ""
.
.SH "NAME"
\fBag\fR \- The Silver Searcher\. Like ack, but faster\.
@@ -51,6 +51,9 @@ Recursively search for PATTERN in PATH\. Like grep or ack, but faster\.
\fB\-\-[no]group\fR
.
.IP "\(bu" 4
+\fB\-g PATTERN\fR: Print filenames matching PATTERN\.
+.
+.IP "\(bu" 4
\fB\-G\fR, \fB\-\-file\-search\-regex PATTERN\fR: Only search filenames matching PATTERN\.
.
.IP "\(bu" 4
@@ -66,6 +69,9 @@ Recursively search for PATTERN in PATH\. Like grep or ack, but faster\.
\fB\-l \-\-files\-with\-matches\fR: Only print filenames containing matches, not matching lines\.
.
.IP "\(bu" 4
+\fB\-L \-\-files\-without\-matches\fR: Only print filenames that don\'t contain matches\.
+.
+.IP "\(bu" 4
\fB\-\-literal\fR: Do not parse PATTERN as a regular expression\. Try to match it literally\.
.
.IP "\(bu" 4
View
@@ -34,6 +34,8 @@ Recursively search for PATTERN in PATH. Like grep or ack, but faster.
* `-f --follow`:
Follow symlinks.
* `--[no]group`
+ * `-g PATTERN`:
+ Print filenames matching PATTERN.
* `-G`, `--file-search-regex PATTERN`:
Only search filenames matching PATTERN.
* `--hidden`:
@@ -42,6 +44,8 @@ Recursively search for PATTERN in PATH. Like grep or ack, but faster.
* `--[no]heading`
* `-l --files-with-matches`:
Only print filenames containing matches, not matching lines.
+ * `-L --files-without-matches`:
+ Only print filenames that don't contain matches.
* `--literal`:
Do not parse PATTERN as a regular expression. Try to match it literally.
* `-m --max-count NUM`:
View
@@ -39,14 +39,14 @@ void add_ignore_pattern(const char* pattern) {
if (is_fnmatch(pattern)) {
ignore_patterns_len++;
- ignore_patterns = realloc(ignore_patterns, (ignore_patterns_len) * sizeof(char**));
+ ignore_patterns = realloc(ignore_patterns, (ignore_patterns_len) * sizeof(char*));
ignore_patterns[ignore_patterns_len - 1] = strdup(pattern);
log_debug("added regex ignore pattern %s", pattern);
}
else {
/* a balanced binary tree is best for performance, but I'm lazy */
ignore_names_len++;
- ignore_names = realloc(ignore_names, ignore_names_len * sizeof(char**));
+ ignore_names = realloc(ignore_names, ignore_names_len * sizeof(char*));
for (i = ignore_names_len-1; i > 0; i--) {
if (strcmp(pattern, ignore_names[i-1]) > 0) {
break;
View
@@ -32,7 +32,8 @@ Search options:\n\
--depth NUM: Search up to NUM directories deep. Default is 25.\n\
-f --follow: Follow symlinks.\n\
--[no]group: Same as --[no]break --[no]heading\n\
--G, --file-search-regex\n\
+-g PATTERN: Print filenames that match PATTERN\n\
+-G, --file-search-regex PATTERN: Only search file names matching PATTERN\n\
-i, --ignore-case\n\
--invert-match\n\
--[no]heading\n\
@@ -86,6 +87,7 @@ void parse_options(int argc, char **argv, char **paths[]) {
int opt_index = 0;
const char *home_dir = getenv("HOME");
char *ignore_file_path = NULL;
+ int needs_query = 1;
init_options();
@@ -116,6 +118,7 @@ void parse_options(int argc, char **argv, char **paths[]) {
{ "help", no_argument, NULL, 'h' },
{ "ignore-case", no_argument, NULL, 'i' },
{ "files-with-matches", no_argument, NULL, 'l' },
+ { "files-without-matches", no_argument, NULL, 'L' },
{ "literal", no_argument, &(opts.literal), 1 },
{ "match", no_argument, &useless, 0 },
{ "max-count", required_argument, NULL, 'm' },
@@ -150,7 +153,7 @@ void parse_options(int argc, char **argv, char **paths[]) {
group = 0;
}
- while ((ch = getopt_long(argc, argv, "A:aB:C:DG:fhilm:nvVu", longopts, &opt_index)) != -1) {
+ while ((ch = getopt_long(argc, argv, "A:aB:C:DG:g:fhiLlm:nvVu", longopts, &opt_index)) != -1) {
switch (ch) {
case 'A':
opts.after = atoi(optarg);
@@ -171,6 +174,10 @@ void parse_options(int argc, char **argv, char **paths[]) {
case 'f':
opts.follow_symlinks = 1;
break;
+ case 'g':
+ needs_query = 0;
+ opts.match_files = 1;
+ /* Fall through and build regex */
case 'G':
opts.file_search_regex = pcre_compile(optarg, 0, &pcre_err, &pcre_err_offset, NULL);
if (opts.file_search_regex == NULL) {
@@ -193,6 +200,10 @@ void parse_options(int argc, char **argv, char **paths[]) {
case 'l':
opts.print_filename_only = 1;
break;
+ case 'L':
+ opts.print_filename_only = 1;
+ opts.invert_match = 1;
+ break;
case 'm':
opts.max_matches_per_file = atoi(optarg);
break;
@@ -252,7 +263,7 @@ void parse_options(int argc, char **argv, char **paths[]) {
exit(0);
}
- if (argc == 0) {
+ if (needs_query && argc == 0) {
log_err("What do you want to search for?");
exit(1);
}
@@ -307,7 +318,12 @@ void parse_options(int argc, char **argv, char **paths[]) {
opts.print_line_numbers = 0;
}
- opts.query = strdup(argv[0]);
+ if (needs_query) {
+ opts.query = strdup(argv[0]);
+ }
+ else {
+ opts.query = strdup(".");
+ }
opts.query_len = strlen(opts.query);
log_debug("Query is %s", opts.query);
View
@@ -20,6 +20,7 @@ typedef struct {
int before;
enum case_behavior casing;
const char *file_search_string;
+ int match_files;
pcre *file_search_regex;
pcre_extra *file_search_regex_extra;
int color;
View
@@ -305,6 +305,11 @@ void search_dir(const pcre *re, const pcre_extra *re_extra, const char* path, co
log_debug("Skipping %s due to file_search_regex.", dir_full_path);
goto cleanup;
}
+ else if (opts.match_files) {
+ log_debug("match_files: file_search_regex matched for %s.", dir_full_path);
+ print_path(dir_full_path, '\n');
+ goto cleanup;
+ }
}
search_file(re, re_extra, dir_full_path);

0 comments on commit 7c81685

Please sign in to comment.