Subject: [PATCH v2 5/8] completion: add --option completion for most builtin commands

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Sat, 24 Mar 2018 21:35:22 +0100

Many builtin commands use parseopt which supports expose the option
list via --git-completion-helper but do not have explicit support in
git-completion.bash. This patch detects those commands and uses
__gitcomp_builtin for option completion.

This does not pollute the command name completion though. "git <tab>"
will show you the same set as before. This only kicks in when you type
the correct command name.

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 contrib/completion/git-completion.bash | 28 ++++++++++++++++++++++++++
 t/t9902-completion.sh                  |  6 ++++++
 2 files changed, 34 insertions(+)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index b3a9ecfad0..a90b0e8db4 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -3034,12 +3034,40 @@ _git_worktree ()
 	fi
 }
 
+__git_complete_common () {
+	local command="$1"
+
+	case "$cur" in
+	--*)
+		__gitcomp_builtin "$command"
+		;;
+	esac
+}
+
+__git_cmds_with_parseopt_helper=
+__git_support_parseopt_helper () {
+	test -n "$__git_cmds_with_parseopt_helper" ||
+		__git_cmds_with_parseopt_helper="$(__git --list-parseopt-builtins)"
+
+	case " $__git_cmds_with_parseopt_helper " in
+	*" $1 "*)
+		return 0
+		;;
+	*)
+		return 1
+		;;
+	esac
+}
+
 __git_complete_command () {
 	local command="$1"
 	local completion_func="_git_${command//-/_}"
 	if declare -f $completion_func >/dev/null 2>/dev/null; then
 		$completion_func
 		return 0
+	elif __git_support_parseopt_helper "$command"; then
+		__git_complete_common "$command"
+		return 0
 	else
 		return 1
 	fi
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index e6485feb0a..d0a1e4c988 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -1454,6 +1454,12 @@ test_expect_success 'completion used <cmd> completion for alias: !f() { : git <c
 	EOF
 '
 
+test_expect_success 'completion without explicit _git_xxx function' '
+	test_completion "git version --" <<-\EOF
+	--build-options Z
+	EOF
+'
+
 test_expect_failure 'complete with tilde expansion' '
 	git init tmp && cd tmp &&
 	test_when_finished "cd .. && rm -rf tmp" &&
-- 
2.17.0.rc0.348.gd5a49e0b6f