{"thread":{"id":"58376","subject":"[PATCH 01/51] test: completion add test for __git_cmd_idx","startedAt":"2022-08-30T09:31:46Z","lastAt":"2022-08-30T09:35:57Z","messageCount":52,"participants":["Felipe Contreras"],"isPatch":true,"patchVersion":1,"patchTotal":51},"messages":[{"id":"462133","messageId":"20220830093138.1581538-1-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":null,"subject":"[PATCH 00/51] completion: revamp","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:47Z","receivedAt":"2022-08-30T09:31:46Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"This patch series revamps the completion code to git-completion 1.4.\n\nI used to send this series minimizing the delta to git upstream in order\nto maximize the chances of it being merged, but it has not received any\nfeedback since the first time it was sent in 2020 [1], so it is safe to\nsay upstream has zero interest in getting this merged. It makes no sense\nfor me to do extra work to maximize the chances of something that will\nnever happen.\n\nTherefore this series starts with the most intrusive change:\nzsh completion tests.\n\nFor several years git-completion has been running zsh completion tests\nto make sure everything works correctly, not only for bash, but also for\nzsh.\n\nThe zsh code delta between upstream and git-completion results in 14\ntests now passing. The new patch series makes that clear now.\n\nHere's a summary of the differences between upstream and git-completion:\n\n * Fixed alias regression\n * Make tests work when user has configured GIT_PS1_* variables\n * Enable colors in bash without prompt command\n * Fix suboptions for zsh\n * Fix COMP_WORDBREAKS handling\n * Fix main option handling for zsh\n * Fix -C handling for zsh\n * Fix -c handling for zsh\n * Fix generic completions for zsh\n * Fix configurations with value for zsh (e1e00089da)\n * Fix option relationships for zsh\n * Add improved removable suffix for zsh\n * Plenty of reorganizations and cleanups\n\nFor more information check [2].\n\nCheers.\n\n[1] https://lore.kernel.org/git/20201110212136.870769-1-felipe.contreras@gmail.com/\n[2] https://github.com/felipec/git-completion\n\nFelipe Contreras (50):\n  test: completion add test for __git_cmd_idx\n  test: add zsh completion tests\n  completion: fix __git_cmd_idx regression for zsh\n  completion: bash: trivial cleanup\n  completion: zsh: add higher-priority location\n  zsh: simplify realpath dirname idiom\n  test: reset environment variables\n  completion: prompt: use generic colors\n  completion: fix for suboptions with value\n  completion: zsh: trivial improvement\n  completion: bash: do not modify COMP_WORDBREAKS\n  test: completion: fix currently typed words\n  test: completion: switch __gitcomp_nl prefix test\n  test: completion: add run_func() helper\n  completion: bash: remove non-append functionality\n  completion: bash: get rid of _append() functions\n  completion: bash: get rid of any non-append code\n  completion: zsh: fix options with arguments\n  completion: zsh: expand --git-dir file argument\n  completion: zsh: add support for general -C opts\n  completion: zsh: fix for undefined completions\n  completion: zsh: add support for general -c opts\n  completion: zsh: fix extra space on foo=\n  completion: zsh: add excluded options\n  completion: zsh: always set compset\n  completion: factor out check in __gitcomp\n  completion: simplify equal suffix check\n  completion: refactor __gitcomp\n  completion: simplify __gitcomp\n  completion: bash: change suffix check in __gitcomp\n  completion: improve __gitcomp suffix code\n  test: completion: add missing test\n  completion: bash: simplify config_variable_name\n  completion: bash: improve __gitcomp description\n  completion: add __gitcomp_opts\n  completion: bash: cleanup __gitcomp* invocations\n  completion: bash: shuffle __gitcomp functions\n  completion: zsh: simplify __gitcomp_direct\n  completion: zsh: shuffle __gitcomp* functions\n  completion: zsh: fix direct quoting\n  completion: zsh: add elements individually in __gitcomp_opts\n  completion: zsh: add __gitcompadd helper\n  completion: zsh: add correct removable suffix\n  completion: bash: simplify _get_comp_words_by_ref()\n  completion: bash: refactor _get_comp_words_by_ref()\n  completion: bash: cleanup _get_comp_words_by_ref()\n  completion: bash: trivial cleanup\n  completion: bash: rename _get_comp_words_by_ref()\n  zsh: remove version\n  completion: bash: trivial grammar fix\n\nMichael Bianco (1):\n  zsh: resolve symlink of script\n\n contrib/completion/git-completion.bash |  637 ++++++-------\n contrib/completion/git-completion.zsh  |  146 ++-\n contrib/completion/git-prompt.sh       |   19 +-\n t/t9902-completion.sh                  |  159 ++--\n t/t9903-bash-prompt.sh                 |   16 +-\n t/t9904-zsh-completion.sh              | 1137 ++++++++++++++++++++++++\n t/t9904/.gitignore                     |    1 +\n t/t9904/.zshrc                         |   50 ++\n t/t9904/_git                           |    1 +\n t/t9904/completion                     |   11 +\n 10 files changed, 1649 insertions(+), 528 deletions(-)\n create mode 100755 t/t9904-zsh-completion.sh\n create mode 100644 t/t9904/.gitignore\n create mode 100644 t/t9904/.zshrc\n create mode 120000 t/t9904/_git\n create mode 100755 t/t9904/completion\n\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462132","messageId":"20220830093138.1581538-2-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 01/51] test: completion add test for __git_cmd_idx","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:48Z","receivedAt":"2022-08-30T09:31:48Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"When __git_func_wrap was fixed to set correctly __git_cmd_idx in\ncea232194d (completion: bash: fix late declaration of __git_cmd_idx,\n2021-06-18) no test was added, therefore we could hit the same bug in\nthe future.\n\nTo ensure that doesn't happen add a test which adds an alias for 'git\nadd' with __git_complete, and then pretend the user typed this alias.\n\nTo make sure __git_cmd_idx is correct we add the --update option to\nensure the result of __git_find_on_cmdline (which uses __git_cmd_idx) is\ncorrect. When __git_cmd_idx isn't correct __git_find_on_cmdline fails,\nand therefore the --update option isn't interpreted correctly.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n t/t9902-completion.sh | 9 +++++++++\n 1 file changed, 9 insertions(+)\n\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 43de868b80..8cc30448c7 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -2659,4 +2659,13 @@ test_expect_success '__git_complete' '\n \ttest_must_fail __git_complete ga missing\n '\n \n+test_expect_success '__git_complete has correct __git_cmd_idx' '\n+\t__git_complete ga _git_add &&\n+\techo modified > file1 &&\n+\ttouch file3 &&\n+\t_words=(ga --update f) _cword=2 &&\n+\t__git_wrap_git_add &&\n+\ttest \"${COMPREPLY[*]}\" = \"file1\"\n+'\n+\n test_done\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462134","messageId":"20220830093138.1581538-4-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 03/51] completion: fix __git_cmd_idx regression for zsh","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:50Z","receivedAt":"2022-08-30T09:31:55Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"The commit 59d85a2a05 (git-completion.bash: use $__git_cmd_idx in more\nplaces, 2021-04-22) caused a regression when using __git_complete and a\ncommand relies on __git_cmd_idx. This was fixed in cea232194d\n(completion: bash: fix late declaration of __git_cmd_idx, 2021-06-18)\nbut only for bash.\n\nWe need the function wrapper (__git_func_wrap in bash and _git in zsh)\nto define __git_cmd_idx.\n\nOtherwise the equivalent of __git_complete in zsh fails:\n\n  compdef _git ga=git_add\n  ga <tab>\n  ga __git_find_on_cmdline:[:14: unknown condition: -lt\n\nReported-by: Harrison McCullough <mccullough.harrison@gmail.com>\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 2 +-\n t/t9904-zsh-completion.sh             | 6 ++++++\n 2 files changed, 7 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex cac6f61881..a1f2d27817 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -271,7 +271,7 @@ __git_zsh_main ()\n _git ()\n {\n \tlocal _ret=1\n-\tlocal cur cword prev\n+\tlocal cur cword prev __git_cmd_idx=0\n \n \tcur=${words[CURRENT]}\n \tprev=${words[CURRENT-1]}\ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nindex 5179b2dc76..656eaf77ab 100755\n--- a/t/t9904-zsh-completion.sh\n+++ b/t/t9904-zsh-completion.sh\n@@ -1121,4 +1121,10 @@ test_expect_failure 'options with value' '\n \tEOF\n '\n \n+test_expect_success 'main sets correct __git_cmd_idx' '\n+\techo modified > file1 &&\n+\ttouch file3 &&\n+\ttest_completion \"compdef _git ga=git_add${LF}ga --update f\" \"file1\"\n+'\n+\n test_done\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462135","messageId":"20220830093138.1581538-3-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 02/51] test: add zsh completion tests","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:49Z","receivedAt":"2022-08-30T09:31:58Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"zsh's completion system is very advanced, but that comes with a\ndisadvantage: there is no easy way to dump the completions. The simplest\nway of doing that is printing them to stdout in a certain format, and\nthen use the zpty module to parse that format and actually print them.\n\nThere is no easier way.\n\nWe also have to simulate `compadd` in order to output the list of\ncompletions in a way that is similar to the bash completion tests.\n\nThe resulting test scripts is very close to the bash completion test\nscript, except some tests don't make sense, and others require minor\nmodifications.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n t/t9904-zsh-completion.sh | 1124 +++++++++++++++++++++++++++++++++++++\n t/t9904/.gitignore        |    1 +\n t/t9904/.zshrc            |   50 ++\n t/t9904/_git              |    1 +\n t/t9904/completion        |   11 +\n 5 files changed, 1187 insertions(+)\n create mode 100755 t/t9904-zsh-completion.sh\n create mode 100644 t/t9904/.gitignore\n create mode 100644 t/t9904/.zshrc\n create mode 120000 t/t9904/_git\n create mode 100755 t/t9904/completion\n\ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nnew file mode 100755\nindex 0000000000..5179b2dc76\n--- /dev/null\n+++ b/t/t9904-zsh-completion.sh\n@@ -0,0 +1,1124 @@\n+#!/bin/bash\n+#\n+# Copyright (c) 2012-2022 Felipe Contreras\n+#\n+\n+test_description='test zsh completion'\n+\n+. ./lib-bash.sh\n+\n+if ! command -v zsh > /dev/null 2>&1; then\n+\tskip_all='skipping completion zsh tests: zsh not available'\n+\ttest_done\n+fi\n+\n+export GIT_BUILD_DIR\n+\n+run_completion ()\n+{\n+\t\"$TEST_DIRECTORY/t9904/completion\" \"$1\" > out\n+\t[[ -s out ]] || { echo > out ; }\n+}\n+\n+# Test high-level completion\n+# Arguments are:\n+# 1: typed text so far (cur)\n+# 2: expected completion\n+test_completion ()\n+{\n+\tif test $# -gt 1\n+\tthen\n+\t\tprintf '%s\\n' \"$2\" >expected\n+\telse\n+\t\tsed -e 's/Z$//' |sort >expected\n+\tfi &&\n+\trun_completion \"$1\" &&\n+\tsort -u out >out_sorted &&\n+\ttest_cmp expected out_sorted\n+}\n+\n+# Test __gitcomp.\n+# The first argument is the typed text so far (cur); the rest are\n+# passed to __gitcomp.  Expected output comes is read from the\n+# standard input, like test_completion().\n+test_gitcomp ()\n+{\n+\tsed -e 's/Z$//' >expected &&\n+\tlocal cur=\"$1\" &&\n+\tshift &&\n+\trun_completion \"git func __gitcomp $(printf \"%q \" \"$@\") $cur\" &&\n+\ttest_cmp expected out\n+}\n+\n+# Test __gitcomp_nl\n+# Arguments are:\n+# 1: current word (cur)\n+# -: the rest are passed to __gitcomp_nl\n+test_gitcomp_nl ()\n+{\n+\tsed -e \"s/Z$//\" >expected &&\n+\tlocal cur=\"$1\" &&\n+\tshift &&\n+\trun_completion \"git func __gitcomp_nl $(printf \"%q \" \"$@\") $cur\" &&\n+\ttest_cmp expected out\n+}\n+\n+actual=\"$TRASH_DIRECTORY/actual\"\n+\n+if test_have_prereq MINGW\n+then\n+\tROOT=\"$(pwd -W)\"\n+else\n+\tROOT=\"$(pwd)\"\n+fi\n+\n+test_expect_success 'setup for __git_find_repo_path/__gitdir tests' '\n+\tmkdir -p subdir/subsubdir &&\n+\tmkdir -p non-repo &&\n+\tgit init -b main otherrepo\n+'\n+\n+test_expect_success '__gitcomp - trailing space - options' '\n+\ttest_gitcomp \"--re\" \"--dry-run --reuse-message= --reedit-message=\n+\t\t--reset-author\" <<-EOF\n+\t--reuse-message=Z\n+\t--reedit-message=Z\n+\t--reset-author Z\n+\tEOF\n+'\n+\n+test_expect_success '__gitcomp - trailing space - config keys' '\n+\ttest_gitcomp \"br\" \"branch. branch.autosetupmerge\n+\t\tbranch.autosetuprebase browser.\" <<-\\EOF\n+\tbranch.Z\n+\tbranch.autosetupmerge Z\n+\tbranch.autosetuprebase Z\n+\tbrowser.Z\n+\tEOF\n+'\n+\n+test_expect_success '__gitcomp - option parameter' '\n+\ttest_gitcomp \"--strategy=re\" \"octopus ours recursive resolve subtree\" \\\n+\t\t\"\" \"re\" <<-\\EOF\n+\trecursive Z\n+\tresolve Z\n+\tEOF\n+'\n+\n+test_expect_failure '__gitcomp - prefix' '\n+\ttest_gitcomp \"branch.me\" \"remote merge mergeoptions rebase\" \\\n+\t\t\"branch.maint.\" \"me\" <<-\\EOF\n+\tbranch.maint.merge Z\n+\tbranch.maint.mergeoptions Z\n+\tEOF\n+'\n+\n+test_expect_failure '__gitcomp - suffix' '\n+\ttest_gitcomp \"branch.me\" \"master maint next seen\" \"branch.\" \\\n+\t\t\"ma\" \".\" <<-\\EOF\n+\tbranch.master.Z\n+\tbranch.maint.Z\n+\tEOF\n+'\n+\n+test_expect_success '__gitcomp - ignore optional negative options' '\n+\ttest_gitcomp \"--\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n+\t--abc Z\n+\t--def Z\n+\t--no-one Z\n+\t--no-... Z\n+\tEOF\n+'\n+\n+test_expect_success '__gitcomp - ignore/narrow optional negative options' '\n+\ttest_gitcomp \"--a\" \"--abc --abcdef --no-one -- --no-two\" <<-\\EOF\n+\t--abc Z\n+\t--abcdef Z\n+\tEOF\n+'\n+\n+test_expect_success '__gitcomp - ignore/narrow optional negative options' '\n+\ttest_gitcomp \"--n\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n+\t--no-one Z\n+\t--no-... Z\n+\tEOF\n+'\n+\n+test_expect_success '__gitcomp - expand all negative options' '\n+\ttest_gitcomp \"--no-\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n+\t--no-one Z\n+\t--no-two Z\n+\tEOF\n+'\n+\n+test_expect_success '__gitcomp - expand/narrow all negative options' '\n+\ttest_gitcomp \"--no-o\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n+\t--no-one Z\n+\tEOF\n+'\n+\n+test_expect_failure '__gitcomp - equal skip' '\n+\ttest_gitcomp \"--option=\" \"--option=\" <<-\\EOF &&\n+\n+\tEOF\n+\ttest_gitcomp \"option=\" \"option=\" <<-\\EOF\n+\n+\tEOF\n+'\n+\n+read -r -d \"\" refs <<-\\EOF\n+main\n+maint\n+next\n+seen\n+EOF\n+\n+test_expect_success '__gitcomp_nl - trailing space' '\n+\ttest_gitcomp_nl \"m\" \"$refs\" <<-EOF\n+\tmain Z\n+\tmaint Z\n+\tEOF\n+'\n+\n+test_expect_failure '__gitcomp_nl - prefix' '\n+\ttest_gitcomp_nl \"--fixup=m\" \"$refs\" \"--fixup=\" \"m\" <<-EOF\n+\t--fixup=main Z\n+\t--fixup=maint Z\n+\tEOF\n+'\n+\n+test_expect_success '__gitcomp_nl - suffix' '\n+\ttest_gitcomp_nl \"branch.ma\" \"$refs\" \"branch.\" \"ma\" \".\" <<-\\EOF\n+\tbranch.main.Z\n+\tbranch.maint.Z\n+\tEOF\n+'\n+\n+test_expect_success '__gitcomp_nl - no suffix' '\n+\ttest_gitcomp_nl \"ma\" \"$refs\" \"\" \"ma\" \"\" <<-\\EOF\n+\tmainZ\n+\tmaintZ\n+\tEOF\n+'\n+\n+test_expect_success 'setup for ref completion' '\n+\tgit commit --allow-empty -m initial &&\n+\tgit branch -M main &&\n+\tgit branch matching-branch &&\n+\tgit tag matching-tag &&\n+\t(\n+\t\tcd otherrepo &&\n+\t\tgit commit --allow-empty -m initial &&\n+\t\tgit branch -m main main-in-other &&\n+\t\tgit branch branch-in-other &&\n+\t\tgit tag tag-in-other\n+\t) &&\n+\tgit remote add other \"$ROOT/otherrepo/.git\" &&\n+\tgit fetch --no-tags other &&\n+\trm -f .git/FETCH_HEAD &&\n+\tgit init thirdrepo\n+'\n+\n+test_expect_success 'git switch - with no options, complete local branches and unique remote branch names for DWIM logic' '\n+\ttest_completion \"git switch \" <<-\\EOF\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - completes refs and unique remote branches for DWIM' '\n+\ttest_completion \"git checkout \" <<-\\EOF\n+\tHEAD Z\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with --no-guess, complete only local branches' '\n+\ttest_completion \"git switch --no-guess \" <<-\\EOF\n+\tmain Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with GIT_COMPLETION_CHECKOUT_NO_GUESS=1, complete only local branches' '\n+\tGIT_COMPLETION_CHECKOUT_NO_GUESS=1 test_completion \"git switch \" <<-\\EOF\n+\tmain Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - --guess overrides GIT_COMPLETION_CHECKOUT_NO_GUESS=1, complete local branches and unique remote names for DWIM logic' '\n+\tGIT_COMPLETION_CHECKOUT_NO_GUESS=1 test_completion \"git switch --guess \" <<-\\EOF\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - a later --guess overrides previous --no-guess, complete local and remote unique branches for DWIM' '\n+\ttest_completion \"git switch --no-guess --guess \" <<-\\EOF\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - a later --no-guess overrides previous --guess, complete only local branches' '\n+\ttest_completion \"git switch --guess --no-guess \" <<-\\EOF\n+\tmain Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with GIT_COMPLETION_NO_GUESS=1 only completes refs' '\n+\tGIT_COMPLETION_CHECKOUT_NO_GUESS=1 test_completion \"git checkout \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - --guess overrides GIT_COMPLETION_NO_GUESS=1, complete refs and unique remote branches for DWIM' '\n+\tGIT_COMPLETION_CHECKOUT_NO_GUESS=1 test_completion \"git checkout --guess \" <<-\\EOF\n+\tHEAD Z\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with --no-guess, only completes refs' '\n+\ttest_completion \"git checkout --no-guess \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - a later --guess overrides previous --no-guess, complete refs and unique remote branches for DWIM' '\n+\ttest_completion \"git checkout --no-guess --guess \" <<-\\EOF\n+\tHEAD Z\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - a later --no-guess overrides previous --guess, complete only refs' '\n+\ttest_completion \"git checkout --guess --no-guess \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with checkout.guess = false, only completes refs' '\n+\ttest_config checkout.guess false &&\n+\ttest_completion \"git checkout \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with checkout.guess = true, completes refs and unique remote branches for DWIM' '\n+\ttest_config checkout.guess true &&\n+\ttest_completion \"git checkout \" <<-\\EOF\n+\tHEAD Z\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - a later --guess overrides previous checkout.guess = false, complete refs and unique remote branches for DWIM' '\n+\ttest_config checkout.guess false &&\n+\ttest_completion \"git checkout --guess \" <<-\\EOF\n+\tHEAD Z\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - a later --no-guess overrides previous checkout.guess = true, complete only refs' '\n+\ttest_config checkout.guess true &&\n+\ttest_completion \"git checkout --no-guess \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with --detach, complete all references' '\n+\ttest_completion \"git switch --detach \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with --detach, complete only references' '\n+\ttest_completion \"git checkout --detach \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with -d, complete all references' '\n+\ttest_completion \"git switch -d \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with -d, complete only references' '\n+\ttest_completion \"git checkout -d \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with --track, complete only remote branches' '\n+\ttest_completion \"git switch --track \" <<-\\EOF\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with --track, complete only remote branches' '\n+\ttest_completion \"git checkout --track \" <<-\\EOF\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with --no-track, complete only local branch names' '\n+\ttest_completion \"git switch --no-track \" <<-\\EOF\n+\tmain Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with --no-track, complete only local references' '\n+\ttest_completion \"git checkout --no-track \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with -c, complete all references' '\n+\ttest_completion \"git switch -c new-branch \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with -C, complete all references' '\n+\ttest_completion \"git switch -C new-branch \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with -c and --track, complete all references' '\n+\ttest_completion \"git switch -c new-branch --track \" <<-EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with -C and --track, complete all references' '\n+\ttest_completion \"git switch -C new-branch --track \" <<-EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with -c and --no-track, complete all references' '\n+\ttest_completion \"git switch -c new-branch --no-track \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with -C and --no-track, complete all references' '\n+\ttest_completion \"git switch -C new-branch --no-track \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with -b, complete all references' '\n+\ttest_completion \"git checkout -b new-branch \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with -B, complete all references' '\n+\ttest_completion \"git checkout -B new-branch \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with -b and --track, complete all references' '\n+\ttest_completion \"git checkout -b new-branch --track \" <<-EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with -B and --track, complete all references' '\n+\ttest_completion \"git checkout -B new-branch --track \" <<-EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with -b and --no-track, complete all references' '\n+\ttest_completion \"git checkout -b new-branch --no-track \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with -B and --no-track, complete all references' '\n+\ttest_completion \"git checkout -B new-branch --no-track \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - for -c, complete local branches and unique remote branches' '\n+\ttest_completion \"git switch -c \" <<-\\EOF\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - for -C, complete local branches and unique remote branches' '\n+\ttest_completion \"git switch -C \" <<-\\EOF\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - for -c with --no-guess, complete local branches only' '\n+\ttest_completion \"git switch --no-guess -c \" <<-\\EOF\n+\tmain Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - for -C with --no-guess, complete local branches only' '\n+\ttest_completion \"git switch --no-guess -C \" <<-\\EOF\n+\tmain Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - for -c with --no-track, complete local branches only' '\n+\ttest_completion \"git switch --no-track -c \" <<-\\EOF\n+\tmain Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - for -C with --no-track, complete local branches only' '\n+\ttest_completion \"git switch --no-track -C \" <<-\\EOF\n+\tmain Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - for -b, complete local branches and unique remote branches' '\n+\ttest_completion \"git checkout -b \" <<-\\EOF\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - for -B, complete local branches and unique remote branches' '\n+\ttest_completion \"git checkout -B \" <<-\\EOF\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - for -b with --no-guess, complete local branches only' '\n+\ttest_completion \"git checkout --no-guess -b \" <<-\\EOF\n+\tmain Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - for -B with --no-guess, complete local branches only' '\n+\ttest_completion \"git checkout --no-guess -B \" <<-\\EOF\n+\tmain Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - for -b with --no-track, complete local branches only' '\n+\ttest_completion \"git checkout --no-track -b \" <<-\\EOF\n+\tmain Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - for -B with --no-track, complete local branches only' '\n+\ttest_completion \"git checkout --no-track -B \" <<-\\EOF\n+\tmain Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - with --orphan completes local branch names and unique remote branch names' '\n+\ttest_completion \"git switch --orphan \" <<-\\EOF\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git switch - --orphan with branch already provided completes nothing else' '\n+\ttest_completion \"git switch --orphan main \" <<-\\EOF\n+\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - with --orphan completes local branch names and unique remote branch names' '\n+\ttest_completion \"git checkout --orphan \" <<-\\EOF\n+\tbranch-in-other Z\n+\tmain Z\n+\tmain-in-other Z\n+\tmatching-branch Z\n+\tEOF\n+'\n+\n+test_expect_success 'git checkout - --orphan with branch already provided completes local refs for a start-point' '\n+\ttest_completion \"git checkout --orphan main \" <<-\\EOF\n+\tHEAD Z\n+\tmain Z\n+\tmatching-branch Z\n+\tmatching-tag Z\n+\tother/branch-in-other Z\n+\tother/main-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'teardown after ref completion' '\n+\tgit branch -d matching-branch &&\n+\tgit tag -d matching-tag &&\n+\tgit remote remove other\n+'\n+\n+test_expect_success 'basic' '\n+\trun_completion \"git \" &&\n+\t# built-in\n+\tgrep -q \"^add\\$\" out &&\n+\t# script\n+\tgrep -q \"^rebase\\$\" out &&\n+\t# plumbing\n+\t! grep -q \"^ls-files\\$\" out &&\n+\n+\trun_completion \"git r\" &&\n+\t! grep -q -v \"^r\" out\n+'\n+\n+test_expect_success 'double dash \"git\" itself' '\n+\ttest_completion \"git --\" <<-\\EOF\n+\t--paginate\n+\t--no-pager\n+\t--git-dir\n+\t--bare\n+\t--version\n+\t--exec-path\n+\t--html-path\n+\t--man-path\n+\t--info-path\n+\t--work-tree\n+\t--namespace\n+\t--no-replace-objects\n+\t--help\n+\tEOF\n+'\n+\n+test_expect_success 'double dash \"git checkout\"' '\n+\ttest_completion \"git checkout --\" <<-\\EOF\n+\t--quiet Z\n+\t--detach Z\n+\t--track Z\n+\t--orphan=Z\n+\t--ours Z\n+\t--theirs Z\n+\t--merge Z\n+\t--conflict=Z\n+\t--patch Z\n+\t--ignore-skip-worktree-bits Z\n+\t--ignore-other-worktrees Z\n+\t--recurse-submodules Z\n+\t--progress Z\n+\t--guess Z\n+\t--no-guess Z\n+\t--no-... Z\n+\t--overlay Z\n+\t--pathspec-file-nul Z\n+\t--pathspec-from-file=Z\n+\tEOF\n+'\n+\n+test_expect_success 'general options' '\n+\ttest_completion \"git --ver\" \"--version\" &&\n+\ttest_completion \"git --hel\" \"--help\" &&\n+\ttest_completion \"git --exe\" \"--exec-path\" &&\n+\ttest_completion \"git --htm\" \"--html-path\" &&\n+\ttest_completion \"git --pag\" \"--paginate\" &&\n+\ttest_completion \"git --no-p\" \"--no-pager\" &&\n+\ttest_completion \"git --git\" \"--git-dir\" &&\n+\ttest_completion \"git --wor\" \"--work-tree\" &&\n+\ttest_completion \"git --nam\" \"--namespace\" &&\n+\ttest_completion \"git --bar\" \"--bare\" &&\n+\ttest_completion \"git --inf\" \"--info-path\" &&\n+\ttest_completion \"git --no-r\" \"--no-replace-objects\"\n+'\n+\n+test_expect_failure 'general options plus command' '\n+\ttest_completion \"git --version check\" \"\" &&\n+\ttest_completion \"git --paginate check\" \"checkout\" &&\n+\ttest_completion \"git --git-dir=foo check\" \"checkout\" &&\n+\ttest_completion \"git --bare check\" \"checkout\" &&\n+\ttest_completion \"git --exec-path=foo check\" \"checkout\" &&\n+\ttest_completion \"git --html-path check\" \"\" &&\n+\ttest_completion \"git --no-pager check\" \"checkout\" &&\n+\ttest_completion \"git --work-tree=foo check\" \"checkout\" &&\n+\ttest_completion \"git --namespace=foo check\" \"checkout\" &&\n+\ttest_completion \"git --paginate check\" \"checkout\" &&\n+\ttest_completion \"git --info-path check\" \"\" &&\n+\ttest_completion \"git --no-replace-objects check\" \"checkout\" &&\n+\ttest_completion \"git --git-dir some/path check\" \"checkout\" &&\n+\ttest_completion \"git -c conf.var=value check\" \"checkout\" &&\n+\ttest_completion \"git -C some/path check\" \"checkout\" &&\n+\ttest_completion \"git --work-tree some/path check\" \"checkout\" &&\n+\ttest_completion \"git --namespace name/space check\" \"checkout\"\n+'\n+\n+test_expect_success 'git --help completion' '\n+\ttest_completion \"git --help ad\" \"add \" &&\n+\ttest_completion \"git --help core\" \"core-tutorial \"\n+'\n+\n+test_expect_success 'setup for integration tests' '\n+\techo content >file1 &&\n+\techo more >file2 &&\n+\tgit add file1 file2 &&\n+\tgit commit -m one &&\n+\tgit branch mybranch &&\n+\tgit tag mytag\n+'\n+\n+test_expect_success 'checkout completes ref names' '\n+\ttest_completion \"git checkout m\" <<-\\EOF\n+\tmain Z\n+\tmybranch Z\n+\tmytag Z\n+\tEOF\n+'\n+\n+test_expect_failure 'git -C <path> checkout uses the right repo' '\n+\ttest_completion \"git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b\" <<-\\EOF\n+\tbranch-in-other Z\n+\tEOF\n+'\n+\n+test_expect_success 'show completes all refs' '\n+\ttest_completion \"git show m\" <<-\\EOF\n+\tmain Z\n+\tmybranch Z\n+\tmytag Z\n+\tEOF\n+'\n+\n+test_expect_success '<ref>: completes paths' '\n+\ttest_completion \"git show mytag:f\" <<-\\EOF\n+\tfile1Z\n+\tfile2Z\n+\tEOF\n+'\n+\n+test_expect_success 'complete tree filename with spaces' '\n+\techo content >\"name with spaces\" &&\n+\tgit add \"name with spaces\" &&\n+\tgit commit -m spaces &&\n+\ttest_completion \"git show HEAD:nam\" <<-\\EOF\n+\tname with spacesZ\n+\tEOF\n+'\n+\n+test_expect_success 'complete tree filename with metacharacters' '\n+\techo content >\"name with \\${meta}\" &&\n+\tgit add \"name with \\${meta}\" &&\n+\tgit commit -m meta &&\n+\ttest_completion \"git show HEAD:nam\" <<-\\EOF\n+\tname with ${meta}Z\n+\tname with spacesZ\n+\tEOF\n+'\n+\n+test_expect_success PERL 'send-email' '\n+\ttest_completion \"git send-email --cov\" <<-\\EOF &&\n+\t--cover-from-description=Z\n+\t--cover-letter Z\n+\tEOF\n+\ttest_completion \"git send-email --val\" <<-\\EOF &&\n+\t--validate Z\n+\tEOF\n+\ttest_completion \"git send-email ma\" \"main \"\n+'\n+\n+test_expect_success 'complete files' '\n+\tgit init tmp && cd tmp &&\n+\ttest_when_finished \"cd .. && rm -rf tmp\" &&\n+\n+\techo \"expected\" > .gitignore &&\n+\techo \"out\" >> .gitignore &&\n+\techo \"out_sorted\" >> .gitignore &&\n+\n+\tgit add .gitignore &&\n+\ttest_completion \"git commit \" \".gitignore\" &&\n+\n+\tgit commit -m ignore &&\n+\n+\ttouch new &&\n+\ttest_completion \"git add \" \"new\" &&\n+\n+\tgit add new &&\n+\tgit commit -a -m new &&\n+\ttest_completion \"git add \" \"\" &&\n+\n+\tgit mv new modified &&\n+\techo modify > modified &&\n+\ttest_completion \"git add \" \"modified\" &&\n+\n+\tmkdir -p some/deep &&\n+\ttouch some/deep/path &&\n+\ttest_completion \"git add some/\" \"some/deep\" &&\n+\tgit clean -f some &&\n+\n+\ttouch untracked &&\n+\n+\t: TODO .gitignore should not be here &&\n+\ttest_completion \"git rm \" <<-\\EOF &&\n+\t.gitignore\n+\tmodified\n+\tEOF\n+\n+\ttest_completion \"git clean \" \"untracked\" &&\n+\n+\t: TODO .gitignore should not be here &&\n+\ttest_completion \"git mv \" <<-\\EOF &&\n+\t.gitignore\n+\tmodified\n+\tEOF\n+\n+\tmkdir dir &&\n+\ttouch dir/file-in-dir &&\n+\tgit add dir/file-in-dir &&\n+\tgit commit -m dir &&\n+\n+\tmkdir untracked-dir &&\n+\n+\t: TODO .gitignore should not be here &&\n+\ttest_completion \"git mv modified \" <<-\\EOF &&\n+\t.gitignore\n+\tdir\n+\tmodified\n+\tuntracked\n+\tuntracked-dir\n+\tEOF\n+\n+\ttest_completion \"git commit \" \"modified\" &&\n+\n+\t: TODO .gitignore should not be here &&\n+\ttest_completion \"git ls-files \" <<-\\EOF &&\n+\t.gitignore\n+\tdir\n+\tmodified\n+\tEOF\n+\n+\ttouch momified &&\n+\ttest_completion \"git add mom\" \"momified\"\n+'\n+\n+test_expect_success \"simple alias\" '\n+\ttest_config alias.co checkout &&\n+\ttest_completion \"git co m\" <<-\\EOF\n+\tmain Z\n+\tmybranch Z\n+\tmytag Z\n+\tEOF\n+'\n+\n+test_expect_success \"recursive alias\" '\n+\ttest_config alias.co checkout &&\n+\ttest_config alias.cod \"co --detached\" &&\n+\ttest_completion \"git cod m\" <<-\\EOF\n+\tmain Z\n+\tmybranch Z\n+\tmytag Z\n+\tEOF\n+'\n+\n+test_expect_success \"completion uses <cmd> completion for alias: !sh -c 'git <cmd> ...'\" '\n+\ttest_config alias.co \"!sh -c '\"'\"'git checkout ...'\"'\"'\" &&\n+\ttest_completion \"git co m\" <<-\\EOF\n+\tmain Z\n+\tmybranch Z\n+\tmytag Z\n+\tEOF\n+'\n+\n+test_expect_success 'completion uses <cmd> completion for alias: !f () { VAR=val git <cmd> ... }' '\n+\ttest_config alias.co \"!f () { VAR=val git checkout ... ; } f\" &&\n+\ttest_completion \"git co m\" <<-\\EOF\n+\tmain Z\n+\tmybranch Z\n+\tmytag Z\n+\tEOF\n+'\n+\n+test_expect_success 'completion used <cmd> completion for alias: !f() { : git <cmd> ; ... }' '\n+\ttest_config alias.co \"!f() { : git checkout ; if ... } f\" &&\n+\ttest_completion \"git co m\" <<-\\EOF\n+\tmain Z\n+\tmybranch Z\n+\tmytag Z\n+\tEOF\n+'\n+\n+test_expect_failure 'completion without explicit _git_xxx function' '\n+\ttest_completion \"git version --\" <<-\\EOF\n+\t--build-options Z\n+\t--no-build-options Z\n+\tEOF\n+'\n+\n+test_expect_failure 'complete with tilde expansion' '\n+\tgit init tmp && cd tmp &&\n+\ttest_when_finished \"cd .. && rm -rf tmp\" &&\n+\n+\ttouch ~/tmp/file &&\n+\n+\ttest_completion \"git add ~/tmp/\" \"~/tmp/file\"\n+'\n+\n+test_expect_success 'setup other remote for remote reference completion' '\n+\tgit remote add other otherrepo &&\n+\tgit fetch other\n+'\n+\n+test_expect_success 'git config - section' '\n+\ttest_completion \"git config br\" <<-\\EOF\n+\tbranch.Z\n+\tbrowser.Z\n+\tEOF\n+'\n+\n+test_expect_success 'git config - section include, includeIf' '\n+\ttest_completion \"git config inclu\" <<-\\EOF\n+\tinclude.Z\n+\tincludeIf.Z\n+\tEOF\n+'\n+\n+test_expect_success 'git config - variable name' '\n+\ttest_completion \"git config log.d\" <<-\\EOF\n+\tlog.date Z\n+\tlog.decorate Z\n+\tlog.diffMerges Z\n+\tEOF\n+'\n+\n+test_expect_success 'git config - variable name include' '\n+\ttest_completion \"git config include.p\" <<-\\EOF\n+\tinclude.path Z\n+\tEOF\n+'\n+\n+test_expect_success 'git config - value' '\n+\ttest_completion \"git config color.pager \" <<-\\EOF\n+\tfalse Z\n+\ttrue Z\n+\tEOF\n+'\n+\n+test_expect_failure 'git -c - section' '\n+\ttest_completion \"git -c br\" <<-\\EOF\n+\tbranch.Z\n+\tbrowser.Z\n+\tEOF\n+'\n+\n+test_expect_failure 'git -c - variable name' '\n+\ttest_completion \"git -c log.d\" <<-\\EOF\n+\tlog.date=Z\n+\tlog.decorate=Z\n+\tlog.diffMerges=Z\n+\tEOF\n+'\n+\n+test_expect_failure 'git -c - value' '\n+\ttest_completion \"git -c color.pager=\" <<-\\EOF\n+\tfalse Z\n+\ttrue Z\n+\tEOF\n+'\n+\n+test_expect_success 'git clone --config= - section' '\n+\ttest_completion \"git clone --config=br\" <<-\\EOF\n+\tbranch.Z\n+\tbrowser.Z\n+\tEOF\n+'\n+\n+test_expect_failure 'git clone --config= - variable name' '\n+\ttest_completion \"git clone --config=log.d\" <<-\\EOF\n+\tlog.date=Z\n+\tlog.decorate=Z\n+\tlog.diffMerges=Z\n+\tEOF\n+'\n+\n+test_expect_success 'git clone --config= - value' '\n+\ttest_completion \"git clone --config=color.pager=\" <<-\\EOF\n+\tfalse Z\n+\ttrue Z\n+\tEOF\n+'\n+\n+test_expect_failure 'options with value' '\n+\ttest_completion \"git merge -X diff-algorithm=\" <<-\\EOF\n+\n+\tEOF\n+'\n+\n+test_done\ndiff --git a/t/t9904/.gitignore b/t/t9904/.gitignore\nnew file mode 100644\nindex 0000000000..f9917e1bf9\n--- /dev/null\n+++ b/t/t9904/.gitignore\n@@ -0,0 +1 @@\n+/.zcompdump\ndiff --git a/t/t9904/.zshrc b/t/t9904/.zshrc\nnew file mode 100644\nindex 0000000000..1da11a5445\n--- /dev/null\n+++ b/t/t9904/.zshrc\n@@ -0,0 +1,50 @@\n+setopt zle\n+\n+PS1=\"<PROMPT>\"\n+fpath=($ZDOTDIR $fpath)\n+LISTMAX=1000\n+\n+autoload -U compinit && compinit -u\n+\n+zstyle ':completion:*:*:git:*' script \"$GIT_BUILD_DIR/contrib/completion/git-completion.bash\"\n+zstyle \":completion:*:default\" list-colors \"no=<NO>\" \"fi=<NO>\" \"di=<NO>\" \"sp=<SP>\" \"lc=<LC>\" \"rc=<RC>\" \"ec=<EC>\\n\"\n+zstyle ':completion:*' verbose no\n+\n+zle_complete () {\n+\tzle list-choices\n+\tzle kill-whole-line\n+\tprint \"<END-CHOICES>\"\n+}\n+zle -N zle_complete\n+bindkey \"^I\" zle_complete\n+\n+functions[_default]=:\n+\n+compadd () {\n+\tlocal pfx sfx\n+\tlocal -a args\n+\n+\tif (( ${@[(I)-a|-d]} )); then\n+\t\tbuiltin compadd -V unsorted \"$@\"\n+\telse\n+\t\twhile (($#)); do\n+\t\t\tcase \"$1\" in\n+\t\t\t-p) pfx=\"$2\" ; shift 2 ;;\n+\t\t\t-S) sfx=\"$2\" ; shift 2 ;;\n+\t\t\t--) args+=($1) ; shift ; break ;;\n+\t\t\t*) args+=(\"$1\") ; shift ;;\n+\t\t\tesac\n+\t\tdone\n+\n+\t\twhile (($#)); do\n+\t\t\targs+=(${pfx}$1${sfx})\n+\t\t\tshift\n+\t\tdone\n+\n+\t\tbuiltin compadd -V unsorted -S '' \"${args[@]}\"\n+\tfi\n+}\n+\n+_git_func () {\n+\teval ${words[2,-2]}\n+}\ndiff --git a/t/t9904/_git b/t/t9904/_git\nnew file mode 120000\nindex 0000000000..92d0240ac4\n--- /dev/null\n+++ b/t/t9904/_git\n@@ -0,0 +1 @@\n+../../contrib/completion/git-completion.zsh\n\\ No newline at end of file\ndiff --git a/t/t9904/completion b/t/t9904/completion\nnew file mode 100755\nindex 0000000000..2927b81f6a\n--- /dev/null\n+++ b/t/t9904/completion\n@@ -0,0 +1,11 @@\n+#!/bin/zsh\n+\n+zmodload zsh/zpty\n+\n+zpty zsh \"ZDOTDIR=$(dirname $0) zsh -o NO_GLOBAL_RCS\"\n+zpty -n -w zsh \"$1\"$'\\t'\n+zpty -r zsh log '*<END-CHOICES>'\n+\n+for x in ${(M)${(f)log}:#*'<LC><NO>'*}; do\n+\tprint -- \"${${x%'<EC>'*}#*'<RC>'}\"\n+done\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462136","messageId":"20220830093138.1581538-5-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 04/51] completion: bash: trivial cleanup","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:51Z","receivedAt":"2022-08-30T09:32:00Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 3 +--\n 1 file changed, 1 insertion(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex ba5c395d2d..2df51ed946 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -3545,8 +3545,7 @@ fi\n \n __git_func_wrap ()\n {\n-\tlocal cur words cword prev\n-\tlocal __git_cmd_idx=0\n+\tlocal cur words cword prev __git_cmd_idx=0\n \t_get_comp_words_by_ref -n =: cur words cword prev\n \t$1\n }\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462137","messageId":"20220830093138.1581538-6-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 05/51] completion: zsh: add higher-priority location","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:52Z","receivedAt":"2022-08-30T09:32:11Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"bash-completion looks in /usr/local/share first, we should too.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex a1f2d27817..535cf03176 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -35,6 +35,7 @@ if [ -z \"$script\" ]; then\n \tlocations=(\n \t\t\"$(dirname ${funcsourcetrace[1]%:*})\"/git-completion.bash\n \t\t\"$HOME/.local/share/bash-completion/completions/git\"\n+\t\t'/usr/local/share/bash-completion/completions/git'\n \t\t\"$bash_completion/git\"\n \t\t'/etc/bash_completion.d/git' # old debian\n \t\t)\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462138","messageId":"20220830093138.1581538-10-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 09/51] completion: prompt: use generic colors","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:56Z","receivedAt":"2022-08-30T09:32:12Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"When the prompt command mode was introduced in 1bfc51ac81 (Allow\n__git_ps1 to be used in PROMPT_COMMAND, 2012-10-10) the assumption was\nthat it was necessary in order to properly add colors to PS1 in bash,\nbut this wasn't true.\n\nIt's true that the \\[ \\] markers add the information needed to properly\ncalculate the width of the prompt, and they have to be added directly to\nPS1, a function returning them doesn't work.\n\nBut that is because bash coverts the \\[ \\] markers in PS1 to \\001 \\002,\nwhich is what readline ultimately needs in order to calculate the width.\n\nWe don't need bash to do this conversion, we can use \\001 \\002\nourselves, and then the prompt command mode is not necessary to display\ncolors.\n\nThis is what functions returning colors are supposed to do [1].\n\n[1] http://mywiki.wooledge.org/BashFAQ/053\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-prompt.sh | 19 +++++++------------\n t/t9903-bash-prompt.sh           |  8 ++++----\n 2 files changed, 11 insertions(+), 16 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 1435548e00..01bd807657 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -96,9 +96,7 @@\n #\n # If you would like a colored hint about the current dirty state, set\n # GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on\n-# the colored output of \"git status -sb\" and are available only when\n-# using __git_ps1 for PROMPT_COMMAND or precmd in Bash,\n-# but always available in Zsh.\n+# the colored output of \"git status -sb\".\n #\n # If you would like __git_ps1 to do nothing in the case when the current\n # directory is set up to be ignored by git, then set\n@@ -255,12 +253,12 @@ __git_ps1_colorize_gitstring ()\n \t\tlocal c_lblue='%F{blue}'\n \t\tlocal c_clear='%f'\n \telse\n-\t\t# Using \\[ and \\] around colors is necessary to prevent\n+\t\t# Using \\001 and \\002 around colors is necessary to prevent\n \t\t# issues with command line editing/browsing/completion!\n-\t\tlocal c_red='\\[\\e[31m\\]'\n-\t\tlocal c_green='\\[\\e[32m\\]'\n-\t\tlocal c_lblue='\\[\\e[1;34m\\]'\n-\t\tlocal c_clear='\\[\\e[0m\\]'\n+\t\tlocal c_red=$'\\001\\e[31m\\002'\n+\t\tlocal c_green=$'\\001\\e[32m\\002'\n+\t\tlocal c_lblue=$'\\001\\e[1;34m\\002'\n+\t\tlocal c_clear=$'\\001\\e[0m\\002'\n \tfi\n \tlocal bad_color=$c_red\n \tlocal ok_color=$c_green\n@@ -564,11 +562,8 @@ __git_ps1 ()\n \t\tb=\"\\${__git_ps1_branch_name}\"\n \tfi\n \n-\t# NO color option unless in PROMPT_COMMAND mode or it's Zsh\n \tif [ -n \"${GIT_PS1_SHOWCOLORHINTS-}\" ]; then\n-\t\tif [ $pcmode = yes ] || [ -n \"${ZSH_VERSION-}\" ]; then\n-\t\t\t__git_ps1_colorize_gitstring\n-\t\tfi\n+\t\t__git_ps1_colorize_gitstring\n \tfi\n \n \tlocal f=\"$h$w$i$s$u$p\"\ndiff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh\nindex c94c351e23..fb396ff3a7 100755\n--- a/t/t9903-bash-prompt.sh\n+++ b/t/t9903-bash-prompt.sh\n@@ -13,10 +13,10 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n . \"$GIT_BUILD_DIR/contrib/completion/git-prompt.sh\"\n \n actual=\"$TRASH_DIRECTORY/actual\"\n-c_red='\\\\[\\\\e[31m\\\\]'\n-c_green='\\\\[\\\\e[32m\\\\]'\n-c_lblue='\\\\[\\\\e[1;34m\\\\]'\n-c_clear='\\\\[\\\\e[0m\\\\]'\n+c_red='\\001\\e[31m\\002'\n+c_green='\\001\\e[32m\\002'\n+c_lblue='\\001\\e[1;34m\\002'\n+c_clear='\\001\\e[0m\\002'\n \n unset GIT_PS1_SHOWDIRTYSTATE\n unset GIT_PS1_SHOWSTASHSTATE\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462139","messageId":"20220830093138.1581538-8-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 07/51] zsh: simplify realpath dirname idiom","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:54Z","receivedAt":"2022-08-30T09:32:14Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"There's a much simpler way in zsh.\n\nIt's a shame that ${0:A:h} doesn't work probably due to a bug in zsh.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 1a405ba0a2..18ad897568 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -33,7 +33,7 @@ if [ -z \"$script\" ]; then\n \t\tbash_completion='/usr/share/bash-completion/completions/'\n \n \tlocations=(\n-\t\t\"$(dirname $(realpath ${funcsourcetrace[1]%:*}))\"/git-completion.bash\n+\t\t\"${${funcsourcetrace[1]%:*}:A:h}\"/git-completion.bash\n \t\t\"$HOME/.local/share/bash-completion/completions/git\"\n \t\t'/usr/local/share/bash-completion/completions/git'\n \t\t\"$bash_completion/git\"\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462140","messageId":"20220830093138.1581538-11-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 10/51] completion: fix for suboptions with value","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:57Z","receivedAt":"2022-08-30T09:32:17Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"We need to ignore options that don't start with -- as well.\n\nDepending on the value of COMP_WORDBREAKS, the last word could be\nduplicated otherwise.\n\nCan be tested with:\n\n  git merge -X diff-algorithm=<tab>\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 2 +-\n t/t9904-zsh-completion.sh             | 4 ++--\n 2 files changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 18ad897568..1905ff98b7 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -56,7 +56,7 @@ __gitcomp ()\n \tlocal cur_=\"${3-$cur}\"\n \n \tcase \"$cur_\" in\n-\t--*=)\n+\t*=)\n \t\t;;\n \t--no-*)\n \t\tlocal c IFS=$' \\t\\n'\ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nindex 656eaf77ab..d3fe42a9b3 100755\n--- a/t/t9904-zsh-completion.sh\n+++ b/t/t9904-zsh-completion.sh\n@@ -157,7 +157,7 @@ test_expect_success '__gitcomp - expand/narrow all negative options' '\n \tEOF\n '\n \n-test_expect_failure '__gitcomp - equal skip' '\n+test_expect_success '__gitcomp - equal skip' '\n \ttest_gitcomp \"--option=\" \"--option=\" <<-\\EOF &&\n \n \tEOF\n@@ -1115,7 +1115,7 @@ test_expect_success 'git clone --config= - value' '\n \tEOF\n '\n \n-test_expect_failure 'options with value' '\n+test_expect_success 'options with value' '\n \ttest_completion \"git merge -X diff-algorithm=\" <<-\\EOF\n \n \tEOF\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462141","messageId":"20220830093138.1581538-7-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 06/51] zsh: resolve symlink of script","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:53Z","receivedAt":"2022-08-30T09:32:19Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"From: Michael Bianco <iloveitaly@gmail.com>\n\nWhen using zinit the completions are symlinked to ~/.zinit/completions,\nthis causes the zsh script to not be able to find the bash script.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 535cf03176..1a405ba0a2 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -33,7 +33,7 @@ if [ -z \"$script\" ]; then\n \t\tbash_completion='/usr/share/bash-completion/completions/'\n \n \tlocations=(\n-\t\t\"$(dirname ${funcsourcetrace[1]%:*})\"/git-completion.bash\n+\t\t\"$(dirname $(realpath ${funcsourcetrace[1]%:*}))\"/git-completion.bash\n \t\t\"$HOME/.local/share/bash-completion/completions/git\"\n \t\t'/usr/local/share/bash-completion/completions/git'\n \t\t\"$bash_completion/git\"\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462142","messageId":"20220830093138.1581538-9-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 08/51] test: reset environment variables","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:55Z","receivedAt":"2022-08-30T09:32:30Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"These should not affect the tests.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n t/t9903-bash-prompt.sh | 8 ++++++++\n 1 file changed, 8 insertions(+)\n\ndiff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh\nindex 6a30f5719c..c94c351e23 100755\n--- a/t/t9903-bash-prompt.sh\n+++ b/t/t9903-bash-prompt.sh\n@@ -18,6 +18,14 @@ c_green='\\\\[\\\\e[32m\\\\]'\n c_lblue='\\\\[\\\\e[1;34m\\\\]'\n c_clear='\\\\[\\\\e[0m\\\\]'\n \n+unset GIT_PS1_SHOWDIRTYSTATE\n+unset GIT_PS1_SHOWSTASHSTATE\n+unset GIT_PS1_SHOWUNTRACKEDFILES\n+unset GIT_PS1_COMPRESSSPARSESTATE\n+unset GIT_PS1_SHOWUPSTREAM\n+unset GIT_PS1_STATESEPARATOR\n+unset GIT_PS1_SHOWCOLORHINTS\n+\n test_expect_success 'setup for prompt tests' '\n \tgit init otherrepo &&\n \techo 1 >file &&\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462143","messageId":"20220830093138.1581538-12-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 11/51] completion: zsh: trivial improvement","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:58Z","receivedAt":"2022-08-30T09:32:32Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"$words has basically all the words we need, except the first one: git.\n\nLets simply add that instead of passing the original, which contains\noptions we don't want to pass downstream (like -c and -C).\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 5 +----\n 1 file changed, 1 insertion(+), 4 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 1905ff98b7..4d81ca73b5 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -220,9 +220,6 @@ __git_zsh_main ()\n {\n \tlocal curcontext=\"$curcontext\" state state_descr line\n \ttypeset -A opt_args\n-\tlocal -a orig_words\n-\n-\torig_words=( ${words[@]} )\n \n \t_arguments -C \\\n \t\t'(-p --paginate --no-pager)'{-p,--paginate}'[pipe all output into ''less'']' \\\n@@ -262,7 +259,7 @@ __git_zsh_main ()\n \n \t\t(( $+opt_args[--help] )) && command='help'\n \n-\t\twords=( ${orig_words[@]} )\n+\t\twords=( git ${words[@]} )\n \n \t\t__git_zsh_bash_func $command\n \t\t;;\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462144","messageId":"20220830093138.1581538-13-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 12/51] completion: bash: do not modify COMP_WORDBREAKS","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:30:59Z","receivedAt":"2022-08-30T09:32:34Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"There was no need for this once __git_reassemble_comp_words_by_ref() was\nintroduced. Now irrespective of the value of COMP_WORDBREAKS, words are\nalways joined together.\n\nBy default COMP_WORDBREAKS does contain a colon, and if it doesn't\nsomebody probably has a reason for it.\n\nCompletions are not supposed to modify COMP_WORDBREAKS and none of the\ncompletions in the bash-completion project do.\n\nWe manually set it in Zsh so the Bash script is not confused.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 5 -----\n contrib/completion/git-completion.zsh  | 1 +\n 2 files changed, 1 insertion(+), 5 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 2df51ed946..ef0b7aa192 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -59,11 +59,6 @@\n #     When set to \"1\" suggest all options, including options which are\n #     typically hidden (e.g. '--allow-empty' for 'git commit').\n \n-case \"$COMP_WORDBREAKS\" in\n-*:*) : great ;;\n-*)   COMP_WORDBREAKS=\"$COMP_WORDBREAKS:\"\n-esac\n-\n # Discovers the path to the git repository taking any '--git-dir=<path>' and\n # '-C <path>' options into account and stores it in the $__git_repo_path\n # variable.\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 4d81ca73b5..2de1a72c09 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -46,6 +46,7 @@ fi\n \n local old_complete=\"$functions[complete]\"\n functions[complete]=:\n+COMP_WORDBREAKS=':'\n GIT_SOURCING_ZSH_COMPLETION=y . \"$script\"\n functions[complete]=\"$old_complete\"\n \n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462145","messageId":"20220830093138.1581538-14-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 13/51] test: completion: fix currently typed words","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:00Z","receivedAt":"2022-08-30T09:32:36Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"They don't match what we are supposed to be completing.\n\nNo functional changes.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n t/t9902-completion.sh     | 4 ++--\n t/t9904-zsh-completion.sh | 4 ++--\n 2 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 8cc30448c7..031f05cf47 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -486,7 +486,7 @@ test_expect_success '__gitcomp - option parameter' '\n '\n \n test_expect_success '__gitcomp - prefix' '\n-\ttest_gitcomp \"branch.me\" \"remote merge mergeoptions rebase\" \\\n+\ttest_gitcomp \"branch.maint.me\" \"remote merge mergeoptions rebase\" \\\n \t\t\"branch.maint.\" \"me\" <<-\\EOF\n \tbranch.maint.merge Z\n \tbranch.maint.mergeoptions Z\n@@ -494,7 +494,7 @@ test_expect_success '__gitcomp - prefix' '\n '\n \n test_expect_success '__gitcomp - suffix' '\n-\ttest_gitcomp \"branch.me\" \"master maint next seen\" \"branch.\" \\\n+\ttest_gitcomp \"branch.ma\" \"master maint next seen\" \"branch.\" \\\n \t\t\"ma\" \".\" <<-\\EOF\n \tbranch.master.Z\n \tbranch.maint.Z\ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nindex d3fe42a9b3..e9df29c135 100755\n--- a/t/t9904-zsh-completion.sh\n+++ b/t/t9904-zsh-completion.sh\n@@ -106,7 +106,7 @@ test_expect_success '__gitcomp - option parameter' '\n '\n \n test_expect_failure '__gitcomp - prefix' '\n-\ttest_gitcomp \"branch.me\" \"remote merge mergeoptions rebase\" \\\n+\ttest_gitcomp \"branch.maint.me\" \"remote merge mergeoptions rebase\" \\\n \t\t\"branch.maint.\" \"me\" <<-\\EOF\n \tbranch.maint.merge Z\n \tbranch.maint.mergeoptions Z\n@@ -114,7 +114,7 @@ test_expect_failure '__gitcomp - prefix' '\n '\n \n test_expect_failure '__gitcomp - suffix' '\n-\ttest_gitcomp \"branch.me\" \"master maint next seen\" \"branch.\" \\\n+\ttest_gitcomp \"branch.ma\" \"master maint next seen\" \"branch.\" \\\n \t\t\"ma\" \".\" <<-\\EOF\n \tbranch.master.Z\n \tbranch.maint.Z\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462146","messageId":"20220830093138.1581538-15-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 14/51] test: completion: switch __gitcomp_nl prefix test","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:01Z","receivedAt":"2022-08-30T09:32:39Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"By default COMP_WORDBREAKS includes =, so it's not realistic to test for\na prefix that almost never will be there.\n\nIn bash there are no functional changes, but in zsh this makes the test\npass.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n t/t9902-completion.sh     | 6 +++---\n t/t9904-zsh-completion.sh | 8 ++++----\n 2 files changed, 7 insertions(+), 7 deletions(-)\n\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 031f05cf47..2fe056ab59 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -565,9 +565,9 @@ test_expect_success '__gitcomp_nl - trailing space' '\n '\n \n test_expect_success '__gitcomp_nl - prefix' '\n-\ttest_gitcomp_nl \"--fixup=m\" \"$refs\" \"--fixup=\" \"m\" <<-EOF\n-\t--fixup=main Z\n-\t--fixup=maint Z\n+\ttest_gitcomp_nl \"branch.m\" \"$refs\" \"branch.\" \"m\" <<-EOF\n+\tbranch.main Z\n+\tbranch.maint Z\n \tEOF\n '\n \ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nindex e9df29c135..dbd0671ab6 100755\n--- a/t/t9904-zsh-completion.sh\n+++ b/t/t9904-zsh-completion.sh\n@@ -180,10 +180,10 @@ test_expect_success '__gitcomp_nl - trailing space' '\n \tEOF\n '\n \n-test_expect_failure '__gitcomp_nl - prefix' '\n-\ttest_gitcomp_nl \"--fixup=m\" \"$refs\" \"--fixup=\" \"m\" <<-EOF\n-\t--fixup=main Z\n-\t--fixup=maint Z\n+test_expect_success '__gitcomp_nl - prefix' '\n+\ttest_gitcomp_nl \"branch.m\" \"$refs\" \"branch.\" \"m\" <<-EOF\n+\tbranch.main Z\n+\tbranch.maint Z\n \tEOF\n '\n \n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462147","messageId":"20220830093138.1581538-16-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 15/51] test: completion: add run_func() helper","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:02Z","receivedAt":"2022-08-30T09:32:41Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Pretty straightforward: runs functions.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n t/t9902-completion.sh | 58 ++++++++++++++++++-------------------------\n 1 file changed, 24 insertions(+), 34 deletions(-)\n\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 2fe056ab59..91dfb618c1 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -75,6 +75,12 @@ run_completion ()\n \t__git_wrap__git_main && print_comp\n }\n \n+run_func ()\n+{\n+\tlocal -a COMPREPLY &&\n+\t\"$@\" && print_comp\n+}\n+\n # Test high-level completion\n # Arguments are:\n # 1: typed text so far (cur)\n@@ -452,8 +458,7 @@ test_expect_success '__gitcomp_direct - puts everything into COMPREPLY as-is' '\n \tEOF\n \t(\n \t\tcur=should_be_ignored &&\n-\t\t__gitcomp_direct \"$(cat expected)\" &&\n-\t\tprint_comp\n+\t\trun_func __gitcomp_direct \"$(cat expected)\"\n \t) &&\n \ttest_cmp expected out\n '\n@@ -547,7 +552,7 @@ test_expect_success '__gitcomp - equal skip' '\n '\n \n test_expect_success '__gitcomp - doesnt fail because of invalid variable name' '\n-\t__gitcomp \"$invalid_variable_name\"\n+\trun_func __gitcomp \"$invalid_variable_name\"\n '\n \n read -r -d \"\" refs <<-\\EOF\n@@ -586,7 +591,7 @@ test_expect_success '__gitcomp_nl - no suffix' '\n '\n \n test_expect_success '__gitcomp_nl - doesnt fail because of invalid variable name' '\n-\t__gitcomp_nl \"$invalid_variable_name\"\n+\trun_func __gitcomp_nl \"$invalid_variable_name\"\n '\n \n test_expect_success '__git_remotes - list remotes from $GIT_DIR/remotes and from config file' '\n@@ -1087,8 +1092,7 @@ test_expect_success '__git_complete_refs - simple' '\n \tEOF\n \t(\n \t\tcur= &&\n-\t\t__git_complete_refs &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_refs\n \t) &&\n \ttest_cmp expected out\n '\n@@ -1100,8 +1104,7 @@ test_expect_success '__git_complete_refs - matching' '\n \tEOF\n \t(\n \t\tcur=mat &&\n-\t\t__git_complete_refs &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_refs\n \t) &&\n \ttest_cmp expected out\n '\n@@ -1114,8 +1117,7 @@ test_expect_success '__git_complete_refs - remote' '\n \tEOF\n \t(\n \t\tcur= &&\n-\t\t__git_complete_refs --remote=other &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_refs --remote=other\n \t) &&\n \ttest_cmp expected out\n '\n@@ -1133,8 +1135,7 @@ test_expect_success '__git_complete_refs - track' '\n \tEOF\n \t(\n \t\tcur= &&\n-\t\t__git_complete_refs --track &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_refs --track\n \t) &&\n \ttest_cmp expected out\n '\n@@ -1146,8 +1147,7 @@ test_expect_success '__git_complete_refs - current word' '\n \tEOF\n \t(\n \t\tcur=\"--option=mat\" &&\n-\t\t__git_complete_refs --cur=\"${cur#*=}\" &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_refs --cur=\"${cur#*=}\"\n \t) &&\n \ttest_cmp expected out\n '\n@@ -1159,8 +1159,7 @@ test_expect_success '__git_complete_refs - prefix' '\n \tEOF\n \t(\n \t\tcur=v1.0..mat &&\n-\t\t__git_complete_refs --pfx=v1.0.. --cur=mat &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_refs --pfx=v1.0.. --cur=mat\n \t) &&\n \ttest_cmp expected out\n '\n@@ -1176,8 +1175,7 @@ test_expect_success '__git_complete_refs - suffix' '\n \tEOF\n \t(\n \t\tcur= &&\n-\t\t__git_complete_refs --sfx=. &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_refs --sfx=.\n \t) &&\n \ttest_cmp expected out\n '\n@@ -1190,8 +1188,7 @@ test_expect_success '__git_complete_fetch_refspecs - simple' '\n \tEOF\n \t(\n \t\tcur= &&\n-\t\t__git_complete_fetch_refspecs other &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_fetch_refspecs other\n \t) &&\n \ttest_cmp expected out\n '\n@@ -1202,8 +1199,7 @@ test_expect_success '__git_complete_fetch_refspecs - matching' '\n \tEOF\n \t(\n \t\tcur=br &&\n-\t\t__git_complete_fetch_refspecs other \"\" br &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_fetch_refspecs other \"\" br\n \t) &&\n \ttest_cmp expected out\n '\n@@ -1216,8 +1212,7 @@ test_expect_success '__git_complete_fetch_refspecs - prefix' '\n \tEOF\n \t(\n \t\tcur=\"+\" &&\n-\t\t__git_complete_fetch_refspecs other \"+\" \"\"  &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_fetch_refspecs other \"+\" \"\"\n \t) &&\n \ttest_cmp expected out\n '\n@@ -1230,8 +1225,7 @@ test_expect_success '__git_complete_fetch_refspecs - fully qualified' '\n \tEOF\n \t(\n \t\tcur=refs/ &&\n-\t\t__git_complete_fetch_refspecs other \"\" refs/ &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_fetch_refspecs other \"\" refs/\n \t) &&\n \ttest_cmp expected out\n '\n@@ -1244,8 +1238,7 @@ test_expect_success '__git_complete_fetch_refspecs - fully qualified & prefix' '\n \tEOF\n \t(\n \t\tcur=+refs/ &&\n-\t\t__git_complete_fetch_refspecs other + refs/ &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_fetch_refspecs other + refs/\n \t) &&\n \ttest_cmp expected out\n '\n@@ -1931,8 +1924,7 @@ test_path_completion ()\n \t\t# unusual characters in path names.  By requesting only\n \t\t# untracked files we do not have to bother adding any\n \t\t# paths to the index in those tests.\n-\t\t__git_complete_index_file --others &&\n-\t\tprint_comp\n+\t\trun_func __git_complete_index_file --others\n \t) &&\n \ttest_cmp expected out\n }\n@@ -2457,8 +2449,7 @@ do\n \t\t\twords=(git push '$flag' other ma) &&\n \t\t\tcword=${#words[@]} cur=${words[cword-1]} &&\n \t\t\t__git_cmd_idx=1 &&\n-\t\t\t__git_complete_remote_or_refspec &&\n-\t\t\tprint_comp\n+\t\t\trun_func __git_complete_remote_or_refspec\n \t\t) &&\n \t\ttest_cmp expected out\n \t'\n@@ -2471,8 +2462,7 @@ do\n \t\t\twords=(git push other '$flag' ma) &&\n \t\t\tcword=${#words[@]} cur=${words[cword-1]} &&\n \t\t\t__git_cmd_idx=1 &&\n-\t\t\t__git_complete_remote_or_refspec &&\n-\t\t\tprint_comp\n+\t\t\trun_func __git_complete_remote_or_refspec\n \t\t) &&\n \t\ttest_cmp expected out\n \t'\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462148","messageId":"20220830093138.1581538-17-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 16/51] completion: bash: remove non-append functionality","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:03Z","receivedAt":"2022-08-30T09:32:43Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"There's no point in setting COMPREPLY only to override it later, and in\nfact... we don't do that.\n\nTherefore there's no functional difference between __gitcomp_direct()\nand __gitcomp_direct_append(), since __gitcomp_direct() *always*\noperates on empty COMPREPLY.\n\nThe same goes for __gitcomp_nl().\n\nThis patch makes the functionality of append and non-append functions\nthe same.\n\nNo functional changes.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 3 +--\n 1 file changed, 1 insertion(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex ef0b7aa192..6571dc1b2d 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -312,7 +312,7 @@ __gitcomp_direct ()\n {\n \tlocal IFS=$'\\n'\n \n-\tCOMPREPLY=($1)\n+\tCOMPREPLY+=($1)\n }\n \n # Similar to __gitcomp_direct, but appends to COMPREPLY instead.\n@@ -464,7 +464,6 @@ __gitcomp_nl_append ()\n #    appended.\n __gitcomp_nl ()\n {\n-\tCOMPREPLY=()\n \t__gitcomp_nl_append \"$@\"\n }\n \n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462149","messageId":"20220830093138.1581538-18-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 17/51] completion: bash: get rid of _append() functions","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:04Z","receivedAt":"2022-08-30T09:32:48Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"There's no need to have duplicated functionality.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 35 ++++++--------------------\n contrib/completion/git-completion.zsh  | 10 --------\n 2 files changed, 7 insertions(+), 38 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 6571dc1b2d..4a7e75b48d 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -301,8 +301,7 @@ _get_comp_words_by_ref ()\n }\n fi\n \n-# Fills the COMPREPLY array with prefiltered words without any additional\n-# processing.\n+# Appends prefiltered words to COMPREPLY without any additional processing.\n # Callers must take care of providing only words that match the current word\n # to be completed and adding any prefix and/or suffix (trailing space!), if\n # necessary.\n@@ -315,19 +314,6 @@ __gitcomp_direct ()\n \tCOMPREPLY+=($1)\n }\n \n-# Similar to __gitcomp_direct, but appends to COMPREPLY instead.\n-# Callers must take care of providing only words that match the current word\n-# to be completed and adding any prefix and/or suffix (trailing space!), if\n-# necessary.\n-# 1: List of newline-separated matching completion words, complete with\n-#    prefix and suffix.\n-__gitcomp_direct_append ()\n-{\n-\tlocal IFS=$'\\n'\n-\n-\tCOMPREPLY+=($1)\n-}\n-\n __gitcompappend ()\n {\n \tlocal x i=${#COMPREPLY[@]}\n@@ -445,16 +431,8 @@ __gitcomp_builtin ()\n \t__gitcomp \"$options\"\n }\n \n-# Variation of __gitcomp_nl () that appends to the existing list of\n-# completion candidates, COMPREPLY.\n-__gitcomp_nl_append ()\n-{\n-\tlocal IFS=$'\\n'\n-\t__gitcompappend \"$1\" \"${2-}\" \"${3-$cur}\" \"${4- }\"\n-}\n-\n # Generates completion reply from newline-separated possible completion words\n-# by appending a space to all of them.\n+# by appending a space to all of them. The result is appended to COMPREPLY.\n # It accepts 1 to 4 arguments:\n # 1: List of possible completion words, separated by a single newline.\n # 2: A prefix to be added to each possible completion word (optional).\n@@ -464,7 +442,8 @@ __gitcomp_nl_append ()\n #    appended.\n __gitcomp_nl ()\n {\n-\t__gitcomp_nl_append \"$@\"\n+\tlocal IFS=$'\\n'\n+\t__gitcompappend \"$1\" \"${2-}\" \"${3-$cur}\" \"${4- }\"\n }\n \n # Fills the COMPREPLY array with prefiltered paths without any additional\n@@ -851,7 +830,7 @@ __git_complete_refs ()\n \n \t# Append DWIM remote branch names if requested\n \tif [ \"$dwim\" = \"yes\" ]; then\n-\t\t__gitcomp_direct_append \"$(__git_dwim_remote_heads \"$pfx\" \"$cur_\" \"$sfx\")\"\n+\t\t__gitcomp_direct \"$(__git_dwim_remote_heads \"$pfx\" \"$cur_\" \"$sfx\")\"\n \tfi\n }\n \n@@ -2650,7 +2629,7 @@ __git_complete_config_variable_name ()\n \t\tlocal pfx=\"${cur_%.*}.\"\n \t\tcur_=\"${cur_#*.}\"\n \t\t__gitcomp_direct \"$(__git_heads \"$pfx\" \"$cur_\" \".\")\"\n-\t\t__gitcomp_nl_append $'autoSetupMerge\\nautoSetupRebase\\n' \"$pfx\" \"$cur_\" \"${sfx- }\"\n+\t\t__gitcomp_nl $'autoSetupMerge\\nautoSetupRebase\\n' \"$pfx\" \"$cur_\" \"${sfx- }\"\n \t\treturn\n \t\t;;\n \tguitool.*.*)\n@@ -2700,7 +2679,7 @@ __git_complete_config_variable_name ()\n \t\tlocal pfx=\"${cur_%.*}.\"\n \t\tcur_=\"${cur_#*.}\"\n \t\t__gitcomp_nl \"$(__git_remotes)\" \"$pfx\" \"$cur_\" \".\"\n-\t\t__gitcomp_nl_append \"pushDefault\" \"$pfx\" \"$cur_\" \"${sfx- }\"\n+\t\t__gitcomp_nl \"pushDefault\" \"$pfx\" \"$cur_\" \"${sfx- }\"\n \t\treturn\n \t\t;;\n \turl.*.*)\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 2de1a72c09..35300a08cd 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -122,16 +122,6 @@ __gitcomp_file ()\n \tcompadd -f -p \"${2-}\" -- ${(f)1} && _ret=0\n }\n \n-__gitcomp_direct_append ()\n-{\n-\t__gitcomp_direct \"$@\"\n-}\n-\n-__gitcomp_nl_append ()\n-{\n-\t__gitcomp_nl \"$@\"\n-}\n-\n __gitcomp_file_direct ()\n {\n \t__gitcomp_file \"$1\" \"\"\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462150","messageId":"20220830093138.1581538-19-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 18/51] completion: bash: get rid of any non-append code","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:05Z","receivedAt":"2022-08-30T09:32:50Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 12 +++---------\n 1 file changed, 3 insertions(+), 9 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 4a7e75b48d..ed126bbec4 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -314,7 +314,7 @@ __gitcomp_direct ()\n \tCOMPREPLY+=($1)\n }\n \n-__gitcompappend ()\n+__gitcompadd ()\n {\n \tlocal x i=${#COMPREPLY[@]}\n \tfor x in $1; do\n@@ -324,12 +324,6 @@ __gitcompappend ()\n \tdone\n }\n \n-__gitcompadd ()\n-{\n-\tCOMPREPLY=()\n-\t__gitcompappend \"$@\"\n-}\n-\n # Generates completion reply, appending a space to possible completion words,\n # if necessary.\n # It accepts 1 to 4 arguments:\n@@ -443,7 +437,7 @@ __gitcomp_builtin ()\n __gitcomp_nl ()\n {\n \tlocal IFS=$'\\n'\n-\t__gitcompappend \"$1\" \"${2-}\" \"${3-$cur}\" \"${4- }\"\n+\t__gitcompadd \"$1\" \"${2-}\" \"${3-$cur}\" \"${4- }\"\n }\n \n # Fills the COMPREPLY array with prefiltered paths without any additional\n@@ -456,7 +450,7 @@ __gitcomp_file_direct ()\n {\n \tlocal IFS=$'\\n'\n \n-\tCOMPREPLY=($1)\n+\tCOMPREPLY+=($1)\n \n \t# use a hack to enable file mode in bash < 4\n \tcompopt -o filenames +o nospace 2>/dev/null ||\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462151","messageId":"20220830093138.1581538-20-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 19/51] completion: zsh: fix options with arguments","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:06Z","receivedAt":"2022-08-30T09:32:52Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"They support both '--git-dir=value' and '--git-dir value'. Fix the\narguments to support both.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 35300a08cd..10ad15face 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -215,15 +215,15 @@ __git_zsh_main ()\n \t_arguments -C \\\n \t\t'(-p --paginate --no-pager)'{-p,--paginate}'[pipe all output into ''less'']' \\\n \t\t'(-p --paginate)--no-pager[do not pipe git output into a pager]' \\\n-\t\t'--git-dir=-[set the path to the repository]: :_directories' \\\n+\t\t'--git-dir=[set the path to the repository]: :_directories' \\\n \t\t'--bare[treat the repository as a bare repository]' \\\n \t\t'(- :)--version[prints the git suite version]' \\\n-\t\t'--exec-path=-[path to where your core git programs are installed]:: :_directories' \\\n+\t\t'--exec-path=[path to where your core git programs are installed]:: :_directories' \\\n \t\t'--html-path[print the path where git''s HTML documentation is installed]' \\\n \t\t'--info-path[print the path where the Info files are installed]' \\\n \t\t'--man-path[print the manpath (see `man(1)`) for the man pages]' \\\n-\t\t'--work-tree=-[set the path to the working tree]: :_directories' \\\n-\t\t'--namespace=-[set the git namespace]' \\\n+\t\t'--work-tree=[set the path to the working tree]: :_directories' \\\n+\t\t'--namespace=[set the git namespace]:' \\\n \t\t'--no-replace-objects[do not use replacement refs to replace git objects]' \\\n \t\t'(- :)--help[prints the synopsis and a list of the most commonly used commands]: :->arg' \\\n \t\t'(-): :->command' \\\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462152","messageId":"20220830093138.1581538-21-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 20/51] completion: zsh: expand --git-dir file argument","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:07Z","receivedAt":"2022-08-30T09:33:01Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 10ad15face..0e72b9add7 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -245,7 +245,7 @@ __git_zsh_main ()\n \t\tif (( $+opt_args[--bare] )); then\n \t\t\t__git_dir='.'\n \t\telse\n-\t\t\t__git_dir=${opt_args[--git-dir]}\n+\t\t\t__git_dir=${~opt_args[--git-dir]}\n \t\tfi\n \n \t\t(( $+opt_args[--help] )) && command='help'\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462153","messageId":"20220830093138.1581538-22-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 21/51] completion: zsh: add support for general -C opts","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:08Z","receivedAt":"2022-08-30T09:33:02Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 6 ++++++\n t/t9904-zsh-completion.sh             | 2 +-\n 2 files changed, 7 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 0e72b9add7..e771a2a53a 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -211,6 +211,7 @@ __git_zsh_main ()\n {\n \tlocal curcontext=\"$curcontext\" state state_descr line\n \ttypeset -A opt_args\n+\tlocal -a __git_C_args\n \n \t_arguments -C \\\n \t\t'(-p --paginate --no-pager)'{-p,--paginate}'[pipe all output into ''less'']' \\\n@@ -226,6 +227,7 @@ __git_zsh_main ()\n \t\t'--namespace=[set the git namespace]:' \\\n \t\t'--no-replace-objects[do not use replacement refs to replace git objects]' \\\n \t\t'(- :)--help[prints the synopsis and a list of the most commonly used commands]: :->arg' \\\n+\t\t'*-C[run as if git was started in the given path]: :_directories' \\\n \t\t'(-): :->command' \\\n \t\t'(-)*:: :->arg' && return\n \n@@ -248,6 +250,10 @@ __git_zsh_main ()\n \t\t\t__git_dir=${~opt_args[--git-dir]}\n \t\tfi\n \n+\t\tfor x in ${(s.:.)opt_args[-C]}; do\n+\t\t\t__git_C_args+=('-C' ${~x})\n+\t\tdone\n+\n \t\t(( $+opt_args[--help] )) && command='help'\n \n \t\twords=( git ${words[@]} )\ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nindex dbd0671ab6..cd223b6e2a 100755\n--- a/t/t9904-zsh-completion.sh\n+++ b/t/t9904-zsh-completion.sh\n@@ -844,7 +844,7 @@ test_expect_success 'checkout completes ref names' '\n \tEOF\n '\n \n-test_expect_failure 'git -C <path> checkout uses the right repo' '\n+test_expect_success 'git -C <path> checkout uses the right repo' '\n \ttest_completion \"git -C subdir -C subsubdir -C .. -C ../otherrepo checkout b\" <<-\\EOF\n \tbranch-in-other Z\n \tEOF\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462154","messageId":"20220830093138.1581538-24-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 23/51] completion: zsh: add support for general -c opts","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:10Z","receivedAt":"2022-08-30T09:33:17Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"So we can specify configurations.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 5 +++++\n t/t9904-zsh-completion.sh             | 4 ++--\n 2 files changed, 7 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 30607aa93d..b062090a13 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -231,6 +231,7 @@ __git_zsh_main ()\n \t\t'--no-replace-objects[do not use replacement refs to replace git objects]' \\\n \t\t'(- :)--help[prints the synopsis and a list of the most commonly used commands]: :->arg' \\\n \t\t'*-C[run as if git was started in the given path]: :_directories' \\\n+\t\t'*-c[pass a configuration parameter to the command]: :->config' \\\n \t\t'(-): :->command' \\\n \t\t'(-)*:: :->arg' && return\n \n@@ -244,6 +245,10 @@ __git_zsh_main ()\n \t\t\tlet _ret || break\n \t\tdone\n \t\t;;\n+\t(config)\n+\t\tcompset -P '*[=:]'\n+\t\temulate ksh -c __git_complete_config_variable_name_and_value\n+\t\t;;\n \t(arg)\n \t\tlocal command=\"${words[1]}\" __git_dir __git_cmd_idx=1\n \ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nindex 14f5e5d9b8..4c7cf4234e 100755\n--- a/t/t9904-zsh-completion.sh\n+++ b/t/t9904-zsh-completion.sh\n@@ -1071,7 +1071,7 @@ test_expect_success 'git config - value' '\n \tEOF\n '\n \n-test_expect_failure 'git -c - section' '\n+test_expect_success 'git -c - section' '\n \ttest_completion \"git -c br\" <<-\\EOF\n \tbranch.Z\n \tbrowser.Z\n@@ -1086,7 +1086,7 @@ test_expect_failure 'git -c - variable name' '\n \tEOF\n '\n \n-test_expect_failure 'git -c - value' '\n+test_expect_success 'git -c - value' '\n \ttest_completion \"git -c color.pager=\" <<-\\EOF\n \tfalse Z\n \ttrue Z\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462155","messageId":"20220830093138.1581538-25-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 24/51] completion: zsh: fix extra space on foo=","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:11Z","receivedAt":"2022-08-30T09:33:23Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Upstream commit e1e00089da fixed the issue for Bash, but not for Zsh.\n\nWhen we are typing configurations an = at the end signifies we still\nwant to type the value.\n\nCan be tested with:\n\n  git -c log.d<tab>\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 2 +-\n t/t9904-zsh-completion.sh             | 4 ++--\n 2 files changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex b062090a13..f732881958 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -87,7 +87,7 @@ __gitcomp ()\n \t\t\tfi\n \t\t\tc=\"$c${4-}\"\n \t\t\tcase $c in\n-\t\t\t--*=|*.) ;;\n+\t\t\t*=|*.) ;;\n \t\t\t*) c=\"$c \" ;;\n \t\t\tesac\n \t\t\tarray+=(\"$c\")\ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nindex 4c7cf4234e..7283af3342 100755\n--- a/t/t9904-zsh-completion.sh\n+++ b/t/t9904-zsh-completion.sh\n@@ -1078,7 +1078,7 @@ test_expect_success 'git -c - section' '\n \tEOF\n '\n \n-test_expect_failure 'git -c - variable name' '\n+test_expect_success 'git -c - variable name' '\n \ttest_completion \"git -c log.d\" <<-\\EOF\n \tlog.date=Z\n \tlog.decorate=Z\n@@ -1100,7 +1100,7 @@ test_expect_success 'git clone --config= - section' '\n \tEOF\n '\n \n-test_expect_failure 'git clone --config= - variable name' '\n+test_expect_success 'git clone --config= - variable name' '\n \ttest_completion \"git clone --config=log.d\" <<-\\EOF\n \tlog.date=Z\n \tlog.decorate=Z\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462156","messageId":"20220830093138.1581538-23-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 22/51] completion: zsh: fix for undefined completions","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:09Z","receivedAt":"2022-08-30T09:33:32Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"The parseopt helper can generate the completions even if the function is\nunspecified.\n\n  git version --<tab>\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 3 +++\n t/t9904-zsh-completion.sh             | 2 +-\n 2 files changed, 4 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex e771a2a53a..30607aa93d 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -141,6 +141,9 @@ __git_complete_command ()\n \tif (( $+functions[$completion_func] )); then\n \t\temulate ksh -c $completion_func\n \t\treturn 0\n+\telif emulate ksh -c \"__git_support_parseopt_helper $command\"; then\n+\t\temulate ksh -c \"__git_complete_common $command\"\n+\t\treturn 0\n \telse\n \t\treturn 1\n \tfi\ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nindex cd223b6e2a..14f5e5d9b8 100755\n--- a/t/t9904-zsh-completion.sh\n+++ b/t/t9904-zsh-completion.sh\n@@ -1015,7 +1015,7 @@ test_expect_success 'completion used <cmd> completion for alias: !f() { : git <c\n \tEOF\n '\n \n-test_expect_failure 'completion without explicit _git_xxx function' '\n+test_expect_success 'completion without explicit _git_xxx function' '\n \ttest_completion \"git version --\" <<-\\EOF\n \t--build-options Z\n \t--no-build-options Z\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462157","messageId":"20220830093138.1581538-29-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 28/51] completion: simplify equal suffix check","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:15Z","receivedAt":"2022-08-30T09:33:51Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"We know the prefix is already '--no-', there's no need to check for the\nfirst '--'.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 2 +-\n contrib/completion/git-completion.zsh  | 2 +-\n 2 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 86c335cfce..2a5e32e457 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -349,7 +349,7 @@ __gitcomp ()\n \t\t\tc=\"$c${4-}\"\n \t\t\tif [[ $c == \"$cur_\"* ]]; then\n \t\t\t\tcase $c in\n-\t\t\t\t--*=|*.) ;;\n+\t\t\t\t*=|*.) ;;\n \t\t\t\t*) c=\"$c \" ;;\n \t\t\t\tesac\n \t\t\t\tCOMPREPLY[i++]=\"${2-}$c\"\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 808cf87f84..a8ff9c089a 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -68,7 +68,7 @@ __gitcomp ()\n \t\t\tfi\n \t\t\tc=\"$c${4-}\"\n \t\t\tcase $c in\n-\t\t\t--*=|*.) ;;\n+\t\t\t*=|*.) ;;\n \t\t\t*) c=\"$c \" ;;\n \t\t\tesac\n \t\t\tarray+=(\"$c\")\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462158","messageId":"20220830093138.1581538-31-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 30/51] completion: simplify __gitcomp","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:17Z","receivedAt":"2022-08-30T09:33:54Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"It's not possible for $cur_ to have anything more than --no- at this\npoint, so there's no need to add a suffix, nor check anything else.\n\nAll we are doing is checking that $cur_ matches --no, and adding a\ncompletion if so.\n\nThis way the code reflects what we are doing.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 5 ++---\n contrib/completion/git-completion.zsh  | 2 +-\n 2 files changed, 3 insertions(+), 4 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 54b2c4e589..c9315d4f9a 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -346,9 +346,8 @@ __gitcomp ()\n \t\t\t\tcontinue\n \t\t\tfi\n \n-\t\t\tc=\"--no-...${4-}\"\n-\t\t\tif [[ $c == \"$cur_\"* ]]; then\n-\t\t\t\tCOMPREPLY[i++]=\"${2-}$c \"\n+\t\t\tif [[ --no == \"$cur_\"* ]]; then\n+\t\t\t\tCOMPREPLY[i++]=\"--no-... \"\n \t\t\tfi\n \t\t\tbreak\n \t\tfi\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 7616f87fa2..d5f4270ee5 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -63,7 +63,7 @@ __gitcomp ()\n \tfor c in ${=1}; do\n \t\tif [[ $c == \"--\" ]]; then\n \t\t\t[[ \"$cur_\" == --no-* ]] && continue\n-\t\t\tarray+=(\"--no-...${4-} \")\n+\t\t\tarray+=(\"--no-... \")\n \t\t\tbreak\n \t\tfi\n \t\tc=\"$c${4-}\"\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462159","messageId":"20220830093138.1581538-33-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 32/51] completion: improve __gitcomp suffix code","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:19Z","receivedAt":"2022-08-30T09:33:56Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"There's no point in adding a suffix after a suffix.\n\nIf a suffix is provided: we add it, if not: then the default heuristic\nis used.\n\nThere's no functional change since most callers don't specify a suffix,\nand the ones that do, use an =, which by default doesn't add an\nadditional suffix.\n\nThe only exception is __git_complete_config_variable_name, so make sure\nwe pass the correct suffix.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 19 +++++++++++--------\n contrib/completion/git-completion.zsh  | 18 +++++++++++-------\n 2 files changed, 22 insertions(+), 15 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 2ff7de1274..d43ec03c12 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -339,7 +339,7 @@ __gitcomp ()\n \t\treturn\n \tfi\n \n-\tlocal c i=0 IFS=$' \\t\\n'\n+\tlocal c i=0 IFS=$' \\t\\n' sfx\n \tfor c in $1; do\n \t\tif [[ $c == \"--\" ]]; then\n \t\t\tif [[ \"$cur_\" == --no-* ]]; then\n@@ -352,12 +352,15 @@ __gitcomp ()\n \t\t\tbreak\n \t\tfi\n \t\tif [[ $c == \"$cur_\"* ]]; then\n-\t\t\tc=\"$c${4-}\"\n-\t\t\tcase $c in\n-\t\t\t*=|*.) ;;\n-\t\t\t*) c=\"$c \" ;;\n-\t\t\tesac\n-\t\t\tCOMPREPLY[i++]=\"${2-}$c\"\n+\t\t\tif [[ -z \"${4+set}\" ]]; then\n+\t\t\t\tcase $c in\n+\t\t\t\t*=|*.) sfx=\"\" ;;\n+\t\t\t\t*) sfx=\" \" ;;\n+\t\t\t\tesac\n+\t\t\telse\n+\t\t\t\tsfx=\"$4\"\n+\t\t\tfi\n+\t\t\tCOMPREPLY[i++]=\"${2-}$c$sfx\"\n \t\tfi\n \tdone\n }\n@@ -2586,7 +2589,7 @@ __git_complete_config_variable_value ()\n #                 subsections) instead of the default space.\n __git_complete_config_variable_name ()\n {\n-\tlocal cur_=\"$cur\" sfx\n+\tlocal cur_=\"$cur\" sfx=\" \"\n \n \twhile test $# != 0; do\n \t\tcase \"$1\" in\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex d5f4270ee5..41aae0f454 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -58,7 +58,7 @@ __gitcomp ()\n \n \t[[ \"$cur_\" == *= ]] && return\n \n-\tlocal c IFS=$' \\t\\n'\n+\tlocal c IFS=$' \\t\\n' sfx\n \tlocal -a array\n \tfor c in ${=1}; do\n \t\tif [[ $c == \"--\" ]]; then\n@@ -66,12 +66,16 @@ __gitcomp ()\n \t\t\tarray+=(\"--no-... \")\n \t\t\tbreak\n \t\tfi\n-\t\tc=\"$c${4-}\"\n-\t\tcase $c in\n-\t\t*=|*.) ;;\n-\t\t*) c=\"$c \" ;;\n-\t\tesac\n-\t\tarray+=(\"$c\")\n+\n+\t\tif [[ -z \"${4+set}\" ]]; then\n+\t\t\tcase $c in\n+\t\t\t*=|*.) sfx=\"\" ;;\n+\t\t\t*) sfx=\" \" ;;\n+\t\t\tesac\n+\t\telse\n+\t\t\tsfx=\"$4\"\n+\t\tfi\n+\t\tarray+=(\"$c$sfx\")\n \tdone\n \tcompadd -Q -S '' -p \"${2-}\" -a -- array && _ret=0\n }\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462160","messageId":"20220830093138.1581538-34-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 33/51] test: completion: add missing test","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:20Z","receivedAt":"2022-08-30T09:33:58Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Once the correct suffix in __git_complete_config_variable_name() is set,\nwe can add the test again.\n\nNow it should work even in bash < 4.0.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n t/t9902-completion.sh     | 7 +++++++\n t/t9904-zsh-completion.sh | 7 +++++++\n 2 files changed, 14 insertions(+)\n\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 91dfb618c1..e1e9c6e365 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -2503,6 +2503,13 @@ test_expect_success 'git config - value' '\n \tEOF\n '\n \n+test_expect_success 'git config - direct completions' '\n+\ttest_completion \"git config branch.autoSetup\" <<-\\EOF\n+\tbranch.autoSetupMerge Z\n+\tbranch.autoSetupRebase Z\n+\tEOF\n+'\n+\n test_expect_success 'git -c - section' '\n \ttest_completion \"git -c br\" <<-\\EOF\n \tbranch.Z\ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nindex d0795ee014..42917833e8 100755\n--- a/t/t9904-zsh-completion.sh\n+++ b/t/t9904-zsh-completion.sh\n@@ -1071,6 +1071,13 @@ test_expect_success 'git config - value' '\n \tEOF\n '\n \n+test_expect_success 'git config - direct completions' '\n+\ttest_completion \"git config branch.autoSetup\" <<-\\EOF\n+\tbranch.autoSetupMerge Z\n+\tbranch.autoSetupRebase Z\n+\tEOF\n+'\n+\n test_expect_success 'git -c - section' '\n \ttest_completion \"git -c br\" <<-\\EOF\n \tbranch.Z\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462161","messageId":"20220830093138.1581538-26-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 25/51] completion: zsh: add excluded options","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:12Z","receivedAt":"2022-08-30T09:34:00Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Add more excluded options, for example: --bare excludes --git-dir.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 17 +++++++++--------\n t/t9904-zsh-completion.sh             |  2 +-\n 2 files changed, 10 insertions(+), 9 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex f732881958..d2eb221d79 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -217,15 +217,16 @@ __git_zsh_main ()\n \tlocal -a __git_C_args\n \n \t_arguments -C \\\n-\t\t'(-p --paginate --no-pager)'{-p,--paginate}'[pipe all output into ''less'']' \\\n-\t\t'(-p --paginate)--no-pager[do not pipe git output into a pager]' \\\n-\t\t'--git-dir=[set the path to the repository]: :_directories' \\\n-\t\t'--bare[treat the repository as a bare repository]' \\\n+\t\t'(-p --paginate -P --no-pager)'{-p,--paginate}'[pipe all output into ''less'']' \\\n+\t\t'(-p --paginate -P --no-pager)'{-P,--no-pager}'[do not pipe git output into a pager]' \\\n+\t\t'(--bare)--git-dir=[set the path to the repository]: :_directories' \\\n+\t\t'(--git-dir)--bare[treat the repository as a bare repository]' \\\n \t\t'(- :)--version[prints the git suite version]' \\\n-\t\t'--exec-path=[path to where your core git programs are installed]:: :_directories' \\\n-\t\t'--html-path[print the path where git''s HTML documentation is installed]' \\\n-\t\t'--info-path[print the path where the Info files are installed]' \\\n-\t\t'--man-path[print the manpath (see `man(1)`) for the man pages]' \\\n+\t\t'--exec-path=[path to where your core git programs are installed]: :_directories' \\\n+\t\t'(- :)--exec-path[print the path where your core git programs are installed]' \\\n+\t\t'(- :)--html-path[print the path where git''s HTML documentation is installed]' \\\n+\t\t'(- :)--info-path[print the path where the Info files are installed]' \\\n+\t\t'(- :)--man-path[print the manpath (see `man(1)`) for the man pages]' \\\n \t\t'--work-tree=[set the path to the working tree]: :_directories' \\\n \t\t'--namespace=[set the git namespace]:' \\\n \t\t'--no-replace-objects[do not use replacement refs to replace git objects]' \\\ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nindex 7283af3342..d0795ee014 100755\n--- a/t/t9904-zsh-completion.sh\n+++ b/t/t9904-zsh-completion.sh\n@@ -802,7 +802,7 @@ test_expect_success 'general options' '\n \ttest_completion \"git --no-r\" \"--no-replace-objects\"\n '\n \n-test_expect_failure 'general options plus command' '\n+test_expect_success 'general options plus command' '\n \ttest_completion \"git --version check\" \"\" &&\n \ttest_completion \"git --paginate check\" \"checkout\" &&\n \ttest_completion \"git --git-dir=foo check\" \"checkout\" &&\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462162","messageId":"20220830093138.1581538-28-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 27/51] completion: factor out check in __gitcomp","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:14Z","receivedAt":"2022-08-30T09:34:02Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"This way we can reorganize the rest of the function.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 6 ++++--\n contrib/completion/git-completion.zsh  | 4 ++--\n 2 files changed, 6 insertions(+), 4 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex ed126bbec4..86c335cfce 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -335,9 +335,11 @@ __gitcomp ()\n {\n \tlocal cur_=\"${3-$cur}\"\n \n+\tif [[ \"$cur_\" == *= ]]; then\n+\t\treturn\n+\tfi\n+\n \tcase \"$cur_\" in\n-\t*=)\n-\t\t;;\n \t--no-*)\n \t\tlocal c i=0 IFS=$' \\t\\n'\n \t\tfor c in $1; do\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 41272b00e3..808cf87f84 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -56,9 +56,9 @@ __gitcomp ()\n \n \tlocal cur_=\"${3-$cur}\"\n \n+\t[[ \"$cur_\" == *= ]] && return\n+\n \tcase \"$cur_\" in\n-\t*=)\n-\t\t;;\n \t--no-*)\n \t\tlocal c IFS=$' \\t\\n'\n \t\tlocal -a array\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462163","messageId":"20220830093138.1581538-27-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 26/51] completion: zsh: always set compset","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:13Z","receivedAt":"2022-08-30T09:34:03Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"So we don't have to set it every time.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 7 ++-----\n 1 file changed, 2 insertions(+), 5 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex d2eb221d79..41272b00e3 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -73,7 +73,6 @@ __gitcomp ()\n \t\t\tesac\n \t\t\tarray+=(\"$c\")\n \t\tdone\n-\t\tcompset -P '*[=:]'\n \t\tcompadd -Q -S '' -p \"${2-}\" -a -- array && _ret=0\n \t\t;;\n \t*)\n@@ -92,7 +91,6 @@ __gitcomp ()\n \t\t\tesac\n \t\t\tarray+=(\"$c\")\n \t\tdone\n-\t\tcompset -P '*[=:]'\n \t\tcompadd -Q -S '' -p \"${2-}\" -a -- array && _ret=0\n \t\t;;\n \tesac\n@@ -102,7 +100,6 @@ __gitcomp_direct ()\n {\n \temulate -L zsh\n \n-\tcompset -P '*[=:]'\n \tcompadd -Q -S '' -- ${(f)1} && _ret=0\n }\n \n@@ -110,7 +107,6 @@ __gitcomp_nl ()\n {\n \temulate -L zsh\n \n-\tcompset -P '*[=:]'\n \tcompadd -Q -S \"${4- }\" -p \"${2-}\" -- ${(f)1} && _ret=0\n }\n \n@@ -118,7 +114,6 @@ __gitcomp_file ()\n {\n \temulate -L zsh\n \n-\tcompset -P '*[=:]'\n \tcompadd -f -p \"${2-}\" -- ${(f)1} && _ret=0\n }\n \n@@ -136,6 +131,8 @@ __git_complete_command ()\n {\n \temulate -L zsh\n \n+\tcompset -P '*[=:]'\n+\n \tlocal command=\"$1\"\n \tlocal completion_func=\"_git_${command//-/_}\"\n \tif (( $+functions[$completion_func] )); then\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462164","messageId":"20220830093138.1581538-30-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 29/51] completion: refactor __gitcomp","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:16Z","receivedAt":"2022-08-30T09:34:05Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"We have two chunks of code doing exactly the same, there's no need for\nthat.\n\nNo functional changes.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 52 +++++++++-----------------\n contrib/completion/git-completion.zsh  | 52 ++++++++------------------\n 2 files changed, 34 insertions(+), 70 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 2a5e32e457..54b2c4e589 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -339,44 +339,28 @@ __gitcomp ()\n \t\treturn\n \tfi\n \n-\tcase \"$cur_\" in\n-\t--no-*)\n-\t\tlocal c i=0 IFS=$' \\t\\n'\n-\t\tfor c in $1; do\n-\t\t\tif [[ $c == \"--\" ]]; then\n+\tlocal c i=0 IFS=$' \\t\\n'\n+\tfor c in $1; do\n+\t\tif [[ $c == \"--\" ]]; then\n+\t\t\tif [[ \"$cur_\" == --no-* ]]; then\n \t\t\t\tcontinue\n \t\t\tfi\n-\t\t\tc=\"$c${4-}\"\n-\t\t\tif [[ $c == \"$cur_\"* ]]; then\n-\t\t\t\tcase $c in\n-\t\t\t\t*=|*.) ;;\n-\t\t\t\t*) c=\"$c \" ;;\n-\t\t\t\tesac\n-\t\t\t\tCOMPREPLY[i++]=\"${2-}$c\"\n-\t\t\tfi\n-\t\tdone\n-\t\t;;\n-\t*)\n-\t\tlocal c i=0 IFS=$' \\t\\n'\n-\t\tfor c in $1; do\n-\t\t\tif [[ $c == \"--\" ]]; then\n-\t\t\t\tc=\"--no-...${4-}\"\n-\t\t\t\tif [[ $c == \"$cur_\"* ]]; then\n-\t\t\t\t\tCOMPREPLY[i++]=\"${2-}$c \"\n-\t\t\t\tfi\n-\t\t\t\tbreak\n-\t\t\tfi\n-\t\t\tc=\"$c${4-}\"\n+\n+\t\t\tc=\"--no-...${4-}\"\n \t\t\tif [[ $c == \"$cur_\"* ]]; then\n-\t\t\t\tcase $c in\n-\t\t\t\t*=|*.) ;;\n-\t\t\t\t*) c=\"$c \" ;;\n-\t\t\t\tesac\n-\t\t\t\tCOMPREPLY[i++]=\"${2-}$c\"\n+\t\t\t\tCOMPREPLY[i++]=\"${2-}$c \"\n \t\t\tfi\n-\t\tdone\n-\t\t;;\n-\tesac\n+\t\t\tbreak\n+\t\tfi\n+\t\tc=\"$c${4-}\"\n+\t\tif [[ $c == \"$cur_\"* ]]; then\n+\t\t\tcase $c in\n+\t\t\t*=|*.) ;;\n+\t\t\t*) c=\"$c \" ;;\n+\t\t\tesac\n+\t\t\tCOMPREPLY[i++]=\"${2-}$c\"\n+\t\tfi\n+\tdone\n }\n \n # Clear the variables caching builtins' options when (re-)sourcing\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex a8ff9c089a..7616f87fa2 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -58,42 +58,22 @@ __gitcomp ()\n \n \t[[ \"$cur_\" == *= ]] && return\n \n-\tcase \"$cur_\" in\n-\t--no-*)\n-\t\tlocal c IFS=$' \\t\\n'\n-\t\tlocal -a array\n-\t\tfor c in ${=1}; do\n-\t\t\tif [[ $c == \"--\" ]]; then\n-\t\t\t\tcontinue\n-\t\t\tfi\n-\t\t\tc=\"$c${4-}\"\n-\t\t\tcase $c in\n-\t\t\t*=|*.) ;;\n-\t\t\t*) c=\"$c \" ;;\n-\t\t\tesac\n-\t\t\tarray+=(\"$c\")\n-\t\tdone\n-\t\tcompadd -Q -S '' -p \"${2-}\" -a -- array && _ret=0\n-\t\t;;\n-\t*)\n-\t\tlocal c IFS=$' \\t\\n'\n-\t\tlocal -a array\n-\t\tfor c in ${=1}; do\n-\t\t\tif [[ $c == \"--\" ]]; then\n-\t\t\t\tc=\"--no-...${4-}\"\n-\t\t\t\tarray+=(\"$c \")\n-\t\t\t\tbreak\n-\t\t\tfi\n-\t\t\tc=\"$c${4-}\"\n-\t\t\tcase $c in\n-\t\t\t*=|*.) ;;\n-\t\t\t*) c=\"$c \" ;;\n-\t\t\tesac\n-\t\t\tarray+=(\"$c\")\n-\t\tdone\n-\t\tcompadd -Q -S '' -p \"${2-}\" -a -- array && _ret=0\n-\t\t;;\n-\tesac\n+\tlocal c IFS=$' \\t\\n'\n+\tlocal -a array\n+\tfor c in ${=1}; do\n+\t\tif [[ $c == \"--\" ]]; then\n+\t\t\t[[ \"$cur_\" == --no-* ]] && continue\n+\t\t\tarray+=(\"--no-...${4-} \")\n+\t\t\tbreak\n+\t\tfi\n+\t\tc=\"$c${4-}\"\n+\t\tcase $c in\n+\t\t*=|*.) ;;\n+\t\t*) c=\"$c \" ;;\n+\t\tesac\n+\t\tarray+=(\"$c\")\n+\tdone\n+\tcompadd -Q -S '' -p \"${2-}\" -a -- array && _ret=0\n }\n \n __gitcomp_direct ()\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462165","messageId":"20220830093138.1581538-32-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 31/51] completion: bash: change suffix check in __gitcomp","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:18Z","receivedAt":"2022-08-30T09:34:06Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"We don't match the prefix, we shouldn't match the suffix either.\n\nThere are no functional changes since all the callers that add a suffix\nadd an =, and if $cur_ ended with that suffix, we would return\nimmediately.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex c9315d4f9a..2ff7de1274 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -351,8 +351,8 @@ __gitcomp ()\n \t\t\tfi\n \t\t\tbreak\n \t\tfi\n-\t\tc=\"$c${4-}\"\n \t\tif [[ $c == \"$cur_\"* ]]; then\n+\t\t\tc=\"$c${4-}\"\n \t\t\tcase $c in\n \t\t\t*=|*.) ;;\n \t\t\t*) c=\"$c \" ;;\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462166","messageId":"20220830093138.1581538-37-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 36/51] completion: add __gitcomp_opts","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:23Z","receivedAt":"2022-08-30T09:34:08Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Create a new simplified version of __gitcomp for most callers, and\n__gitcomp_opts for the ones that need reorganizing all the options.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 94 +++++++++++++++-----------\n contrib/completion/git-completion.zsh  |  8 +++\n t/t9902-completion.sh                  | 58 ++++++++--------\n t/t9904-zsh-completion.sh              | 54 +++++++--------\n 4 files changed, 117 insertions(+), 97 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 6610054e0e..2cedbd6cc8 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -324,13 +324,25 @@ __gitcompadd ()\n \tdone\n }\n \n-# Creates completion replies, reorganizing options and adding suffixes as needed.\n+# Creates completion replies.\n # It accepts 1 to 4 arguments:\n # 1: List of possible completion words.\n # 2: A prefix to be added to each possible completion word (optional).\n # 3: Generate possible completion matches for this word (optional).\n # 4: A suffix to be appended to each possible completion word (optional).\n __gitcomp ()\n+{\n+\tlocal IFS=$' \\t\\n'\n+\t__gitcompadd \"$1\" \"${2-}\" \"${3-$cur}\" \"${4- }\"\n+}\n+\n+# Creates completion replies, reorganizing options and adding suffixes as needed.\n+# It accepts 1 to 4 arguments:\n+# 1: List of possible completion words.\n+# 2: A prefix to be added to each possible completion word (optional).\n+# 3: Generate possible completion matches for this word (optional).\n+# 4: A suffix to be appended to each possible completion word (optional).\n+__gitcomp_opts ()\n {\n \tlocal cur_=\"${3-$cur}\"\n \n@@ -374,7 +386,7 @@ fi\n \n # This function is equivalent to\n #\n-#    __gitcomp \"$(git xxx --git-completion-helper) ...\"\n+#    __gitcomp_opts \"$(git xxx --git-completion-helper) ...\"\n #\n # except that the output is cached. Accept 1-3 arguments:\n # 1: the git command to execute, this is also the cache key\n@@ -409,7 +421,7 @@ __gitcomp_builtin ()\n \t\teval \"$var=\\\"$options\\\"\"\n \tfi\n \n-\t__gitcomp \"$options\"\n+\t__gitcomp_opts \"$options\"\n }\n \n # Generates completion reply from newline-separated possible completion words\n@@ -1046,7 +1058,7 @@ __git_complete_strategy ()\n \t\treturn 0\n \t\t;;\n \t-X)\n-\t\t__gitcomp \"$__git_merge_strategy_options\"\n+\t\t__gitcomp_opts \"$__git_merge_strategy_options\"\n \t\treturn 0\n \t\t;;\n \tesac\n@@ -1056,7 +1068,7 @@ __git_complete_strategy ()\n \t\treturn 0\n \t\t;;\n \t--strategy-option=*)\n-\t\t__gitcomp \"$__git_merge_strategy_options\" \"\" \"${cur##--strategy-option=}\"\n+\t\t__gitcomp_opts \"$__git_merge_strategy_options\" \"\" \"${cur##--strategy-option=}\"\n \t\treturn 0\n \t\t;;\n \tesac\n@@ -1298,7 +1310,7 @@ _git_am ()\n {\n \t__git_find_repo_path\n \tif [ -d \"$__git_repo_path\"/rebase-apply ]; then\n-\t\t__gitcomp \"$__git_am_inprogress_options\"\n+\t\t__gitcomp_opts \"$__git_am_inprogress_options\"\n \t\treturn\n \tfi\n \tcase \"$cur\" in\n@@ -1558,7 +1570,7 @@ _git_cherry_pick ()\n {\n \t__git_find_repo_path\n \tif [ -f \"$__git_repo_path\"/CHERRY_PICK_HEAD ]; then\n-\t\t__gitcomp \"$__git_cherry_pick_inprogress_options\"\n+\t\t__gitcomp_opts \"$__git_cherry_pick_inprogress_options\"\n \t\treturn\n \tfi\n \n@@ -1717,7 +1729,7 @@ _git_diff ()\n \t\treturn\n \t\t;;\n \t--*)\n-\t\t__gitcomp \"$__git_diff_difftool_options\"\n+\t\t__gitcomp_opts \"$__git_diff_difftool_options\"\n \t\treturn\n \t\t;;\n \tesac\n@@ -2011,7 +2023,7 @@ _git_log ()\n \t\treturn\n \t\t;;\n \t--*)\n-\t\t__gitcomp \"\n+\t\t__gitcomp_opts \"\n \t\t\t$__git_log_common_options\n \t\t\t$__git_log_shortlog_options\n \t\t\t$__git_log_gitk_options\n@@ -2074,7 +2086,7 @@ _git_mergetool ()\n \t\treturn\n \t\t;;\n \t--*)\n-\t\t__gitcomp \"--tool= --prompt --no-prompt --gui --no-gui\"\n+\t\t__gitcomp_opts \"--tool= --prompt --no-prompt --gui --no-gui\"\n \t\treturn\n \t\t;;\n \tesac\n@@ -2222,7 +2234,7 @@ _git_range_diff ()\n {\n \tcase \"$cur\" in\n \t--*)\n-\t\t__gitcomp \"\n+\t\t__gitcomp_opts \"\n \t\t\t--creation-factor= --no-dual-color\n \t\t\t$__git_diff_common_options\n \t\t\"\n@@ -2239,11 +2251,11 @@ _git_rebase ()\n {\n \t__git_find_repo_path\n \tif [ -f \"$__git_repo_path\"/rebase-merge/interactive ]; then\n-\t\t__gitcomp \"$__git_rebase_interactive_inprogress_options\"\n+\t\t__gitcomp_opts \"$__git_rebase_interactive_inprogress_options\"\n \t\treturn\n \telif [ -d \"$__git_repo_path\"/rebase-apply ] || \\\n \t     [ -d \"$__git_repo_path\"/rebase-merge ]; then\n-\t\t__gitcomp \"$__git_rebase_inprogress_options\"\n+\t\t__gitcomp_opts \"$__git_rebase_inprogress_options\"\n \t\treturn\n \tfi\n \t__git_complete_strategy && return\n@@ -2857,7 +2869,7 @@ _git_revert ()\n {\n \t__git_find_repo_path\n \tif [ -f \"$__git_repo_path\"/REVERT_HEAD ]; then\n-\t\t__gitcomp \"$__git_revert_inprogress_options\"\n+\t\t__gitcomp_opts \"$__git_revert_inprogress_options\"\n \t\treturn\n \tfi\n \t__git_complete_strategy && return\n@@ -2889,7 +2901,7 @@ _git_shortlog ()\n \n \tcase \"$cur\" in\n \t--*)\n-\t\t__gitcomp \"\n+\t\t__gitcomp_opts \"\n \t\t\t$__git_log_common_options\n \t\t\t$__git_log_shortlog_options\n \t\t\t--numbered --summary --email\n@@ -2927,7 +2939,7 @@ _git_show ()\n \t\treturn\n \t\t;;\n \t--*)\n-\t\t__gitcomp \"--pretty= --format= --abbrev-commit --no-abbrev-commit\n+\t\t__gitcomp_opts \"--pretty= --format= --abbrev-commit --no-abbrev-commit\n \t\t\t--oneline --show-signature\n \t\t\t--expand-tabs --expand-tabs= --no-expand-tabs\n \t\t\t$__git_diff_common_options\n@@ -3053,7 +3065,7 @@ _git_submodule ()\n \tif [ -z \"$subcommand\" ]; then\n \t\tcase \"$cur\" in\n \t\t--*)\n-\t\t\t__gitcomp \"--quiet\"\n+\t\t\t__gitcomp_opts \"--quiet\"\n \t\t\t;;\n \t\t*)\n \t\t\t__gitcomp \"$subcommands\"\n@@ -3064,29 +3076,29 @@ _git_submodule ()\n \n \tcase \"$subcommand,$cur\" in\n \tadd,--*)\n-\t\t__gitcomp \"--branch --force --name --reference --depth\"\n+\t\t__gitcomp_opts \"--branch --force --name --reference --depth\"\n \t\t;;\n \tstatus,--*)\n-\t\t__gitcomp \"--cached --recursive\"\n+\t\t__gitcomp_opts \"--cached --recursive\"\n \t\t;;\n \tdeinit,--*)\n-\t\t__gitcomp \"--force --all\"\n+\t\t__gitcomp_opts \"--force --all\"\n \t\t;;\n \tupdate,--*)\n-\t\t__gitcomp \"\n+\t\t__gitcomp_opts \"\n \t\t\t--init --remote --no-fetch\n \t\t\t--recommend-shallow --no-recommend-shallow\n \t\t\t--force --rebase --merge --reference --depth --recursive --jobs\n \t\t\"\n \t\t;;\n \tset-branch,--*)\n-\t\t__gitcomp \"--default --branch\"\n+\t\t__gitcomp_opts \"--default --branch\"\n \t\t;;\n \tsummary,--*)\n-\t\t__gitcomp \"--cached --files --summary-limit\"\n+\t\t__gitcomp_opts \"--cached --files --summary-limit\"\n \t\t;;\n \tforeach,--*|sync,--*)\n-\t\t__gitcomp \"--recursive\"\n+\t\t__gitcomp_opts \"--recursive\"\n \t\t;;\n \t*)\n \t\t;;\n@@ -3127,64 +3139,64 @@ _git_svn ()\n \n \t\tcase \"$subcommand,$cur\" in\n \t\tfetch,--*)\n-\t\t\t__gitcomp \"--revision= --fetch-all $fc_opts\"\n+\t\t\t__gitcomp_opts \"--revision= --fetch-all $fc_opts\"\n \t\t\t;;\n \t\tclone,--*)\n-\t\t\t__gitcomp \"--revision= $fc_opts $init_opts\"\n+\t\t\t__gitcomp_opts \"--revision= $fc_opts $init_opts\"\n \t\t\t;;\n \t\tinit,--*)\n-\t\t\t__gitcomp \"$init_opts\"\n+\t\t\t__gitcomp_opts \"$init_opts\"\n \t\t\t;;\n \t\tdcommit,--*)\n-\t\t\t__gitcomp \"\n+\t\t\t__gitcomp_opts \"\n \t\t\t\t--merge --strategy= --verbose --dry-run\n \t\t\t\t--fetch-all --no-rebase --commit-url\n \t\t\t\t--revision --interactive $cmt_opts $fc_opts\n \t\t\t\t\"\n \t\t\t;;\n \t\tset-tree,--*)\n-\t\t\t__gitcomp \"--stdin $cmt_opts $fc_opts\"\n+\t\t\t__gitcomp_opts \"--stdin $cmt_opts $fc_opts\"\n \t\t\t;;\n \t\tcreate-ignore,--*|propget,--*|proplist,--*|show-ignore,--*|\\\n \t\tshow-externals,--*|mkdirs,--*)\n-\t\t\t__gitcomp \"--revision=\"\n+\t\t\t__gitcomp_opts \"--revision=\"\n \t\t\t;;\n \t\tlog,--*)\n-\t\t\t__gitcomp \"\n+\t\t\t__gitcomp_opts \"\n \t\t\t\t--limit= --revision= --verbose --incremental\n \t\t\t\t--oneline --show-commit --non-recursive\n \t\t\t\t--authors-file= --color\n \t\t\t\t\"\n \t\t\t;;\n \t\trebase,--*)\n-\t\t\t__gitcomp \"\n+\t\t\t__gitcomp_opts \"\n \t\t\t\t--merge --verbose --strategy= --local\n \t\t\t\t--fetch-all --dry-run $fc_opts\n \t\t\t\t\"\n \t\t\t;;\n \t\tcommit-diff,--*)\n-\t\t\t__gitcomp \"--message= --file= --revision= $cmt_opts\"\n+\t\t\t__gitcomp_opts \"--message= --file= --revision= $cmt_opts\"\n \t\t\t;;\n \t\tinfo,--*)\n-\t\t\t__gitcomp \"--url\"\n+\t\t\t__gitcomp_opts \"--url\"\n \t\t\t;;\n \t\tbranch,--*)\n-\t\t\t__gitcomp \"--dry-run --message --tag\"\n+\t\t\t__gitcomp_opts \"--dry-run --message --tag\"\n \t\t\t;;\n \t\ttag,--*)\n-\t\t\t__gitcomp \"--dry-run --message\"\n+\t\t\t__gitcomp_opts \"--dry-run --message\"\n \t\t\t;;\n \t\tblame,--*)\n-\t\t\t__gitcomp \"--git-format\"\n+\t\t\t__gitcomp_opts \"--git-format\"\n \t\t\t;;\n \t\tmigrate,--*)\n-\t\t\t__gitcomp \"\n+\t\t\t__gitcomp_opts \"\n \t\t\t\t--config-dir= --ignore-paths= --minimize\n \t\t\t\t--no-auth-cache --username=\n \t\t\t\t\"\n \t\t\t;;\n \t\treset,--*)\n-\t\t\t__gitcomp \"--revision= --parent\"\n+\t\t\t__gitcomp_opts \"--revision= --parent\"\n \t\t\t;;\n \t\t*)\n \t\t\t;;\n@@ -3424,7 +3436,7 @@ __git_main ()\n \t\tesac\n \t\tcase \"$cur\" in\n \t\t--*)\n-\t\t\t__gitcomp \"\n+\t\t\t__gitcomp_opts \"\n \t\t\t--paginate\n \t\t\t--no-pager\n \t\t\t--git-dir=\n@@ -3481,7 +3493,7 @@ __gitk_main ()\n \tfi\n \tcase \"$cur\" in\n \t--*)\n-\t\t__gitcomp \"\n+\t\t__gitcomp_opts \"\n \t\t\t$__git_log_common_options\n \t\t\t$__git_log_gitk_options\n \t\t\t$merge\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 41aae0f454..2ad24f1510 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -54,6 +54,14 @@ __gitcomp ()\n {\n \temulate -L zsh\n \n+\tlocal IFS=$' \\t\\n'\n+\tcompadd -Q -S \"${4- }\" -p \"${2-}\" -- ${=1} && _ret=0\n+}\n+\n+__gitcomp_opts ()\n+{\n+\temulate -L zsh\n+\n \tlocal cur_=\"${3-$cur}\"\n \n \t[[ \"$cur_\" == *= ]] && return\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex e1e9c6e365..eb8e173e6b 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -98,17 +98,17 @@ test_completion ()\n \ttest_cmp expected out_sorted\n }\n \n-# Test __gitcomp.\n+# Test __gitcomp_opts.\n # The first argument is the typed text so far (cur); the rest are\n-# passed to __gitcomp.  Expected output comes is read from the\n+# passed to __gitcomp_opts.  Expected output comes is read from the\n # standard input, like test_completion().\n-test_gitcomp ()\n+test_gitcomp_opts ()\n {\n \tlocal -a COMPREPLY &&\n \tsed -e 's/Z$//' >expected &&\n \tlocal cur=\"$1\" &&\n \tshift &&\n-\t__gitcomp \"$@\" &&\n+\t__gitcomp_opts \"$@\" &&\n \tprint_comp &&\n \ttest_cmp expected out\n }\n@@ -463,8 +463,8 @@ test_expect_success '__gitcomp_direct - puts everything into COMPREPLY as-is' '\n \ttest_cmp expected out\n '\n \n-test_expect_success '__gitcomp - trailing space - options' '\n-\ttest_gitcomp \"--re\" \"--dry-run --reuse-message= --reedit-message=\n+test_expect_success '__gitcomp_opts - trailing space - options' '\n+\ttest_gitcomp_opts \"--re\" \"--dry-run --reuse-message= --reedit-message=\n \t\t--reset-author\" <<-EOF\n \t--reuse-message=Z\n \t--reedit-message=Z\n@@ -472,8 +472,8 @@ test_expect_success '__gitcomp - trailing space - options' '\n \tEOF\n '\n \n-test_expect_success '__gitcomp - trailing space - config keys' '\n-\ttest_gitcomp \"br\" \"branch. branch.autosetupmerge\n+test_expect_success '__gitcomp_opts - trailing space - config keys' '\n+\ttest_gitcomp_opts \"br\" \"branch. branch.autosetupmerge\n \t\tbranch.autosetuprebase browser.\" <<-\\EOF\n \tbranch.Z\n \tbranch.autosetupmerge Z\n@@ -482,32 +482,32 @@ test_expect_success '__gitcomp - trailing space - config keys' '\n \tEOF\n '\n \n-test_expect_success '__gitcomp - option parameter' '\n-\ttest_gitcomp \"--strategy=re\" \"octopus ours recursive resolve subtree\" \\\n+test_expect_success '__gitcomp_opts - option parameter' '\n+\ttest_gitcomp_opts \"--strategy=re\" \"octopus ours recursive resolve subtree\" \\\n \t\t\"\" \"re\" <<-\\EOF\n \trecursive Z\n \tresolve Z\n \tEOF\n '\n \n-test_expect_success '__gitcomp - prefix' '\n-\ttest_gitcomp \"branch.maint.me\" \"remote merge mergeoptions rebase\" \\\n+test_expect_success '__gitcomp_opts - prefix' '\n+\ttest_gitcomp_opts \"branch.maint.me\" \"remote merge mergeoptions rebase\" \\\n \t\t\"branch.maint.\" \"me\" <<-\\EOF\n \tbranch.maint.merge Z\n \tbranch.maint.mergeoptions Z\n \tEOF\n '\n \n-test_expect_success '__gitcomp - suffix' '\n-\ttest_gitcomp \"branch.ma\" \"master maint next seen\" \"branch.\" \\\n+test_expect_success '__gitcomp_opts - suffix' '\n+\ttest_gitcomp_opts \"branch.ma\" \"master maint next seen\" \"branch.\" \\\n \t\t\"ma\" \".\" <<-\\EOF\n \tbranch.master.Z\n \tbranch.maint.Z\n \tEOF\n '\n \n-test_expect_success '__gitcomp - ignore optional negative options' '\n-\ttest_gitcomp \"--\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n+test_expect_success '__gitcomp_opts - ignore optional negative options' '\n+\ttest_gitcomp_opts \"--\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n \t--abc Z\n \t--def Z\n \t--no-one Z\n@@ -515,44 +515,44 @@ test_expect_success '__gitcomp - ignore optional negative options' '\n \tEOF\n '\n \n-test_expect_success '__gitcomp - ignore/narrow optional negative options' '\n-\ttest_gitcomp \"--a\" \"--abc --abcdef --no-one -- --no-two\" <<-\\EOF\n+test_expect_success '__gitcomp_opts - ignore/narrow optional negative options' '\n+\ttest_gitcomp_opts \"--a\" \"--abc --abcdef --no-one -- --no-two\" <<-\\EOF\n \t--abc Z\n \t--abcdef Z\n \tEOF\n '\n \n-test_expect_success '__gitcomp - ignore/narrow optional negative options' '\n-\ttest_gitcomp \"--n\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n+test_expect_success '__gitcomp_opts - ignore/narrow optional negative options' '\n+\ttest_gitcomp_opts \"--n\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n \t--no-one Z\n \t--no-... Z\n \tEOF\n '\n \n-test_expect_success '__gitcomp - expand all negative options' '\n-\ttest_gitcomp \"--no-\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n+test_expect_success '__gitcomp_opts - expand all negative options' '\n+\ttest_gitcomp_opts \"--no-\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n \t--no-one Z\n \t--no-two Z\n \tEOF\n '\n \n-test_expect_success '__gitcomp - expand/narrow all negative options' '\n-\ttest_gitcomp \"--no-o\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n+test_expect_success '__gitcomp_opts - expand/narrow all negative options' '\n+\ttest_gitcomp_opts \"--no-o\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n \t--no-one Z\n \tEOF\n '\n \n-test_expect_success '__gitcomp - equal skip' '\n-\ttest_gitcomp \"--option=\" \"--option=\" <<-\\EOF &&\n+test_expect_success '__gitcomp_opts - equal skip' '\n+\ttest_gitcomp_opts \"--option=\" \"--option=\" <<-\\EOF &&\n \n \tEOF\n-\ttest_gitcomp \"option=\" \"option=\" <<-\\EOF\n+\ttest_gitcomp_opts \"option=\" \"option=\" <<-\\EOF\n \n \tEOF\n '\n \n-test_expect_success '__gitcomp - doesnt fail because of invalid variable name' '\n-\trun_func __gitcomp \"$invalid_variable_name\"\n+test_expect_success '__gitcomp_opts - doesnt fail because of invalid variable name' '\n+\trun_func __gitcomp_opts \"$invalid_variable_name\"\n '\n \n read -r -d \"\" refs <<-\\EOF\ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nindex 42917833e8..894f3287f4 100755\n--- a/t/t9904-zsh-completion.sh\n+++ b/t/t9904-zsh-completion.sh\n@@ -37,16 +37,16 @@ test_completion ()\n \ttest_cmp expected out_sorted\n }\n \n-# Test __gitcomp.\n+# Test __gitcomp_opts.\n # The first argument is the typed text so far (cur); the rest are\n-# passed to __gitcomp.  Expected output comes is read from the\n+# passed to __gitcomp_opts.  Expected output comes is read from the\n # standard input, like test_completion().\n-test_gitcomp ()\n+test_gitcomp_opts ()\n {\n \tsed -e 's/Z$//' >expected &&\n \tlocal cur=\"$1\" &&\n \tshift &&\n-\trun_completion \"git func __gitcomp $(printf \"%q \" \"$@\") $cur\" &&\n+\trun_completion \"git func __gitcomp_opts $(printf \"%q \" \"$@\") $cur\" &&\n \ttest_cmp expected out\n }\n \n@@ -78,8 +78,8 @@ test_expect_success 'setup for __git_find_repo_path/__gitdir tests' '\n \tgit init -b main otherrepo\n '\n \n-test_expect_success '__gitcomp - trailing space - options' '\n-\ttest_gitcomp \"--re\" \"--dry-run --reuse-message= --reedit-message=\n+test_expect_success '__gitcomp_opts - trailing space - options' '\n+\ttest_gitcomp_opts \"--re\" \"--dry-run --reuse-message= --reedit-message=\n \t\t--reset-author\" <<-EOF\n \t--reuse-message=Z\n \t--reedit-message=Z\n@@ -87,8 +87,8 @@ test_expect_success '__gitcomp - trailing space - options' '\n \tEOF\n '\n \n-test_expect_success '__gitcomp - trailing space - config keys' '\n-\ttest_gitcomp \"br\" \"branch. branch.autosetupmerge\n+test_expect_success '__gitcomp_opts - trailing space - config keys' '\n+\ttest_gitcomp_opts \"br\" \"branch. branch.autosetupmerge\n \t\tbranch.autosetuprebase browser.\" <<-\\EOF\n \tbranch.Z\n \tbranch.autosetupmerge Z\n@@ -97,32 +97,32 @@ test_expect_success '__gitcomp - trailing space - config keys' '\n \tEOF\n '\n \n-test_expect_success '__gitcomp - option parameter' '\n-\ttest_gitcomp \"--strategy=re\" \"octopus ours recursive resolve subtree\" \\\n+test_expect_success '__gitcomp_opts - option parameter' '\n+\ttest_gitcomp_opts \"--strategy=re\" \"octopus ours recursive resolve subtree\" \\\n \t\t\"\" \"re\" <<-\\EOF\n \trecursive Z\n \tresolve Z\n \tEOF\n '\n \n-test_expect_failure '__gitcomp - prefix' '\n-\ttest_gitcomp \"branch.maint.me\" \"remote merge mergeoptions rebase\" \\\n+test_expect_failure '__gitcomp_opts - prefix' '\n+\ttest_gitcomp_opts \"branch.maint.me\" \"remote merge mergeoptions rebase\" \\\n \t\t\"branch.maint.\" \"me\" <<-\\EOF\n \tbranch.maint.merge Z\n \tbranch.maint.mergeoptions Z\n \tEOF\n '\n \n-test_expect_failure '__gitcomp - suffix' '\n-\ttest_gitcomp \"branch.ma\" \"master maint next seen\" \"branch.\" \\\n+test_expect_failure '__gitcomp_opts - suffix' '\n+\ttest_gitcomp_opts \"branch.ma\" \"master maint next seen\" \"branch.\" \\\n \t\t\"ma\" \".\" <<-\\EOF\n \tbranch.master.Z\n \tbranch.maint.Z\n \tEOF\n '\n \n-test_expect_success '__gitcomp - ignore optional negative options' '\n-\ttest_gitcomp \"--\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n+test_expect_success '__gitcomp_opts - ignore optional negative options' '\n+\ttest_gitcomp_opts \"--\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n \t--abc Z\n \t--def Z\n \t--no-one Z\n@@ -130,38 +130,38 @@ test_expect_success '__gitcomp - ignore optional negative options' '\n \tEOF\n '\n \n-test_expect_success '__gitcomp - ignore/narrow optional negative options' '\n-\ttest_gitcomp \"--a\" \"--abc --abcdef --no-one -- --no-two\" <<-\\EOF\n+test_expect_success '__gitcomp_opts - ignore/narrow optional negative options' '\n+\ttest_gitcomp_opts \"--a\" \"--abc --abcdef --no-one -- --no-two\" <<-\\EOF\n \t--abc Z\n \t--abcdef Z\n \tEOF\n '\n \n-test_expect_success '__gitcomp - ignore/narrow optional negative options' '\n-\ttest_gitcomp \"--n\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n+test_expect_success '__gitcomp_opts - ignore/narrow optional negative options' '\n+\ttest_gitcomp_opts \"--n\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n \t--no-one Z\n \t--no-... Z\n \tEOF\n '\n \n-test_expect_success '__gitcomp - expand all negative options' '\n-\ttest_gitcomp \"--no-\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n+test_expect_success '__gitcomp_opts - expand all negative options' '\n+\ttest_gitcomp_opts \"--no-\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n \t--no-one Z\n \t--no-two Z\n \tEOF\n '\n \n-test_expect_success '__gitcomp - expand/narrow all negative options' '\n-\ttest_gitcomp \"--no-o\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n+test_expect_success '__gitcomp_opts - expand/narrow all negative options' '\n+\ttest_gitcomp_opts \"--no-o\" \"--abc --def --no-one -- --no-two\" <<-\\EOF\n \t--no-one Z\n \tEOF\n '\n \n-test_expect_success '__gitcomp - equal skip' '\n-\ttest_gitcomp \"--option=\" \"--option=\" <<-\\EOF &&\n+test_expect_success '__gitcomp_opts - equal skip' '\n+\ttest_gitcomp_opts \"--option=\" \"--option=\" <<-\\EOF &&\n \n \tEOF\n-\ttest_gitcomp \"option=\" \"option=\" <<-\\EOF\n+\ttest_gitcomp_opts \"option=\" \"option=\" <<-\\EOF\n \n \tEOF\n '\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462167","messageId":"20220830093138.1581538-38-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 37/51] completion: bash: cleanup __gitcomp* invocations","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:24Z","receivedAt":"2022-08-30T09:34:10Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Some __gitcomp calls should be __gitcomp_nl, and vice versa.\n\nNo functional changes.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 22 +++++++++-------------\n 1 file changed, 9 insertions(+), 13 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 2cedbd6cc8..499ccd3a93 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1374,7 +1374,7 @@ _git_archive ()\n {\n \tcase \"$cur\" in\n \t--format=*)\n-\t\t__gitcomp \"$(git archive --list)\" \"\" \"${cur##--format=}\"\n+\t\t__gitcomp_nl \"$(git archive --list)\" \"\" \"${cur##--format=}\"\n \t\treturn\n \t\t;;\n \t--remote=*)\n@@ -1788,9 +1788,7 @@ _git_format_patch ()\n {\n \tcase \"$cur\" in\n \t--thread=*)\n-\t\t__gitcomp \"\n-\t\t\tdeep shallow\n-\t\t\t\" \"\" \"${cur##--thread=}\"\n+\t\t__gitcomp \"deep shallow\" \"\" \"${cur##--thread=}\"\n \t\treturn\n \t\t;;\n \t--base=*|--interdiff=*|--range-diff=*)\n@@ -2296,7 +2294,7 @@ _git_send_email ()\n {\n \tcase \"$prev\" in\n \t--to|--cc|--bcc|--from)\n-\t\t__gitcomp \"$(__git send-email --dump-aliases)\"\n+\t\t__gitcomp_nl \"$(__git send-email --dump-aliases)\"\n \t\treturn\n \t\t;;\n \tesac\n@@ -2320,9 +2318,7 @@ _git_send_email ()\n \t\treturn\n \t\t;;\n \t--thread=*)\n-\t\t__gitcomp \"\n-\t\t\tdeep shallow\n-\t\t\t\" \"\" \"${cur##--thread=}\"\n+\t\t__gitcomp \"deep shallow\" \"\" \"${cur##--thread=}\"\n \t\treturn\n \t\t;;\n \t--to=*|--cc=*|--bcc=*|--from=*)\n@@ -2622,7 +2618,7 @@ __git_complete_config_variable_name ()\n \t\tlocal pfx=\"${cur_%.*}.\"\n \t\tcur_=\"${cur_#*.}\"\n \t\t__gitcomp_direct \"$(__git_heads \"$pfx\" \"$cur_\" \".\")\"\n-\t\t__gitcomp_nl $'autoSetupMerge\\nautoSetupRebase\\n' \"$pfx\" \"$cur_\" \"$sfx\"\n+\t\t__gitcomp \"autoSetupMerge autoSetupRebase\" \"$pfx\" \"$cur_\" \"$sfx\"\n \t\treturn\n \t\t;;\n \tguitool.*.*)\n@@ -2672,7 +2668,7 @@ __git_complete_config_variable_name ()\n \t\tlocal pfx=\"${cur_%.*}.\"\n \t\tcur_=\"${cur_#*.}\"\n \t\t__gitcomp_nl \"$(__git_remotes)\" \"$pfx\" \"$cur_\" \".\"\n-\t\t__gitcomp_nl \"pushDefault\" \"$pfx\" \"$cur_\" \"$sfx\"\n+\t\t__gitcomp \"pushDefault\" \"$pfx\" \"$cur_\" \"$sfx\"\n \t\treturn\n \t\t;;\n \turl.*.*)\n@@ -2687,7 +2683,7 @@ __git_complete_config_variable_name ()\n \t\t;;\n \t*)\n \t\t__git_compute_config_sections\n-\t\t__gitcomp \"$__git_config_sections\" \"\" \"$cur_\" \".\"\n+\t\t__gitcomp_nl \"$__git_config_sections\" \"\" \"$cur_\" \".\"\n \t\t;;\n \tesac\n }\n@@ -2781,7 +2777,7 @@ _git_remote ()\n \t\t__gitcomp_builtin remote_update\n \t\t;;\n \tupdate,*)\n-\t\t__gitcomp \"$(__git_remotes) $(__git_get_config_variables \"remotes\")\"\n+\t\t__gitcomp_nl \"$(__git_remotes) $(__git_get_config_variables \"remotes\")\"\n \t\t;;\n \tset-url,--*)\n \t\t__gitcomp_builtin remote_set-url\n@@ -3464,7 +3460,7 @@ __git_main ()\n \t\t\t\tthen\n \t\t\t\t\tlist_cmds=builtins,$list_cmds\n \t\t\t\tfi\n-\t\t\t\t__gitcomp \"$(__git --list-cmds=$list_cmds)\"\n+\t\t\t\t__gitcomp_nl \"$(__git --list-cmds=$list_cmds)\"\n \t\t\tfi\n \t\t\t;;\n \t\tesac\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462168","messageId":"20220830093138.1581538-35-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 34/51] completion: bash: simplify config_variable_name","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:21Z","receivedAt":"2022-08-30T09:34:13Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Now sfx is never null.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex d43ec03c12..9e15538f53 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -2611,7 +2611,7 @@ __git_complete_config_variable_name ()\n \t\tlocal pfx=\"${cur_%.*}.\"\n \t\tcur_=\"${cur_#*.}\"\n \t\t__gitcomp_direct \"$(__git_heads \"$pfx\" \"$cur_\" \".\")\"\n-\t\t__gitcomp_nl $'autoSetupMerge\\nautoSetupRebase\\n' \"$pfx\" \"$cur_\" \"${sfx- }\"\n+\t\t__gitcomp_nl $'autoSetupMerge\\nautoSetupRebase\\n' \"$pfx\" \"$cur_\" \"$sfx\"\n \t\treturn\n \t\t;;\n \tguitool.*.*)\n@@ -2645,7 +2645,7 @@ __git_complete_config_variable_name ()\n \t\tlocal pfx=\"${cur_%.*}.\"\n \t\tcur_=\"${cur_#*.}\"\n \t\t__git_compute_all_commands\n-\t\t__gitcomp_nl \"$__git_all_commands\" \"$pfx\" \"$cur_\" \"${sfx- }\"\n+\t\t__gitcomp_nl \"$__git_all_commands\" \"$pfx\" \"$cur_\" \"$sfx\"\n \t\treturn\n \t\t;;\n \tremote.*.*)\n@@ -2661,7 +2661,7 @@ __git_complete_config_variable_name ()\n \t\tlocal pfx=\"${cur_%.*}.\"\n \t\tcur_=\"${cur_#*.}\"\n \t\t__gitcomp_nl \"$(__git_remotes)\" \"$pfx\" \"$cur_\" \".\"\n-\t\t__gitcomp_nl \"pushDefault\" \"$pfx\" \"$cur_\" \"${sfx- }\"\n+\t\t__gitcomp_nl \"pushDefault\" \"$pfx\" \"$cur_\" \"$sfx\"\n \t\treturn\n \t\t;;\n \turl.*.*)\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462169","messageId":"20220830093138.1581538-36-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 35/51] completion: bash: improve __gitcomp description","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:22Z","receivedAt":"2022-08-30T09:34:15Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"It does a lot more than what is stated now.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 3 +--\n 1 file changed, 1 insertion(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 9e15538f53..6610054e0e 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -324,8 +324,7 @@ __gitcompadd ()\n \tdone\n }\n \n-# Generates completion reply, appending a space to possible completion words,\n-# if necessary.\n+# Creates completion replies, reorganizing options and adding suffixes as needed.\n # It accepts 1 to 4 arguments:\n # 1: List of possible completion words.\n # 2: A prefix to be added to each possible completion word (optional).\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462170","messageId":"20220830093138.1581538-39-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 38/51] completion: bash: shuffle __gitcomp functions","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:25Z","receivedAt":"2022-08-30T09:34:44Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"They are the ones that actually do the completion, put them at the top.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 270 +++++++++++++------------\n 1 file changed, 139 insertions(+), 131 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 499ccd3a93..1fb99265e4 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -59,6 +59,145 @@\n #     When set to \"1\" suggest all options, including options which are\n #     typically hidden (e.g. '--allow-empty' for 'git commit').\n \n+# The following functions are meant to modify COMPREPLY, which should not be\n+# modified directly.  The purpose is to localize the modifications so it's\n+# easier to emulate it in Zsh. Every time a new __gitcomp* function is added,\n+# the corresponding function should be added to Zsh.\n+\n+__gitcompadd ()\n+{\n+\tlocal x i=${#COMPREPLY[@]}\n+\tfor x in $1; do\n+\t\tif [[ \"$x\" == \"$3\"* ]]; then\n+\t\t\tCOMPREPLY[i++]=\"$2$x$4\"\n+\t\tfi\n+\tdone\n+}\n+\n+# Creates completion replies.\n+# It accepts 1 to 4 arguments:\n+# 1: List of possible completion words.\n+# 2: A prefix to be added to each possible completion word (optional).\n+# 3: Generate possible completion matches for this word (optional).\n+# 4: A suffix to be appended to each possible completion word (optional).\n+__gitcomp ()\n+{\n+\tlocal IFS=$' \\t\\n'\n+\t__gitcompadd \"$1\" \"${2-}\" \"${3-$cur}\" \"${4- }\"\n+}\n+\n+# Generates completion reply from newline-separated possible completion words\n+# by appending a space to all of them. The result is appended to COMPREPLY.\n+# It accepts 1 to 4 arguments:\n+# 1: List of possible completion words, separated by a single newline.\n+# 2: A prefix to be added to each possible completion word (optional).\n+# 3: Generate possible completion matches for this word (optional).\n+# 4: A suffix to be appended to each possible completion word instead of\n+#    the default space (optional).  If specified but empty, nothing is\n+#    appended.\n+__gitcomp_nl ()\n+{\n+\tlocal IFS=$'\\n'\n+\t__gitcompadd \"$1\" \"${2-}\" \"${3-$cur}\" \"${4- }\"\n+}\n+\n+# Appends prefiltered words to COMPREPLY without any additional processing.\n+# Callers must take care of providing only words that match the current word\n+# to be completed and adding any prefix and/or suffix (trailing space!), if\n+# necessary.\n+# 1: List of newline-separated matching completion words, complete with\n+#    prefix and suffix.\n+__gitcomp_direct ()\n+{\n+\tlocal IFS=$'\\n'\n+\n+\tCOMPREPLY+=($1)\n+}\n+\n+# Generates completion reply with compgen from newline-separated possible\n+# completion filenames.\n+# It accepts 1 to 3 arguments:\n+# 1: List of possible completion filenames, separated by a single newline.\n+# 2: A directory prefix to be added to each possible completion filename\n+#    (optional).\n+# 3: Generate possible completion matches for this word (optional).\n+__gitcomp_file ()\n+{\n+\tlocal IFS=$'\\n'\n+\n+\t# XXX does not work when the directory prefix contains a tilde,\n+\t# since tilde expansion is not applied.\n+\t# This means that COMPREPLY will be empty and Bash default\n+\t# completion will be used.\n+\t__gitcompadd \"$1\" \"${2-}\" \"${3-$cur}\" \"\"\n+\n+\t# use a hack to enable file mode in bash < 4\n+\tcompopt -o filenames +o nospace 2>/dev/null ||\n+\tcompgen -f /non-existing-dir/ >/dev/null ||\n+\ttrue\n+}\n+\n+# Fills the COMPREPLY array with prefiltered paths without any additional\n+# processing.\n+# Callers must take care of providing only paths that match the current path\n+# to be completed and adding any prefix path components, if necessary.\n+# 1: List of newline-separated matching paths, complete with all prefix\n+#    path components.\n+__gitcomp_file_direct ()\n+{\n+\tlocal IFS=$'\\n'\n+\n+\tCOMPREPLY+=($1)\n+\n+\t# use a hack to enable file mode in bash < 4\n+\tcompopt -o filenames +o nospace 2>/dev/null ||\n+\tcompgen -f /non-existing-dir/ >/dev/null ||\n+\ttrue\n+}\n+\n+# Creates completion replies, reorganizing options and adding suffixes as needed.\n+# It accepts 1 to 4 arguments:\n+# 1: List of possible completion words.\n+# 2: A prefix to be added to each possible completion word (optional).\n+# 3: Generate possible completion matches for this word (optional).\n+# 4: A suffix to be appended to each possible completion word (optional).\n+__gitcomp_opts ()\n+{\n+\tlocal cur_=\"${3-$cur}\"\n+\n+\tif [[ \"$cur_\" == *= ]]; then\n+\t\treturn\n+\tfi\n+\n+\tlocal c i=0 IFS=$' \\t\\n' sfx\n+\tfor c in $1; do\n+\t\tif [[ $c == \"--\" ]]; then\n+\t\t\tif [[ \"$cur_\" == --no-* ]]; then\n+\t\t\t\tcontinue\n+\t\t\tfi\n+\n+\t\t\tif [[ --no == \"$cur_\"* ]]; then\n+\t\t\t\tCOMPREPLY[i++]=\"--no-... \"\n+\t\t\tfi\n+\t\t\tbreak\n+\t\tfi\n+\t\tif [[ $c == \"$cur_\"* ]]; then\n+\t\t\tif [[ -z \"${4+set}\" ]]; then\n+\t\t\t\tcase $c in\n+\t\t\t\t*=|*.) sfx=\"\" ;;\n+\t\t\t\t*) sfx=\" \" ;;\n+\t\t\t\tesac\n+\t\t\telse\n+\t\t\t\tsfx=\"$4\"\n+\t\t\tfi\n+\t\t\tCOMPREPLY[i++]=\"${2-}$c$sfx\"\n+\t\tfi\n+\tdone\n+}\n+\n+# __gitcomp functions end here\n+# ==============================================================================\n+\n # Discovers the path to the git repository taking any '--git-dir=<path>' and\n # '-C <path>' options into account and stores it in the $__git_repo_path\n # variable.\n@@ -301,81 +440,6 @@ _get_comp_words_by_ref ()\n }\n fi\n \n-# Appends prefiltered words to COMPREPLY without any additional processing.\n-# Callers must take care of providing only words that match the current word\n-# to be completed and adding any prefix and/or suffix (trailing space!), if\n-# necessary.\n-# 1: List of newline-separated matching completion words, complete with\n-#    prefix and suffix.\n-__gitcomp_direct ()\n-{\n-\tlocal IFS=$'\\n'\n-\n-\tCOMPREPLY+=($1)\n-}\n-\n-__gitcompadd ()\n-{\n-\tlocal x i=${#COMPREPLY[@]}\n-\tfor x in $1; do\n-\t\tif [[ \"$x\" == \"$3\"* ]]; then\n-\t\t\tCOMPREPLY[i++]=\"$2$x$4\"\n-\t\tfi\n-\tdone\n-}\n-\n-# Creates completion replies.\n-# It accepts 1 to 4 arguments:\n-# 1: List of possible completion words.\n-# 2: A prefix to be added to each possible completion word (optional).\n-# 3: Generate possible completion matches for this word (optional).\n-# 4: A suffix to be appended to each possible completion word (optional).\n-__gitcomp ()\n-{\n-\tlocal IFS=$' \\t\\n'\n-\t__gitcompadd \"$1\" \"${2-}\" \"${3-$cur}\" \"${4- }\"\n-}\n-\n-# Creates completion replies, reorganizing options and adding suffixes as needed.\n-# It accepts 1 to 4 arguments:\n-# 1: List of possible completion words.\n-# 2: A prefix to be added to each possible completion word (optional).\n-# 3: Generate possible completion matches for this word (optional).\n-# 4: A suffix to be appended to each possible completion word (optional).\n-__gitcomp_opts ()\n-{\n-\tlocal cur_=\"${3-$cur}\"\n-\n-\tif [[ \"$cur_\" == *= ]]; then\n-\t\treturn\n-\tfi\n-\n-\tlocal c i=0 IFS=$' \\t\\n' sfx\n-\tfor c in $1; do\n-\t\tif [[ $c == \"--\" ]]; then\n-\t\t\tif [[ \"$cur_\" == --no-* ]]; then\n-\t\t\t\tcontinue\n-\t\t\tfi\n-\n-\t\t\tif [[ --no == \"$cur_\"* ]]; then\n-\t\t\t\tCOMPREPLY[i++]=\"--no-... \"\n-\t\t\tfi\n-\t\t\tbreak\n-\t\tfi\n-\t\tif [[ $c == \"$cur_\"* ]]; then\n-\t\t\tif [[ -z \"${4+set}\" ]]; then\n-\t\t\t\tcase $c in\n-\t\t\t\t*=|*.) sfx=\"\" ;;\n-\t\t\t\t*) sfx=\" \" ;;\n-\t\t\t\tesac\n-\t\t\telse\n-\t\t\t\tsfx=\"$4\"\n-\t\t\tfi\n-\t\t\tCOMPREPLY[i++]=\"${2-}$c$sfx\"\n-\t\tfi\n-\tdone\n-}\n-\n # Clear the variables caching builtins' options when (re-)sourcing\n # the completion script.\n if [[ -n ${ZSH_VERSION-} ]]; then\n@@ -424,62 +488,6 @@ __gitcomp_builtin ()\n \t__gitcomp_opts \"$options\"\n }\n \n-# Generates completion reply from newline-separated possible completion words\n-# by appending a space to all of them. The result is appended to COMPREPLY.\n-# It accepts 1 to 4 arguments:\n-# 1: List of possible completion words, separated by a single newline.\n-# 2: A prefix to be added to each possible completion word (optional).\n-# 3: Generate possible completion matches for this word (optional).\n-# 4: A suffix to be appended to each possible completion word instead of\n-#    the default space (optional).  If specified but empty, nothing is\n-#    appended.\n-__gitcomp_nl ()\n-{\n-\tlocal IFS=$'\\n'\n-\t__gitcompadd \"$1\" \"${2-}\" \"${3-$cur}\" \"${4- }\"\n-}\n-\n-# Fills the COMPREPLY array with prefiltered paths without any additional\n-# processing.\n-# Callers must take care of providing only paths that match the current path\n-# to be completed and adding any prefix path components, if necessary.\n-# 1: List of newline-separated matching paths, complete with all prefix\n-#    path components.\n-__gitcomp_file_direct ()\n-{\n-\tlocal IFS=$'\\n'\n-\n-\tCOMPREPLY+=($1)\n-\n-\t# use a hack to enable file mode in bash < 4\n-\tcompopt -o filenames +o nospace 2>/dev/null ||\n-\tcompgen -f /non-existing-dir/ >/dev/null ||\n-\ttrue\n-}\n-\n-# Generates completion reply with compgen from newline-separated possible\n-# completion filenames.\n-# It accepts 1 to 3 arguments:\n-# 1: List of possible completion filenames, separated by a single newline.\n-# 2: A directory prefix to be added to each possible completion filename\n-#    (optional).\n-# 3: Generate possible completion matches for this word (optional).\n-__gitcomp_file ()\n-{\n-\tlocal IFS=$'\\n'\n-\n-\t# XXX does not work when the directory prefix contains a tilde,\n-\t# since tilde expansion is not applied.\n-\t# This means that COMPREPLY will be empty and Bash default\n-\t# completion will be used.\n-\t__gitcompadd \"$1\" \"${2-}\" \"${3-$cur}\" \"\"\n-\n-\t# use a hack to enable file mode in bash < 4\n-\tcompopt -o filenames +o nospace 2>/dev/null ||\n-\tcompgen -f /non-existing-dir/ >/dev/null ||\n-\ttrue\n-}\n-\n # Execute 'git ls-files', unless the --committable option is specified, in\n # which case it runs 'git diff-index' to find out the files that can be\n # committed.  It return paths relative to the directory specified in the first\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462171","messageId":"20220830093138.1581538-40-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 39/51] completion: zsh: simplify __gitcomp_direct","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:26Z","receivedAt":"2022-08-30T09:34:50Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Not much different from __gitcomp_nl.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 4 +---\n 1 file changed, 1 insertion(+), 3 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 2ad24f1510..3619c93ea9 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -90,9 +90,7 @@ __gitcomp_opts ()\n \n __gitcomp_direct ()\n {\n-\temulate -L zsh\n-\n-\tcompadd -Q -S '' -- ${(f)1} && _ret=0\n+\t__gitcomp_nl \"$1\" \"\" \"\" \"\"\n }\n \n __gitcomp_nl ()\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462172","messageId":"20220830093138.1581538-43-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 42/51] completion: zsh: add elements individually in __gitcomp_opts","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:29Z","receivedAt":"2022-08-30T09:34:59Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"It's useful to specify specific suffixes for specific words.\n\nThis will be useful later on.\n\nAdditionally two tests now pass because we are not using an array\nanymore.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 6 ++----\n t/t9904-zsh-completion.sh             | 4 ++--\n 2 files changed, 4 insertions(+), 6 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 27ca6efe89..42bf9b95eb 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -67,11 +67,10 @@ __gitcomp_opts ()\n \t[[ \"$cur_\" == *= ]] && return\n \n \tlocal c IFS=$' \\t\\n' sfx\n-\tlocal -a array\n \tfor c in ${=1}; do\n \t\tif [[ $c == \"--\" ]]; then\n \t\t\t[[ \"$cur_\" == --no-* ]] && continue\n-\t\t\tarray+=(\"--no-... \")\n+\t\t\tcompadd -S \" \" -- \"--no-...\" && _ret=0\n \t\t\tbreak\n \t\tfi\n \n@@ -83,9 +82,8 @@ __gitcomp_opts ()\n \t\telse\n \t\t\tsfx=\"$4\"\n \t\tfi\n-\t\tarray+=(\"$c$sfx\")\n+\t\tcompadd -S \"$sfx\" -p \"${2-}\" -- \"$c\" && _ret=0\n \tdone\n-\tcompadd -S '' -p \"${2-}\" -a -- array && _ret=0\n }\n \n __gitcomp_nl ()\ndiff --git a/t/t9904-zsh-completion.sh b/t/t9904-zsh-completion.sh\nindex 894f3287f4..dc1578f41d 100755\n--- a/t/t9904-zsh-completion.sh\n+++ b/t/t9904-zsh-completion.sh\n@@ -105,7 +105,7 @@ test_expect_success '__gitcomp_opts - option parameter' '\n \tEOF\n '\n \n-test_expect_failure '__gitcomp_opts - prefix' '\n+test_expect_success '__gitcomp_opts - prefix' '\n \ttest_gitcomp_opts \"branch.maint.me\" \"remote merge mergeoptions rebase\" \\\n \t\t\"branch.maint.\" \"me\" <<-\\EOF\n \tbranch.maint.merge Z\n@@ -113,7 +113,7 @@ test_expect_failure '__gitcomp_opts - prefix' '\n \tEOF\n '\n \n-test_expect_failure '__gitcomp_opts - suffix' '\n+test_expect_success '__gitcomp_opts - suffix' '\n \ttest_gitcomp_opts \"branch.ma\" \"master maint next seen\" \"branch.\" \\\n \t\t\"ma\" \".\" <<-\\EOF\n \tbranch.master.Z\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462173","messageId":"20220830093138.1581538-44-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 43/51] completion: zsh: add __gitcompadd helper","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:30Z","receivedAt":"2022-08-30T09:35:02Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"So we don't have to do the same over and over.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 12 ++++++++----\n 1 file changed, 8 insertions(+), 4 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 42bf9b95eb..e66044ee89 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -50,12 +50,16 @@ COMP_WORDBREAKS=':'\n GIT_SOURCING_ZSH_COMPLETION=y . \"$script\"\n functions[complete]=\"$old_complete\"\n \n+__gitcompadd ()\n+{\n+\tcompadd -p \"${2-}\" -S \"${3- }\" -- ${=1} && _ret=0\n+}\n+\n __gitcomp ()\n {\n \temulate -L zsh\n \n-\tlocal IFS=$' \\t\\n'\n-\tcompadd -S \"${4- }\" -p \"${2-}\" -- ${=1} && _ret=0\n+\tIFS=$' \\t\\n' __gitcompadd \"$1\" \"${2-}\" \"${4- }\"\n }\n \n __gitcomp_opts ()\n@@ -70,7 +74,7 @@ __gitcomp_opts ()\n \tfor c in ${=1}; do\n \t\tif [[ $c == \"--\" ]]; then\n \t\t\t[[ \"$cur_\" == --no-* ]] && continue\n-\t\t\tcompadd -S \" \" -- \"--no-...\" && _ret=0\n+\t\t\t__gitcompadd \"--no-...\"\n \t\t\tbreak\n \t\tfi\n \n@@ -82,7 +86,7 @@ __gitcomp_opts ()\n \t\telse\n \t\t\tsfx=\"$4\"\n \t\tfi\n-\t\tcompadd -S \"$sfx\" -p \"${2-}\" -- \"$c\" && _ret=0\n+\t\t__gitcompadd \"$c\" \"${2-}\" \"$sfx\"\n \tdone\n }\n \n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462174","messageId":"20220830093138.1581538-41-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 40/51] completion: zsh: shuffle __gitcomp* functions","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:27Z","receivedAt":"2022-08-30T09:35:04Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 3619c93ea9..645b4bac31 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -88,11 +88,6 @@ __gitcomp_opts ()\n \tcompadd -Q -S '' -p \"${2-}\" -a -- array && _ret=0\n }\n \n-__gitcomp_direct ()\n-{\n-\t__gitcomp_nl \"$1\" \"\" \"\" \"\"\n-}\n-\n __gitcomp_nl ()\n {\n \temulate -L zsh\n@@ -107,6 +102,11 @@ __gitcomp_file ()\n \tcompadd -f -p \"${2-}\" -- ${(f)1} && _ret=0\n }\n \n+__gitcomp_direct ()\n+{\n+\t__gitcomp_nl \"$1\" \"\" \"\" \"\"\n+}\n+\n __gitcomp_file_direct ()\n {\n \t__gitcomp_file \"$1\" \"\"\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462175","messageId":"20220830093138.1581538-46-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 45/51] completion: bash: simplify _get_comp_words_by_ref()","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:32Z","receivedAt":"2022-08-30T09:35:08Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"We don't need the whole functionality of _get_comp_words_by_ref(), we\nknow exactly what we need from that function, so only do that.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 30 ++++++--------------------\n t/t9902-completion.sh                  | 21 ++++--------------\n 2 files changed, 10 insertions(+), 41 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 1fb99265e4..45550f7839 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -413,30 +413,12 @@ __git_reassemble_comp_words_by_ref()\n if ! type _get_comp_words_by_ref >/dev/null 2>&1; then\n _get_comp_words_by_ref ()\n {\n-\tlocal exclude cur_ words_ cword_\n-\tif [ \"$1\" = \"-n\" ]; then\n-\t\texclude=$2\n-\t\tshift 2\n-\tfi\n-\t__git_reassemble_comp_words_by_ref \"$exclude\"\n-\tcur_=${words_[cword_]}\n-\twhile [ $# -gt 0 ]; do\n-\t\tcase \"$1\" in\n-\t\tcur)\n-\t\t\tcur=$cur_\n-\t\t\t;;\n-\t\tprev)\n-\t\t\tprev=${words_[$cword_-1]}\n-\t\t\t;;\n-\t\twords)\n-\t\t\twords=(\"${words_[@]}\")\n-\t\t\t;;\n-\t\tcword)\n-\t\t\tcword=$cword_\n-\t\t\t;;\n-\t\tesac\n-\t\tshift\n-\tdone\n+\tlocal words_ cword_\n+\t__git_reassemble_comp_words_by_ref \"=:\"\n+\tcword=$cword_\n+\tcur=${words_[cword]}\n+\tprev=${words_[cword-1]}\n+\twords=(\"${words_[@]}\")\n }\n fi\n \ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex eb8e173e6b..fc09bafa07 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -40,23 +40,10 @@ GIT_TESTING_PORCELAIN_COMMAND_LIST='add checkout rebase'\n # So let's override it with a minimal version for testing purposes.\n _get_comp_words_by_ref ()\n {\n-\twhile [ $# -gt 0 ]; do\n-\t\tcase \"$1\" in\n-\t\tcur)\n-\t\t\tcur=${_words[_cword]}\n-\t\t\t;;\n-\t\tprev)\n-\t\t\tprev=${_words[_cword-1]}\n-\t\t\t;;\n-\t\twords)\n-\t\t\twords=(\"${_words[@]}\")\n-\t\t\t;;\n-\t\tcword)\n-\t\t\tcword=$_cword\n-\t\t\t;;\n-\t\tesac\n-\t\tshift\n-\tdone\n+\tcword=$_cword\n+\tcur=${_words[cword]}\n+\tprev=${_words[cword-1]}\n+\twords=(\"${_words[@]}\")\n }\n \n print_comp ()\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462176","messageId":"20220830093138.1581538-42-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 41/51] completion: zsh: fix direct quoting","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:28Z","receivedAt":"2022-08-30T09:35:18Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Apparently using \"compadd -Q\" is almost always wrong, we want zsh to add\nquoting when necessary. However, if we remove the -Q option, that would\nmake zsh add an extra \"\\ \" at the end of some completions.\n\nWe can manually remove the spaces from the completions that have them,\nand then add the suffix with the -S option, thus there's no more need\nfor the -Q option.\n\nThis makes completions like \"stash@{0}\" complete correctly:\n\n  git stash show <tab>\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 9 ++++++---\n 1 file changed, 6 insertions(+), 3 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 645b4bac31..27ca6efe89 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -55,7 +55,7 @@ __gitcomp ()\n \temulate -L zsh\n \n \tlocal IFS=$' \\t\\n'\n-\tcompadd -Q -S \"${4- }\" -p \"${2-}\" -- ${=1} && _ret=0\n+\tcompadd -S \"${4- }\" -p \"${2-}\" -- ${=1} && _ret=0\n }\n \n __gitcomp_opts ()\n@@ -85,14 +85,17 @@ __gitcomp_opts ()\n \t\tfi\n \t\tarray+=(\"$c$sfx\")\n \tdone\n-\tcompadd -Q -S '' -p \"${2-}\" -a -- array && _ret=0\n+\tcompadd -S '' -p \"${2-}\" -a -- array && _ret=0\n }\n \n __gitcomp_nl ()\n {\n \temulate -L zsh\n \n-\tcompadd -Q -S \"${4- }\" -p \"${2-}\" -- ${(f)1} && _ret=0\n+\t# words that don't end up in space\n+\tcompadd -p \"${2-}\" -S \"${4- }\" -q -- ${${(f)1}:#*\\ } && _ret=0\n+\t# words that end in space\n+\tcompadd -p \"${2-}\" -S \" ${4- }\" -q -- ${${(M)${(f)1}:#*\\ }% } && _ret=0\n }\n \n __gitcomp_file ()\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462177","messageId":"20220830093138.1581538-45-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 44/51] completion: zsh: add correct removable suffix","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:31Z","receivedAt":"2022-08-30T09:35:22Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Zsh has a nice feature that allows a suffix to be automatically removed\nif followed by a space.\n\nFor example:\n\n  git log --prety=\n\nIf a space is typed, the suffix '=' is removed.\n\nBut we have to set the correct prefix first.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex e66044ee89..7d34522621 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -52,7 +52,7 @@ functions[complete]=\"$old_complete\"\n \n __gitcompadd ()\n {\n-\tcompadd -p \"${2-}\" -S \"${3- }\" -- ${=1} && _ret=0\n+\tcompadd -p \"${2-}\" -S \"${3- }\" -q -- ${=1} && _ret=0\n }\n \n __gitcomp ()\n@@ -80,7 +80,8 @@ __gitcomp_opts ()\n \n \t\tif [[ -z \"${4+set}\" ]]; then\n \t\t\tcase $c in\n-\t\t\t*=|*.) sfx=\"\" ;;\n+\t\t\t*=) c=\"${c%=}\"; sfx=\"=\" ;;\n+\t\t\t*.) sfx=\"\" ;;\n \t\t\t*) sfx=\" \" ;;\n \t\t\tesac\n \t\telse\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462178","messageId":"20220830093138.1581538-49-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 48/51] completion: bash: trivial cleanup","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:35Z","receivedAt":"2022-08-30T09:35:24Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"The most typical case first (COMP_WORDBREAKS contains our wanted words).\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 92831977d7..395a356106 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -360,9 +360,7 @@ _get_comp_words_by_ref ()\n \t# Which word separators to exclude?\n \texclude=\"${COMP_WORDBREAKS//[^=:]}\"\n \tcword=$COMP_CWORD\n-\tif [ -z \"$exclude\" ]; then\n-\t\twords=(\"${COMP_WORDS[@]}\")\n-\telse\n+\tif [ -n \"$exclude\" ]; then\n \t\t# List of word completion separators has shrunk;\n \t\t# re-assemble words to complete.\n \t\tfor ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do\n@@ -397,6 +395,8 @@ _get_comp_words_by_ref ()\n \t\t\t\tcword=$j\n \t\t\tfi\n \t\tdone\n+\telse\n+\t\twords=(\"${COMP_WORDS[@]}\")\n \tfi\n \n \tcur=${words[cword]}\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462179","messageId":"20220830093138.1581538-48-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 47/51] completion: bash: cleanup _get_comp_words_by_ref()","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:34Z","receivedAt":"2022-08-30T09:35:26Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Remove temporary variables.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 19 ++++++++-----------\n 1 file changed, 8 insertions(+), 11 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 4261143d97..92831977d7 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -355,14 +355,13 @@ __git_dequote ()\n if ! type _get_comp_words_by_ref >/dev/null 2>&1; then\n _get_comp_words_by_ref ()\n {\n-\tlocal words_ cword_\n \tlocal exclude i j first\n \n \t# Which word separators to exclude?\n \texclude=\"${COMP_WORDBREAKS//[^=:]}\"\n-\tcword_=$COMP_CWORD\n+\tcword=$COMP_CWORD\n \tif [ -z \"$exclude\" ]; then\n-\t\twords_=(\"${COMP_WORDS[@]}\")\n+\t\twords=(\"${COMP_WORDS[@]}\")\n \telse\n \t\t# List of word completion separators has shrunk;\n \t\t# re-assemble words to complete.\n@@ -382,9 +381,9 @@ _get_comp_words_by_ref ()\n \t\t\t\t\t((j--))\n \t\t\t\tfi\n \t\t\t\tfirst=\n-\t\t\t\twords_[$j]=${words_[j]}${COMP_WORDS[i]}\n+\t\t\t\twords[$j]=${words[j]}${COMP_WORDS[i]}\n \t\t\t\tif [ $i = $COMP_CWORD ]; then\n-\t\t\t\t\tcword_=$j\n+\t\t\t\t\tcword=$j\n \t\t\t\tfi\n \t\t\t\tif (($i < ${#COMP_WORDS[@]} - 1)); then\n \t\t\t\t\t((i++))\n@@ -393,17 +392,15 @@ _get_comp_words_by_ref ()\n \t\t\t\t\tbreak 2\n \t\t\t\tfi\n \t\t\tdone\n-\t\t\twords_[$j]=${words_[j]}${COMP_WORDS[i]}\n+\t\t\twords[$j]=${words[j]}${COMP_WORDS[i]}\n \t\t\tif [ $i = $COMP_CWORD ]; then\n-\t\t\t\tcword_=$j\n+\t\t\t\tcword=$j\n \t\t\tfi\n \t\tdone\n \tfi\n \n-\tcword=$cword_\n-\tcur=${words_[cword]}\n-\tprev=${words_[cword-1]}\n-\twords=(\"${words_[@]}\")\n+\tcur=${words[cword]}\n+\tprev=${words[cword-1]}\n }\n fi\n \n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462180","messageId":"20220830093138.1581538-47-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 46/51] completion: bash: refactor _get_comp_words_by_ref()","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:33Z","receivedAt":"2022-08-30T09:35:29Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"We don't need a separate function to do what we already know we want to\ndo.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 93 +++++++++++---------------\n 1 file changed, 39 insertions(+), 54 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 45550f7839..4261143d97 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -339,21 +339,11 @@ __git_dequote ()\n #\n #   RELEASE: 2.x\n \n-# This function can be used to access a tokenized list of words\n-# on the command line:\n-#\n-#\t__git_reassemble_comp_words_by_ref '=:'\n-#\tif test \"${words_[cword_-1]}\" = -w\n-#\tthen\n-#\t\t...\n-#\tfi\n-#\n-# The argument should be a collection of characters from the list of\n-# word completion separators (COMP_WORDBREAKS) to treat as ordinary\n-# characters.\n+# This function reorganizes the words on the command line to be processed by\n+# the rest of the script.\n #\n # This is roughly equivalent to going back in time and setting\n-# COMP_WORDBREAKS to exclude those characters.  The intent is to\n+# COMP_WORDBREAKS to exclude '=' and ':'.  The intent is to\n # make option types like --date=<type> and <rev>:<path> easy to\n # recognize by treating each shell word as a single token.\n #\n@@ -361,60 +351,55 @@ __git_dequote ()\n # shared with other completion scripts.  By the time the completion\n # function gets called, COMP_WORDS has already been populated so local\n # changes to COMP_WORDBREAKS have no effect.\n-#\n-# Output: words_, cword_, cur_.\n \n-__git_reassemble_comp_words_by_ref()\n+if ! type _get_comp_words_by_ref >/dev/null 2>&1; then\n+_get_comp_words_by_ref ()\n {\n+\tlocal words_ cword_\n \tlocal exclude i j first\n+\n \t# Which word separators to exclude?\n-\texclude=\"${1//[^$COMP_WORDBREAKS]}\"\n+\texclude=\"${COMP_WORDBREAKS//[^=:]}\"\n \tcword_=$COMP_CWORD\n \tif [ -z \"$exclude\" ]; then\n \t\twords_=(\"${COMP_WORDS[@]}\")\n-\t\treturn\n-\tfi\n-\t# List of word completion separators has shrunk;\n-\t# re-assemble words to complete.\n-\tfor ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do\n-\t\t# Append each nonempty word consisting of just\n-\t\t# word separator characters to the current word.\n-\t\tfirst=t\n-\t\twhile\n-\t\t\t[ $i -gt 0 ] &&\n-\t\t\t[ -n \"${COMP_WORDS[$i]}\" ] &&\n-\t\t\t# word consists of excluded word separators\n-\t\t\t[ \"${COMP_WORDS[$i]//[^$exclude]}\" = \"${COMP_WORDS[$i]}\" ]\n-\t\tdo\n-\t\t\t# Attach to the previous token,\n-\t\t\t# unless the previous token is the command name.\n-\t\t\tif [ $j -ge 2 ] && [ -n \"$first\" ]; then\n-\t\t\t\t((j--))\n-\t\t\tfi\n-\t\t\tfirst=\n+\telse\n+\t\t# List of word completion separators has shrunk;\n+\t\t# re-assemble words to complete.\n+\t\tfor ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do\n+\t\t\t# Append each nonempty word consisting of just\n+\t\t\t# word separator characters to the current word.\n+\t\t\tfirst=t\n+\t\t\twhile\n+\t\t\t\t[ $i -gt 0 ] &&\n+\t\t\t\t[ -n \"${COMP_WORDS[$i]}\" ] &&\n+\t\t\t\t# word consists of excluded word separators\n+\t\t\t\t[ \"${COMP_WORDS[$i]//[^$exclude]}\" = \"${COMP_WORDS[$i]}\" ]\n+\t\t\tdo\n+\t\t\t\t# Attach to the previous token,\n+\t\t\t\t# unless the previous token is the command name.\n+\t\t\t\tif [ $j -ge 2 ] && [ -n \"$first\" ]; then\n+\t\t\t\t\t((j--))\n+\t\t\t\tfi\n+\t\t\t\tfirst=\n+\t\t\t\twords_[$j]=${words_[j]}${COMP_WORDS[i]}\n+\t\t\t\tif [ $i = $COMP_CWORD ]; then\n+\t\t\t\t\tcword_=$j\n+\t\t\t\tfi\n+\t\t\t\tif (($i < ${#COMP_WORDS[@]} - 1)); then\n+\t\t\t\t\t((i++))\n+\t\t\t\telse\n+\t\t\t\t\t# Done.\n+\t\t\t\t\tbreak 2\n+\t\t\t\tfi\n+\t\t\tdone\n \t\t\twords_[$j]=${words_[j]}${COMP_WORDS[i]}\n \t\t\tif [ $i = $COMP_CWORD ]; then\n \t\t\t\tcword_=$j\n \t\t\tfi\n-\t\t\tif (($i < ${#COMP_WORDS[@]} - 1)); then\n-\t\t\t\t((i++))\n-\t\t\telse\n-\t\t\t\t# Done.\n-\t\t\t\treturn\n-\t\t\tfi\n \t\tdone\n-\t\twords_[$j]=${words_[j]}${COMP_WORDS[i]}\n-\t\tif [ $i = $COMP_CWORD ]; then\n-\t\t\tcword_=$j\n-\t\tfi\n-\tdone\n-}\n+\tfi\n \n-if ! type _get_comp_words_by_ref >/dev/null 2>&1; then\n-_get_comp_words_by_ref ()\n-{\n-\tlocal words_ cword_\n-\t__git_reassemble_comp_words_by_ref \"=:\"\n \tcword=$cword_\n \tcur=${words_[cword]}\n \tprev=${words_[cword-1]}\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462181","messageId":"20220830093138.1581538-50-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 49/51] completion: bash: rename _get_comp_words_by_ref()","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:36Z","receivedAt":"2022-08-30T09:35:48Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"It's only used in one place, rename it, and use it even if\nbash-completion's more inefficient version of _get_comp_words_by_ref()\nis available.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 186 ++++++++++++-------------\n t/t9902-completion.sh                  |   2 +-\n 2 files changed, 94 insertions(+), 94 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 395a356106..77a475e272 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -312,98 +312,6 @@ __git_dequote ()\n \tdone\n }\n \n-# The following function is based on code from:\n-#\n-#   bash_completion - programmable completion functions for bash 3.2+\n-#\n-#   Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>\n-#             © 2009-2010, Bash Completion Maintainers\n-#                     <bash-completion-devel@lists.alioth.debian.org>\n-#\n-#   This program is free software; you can redistribute it and/or modify\n-#   it under the terms of the GNU General Public License as published by\n-#   the Free Software Foundation; either version 2, or (at your option)\n-#   any later version.\n-#\n-#   This program is distributed in the hope that it will be useful,\n-#   but WITHOUT ANY WARRANTY; without even the implied warranty of\n-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n-#   GNU General Public License for more details.\n-#\n-#   You should have received a copy of the GNU General Public License\n-#   along with this program; if not, see <http://www.gnu.org/licenses/>.\n-#\n-#   The latest version of this software can be obtained here:\n-#\n-#   http://bash-completion.alioth.debian.org/\n-#\n-#   RELEASE: 2.x\n-\n-# This function reorganizes the words on the command line to be processed by\n-# the rest of the script.\n-#\n-# This is roughly equivalent to going back in time and setting\n-# COMP_WORDBREAKS to exclude '=' and ':'.  The intent is to\n-# make option types like --date=<type> and <rev>:<path> easy to\n-# recognize by treating each shell word as a single token.\n-#\n-# It is best not to set COMP_WORDBREAKS directly because the value is\n-# shared with other completion scripts.  By the time the completion\n-# function gets called, COMP_WORDS has already been populated so local\n-# changes to COMP_WORDBREAKS have no effect.\n-\n-if ! type _get_comp_words_by_ref >/dev/null 2>&1; then\n-_get_comp_words_by_ref ()\n-{\n-\tlocal exclude i j first\n-\n-\t# Which word separators to exclude?\n-\texclude=\"${COMP_WORDBREAKS//[^=:]}\"\n-\tcword=$COMP_CWORD\n-\tif [ -n \"$exclude\" ]; then\n-\t\t# List of word completion separators has shrunk;\n-\t\t# re-assemble words to complete.\n-\t\tfor ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do\n-\t\t\t# Append each nonempty word consisting of just\n-\t\t\t# word separator characters to the current word.\n-\t\t\tfirst=t\n-\t\t\twhile\n-\t\t\t\t[ $i -gt 0 ] &&\n-\t\t\t\t[ -n \"${COMP_WORDS[$i]}\" ] &&\n-\t\t\t\t# word consists of excluded word separators\n-\t\t\t\t[ \"${COMP_WORDS[$i]//[^$exclude]}\" = \"${COMP_WORDS[$i]}\" ]\n-\t\t\tdo\n-\t\t\t\t# Attach to the previous token,\n-\t\t\t\t# unless the previous token is the command name.\n-\t\t\t\tif [ $j -ge 2 ] && [ -n \"$first\" ]; then\n-\t\t\t\t\t((j--))\n-\t\t\t\tfi\n-\t\t\t\tfirst=\n-\t\t\t\twords[$j]=${words[j]}${COMP_WORDS[i]}\n-\t\t\t\tif [ $i = $COMP_CWORD ]; then\n-\t\t\t\t\tcword=$j\n-\t\t\t\tfi\n-\t\t\t\tif (($i < ${#COMP_WORDS[@]} - 1)); then\n-\t\t\t\t\t((i++))\n-\t\t\t\telse\n-\t\t\t\t\t# Done.\n-\t\t\t\t\tbreak 2\n-\t\t\t\tfi\n-\t\t\tdone\n-\t\t\twords[$j]=${words[j]}${COMP_WORDS[i]}\n-\t\t\tif [ $i = $COMP_CWORD ]; then\n-\t\t\t\tcword=$j\n-\t\t\tfi\n-\t\tdone\n-\telse\n-\t\twords=(\"${COMP_WORDS[@]}\")\n-\tfi\n-\n-\tcur=${words[cword]}\n-\tprev=${words[cword-1]}\n-}\n-fi\n-\n # Clear the variables caching builtins' options when (re-)sourcing\n # the completion script.\n if [[ -n ${ZSH_VERSION-} ]]; then\n@@ -3477,10 +3385,102 @@ if [[ -n ${ZSH_VERSION-} && -z ${GIT_SOURCING_ZSH_COMPLETION-} ]]; then\n \treturn\n fi\n \n+# The following function is based on code from:\n+#\n+#   bash_completion - programmable completion functions for bash 3.2+\n+#\n+#   Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>\n+#             © 2009-2010, Bash Completion Maintainers\n+#                     <bash-completion-devel@lists.alioth.debian.org>\n+#\n+#   This program is free software; you can redistribute it and/or modify\n+#   it under the terms of the GNU General Public License as published by\n+#   the Free Software Foundation; either version 2, or (at your option)\n+#   any later version.\n+#\n+#   This program is distributed in the hope that it will be useful,\n+#   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+#   GNU General Public License for more details.\n+#\n+#   You should have received a copy of the GNU General Public License\n+#   along with this program; if not, see <http://www.gnu.org/licenses/>.\n+#\n+#   The latest version of this software can be obtained here:\n+#\n+#   http://bash-completion.alioth.debian.org/\n+#\n+#   RELEASE: 2.x\n+\n+# This function reorganizes the words on the command line to be processed by\n+# the rest of the script.\n+#\n+# This is roughly equivalent to going back in time and setting\n+# COMP_WORDBREAKS to exclude '=' and ':'.  The intent is to\n+# make option types like --date=<type> and <rev>:<path> easy to\n+# recognize by treating each shell word as a single token.\n+#\n+# It is best not to set COMP_WORDBREAKS directly because the value is\n+# shared with other completion scripts.  By the time the completion\n+# function gets called, COMP_WORDS has already been populated so local\n+# changes to COMP_WORDBREAKS have no effect.\n+\n+if ! type __git_get_comp_words_by_ref >/dev/null 2>&1; then\n+__git_get_comp_words_by_ref ()\n+{\n+\tlocal exclude i j first\n+\n+\t# Which word separators to exclude?\n+\texclude=\"${COMP_WORDBREAKS//[^=:]}\"\n+\tcword=$COMP_CWORD\n+\tif [ -n \"$exclude\" ]; then\n+\t\t# List of word completion separators has shrunk;\n+\t\t# re-assemble words to complete.\n+\t\tfor ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do\n+\t\t\t# Append each nonempty word consisting of just\n+\t\t\t# word separator characters to the current word.\n+\t\t\tfirst=t\n+\t\t\twhile\n+\t\t\t\t[ $i -gt 0 ] &&\n+\t\t\t\t[ -n \"${COMP_WORDS[$i]}\" ] &&\n+\t\t\t\t# word consists of excluded word separators\n+\t\t\t\t[ \"${COMP_WORDS[$i]//[^$exclude]}\" = \"${COMP_WORDS[$i]}\" ]\n+\t\t\tdo\n+\t\t\t\t# Attach to the previous token,\n+\t\t\t\t# unless the previous token is the command name.\n+\t\t\t\tif [ $j -ge 2 ] && [ -n \"$first\" ]; then\n+\t\t\t\t\t((j--))\n+\t\t\t\tfi\n+\t\t\t\tfirst=\n+\t\t\t\twords[$j]=${words[j]}${COMP_WORDS[i]}\n+\t\t\t\tif [ $i = $COMP_CWORD ]; then\n+\t\t\t\t\tcword=$j\n+\t\t\t\tfi\n+\t\t\t\tif (($i < ${#COMP_WORDS[@]} - 1)); then\n+\t\t\t\t\t((i++))\n+\t\t\t\telse\n+\t\t\t\t\t# Done.\n+\t\t\t\t\tbreak 2\n+\t\t\t\tfi\n+\t\t\tdone\n+\t\t\twords[$j]=${words[j]}${COMP_WORDS[i]}\n+\t\t\tif [ $i = $COMP_CWORD ]; then\n+\t\t\t\tcword=$j\n+\t\t\tfi\n+\t\tdone\n+\telse\n+\t\twords=(\"${COMP_WORDS[@]}\")\n+\tfi\n+\n+\tcur=${words[cword]}\n+\tprev=${words[cword-1]}\n+}\n+fi\n+\n __git_func_wrap ()\n {\n \tlocal cur words cword prev __git_cmd_idx=0\n-\t_get_comp_words_by_ref -n =: cur words cword prev\n+\t__git_get_comp_words_by_ref\n \t$1\n }\n \ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex fc09bafa07..fff8451716 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -38,7 +38,7 @@ GIT_TESTING_PORCELAIN_COMMAND_LIST='add checkout rebase'\n # We don't need this function to actually join words or do anything special.\n # Also, it's cleaner to avoid touching bash's internal completion variables.\n # So let's override it with a minimal version for testing purposes.\n-_get_comp_words_by_ref ()\n+__git_get_comp_words_by_ref ()\n {\n \tcword=$_cword\n \tcur=${_words[cword]}\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462182","messageId":"20220830093138.1581538-51-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 50/51] zsh: remove version","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:37Z","receivedAt":"2022-08-30T09:35:51Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Doesn't seem to be useful.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.zsh | 5 -----\n 1 file changed, 5 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh\nindex 7d34522621..31bf88c1c5 100644\n--- a/contrib/completion/git-completion.zsh\n+++ b/contrib/completion/git-completion.zsh\n@@ -118,11 +118,6 @@ __gitcomp_file_direct ()\n \t__gitcomp_file \"$1\" \"\"\n }\n \n-_git_zsh ()\n-{\n-\t__gitcomp \"v1.1\"\n-}\n-\n __git_complete_command ()\n {\n \temulate -L zsh\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"},{"id":"462183","messageId":"20220830093138.1581538-52-felipe.contreras@gmail.com","threadId":"58376","inReplyTo":"20220830093138.1581538-1-felipe.contreras@gmail.com","subject":"[PATCH 51/51] completion: bash: trivial grammar fix","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-30T09:31:38Z","receivedAt":"2022-08-30T09:35:57Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n contrib/completion/git-completion.bash | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 77a475e272..dffb34266f 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -3152,7 +3152,7 @@ _git_worktree ()\n \t\t# Here we are not completing an --option, it's either the\n \t\t# path or a ref.\n \t\tcase \"$prev\" in\n-\t\t-b|-B)\t# Complete refs for branch to be created/reseted.\n+\t\t-b|-B)\t# Complete refs for branch to be created/reset.\n \t\t\t__git_complete_refs\n \t\t\t;;\n \t\t-*)\t# The previous word is an -o|--option without an\n-- \n2.37.2.351.g9bf691b78c.dirty\n\n"}]}