diff options
Diffstat (limited to 'plugins/gitfast')
-rw-r--r-- | plugins/gitfast/README.md | 15 | ||||
-rw-r--r-- | plugins/gitfast/_git | 11 | ||||
-rw-r--r-- | plugins/gitfast/git-completion.bash | 913 | ||||
-rw-r--r-- | plugins/gitfast/git-prompt.sh | 9 | ||||
-rw-r--r-- | plugins/gitfast/gitfast.plugin.zsh | 7 |
5 files changed, 762 insertions, 193 deletions
diff --git a/plugins/gitfast/README.md b/plugins/gitfast/README.md new file mode 100644 index 000000000..84e35d77c --- /dev/null +++ b/plugins/gitfast/README.md @@ -0,0 +1,15 @@ +# Gitfast plugin + +This plugin adds completion for Git, using the zsh completion from git.git folks, which is much faster than the official one from zsh. A lot of zsh-specific features are not supported, like descriptions for every argument, but everything the bash completion has, this one does too (as it is using it behind the scenes). Not only is it faster, it should be more robust, and updated regularly to the latest git upstream version.. + +To use it, add `gitfast` to the plugins array in your zshrc file: + +```zsh +plugins=(... gitfast) +``` + +## Aliases + +An earlier version of the plugin also loaded the git plugin. If you want to keep those +aliases enable the [git plugin](https://github.com/robbyrussell/oh-my-zsh/tree/master/plugins/git) +as well. diff --git a/plugins/gitfast/_git b/plugins/gitfast/_git index 6d1b4ecc7..78a6dbb3d 100644 --- a/plugins/gitfast/_git +++ b/plugins/gitfast/_git @@ -9,7 +9,7 @@ # # If your script is somewhere else, you can configure it on your ~/.zshrc: # -# zstyle ':completion:*:*:git:*' script ~/.git-completion.sh +# zstyle ':completion:*:*:git:*' script ~/.git-completion.zsh # # The recommended way to install this script is to copy to '~/.zsh/_git', and # then add the following to your ~/.zshrc file: @@ -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/plugins/gitfast/git-completion.bash b/plugins/gitfast/git-completion.bash index 8ce6b5c5f..d93441747 100644 --- a/plugins/gitfast/git-completion.bash +++ b/plugins/gitfast/git-completion.bash @@ -28,27 +28,55 @@ # 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 ;; *) COMP_WORDBREAKS="$COMP_WORDBREAKS:" esac +# Discovers the path to the git repository taking any '--git-dir=<path>' and +# '-C <path>' options into account and stores it in the $__git_repo_path +# variable. +__git_find_repo_path () +{ + if [ -n "$__git_repo_path" ]; then + # we already know where it is + return + fi + + if [ -n "${__git_C_args-}" ]; then + __git_repo_path="$(git "${__git_C_args[@]}" \ + ${__git_dir:+--git-dir="$__git_dir"} \ + rev-parse --absolute-git-dir 2>/dev/null)" + elif [ -n "${__git_dir-}" ]; then + test -d "$__git_dir" && + __git_repo_path="$__git_dir" + elif [ -n "${GIT_DIR-}" ]; then + test -d "${GIT_DIR-}" && + __git_repo_path="$GIT_DIR" + elif [ -d .git ]; then + __git_repo_path=.git + else + __git_repo_path="$(git rev-parse --git-dir 2>/dev/null)" + fi +} + +# Deprecated: use __git_find_repo_path() and $__git_repo_path instead # __gitdir accepts 0 or 1 arguments (i.e., location) # returns location of .git repo __gitdir () { if [ -z "${1-}" ]; then - if [ -n "${__git_dir-}" ]; then - echo "$__git_dir" - elif [ -n "${GIT_DIR-}" ]; then - test -d "${GIT_DIR-}" || return 1 - echo "$GIT_DIR" - elif [ -d .git ]; then - echo .git - else - git rev-parse --git-dir 2>/dev/null - fi + __git_find_repo_path || return 1 + echo "$__git_repo_path" elif [ -d "$1/.git" ]; then echo "$1/.git" else @@ -56,6 +84,14 @@ __gitdir () fi } +# Runs git with all the options given as argument, respecting any +# '--git-dir=<path>' and '-C <path>' options present on the command line +__git () +{ + git ${__git_C_args:+"${__git_C_args[@]}"} \ + ${__git_dir:+--git-dir="$__git_dir"} "$@" 2>/dev/null +} + # The following function is based on code from: # # bash_completion - programmable completion functions for bash 3.2+ @@ -185,6 +221,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[@]} @@ -283,11 +333,11 @@ __gitcomp_file () __git_ls_files_helper () { if [ "$2" == "--committable" ]; then - git -C "$1" diff-index --name-only --relative HEAD + __git -C "$1" diff-index --name-only --relative HEAD else # NOTE: $2 is not quoted in order to support multiple options - git -C "$1" ls-files --exclude-standard $2 - fi 2>/dev/null + __git -C "$1" ls-files --exclude-standard $2 + fi } @@ -299,99 +349,195 @@ __git_ls_files_helper () # slash. __git_index_files () { - local dir="$(__gitdir)" root="${2-.}" file + local root="${2-.}" file - if [ -d "$dir" ]; then - __git_ls_files_helper "$root" "$1" | - while read -r file; do - case "$file" in - ?*/*) echo "${file%%/*}" ;; - *) echo "$file" ;; - esac - done | sort | uniq - fi + __git_ls_files_helper "$root" "$1" | + while read -r file; do + case "$file" in + ?*/*) echo "${file%%/*}" ;; + *) echo "$file" ;; + esac + 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 () { - local dir="$(__gitdir)" - if [ -d "$dir" ]; then - git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ - refs/heads - return - fi + 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 () { - local dir="$(__gitdir)" - if [ -d "$dir" ]; then - git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ - refs/tags - return - fi + local pfx="${1-}" cur_="${2-}" sfx="${3-}" + + __git for-each-ref --format="${pfx//\%/%%}%(refname:strip=2)$sfx" \ + "refs/tags/$cur_*" "refs/tags/$cur_*/**" } -# __git_refs accepts 0, 1 (to pass to __gitdir), or 2 arguments -# presence of 2nd argument means use the guess heuristic employed -# by checkout for tracking branches +# Lists refs from the local (by default) or from a remote repository. +# It accepts 0, 1 or 2 arguments: +# 1: The remote to list refs from (optional; ignored, if set but empty). +# 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="$(__gitdir "${1-}")" track="${2-}" + local i hash dir track="${2-}" + local list_refs_from=path remote="${1-}" local format refs - if [ -d "$dir" ]; then - case "$cur" in + 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" + + if [ -z "$remote" ]; then + if [ -z "$dir" ]; then + return + fi + else + if __git_is_configured_remote "$remote"; then + # configured remote takes precedence over a + # local directory with the same name + list_refs_from=remote + elif [ -d "$remote/.git" ]; then + dir="$remote/.git" + elif [ -d "$remote" ]; then + dir="$remote" + else + list_refs_from=url + fi + fi + + if [ "$list_refs_from" = path ]; then + 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="" ;; *) for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do - if [ -e "$dir/$i" ]; then echo $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 --git-dir="$dir" for-each-ref --format="%($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 --git-dir="$dir" 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 "$dir" "$cur*" 2>/dev/null | \ + __git ls-remote "$remote" "$match*" | \ while read -r hash i; do case "$i" in *^{}) ;; - *) echo "$i" ;; + *) echo "$pfx$i$sfx" ;; esac done ;; *) - echo "HEAD" - git for-each-ref --format="%(refname:short)" -- \ - "refs/remotes/$dir/" 2>/dev/null | sed -e "s#^$dir/##" + if [ "$list_refs_from" = remote ]; then + 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 + 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 "$pfx${i#refs/*/}$sfx" ;; + *) echo "$pfx$i$sfx" ;; # symbolic refs + esac + done + fi ;; esac } +# Completes refs, short and long, local and remote, symbolic and pseudo. +# +# Usage: __git_complete_refs [<option>]... +# --remote=<remote>: The remote to list refs from, can be the name of a +# configured remote, a path, or a URL. +# --track: List unique remote branches for 'git checkout's tracking DWIMery. +# --pfx=<prefix>: A prefix to be added to each ref. +# --cur=<word>: The current ref to be completed. Defaults to the current +# word to be completed. +# --sfx=<suffix>: A suffix to be appended to each ref instead of the default +# space. +__git_complete_refs () +{ + local remote track pfx cur_="$cur" sfx=" " + + while test $# != 0; do + case "$1" in + --remote=*) remote="${1##--remote=}" ;; + --track) track="yes" ;; + --pfx=*) pfx="${1##--pfx=}" ;; + --cur=*) cur_="${1##--cur=}" ;; + --sfx=*) sfx="${1##--sfx=}" ;; + *) return 1 ;; + esac + shift + done + + __gitcomp_direct "$(__git_refs "$remote" "$track" "$pfx" "$cur_" "$sfx")" +} + # __git_refs2 requires 1 argument (to pass to __git_refs) +# Deprecated: use __git_complete_fetch_refspecs() instead. __git_refs2 () { local i @@ -400,11 +546,29 @@ __git_refs2 () done } +# Completes refspecs for fetching from a remote repository. +# 1: The remote repository. +# 2: A prefix to be added to each listed refspec (optional). +# 3: The ref to be completed as a refspec instead of the current word to be +# completed (optional) +# 4: A suffix to be appended to each listed refspec instead of the default +# space (optional). +__git_complete_fetch_refspecs () +{ + local i remote="$1" pfx="${2-}" cur_="${3-$cur}" sfx="${4- }" + + __gitcomp_direct "$( + for i in $(__git_refs "$remote" "" "" "$cur_") ; do + echo "$pfx$i:$i$sfx" + done + )" +} + # __git_refs_remotes requires 1 argument (to pass to ls-remote) __git_refs_remotes () { local i hash - git ls-remote "$1" 'refs/heads/*' 2>/dev/null | \ + __git ls-remote "$1" 'refs/heads/*' | \ while read -r hash i; do echo "$i:refs/remotes/$1/${i#refs/heads/}" done @@ -412,9 +576,21 @@ __git_refs_remotes () __git_remotes () { - local d="$(__gitdir)" - test -d "$d/remotes" && ls -1 "$d/remotes" - git --git-dir="$d" remote + __git_find_repo_path + test -d "$__git_repo_path/remotes" && ls -1 "$__git_repo_path/remotes" + __git remote +} + +# Returns true if $1 matches the name of a configured remote, false otherwise. +__git_is_configured_remote () +{ + local remote + for remote in $(__git_remotes); do + if [ "$remote" = "$1" ]; then + return 0 + fi + done + return 1 } __git_list_merge_strategies () @@ -468,7 +644,7 @@ __git_complete_revlist_file () *) pfx="$ref:$pfx" ;; esac - __gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" 2>/dev/null \ + __gitcomp_nl "$(__git ls-tree "$ls" \ | sed '/^100... blob /{ s,^.* ,, s,$, , @@ -487,15 +663,15 @@ __git_complete_revlist_file () *...*) pfx="${cur_%...*}..." cur_="${cur_#*...}" - __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + __git_complete_refs --pfx="$pfx" --cur="$cur_" ;; *..*) pfx="${cur_%..*}.." cur_="${cur_#*..}" - __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + __git_complete_refs --pfx="$pfx" --cur="$cur_" ;; *) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs ;; esac } @@ -541,6 +717,7 @@ __git_complete_remote_or_refspec () i="${words[c]}" case "$i" in --mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;; + -d|--delete) [ "$cmd" = "push" ] && lhs=0 ;; --all) case "$cmd" in push) no_complete_refspec=1 ;; @@ -580,23 +757,23 @@ __git_complete_remote_or_refspec () case "$cmd" in fetch) if [ $lhs = 1 ]; then - __gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_" + __git_complete_fetch_refspecs "$remote" "$pfx" "$cur_" else - __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + __git_complete_refs --pfx="$pfx" --cur="$cur_" fi ;; pull|remote) if [ $lhs = 1 ]; then - __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" + __git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_" else - __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + __git_complete_refs --pfx="$pfx" --cur="$cur_" fi ;; push) if [ $lhs = 1 ]; then - __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + __git_complete_refs --pfx="$pfx" --cur="$cur_" else - __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" + __git_complete_refs --remote="$remote" --pfx="$pfx" --cur="$cur_" fi ;; esac @@ -746,7 +923,7 @@ __git_compute_porcelain_commands () __git_get_config_variables () { local section="$1" i IFS=$'\n' - for i in $(git --git-dir="$(__gitdir)" config --name-only --get-regexp "^$section\..*" 2>/dev/null); do + for i in $(__git config --name-only --get-regexp "^$section\..*"); do echo "${i#$section.}" done } @@ -764,8 +941,7 @@ __git_aliases () # __git_aliased_command requires 1 argument __git_aliased_command () { - local word cmdline=$(git --git-dir="$(__gitdir)" \ - config --get "alias.$1") + local word cmdline=$(__git config --get "alias.$1") for word in $cmdline; do case "$word" in \!gitk|gitk) @@ -803,6 +979,50 @@ __git_find_on_cmdline () done } +# Echo the value of an option set on the command line or config +# +# $1: short option name +# $2: long option name including = +# $3: list of possible values +# $4: config string (optional) +# +# example: +# result="$(__git_get_option_value "-d" "--do-something=" \ +# "yes no" "core.doSomething")" +# +# result is then either empty (no option set) or "yes" or "no" +# +# __git_get_option_value requires 3 arguments +__git_get_option_value () +{ + local c short_opt long_opt val + local result= values config_key word + + short_opt="$1" + long_opt="$2" + values="$3" + config_key="$4" + + ((c = $cword - 1)) + while [ $c -ge 0 ]; do + word="${words[c]}" + for val in $values; do + if [ "$short_opt$val" = "$word" ] || + [ "$long_opt$val" = "$word" ]; then + result="$val" + break 2 + fi + done + ((c--)) + done + + if [ -n "$config_key" ] && [ -z "$result" ]; then + result="$(__git config "$config_key")" + fi + + echo "$result" +} + __git_has_doubledash () { local c=1 @@ -856,8 +1076,8 @@ __git_whitespacelist="nowarn warn error error-all fix" _git_am () { - local dir="$(__gitdir)" - if [ -d "$dir"/rebase-apply ]; then + __git_find_repo_path + if [ -d "$__git_repo_path"/rebase-apply ]; then __gitcomp "--skip --continue --resolved --abort" return fi @@ -891,6 +1111,7 @@ _git_apply () --apply --no-add --exclude= --ignore-whitespace --ignore-space-change --whitespace= --inaccurate-eof --verbose + --recount --directory= " return esac @@ -902,13 +1123,17 @@ _git_add () --*) __gitcomp " --interactive --refresh --patch --update --dry-run - --ignore-errors --intent-to-add + --ignore-errors --intent-to-add --force --edit --chmod= " return esac - # XXX should we check for --update and --all options ? - __git_complete_index_file "--others --modified --directory --no-empty-directory" + local complete_opt="--others --modified --directory --no-empty-directory" + if test -n "$(__git_find_on_cmdline "-u --update")" + then + complete_opt="--modified" + fi + __git_complete_index_file "$complete_opt" } _git_archive () @@ -925,7 +1150,7 @@ _git_archive () --*) __gitcomp " --format= --list --verbose - --prefix= --remote= --exec= + --prefix= --remote= --exec= --output " return ;; @@ -940,7 +1165,8 @@ _git_bisect () local subcommands="start bad good skip reset visualize replay log run" local subcommand="$(__git_find_on_cmdline "$subcommands")" if [ -z "$subcommand" ]; then - if [ -f "$(__gitdir)"/BISECT_START ]; then + __git_find_repo_path + if [ -f "$__git_repo_path"/BISECT_START ]; then __gitcomp "$subcommands" else __gitcomp "replay start" @@ -950,7 +1176,7 @@ _git_bisect () case "$subcommand" in bad|good|reset|skip|start) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs ;; *) ;; @@ -964,29 +1190,30 @@ _git_branch () while [ $c -lt $cword ]; do i="${words[c]}" case "$i" in - -d|-m) only_local_ref="y" ;; - -r) has_r="y" ;; + -d|--delete|-m|--move) only_local_ref="y" ;; + -r|--remotes) has_r="y" ;; esac ((c++)) done case "$cur" in --set-upstream-to=*) - __gitcomp_nl "$(__git_refs)" "" "${cur##--set-upstream-to=}" + __git_complete_refs --cur="${cur##--set-upstream-to=}" ;; --*) __gitcomp " --color --no-color --verbose --abbrev= --no-abbrev - --track --no-track --contains --merged --no-merged + --track --no-track --contains --no-contains --merged --no-merged --set-upstream-to= --edit-description --list - --unset-upstream + --unset-upstream --delete --move --remotes + --column --no-column --sort= --points-at " ;; *) if [ $only_local_ref = "y" -a $has_r = "n" ]; then - __gitcomp_nl "$(__git_heads)" + __gitcomp_direct "$(__git_heads "" "$cur" " ")" else - __gitcomp_nl "$(__git_refs)" + __git_complete_refs fi ;; esac @@ -1029,24 +1256,25 @@ _git_checkout () *) # check if --track, --no-track, or --no-guess was specified # if so, disable DWIM mode - local flags="--track --no-track --no-guess" track=1 - if [ -n "$(__git_find_on_cmdline "$flags")" ]; then - track='' + local flags="--track --no-track --no-guess" track_opt="--track" + if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ] || + [ -n "$(__git_find_on_cmdline "$flags")" ]; then + track_opt='' fi - __gitcomp_nl "$(__git_refs '' $track)" + __git_complete_refs $track_opt ;; esac } _git_cherry () { - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_cherry_pick () { - local dir="$(__gitdir)" - if [ -f "$dir"/CHERRY_PICK_HEAD ]; then + __git_find_repo_path + if [ -f "$__git_repo_path"/CHERRY_PICK_HEAD ]; then __gitcomp "--continue --quit --abort" return fi @@ -1055,7 +1283,7 @@ _git_cherry_pick () __gitcomp "--edit --no-commit --signoff --strategy= --mainline" ;; *) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs ;; esac } @@ -1091,18 +1319,24 @@ _git_clone () --template= --depth --single-branch + --no-tags --branch + --recurse-submodules + --no-single-branch + --shallow-submodules " return ;; esac } +__git_untracked_file_modes="all no normal" + _git_commit () { case "$prev" in -c|-C) - __gitcomp_nl "$(__git_refs)" "" "${cur}" + __git_complete_refs return ;; esac @@ -1115,11 +1349,11 @@ _git_commit () ;; --reuse-message=*|--reedit-message=*|\ --fixup=*|--squash=*) - __gitcomp_nl "$(__git_refs)" "" "${cur#*=}" + __git_complete_refs --cur="${cur#*=}" return ;; --untracked-files=*) - __gitcomp "all no normal" "" "${cur##--untracked-files=}" + __gitcomp "$__git_untracked_file_modes" "" "${cur##--untracked-files=}" return ;; --*) @@ -1131,11 +1365,12 @@ _git_commit () --reset-author --file= --message= --template= --cleanup= --untracked-files --untracked-files= --verbose --quiet --fixup= --squash= + --patch --short --date --allow-empty " return esac - if git rev-parse --verify --quiet HEAD >/dev/null; then + if __git rev-parse --verify --quiet HEAD >/dev/null; then __git_complete_index_file "--committable" else # This is the first commit @@ -1149,15 +1384,18 @@ _git_describe () --*) __gitcomp " --all --tags --contains --abbrev= --candidates= - --exact-match --debug --long --match --always + --exact-match --debug --long --match --always --first-parent + --exclude " return esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } __git_diff_algorithms="myers minimal patience histogram" +__git_diff_submodule_formats="diff log short" + __git_diff_common_options="--stat --numstat --shortstat --summary --patch-with-stat --name-only --name-status --color --no-color --color-words --no-renames --check @@ -1173,6 +1411,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary --dirstat --dirstat= --dirstat-by-file --dirstat-by-file= --cumulative --diff-algorithm= + --submodule --submodule= " _git_diff () @@ -1184,6 +1423,10 @@ _git_diff () __gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}" return ;; + --submodule=*) + __gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}" + return + ;; --*) __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex --base --ours --theirs --no-index @@ -1225,6 +1468,7 @@ __git_fetch_recurse_submodules="yes on-demand no" __git_fetch_options=" --quiet --verbose --append --upload-pack --force --keep --depth= --tags --no-tags --all --prune --dry-run --recurse-submodules= + --unshallow --update-shallow " _git_fetch () @@ -1274,7 +1518,7 @@ _git_fsck () --*) __gitcomp " --tags --root --unreachable --cache --no-reflogs --full - --strict --verbose --lost-found + --strict --verbose --lost-found --name-objects " return ;; @@ -1296,8 +1540,43 @@ _git_gitk () _gitk } -__git_match_ctag() { - awk "/^${1//\//\\/}/ { print \$1 }" "$2" +# Lists matching symbol names from a tag (as in ctags) file. +# 1: List symbol names matching this word. +# 2: The tag file to list symbol names from. +# 3: A prefix to be added to each listed symbol name (optional). +# 4: A suffix to be appended to each listed symbol name (optional). +__git_match_ctag () { + awk -v pfx="${3-}" -v sfx="${4-}" " + /^${1//\//\\/}/ { print pfx \$1 sfx } + " "$2" +} + +# Complete symbol names from a tag file. +# Usage: __git_complete_symbol [<option>]... +# --tags=<file>: The tag file to list symbol names from instead of the +# default "tags". +# --pfx=<prefix>: A prefix to be added to each symbol name. +# --cur=<word>: The current symbol name to be completed. Defaults to +# the current word to be completed. +# --sfx=<suffix>: A suffix to be appended to each symbol name instead +# of the default space. +__git_complete_symbol () { + local tags=tags pfx="" cur_="${cur-}" sfx=" " + + while test $# != 0; do + case "$1" in + --tags=*) tags="${1##--tags=}" ;; + --pfx=*) pfx="${1##--pfx=}" ;; + --cur=*) cur_="${1##--cur=}" ;; + --sfx=*) sfx="${1##--sfx=}" ;; + *) return 1 ;; + esac + shift + done + + if test -r "$tags"; then + __gitcomp_direct "$(__git_match_ctag "$cur_" "$tags" "$pfx" "$sfx")" + fi } _git_grep () @@ -1318,6 +1597,8 @@ _git_grep () --max-depth --count --and --or --not --all-match + --break --heading --show-function --function-context + --untracked --no-index " return ;; @@ -1325,29 +1606,26 @@ _git_grep () case "$cword,$prev" in 2,*|*,-*) - if test -r tags; then - __gitcomp_nl "$(__git_match_ctag "$cur" tags)" - return - fi + __git_complete_symbol && return ;; esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_help () { case "$cur" in --*) - __gitcomp "--all --info --man --web" + __gitcomp "--all --guides --info --man --web" return ;; esac __git_compute_all_commands __gitcomp "$__git_all_commands $(__git_aliases) attributes cli core-tutorial cvs-migration - diffcore gitk glossary hooks ignore modules - namespaces repository-layout tutorial tutorial-2 + diffcore everyday gitk glossary hooks ignore modules + namespaces repository-layout revisions tutorial tutorial-2 workflows " } @@ -1390,6 +1668,12 @@ _git_ls_files () _git_ls_remote () { + case "$cur" in + --*) + __gitcomp "--heads --tags --refs --get-url --symref" + return + ;; + esac __gitcomp_nl "$(__git_remotes)" } @@ -1427,12 +1711,25 @@ __git_log_date_formats="relative iso8601 rfc2822 short local default raw" _git_log () { __git_has_doubledash && return + __git_find_repo_path - local g="$(git rev-parse --git-dir 2>/dev/null)" local merge="" - if [ -f "$g/MERGE_HEAD" ]; then + if [ -f "$__git_repo_path/MERGE_HEAD" ]; then merge="--merge" fi + case "$prev,$cur" in + -L,:*:*) + return # fall back to Bash filename completion + ;; + -L,:*) + __git_complete_symbol --cur="${cur#:}" --sfx=":" + return + ;; + -G,*|-S,*) + __git_complete_symbol + return + ;; + esac case "$cur" in --pretty=*|--format=*) __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases) @@ -1447,6 +1744,14 @@ _git_log () __gitcomp "full short no" "" "${cur##--decorate=}" return ;; + --diff-algorithm=*) + __gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}" + return + ;; + --submodule=*) + __gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}" + return + ;; --*) __gitcomp " $__git_log_common_options @@ -1458,6 +1763,7 @@ _git_log () --relative-date --date= --pretty= --format= --oneline --show-signature + --cherry-mark --cherry-pick --graph --decorate --decorate= @@ -1469,6 +1775,21 @@ _git_log () " return ;; + -L:*:*) + return # fall back to Bash filename completion + ;; + -L:*) + __git_complete_symbol --cur="${cur#-L:}" --sfx=":" + return + ;; + -G*) + __git_complete_symbol --pfx="-G" --cur="${cur#-G}" + return + ;; + -S*) + __git_complete_symbol --pfx="-S" --cur="${cur#-S}" + return + ;; esac __git_complete_revlist } @@ -1488,10 +1809,10 @@ _git_merge () case "$cur" in --*) __gitcomp "$__git_merge_options - --rerere-autoupdate --no-rerere-autoupdate --abort" + --rerere-autoupdate --no-rerere-autoupdate --abort --continue" return esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_mergetool () @@ -1502,7 +1823,7 @@ _git_mergetool () return ;; --*) - __gitcomp "--tool=" + __gitcomp "--tool= --prompt --no-prompt" return ;; esac @@ -1516,7 +1837,7 @@ _git_merge_base () return ;; esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_mv () @@ -1554,7 +1875,7 @@ _git_notes () ,*) case "$prev" in --ref) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs ;; *) __gitcomp "$subcommands --ref" @@ -1563,7 +1884,7 @@ _git_notes () ;; add,--reuse-message=*|append,--reuse-message=*|\ add,--reedit-message=*|append,--reedit-message=*) - __gitcomp_nl "$(__git_refs)" "" "${cur#*=}" + __git_complete_refs --cur="${cur#*=}" ;; add,--*|append,--*) __gitcomp '--file= --message= --reedit-message= @@ -1582,7 +1903,7 @@ _git_notes () -m|-F) ;; *) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs ;; esac ;; @@ -1610,7 +1931,7 @@ _git_pull () __git_complete_remote_or_refspec } -__git_push_recurse_submodules="check on-demand" +__git_push_recurse_submodules="check on-demand only" __git_complete_force_with_lease () { @@ -1620,10 +1941,10 @@ __git_complete_force_with_lease () --*=) ;; *:*) - __gitcomp_nl "$(__git_refs)" "" "${cur_#*:}" + __git_complete_refs --cur="${cur_#*:}" ;; *) - __gitcomp_nl "$(__git_refs)" "" "$cur_" + __git_complete_refs --cur="$cur_" ;; esac } @@ -1668,12 +1989,13 @@ _git_push () _git_rebase () { - local dir="$(__gitdir)" - if [ -f "$dir"/rebase-merge/interactive ]; then - __gitcomp "--continue --skip --abort --edit-todo" + __git_find_repo_path + if [ -f "$__git_repo_path"/rebase-merge/interactive ]; then + __gitcomp "--continue --skip --abort --quit --edit-todo" return - elif [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then - __gitcomp "--continue --skip --abort" + elif [ -d "$__git_repo_path"/rebase-apply ] || \ + [ -d "$__git_repo_path"/rebase-merge ]; then + __gitcomp "--continue --skip --abort --quit" return fi __git_complete_strategy && return @@ -1698,7 +2020,7 @@ _git_rebase () return esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_reflog () @@ -1709,7 +2031,7 @@ _git_reflog () if [ -z "$subcommand" ]; then __gitcomp "$subcommands" else - __gitcomp_nl "$(__git_refs)" + __git_complete_refs fi } @@ -1720,9 +2042,7 @@ _git_send_email () { case "$prev" in --to|--cc|--bcc|--from) - __gitcomp " - $(git --git-dir="$(__gitdir)" send-email --dump-aliases 2>/dev/null) - " + __gitcomp "$(__git send-email --dump-aliases)" return ;; esac @@ -1752,9 +2072,7 @@ _git_send_email () return ;; --to=*|--cc=*|--bcc=*|--from=*) - __gitcomp " - $(git --git-dir="$(__gitdir)" send-email --dump-aliases 2>/dev/null) - " "" "${cur#--*=}" + __gitcomp "$(__git send-email --dump-aliases)" "" "${cur#--*=}" return ;; --*) @@ -1779,6 +2097,56 @@ _git_stage () _git_add } +_git_status () +{ + local complete_opt + local untracked_state + + case "$cur" in + --ignore-submodules=*) + __gitcomp "none untracked dirty all" "" "${cur##--ignore-submodules=}" + return + ;; + --untracked-files=*) + __gitcomp "$__git_untracked_file_modes" "" "${cur##--untracked-files=}" + return + ;; + --column=*) + __gitcomp " + always never auto column row plain dense nodense + " "" "${cur##--column=}" + return + ;; + --*) + __gitcomp " + --short --branch --porcelain --long --verbose + --untracked-files= --ignore-submodules= --ignored + --column= --no-column + " + return + ;; + esac + + untracked_state="$(__git_get_option_value "-u" "--untracked-files=" \ + "$__git_untracked_file_modes" "status.showUntrackedFiles")" + + case "$untracked_state" in + no) + # --ignored option does not matter + complete_opt= + ;; + all|normal|*) + complete_opt="--cached --directory --no-empty-directory --others" + + if [ -n "$(__git_find_on_cmdline "--ignored")" ]; then + complete_opt="$complete_opt --ignored --exclude=*" + fi + ;; + esac + + __git_complete_index_file "$complete_opt" +} + __git_config_get_set_variables () { local prevword word config_file= c=$cword @@ -1798,7 +2166,7 @@ __git_config_get_set_variables () c=$((--c)) done - git --git-dir="$(__gitdir)" config $config_file --name-only --list 2>/dev/null + __git config $config_file --name-only --list } _git_config () @@ -1809,7 +2177,7 @@ _git_config () return ;; branch.*.merge) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs return ;; branch.*.rebase) @@ -1833,9 +2201,8 @@ _git_config () remote.*.push) local remote="${prev#remote.}" remote="${remote%.push}" - __gitcomp_nl "$(git --git-dir="$(__gitdir)" \ - for-each-ref --format='%(refname):%(refname)' \ - refs/heads)" + __gitcomp_nl "$(__git for-each-ref \ + --format='%(refname):%(refname)' refs/heads)" return ;; pull.twohead|pull.octopus) @@ -1914,7 +2281,7 @@ _git_config () ;; branch.*) local pfx="${cur%.*}." cur_="${cur#*.}" - __gitcomp_nl "$(__git_heads)" "$pfx" "$cur_" "." + __gitcomp_direct "$(__git_heads "$pfx" "$cur_" ".")" __gitcomp_nl_append $'autosetupmerge\nautosetuprebase\n' "$pfx" "$cur_" return ;; @@ -1969,14 +2336,23 @@ _git_config () esac __gitcomp " add.ignoreErrors + advice.amWorkDir advice.commitBeforeMerge advice.detachedHead advice.implicitIdentity - advice.pushNonFastForward + advice.pushAlreadyExists + advice.pushFetchFirst + advice.pushNeedsForce + advice.pushNonFFCurrent + advice.pushNonFFMatching + advice.pushUpdateRejected advice.resolveConflict + advice.rmHints advice.statusHints + advice.statusUoption alias. am.keepcr + am.threeWay apply.ignorewhitespace apply.whitespace branch.autosetupmerge @@ -2021,19 +2397,26 @@ _git_config () color.status.added color.status.changed color.status.header + color.status.localBranch color.status.nobranch + color.status.remoteBranch color.status.unmerged color.status.untracked color.status.updated color.ui + commit.cleanup + commit.gpgSign commit.status commit.template + commit.verbose core.abbrev core.askpass core.attributesfile core.autocrlf core.bare core.bigFileThreshold + core.checkStat + core.commentChar core.compression core.createObject core.deltaBaseCacheLimit @@ -2043,6 +2426,8 @@ _git_config () core.fileMode core.fsyncobjectfiles core.gitProxy + core.hideDotFiles + core.hooksPath core.ignoreStat core.ignorecase core.logAllRefUpdates @@ -2050,20 +2435,30 @@ _git_config () core.notesRef core.packedGitLimit core.packedGitWindowSize + core.packedRefsTimeout core.pager + core.precomposeUnicode core.preferSymlinkRefs core.preloadindex + core.protectHFS + core.protectNTFS core.quotepath core.repositoryFormatVersion core.safecrlf core.sharedRepository core.sparseCheckout + core.splitIndex + core.sshCommand core.symlinks core.trustctime core.untrackedCache core.warnAmbiguousRefs core.whitespace core.worktree + credential.helper + credential.useHttpPath + credential.username + credentialCache.ignoreSIGHUP diff.autorefreshindex diff.external diff.ignoreSubmodules @@ -2084,6 +2479,7 @@ _git_config () format.attach format.cc format.coverLetter + format.from format.headers format.numbered format.pretty @@ -2094,15 +2490,19 @@ _git_config () format.thread format.to gc. + gc.aggressiveDepth gc.aggressiveWindow gc.auto + gc.autoDetach gc.autopacklimit + gc.logExpiry gc.packrefs gc.pruneexpire gc.reflogexpire gc.reflogexpireunreachable gc.rerereresolved gc.rerereunresolved + gc.worktreePruneExpire gitcvs.allbinary gitcvs.commitmsgannotation gitcvs.dbTableNamePrefix @@ -2241,6 +2641,8 @@ _git_config () sendemail.thread sendemail.to sendemail.validate + sendemail.smtpbatchsize + sendemail.smtprelogindelay showbranch.default status.relativePaths status.showUntrackedFiles @@ -2259,31 +2661,79 @@ _git_config () _git_remote () { - local subcommands="add rename remove set-head set-branches set-url show prune update" + local subcommands=" + add rename remove set-head set-branches + get-url set-url show prune update + " local subcommand="$(__git_find_on_cmdline "$subcommands")" if [ -z "$subcommand" ]; then - __gitcomp "$subcommands" + case "$cur" in + --*) + __gitcomp "--verbose" + ;; + *) + __gitcomp "$subcommands" + ;; + esac return fi - case "$subcommand" in - rename|remove|set-url|show|prune) - __gitcomp_nl "$(__git_remotes)" + case "$subcommand,$cur" in + add,--*) + __gitcomp "--track --master --fetch --tags --no-tags --mirror=" + ;; + add,*) + ;; + set-head,--*) + __gitcomp "--auto --delete" + ;; + set-branches,--*) + __gitcomp "--add" ;; - set-head|set-branches) + set-head,*|set-branches,*) __git_complete_remote_or_refspec ;; - update) + update,--*) + __gitcomp "--prune" + ;; + update,*) __gitcomp "$(__git_get_config_variables "remotes")" ;; + set-url,--*) + __gitcomp "--push --add --delete" + ;; + get-url,--*) + __gitcomp "--push --all" + ;; + prune,--*) + __gitcomp "--dry-run" + ;; *) + __gitcomp_nl "$(__git_remotes)" ;; esac } _git_replace () { - __gitcomp_nl "$(__git_refs)" + case "$cur" in + --*) + __gitcomp "--edit --graft --format= --list --delete" + return + ;; + esac + __git_complete_refs +} + +_git_rerere () +{ + local subcommands="clear forget diff remaining status gc" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if test -z "$subcommand" + then + __gitcomp "$subcommands" + return + fi } _git_reset () @@ -2292,27 +2742,30 @@ _git_reset () case "$cur" in --*) - __gitcomp "--merge --mixed --hard --soft --patch" + __gitcomp "--merge --mixed --hard --soft --patch --keep" return ;; esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_revert () { - local dir="$(__gitdir)" - if [ -f "$dir"/REVERT_HEAD ]; then + __git_find_repo_path + if [ -f "$__git_repo_path"/REVERT_HEAD ]; then __gitcomp "--continue --quit --abort" return fi case "$cur" in --*) - __gitcomp "--edit --mainline --no-edit --no-commit --signoff" + __gitcomp " + --edit --mainline --no-edit --no-commit --signoff + --strategy= --strategy-option= + " return ;; esac - __gitcomp_nl "$(__git_refs)" + __git_complete_refs } _git_rm () @@ -2336,7 +2789,7 @@ _git_shortlog () __gitcomp " $__git_log_common_options $__git_log_shortlog_options - --numbered --summary + --numbered --summary --email " return ;; @@ -2358,6 +2811,10 @@ _git_show () __gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}" return ;; + --submodule=*) + __gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}" + return + ;; --*) __gitcomp "--pretty= --format= --abbrev-commit --oneline --show-signature @@ -2388,7 +2845,7 @@ _git_show_branch () _git_stash () { local save_opts='--all --keep-index --no-keep-index --quiet --patch --include-untracked' - local subcommands='save list show apply clear drop pop create branch' + local subcommands='push save list show apply clear drop pop create branch' local subcommand="$(__git_find_on_cmdline "$subcommands")" if [ -z "$subcommand" ]; then case "$cur" in @@ -2403,6 +2860,9 @@ _git_stash () esac else case "$subcommand,$cur" in + push,--*) + __gitcomp "$save_opts --message" + ;; save,--*) __gitcomp "$save_opts" ;; @@ -2416,14 +2876,14 @@ _git_stash () ;; branch,*) if [ $cword -eq 3 ]; then - __gitcomp_nl "$(__git_refs)"; + __git_complete_refs else - __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \ + __gitcomp_nl "$(__git stash list \ | sed -n -e 's/:.*//p')" fi ;; show,*|apply,*|drop,*|pop,*) - __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \ + __gitcomp_nl "$(__git stash list \ | sed -n -e 's/:.*//p')" ;; *) @@ -2437,10 +2897,11 @@ _git_submodule () __git_has_doubledash && return local subcommands="add status init deinit update summary foreach sync" - if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then case "$cur" in --*) - __gitcomp "--quiet --cached" + __gitcomp "--quiet" ;; *) __gitcomp "$subcommands" @@ -2448,6 +2909,33 @@ _git_submodule () esac return fi + + case "$subcommand,$cur" in + add,--*) + __gitcomp "--branch --force --name --reference --depth" + ;; + status,--*) + __gitcomp "--cached --recursive" + ;; + deinit,--*) + __gitcomp "--force --all" + ;; + update,--*) + __gitcomp " + --init --remote --no-fetch + --recommend-shallow --no-recommend-shallow + --force --rebase --merge --reference --depth --recursive --jobs + " + ;; + summary,--*) + __gitcomp "--cached --files --summary-limit" + ;; + foreach,--*|sync,--*) + __gitcomp "--recursive" + ;; + *) + ;; + esac } _git_svn () @@ -2468,14 +2956,14 @@ _git_svn () --no-metadata --use-svm-props --use-svnsync-props --log-window-size= --no-checkout --quiet --repack-flags --use-log-author --localtime + --add-author-from --ignore-paths= --include-paths= $remote_opts " local init_opts=" --template= --shared= --trunk= --tags= --branches= --stdlayout --minimize-url --no-metadata --use-svm-props --use-svnsync-props - --rewrite-root= --prefix= --use-log-author - --add-author-from $remote_opts + --rewrite-root= --prefix= $remote_opts " local cmt_opts=" --edit --rmdir --find-copies-harder --copy-similarity= @@ -2555,7 +3043,7 @@ _git_tag () i="${words[c]}" case "$i" in -d|-v) - __gitcomp_nl "$(__git_tags)" + __gitcomp_direct "$(__git_tags "" "$cur" " ")" return ;; -f) @@ -2570,11 +3058,11 @@ _git_tag () ;; -*|tag) if [ $f = 1 ]; then - __gitcomp_nl "$(__git_tags)" + __gitcomp_direct "$(__git_tags "" "$cur" " ")" fi ;; *) - __gitcomp_nl "$(__git_refs)" + __git_complete_refs ;; esac @@ -2582,8 +3070,8 @@ _git_tag () --*) __gitcomp " --list --delete --verify --annotate --message --file - --sign --cleanup --local-user --force --column --sort - --contains --points-at + --sign --cleanup --local-user --force --column --sort= + --contains --no-contains --points-at --merged --no-merged --create-reflog " ;; esac @@ -2594,9 +3082,36 @@ _git_whatchanged () _git_log } +_git_worktree () +{ + local subcommands="add list lock prune unlock" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + else + case "$subcommand,$cur" in + add,--*) + __gitcomp "--detach" + ;; + list,--*) + __gitcomp "--porcelain" + ;; + lock,--*) + __gitcomp "--reason" + ;; + prune,--*) + __gitcomp "--dry-run --expire --verbose" + ;; + *) + ;; + esac + fi +} + __git_main () { - local i c=1 command __git_dir + local i c=1 command __git_dir __git_repo_path + local __git_C_args C_args_count=0 while [ $c -lt $cword ]; do i="${words[c]}" @@ -2606,6 +3121,10 @@ __git_main () --bare) __git_dir="." ;; --help) command="help"; break ;; -c|--work-tree|--namespace) ((c++)) ;; + -C) __git_C_args[C_args_count++]=-C + ((c++)) + __git_C_args[C_args_count++]="${words[c]}" + ;; -*) ;; *) command="$i"; break ;; esac @@ -2613,6 +3132,17 @@ __git_main () done if [ -z "$command" ]; then + case "$prev" in + --git-dir|-C|--work-tree) + # these need a path argument, let's fall back to + # Bash filename completion + return + ;; + -c|--namespace) + # we don't support completing these options' arguments + return + ;; + esac case "$cur" in --*) __gitcomp " --paginate @@ -2638,13 +3168,13 @@ __git_main () fi local completion_func="_git_${command//-/_}" - declare -f $completion_func >/dev/null && $completion_func && return + declare -f $completion_func >/dev/null 2>/dev/null && $completion_func && return local expansion=$(__git_aliased_command "$command") if [ -n "$expansion" ]; then words[1]=$expansion completion_func="_git_${expansion//-/_}" - declare -f $completion_func >/dev/null && $completion_func + declare -f $completion_func >/dev/null 2>/dev/null && $completion_func fi } @@ -2652,9 +3182,11 @@ __gitk_main () { __git_has_doubledash && return - local g="$(__gitdir)" + local __git_repo_path + __git_find_repo_path + local merge="" - if [ -f "$g/MERGE_HEAD" ]; then + if [ -f "$__git_repo_path/MERGE_HEAD" ]; then merge="--merge" fi case "$cur" in @@ -2701,6 +3233,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 @@ -2771,6 +3312,6 @@ __git_complete gitk __gitk_main # when the user has tab-completed the executable name and consequently # included the '.exe' suffix. # -if [[ "$OSTYPE" = cygwin* ]]; then +if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then __git_complete git.exe __git_main fi diff --git a/plugins/gitfast/git-prompt.sh b/plugins/gitfast/git-prompt.sh index 0da14eee9..cd905759e 100644 --- a/plugins/gitfast/git-prompt.sh +++ b/plugins/gitfast/git-prompt.sh @@ -82,6 +82,7 @@ # contains relative to newer annotated tag (v1.6.3.2~35) # branch relative to newer tag or branch (master~4) # describe relative to older annotated tag (v1.6.3.1-13-gdd42c2f) +# tag relative to any older tag (v1.6.3.1-13-gdd42c2f) # default exactly matching tag # # If you would like a colored hint about the current dirty state, set @@ -355,8 +356,8 @@ __git_ps1 () # incorrect.) # local ps1_expanded=yes - [ -z "$ZSH_VERSION" ] || [[ -o PROMPT_SUBST ]] || ps1_expanded=no - [ -z "$BASH_VERSION" ] || shopt -q promptvars || ps1_expanded=no + [ -z "${ZSH_VERSION-}" ] || [[ -o PROMPT_SUBST ]] || ps1_expanded=no + [ -z "${BASH_VERSION-}" ] || shopt -q promptvars || ps1_expanded=no local repo_info rev_parse_exit_code repo_info="$(git rev-parse --git-dir --is-inside-git-dir \ @@ -368,7 +369,7 @@ __git_ps1 () return $exit fi - local short_sha + local short_sha="" if [ "$rev_parse_exit_code" = "0" ]; then short_sha="${repo_info##*$'\n'}" repo_info="${repo_info%$'\n'*}" @@ -443,6 +444,8 @@ __git_ps1 () git describe --contains HEAD ;; (branch) git describe --contains --all HEAD ;; + (tag) + git describe --tags HEAD ;; (describe) git describe HEAD ;; (* | default) diff --git a/plugins/gitfast/gitfast.plugin.zsh b/plugins/gitfast/gitfast.plugin.zsh index dba1b1315..8c2aea497 100644 --- a/plugins/gitfast/gitfast.plugin.zsh +++ b/plugins/gitfast/gitfast.plugin.zsh @@ -1,8 +1,9 @@ -dir=$(dirname $0) -source $dir/../git/git.plugin.zsh -source $dir/git-prompt.sh +dir="${0:A:h}" +source "$dir/git-prompt.sh" function git_prompt_info() { dirty="$(parse_git_dirty)" __git_ps1 "${ZSH_THEME_GIT_PROMPT_PREFIX//\%/%%}%s${dirty//\%/%%}${ZSH_THEME_GIT_PROMPT_SUFFIX//\%/%%}" } + +unset dir |