From: Felipe Contreras <felipe.contreras@xxxxxxxxx> It seems there's always issues with zsh's bash completion emulation, after I took a deep look at the code, I found many issues[1]. So, here is a kind of wrapper that does the same, but properly :) This would also allow us to make fixes if necessary, since the code is simple enough, and extend functionality. [1] http://article.gmane.org/gmane.comp.shells.zsh.devel/24290 Signed-off-by: Felipe Contreras <felipe.contreras@xxxxxxxxx> --- v2: * Fix completion of aliased commands * Add check for wrong commands * Properly set return codes * Add default actiooon; for 'git foo -- <tab>' contrib/completion/git-completion.zsh | 181 +++++++++++++++++++++++++++++++++ 1 files changed, 181 insertions(+), 0 deletions(-) create mode 100644 contrib/completion/git-completion.zsh diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh new file mode 100644 index 0000000..bca08f2 --- /dev/null +++ b/contrib/completion/git-completion.zsh @@ -0,0 +1,181 @@ +#compdef git gitk + +# zsh completion wrapper for git +# +# You need git's bash completion script installed somewhere, by default on the +# same directory as this script. +# +# If your script is on ~/.git-completion.sh instead, you can configure it on +# your ~/.zshrc: +# +# zstyle ':completion:*:*:git:*' script ~/.git-completion.sh +# +# The recommended way to install this script is to copy to +# '~/.zsh/completion/_git', and then add the following to your ~/.zshrc file: +# +# fpath=(~/.zsh/completion $fpath) + +compgen () { + local prefix suffix + local -a results + while getopts "W:P:S:" opt + do + case $opt in + W) + results=( ${(Q)~=OPTARG} ) + ;; + P) + prefix="$OPTARG" + ;; + S) + suffix="$OPTARG" + ;; + esac + done + print -l -r -- "$prefix${^results[@]}$suffix" +} + +complete () { + # do nothing + return 0 +} + +zstyle -s ":completion:$curcontext:" script script +test -z "$script" && script="$(dirname ${funcsourcetrace[1]%:*})"/git-completion.bash +ZSH_VERSION='' . "$script" + +_get_comp_words_by_ref () +{ + while [ $# -gt 0 ]; do + case "$1" in + cur) + cur=${_words[CURRENT]} + ;; + prev) + cur=${_words[CURRENT-1]} + ;; + words) + words=("${_words[@]}") + ;; + cword) + ((cword = CURRENT - 1)) + ;; + esac + shift + done +} + +_bash_wrap () +{ + local -a COMPREPLY results _words + _words=( $words ) + () { + emulate -L sh + setopt KSH_TYPESET + setopt kshglob noshglob braceexpand nokshautoload + typeset -h words + local cur words cword prev + _get_comp_words_by_ref -n =: cur words cword prev + $1 + } $1 + results=( "${^COMPREPLY[@]}" ) + if [[ -n $results ]]; then + local COMP_WORDBREAKS="\"'@><=;|&(:" + local i start + local cur="${words[CURRENT]}" + i=$(expr index "$cur" "$COMP_WORDBREAKS") + start="${cur:0:$i}" + compadd -Q -S '' -p "$start" -a results && ret=0 + fi + if (( ret )); then + _default -S '' && ret=0 + fi +} + +_gitk () +{ + __git_has_doubledash && return + + local g="$(__gitdir)" + local merge="" + if [ -f "$g/MERGE_HEAD" ]; then + merge="--merge" + fi + case "$cur" in + --*) + __gitcomp " + $__git_log_common_options + $__git_log_gitk_options + $merge + " + return + ;; + esac + __git_complete_revlist +} + +_get_completion_func () +{ + emulate -L sh + setopt KSH_TYPESET + local command="$1" + + completion_func="_git_${command//-/_}" + declare -f $completion_func >/dev/null && return + + local expansion=$(__git_aliased_command "$command") + if [ -n "$expansion" ]; then + completion_func="_git_${expansion//-/_}" + declare -f $completion_func >/dev/null && return + fi + + completion_func= +} + +_git () +{ + local ret=1 + + if [[ $service != git ]] + then + _bash_wrap _$service + return ret + fi + + local curcontext="$curcontext" state state_descr line + typeset -A opt_args + + _arguments -C \ + '(-p --paginate --no-pager)'{-p,--paginate}'[Pipe all output into ''less'']' \ + '(-p --paginate)--no-pager[Do not pipe git output into a pager]' \ + '--git-dir=-[Set the path to the repository]: :_directories' \ + '--bare[Treat the repository as a bare repository]' \ + '(- :)--version[Prints the git suite version]' \ + '--exec-path=-[Path to where your core git programs are installed]:: :_directories' \ + '--html-path[Print the path where git''s HTML documentation is installed]' \ + '--work-tree=-[Set the path to the working tree]: :_directories' \ + '--namespace=-[Set the git namespace]: :_directories' \ + '(- :)--help[Prints the synopsis and a list of the most commonly used commands]' \ + '(-): :->command' \ + '(-)*:: :->option-or-argument' && return 0 + + case $state in + (command) + emulate sh -c __git_compute_porcelain_commands + local -a porcelain aliases + porcelain=( ${=__git_porcelain_commands} ) + aliases=( $(__git_aliases) ) + _describe -t porcelain-commands 'porcelain commands' porcelain && ret=0 + _describe -t aliases 'aliases' aliases && ret=0 + ;; + (option-or-argument) + local completion_func + _get_completion_func "${words[1]}" + test "$completion_func" && _bash_wrap $completion_func + ;; + esac + + return ret +} + +_git -- 1.7.8 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html