]> git.ipfire.org Git - thirdparty/git.git/blobdiff - contrib/completion/git-completion.bash
completion: fill COMPREPLY directly when completing refs
[thirdparty/git.git] / contrib / completion / git-completion.bash
index d26312899db45180524a394be0d0064c2ab38675..41e6589313952b89222fc4775f2c83bc09815d82 100644 (file)
@@ -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