parse-options: support --git-completion-helper
This option is designed to be used by git-completion.bash. For many simple cases, what we do in there is usually __gitcomp "lots of completion options" which has to be manually updated when a new user-visible option is added. With support from parse-options, we can write __gitcomp "$(git command --git-completion-helper)" and get that list directly from the parser for free. Dangerous/Unpopular options could be hidden with the new "NOCOMPLETE" flag. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Nguyễn Thái Ngọc Duy committed
Feb 9, 2018 at 18:01 UTC
b9d7f4b4dbebea34ca8d02be8889884fc3fb90c7
2 files changed
+48
-1
parse-options.c
+44
@@ -425,6 +425,46 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,
425
parse_options_check(options);
426
}
427
428
+/*
429
+ * TODO: we are not completing the --no-XXX form yet because there are
430
+ * many options that do not suppress it properly.
431
+ */
432
+static int show_gitcomp(struct parse_opt_ctx_t *ctx,
433
+ const struct option *opts)
434
+{
435
+ for (; opts->type != OPTION_END; opts++) {
436
+ const char *suffix = "";
437
+
438
+ if (!opts->long_name)
439
+ continue;
440
+ if (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE))
441
+ continue;
442
+
443
+ switch (opts->type) {
444
+ case OPTION_GROUP:
445
+ continue;
446
+ case OPTION_STRING:
447
+ case OPTION_FILENAME:
448
+ case OPTION_INTEGER:
449
+ case OPTION_MAGNITUDE:
450
+ case OPTION_CALLBACK:
451
+ if (opts->flags & PARSE_OPT_NOARG)
452
+ break;
453
+ if (opts->flags & PARSE_OPT_OPTARG)
454
+ break;
455
+ if (opts->flags & PARSE_OPT_LASTARG_DEFAULT)
456
+ break;
457
+ suffix = "=";
458
+ break;
459
+ default:
460
+ break;
461
+ }
462
+ printf(" --%s%s", opts->long_name, suffix);
463
+ }
464
+ fputc('\n', stdout);
465
+ exit(0);
466
+}
467
+
468
static int usage_with_options_internal(struct parse_opt_ctx_t *,
469
const char * const *,
470
const struct option *, int, int);
@@ -455,6 +495,10 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
495
if (internal_help && ctx->total == 1 && !strcmp(arg + 1, "h"))
496
goto show_usage;
497
498
+ /* lone --git-completion-helper is asked by git-completion.bash */
499
+ if (ctx->total == 1 && !strcmp(arg + 1, "-git-completion-helper"))
500
+ return show_gitcomp(ctx, options);
501
+
502
if (arg[1] != '-') {
503
ctx->opt = arg + 1;
504
switch (parse_short_opt(ctx, options)) {
parse-options.h
+4
-1
@@ -38,7 +38,8 @@ enum parse_opt_option_flags {
38
PARSE_OPT_LASTARG_DEFAULT = 16,
39
PARSE_OPT_NODASH = 32,
40
PARSE_OPT_LITERAL_ARGHELP = 64,
41
- PARSE_OPT_SHELL_EVAL = 256
41
+ PARSE_OPT_SHELL_EVAL = 256,
42
+ PARSE_OPT_NOCOMPLETE = 512
43
};
44
45
struct option;
@@ -89,6 +90,8 @@ typedef int parse_opt_ll_cb(struct parse_opt_ctx_t *ctx,
90
* PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets
91
* (i.e. '<argh>') in the help message.
92
* Useful for options with multiple parameters.
93
+ * PARSE_OPT_NOCOMPLETE: by default all visible options are completable
94
+ * by git-completion.bash. This option suppresses that.
95
*
96
* `callback`::
97
* pointer to the callback to use for OPTION_CALLBACK or