diff options
Diffstat (limited to 'contrib/completion/git-completion.bash')
-rw-r--r-- | contrib/completion/git-completion.bash | 285 |
1 files changed, 90 insertions, 195 deletions
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index e769800393..e1b7313072 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -33,8 +33,6 @@ esac # returns location of .git repo __gitdir () { - # Note: this function is duplicated in git-prompt.sh - # When updating it, make sure you update the other one to match. if [ -z "${1-}" ]; then if [ -n "${__git_dir-}" ]; then echo "$__git_dir" @@ -53,19 +51,6 @@ __gitdir () fi } -__gitcomp_1 () -{ - local c IFS=$' \t\n' - for c in $1; do - c="$c$2" - case $c in - --*=*|*.) ;; - *) c="$c " ;; - esac - printf '%s\n' "$c" - done -} - # The following function is based on code from: # # bash_completion - programmable completion functions for bash 3.2+ @@ -195,8 +180,18 @@ _get_comp_words_by_ref () } fi -# Generates completion reply with compgen, appending a space to possible -# completion words, if necessary. +__gitcompadd () +{ + local i=0 + for x in $1; do + if [[ "$x" == "$3"* ]]; then + COMPREPLY[i++]="$2$x$4" + fi + done +} + +# Generates completion reply, appending a space to possible completion words, +# if necessary. # It accepts 1 to 4 arguments: # 1: List of possible completion words. # 2: A prefix to be added to each possible completion word (optional). @@ -208,19 +203,25 @@ __gitcomp () case "$cur_" in --*=) - COMPREPLY=() ;; *) - local IFS=$'\n' - COMPREPLY=($(compgen -P "${2-}" \ - -W "$(__gitcomp_1 "${1-}" "${4-}")" \ - -- "$cur_")) + local c i=0 IFS=$' \t\n' + for c in $1; do + c="$c${4-}" + if [[ $c == "$cur_"* ]]; then + case $c in + --*=*|*.) ;; + *) c="$c " ;; + esac + COMPREPLY[i++]="${2-}$c" + fi + done ;; esac } -# Generates completion reply with compgen from newline-separated possible -# completion words by appending a space to all of them. +# Generates completion reply from newline-separated possible completion words +# by appending a space to all of them. # It accepts 1 to 4 arguments: # 1: List of possible completion words, separated by a single newline. # 2: A prefix to be added to each possible completion word (optional). @@ -231,7 +232,7 @@ __gitcomp () __gitcomp_nl () { local IFS=$'\n' - COMPREPLY=($(compgen -P "${2-}" -S "${4- }" -W "$1" -- "${3-$cur}")) + __gitcompadd "$1" "${2-}" "${3-$cur}" "${4- }" } # Generates completion reply with compgen from newline-separated possible @@ -249,106 +250,50 @@ __gitcomp_file () # since tilde expansion is not applied. # This means that COMPREPLY will be empty and Bash default # completion will be used. - COMPREPLY=($(compgen -P "${2-}" -W "$1" -- "${3-$cur}")) - - # Tell Bash that compspec generates filenames. - compopt -o filenames 2>/dev/null -} - -__git_index_file_list_filter_compat () -{ - local path - - while read -r path; do - case "$path" in - ?*/*) echo "${path%%/*}/" ;; - *) echo "$path" ;; - esac - done -} - -__git_index_file_list_filter_bash () -{ - local path - - while read -r path; do - case "$path" in - ?*/*) - # XXX if we append a slash to directory names when using - # `compopt -o filenames`, Bash will append another slash. - # This is pretty stupid, and this the reason why we have to - # define a compatible version for this function. - echo "${path%%/*}" ;; - *) - echo "$path" ;; - esac - done -} + __gitcompadd "$1" "${2-}" "${3-$cur}" "" -# Process path list returned by "ls-files" and "diff-index --name-only" -# commands, in order to list only file names relative to a specified -# directory, and append a slash to directory names. -__git_index_file_list_filter () -{ - # Default to Bash >= 4.x - __git_index_file_list_filter_bash + # 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 } -# Execute git ls-files, returning paths relative to the directory -# specified in the first argument, and using the options specified in -# the second argument. +# Execute 'git ls-files', unless the --committable option is specified, in +# which case it runs 'git diff-index' to find out the files that can be +# committed. It return paths relative to the directory specified in the first +# argument, and using the options specified in the second argument. __git_ls_files_helper () { ( test -n "${CDPATH+set}" && unset CDPATH - # NOTE: $2 is not quoted in order to support multiple options - cd "$1" && git ls-files --exclude-standard $2 + cd "$1" + if [ "$2" == "--committable" ]; then + git diff-index --name-only --relative HEAD + else + # NOTE: $2 is not quoted in order to support multiple options + git ls-files --exclude-standard $2 + fi ) 2>/dev/null } -# Execute git diff-index, returning paths relative to the directory -# specified in the first argument, and using the tree object id -# specified in the second argument. -__git_diff_index_helper () -{ - ( - test -n "${CDPATH+set}" && unset CDPATH - cd "$1" && git diff-index --name-only --relative "$2" - ) 2>/dev/null -} - # __git_index_files accepts 1 or 2 arguments: # 1: Options to pass to ls-files (required). -# Supported options are --cached, --modified, --deleted, --others, -# and --directory. # 2: A directory path (optional). # If provided, only files within the specified directory are listed. # Sub directories are never recursed. Path must have a trailing # slash. __git_index_files () { - local dir="$(__gitdir)" root="${2-.}" + local dir="$(__gitdir)" root="${2-.}" file if [ -d "$dir" ]; then - __git_ls_files_helper "$root" "$1" | __git_index_file_list_filter | - sort | uniq - fi -} - -# __git_diff_index_files accepts 1 or 2 arguments: -# 1) The id of a tree object. -# 2) A directory path (optional). -# If provided, only files within the specified directory are listed. -# Sub directories are never recursed. Path must have a trailing -# slash. -__git_diff_index_files () -{ - local dir="$(__gitdir)" root="${2-.}" - - if [ -d "$dir" ]; then - __git_diff_index_helper "$root" "$1" | __git_index_file_list_filter | - sort | uniq + __git_ls_files_helper "$root" "$1" | + while read -r file; do + case "$file" in + ?*/*) echo "${file%%/*}" ;; + *) echo "$file" ;; + esac + done | sort | uniq fi } @@ -424,14 +369,8 @@ __git_refs () done ;; *) - git ls-remote "$dir" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \ - while read -r hash i; do - case "$i" in - *^{}) ;; - refs/*) echo "${i#refs/*/}" ;; - *) echo "$i" ;; - esac - done + echo "HEAD" + git for-each-ref --format="%(refname:short)" -- "refs/remotes/$dir/" | sed -e "s#^$dir/##" ;; esac } @@ -549,44 +488,23 @@ __git_complete_revlist_file () } -# __git_complete_index_file requires 1 argument: the options to pass to -# ls-file +# __git_complete_index_file requires 1 argument: +# 1: the options to pass to ls-file +# +# The exception is --committable, which finds the files appropriate commit. __git_complete_index_file () { - local pfx cur_="$cur" + local pfx="" cur_="$cur" case "$cur_" in ?*/*) pfx="${cur_%/*}" cur_="${cur_##*/}" pfx="${pfx}/" - - __gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_" - ;; - *) - __gitcomp_file "$(__git_index_files "$1")" "" "$cur_" ;; esac -} - -# __git_complete_diff_index_file requires 1 argument: the id of a tree -# object -__git_complete_diff_index_file () -{ - local pfx cur_="$cur" - - case "$cur_" in - ?*/*) - pfx="${cur_%/*}" - cur_="${cur_##*/}" - pfx="${pfx}/" - __gitcomp_file "$(__git_diff_index_files "$1" "$pfx")" "$pfx" "$cur_" - ;; - *) - __gitcomp_file "$(__git_diff_index_files "$1")" "" "$cur_" - ;; - esac + __gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_" } __git_complete_file () @@ -614,7 +532,6 @@ __git_complete_remote_or_refspec () case "$cmd" in push) no_complete_refspec=1 ;; fetch) - COMPREPLY=() return ;; *) ;; @@ -630,7 +547,6 @@ __git_complete_remote_or_refspec () return fi if [ $no_complete_refspec = 1 ]; then - COMPREPLY=() return fi [ "$remote" = "." ] && remote= @@ -732,6 +648,7 @@ __git_list_porcelain_commands () cat-file) : plumbing;; check-attr) : plumbing;; check-ignore) : plumbing;; + check-mailmap) : plumbing;; check-ref-format) : plumbing;; checkout-index) : plumbing;; commit-tree) : plumbing;; @@ -951,7 +868,6 @@ _git_am () " return esac - COMPREPLY=() } _git_apply () @@ -971,7 +887,6 @@ _git_apply () " return esac - COMPREPLY=() } _git_add () @@ -1031,7 +946,6 @@ _git_bisect () __gitcomp_nl "$(__git_refs)" ;; *) - COMPREPLY=() ;; esac } @@ -1124,9 +1038,14 @@ _git_cherry () _git_cherry_pick () { + local dir="$(__gitdir)" + if [ -f "$dir"/CHERRY_PICK_HEAD ]; then + __gitcomp "--continue --quit --abort" + return + fi case "$cur" in --*) - __gitcomp "--edit --no-commit" + __gitcomp "--edit --no-commit --signoff --strategy= --mainline" ;; *) __gitcomp_nl "$(__git_refs)" @@ -1170,7 +1089,6 @@ _git_clone () return ;; esac - COMPREPLY=() } _git_commit () @@ -1211,7 +1129,7 @@ _git_commit () esac if git rev-parse --verify --quiet HEAD >/dev/null; then - __git_complete_diff_index_file "HEAD" + __git_complete_index_file "--committable" else # This is the first commit __git_complete_index_file "--cached" @@ -1244,7 +1162,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary --no-prefix --src-prefix= --dst-prefix= --inter-hunk-context= --patience --histogram --minimal - --raw + --raw --word-diff --dirstat --dirstat= --dirstat-by-file --dirstat-by-file= --cumulative --diff-algorithm= @@ -1292,7 +1210,7 @@ _git_difftool () return ;; esac - __git_complete_file + __git_complete_revlist_file } __git_fetch_options=" @@ -1312,11 +1230,12 @@ _git_fetch () } __git_format_patch_options=" - --stdout --attach --no-attach --thread --thread= --output-directory + --stdout --attach --no-attach --thread --thread= --no-thread --numbered --start-number --numbered-files --keep-subject --signoff --signature --no-signature --in-reply-to= --cc= --full-index --binary --not --all --cover-letter --no-prefix --src-prefix= --dst-prefix= --inline --suffix= --ignore-if-in-upstream --subject-prefix= + --output-directory --reroll-count --to= --quiet --notes " _git_format_patch () @@ -1347,7 +1266,6 @@ _git_fsck () return ;; esac - COMPREPLY=() } _git_gc () @@ -1358,7 +1276,6 @@ _git_gc () return ;; esac - COMPREPLY=() } _git_gitk () @@ -1435,7 +1352,6 @@ _git_init () return ;; esac - COMPREPLY=() } _git_ls_files () @@ -1571,7 +1487,6 @@ _git_mergetool () return ;; esac - COMPREPLY=() } _git_merge_base () @@ -1812,7 +1727,7 @@ __git_config_get_set_variables () _git_config () { case "$prev" in - branch.*.remote) + branch.*.remote|branch.*.pushremote) __gitcomp_nl "$(__git_remotes)" return ;; @@ -1824,11 +1739,15 @@ _git_config () __gitcomp "false true" return ;; + remote.pushdefault) + __gitcomp_nl "$(__git_remotes)" + return + ;; remote.*.fetch) local remote="${prev#remote.}" remote="${remote%.fetch}" if [ -z "$cur" ]; then - COMPREPLY=("refs/heads/") + __gitcomp_nl "refs/heads/" "" "" "" return fi __gitcomp_nl "$(__git_refs_remotes "$remote")" @@ -1892,7 +1811,6 @@ _git_config () return ;; *.*) - COMPREPLY=() return ;; esac @@ -1909,7 +1827,7 @@ _git_config () ;; branch.*.*) local pfx="${cur%.*}." cur_="${cur##*.}" - __gitcomp "remote merge mergeoptions rebase" "$pfx" "$cur_" + __gitcomp "remote pushremote merge mergeoptions rebase" "$pfx" "$cur_" return ;; branch.*) @@ -2040,7 +1958,6 @@ _git_config () core.fileMode core.fsyncobjectfiles core.gitProxy - core.ignoreCygwinFSTricks core.ignoreStat core.ignorecase core.logAllRefUpdates @@ -2204,6 +2121,7 @@ _git_config () receive.fsckObjects receive.unpackLimit receive.updateserverinfo + remote.pushdefault remotes. repack.usedeltabaseoffset rerere.autoupdate @@ -2274,7 +2192,6 @@ _git_remote () __gitcomp "$c" ;; *) - COMPREPLY=() ;; esac } @@ -2358,7 +2275,7 @@ _git_show () return ;; esac - __git_complete_file + __git_complete_revlist_file } _git_show_branch () @@ -2390,8 +2307,6 @@ _git_stash () *) if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then __gitcomp "$subcommands" - else - COMPREPLY=() fi ;; esac @@ -2404,14 +2319,12 @@ _git_stash () __gitcomp "--index --quiet" ;; show,--*|drop,--*|branch,--*) - COMPREPLY=() ;; show,*|apply,*|drop,*|pop,*|branch,*) __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \ | sed -n -e 's/:.*//p')" ;; *) - COMPREPLY=() ;; esac fi @@ -2421,7 +2334,7 @@ _git_submodule () { __git_has_doubledash && return - local subcommands="add status init update summary foreach sync" + local subcommands="add status init deinit update summary foreach sync" if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then case "$cur" in --*) @@ -2453,7 +2366,7 @@ _git_svn () --no-metadata --use-svm-props --use-svnsync-props --log-window-size= --no-checkout --quiet --repack-flags --use-log-author --localtime - --ignore-paths= $remote_opts + --ignore-paths= --include-paths= $remote_opts " local init_opts=" --template= --shared= --trunk= --tags= @@ -2528,7 +2441,6 @@ _git_svn () __gitcomp "--revision= --parent" ;; *) - COMPREPLY=() ;; esac fi @@ -2553,13 +2465,10 @@ _git_tag () case "$prev" in -m|-F) - COMPREPLY=() ;; -*|tag) if [ $f = 1 ]; then __gitcomp_nl "$(__git_tags)" - else - COMPREPLY=() fi ;; *) @@ -2581,9 +2490,10 @@ __git_main () i="${words[c]}" case "$i" in --git-dir=*) __git_dir="${i#--git-dir=}" ;; + --git-dir) ((c++)) ; __git_dir="${words[c]}" ;; --bare) __git_dir="." ;; --help) command="help"; break ;; - -c) c=$((++c)) ;; + -c|--work-tree|--namespace) ((c++)) ;; -*) ;; *) command="$i"; break ;; esac @@ -2601,6 +2511,7 @@ __git_main () --exec-path --exec-path= --html-path + --man-path --info-path --work-tree= --namespace= @@ -2669,7 +2580,7 @@ if [[ -n ${ZSH_VERSION-} ]]; then --*=*|*.) ;; *) c="$c " ;; esac - array[$#array+1]="$c" + array[${#array[@]}+1]="$c" done compset -P '*[=:]' compadd -Q -S '' -p "${2-}" -a -- array && _ret=0 @@ -2695,35 +2606,19 @@ if [[ -n ${ZSH_VERSION-} ]]; then compadd -Q -p "${2-}" -f -- ${=1} && _ret=0 } - __git_zsh_helper () - { - emulate -L ksh - local cur cword prev - cur=${words[CURRENT-1]} - prev=${words[CURRENT-2]} - let cword=CURRENT-1 - __${service}_main - } - _git () { - emulate -L zsh - local _ret=1 - __git_zsh_helper - let _ret && _default -S '' && _ret=0 + local _ret=1 cur cword prev + cur=${words[CURRENT]} + prev=${words[CURRENT-1]} + let cword=CURRENT-1 + emulate ksh -c __${service}_main + let _ret && _default && _ret=0 return _ret } compdef _git git gitk return -elif [[ -n ${BASH_VERSION-} ]]; then - if ((${BASH_VERSINFO[0]} < 4)); then - # compopt is not supported - __git_index_file_list_filter () - { - __git_index_file_list_filter_compat - } - fi fi __git_func_wrap () |