git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH v2] completion: add new zsh completion
@ 2012-01-30 17:40 Felipe Contreras
  0 siblings, 0 replies; only message in thread
From: Felipe Contreras @ 2012-01-30 17:40 UTC (permalink / raw)
  To: git; +Cc: Felipe Contreras

From: Felipe Contreras <felipe.contreras@gmail.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>
---

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

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2012-01-30 17:40 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-30 17:40 [PATCH v2] completion: add new zsh completion Felipe Contreras

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).