This is useful to specify more complicated pattern as with '--grep'. Signed-off-by: Christoph Junghans <ottxor@xxxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html