# Clear the variables caching builtins' options when (re-)sourcing
# the completion script.
-unset $(set |sed -ne 's/^\(__gitcomp_builtin_[a-zA-Z0-9_][a-zA-Z0-9_]*\)=.*/\1/p') 2>/dev/null
+if [[ -n ${ZSH_VERSION-} ]]; then
+ unset $(set |sed -ne 's/^\(__gitcomp_builtin_[a-zA-Z0-9_][a-zA-Z0-9_]*\)=.*/\1/p') 2>/dev/null
+else
+ unset $(compgen -v __gitcomp_builtin_)
+fi
# This function is equivalent to
#
__gitcomp_nl_append "$@"
}
+# Fills the COMPREPLY array with prefiltered paths without any additional
+# processing.
+# Callers must take care of providing only paths that match the current path
+# to be completed and adding any prefix path components, if necessary.
+# 1: List of newline-separated matching paths, complete with all prefix
+# path componens.
+__gitcomp_file_direct ()
+{
+ local IFS=$'\n'
+
+ COMPREPLY=($1)
+
+ # use a hack to enable file mode in bash < 4
+ compopt -o filenames +o nospace 2>/dev/null ||
+ compgen -f /non-existing-dir/ >/dev/null ||
+ true
+}
+
# Generates completion reply with compgen from newline-separated possible
# completion filenames.
# It accepts 1 to 3 arguments:
# use a hack to enable file mode in bash < 4
compopt -o filenames +o nospace 2>/dev/null ||
- compgen -f /non-existing-dir/ > /dev/null
+ compgen -f /non-existing-dir/ >/dev/null ||
+ true
}
# Execute 'git ls-files', unless the --committable option is specified, in
# 3: List only paths matching this path component (optional).
__git_index_files ()
{
- local root="$2" match="$3" file
+ local root="$2" match="$3"
__git_ls_files_helper "$root" "$1" "$match" |
- while read -r file; do
- case "$file" in
- ?*/*) echo "${file%%/*}" ;;
- *) echo "$file" ;;
- esac
- done | sort | uniq
+ awk -F / -v pfx="${2//\\/\\\\}" '{
+ paths[$1] = 1
+ }
+ END {
+ for (p in paths) {
+ if (substr(p, 1, 1) != "\"") {
+ # No special characters, easy!
+ print pfx p
+ continue
+ }
+
+ # The path is quoted.
+ p = dequote(p)
+ if (p == "")
+ continue
+
+ # Even when a directory name itself does not contain
+ # any special characters, it will still be quoted if
+ # any of its (stripped) trailing path components do.
+ # Because of this we may have seen the same direcory
+ # both quoted and unquoted.
+ if (p in paths)
+ # We have seen the same directory unquoted,
+ # skip it.
+ continue
+ else
+ print pfx p
+ }
+ }
+ function dequote(p, bs_idx, out, esc, esc_idx, dec) {
+ # Skip opening double quote.
+ p = substr(p, 2)
+
+ # Interpret backslash escape sequences.
+ while ((bs_idx = index(p, "\\")) != 0) {
+ out = out substr(p, 1, bs_idx - 1)
+ esc = substr(p, bs_idx + 1, 1)
+ p = substr(p, bs_idx + 2)
+
+ if ((esc_idx = index("abtvfr\"\\", esc)) != 0) {
+ # C-style one-character escape sequence.
+ out = out substr("\a\b\t\v\f\r\"\\",
+ esc_idx, 1)
+ } else if (esc == "n") {
+ # Uh-oh, a newline character.
+ # We cant reliably put a pathname
+ # containing a newline into COMPREPLY,
+ # and the newline would create a mess.
+ # Skip this path.
+ return ""
+ } else {
+ # Must be a \nnn octal value, then.
+ dec = esc * 64 + \
+ substr(p, 1, 1) * 8 + \
+ substr(p, 2, 1)
+ out = out sprintf("%c", dec)
+ p = substr(p, 3)
+ }
+ }
+ # Drop closing double quote, if there is one.
+ # (There isnt any if this is a directory, as it was
+ # already stripped with the trailing path components.)
+ if (substr(p, length(p), 1) == "\"")
+ out = out substr(p, 1, length(p) - 1)
+ else
+ out = out p
+
+ return out
+ }'
}
# __git_complete_index_file requires 1 argument:
cur_="$dequoted_word"
esac
- __gitcomp_file "$(__git_index_files "$1" "$pfx" "$cur_")" "$pfx" "$cur_"
+ __gitcomp_file_direct "$(__git_index_files "$1" "$pfx" "$cur_")"
}
# Lists branches from the local repository.
check-ref-format) : plumbing;;
checkout-index) : plumbing;;
column) : internal helper;;
+ commit-graph) : plumbing;;
commit-tree) : plumbing;;
count-objects) : infrequent;;
credential) : credentials;;
--*)
__gitcomp "
--onto --merge --strategy --interactive
- --preserve-merges --stat --no-stat
+ --rebase-merges --preserve-merges --stat --no-stat
--committer-date-is-author-date --ignore-date
--ignore-whitespace --whitespace=
--autosquash --no-autosquash
return
;;
branch.*.rebase)
- __gitcomp "false true preserve interactive"
+ __gitcomp "false true merges preserve interactive"
return
;;
remote.pushdefault)
__gitcomp "$__git_log_date_formats"
return
;;
- sendemail.aliasesfiletype)
+ sendemail.aliasfiletype)
__gitcomp "mutt mailrc pine elm gnus"
return
;;
core.bigFileThreshold
core.checkStat
core.commentChar
+ core.commitGraph
core.compression
core.createObject
core.deltaBaseCacheLimit
_git_stash ()
{
local save_opts='--all --keep-index --no-keep-index --quiet --patch --include-untracked'
- local subcommands='push save list show apply clear drop pop create branch'
- local subcommand="$(__git_find_on_cmdline "$subcommands")"
+ local subcommands='push list show apply clear drop pop create branch'
+ local subcommand="$(__git_find_on_cmdline "$subcommands save")"
+ if [ -n "$(__git_find_on_cmdline "-p")" ]; then
+ subcommand="push"
+ fi
if [ -z "$subcommand" ]; then
case "$cur" in
--*)
__gitcomp "$save_opts"
;;
+ sa*)
+ if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then
+ __gitcomp "save"
+ fi
+ ;;
*)
if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then
__gitcomp "$subcommands"
__git_complete_command () {
local command="$1"
local completion_func="_git_${command//-/_}"
- if declare -f $completion_func >/dev/null 2>/dev/null; then
+ if ! declare -f $completion_func >/dev/null 2>/dev/null &&
+ declare -f _completion_loader >/dev/null 2>/dev/null
+ then
+ _completion_loader "git-$command"
+ fi
+ if declare -f $completion_func >/dev/null 2>/dev/null
+ then
$completion_func
return 0
- elif __git_support_parseopt_helper "$command"; then
+ elif __git_support_parseopt_helper "$command"
+ then
__git_complete_common "$command"
return 0
else
compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0
}
+ __gitcomp_file_direct ()
+ {
+ emulate -L zsh
+
+ local IFS=$'\n'
+ compset -P '*[=:]'
+ compadd -Q -f -- ${=1} && _ret=0
+ }
+
__gitcomp_file ()
{
emulate -L zsh