Subject: [PATCH 11/11] completion: complete config variables and values for 'git clone --config='

From: SZEDER Gábor <[email-masked]>
Date: Tue, 13 Aug 2019 14:26:52 +0200

Completing configuration sections and variable names for the stuck
argument of 'git clone --config=<TAB>' requires a bit of extra care
compared to doing the same for the unstuck argument of 'git clone
--config <TAB>', because we have to deal with that '--config=' being
part of the current word to be completed.

Add an option to the __git_complete_config_variable_name_and_value()
and in turn to the __git_complete_config_variable_name() helper
functions to specify the current section/variable name to be
completed, so they can be used even when completing the stuck argument
of '--config='.

__git_complete_config_variable_value() already has such an option, and
thus no further changes were necessary to complete possible values
after 'git clone --config=section.name=<TAB>'.

Signed-off-by: SZEDER Gábor <[email-masked]>
---
 contrib/completion/git-completion.bash | 66 +++++++++++++++++++-------
 t/t9902-completion.sh                  | 21 ++++++++
 2 files changed, 70 insertions(+), 17 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 279f04df87..ce7ff0a96d 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1406,6 +1406,11 @@ _git_clone ()
 		;;
 	esac
 	case "$cur" in
+	--config=*)
+		__git_complete_config_variable_name_and_value \
+			--cur="${cur##--config=}"
+		return
+		;;
 	--*)
 		__gitcomp_builtin clone
 		return
@@ -2352,35 +2357,41 @@ __git_complete_config_variable_value ()
 # Completes configuration sections, subsections, variable names.
 #
 # Usage: __git_complete_config_variable_name [<option>]...
+# --cur=<word>: The current configuration section/variable name to be
+#               completed.  Defaults to the current word to be completed.
 # --sfx=<suffix>: A suffix to be appended to each fully completed
 #                 configuration variable name (but not to sections or
 #                 subsections) instead of the default space.
 __git_complete_config_variable_name ()
 {
-	local sfx
+	local cur_="$cur" sfx
 
 	while test $# != 0; do
 		case "$1" in
+		--cur=*)	cur_="${1##--cur=}" ;;
 		--sfx=*)	sfx="${1##--sfx=}" ;;
 		*)		return 1 ;;
 		esac
 		shift
 	done
 
-	case "$cur" in
+	case "$cur_" in
 	branch.*.*)
-		local pfx="${cur%.*}." cur_="${cur##*.}"
+		local pfx="${cur_%.*}."
+		cur_="${cur_##*.}"
 		__gitcomp "remote pushRemote merge mergeOptions rebase" "$pfx" "$cur_" "$sfx"
 		return
 		;;
 	branch.*)
-		local pfx="${cur%.*}." cur_="${cur#*.}"
+		local pfx="${cur%.*}."
+		cur_="${cur#*.}"
 		__gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")"
 		__gitcomp_nl_append $'autoSetupMerge\nautoSetupRebase\n' "$pfx" "$cur_" "$sfx"
 		return
 		;;
 	guitool.*.*)
-		local pfx="${cur%.*}." cur_="${cur##*.}"
+		local pfx="${cur_%.*}."
+		cur_="${cur_##*.}"
 		__gitcomp "
 			argPrompt cmd confirm needsFile noConsole noRescan
 			prompt revPrompt revUnmerged title
@@ -2388,28 +2399,33 @@ __git_complete_config_variable_name ()
 		return
 		;;
 	difftool.*.*)
-		local pfx="${cur%.*}." cur_="${cur##*.}"
+		local pfx="${cur_%.*}."
+		cur_="${cur_##*.}"
 		__gitcomp "cmd path" "$pfx" "$cur_" "$sfx"
 		return
 		;;
 	man.*.*)
-		local pfx="${cur%.*}." cur_="${cur##*.}"
+		local pfx="${cur_%.*}."
+		cur_="${cur_##*.}"
 		__gitcomp "cmd path" "$pfx" "$cur_" "$sfx"
 		return
 		;;
 	mergetool.*.*)
