This is useful to specify more complicated pattern as with '--grep'.

Signed-off-by: Christoph Junghans <ott...@gentoo.org>
---
 builtin/grep.c | 73 +++++-----------------------------------------------------
 grep.c         | 62 +++++++++++++++++++++++++++++++++++++++++++++++++
 grep.h         | 10 ++++++++
 revision.c     | 56 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 134 insertions(+), 67 deletions(-)

diff --git a/builtin/grep.c b/builtin/grep.c
index 4063882..0127fa0 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -551,67 +551,6 @@ static int context_callback(const struct option *opt, 
const char *arg,
        return 0;
 }
 
-static int file_callback(const struct option *opt, const char *arg, int unset)
-{
-       struct grep_opt *grep_opt = opt->value;
-       int from_stdin = !strcmp(arg, "-");
-       FILE *patterns;
-       int lno = 0;
-       struct strbuf sb = STRBUF_INIT;
-
-       patterns = from_stdin ? stdin : fopen(arg, "r");
-       if (!patterns)
-               die_errno(_("cannot open '%s'"), arg);
-       while (strbuf_getline(&sb, patterns, '\n') == 0) {
-               /* ignore empty line like grep does */
-               if (sb.len == 0)
-                       continue;
-
-               append_grep_pat(grep_opt, sb.buf, sb.len, arg, ++lno,
-                               GREP_PATTERN);
-       }
-       if (!from_stdin)
-               fclose(patterns);
-       strbuf_release(&sb);
-       return 0;
-}
-
-static int not_callback(const struct option *opt, const char *arg, int unset)
-{
-       struct grep_opt *grep_opt = opt->value;
-       append_grep_pattern(grep_opt, "--not", "command line", 0, GREP_NOT);
-       return 0;
-}
-
-static int and_callback(const struct option *opt, const char *arg, int unset)
-{
-       struct grep_opt *grep_opt = opt->value;
-       append_grep_pattern(grep_opt, "--and", "command line", 0, GREP_AND);
-       return 0;
-}
-
-static int open_callback(const struct option *opt, const char *arg, int unset)
-{
-       struct grep_opt *grep_opt = opt->value;
-       append_grep_pattern(grep_opt, "(", "command line", 0, GREP_OPEN_PAREN);
-       return 0;
-}
-
-static int close_callback(const struct option *opt, const char *arg, int unset)
-{
-       struct grep_opt *grep_opt = opt->value;
-       append_grep_pattern(grep_opt, ")", "command line", 0, GREP_CLOSE_PAREN);
-       return 0;
-}
-
-static int pattern_callback(const struct option *opt, const char *arg,
-                           int unset)
-{
-       struct grep_opt *grep_opt = opt->value;
-       append_grep_pattern(grep_opt, arg, "-e option", 0, GREP_PATTERN);
-       return 0;
-}
-
 static int help_callback(const struct option *opt, const char *arg, int unset)
 {
        return -1;
@@ -710,21 +649,21 @@ int cmd_grep(int argc, const char **argv, const char 
*prefix)
                        N_("show the surrounding function")),
                OPT_GROUP(""),
                OPT_CALLBACK('f', NULL, &opt, N_("file"),
-                       N_("read patterns from file"), file_callback),
+                       N_("read patterns from file"), grep_file_callback),
                { OPTION_CALLBACK, 'e', NULL, &opt, N_("pattern"),
-                       N_("match <pattern>"), PARSE_OPT_NONEG, 
pattern_callback },
+                       N_("match <pattern>"), PARSE_OPT_NONEG, 
grep_pattern_callback },
                { OPTION_CALLBACK, 0, "and", &opt, NULL,
                  N_("combine patterns specified with -e"),
-                 PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
+                 PARSE_OPT_NOARG | PARSE_OPT_NONEG, grep_and_callback },
                OPT_BOOL(0, "or", &dummy, ""),
                { OPTION_CALLBACK, 0, "not", &opt, NULL, "",
-                 PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback },
+                 PARSE_OPT_NOARG | PARSE_OPT_NONEG, grep_not_callback },
                { OPTION_CALLBACK, '(', NULL, &opt, NULL, "",
                  PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
-                 open_callback },
+                 grep_open_callback },
                { OPTION_CALLBACK, ')', NULL, &opt, NULL, "",
                  PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
-                 close_callback },
+                 grep_close_callback },
                OPT__QUIET(&opt.status_only,
                           N_("indicate hit with exit status without output")),
                OPT_BOOL(0, "all-match", &opt.all_match,
diff --git a/grep.c b/grep.c
index 6e085f8..0c9a977 100644
--- a/grep.c
+++ b/grep.c
@@ -1796,3 +1796,65 @@ static int grep_source_is_binary(struct grep_source *gs)
 
        return 0;
 }
