On Tue, Jan 16, 2018 at 2:36 AM, Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> wrote: > 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 "NO_GITCOMP" flag. > > Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> Was this possibly avoided in the past due to being slower than simply storing the list in the completion code itself? I think this is a good idea myself. Thanks, Jake > --- > parse-options.c | 37 +++++++++++++++++++++++++++++++++++++ > parse-options.h | 6 ++++-- > 2 files changed, 41 insertions(+), 2 deletions(-) > > diff --git a/parse-options.c b/parse-options.c > index fca7159646..6c542f44cf 100644 > --- a/parse-options.c > +++ b/parse-options.c > @@ -425,6 +425,35 @@ void parse_options_start(struct parse_opt_ctx_t *ctx, > parse_options_check(options); > } > > +static int show_gitcomp(struct parse_opt_ctx_t *ctx, const struct option *opts) > +{ > + for (; opts->type != OPTION_END; opts++) { > + const char *suffix; > + > + if (!opts->long_name) > + continue; > + if (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NO_GITCOMP)) > + continue; > + > + switch (opts->type) { > + case OPTION_GROUP: > + continue; > + case OPTION_STRING: > + case OPTION_FILENAME: > + case OPTION_INTEGER: > + case OPTION_MAGNITUDE: > + if (!(opts->flags & PARSE_OPT_OPTARG)) > + suffix = "="; > + break; > + default: > + suffix = ""; > + } > + printf(" --%s%s", opts->long_name, suffix); > + } > + fputc('\n', stdout); > + exit(0); > +} > + > static int usage_with_options_internal(struct parse_opt_ctx_t *, > const char * const *, > const struct option *, int, int); > @@ -434,6 +463,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, > const char * const usagestr[]) > { > int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); > + int internal_gitcomp = !(ctx->flags & PARSE_OPT_NO_INTERNAL_GITCOMP); > int err = 0; > > /* we must reset ->opt, unknown short option leave it dangling */ > @@ -455,6 +485,11 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, > if (internal_help && ctx->total == 1 && !strcmp(arg + 1, "h")) > goto show_usage; > > + /* lone --git-completion-helper is asked by git-completion.bash */ > + if (internal_gitcomp && ctx->total == 1 && > + !strcmp(arg + 1, "-git-completion-helper")) > + goto show_git_comp; > + > if (arg[1] != '-') { > ctx->opt = arg + 1; > switch (parse_short_opt(ctx, options)) { > @@ -521,6 +556,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, > err = 1; > show_usage: > return usage_with_options_internal(ctx, usagestr, options, 0, err); > + show_git_comp: > + return show_gitcomp(ctx, options); > } > > int parse_options_end(struct parse_opt_ctx_t *ctx) > diff --git a/parse-options.h b/parse-options.h > index af711227ae..8a3389b05b 100644 > --- a/parse-options.h > +++ b/parse-options.h > @@ -27,7 +27,8 @@ enum parse_opt_flags { > PARSE_OPT_STOP_AT_NON_OPTION = 2, > PARSE_OPT_KEEP_ARGV0 = 4, > PARSE_OPT_KEEP_UNKNOWN = 8, > - PARSE_OPT_NO_INTERNAL_HELP = 16 > + PARSE_OPT_NO_INTERNAL_HELP = 16, > + PARSE_OPT_NO_INTERNAL_GITCOMP = 32 > }; > > enum parse_opt_option_flags { > @@ -38,7 +39,8 @@ enum parse_opt_option_flags { > PARSE_OPT_LASTARG_DEFAULT = 16, > PARSE_OPT_NODASH = 32, > PARSE_OPT_LITERAL_ARGHELP = 64, > - PARSE_OPT_SHELL_EVAL = 256 > + PARSE_OPT_SHELL_EVAL = 256, > + PARSE_OPT_NO_GITCOMP = 512 > }; > > struct option; > -- > 2.15.1.600.g899a5f85c6 >