If options are aggregated, and that the whole token looks like (is the exact prefix of length >= 3 of) a long option, then parse_options rejects it. The typo check isn't performed if there is no aggregation, because the stuck for is the recommended one, hence if we have `-o` being a valid short option that takes an argument, and --option a long one, then we _MUST_ accept -option as it is our official recommended form. Signed-off-by: Pierre Habouzit <madcoder@xxxxxxxxxx> --- parse-options.c | 30 ++++++++++++++++++++++++++++-- t/t0040-parse-options.sh | 11 +++++++++++ test-parse-options.c | 1 + 3 files changed, 40 insertions(+), 2 deletions(-) On Sat, Jan 26, 2008 at 10:42:16AM +0000, Pierre Habouzit wrote: > I agree, I think that we should refuse things where the string after a > /one/ dash starts with 3 or more consecutive characters that are also > the beginning of a long option. I think that 2 is usually a bit "short" > to assume that it's a typo. I'll provide a patch soon Here it is, and we have now: $ git commit -amend error: did you mean `--amend` (with two dashes ?) diff --git a/parse-options.c b/parse-options.c index 7a08a0c..d9562ba 100644 --- a/parse-options.c +++ b/parse-options.c @@ -216,6 +216,26 @@ is_abbreviated: return error("unknown option `%s'", arg); } +void check_typos(const char *arg, const struct option *options) +{ + if (strlen(arg) < 3) + return; + + if (!prefixcmp(arg, "no-")) { + error ("did you mean `--%s` (with two dashes ?)", arg); + exit(129); + } + + for (; options->type != OPTION_END; options++) { + if (!options->long_name) + continue; + if (!prefixcmp(options->long_name, arg)) { + error ("did you mean `--%s` (with two dashes ?)", arg); + exit(129); + } + } +} + static NORETURN void usage_with_options_internal(const char * const *, const struct option *, int); @@ -235,12 +255,18 @@ int parse_options(int argc, const char **argv, const struct option *options, if (arg[1] != '-') { args.opt = arg + 1; - do { + if (*args.opt == 'h') + usage_with_options(usagestr, options); + if (parse_short_opt(&args, options) < 0) + usage_with_options(usagestr, options); + if (args.opt) + check_typos(arg + 1, options); + while (args.opt) { if (*args.opt == 'h') usage_with_options(usagestr, options); if (parse_short_opt(&args, options) < 0) usage_with_options(usagestr, options); - } while (args.opt); + } continue; } diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 462fdf2..0a3b55d 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -19,6 +19,7 @@ string options get a string --string2 <str> get another string --st <st> get another string (pervert ordering) + -o <str> get another string EOF @@ -103,4 +104,14 @@ test_expect_success 'non ambiguous option (after two options it abbreviates)' ' git diff expect output ' +cat > expect.err << EOF +error: did you mean \`--boolean\` (with two dashes ?) +EOF + +test_expect_success 'detect possible typos' ' + ! test-parse-options -boolean > output 2> output.err && + test ! -s output && + git diff expect.err output.err +' + test_done diff --git a/test-parse-options.c b/test-parse-options.c index 4d3e2ec..eed8a02 100644 --- a/test-parse-options.c +++ b/test-parse-options.c @@ -19,6 +19,7 @@ int main(int argc, const char **argv) OPT_STRING('s', "string", &string, "string", "get a string"), OPT_STRING(0, "string2", &string, "str", "get another string"), OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"), + OPT_STRING('o', NULL, &string, "str", "get another string"), OPT_END(), }; int i; -- 1.5.4.rc4.24.g5232a
Attachment:
pgpQRHGLfSiVf.pgp
Description: PGP signature