Subject: [PATCH v3 04/42] git-completion.bash: introduce __gitcomp_builtin

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Fri, 9 Feb 2018 18:01:43 +0700

This is a __gitcomp wrapper that will execute

    git ... --git-completion-helper

to get the list of completable options. The call will be made only
once and cached to avoid performance issues, especially on Windows.

__gitcomp_builtin() allows callers to change its output a bit by adding
some more options, or removing some.

- Current --git-completion-helper for example does not output --no-foo
  form, this has to be added manually by __gitcomp_builtin() callers
  when necessary

- Some options from --git-completion-helper should only be available in
  certain conditions (e.g. --continue and friends). __gitcomp_builtin()
  callers can remove them if the conditions are not met.

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 contrib/completion/git-completion.bash | 33 ++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 3683c772c5..85e7f26328 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -280,6 +280,39 @@ __gitcomp ()
 	esac
 }
 
+# This function is equivalent to
+#
+#    __gitcomp "$(git xxx --git-completion-helper) ..."
+#
+# except that the output is cached. Accept 1-3 arguments:
+# 1: the git command to execute, this is also the cache key
+# 2: extra options to be added on top (e.g. negative forms)
+# 3: options to be excluded
+__gitcomp_builtin ()
+{
+	# spaces must be replaced with underscore for multi-word
+	# commands, e.g. "git remote add" becomes remote_add.
+	local cmd="$1"
+	local incl="$2"
+	local excl="$3"
+
+	local var=__gitcomp_builtin_"${cmd/-/_}"
+	local options
+	eval "options=\$$var"
+
+	if [ -z "$options" ]; then
+		# leading and trailing spaces are significant to make
+		# option removal work correctly.
+		options=" $(__git ${cmd/_/ } --git-completion-helper) $incl "
+		for i in $excl; do
+			options="${options/ $i / }"
+		done
+		eval "$var=\"$options\""
+	fi
+
+	__gitcomp "$options"
+}
+
 # Variation of __gitcomp_nl () that appends to the existing list of
 # completion candidates, COMPREPLY.
 __gitcomp_nl_append ()
-- 
2.16.1.207.gedba492059