From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:23
These patches represent what comprises git-completion 1.3, a friendly
fork I'm maintaining.
Some of these have already been sent, and should be in "seen", but for
some reason they are not [1]. Others have been sent, but probably won't
receive any review soon. And others, particularly zsh improvements,
haven't been sent before.
A summary:
* Tons of bugfixes
* zsh: a bunch of improvements
* zsh: an important fix regarding quoting
* zsh: automatic suffix removal
The rest is reorganization, but it's still much needed.
I'm not anticipating these patches to be merged, I'm providing them in
case somebody is interested.
[1] https://lore.kernel.org/git/5fea87e816fff_23821208d4@natae.notmuch/
Felipe Contreras (47):
completion: bash: fix prefix detection in branch.*
completion: fix for suboptions with value
completion: bash: fix for multiple dash commands
completion: bash: add correct suffix in variables
completion: bash: do not modify COMP_WORDBREAKS
test: completion: fix currently typed words
test: completion: switch __gitcomp_nl prefix test
test: completion: add run_func() helper
completion: bash: remove non-append functionality
completion: bash: get rid of _append() functions
completion: bash: get rid of any non-append code
completion: zsh: fix options with arguments
completion: zsh: expand --git-dir file argument
completion: zsh: add support for general -C opts
completion: zsh: fix for undefined completions
completion: zsh: add support for general -c opts
completion: zsh: fix extra space on foo=
completion: zsh: add excluded options
completion: zsh: always set compset
completion: factor out check in __gitcomp
completion: simplify equal suffix check
completion: refactor __gitcomp
completion: simplify __gitcomp
completion: bash: change suffix check in __gitcomp
completion: improve __gitcomp suffix code
completion: bash: simplify config_variable_name
test: completion: add missing test
completion: bash: improve __gitcomp description
completion: add __gitcomp_opts
completion: bash: cleanup __gitcomp* invocations
completion: bash: shuffle __gitcomp functions
completion: zsh: simplify __gitcomp_direct
completion: zsh: shuffle __gitcomp* functions
completion: zsh: fix direct quoting
completion: zsh: add elements individually in __gitcomp_opts
completion: zsh: add __gitcompadd helper
completion: zsh: add correct removable suffix
completion: bash: simplify _get_comp_words_by_ref()
completion: bash: refactor _get_comp_words_by_ref()
completion: bash: cleanup _get_comp_words_by_ref()
completion: bash: trivial cleanup
completion: bash: rename _get_comp_words_by_ref()
completion: bash: add __git_have_func helper
completion: bash: improve function detection
test: completion: add tests for __git_complete
completion: add proper public __git_complete
completion: zsh: add higher-priority location
contrib/completion/git-completion.bash | 704 ++++++++++++-------------
contrib/completion/git-completion.zsh | 133 +++--
t/t9902-completion.sh | 179 ++++---
3 files changed, 498 insertions(+), 518 deletions(-)
--
2.30.0
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:23
They don't match what we are supposed to be completing.
No functional change.
Signed-off-by: Felipe Contreras <redacted>
---
t/t9902-completion.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:23
There was no need for this once __git_reassemble_comp_words_by_ref() was
introduced. Now irrespective of the value of COMP_WORDBREAKS, words are
always joined together.
By default COMP_WORDBREAKS does contain a colon, and if it doesn't
somebody probably has a reason for it.
Completions are not supposed to modify COMP_WORDBREAKS and none of the
completions in the bash-completion project do.
We manually set it in Zsh so the Bash script is not confused.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 5 -----
contrib/completion/git-completion.zsh | 1 +
2 files changed, 1 insertion(+), 5 deletions(-)
@@ -45,11 +45,6 @@# When set to "1" suggest all options, including options which are# typically hidden (e.g. '--allow-empty' for 'git commit').-case"$COMP_WORDBREAKS"in-*:*):great;;-*)COMP_WORDBREAKS="$COMP_WORDBREAKS:"-esac-# Discovers the path to the git repository taking any '--git-dir=<path>' and# '-C <path>' options into account and stores it in the $__git_repo_path# variable.
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:23
The parseopt helper can generate the completions even if the function is
unspecified.
git version --<tab>
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.zsh | 3 +++
1 file changed, 3 insertions(+)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:23
We need to ignore options that don't start with -- as well.
Depending on the value of COMP_WORDBREAKS, the last word could be
duplicated otherwise.
Can be tested with:
git merge -X diff-algorithm=<tab>
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 2 +-
contrib/completion/git-completion.zsh | 2 +-
t/t9902-completion.sh | 15 +++++++++++++++
3 files changed, 17 insertions(+), 2 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:23
Otherwise we are completely ignoring the --cur argument.
The issue can be tested with:
git clone --config=branch.<tab>
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:23
__gitcomp automatically adds a suffix, but __gitcomp_nl and others
don't, we need to specify a space by default.
Can be tested with:
git config branch.autoSetupMe<tab>
This fix only works for versions of bash greater than 4.0, before that
"local sfx" creates an empty string, therefore the unset expansion
doesn't work. The same happens in zsh.
Therefore we don't add the test for that for now.
The correct fix for all shells requires semantic changes in __gitcomp,
but that can be done later.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:24
By default COMP_WORDBREAKS includes =, so it's not realistic to test for
a prefix that almost never will be there.
No functional changes.
Signed-off-by: Felipe Contreras <redacted>
---
t/t9902-completion.sh | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
@@ -287,8 +287,7 @@ _get_comp_words_by_ref ()}fi-# Fills the COMPREPLY array with prefiltered words without any additional-# processing.+# Appends prefiltered words to COMPREPLY without any additional processing.# Callers must take care of providing only words that match the current word# to be completed and adding any prefix and/or suffix (trailing space!), if# necessary.
@@ -301,19 +300,6 @@ __gitcomp_direct ()COMPREPLY+=($1)}-# Similar to __gitcomp_direct, but appends to COMPREPLY instead.-# Callers must take care of providing only words that match the current word-# to be completed and adding any prefix and/or suffix (trailing space!), if-# necessary.-# 1: List of newline-separated matching completion words, complete with-# prefix and suffix.-__gitcomp_direct_append()-{-localIFS=$'\n'--COMPREPLY+=($1)-}- __gitcompappend(){localxi=${#COMPREPLY[@]}
@@ -431,16 +417,8 @@ __gitcomp_builtin ()__gitcomp"$options"}-# Variation of __gitcomp_nl () that appends to the existing list of-# completion candidates, COMPREPLY.-__gitcomp_nl_append()-{-localIFS=$'\n'-__gitcompappend"$1""${2-}""${3-$cur}""${4- }"-}-# Generates completion reply from newline-separated possible completion words-# by appending a space to all of them.+# by appending a space to all of them. The result is appended to COMPREPLY.# It accepts 1 to 4 arguments:# 1: List of possible completion words, separated by a single newline.# 2: A prefix to be added to each possible completion word (optional).
@@ -450,7 +428,8 @@ __gitcomp_nl_append ()# appended. __gitcomp_nl(){-__gitcomp_nl_append"$@"+localIFS=$'\n'+__gitcompappend"$1""${2-}""${3-$cur}""${4- }"}# Fills the COMPREPLY array with prefiltered paths without any additional
@@ -75,6 +75,12 @@ run_completion ()__git_wrap__git_main&&print_comp}+run_func()+{+local-aCOMPREPLY&&+"$@"&&print_comp+}+# Test high-level completion# Arguments are:# 1: typed text so far (cur)
@@ -547,7 +552,7 @@ test_expect_success '__gitcomp - equal skip' '' test_expect_success'__gitcomp - doesnt fail because of invalid variable name''-__gitcomp"$invalid_variable_name"+run_func__gitcomp"$invalid_variable_name"'read-r-d""refs<<-\EOF
@@ -586,7 +591,7 @@ test_expect_success '__gitcomp_nl - no suffix' '' test_expect_success'__gitcomp_nl - doesnt fail because of invalid variable name''-__gitcomp_nl"$invalid_variable_name"+run_func__gitcomp_nl"$invalid_variable_name"' test_expect_success'__git_remotes - list remotes from $GIT_DIR/remotes and from config file''
@@ -1776,8 +1769,7 @@ test_path_completion ()# unusual characters in path names. By requesting only# untracked files we do not have to bother adding any# paths to the index in those tests.-__git_complete_index_file--others&&-print_comp+run_func__git_complete_index_file--others)&&test_cmpexpectedout}
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:24
Upstream commit e1e00089da fixed the issue for Bash, but not for Zsh.
When we are typing configurations an = at the end signifies we still
want to type the value.
Can be tested with:
git -c log.d<tab>
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.zsh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:24
It's not possible for $cur_ to have anything more than --no- at this
point, so there's no need to add a suffix, nor check anything else.
All we are doing is checking that $cur_ matches --no, and adding a
completion if so.
This way the code reflects what we are doing.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 5 ++---
contrib/completion/git-completion.zsh | 2 +-
2 files changed, 3 insertions(+), 4 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:25
We know the prefix is already '--no-', there's no need to check for the
first '--'.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 2 +-
contrib/completion/git-completion.zsh | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:25
So we don't have to set it every time.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.zsh | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:27
Once the correct suffix in __git_complete_config_variable_name() is set,
we can add the test again.
Signed-off-by: Felipe Contreras <redacted>
---
t/t9902-completion.sh | 7 +++++++
1 file changed, 7 insertions(+)
@@ -310,12 +310,6 @@ __gitcompappend ()done}-__gitcompadd()-{-COMPREPLY=()-__gitcompappend"$@"-}-# Generates completion reply, appending a space to possible completion words,# if necessary.# It accepts 1 to 4 arguments:
@@ -429,7 +423,7 @@ __gitcomp_builtin () __gitcomp_nl(){localIFS=$'\n'-__gitcompappend"$1""${2-}""${3-$cur}""${4- }"+__gitcompadd"$1""${2-}""${3-$cur}""${4- }"}# Fills the COMPREPLY array with prefiltered paths without any additional
@@ -442,7 +436,7 @@ __gitcomp_file_direct (){localIFS=$'\n'-COMPREPLY=($1)+COMPREPLY+=($1)# use a hack to enable file mode in bash < 4compopt-ofilenames+onospace2>/dev/null||
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:29
There's no point in adding a suffix after a suffix.
If a suffix is provided, we add it, if not, then the default heuristic
is used.
There's no functional change since most callers don't specify a suffix,
and the ones that do use an =, which by default doesn't add an
additional suffix.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 17 ++++++++++-------
contrib/completion/git-completion.zsh | 18 +++++++++++-------
2 files changed, 21 insertions(+), 14 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:29
It does a lot more than what is stated now.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
@@ -310,8 +310,7 @@ __gitcompadd ()done}-# Generates completion reply, appending a space to possible completion words,-# if necessary.+# Creates completion replies, reorganizing options and adding suffixes as needed.# It accepts 1 to 4 arguments:# 1: List of possible completion words.# 2: A prefix to be added to each possible completion word (optional).
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:30
They support both '--git-dir=value' and '--git-dir value'. Fix the
arguments to support both.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.zsh | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
@@ -217,15 +217,15 @@ __git_zsh_main ()_arguments-C\'(-p --paginate --no-pager)'{-p,--paginate}'[pipe all output into ''less'']'\'(-p --paginate)--no-pager[do not pipe git output into a pager]'\-'--git-dir=-[set the path to the repository]: :_directories'\+'--git-dir=[set the path to the repository]: :_directories'\'--bare[treat the repository as a bare repository]'\'(- :)--version[prints the git suite version]'\-'--exec-path=-[path to where your core git programs are installed]:: :_directories'\+'--exec-path=[path to where your core git programs are installed]:: :_directories'\'--html-path[print the path where git''s HTML documentation is installed]'\'--info-path[print the path where the Info files are installed]'\'--man-path[print the manpath (see `man(1)`) for the man pages]'\-'--work-tree=-[set the path to the working tree]: :_directories'\-'--namespace=-[set the git namespace]'\+'--work-tree=[set the path to the working tree]: :_directories'\+'--namespace=[set the git namespace]:'\'--no-replace-objects[do not use replacement refs to replace git objects]'\'(- :)--help[prints the synopsis and a list of the most commonly used commands]: :->arg'\'(-): :->command'\
@@ -228,6 +228,7 @@ __git_zsh_main ()'--namespace=[set the git namespace]:'\'--no-replace-objects[do not use replacement refs to replace git objects]'\'(- :)--help[prints the synopsis and a list of the most commonly used commands]: :->arg'\+'*-C[run as if git was started in the given path]: :_directories'\'(-): :->command'\'(-)*:: :->arg'&&return
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:33
So we can specify configurations.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.zsh | 5 +++++
1 file changed, 5 insertions(+)
@@ -232,6 +232,7 @@ __git_zsh_main ()'--no-replace-objects[do not use replacement refs to replace git objects]'\'(- :)--help[prints the synopsis and a list of the most commonly used commands]: :->arg'\'*-C[run as if git was started in the given path]: :_directories'\+'*-c[pass a configuration parameter to the command]: :->config'\'(-): :->command'\'(-)*:: :->arg'&&return
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:34
Create a new simplified version of __gitcomp for most callers, and
__gitcomp_opts for the ones that need reorganizing all the options.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 114 ++++++++++++++-----------
contrib/completion/git-completion.zsh | 8 ++
t/t9902-completion.sh | 58 ++++++-------
3 files changed, 100 insertions(+), 80 deletions(-)
@@ -310,13 +310,25 @@ __gitcompadd ()done}-# Creates completion replies, reorganizing options and adding suffixes as needed.+# Creates completion replies.# It accepts 1 to 4 arguments:# 1: List of possible completion words.# 2: A prefix to be added to each possible completion word (optional).# 3: Generate possible completion matches for this word (optional).# 4: A suffix to be appended to each possible completion word (optional). __gitcomp()+{+localIFS=$' \t\n'+__gitcompadd"$1""${2-}""${3-$cur}""${4- }"+}++# Creates completion replies, reorganizing options and adding suffixes as needed.+# It accepts 1 to 4 arguments:+# 1: List of possible completion words.+# 2: A prefix to be added to each possible completion word (optional).+# 3: Generate possible completion matches for this word (optional).+# 4: A suffix to be appended to each possible completion word (optional).+__gitcomp_opts(){localcur_="${3-$cur}"
@@ -360,7 +372,7 @@ fi# This function is equivalent to#-# __gitcomp "$(git xxx --git-completion-helper) ..."+# __gitcomp_opts "$(git xxx --git-completion-helper) ..."## except that the output is cached. Accept 1-3 arguments:# 1: the git command to execute, this is also the cache key
@@ -395,7 +407,7 @@ __gitcomp_builtin ()eval"$var=\"$options\""fi-__gitcomp"$options"+__gitcomp_opts"$options"}# Generates completion reply from newline-separated possible completion words
@@ -98,17 +98,17 @@ test_completion ()test_cmpexpectedout_sorted}-# Test __gitcomp.+# Test __gitcomp_opts.# The first argument is the typed text so far (cur); the rest are-# passed to __gitcomp. Expected output comes is read from the+# passed to __gitcomp_opts. Expected output comes is read from the# standard input, like test_completion().-test_gitcomp()+test_gitcomp_opts(){local-aCOMPREPLY&&sed-e's/Z$//'>expected&&localcur="$1"&&shift&&-__gitcomp"$@"&&+__gitcomp_opts"$@"&&print_comp&&test_cmpexpectedout}
@@ -463,8 +463,8 @@ test_expect_success '__gitcomp_direct - puts everything into COMPREPLY as-is' 'test_cmpexpectedout'-test_expect_success'__gitcomp - trailing space - options''-test_gitcomp"--re""--dry-run --reuse-message= --reedit-message=+test_expect_success'__gitcomp_opts - trailing space - options''+test_gitcomp_opts"--re""--dry-run --reuse-message= --reedit-message=--reset-author" <<-EOF--reuse-message=Z--reedit-message=Z
@@ -472,8 +472,8 @@ test_expect_success '__gitcomp - trailing space - options' 'EOF'-test_expect_success'__gitcomp - trailing space - config keys''-test_gitcomp"br""branch. branch.autosetupmerge+test_expect_success'__gitcomp_opts - trailing space - config keys''+test_gitcomp_opts"br""branch. branch.autosetupmergebranch.autosetuprebasebrowser." <<-\EOFbranch.Zbranch.autosetupmergeZ
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:35
Some __gitcomp calls should be __gitcomp_nl, and vice versa.
No functional changes.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:37
There's no point in setting COMPREPLY only to override it later, and in
fact; we don't do that.
Therefore there's no functional difference between __gitcomp_direct()
and __gitcomp_direct_append(), since __gitcomp_direct() *always*
operates on empty COMPREPLY.
The same goes for __gitcomp_nl().
This patch makes the functionality of append and non-append functions
the same.
There should be no functional changes.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:39
It's useful to specify specific suffixes for specific words.
This will be useful later on.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.zsh | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:40
So we don't have to do the same over and over.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.zsh | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:41
They are the ones that actually do the completion, put them at the top.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 270 +++++++++++++------------
1 file changed, 139 insertions(+), 131 deletions(-)
@@ -45,6 +45,145 @@# When set to "1" suggest all options, including options which are# typically hidden (e.g. '--allow-empty' for 'git commit').+# The following functions are meant to modify COMPREPLY, which should not be+# modified directly. The purpose is to localize the modifications so it's+# easier to emulate it in Zsh. Every time a new __gitcomp* function is added,+# the corresponding function should be added to Zsh.++__gitcompadd()+{+localxi=${#COMPREPLY[@]}+forxin$1;do+if[["$x"=="$3"*]];then+COMPREPLY[i++]="$2$x$4"+fi+done+}++# Creates completion replies.+# It accepts 1 to 4 arguments:+# 1: List of possible completion words.+# 2: A prefix to be added to each possible completion word (optional).+# 3: Generate possible completion matches for this word (optional).+# 4: A suffix to be appended to each possible completion word (optional).+__gitcomp()+{+localIFS=$' \t\n'+__gitcompadd"$1""${2-}""${3-$cur}""${4- }"+}++# Generates completion reply from newline-separated possible completion words+# by appending a space to all of them. The result is appended to COMPREPLY.+# It accepts 1 to 4 arguments:+# 1: List of possible completion words, separated by a single newline.+# 2: A prefix to be added to each possible completion word (optional).+# 3: Generate possible completion matches for this word (optional).+# 4: A suffix to be appended to each possible completion word instead of+# the default space (optional). If specified but empty, nothing is+# appended.+__gitcomp_nl()+{+localIFS=$'\n'+__gitcompadd"$1""${2-}""${3-$cur}""${4- }"+}++# Appends prefiltered words to COMPREPLY without any additional processing.+# Callers must take care of providing only words that match the current word+# to be completed and adding any prefix and/or suffix (trailing space!), if+# necessary.+# 1: List of newline-separated matching completion words, complete with+# prefix and suffix.+__gitcomp_direct()+{+localIFS=$'\n'++COMPREPLY+=($1)+}++# Generates completion reply with compgen from newline-separated possible+# completion filenames.+# It accepts 1 to 3 arguments:+# 1: List of possible completion filenames, separated by a single newline.+# 2: A directory prefix to be added to each possible completion filename+# (optional).+# 3: Generate possible completion matches for this word (optional).+__gitcomp_file()+{+localIFS=$'\n'++# XXX does not work when the directory prefix contains a tilde,+# since tilde expansion is not applied.+# This means that COMPREPLY will be empty and Bash default+# completion will be used.+__gitcompadd"$1""${2-}""${3-$cur}"""++# use a hack to enable file mode in bash < 4+compopt-ofilenames+onospace2>/dev/null||+compgen-f/non-existing-dir/>/dev/null||+true+}++# Fills the COMPREPLY array with prefiltered paths without any additional+# processing.+# Callers must take care of providing only paths that match the current path+# to be completed and adding any prefix path components, if necessary.+# 1: List of newline-separated matching paths, complete with all prefix+# path components.+__gitcomp_file_direct()+{+localIFS=$'\n'++COMPREPLY+=($1)++# use a hack to enable file mode in bash < 4+compopt-ofilenames+onospace2>/dev/null||+compgen-f/non-existing-dir/>/dev/null||+true+}++# Creates completion replies, reorganizing options and adding suffixes as needed.+# It accepts 1 to 4 arguments:+# 1: List of possible completion words.+# 2: A prefix to be added to each possible completion word (optional).+# 3: Generate possible completion matches for this word (optional).+# 4: A suffix to be appended to each possible completion word (optional).+__gitcomp_opts()+{+localcur_="${3-$cur}"++if[["$cur_"==*=]];then+return+fi++localci=0IFS=$' \t\n'sfx+forcin$1;do+if[[$c=="--"]];then+if[["$cur_"==--no-*]];then+continue+fi++if[[--no=="$cur_"*]];then+COMPREPLY[i++]="--no-... "+fi+break+fi+if[[$c=="$cur_"*]];then+if[[-z"${4+set}"]];then+case$cin+*=|*.)sfx="";;+*)sfx=" ";;+esac+else+sfx="$4"+fi+COMPREPLY[i++]="${2-}$c$sfx"+fi+done+}++# __gitcomp functions end here+# ==============================================================================+# Discovers the path to the git repository taking any '--git-dir=<path>' and# '-C <path>' options into account and stores it in the $__git_repo_path# variable.
@@ -287,81 +426,6 @@ _get_comp_words_by_ref ()}fi-# Appends prefiltered words to COMPREPLY without any additional processing.-# Callers must take care of providing only words that match the current word-# to be completed and adding any prefix and/or suffix (trailing space!), if-# necessary.-# 1: List of newline-separated matching completion words, complete with-# prefix and suffix.-__gitcomp_direct()-{-localIFS=$'\n'--COMPREPLY+=($1)-}--__gitcompadd()-{-localxi=${#COMPREPLY[@]}-forxin$1;do-if[["$x"=="$3"*]];then-COMPREPLY[i++]="$2$x$4"-fi-done-}--# Creates completion replies.-# It accepts 1 to 4 arguments:-# 1: List of possible completion words.-# 2: A prefix to be added to each possible completion word (optional).-# 3: Generate possible completion matches for this word (optional).-# 4: A suffix to be appended to each possible completion word (optional).-__gitcomp()-{-localIFS=$' \t\n'-__gitcompadd"$1""${2-}""${3-$cur}""${4- }"-}--# Creates completion replies, reorganizing options and adding suffixes as needed.-# It accepts 1 to 4 arguments:-# 1: List of possible completion words.-# 2: A prefix to be added to each possible completion word (optional).-# 3: Generate possible completion matches for this word (optional).-# 4: A suffix to be appended to each possible completion word (optional).-__gitcomp_opts()-{-localcur_="${3-$cur}"--if[["$cur_"==*=]];then-return-fi--localci=0IFS=$' \t\n'sfx-forcin$1;do-if[[$c=="--"]];then-if[["$cur_"==--no-*]];then-continue-fi--if[[--no=="$cur_"*]];then-COMPREPLY[i++]="--no-... "-fi-break-fi-if[[$c=="$cur_"*]];then-if[[-z"${4+set}"]];then-case$cin-*=|*.)sfx="";;-*)sfx=" ";;-esac-else-sfx="$4"-fi-COMPREPLY[i++]="${2-}$c$sfx"-fi-done-}-# Clear the variables caching builtins' options when (re-)sourcing# the completion script.if[[-n${ZSH_VERSION-}]];then
@@ -410,62 +474,6 @@ __gitcomp_builtin ()__gitcomp_opts"$options"}-# Generates completion reply from newline-separated possible completion words-# by appending a space to all of them. The result is appended to COMPREPLY.-# It accepts 1 to 4 arguments:-# 1: List of possible completion words, separated by a single newline.-# 2: A prefix to be added to each possible completion word (optional).-# 3: Generate possible completion matches for this word (optional).-# 4: A suffix to be appended to each possible completion word instead of-# the default space (optional). If specified but empty, nothing is-# appended.-__gitcomp_nl()-{-localIFS=$'\n'-__gitcompadd"$1""${2-}""${3-$cur}""${4- }"-}--# Fills the COMPREPLY array with prefiltered paths without any additional-# processing.-# Callers must take care of providing only paths that match the current path-# to be completed and adding any prefix path components, if necessary.-# 1: List of newline-separated matching paths, complete with all prefix-# path components.-__gitcomp_file_direct()-{-localIFS=$'\n'--COMPREPLY+=($1)--# use a hack to enable file mode in bash < 4-compopt-ofilenames+onospace2>/dev/null||-compgen-f/non-existing-dir/>/dev/null||-true-}--# Generates completion reply with compgen from newline-separated possible-# completion filenames.-# It accepts 1 to 3 arguments:-# 1: List of possible completion filenames, separated by a single newline.-# 2: A directory prefix to be added to each possible completion filename-# (optional).-# 3: Generate possible completion matches for this word (optional).-__gitcomp_file()-{-localIFS=$'\n'--# XXX does not work when the directory prefix contains a tilde,-# since tilde expansion is not applied.-# This means that COMPREPLY will be empty and Bash default-# completion will be used.-__gitcompadd"$1""${2-}""${3-$cur}"""--# use a hack to enable file mode in bash < 4-compopt-ofilenames+onospace2>/dev/null||-compgen-f/non-existing-dir/>/dev/null||-true-}-# Execute 'git ls-files', unless the --committable option is specified, in# which case it runs 'git diff-index' to find out the files that can be# committed. It return paths relative to the directory specified in the first
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:42
We don't need the whole functionality of _get_comp_words_by_ref(), we
know exactly what we need from that function, so only do that.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 30 ++++++--------------------
t/t9902-completion.sh | 21 ++++--------------
2 files changed, 10 insertions(+), 41 deletions(-)
@@ -40,23 +40,10 @@ GIT_TESTING_PORCELAIN_COMMAND_LIST='add checkout rebase'# So let's override it with a minimal version for testing purposes. _get_comp_words_by_ref(){-while[$#-gt0];do-case"$1"in-cur)-cur=${_words[_cword]}-;;-prev)-prev=${_words[_cword-1]}-;;-words)-words=("${_words[@]}")-;;-cword)-cword=$_cword-;;-esac-shift-done+cword=$_cword+cur=${_words[cword]}+prev=${_words[cword-1]}+words=("${_words[@]}")} print_comp()
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:42
Zsh has a nice feature that allows a suffix to be automatically removed
if followed by a space.
For example:
git log --prety=
If a space is typed, the suffix '=' is removed.
But we have to set the correct prefix first.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.zsh | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:44
We don't need a separate function to do what we already know we want to
do.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 93 +++++++++++---------------
1 file changed, 39 insertions(+), 54 deletions(-)
@@ -325,21 +325,11 @@ __git_dequote ()## RELEASE: 2.x-# This function can be used to access a tokenized list of words-# on the command line:-#-# __git_reassemble_comp_words_by_ref '=:'-# if test "${words_[cword_-1]}" = -w-# then-# ...-# fi-#-# The argument should be a collection of characters from the list of-# word completion separators (COMP_WORDBREAKS) to treat as ordinary-# characters.+# This function reorganizes the words on the command line to be processed by+# the rest of the script.## This is roughly equivalent to going back in time and setting-# COMP_WORDBREAKS to exclude those characters. The intent is to+# COMP_WORDBREAKS to exclude '=' and ':'. The intent is to# make option types like --date=<type> and <rev>:<path> easy to# recognize by treating each shell word as a single token.#
@@ -347,60 +337,55 @@ __git_dequote ()# shared with other completion scripts. By the time the completion# function gets called, COMP_WORDS has already been populated so local# changes to COMP_WORDBREAKS have no effect.-#-# Output: words_, cword_, cur_.-__git_reassemble_comp_words_by_ref()+if!type_get_comp_words_by_ref>/dev/null2>&1;then+_get_comp_words_by_ref(){+localwords_cword_localexcludeijfirst+# Which word separators to exclude?-exclude="${1//[^$COMP_WORDBREAKS]}"+exclude="${COMP_WORDBREAKS//[^=:]}"cword_=$COMP_CWORDif[-z"$exclude"];thenwords_=("${COMP_WORDS[@]}")-return-fi-# List of word completion separators has shrunk;-# re-assemble words to complete.-for((i=0,j=0;i<${#COMP_WORDS[@]};i++,j++));do-# Append each nonempty word consisting of just-# word separator characters to the current word.-first=t-while-[$i-gt0]&&-[-n"${COMP_WORDS[$i]}"]&&-# word consists of excluded word separators-["${COMP_WORDS[$i]//[^$exclude]}"="${COMP_WORDS[$i]}"]-do-# Attach to the previous token,-# unless the previous token is the command name.-if[$j-ge2]&&[-n"$first"];then-((j--))-fi-first=+else+# List of word completion separators has shrunk;+# re-assemble words to complete.+for((i=0,j=0;i<${#COMP_WORDS[@]};i++,j++));do+# Append each nonempty word consisting of just+# word separator characters to the current word.+first=t+while+[$i-gt0]&&+[-n"${COMP_WORDS[$i]}"]&&+# word consists of excluded word separators+["${COMP_WORDS[$i]//[^$exclude]}"="${COMP_WORDS[$i]}"]+do+# Attach to the previous token,+# unless the previous token is the command name.+if[$j-ge2]&&[-n"$first"];then+((j--))+fi+first=+words_[$j]=${words_[j]}${COMP_WORDS[i]}+if[$i=$COMP_CWORD];then+cword_=$j+fi+if(($i<${#COMP_WORDS[@]}-1));then+((i++))+else+# Done.+break2+fi+donewords_[$j]=${words_[j]}${COMP_WORDS[i]}if[$i=$COMP_CWORD];thencword_=$jfi-if(($i<${#COMP_WORDS[@]}-1));then-((i++))-else-# Done.-return-fidone-words_[$j]=${words_[j]}${COMP_WORDS[i]}-if[$i=$COMP_CWORD];then-cword_=$j-fi-done-}+fi-if!type_get_comp_words_by_ref>/dev/null2>&1;then-_get_comp_words_by_ref()-{-localwords_cword_-__git_reassemble_comp_words_by_ref"=:"cword=$cword_cur=${words_[cword]}prev=${words_[cword-1]}
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:45
Not much different from __gitcomp_nl.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.zsh | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
@@ -341,14 +341,13 @@ __git_dequote ()if!type_get_comp_words_by_ref>/dev/null2>&1;then _get_comp_words_by_ref(){-localwords_cword_localexcludeijfirst# Which word separators to exclude?exclude="${COMP_WORDBREAKS//[^=:]}"-cword_=$COMP_CWORD+cword=$COMP_CWORDif[-z"$exclude"];then-words_=("${COMP_WORDS[@]}")+words=("${COMP_WORDS[@]}")else# List of word completion separators has shrunk;# re-assemble words to complete.
@@ -218,15 +218,16 @@ __git_zsh_main ()orig_words=(${words[@]})_arguments-C\-'(-p --paginate --no-pager)'{-p,--paginate}'[pipe all output into ''less'']'\-'(-p --paginate)--no-pager[do not pipe git output into a pager]'\-'--git-dir=[set the path to the repository]: :_directories'\-'--bare[treat the repository as a bare repository]'\+'(-p --paginate -P --no-pager)'{-p,--paginate}'[pipe all output into ''less'']'\+'(-p --paginate -P --no-pager)'{-P,--no-pager}'[do not pipe git output into a pager]'\+'(--bare)--git-dir=[set the path to the repository]: :_directories'\+'(--git-dir)--bare[treat the repository as a bare repository]'\'(- :)--version[prints the git suite version]'\-'--exec-path=[path to where your core git programs are installed]:: :_directories'\-'--html-path[print the path where git''s HTML documentation is installed]'\-'--info-path[print the path where the Info files are installed]'\-'--man-path[print the manpath (see `man(1)`) for the man pages]'\+'--exec-path=[path to where your core git programs are installed]: :_directories'\+'(- :)--exec-path[print the path where your core git programs are installed]'\+'(- :)--html-path[print the path where git''s HTML documentation is installed]'\+'(- :)--info-path[print the path where the Info files are installed]'\+'(- :)--man-path[print the manpath (see `man(1)`) for the man pages]'\'--work-tree=[set the path to the working tree]: :_directories'\'--namespace=[set the git namespace]:'\'--no-replace-objects[do not use replacement refs to replace git objects]'\
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:48
This way we can reorganize the rest of the function.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 6 ++++--
contrib/completion/git-completion.zsh | 4 ++--
2 files changed, 6 insertions(+), 4 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:49
We have to chunks of code doing exactly the same. There's no need for
that.
No functional changes.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 52 +++++++++-----------------
contrib/completion/git-completion.zsh | 52 ++++++++------------------
2 files changed, 34 insertions(+), 70 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:50
We don't match the prefix, we shouldn't match the suffix either.
There are no functional changes since all the callers that add a suffix
add an =, and if $cur_ ended with that suffix, we would return
immediately.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:53
1. We should quote the argument
2. We don't need two redirections
3. A safeguard for arguments (-a) would be good
Suggested-by: René Scharfe <redacted>
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:54
Now that we can actually pass a suffix to __gitcomp function, and it
does the right thing, all the functions can receive the same suffix.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:55
Even though the function was marked as not public, it's already used in
the wild.
We should at least test basic functionality.
Signed-off-by: Felipe Contreras <redacted>
---
t/t9902-completion.sh | 8 ++++++++
1 file changed, 8 insertions(+)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:17:58
It's only used in one place, rename it, and use it even if
bash-completion's more inefficient version of _get_comp_words_by_ref()
is available.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 184 ++++++++++++-------------
t/t9902-completion.sh | 2 +-
2 files changed, 92 insertions(+), 94 deletions(-)
@@ -38,7 +38,7 @@ GIT_TESTING_PORCELAIN_COMMAND_LIST='add checkout rebase'# We don't need this function to actually join words or do anything special.# Also, it's cleaner to avoid touching bash's internal completion variables.# So let's override it with a minimal version for testing purposes.-_get_comp_words_by_ref()+__git_get_comp_words_by_ref(){cword=$_cwordcur=${_words[cword]}
From: Felipe Contreras <hidden> Date: 2021-01-01 02:18:01
Apparently using "compadd -Q" is almost always wrong, we want zsh to add
quoting when necessary. However, if we remove the -Q option, that would
make zsh add an extra "\ " at the end of some completions.
We can manually remove the spaces from the completions that have them,
and then add the suffix with the -S option, thus there's no more need
for the -Q option.
This makes completions like "stash@{0}" complete correctly:
git stash show <tab>
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.zsh | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
@@ -84,14 +84,17 @@ __gitcomp_opts ()fiarray+=("$c$sfx")done-compadd-Q-S''-p"${2-}"-a--array&&_ret=0+compadd-S''-p"${2-}"-a--array&&_ret=0} __gitcomp_nl(){emulate-Lzsh-compadd-Q-S"${4- }"-p"${2-}"--${(f)1}&&_ret=0+# words that don't end up in space+compadd-p"${2-}"-S"${4- }"-q--${${(f)1}:#*\ }&&_ret=0+# words that end in space+compadd-p"${2-}"-S" ${4- }"-q--${${(M)${(f)1}:#*\ }% }&&_ret=0} __gitcomp_file()
@@ -346,9 +346,7 @@ _get_comp_words_by_ref ()# Which word separators to exclude?exclude="${COMP_WORDBREAKS//[^=:]}"cword=$COMP_CWORD-if[-z"$exclude"];then-words=("${COMP_WORDS[@]}")-else+if[-n"$exclude"];then# List of word completion separators has shrunk;# re-assemble words to complete.for((i=0,j=0;i<${#COMP_WORDS[@]};i++,j++));do
From: Felipe Contreras <hidden> Date: 2021-01-01 02:18:15
This makes the code more readable, and also will help when new code
wants to do similar checks.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
From: Felipe Contreras <hidden> Date: 2021-01-01 02:18:22
When __git_complete was introduced, it was meant to be temporarily, while
a proper guideline for public shell functions was established
(tentatively _GIT_complete), but since that never happened, people
in the wild started to use __git_complete, even though it was marked as
not public.
Eight years is more than enough wait, let's mark this function as
public, and make it a bit more user-friendly.
So that instead of doing:
__git_complete gk __gitk_main
The user can do:
__git_complete gk gitk
And instead of:
__git_complete gf _git_fetch
Do:
__git_complete gf git_fetch
Backwards compatibility is maintained.
Signed-off-by: Felipe Contreras <redacted>
---
contrib/completion/git-completion.bash | 40 +++++++++++++++++++++-----
t/t9902-completion.sh | 14 ++++++++-
2 files changed, 46 insertions(+), 8 deletions(-)
@@ -29,6 +29,15 @@# tell the completion to use commit completion. This also works with aliases# of form "!sh -c '...'". For example, "!sh -c ': git commit ; ... '".#+# If you have a command that is not part of git, but you would still+# like completion, you can use __git_complete:+#+# __git_complete gl git_log+#+# Or if it's a main command (i.e. git or gitk):+#+# __git_complete gk gitk+## Compatible with bash 3.2.57.## You can set the following environment variables to influence the behavior of
@@ -3429,10 +3438,7 @@ __git_func_wrap ()$1}-# Setup completion for certain functions defined above by setting common-# variables and workarounds.-# This is NOT a public function; use at your own risk.-__git_complete()+___git_complete(){localwrapper="__git_wrap${2}"eval"$wrapper () { __git_func_wrap $2 ; }"
@@ -3440,13 +3446,33 @@ __git_complete ()||complete-odefault-onospace-F$wrapper$1}-__git_completegit__git_main-__git_completegitk__gitk_main+# Setup the completion for git commands+# 1: command or alias+# 2: function to call (e.g. `git`, `gitk`, `git_fetch`)+__git_complete()+{+localfunc++if__git_have_func$2;then+func=$2+elif__git_have_func__$2_main;then+func=__$2_main+elif__git_have_func_$2;then+func=_$2+else+echo"ERROR: could not find function '$2'"1>&2+return1+fi+___git_complete$1$func+}++___git_completegit__git_main+___git_completegitk__gitk_main# The following are necessary only for Cygwin, and only are needed# when the user has tab-completed the executable name and consequently# included the '.exe' suffix.#if["$OSTYPE"=cygwin];then-__git_completegit.exe__git_main+___git_completegit.exe__git_mainfi