The silver search(ag)比ack-grep还快

今天用ag搜索android4.1的代码,发现总是被一个长得让崩溃的.json文件匹配(键入ag ::layout)搞得没法健康地查看ag.el的结果。

一看ag的代码才知道这长行打印压制还是个未完成功能

src/options.h:48:30:    int print_long_lines; /* TODO: support this in print.c */


好在作者的C代码简洁明了,使得我可以很快写出一个Patch,使用-M 参数来压制长行输出。patch邮件已经发送。我自己也backup一下:


diff --git a/src/options.c b/src/options.c
index b08903f..2f4b18e 100644
--- a/src/options.c
+++ b/src/options.c
@@ -77,6 +77,8 @@ Search options:\n\
 -p --path-to-agignore STRING\n\
                         Use .agignore file at STRING\n\
 --print-long-lines      Print matches on very long lines (Default: >2k characters)\n\
+-M --max-printable-line-length NUM \n\
+                        Skip print the matching lines that have a length bigger than NUM\n      \
 -Q --literal            Don't parse PATTERN as a regular expression\n\
 -s --case-sensitive     Match case sensitively (Enabled by default)\n\
 -S --smart-case         Match case insensitively unless PATTERN contains\n\
@@ -115,6 +117,7 @@ void init_options() {
     opts.color_path = ag_strdup(color_path);
     opts.color_match = ag_strdup(color_match);
     opts.color_line_number = ag_strdup(color_line_number);
+    opts.max_printable_line_length = DEFAULT_MAX_PRINTABLE_LINE_LENGTH;
 }
 
 void cleanup_options() {
@@ -221,6 +224,7 @@ void parse_options(int argc, char **argv, char **base_paths[], char **paths[]) {
         { "version", no_argument, &version, 1 },
         { "word-regexp", no_argument, NULL, 'w' },
         { "workers", required_argument, NULL, 0 },
+        { "max-printable-line-length", required_argument, NULL, 'M' },
         { NULL, 0, NULL, 0 }
     };
 
@@ -253,7 +257,7 @@ void parse_options(int argc, char **argv, char **base_paths[], char **paths[]) {
         opts.stdout_inode = statbuf.st_ino;
     }
 
-    while ((ch = getopt_long(argc, argv, "A:aB:C:DG:g:fhiLlm:np:QRrSsvVtuUwz", longopts, &opt_index)) != -1) {
+    while ((ch = getopt_long(argc, argv, "A:aB:C:DG:g:fhiLlm:M:np:QRrSsvVtuUwz", longopts, &opt_index)) != -1) {
         switch (ch) {
             case 'A':
                 opts.after = atoi(optarg);
@@ -305,6 +309,9 @@ void parse_options(int argc, char **argv, char **base_paths[], char **paths[]) {
             case 'm':
                 opts.max_matches_per_file = atoi(optarg);
                 break;
+            case 'M':
+                opts.max_printable_line_length = atoi(optarg);
+                break;
             case 'n':
                 opts.recurse_dirs = 0;
                 break;
diff --git a/src/options.h b/src/options.h
index 5049ab5..b4d2468 100644
--- a/src/options.h
+++ b/src/options.h
@@ -7,6 +7,7 @@
 #include <pcre.h>
 
 #define DEFAULT_CONTEXT_LEN 2
+#define DEFAULT_MAX_PRINTABLE_LINE_LENGTH 2000
 
 enum case_behavior {
     CASE_SENSITIVE,
@@ -45,6 +46,7 @@ typedef struct {
     int print_heading;
     int print_line_numbers;
     int print_long_lines; /* TODO: support this in print.c */
+    int max_printable_line_length;
     pcre *re;
     pcre_extra *re_extra;
     int recurse_dirs;
diff --git a/src/print.c b/src/print.c
index dc11594..4be9874 100644
--- a/src/print.c
+++ b/src/print.c
@@ -34,6 +34,15 @@ void print_binary_file_matches(const char* path) {
     fprintf(out_fd, "Binary file %s matches.\n", path);
 }
 
+static void check_printable(int len, int *printable) {
+    if (len > opts.max_printable_line_length) {
+        *printable = FALSE;
+        fprintf(out_fd, "+EVIL+MARK+VERY+LONG+LINES+HERE\n");
+    } else {
+        *printable = TRUE;
+    }
+}
+
 void print_file_matches(const char* path, const char* buf, const int buf_len, const match matches[], const int matches_len) {
     int line = 1;
     char **context_prev_lines = NULL;
@@ -49,6 +58,7 @@ void print_file_matches(const char* path, const char* buf, const int buf_len, co
     int i, j;
     int in_a_match = FALSE;
     int printing_a_match = FALSE;
+    int printable = TRUE;
 
     if (opts.ackmate) {
         sep = ':';
@@ -129,7 +139,8 @@ void print_file_matches(const char* path, const char* buf, const int buf_len, co
                     }
                     j = prev_line_offset;
                     /* print up to current char */
-                    for (; j <= i; j++) {
+                    check_printable(i - prev_line_offset, &printable);
+                    for (; j <= i && printable; j++) {
                         fputc(buf[j], out_fd);
                     }
                 } else {
@@ -141,7 +152,8 @@ void print_file_matches(const char* path, const char* buf, const int buf_len, co
                     if (printing_a_match && opts.color) {
                         fprintf(out_fd, "%s", opts.color_match);
                     }
-                    for (j = prev_line_offset; j <= i; j++) {
+                    check_printable(i - prev_line_offset, &printable);
+                    for (j = prev_line_offset; j <= i && printable; j++) {
                         if (j == matches[last_printed_match].end && last_printed_match < matches_len) {
                             if (opts.color) {
                                 fprintf(out_fd, "%s", color_reset);


你可能感兴趣的:(The silver search(ag)比ack-grep还快)