completion: make compatible with zsh

Modify git-completion.bash so that it also works with zsh when using
bashcompinit.  In particular:

declare -F
    Zsh doesn't have the same 'declare -F' as bash, but 'declare -f'
    is the same, and it works just as well for our purposes.

${var:2}
    Zsh does not implement ${var:2} to skip the first 2 characters, but
    ${var#??} works in both shells to replace the first 2 characters
    with nothing.  Thanks to Jonathan Nieder for the suggestion.

for (( n=1; "$n" ... ))
    Zsh does not allow "$var" in arithmetic loops.  Instead, pre-compute
    the endpoint and use the variables without $'s or quotes.

shopt
    Zsh uses 'setopt', which has a different syntax than 'shopt'.  Since
    'shopt' is used infrequently in git-completion, we provide
    a bare-bones emulation.

emulate -L bash
KSH_TYPESET
    Zsh offers bash emulation, which turns on a set of features to
    closely resemble bash. In particular, this enables SH_WORDSPLIT,
    which splits scalar variables on word boundaries in 'for' loops.
    We also need to set KSH_TYPESET, to fix "local var=$(echo foo bar)"
    issues.

The last set of options are turned on only in _git and _gitk.  Some of
the sub-functions may not work correctly if called directly.

Signed-off-by: Mark Lodato <lodatom@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Mark Lodato 2010-09-06 08:33:19 -04:00 committed by Junio C Hamano
parent 154adcf9c0
commit 06f44c3cc5

View File

@ -21,6 +21,11 @@
# 2) Added the following line to your .bashrc:
# source ~/.git-completion.sh
#
# Or, add the following lines to your .zshrc:
# autoload bashcompinit
# bashcompinit
# source ~/.git-completion.sh
#
# 3) Consider changing your PS1 to also show the current branch:
# PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
#
@ -138,11 +143,12 @@ __git_ps1_show_upstream ()
# get the upstream from the "git-svn-id: ..." in a commit message
# (git-svn uses essentially the same procedure internally)
local svn_upstream=($(git log --first-parent -1 \
--grep="^git-svn-id: \(${svn_url_pattern:2}\)" 2>/dev/null))
--grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null))
if [[ 0 -ne ${#svn_upstream[@]} ]]; then
svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]}
svn_upstream=${svn_upstream%@*}
for ((n=1; "$n" <= "${#svn_remote[@]}"; ++n)); do
local n_stop="${#svn_remote[@]}"
for ((n=1; n <= n_stop; ++n)); do
svn_upstream=${svn_upstream#${svn_remote[$n]}}
done
@ -2339,6 +2345,11 @@ _git ()
{
local i c=1 command __git_dir
if [[ -n $ZSH_VERSION ]]; then
emulate -L bash
setopt KSH_TYPESET
fi
while [ $c -lt $COMP_CWORD ]; do
i="${COMP_WORDS[c]}"
case "$i" in
@ -2372,17 +2383,22 @@ _git ()
fi
local completion_func="_git_${command//-/_}"
declare -F $completion_func >/dev/null && $completion_func && return
declare -f $completion_func >/dev/null && $completion_func && return
local expansion=$(__git_aliased_command "$command")
if [ -n "$expansion" ]; then
completion_func="_git_${expansion//-/_}"
declare -F $completion_func >/dev/null && $completion_func
declare -f $completion_func >/dev/null && $completion_func
fi
}
_gitk ()
{
if [[ -n $ZSH_VERSION ]]; then
emulate -L bash
setopt KSH_TYPESET
fi
__git_has_doubledash && return
local cur="${COMP_WORDS[COMP_CWORD]}"
@ -2417,3 +2433,29 @@ if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
complete -o bashdefault -o default -o nospace -F _git git.exe 2>/dev/null \
|| complete -o default -o nospace -F _git git.exe
fi
if [[ -n $ZSH_VERSION ]]; then
shopt () {
local option
if [ $# -ne 2 ]; then
echo "USAGE: $0 (-q|-s|-u) <option>" >&2
return 1
fi
case "$2" in
nullglob)
option="$2"
;;
*)
echo "$0: invalid option: $2" >&2
return 1
esac
case "$1" in
-q) setopt | grep -q "$option" ;;
-u) unsetopt "$option" ;;
-s) setopt "$option" ;;
*)
echo "$0: invalid flag: $1" >&2
return 1
esac
}
fi