When there is an option "--amend", the option parser now recognizes "--am" for that option, provided that there is no other option beginning with "--am". Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx> --- On Sun, 14 Oct 2007, Pierre Habouzit wrote: > On Sun, Oct 14, 2007 at 09:18:55AM +0000, Eric Wong wrote: > > > > One feature I really like is automatically handling of long > > option abbreviations. gitopt supported this at the expense of > > complexity and the aforementioned intrusivenes. This allows > > automatic handling of the abbreviation style seen commonly in > > git shell scripts: > > > > --a|--am|--ame|--amen|--amend) (from git-commit.sh) > > Yes, but if you do that, you can't order options in the order > you want (because of first match issues), making the help dumps > hopelessly random. I think this patch proves that you do not need to order the options... ;-) parse-options.c | 32 ++++++++++++++++++++++++++++++++ t/t0040-parse-options.sh | 22 ++++++++++++++++++++++ 2 files changed, 54 insertions(+), 0 deletions(-) diff --git a/parse-options.c b/parse-options.c index 72656a8..afc6c89 100644 --- a/parse-options.c +++ b/parse-options.c @@ -102,6 +102,13 @@ static int parse_short_opt(struct optparse_t *p, const struct option *options) static int parse_long_opt(struct optparse_t *p, const char *arg, const struct option *options) { + const char *arg_end = strchr(arg, '='); + const struct option *abbrev_option = NULL; + int abbrev_flags = 0; + + if (!arg_end) + arg_end = arg + strlen(arg); + for (; options->type != OPTION_END; options++) { const char *rest; int flags = 0; @@ -111,10 +118,33 @@ static int parse_long_opt(struct optparse_t *p, const char *arg, rest = skip_prefix(arg, options->long_name); if (!rest) { + /* abbreviated? */ + if (!strncmp(options->long_name, arg, arg_end - arg)) { +is_abbreviated: + if (abbrev_option) + die ("Ambiguous option: %s " + "(could be --%s%s or --%s%s)", + arg, + (flags & OPT_UNSET) ? + "no-" : "", + options->long_name, + (abbrev_flags & OPT_UNSET) ? + "no-" : "", + abbrev_option->long_name); + if (!(flags & OPT_UNSET) && *arg_end) + p->opt = arg_end + 1; + abbrev_option = options; + abbrev_flags = flags; + continue; + } + /* negated? */ if (strncmp(arg, "no-", 3)) continue; flags |= OPT_UNSET; rest = skip_prefix(arg + 3, options->long_name); + /* abbreviated and negated? */ + if (!rest && !prefixcmp(options->long_name, arg + 3)) + goto is_abbreviated; if (!rest) continue; } @@ -125,6 +155,8 @@ static int parse_long_opt(struct optparse_t *p, const char *arg, } return get_value(p, options, flags); } + if (abbrev_option) + return get_value(p, abbrev_option, abbrev_flags); return error("unknown option `%s'", arg); } diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 09b3230..e4dd86f 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -66,4 +66,26 @@ test_expect_success 'intermingled arguments' ' git diff expect output ' +cat > expect << EOF +boolean: 0 +integer: 2 +string: (not set) +EOF + +test_expect_success 'unambiguously abbreviated option' ' + test-parse-options --int 2 --boolean --no-bo > output 2> output.err && + test ! -s output.err && + git diff expect output +' + +test_expect_success 'unambiguously abbreviated option with "="' ' + test-parse-options --int=2 > output 2> output.err && + test ! -s output.err && + git diff expect output +' + +test_expect_failure 'ambiguously abbreviated option' ' + test-parse-options --strin 123 +' + test_done -- 1.5.3.4.1174.gcd0d6-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