builtin-grep: support -c (--count).
authorJunio C Hamano <junkio@cox.net>
Tue, 2 May 2006 22:40:49 +0000 (15:40 -0700)
committerJunio C Hamano <junkio@cox.net>
Tue, 2 May 2006 22:46:32 +0000 (15:46 -0700)
Signed-off-by: Junio C Hamano <junkio@cox.net>
builtin-grep.c

index b835120..f1800a5 100644 (file)
@@ -88,6 +88,7 @@ struct grep_opt {
        unsigned linenum:1;
        unsigned invert:1;
        unsigned name_only:1;
+       unsigned count:1;
        int regflags;
        unsigned pre_context;
        unsigned post_context;
@@ -149,6 +150,7 @@ static int grep_buffer(struct grep_opt *opt, const char *name,
        unsigned last_hit = 0;
        unsigned last_shown = 0;
        const char *hunk_mark = "";
+       unsigned count = 0;
 
        if (opt->pre_context)
                prev = xcalloc(opt->pre_context, sizeof(*prev));
@@ -179,12 +181,16 @@ static int grep_buffer(struct grep_opt *opt, const char *name,
                if (opt->invert)
                        hit = !hit;
                if (hit) {
+                       count++;
                        if (opt->name_only) {
                                printf("%s\n", name);
                                return 1;
                        }
                        /* Hit at this line.  If we haven't shown the
                         * pre-context lines, we would need to show them.
+                        * When asked to do "count", this still show
+                        * the context which is nonsense, but the user
+                        * deserves to get that ;-).
                         */
                        if (opt->pre_context) {
                                unsigned from;
@@ -206,7 +212,8 @@ static int grep_buffer(struct grep_opt *opt, const char *name,
                        }
                        if (last_shown && lno != last_shown + 1)
                                printf(hunk_mark);
-                       show_line(opt, bol, eol, name, lno, ':');
+                       if (!opt->count)
+                               show_line(opt, bol, eol, name, lno, ':');
                        last_shown = last_hit = lno;
                }
                else if (last_hit &&
@@ -230,6 +237,13 @@ static int grep_buffer(struct grep_opt *opt, const char *name,
                left--;
                lno++;
        }
+       /* NEEDSWORK:
+        * The real "grep -c foo *.c" gives many "bar.c:0" lines,
+        * which feels mostly useless but sometimes useful.  Maybe
+        * make it another option?  For now suppress them.
+        */
+       if (opt->count && count)
+               printf("%s:%u\n", name, count);
        return !!last_hit;
 }
 
@@ -442,6 +456,11 @@ int cmd_grep(int argc, const char **argv, char **envp)
                        opt.name_only = 1;
                        continue;
                }
+               if (!strcmp("-c", arg) ||
+                   !strcmp("--count", arg)) {
+                       opt.count = 1;
+                       continue;
+               }
                if (!strncmp("-A", arg, 2) ||
                    !strncmp("-B", arg, 2) ||
                    !strncmp("-C", arg, 2) ||