summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/completion/git-completion.bash54
-rw-r--r--contrib/completion/git-completion.zsh9
-rwxr-xr-xt/t9902-completion.sh27
3 files changed, 76 insertions, 14 deletions
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index d26312899d..41e6589313 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -213,6 +213,20 @@ _get_comp_words_by_ref ()
}
fi
+# Fills the COMPREPLY array with prefiltered words without any additional
+# processing.
+# Callers must take care of providing only words that match the current word
+# to be completed and adding any prefix and/or suffix (trailing space!), if
+# necessary.
+# 1: List of newline-separated matching completion words, complete with
+# prefix and suffix.
+__gitcomp_direct ()
+{
+ local IFS=$'\n'
+
+ COMPREPLY=($1)
+}
+
__gitcompappend ()
{
local x i=${#COMPREPLY[@]}
@@ -354,18 +368,21 @@ __git_tags ()
# Can be the name of a configured remote, a path, or a URL.
# 2: In addition to local refs, list unique branches from refs/remotes/ for
# 'git checkout's tracking DWIMery (optional; ignored, if set but empty).
-# 3: Currently ignored.
+# 3: A prefix to be added to each listed ref (optional).
# 4: List only refs matching this word (optional; list all refs if unset or
# empty).
+# 5: A suffix to be appended to each listed ref (optional; ignored, if set
+# but empty).
#
# Use __git_complete_refs() instead.
__git_refs ()
{
local i hash dir track="${2-}"
local list_refs_from=path remote="${1-}"
- local format refs pfx
- local cur_="${4-$cur}"
+ local format refs
+ local pfx="${3-}" cur_="${4-$cur}" sfx="${5-}"
local match="${4-}"
+ local fer_pfx="${pfx//\%/%%}" # "escape" for-each-ref format specifiers
__git_find_repo_path
dir="$__git_repo_path"
@@ -390,7 +407,8 @@ __git_refs ()
if [ "$list_refs_from" = path ]; then
if [[ "$cur_" == ^* ]]; then
- pfx="^"
+ pfx="$pfx^"
+ fer_pfx="$fer_pfx^"
cur_=${cur_#^}
match=${match#^}
fi
@@ -405,7 +423,7 @@ __git_refs ()
case "$i" in
$match*)
if [ -e "$dir/$i" ]; then
- echo $pfx$i
+ echo "$pfx$i$sfx"
fi
;;
esac
@@ -416,13 +434,13 @@ __git_refs ()
"refs/remotes/$match*" "refs/remotes/$match*/**")
;;
esac
- __git_dir="$dir" __git for-each-ref --format="$pfx%($format)" \
+ __git_dir="$dir" __git for-each-ref --format="$fer_pfx%($format)$sfx" \
"${refs[@]}"
if [ -n "$track" ]; then
# employ the heuristic used by git checkout
# Try to find a remote branch that matches the completion word
# but only output if the branch name is unique
- __git for-each-ref --format="%(refname:strip=3)" \
+ __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
--sort="refname:strip=3" \
"refs/remotes/*/$match*" "refs/remotes/*/$match*/**" | \
uniq -u
@@ -435,16 +453,16 @@ __git_refs ()
while read -r hash i; do
case "$i" in
*^{}) ;;
- *) echo "$i" ;;
+ *) echo "$pfx$i$sfx" ;;
esac
done
;;
*)
if [ "$list_refs_from" = remote ]; then
case "HEAD" in
- $match*) echo "HEAD" ;;
+ $match*) echo "${pfx}HEAD$sfx" ;;
esac
- __git for-each-ref --format="%(refname:strip=3)" \
+ __git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
"refs/remotes/$remote/$match*" \
"refs/remotes/$remote/$match*/**"
else
@@ -458,8 +476,8 @@ __git_refs ()
while read -r hash i; do
case "$i" in
*^{}) ;;
- refs/*) echo "${i#refs/*/}" ;;
- *) echo "$i" ;; # symbolic refs
+ refs/*) echo "$pfx${i#refs/*/}$sfx" ;;
+ *) echo "$pfx$i$sfx" ;; # symbolic refs
esac
done
fi
@@ -494,8 +512,7 @@ __git_complete_refs ()
shift
done
- __gitcomp_nl "$(__git_refs "$remote" "$track" "" "$cur_")" \
- "$pfx" "$cur_" "$sfx"
+ __gitcomp_direct "$(__git_refs "$remote" "$track" "$pfx" "$cur_" "$sfx")"
}
# __git_refs2 requires 1 argument (to pass to __git_refs)
@@ -2997,6 +3014,15 @@ if [[ -n ${ZSH_VERSION-} ]]; then
esac
}
+ __gitcomp_direct ()
+ {
+ emulate -L zsh
+
+ local IFS=$'\n'
+ compset -P '*[=:]'
+ compadd -Q -- ${=1} && _ret=0
+ }
+
__gitcomp_nl ()
{
emulate -L zsh
diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh
index e25541308a..c3521fbfc4 100644
--- a/contrib/completion/git-completion.zsh
+++ b/contrib/completion/git-completion.zsh
@@ -67,6 +67,15 @@ __gitcomp ()
esac
}
+__gitcomp_direct ()
+{
+ emulate -L zsh
+
+ local IFS=$'\n'
+ compset -P '*[=:]'
+ compadd -Q -- ${=1} && _ret=0
+}
+
__gitcomp_nl ()
{
emulate -L zsh
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index cc9e741f92..5ed28135be 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -400,6 +400,22 @@ test_expect_success '__gitdir - remote as argument' '
test_cmp expected "$actual"
'
+test_expect_success '__gitcomp_direct - puts everything into COMPREPLY as-is' '
+ sed -e "s/Z$//g" >expected <<-EOF &&
+ with-trailing-space Z
+ without-trailing-spaceZ
+ --option Z
+ --option=Z
+ $invalid_variable_name Z
+ EOF
+ (
+ cur=should_be_ignored &&
+ __gitcomp_direct "$(cat expected)" &&
+ print_comp
+ ) &&
+ test_cmp expected out
+'
+
test_expect_success '__gitcomp - trailing space - options' '
test_gitcomp "--re" "--dry-run --reuse-message= --reedit-message=
--reset-author" <<-EOF
@@ -961,6 +977,17 @@ test_expect_success 'teardown after filtering matching refs' '
git -C otherrepo branch -D matching/branch-in-other
'
+test_expect_success '__git_refs - for-each-ref format specifiers in prefix' '
+ cat >expected <<-EOF &&
+ evil-%%-%42-%(refname)..master
+ EOF
+ (
+ cur="evil-%%-%42-%(refname)..mas" &&
+ __git_refs "" "" "evil-%%-%42-%(refname).." mas >"$actual"
+ ) &&
+ test_cmp expected "$actual"
+'
+
test_expect_success '__git_complete_refs - simple' '
sed -e "s/Z$//" >expected <<-EOF &&
HEAD Z