+
+int grep_file_callback(const struct option *opt, const char *arg, int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       int from_stdin = !strcmp(arg, "-");
+       FILE *patterns;
+       int lno = 0;
+       struct strbuf sb = STRBUF_INIT;
+
+       patterns = from_stdin ? stdin : fopen(arg, "r");
+       if (!patterns)
+               die_errno(_("cannot open '%s'"), arg);
+       while (strbuf_getline(&sb, patterns, '\n') == 0) {
+               /* ignore empty line like grep does */
+               if (sb.len == 0)
+                       continue;
+
+               append_grep_pat(grep_opt, sb.buf, sb.len, arg, ++lno,
+                               GREP_PATTERN);
+       }
+       if (!from_stdin)
+               fclose(patterns);
+       strbuf_release(&sb);
+       return 0;
+}
+
+int grep_not_callback(const struct option *opt, const char *arg, int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       append_grep_pattern(grep_opt, "--not", "command line", 0, GREP_NOT);
+       return 0;
+}
+
+int grep_and_callback(const struct option *opt, const char *arg, int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       append_grep_pattern(grep_opt, "--and", "command line", 0, GREP_AND);
+       return 0;
+}
+
+int grep_open_callback(const struct option *opt, const char *arg, int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       append_grep_pattern(grep_opt, "(", "command line", 0, GREP_OPEN_PAREN);
+       return 0;
+}
+
+int grep_close_callback(const struct option *opt, const char *arg, int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       append_grep_pattern(grep_opt, ")", "command line", 0, GREP_CLOSE_PAREN);
+       return 0;
+}
+
+int grep_pattern_callback(const struct option *opt, const char *arg,
+                           int unset)
+{
+       struct grep_opt *grep_opt = opt->value;
+       append_grep_pattern(grep_opt, arg, "-e option", 0, GREP_PATTERN);
+       return 0;
+}
+
diff --git a/grep.h b/grep.h
index 95f197a..d85fdb4 100644
--- a/grep.h
+++ b/grep.h
@@ -10,6 +10,7 @@ typedef int pcre_extra;
 #include "kwset.h"
 #include "thread-utils.h"
 #include "userdiff.h"
+#include "parse-options.h"
 
 enum grep_pat_token {
        GREP_PATTERN,
@@ -181,6 +182,15 @@ void grep_source_load_driver(struct grep_source *gs);
 
 int grep_source(struct grep_opt *opt, struct grep_source *gs);
 
+
+int grep_file_callback(const struct option *opt, const char *arg, int unset);
+int grep_not_callback(const struct option *opt, const char *arg, int unset);
+int grep_and_callback(const struct option *opt, const char *arg, int unset);
+int grep_open_callback(const struct option *opt, const char *arg, int unset);
+int grep_close_callback(const struct option *opt, const char *arg, int unset);
+int grep_pattern_callback(const struct option *opt, const char *arg, int 
unset);
+
+
 extern struct grep_opt *grep_opt_dup(const struct grep_opt *opt);
 extern int grep_threads_ok(const struct grep_opt *opt);
 
diff --git a/revision.c b/revision.c
index 75dda92..4fe9085 100644
--- a/revision.c
+++ b/revision.c
@@ -1998,6 +1998,62 @@ static int handle_revision_opt(struct rev_info *revs, 
int argc, const char **arg
                return argcount;
        } else if (!strcmp(arg, "--grep-debug")) {
                revs->grep_filter.debug = 1;
+       } else if (!strcmp(arg, "--grep-begin")) {
+               if (argc <= 1)
+                       return error("--grep-begin requires an argument");
+               int dummy;
+               struct option options[] = {
+                       OPT_CALLBACK('f', NULL, &revs->grep_filter, N_("file"),
+                               N_("read patterns from file"), 
grep_file_callback),
+                       { OPTION_CALLBACK, 'e', NULL, &revs->grep_filter, 
N_("pattern"),
+                               N_("match <pattern>"), PARSE_OPT_NONEG, 
grep_pattern_callback },
+                       { OPTION_CALLBACK, 0, "and", &revs->grep_filter, NULL,
+                         N_("combine patterns specified with -e"),
+                         PARSE_OPT_NOARG | PARSE_OPT_NONEG, grep_and_callback 
},
+                       OPT_BOOL(0, "or", &dummy, ""),
+                       { OPTION_CALLBACK, 0, "not", &revs->grep_filter, NULL, 
"",
+                         PARSE_OPT_NOARG | PARSE_OPT_NONEG, grep_not_callback 
},
+                       { OPTION_CALLBACK, '(', NULL, &revs->grep_filter, NULL, 
"",
+                         PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
+                         grep_open_callback },
+                       { OPTION_CALLBACK, ')', NULL, &revs->grep_filter, NULL, 
"",
+                         PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
+                         grep_close_callback },
+                       OPT_END()
+               };
+               char const * const grep_usage[] = {
+                       N_("git log [log-options] --begin-grep [grep-options] 
--end-grep ..."), 
+                       NULL 
+               };
+               struct parse_opt_ctx_t ctx;
+
+               parse_options_start(&ctx, argc, argv, revs->prefix, options,
+                               PARSE_OPT_STOP_AT_NON_OPTION | 
PARSE_OPT_NO_INTERNAL_HELP);
+               if (parse_options_step(&ctx, options, grep_usage) != 
PARSE_OPT_UNKNOWN) {
+                       error("--grep-end expected");
+                       usage_with_options(grep_usage, options);
+               }
+               if(strcmp(ctx.argv[0], "--grep-end")) {
+                       if (ctx.argv[0][1] == '-') {
+                       error("unknown option `%s'", ctx.argv[0] + 2);
+                       } else if (isascii(*ctx.opt)) {
+                               error("unknown switch `%c'", *ctx.opt);
+                       } else {
+                       error("unknown non-ascii option in string: `%s'",
+                             ctx.argv[0]);
+                       }       
+                       usage_with_options(grep_usage, options);
+               }
+
+               precompose_argv(argc, argv);
+               argcount = argc + 1 - parse_options_end(&ctx);
+               if (argcount == 2 ) {
+                       return error("There should be options between 
--grep-begin and --grep-end ;-)");
+               }
+
+               grep_commit_pattern_type(GREP_PATTERN_TYPE_UNSPECIFIED, 
&revs->grep_filter);
+
+               return argcount;
        } else if (!strcmp(arg, "--basic-regexp")) {
                grep_set_pattern_type_option(GREP_PATTERN_TYPE_BRE, 
&revs->grep_filter);
        } else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
-- 
2.0.5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to