--- .git-completion.bash2017-06-22 09:37:23.336295271 +0800
+++ git_bak 2017-06-19 13:18:18.797790093 +0800
@@ -28,6 +28,14 @@
# completion style.For example '!f() { : git commit ;
... };
f' will
# tell the completion to use commit completion.This also works with aliases
# of form "!sh -c '...'".For example, "!sh -c ': git commit ;
... '".
+#
+# You can set the following environment variables to influence the behavior of
+# the completion routines:
+#
+#GIT_COMPLETION_CHECKOUT_NO_GUESS
+#
+#When set to "1", do not include "DWIM" suggestions in git-checkout
+#completion (e.g., completing "foo" when "origin/foo" exists). case "$COMP_WORDBREAKS" in
*:*) : great ;
;
@@ -213,6 +221,20 @@
}
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[@]}
@@ -338,14 +360,27 @@
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:short)' 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:short)' 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.
@@ -354,11 +389,21 @@
#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: 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 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"
@@ -382,63 +427,78 @@
fiif [ "$list_refs_from" = path ];
then
-case "$cur" in
+if [[ "$cur_" == ^* ]];
then
+pfx="$pfx^"
+fer_pfx="$fer_pfx^"
+cur_=${cur_#^}
+match=${match#^}
+fi
+case "$cur_" in
refs|refs/*)
format="refname"
-refs="${cur%/*}"
+refs=("$match*" "$match*/**")
track=""
;
;
*)
-[[ "$cur" == ^* ]] && pfx="^"
for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD;
do
-if [ -e "$dir/$i" ];
then echo $pfx$i;
fi
+case "$i" in
+$match*)
+if [ -e "$dir/$i" ];
then
+echo "$pfx$i$sfx"
+fi
+;
;
+esac
done
-format="refname:short"
-refs="refs/tags refs/heads refs/remotes"
+format="refname:strip=2"
+refs=("refs/tags/$match*" "refs/tags/$match*/**"
+"refs/heads/$match*" "refs/heads/$match*/**"
+"refs/remotes/$match*" "refs/remotes/$match*/**")
;
;
esac
-__git_dir="$dir" __git for-each-ref --format="$pfx%($format)" \
-$refs
+__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
-local ref entry
-__git for-each-ref --shell --format="ref=%(refname:short)" \
-"refs/remotes/" | \
-while read -r entry;
do
-eval "$entry"
-ref="${ref#*/}"
-if [[ "$ref" == "$cur"* ]];
then
-echo "$ref"
-fi
-done | sort | uniq -u
+__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
+--sort="refname:strip=3" \
+"refs/remotes/*/$match*" "refs/remotes/*/$match*/**" | \
+uniq -u
fi
return
fi
-case "$cur" in
+case "$cur_" in
refs|refs/*)
-__git ls-remote "$remote" "$cur*" | \
+__git ls-remote "$remote" "$match*" | \
while read -r hash i;
do
case "$i" in
*^{}) ;
;
-*) echo "$i" ;
;
+*) echo "$pfx$i$sfx" ;
;
esac
done
;
;
*)
if [ "$list_refs_from" = remote ];
then
-echo "HEAD"
-__git for-each-ref --format="%(refname:short)" \
-"refs/remotes/$remote/" | sed -e "s#^$remote/##"
+case "HEAD" in
+$match*) echo "${pfx}HEAD$sfx" ;
;
+esac
+__git for-each-ref --format="$fer_pfx%(refname:strip=3)$sfx" \
+"refs/remotes/$remote/$match*" \
+"refs/remotes/$remote/$match*/**"
else
-__git ls-remote "$remote" HEAD \
-"refs/tags/*" "refs/heads/*" "refs/remotes/*" |
+local query_symref
+case "HEAD" in
+$match*)query_symref="HEAD" ;
;
+esac
+__git ls-remote "$remote" $query_symref \
+"refs/tags/$match*" "refs/heads/$match*" \
+"refs/remotes/$match*" |
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
@@ -446,7 +506,38 @@
esac
}+# Completes refs, short and long, local and remote, symbolic and pseudo.
+#
+# Usage: __git_complete_refs [