v3 improves __gitcomp_builtin() function a bit to allows both adding extra options (to complement --git-completion-helper limitations) and removing options. v3 should also fix Mac OS breakage. The last change in 42/42 is a new configurable variable in git-completion.bash that allows you to complete _all_ options, including ones that are filtered out by default. For the record there are 22 of them with the following counts: 10 --force 4 --rerere-autoupdate 1 --unsafe-paths 1 --thin 1 --overwrite-ignore 1 --open-files-in-pager 1 --null 1 --ext-grep 1 --exit-code 1 --auto The first 41 patches should be ok to enter 'next' unless people find something else. 42/42 may be a bit more questionable (e.g. configuration variable name, or how we pass options to --git-completion-helper...) and might have to stay on 'pu' longer. Interdiff with v2 below. I remove changes that are reverts back to 'master' to reduce the noise a bit. diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index cfd24c5764..0cfa489a8e 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -36,6 +36,10 @@ # # When set to "1", do not include "DWIM" suggestions in git-checkout # completion (e.g., completing "foo" when "origin/foo" exists). +# +# GIT_COMPLETION_OPTIONS +# +# When set to "all", complete all possible options case "$COMP_WORDBREAKS" in *:*) : great ;; @@ -284,24 +288,33 @@ __gitcomp () # # __gitcomp "$(git xxx --git-completion-helper) ..." # -# except that the value from $(git) is cached +# except that the output is cached. Accept 1-3 arguments: +# 1: the git command to execute, this is also the cache key +# 2: extra options to be added on top (e.g. negative forms) +# 3: options to be excluded __gitcomp_builtin () { # spaces must be replaced with underscore for multi-word # commands, e.g. "git remote add" becomes remote_add. local cmd="$1" - shift + local incl="$2" + local excl="$3" local var=__gitcomp_builtin_"${cmd/-/_}" local options eval "options=\$$var" if [ -z "$options" ]; then - declare -g "$var=$(__git ${cmd/_/ } --git-completion-helper)" - eval "options=\$$var" + # leading and trailing spaces are significant to make + # option removal work correctly. + options=" $(__git ${cmd/_/ } --git-completion-helper=$GIT_COMPLETION_OPTIONS) $incl " + for i in $excl; do + options="${options/ $i / }" + done + eval "$var=\"$options\"" fi - __gitcomp "$options $*" + __gitcomp "$options" } # Variation of __gitcomp_nl () that appends to the existing list of @@ -1096,12 +1109,13 @@ __git_count_arguments () } __git_whitespacelist="nowarn warn error error-all fix" +__git_am_inprogress_options="--skip --continue --resolved --abort" _git_am () { __git_find_repo_path if [ -d "$__git_repo_path"/rebase-apply ]; then - __gitcomp "--skip --continue --resolved --abort" + __gitcomp "$__git_am_inprogress_options" return fi case "$cur" in @@ -1110,7 +1124,8 @@ _git_am () return ;; --*) - __gitcomp_builtin am "--no-utf8" + __gitcomp_builtin am "--no-utf8" \ + "$__git_am_inprogress_options" return esac } @@ -1272,16 +1287,19 @@ _git_cherry () __git_complete_refs } +__git_cherry_pick_inprogress_options="--continue --quit --abort" + _git_cherry_pick () { __git_find_repo_path if [ -f "$__git_repo_path"/CHERRY_PICK_HEAD ]; then - __gitcomp "--continue --quit --abort" + __gitcomp "$__git_cherry_pick_inprogress_options" return fi case "$cur" in --*) - __gitcomp_builtin cherry-pick + __gitcomp_builtin cherry-pick "" \ + "$__git_cherry_pick_inprogress_options" ;; *) __git_complete_refs @@ -2674,16 +2692,19 @@ _git_reset () __git_complete_refs } +__git_revert_inprogress_options="--continue --quit --abort" + _git_revert () { __git_find_repo_path if [ -f "$__git_repo_path"/REVERT_HEAD ]; then - __gitcomp "--continue --quit --abort" + __gitcomp "$__git_revert_inprogress_options" return fi case "$cur" in --*) - __gitcomp_builtin revert "--no-edit" + __gitcomp_builtin revert "--no-edit" \ + "$__git_revert_inprogress_options" return ;; esac diff --git a/parse-options.c b/parse-options.c index 979577ba2c..5b8b2b376e 100644 --- a/parse-options.c +++ b/parse-options.c @@ -430,14 +430,17 @@ void parse_options_start(struct parse_opt_ctx_t *ctx, * many options that do not suppress it properly. */ static int show_gitcomp(struct parse_opt_ctx_t *ctx, - const struct option *opts) + const struct option *opts, + const char *arg) { for (; opts->type != OPTION_END; opts++) { const char *suffix = ""; if (!opts->long_name) continue; - if (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE)) + if (opts->flags & PARSE_OPT_HIDDEN) + continue; + if ((opts->flags & PARSE_OPT_NOCOMPLETE) && strcmp(arg, "all")) continue; switch (opts->type) { @@ -498,8 +501,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, goto show_usage; /* lone --git-completion-helper is asked by git-completion.bash */ - if (ctx->total == 1 && !strcmp(arg + 1, "-git-completion-helper")) - return show_gitcomp(ctx, options); + if (ctx->total == 1 && skip_prefix(arg + 1, "-git-completion-helper=", &arg)) + return show_gitcomp(ctx, options, arg); if (arg[1] != '-') { ctx->opt = arg + 1; diff --git a/parse-options.h b/parse-options.h index f63151fbda..0ba08691e6 100644 --- a/parse-options.h +++ b/parse-options.h @@ -92,7 +92,7 @@ typedef int parse_opt_ll_cb(struct parse_opt_ctx_t *ctx, * (i.e. '<argh>') in the help message. * Useful for options with multiple parameters. * PARSE_OPT_NOCOMPLETE: by default all visible options are completable - * git-completion.bash. This option suppresses that. + * by git-completion.bash. This option suppresses that. * PARSE_OPT_COMP_ARG: this option forces to git-completion.bash to * complete an option as --name= not --name even if * the option takes optional argument. -- 2.16.1.207.gedba492059