From: "D. Ben Knoble via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Junio Hamano <gitster@pobox.com>,
Philippe Blain <levraiphilippeblain@gmail.com>,
"D. Ben Knoble" <ben.knoble+github@gmail.com>,
"D. Ben Knoble" <ben.knoble+github@gmail.com>
Subject: [PATCH v3] completion: repair config completion for Zsh
Date: Mon, 06 Jan 2025 21:47:06 +0000 [thread overview]
Message-ID: <pull.1860.v3.git.git.1736200026899.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1860.v2.git.git.1736002073641.gitgitgadget@gmail.com>
From: "D. Ben Knoble" <ben.knoble+github@gmail.com>
Commit 1e0ee4087e (completion: add and use
__git_compute_first_level_config_vars_for_section, 2024-02-10) uses an
indirect variable syntax that is only valid for Bash, but the Zsh
completion code relies on the Bash completion code to function. Zsh
supports a different indirect variable expansion using ${(P)var}, but in
`emulate ksh` mode does not support Bash's ${!var}.
This manifests as completing strange config options like
"__git_first_level_config_vars_for_section_remote" as a choice for the
command line
git config set remote.
Using Zsh's C-x ? _complete_debug widget with the cursor at the end of
that command line captures a trace, in which we see (some details
elided):
+__git_complete_config_variable_name:7> __git_compute_first_level_config_vars_for_section remote
+__git_compute_first_level_config_vars_for_section:7> local section=remote
+__git_compute_first_level_config_vars_for_section:7> __git_compute_config_vars
+__git_compute_config_vars:7> test -n $'add.ignoreErrors\nadvice.addEmbeddedRepo\nadvice.addEmptyPathspec\nadvice.addIgnoredFile[…]'
+__git_compute_first_level_config_vars_for_section:7> local this_section=__git_first_level_config_vars_for_section_remote
+__git_compute_first_level_config_vars_for_section:7> test -n __git_first_level_config_vars_for_section_remote
+__git_complete_config_variable_name:7> local this_section=__git_first_level_config_vars_for_section_remote
+__git_complete_config_variable_name:7> __gitcomp_nl_append __git_first_level_config_vars_for_section_remote remote. '' ' '
+__gitcomp_nl_append:7> __gitcomp_nl __git_first_level_config_vars_for_section_remote remote. '' ' '
+__gitcomp_nl:7> emulate -L zsh
+__gitcomp_nl:7> compset -P '*[=:]'
+__gitcomp_nl:7> compadd -Q -S ' ' -p remote. -- __git_first_level_config_vars_for_section_remote
We perform the test for __git_compute_config_vars correctly, but the
${!this_section} references are not expanded as expected.
Instead, portably expand indirect references through the new
__git_indirect. Contrary to some versions you might find online [1],
this version avoids echo non-portabilities [2] [3] and correctly quotes
the indirect expansion after eval (so that the result is not split or
globbed before being handed to printf).
[1]: https://unix.stackexchange.com/a/41409/301073
[2]: https://askubuntu.com/questions/715765/mysterious-behavior-of-echo-command#comment1056038_715769
[3]: https://mywiki.wooledge.org/CatEchoLs
The following demo program demonstrates how this works:
b=1
indirect() {
eval printf '%s' "\"\$$1\""
}
f() {
# Comment this out to see that it works for globals, too. Or, use
# a value with spaces like '2 3 4' to see how it handles those.
local b=2
local a=b
test -n "$(indirect $a)" && echo nice
}
f
When placed in a file "demo", then both
bash -x demo
and
zsh -xc 'emulate ksh -c ". ./demo"' |& tail
provide traces showing that "$(indirect $a)" produces 2 (or 1, with the
global, or "2 3 4" as a single string, etc.).
Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
Acked-by: Philippe Blain <levraiphilippeblain@gmail.com>
---
completion: repair config completion for Zsh
With apologies to both CC'd if I've misunderstood the flow in
https://git-scm.com/docs/SubmittingPatches#_choosing_your_reviewers or
Phillipe's comments on v1.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1860%2Fbenknoble%2Ffix-zsh-config-completion-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1860/benknoble/fix-zsh-config-completion-v3
Pull-Request: https://github.com/git/git/pull/1860
Range-diff vs v2:
1: daee7636106 ! 1: 13a42324658 completion: repair config completion for Zsh
@@ Commit message
global, or "2 3 4" as a single string, etc.).
Signed-off-by: D. Ben Knoble <ben.knoble+github@gmail.com>
+ Acked-by: Philippe Blain <levraiphilippeblain@gmail.com>
## contrib/completion/git-completion.bash ##
@@ contrib/completion/git-completion.bash: __git_compute_config_vars_all ()
contrib/completion/git-completion.bash | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index b3b6aa3bae2..413911be3be 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2737,12 +2737,17 @@ __git_compute_config_vars_all ()
__git_config_vars_all="$(git --no-pager help --config)"
}
+__git_indirect()
+{
+ eval printf '%s' "\"\$$1\""
+}
+
__git_compute_first_level_config_vars_for_section ()
{
local section="$1"
__git_compute_config_vars
local this_section="__git_first_level_config_vars_for_section_${section}"
- test -n "${!this_section}" ||
+ test -n "$(__git_indirect "${this_section}")" ||
printf -v "__git_first_level_config_vars_for_section_${section}" %s \
"$(echo "$__git_config_vars" | awk -F. "/^${section}\.[a-z]/ { print \$2 }")"
}
@@ -2752,7 +2757,7 @@ __git_compute_second_level_config_vars_for_section ()
local section="$1"
__git_compute_config_vars_all
local this_section="__git_second_level_config_vars_for_section_${section}"
- test -n "${!this_section}" ||
+ test -n "$(__git_indirect "${this_section}")" ||
printf -v "__git_second_level_config_vars_for_section_${section}" %s \
"$(echo "$__git_config_vars_all" | awk -F. "/^${section}\.</ { print \$3 }")"
}
@@ -2907,7 +2912,7 @@ __git_complete_config_variable_name ()
local section="${pfx%.*.}"
__git_compute_second_level_config_vars_for_section "${section}"
local this_section="__git_second_level_config_vars_for_section_${section}"
- __gitcomp "${!this_section}" "$pfx" "$cur_" "$sfx"
+ __gitcomp "$(__git_indirect "${this_section}")" "$pfx" "$cur_" "$sfx"
return
;;
branch.*)
@@ -2917,7 +2922,7 @@ __git_complete_config_variable_name ()
__gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")"
__git_compute_first_level_config_vars_for_section "${section}"
local this_section="__git_first_level_config_vars_for_section_${section}"
- __gitcomp_nl_append "${!this_section}" "$pfx" "$cur_" "${sfx:- }"
+ __gitcomp_nl_append "$(__git_indirect "${this_section}")" "$pfx" "$cur_" "${sfx:- }"
return
;;
pager.*)
@@ -2934,7 +2939,7 @@ __git_complete_config_variable_name ()
__gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "."
__git_compute_first_level_config_vars_for_section "${section}"
local this_section="__git_first_level_config_vars_for_section_${section}"
- __gitcomp_nl_append "${!this_section}" "$pfx" "$cur_" "${sfx:- }"
+ __gitcomp_nl_append "$(__git_indirect "${this_section}")" "$pfx" "$cur_" "${sfx:- }"
return
;;
submodule.*)
@@ -2944,7 +2949,7 @@ __git_complete_config_variable_name ()
__gitcomp_nl "$(__git config -f "$(__git rev-parse --show-toplevel)/.gitmodules" --get-regexp 'submodule.*.path' | awk -F. '{print $2}')" "$pfx" "$cur_" "."
__git_compute_first_level_config_vars_for_section "${section}"
local this_section="__git_first_level_config_vars_for_section_${section}"
- __gitcomp_nl_append "${!this_section}" "$pfx" "$cur_" "${sfx:- }"
+ __gitcomp_nl_append "$(__git_indirect "${this_section}")" "$pfx" "$cur_" "${sfx:- }"
return
;;
*.*)
base-commit: 306ab352f4e98f6809ce52fc4e5d63fb947d0635
--
gitgitgadget
next prev parent reply other threads:[~2025-01-06 21:47 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-30 0:00 [PATCH] completion: repair config completion for Zsh D. Ben Knoble via GitGitGadget
2025-01-03 17:20 ` Philippe Blain
2025-01-03 18:07 ` D. Ben Knoble
2025-01-04 14:47 ` [PATCH v2] " D. Ben Knoble via GitGitGadget
2025-01-06 21:47 ` D. Ben Knoble via GitGitGadget [this message]
2025-01-07 1:23 ` [PATCH v3] " Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.1860.v3.git.git.1736200026899.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=ben.knoble+github@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=levraiphilippeblain@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).