# [PATCH] completion: add new zsh completion

7 messages from 2012-01-30 to 2012-01-30. Participants: Felipe Contreras, Matthieu Moy, Johannes Sixt, Junio C Hamano.
Thread: https://gitlist.dev/t/29470

## Felipe Contreras, 2012-01-30 00:01

Subject: [PATCH] completion: add new zsh completion
Message-ID: <1327881699-25461-1-git-send-email-felipe.contreras@gmail.com>
URL: https://gitlist.dev/e/1327881699-25461-1-git-send-email-felipe.contreras%40gmail.com

```
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@gmail.com>
---
 contrib/completion/git-completion.zsh |  146 +++++++++++++++++++++++++++++++++
 1 files changed, 146 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..15961df
--- /dev/null
+++ b/contrib/completion/git-completion.zsh
@@ -0,0 +1,146 @@
+#compdef git gitk
+
+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
+}
+
+ZSH_VERSION='' . /usr/share/git/completion/git-completion.bash
+
+_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 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[@]}" )
+	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 && return 0
+}
+
+_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
+}
+
+_git ()
+{
+	if [[ $service != git ]]
+	then
+		_bash_wrap _$service
+		return ret
+	fi
+
+	local ret=1
+	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 command="${words[1]}"
+
+		completion_func="_git_${command//-/_}"
+		declare -f $completion_func >/dev/null && _bash_wrap $completion_func && return 0
+
+		local expansion=$(__git_aliased_command "$command")
+		if [ -n "$expansion" ]; then
+			completion_func="_git_${expansion//-/_}"
+			declare -f $completion_func >/dev/null && _bash_wrap $completion_func && return 0
+		fi
+		;;
+	esac
+
+	return ret
+}
+
+_git
-- 
1.7.8.3

```

## Matthieu Moy, 2012-01-30 08:39

Subject: Re: [PATCH] completion: add new zsh completion
Message-ID: <vpqwr89d1p7.fsf@bauges.imag.fr>
URL: https://gitlist.dev/e/vpqwr89d1p7.fsf%40bauges.imag.fr
In-Reply-To: <1327881699-25461-1-git-send-email-felipe.contreras@gmail.com>

```
Felipe Contreras <felipe.contreras@gmail.com> writes:

> +ZSH_VERSION='' . /usr/share/git/completion/git-completion.bash

Probably stating the obvious, but this path shouldn't be hardcoded.

Something along the lines of

ZSH_VERSION='' . $(dirname ${funcsourcetrace[1]%:*})/git-completion.bash

should do it (mostly untested, and written by a non-ZSH expert).

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

```

## Felipe Contreras, 2012-01-30 10:59

Subject: Re: [PATCH] completion: add new zsh completion
Message-ID: <CAMP44s3QeZuXrR=UE4qvDadu66Cmi-txmSps8Ow24om27URxOg@mail.gmail.com>
URL: https://gitlist.dev/e/CAMP44s3QeZuXrR%3DUE4qvDadu66Cmi-txmSps8Ow24om27URxOg%40mail.gmail.com
In-Reply-To: <vpqwr89d1p7.fsf@bauges.imag.fr>

```
On Mon, Jan 30, 2012 at 10:39 AM, Matthieu Moy
<Matthieu.Moy@grenoble-inp.fr> wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
>
>> +ZSH_VERSION='' . /usr/share/git/completion/git-completion.bash
>
> Probably stating the obvious, but this path shouldn't be hardcoded.
>
> Something along the lines of
>
> ZSH_VERSION='' . $(dirname ${funcsourcetrace[1]%:*})/git-completion.bash
>
> should do it (mostly untested, and written by a non-ZSH expert).

Yes, it's hard-coded, because there's no way to know where is this
file. In my case, it's on ~/.git-completion.sh, and this one that I am
proposing sits in ~/.zsh/completion/_zsh, so your proposal breaks
things completely for me.

I will think about it, but I think for now, users of this script
should set that manually--if for some reason they don't want to use
the default.

Maybe we should use zstyle so they can configure it on their .zshrc?

-- 
Felipe Contreras

```

## Johannes Sixt, 2012-01-30 11:11

Subject: Re: [PATCH] completion: add new zsh completion
Message-ID: <4F267AC9.1080407@viscovery.net>
URL: https://gitlist.dev/e/4F267AC9.1080407%40viscovery.net
In-Reply-To: <vpqwr89d1p7.fsf@bauges.imag.fr>

```
Am 1/30/2012 9:39, schrieb Matthieu Moy:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
>> +ZSH_VERSION='' . /usr/share/git/completion/git-completion.bash
> 
> Probably stating the obvious, but this path shouldn't be hardcoded.
> 
> Something along the lines of
> 
> ZSH_VERSION='' . $(dirname ${funcsourcetrace[1]%:*})/git-completion.bash
> 
> should do it (mostly untested, and written by a non-ZSH expert).

Moreover, if zsh is POSIX compliant, the value of ZSH_VERSION will be an
empty string after this statement. That may or (more likely) may not be
what you want.

-- Hannes

```

