Subject: [PATCH/RFC] completion: complete refs in multiple steps

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Mon, 28 Jan 2019 16:41:55 +0700

This is in the same spirit of f22f682695 (completion: complete general
config vars in two steps - 2018-05-27). Instead of considering all full
refs as completion candidates, it completes one "path" component at a
time, e.g.

    $ git switch-branch -d j<TAB>
    jch/            junio-gpg-pub

    $ git switch-branch -d jch/<TAB>
    Display all 154 possibilities? (y or n)
    jch/ab/            jch/fc/
    ....

    $ git switch-branch -d jch/nd/<TAB>
    jch/nd/attr-pathspec-fix
    jch/nd/attr-pathspec-in-tree-walk
    ...

For refs organized in multiple levels like this (and I've seen refs in 4
levels), especially when there a lot of refs, incremental completion
this way makes it easier to get to what you want.

The cost of course is more complicated completion and also slower on
systems with slow process creation. So maybe there will be a switch to
turn this on or off?

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

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 499e56f83d..d74ee79866 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -742,6 +742,17 @@ __git_refs ()
 	esac
 }
 
+__git_collapse_refs ()
+{
+	local regex="$(echo "$1" | sed 's/[^/]\+/[^\/]*/g')"
+	case "$regex" in
+		'') regex='[^\/]*';;
+		*/) regex="${regex}[^/]*";;
+	esac
+	regex="$(echo "$regex" | sed 's/\//\\\//g')"
+	sed -ne "s/\\($regex\\/\\?\\).*/\\1/p"
+}
+
 # Completes refs, short and long, local and remote, symbolic and pseudo.
 #
 # Usage: __git_complete_refs [<option>]...
@@ -769,7 +780,7 @@ __git_complete_refs ()
 		shift
 	done
 
-	__gitcomp_direct "$(__git_refs "$remote" "$track" "$pfx" "$cur_" "$sfx")"
+	__gitcomp_direct "$(__git_refs "$remote" "$track" "$pfx" "$cur_" "$sfx" | __git_collapse_refs "$cur_")"
 }
 
 # __git_refs2 requires 1 argument (to pass to __git_refs)
-- 
2.20.1.560.g70ca8b83ee