completion: speed up branch and tag completion

Modify __git_heads() and __git_tags() and the few callsites they have,
so we can let 'git for-each-ref' do all the hard work and these
functions' output won't need any further processing or filtering
before being handed over to Bash, resulting in faster branch and tag
completion.  These are some of the same tricks used in the previous
commits to speed up refs completion, namely:

  - Extend both functions to accept prefix, current word and suffix
    positional parameters, all optional and all empty by default to
    keep the parameterless behavior unaltered.

  - Specify appropriate globbing patterns to 'git for-each-ref' to
    list only branches or tags matching the given current word
    parameter.

  - Modify the 'git for-each-ref --format=<...>' to include the given
    prefix and suffix.

  - Adjust all callsites to specify the proper prefix, current word
    and suffix parameters, and to fill COMPREPLY using
    __gitcomp_direct().

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
SZEDER Gábor 2017-03-23 16:29:24 +01:00 committed by Junio C Hamano
parent 745d655dc9
commit 227307a639

View File

@ -352,14 +352,27 @@ __git_index_files ()
done | sort | uniq
}
# Lists branches from the local repository.
# 1: A prefix to be added to each listed branch (optional).
# 2: List only branches matching this word (optional; list all branches if
# unset or empty).
# 3: A suffix to be appended to each listed branch (optional).
__git_heads ()
{
__git for-each-ref --format='%(refname:strip=2)' refs/heads
local pfx="${1-}" cur_="${2-}" sfx="${3-}"
__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
"refs/heads/$cur_*" "refs/heads/$cur_*/**"
}
# Lists tags from the local repository.
# Accepts the same positional parameters as __git_heads() above.
__git_tags ()
{
__git for-each-ref --format='%(refname:strip=2)' refs/tags
local pfx="${1-}" cur_="${2-}" sfx="${3-}"
__git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \
"refs/tags/$cur_*" "refs/tags/$cur_*/**"
}
# Lists refs from the local (by default) or from a remote repository.
@ -1183,7 +1196,7 @@ _git_branch ()
;;
*)
if [ $only_local_ref = "y" -a $has_r = "n" ]; then
__gitcomp_nl "$(__git_heads)"
__gitcomp_direct "$(__git_heads "" "$cur" " ")"
else
__git_complete_refs
fi
@ -2178,7 +2191,7 @@ _git_config ()
;;
branch.*)
local pfx="${cur%.*}." cur_="${cur#*.}"
__gitcomp_nl "$(__git_heads)" "$pfx" "$cur_" "."
__gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")"
__gitcomp_nl_append $'autosetupmerge\nautosetuprebase\n' "$pfx" "$cur_"
return
;;
@ -2824,7 +2837,7 @@ _git_tag ()
i="${words[c]}"
case "$i" in
-d|-v)
__gitcomp_nl "$(__git_tags)"
__gitcomp_direct "$(__git_tags "" "$cur" " ")"
return
;;
-f)
@ -2839,7 +2852,7 @@ _git_tag ()
;;
-*|tag)
if [ $f = 1 ]; then
__gitcomp_nl "$(__git_tags)"
__gitcomp_direct "$(__git_tags "" "$cur" " ")"
fi
;;
*)