diff options
author | Johannes Schindelin <Johannes.Schindelin@gmx.de> | 2007-10-14 17:54:06 +0100 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2007-10-29 21:03:30 -0700 |
commit | 7f275b91520d31bfbe43ec5a9bbaf8ac6e663ce0 (patch) | |
tree | 3e21e4a89617c56b47b7d4d1f2312198a8641de9 | |
parent | 0ce865b134f8ccd60f6e584744144b0978a9fdf2 (diff) | |
download | git-7f275b91520d31bfbe43ec5a9bbaf8ac6e663ce0.tar.gz |
parse-options: Allow abbreviated options when unambiguous
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@gmx.de>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
-rw-r--r-- | parse-options.c | 37 | ||||
-rwxr-xr-x | t/t0040-parse-options.sh | 23 |
2 files changed, 60 insertions, 0 deletions
diff --git a/parse-options.c b/parse-options.c index 12a9f9ea68..b4a3b63e9f 100644 --- a/parse-options.c +++ b/parse-options.c @@ -113,6 +113,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; @@ -122,10 +129,38 @@ 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) + return error("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 and abbreviated very much? */ + if (!prefixcmp("no-", arg)) { + flags |= OPT_UNSET; + goto is_abbreviated; + } + /* 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; } @@ -136,6 +171,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 8e4d74b200..ae49424aa0 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -67,4 +67,27 @@ 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 $? != 129 +' + test_done |