-		local pfx="${cur%.*}." cur_="${cur##*.}"
+		local pfx="${cur_%.*}."
+		cur_="${cur_##*.}"
 		__gitcomp "cmd path trustExitCode" "$pfx" "$cur_" "$sfx"
 		return
 		;;
 	pager.*)
-		local pfx="${cur%.*}." cur_="${cur#*.}"
+		local pfx="${cur_%.*}."
+		cur_="${cur_#*.}"
 		__git_compute_all_commands
 		__gitcomp_nl "$__git_all_commands" "$pfx" "$cur_" "$sfx"
 		return
 		;;
 	remote.*.*)
-		local pfx="${cur%.*}." cur_="${cur##*.}"
+		local pfx="${cur_%.*}."
+		cur_="${cur_##*.}"
 		__gitcomp "
 			url proxy fetch push mirror skipDefaultUpdate
 			receivepack uploadpack tagOpt pushurl
@@ -2417,19 +2433,21 @@ __git_complete_config_variable_name ()
 		return
 		;;
 	remote.*)
-		local pfx="${cur%.*}." cur_="${cur#*.}"
+		local pfx="${cur_%.*}."
+		cur_="${cur_#*.}"
 		__gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "."
 		__gitcomp_nl_append "pushDefault" "$pfx" "$cur_" "$sfx"
 		return
 		;;
 	url.*.*)
-		local pfx="${cur%.*}." cur_="${cur##*.}"
+		local pfx="${cur_%.*}."
+		cur_="${cur_##*.}"
 		__gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur_" "$sfx"
 		return
 		;;
 	*.*)
 		__git_compute_config_vars
-		__gitcomp "$__git_config_vars" "" "$cur" "$sfx"
+		__gitcomp "$__git_config_vars" "" "$cur_" "$sfx"
 		;;
 	*)
 		__git_compute_config_vars
@@ -2441,22 +2459,36 @@ __git_complete_config_variable_name ()
 					for (s in sections)
 						print s "."
 				}
-				')"
+				')" "" "$cur_"
 		;;
 	esac
 }
 
 # Completes '='-separated configuration sections/variable names and values
 # for 'git -c section.name=value'.
+#
+# Usage: __git_complete_config_variable_name_and_value [<option>]...
+# --cur=<word>: The current configuration section/variable name/value to be
+#               completed. Defaults to the current word to be completed.
 __git_complete_config_variable_name_and_value ()
 {
-	case "$cur" in
+	local cur_="$cur"
+
+	while test $# != 0; do
+		case "$1" in
+		--cur=*)	cur_="${1##--cur=}" ;;
+		*)		return 1 ;;
+		esac
+		shift
+	done
+
+	case "$cur_" in
 	*=*)
 		__git_complete_config_variable_value \
-			--varname="${cur%%=*}" --cur="${cur#*=}"
+			--varname="${cur_%%=*}" --cur="${cur_#*=}"
 		;;
 	*)
-		__git_complete_config_variable_name --sfx='='
+		__git_complete_config_variable_name --cur="$cur_" --sfx='='
 		;;
 	esac
 }
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 9e90a64830..5d98d66dbd 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -1740,6 +1740,27 @@ test_expect_success 'git -c - value' '
 	EOF
 '
 
+test_expect_success 'git clone --config= - section' '
+	test_completion "git clone --config=br" <<-\EOF
+	branch.Z
+	browser.Z
+	EOF
+'
+
+test_expect_success 'git clone --config= - variable name' '
+	test_completion "git clone --config=log.d" <<-\EOF
+	log.date=Z
+	log.decorate=Z
+	EOF
+'
+
+test_expect_success 'git clone --config= - value' '
+	test_completion "git clone --config=color.pager=" <<-\EOF
+	false Z
+	true Z
+	EOF
+'
+
 test_expect_success 'sourcing the completion script clears cached commands' '
 	__git_compute_all_commands &&
 	verbose test -n "$__git_all_commands" &&
-- 
2.23.0.rc2.350.gf4fdc32db7