Just a proof of concept. Cc: René Scharfe <rene.scharfe@xxxxxxxxxxxxxx> Signed-off-by: Jonathan Nieder <jrnieder@xxxxxxxxx> --- Jakub Narebski wrote: > If there were more options that use <n> == 0 to actually mean unlimited > (infinity), perhaps it would be better to extend parseopt to provide for > such situation, e.g. OPT_INT_INF or something. Something like this, maybe. Documentation/technical/api-parse-options.txt | 6 ++++++ builtin/grep.c | 8 ++++++-- grep.c | 8 +++++--- grep.h | 4 ++-- parse-options.c | 21 +++++++++++++++++++++ parse-options.h | 4 ++++ 6 files changed, 44 insertions(+), 7 deletions(-) diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt index 312e3b2..f152a3f 100644 --- a/Documentation/technical/api-parse-options.txt +++ b/Documentation/technical/api-parse-options.txt @@ -160,6 +160,12 @@ There are some macros to easily define options: Introduce an option with integer argument. The integer is put into `int_var`. +`OPT_INT_INF(short, long, &int_var, inf_val, description)`:: + Introduce an option with integer argument. + The integer is put into `int_var`. If the special value + "inf" (or "infinity") is used as an argument, then `inf_val` + is put into `int_var`. + `OPT_DATE(short, long, &int_var, description)`:: Introduce an option with date argument, see `approxidate()`. The timestamp is put into `int_var`. diff --git a/builtin/grep.c b/builtin/grep.c index 597f76b..9fbc985 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -750,6 +750,10 @@ static int context_callback(const struct option *opt, const char *arg, grep_opt->pre_context = grep_opt->post_context = 0; return 0; } + if (!strcasecmp(arg, "inf") || !strcasecmp(arg, "infinity")) { + grep_opt->pre_context = grep_opt->post_context = -1; + return 0; + } value = strtol(arg, (char **)&endp, 10); if (*endp) { return error("switch `%c' expects a numerical value", @@ -890,9 +894,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix) OPT_CALLBACK('C', NULL, &opt, "n", "show <n> context lines before and after matches", context_callback), - OPT_INTEGER('B', NULL, &opt.pre_context, + OPT_INT_INF('B', NULL, &opt.pre_context, -1, "show <n> context lines before matches"), - OPT_INTEGER('A', NULL, &opt.post_context, + OPT_INT_INF('A', NULL, &opt.post_context, -1, "show <n> context lines after matches"), OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM", context_callback), diff --git a/grep.c b/grep.c index 82fb349..793d41f 100644 --- a/grep.c +++ b/grep.c @@ -687,7 +687,7 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf, unsigned cur = lno, from = 1, funcname_lno = 0; int funcname_needed = opt->funcname; - if (opt->pre_context < lno) + if (opt->pre_context >= 0 && opt->pre_context < lno) from = lno - opt->pre_context; if (from <= opt->last_shown) from = opt->last_shown + 1; @@ -861,7 +861,8 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name, */ if (try_lookahead && !(last_hit - && lno <= last_hit + opt->post_context) + && (opt->post_context < 0 + || lno <= last_hit + opt->post_context)) && look_ahead(opt, &left, &lno, &bol)) break; eol = end_of_line(bol, &left); @@ -916,7 +917,8 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name, last_hit = lno; } else if (last_hit && - lno <= last_hit + opt->post_context) { + (opt->post_context < 0 || + lno <= last_hit + opt->post_context)) { /* If the last hit is within the post context, * we need to show this line. */ diff --git a/grep.h b/grep.h index efa8cff..13aae94 100644 --- a/grep.h +++ b/grep.h @@ -95,8 +95,8 @@ struct grep_opt { char color_selected[COLOR_MAXLEN]; char color_sep[COLOR_MAXLEN]; int regflags; - unsigned pre_context; - unsigned post_context; + int pre_context; + int post_context; unsigned last_shown; int show_hunk_mark; void *priv; diff --git a/parse-options.c b/parse-options.c index 0fa79bc..b299125 100644 --- a/parse-options.c +++ b/parse-options.c @@ -612,6 +612,27 @@ int parse_opt_approxidate_cb(const struct option *opt, const char *arg, return 0; } +int parse_opt_infinity_cb(const struct option *opt, const char *arg, + int unset) +{ + const char *endp; + + if (unset) { + *(int *)opt->value = 0; + return 0; + } + if (!arg) + return opterror(opt, "expects a numerical value", 0); + if (!strcasecmp(arg, "inf") || !strcasecmp(arg, "infinity")) { + *(int *)opt->value = opt->defval; + return 0; + } + *(int *)opt->value = strtol(arg, (char **)&endp, 10); + if (*endp) + return opterror(opt, "expects a numerical value", 0); + return 0; +} + int parse_opt_color_flag_cb(const struct option *opt, const char *arg, int unset) { diff --git a/parse-options.h b/parse-options.h index 7435cdb..6ae041a 100644 --- a/parse-options.h +++ b/parse-options.h @@ -126,6 +126,9 @@ struct option { #define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) } #define OPT_UYN(s, l, v, h) { OPTION_CALLBACK, (s), (l), (v), NULL, \ (h), PARSE_OPT_NOARG, &parse_opt_tertiary } +#define OPT_INT_INF(s, l, v, i, h) \ + { OPTION_CALLBACK, (s), (l), (v), "n", (h), 0, \ + parse_opt_infinity_cb, (intptr_t)(i) } #define OPT_DATE(s, l, v, h) \ { OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \ parse_opt_approxidate_cb } @@ -193,6 +196,7 @@ extern int parse_options_concat(struct option *dst, size_t, struct option *src); /*----- some often used options -----*/ extern int parse_opt_abbrev_cb(const struct option *, const char *, int); extern int parse_opt_approxidate_cb(const struct option *, const char *, int); +extern int parse_opt_infinity_cb(const struct option *, const char *, int); extern int parse_opt_color_flag_cb(const struct option *, const char *, int); extern int parse_opt_verbosity_cb(const struct option *, const char *, int); extern int parse_opt_with_commit(const struct option *, const char *, int); -- 1.7.2.2.536.g42dab.dirty -- 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