worktree: teach 'move' to override lock when --force given twice
[gitweb.git] / parse-options.c
index 0f7059a8ab32a624775026d7dc2289245c87c192..3b874a83a0c897845deeec37c1a3b85e0b625050 100644 (file)
@@ -427,13 +427,59 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,
        parse_options_check(options);
 }
 
-/*
- * TODO: we are not completing the --no-XXX form yet because there are
- * many options that do not suppress it properly.
- */
+static void show_negated_gitcomp(const struct option *opts, int nr_noopts)
+{
+       int printed_dashdash = 0;
+
+       for (; opts->type != OPTION_END; opts++) {
+               int has_unset_form = 0;
+               const char *name;
+
+               if (!opts->long_name)
+                       continue;
+               if (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE))
+                       continue;
+               if (opts->flags & PARSE_OPT_NONEG)
+                       continue;
+
+               switch (opts->type) {
+               case OPTION_STRING:
+               case OPTION_FILENAME:
+               case OPTION_INTEGER:
+               case OPTION_MAGNITUDE:
+               case OPTION_CALLBACK:
+               case OPTION_BIT:
+               case OPTION_NEGBIT:
+               case OPTION_COUNTUP:
+               case OPTION_SET_INT:
+                       has_unset_form = 1;
+                       break;
+               default:
+                       break;
+               }
+               if (!has_unset_form)
+                       continue;
+
+               if (skip_prefix(opts->long_name, "no-", &name)) {
+                       if (nr_noopts < 0)
+                               printf(" --%s", name);
+               } else if (nr_noopts >= 0) {
+                       if (nr_noopts && !printed_dashdash) {
+                               printf(" --");
+                               printed_dashdash = 1;
+                       }
+                       printf(" --no-%s", opts->long_name);
+                       nr_noopts++;
+               }
+       }
+}
+
 static int show_gitcomp(struct parse_opt_ctx_t *ctx,
                        const struct option *opts)
 {
+       const struct option *original_opts = opts;
+       int nr_noopts = 0;
+
        for (; opts->type != OPTION_END; opts++) {
                const char *suffix = "";
 
@@ -463,8 +509,12 @@ static int show_gitcomp(struct parse_opt_ctx_t *ctx,
                }
                if (opts->flags & PARSE_OPT_COMP_ARG)
                        suffix = "=";
+               if (starts_with(opts->long_name, "no-"))
+                       nr_noopts++;
                printf(" --%s%s", opts->long_name, suffix);
        }
+       show_negated_gitcomp(original_opts, -1);
+       show_negated_gitcomp(original_opts, nr_noopts);
        fputc('\n', stdout);
        exit(0);
 }
@@ -610,7 +660,8 @@ int parse_options(int argc, const char **argv, const char *prefix,
 static int usage_argh(const struct option *opts, FILE *outfile)
 {
        const char *s;
-       int literal = (opts->flags & PARSE_OPT_LITERAL_ARGHELP) || !opts->argh;
+       int literal = (opts->flags & PARSE_OPT_LITERAL_ARGHELP) ||
+               !opts->argh || !!strpbrk(opts->argh, "()<>[]|");
        if (opts->flags & PARSE_OPT_OPTARG)
                if (opts->long_name)
                        s = literal ? "[=%s]" : "[=<%s>]";