## Felipe Contreras, 2012-01-30 11:28

Subject: Re: [PATCH] completion: add new zsh completion
Message-ID: <CAMP44s2MmqEeyvztk8_3q9Ms_-su0D12GYD_LLWCKPAmb2ZKXg@mail.gmail.com>
URL: https://gitlist.dev/e/CAMP44s2MmqEeyvztk8_3q9Ms_-su0D12GYD_LLWCKPAmb2ZKXg%40mail.gmail.com
In-Reply-To: <CAMP44s3QeZuXrR=UE4qvDadu66Cmi-txmSps8Ow24om27URxOg@mail.gmail.com>

```
On Mon, Jan 30, 2012 at 12:59 PM, Felipe Contreras
<felipe.contreras@gmail.com> wrote:
> On Mon, Jan 30, 2012 at 10:39 AM, Matthieu Moy
> <Matthieu.Moy@grenoble-inp.fr> wrote:
>> Felipe Contreras <felipe.contreras@gmail.com> writes:
>>
>>> +ZSH_VERSION='' . /usr/share/git/completion/git-completion.bash
>>
>> Probably stating the obvious, but this path shouldn't be hardcoded.
>>
>> Something along the lines of
>>
>> ZSH_VERSION='' . $(dirname ${funcsourcetrace[1]%:*})/git-completion.bash
>>
>> should do it (mostly untested, and written by a non-ZSH expert).
>
> Yes, it's hard-coded, because there's no way to know where is this
> file. In my case, it's on ~/.git-completion.sh, and this one that I am
> proposing sits in ~/.zsh/completion/_zsh, so your proposal breaks
> things completely for me.
>
> I will think about it, but I think for now, users of this script
> should set that manually--if for some reason they don't want to use
> the default.
>
> Maybe we should use zstyle so they can configure it on their .zshrc?

This seems to do the trick:

zstyle -s ":completion:$curcontext:" script script
test -z "$script" && script="$(dirname
${funcsourcetrace[1]%:*})"/git-completion.bash
ZSH_VERSION='' . "$script"

.zshrc:
zstyle ':completion:*:*:git:*' script ~/.git-completion.sh

-- 
Felipe Contreras

```

## Felipe Contreras, 2012-01-30 11:32

Subject: Re: [PATCH] completion: add new zsh completion
Message-ID: <CAMP44s2B_WLmGryUv9Fitak67nWhp8Gpw3Ac-dApKB4KjYv1fQ@mail.gmail.com>
URL: https://gitlist.dev/e/CAMP44s2B_WLmGryUv9Fitak67nWhp8Gpw3Ac-dApKB4KjYv1fQ%40mail.gmail.com
In-Reply-To: <4F267AC9.1080407@viscovery.net>

```
On Mon, Jan 30, 2012 at 1:11 PM, Johannes Sixt <j.sixt@viscovery.net> wrote:
> Am 1/30/2012 9:39, schrieb Matthieu Moy:
>> Felipe Contreras <felipe.contreras@gmail.com> writes:
>>
>>> +ZSH_VERSION='' . /usr/share/git/completion/git-completion.bash
>>
>> Probably stating the obvious, but this path shouldn't be hardcoded.
>>
>> Something along the lines of
>>
>> ZSH_VERSION='' . $(dirname ${funcsourcetrace[1]%:*})/git-completion.bash
>>
>> should do it (mostly untested, and written by a non-ZSH expert).
>
> Moreover, if zsh is POSIX compliant, the value of ZSH_VERSION will be an
> empty string after this statement. That may or (more likely) may not be
> what you want.

It's not, only inside that script. Same in bash.

And that's exactly what I want... I wan the git-completion.bash to
avoid any zsh hacks and workarounds.

Cheers.

-- 
Felipe Contreras

```

## Junio C Hamano, 2012-01-30 18:52

Subject: Re: [PATCH] completion: add new zsh completion
Message-ID: <7vy5spauqh.fsf@alter.siamese.dyndns.org>
URL: https://gitlist.dev/e/7vy5spauqh.fsf%40alter.siamese.dyndns.org
In-Reply-To: <4F267AC9.1080407@viscovery.net>

```
Johannes Sixt <j.sixt@viscovery.net> writes:

>> Something along the lines of
>> 
>> ZSH_VERSION='' . $(dirname ${funcsourcetrace[1]%:*})/git-completion.bash
>> 
>> should do it (mostly untested, and written by a non-ZSH expert).
>
> Moreover, if zsh is POSIX compliant, the value of ZSH_VERSION will be an
> empty string after this statement. That may or (more likely) may not be
> what you want.

As this split-file is about only zsh completion, it can be as non-POSIX as
it wants, and it appears that zsh is not striving to be POSIX compliant,
judging from Felipe's other messages.

Whatever works for zsh is just fine.

```
