git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Nieder <jrnieder@gmail.com>
To: Junio C Hamano <gitster@pobox.com>
Cc: "Felipe Contreras" <felipe.contreras@gmail.com>,
	git@vger.kernel.org, "Stefan Haller" <lists@haller-berlin.de>,
	"SZEDER Gábor" <szeder@ira.uka.de>,
	"Mark Lodato" <lodatom@gmail.com>
Subject: [RFC/PATCH] completion: avoid "words" as variable name for zsh portability
Date: Wed, 27 Apr 2011 01:40:34 -0500	[thread overview]
Message-ID: <20110427064033.GB4226@elie> (raw)
In-Reply-To: <7v62q0b8e0.fsf@alter.siamese.dyndns.org>

The "_get_comp_words_by_ref -n := words" command from the
bash_completion library reassembles a modified version of COMP_WORDS
with ':' and '=' no longer treated as word separators and stores it in
the ${words[@]} array.  Git's programmable tab completion script uses
this to abstract away the difference between bash v3's and bash v4's
definitions of COMP_WORDS (bash v3 used shell words, while bash v4
breaks at separator characters); see v1.7.4-rc0~11^2~2 (bash: get
--pretty=m<tab> completion to work with bash v4, 2010-12-02).

zsh has (or rather its completion functions have) another idea about
what ${words[@]} should contain: the array is prepopulated with the
words from the command it is completing.  For reasons that are not
well understood, when git-completion.bash reserves its own "words"
variable with "local words", the variable becomes empty and cannot be
changed from then on.  So the completion script neglects the arguments
it has seen, and words complete like git subcommand names.  For
example, typing "git log origi<TAB>" gives no completions because
there are no "git origi..." commands.

Work around this by using a different variable (comp_words) that is
not special to zsh.  So now commands that completed correctly before
v1.7.4-rc0~11^2~2 on zsh should be able to complete correctly again.

Reported-by: Stefan Haller <lists@haller-berlin.de>
Suggested-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
Junio C Hamano wrote:

> I'd love to share the enthusiasm, but find that "as we can see" needs a
> much more clarification.

Sorry, I got carried away (I am happy to see someone has made some
headway in investigating this old bug).  How about this?

There is still a "for unknown reasons" in the above explanation.

 contrib/completion/git-completion.bash |   68 ++++++++++++++++---------------
 1 files changed, 35 insertions(+), 33 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 9150ea6..ce6b3e4 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -447,8 +447,9 @@ _get_comp_words_by_ref ()
 		prev)
 			prev=${words_[$cword_-1]}
 			;;
-		words)
-			words=("${words_[@]}")
+		-w)
+			eval $2'=("${words_[@]}")'
+			shift
 			;;
 		cword)
 			cword=$cword_
@@ -468,8 +469,9 @@ _get_comp_words_by_ref ()
 		prev)
 			prev=${COMP_WORDS[COMP_CWORD-1]}
 			;;
-		words)
-			words=("${COMP_WORDS[@]}")
+		-w)
+			eval $2='("${COMP_WORDS[@]}")'
+			shift
 			;;
 		cword)
 			cword=$COMP_CWORD
@@ -739,12 +741,12 @@ __git_complete_revlist ()
 
 __git_complete_remote_or_refspec ()
 {
-	local cur words cword
-	_get_comp_words_by_ref -n =: cur words cword
-	local cmd="${words[1]}"
+	local cur comp_words cword
+	_get_comp_words_by_ref -n =: -w comp_words cur cword
+	local cmd="${comp_words[1]}"
 	local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
 	while [ $c -lt $cword ]; do
-		i="${words[c]}"
+		i="${comp_words[c]}"
 		case "$i" in
 		--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
 		--all)
@@ -991,10 +993,10 @@ __git_aliased_command ()
 # __git_find_on_cmdline requires 1 argument
 __git_find_on_cmdline ()
 {
-	local word subcommand c=1 words cword
-	_get_comp_words_by_ref -n =: words cword
+	local word subcommand c=1 comp_words cword
+	_get_comp_words_by_ref -n =: -w comp_words cword
 	while [ $c -lt $cword ]; do
-		word="${words[c]}"
+		word="${comp_words[c]}"
 		for subcommand in $1; do
 			if [ "$subcommand" = "$word" ]; then
 				echo "$subcommand"
@@ -1007,10 +1009,10 @@ __git_find_on_cmdline ()
 
 __git_has_doubledash ()
 {
-	local c=1 words cword
-	_get_comp_words_by_ref -n =: words cword
+	local c=1 comp_words cword
+	_get_comp_words_by_ref -n =: -w comp_words cword
 	while [ $c -lt $cword ]; do
-		if [ "--" = "${words[c]}" ]; then
+		if [ "--" = "${comp_words[c]}" ]; then
 			return 0
 		fi
 		c=$((++c))
@@ -1135,11 +1137,11 @@ _git_bisect ()
 
 _git_branch ()
 {
-	local i c=1 only_local_ref="n" has_r="n" cur words cword
+	local i c=1 only_local_ref="n" has_r="n" cur comp_words cword
 
-	_get_comp_words_by_ref -n =: cur words cword
+	_get_comp_words_by_ref -n =: -w comp_words cur cword
 	while [ $c -lt $cword ]; do
-		i="${words[c]}"
+		i="${comp_words[c]}"
 		case "$i" in
 		-d|-m)	only_local_ref="y" ;;
 		-r)	has_r="y" ;;
@@ -1167,9 +1169,9 @@ _git_branch ()
 
 _git_bundle ()
 {
-	local words cword
-	_get_comp_words_by_ref -n =: words cword
-	local cmd="${words[2]}"
+	local comp_words cword
+	_get_comp_words_by_ref -n =: -w comp_words cword
+	local cmd="${comp_words[2]}"
 	case "$cword" in
 	2)
 		__gitcomp "create list-heads verify unbundle"
@@ -1713,15 +1715,15 @@ _git_notes ()
 {
 	local subcommands='add append copy edit list prune remove show'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
-	local cur words cword
-	_get_comp_words_by_ref -n =: cur words cword
+	local cur comp_words cword
+	_get_comp_words_by_ref -n =: -w comp_words cur cword
 
 	case "$subcommand,$cur" in
 	,--*)
 		__gitcomp '--ref'
 		;;
 	,*)
-		case "${words[cword-1]}" in
+		case "${comp_words[cword-1]}" in
 		--ref)
 			__gitcomp "$(__git_refs)"
 			;;
@@ -1749,7 +1751,7 @@ _git_notes ()
 	prune,*)
 		;;
 	*)
-		case "${words[cword-1]}" in
+		case "${comp_words[cword-1]}" in
 		-m|-F)
 			;;
 		*)
@@ -1893,11 +1895,11 @@ _git_stage ()
 
 __git_config_get_set_variables ()
 {
-	local words cword
-	_get_comp_words_by_ref -n =: words cword
+	local comp_words cword
+	_get_comp_words_by_ref -n =: -w comp_words cword
 	local prevword word config_file= c=$cword
 	while [ $c -gt 1 ]; do
-		word="${words[c]}"
+		word="${comp_words[c]}"
 		case "$word" in
 		--global|--system|--file=*)
 			config_file="$word"
@@ -2665,10 +2667,10 @@ _git_svn ()
 _git_tag ()
 {
 	local i c=1 f=0
-	local words cword prev
-	_get_comp_words_by_ref -n =: words cword prev
+	local comp_words cword prev
+	_get_comp_words_by_ref -n =: -w comp_words cword prev
 	while [ $c -lt $cword ]; do
-		i="${words[c]}"
+		i="${comp_words[c]}"
 		case "$i" in
 		-d|-v)
 			__gitcomp "$(__git_tags)"
@@ -2712,10 +2714,10 @@ _git ()
 		setopt KSH_TYPESET
 	fi
 
-	local cur words cword
-	_get_comp_words_by_ref -n =: cur words cword
+	local cur comp_words cword
+	_get_comp_words_by_ref -n =: -w comp_words cur cword
 	while [ $c -lt $cword ]; do
-		i="${words[c]}"
+		i="${comp_words[c]}"
 		case "$i" in
 		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
 		--bare)      __git_dir="." ;;
-- 
1.7.5

  reply	other threads:[~2011-04-27  6:40 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-27  1:26 [PATCH] git-completion: fix zsh support Felipe Contreras
2011-04-27  1:35 ` Jonathan Nieder
2011-04-27  1:42   ` Felipe Contreras
2011-04-27  4:55   ` Junio C Hamano
2011-04-27  6:40     ` Jonathan Nieder [this message]
2011-04-27  8:42       ` [RFC/PATCH] completion: avoid "words" as variable name for zsh portability Felipe Contreras
2011-04-27  9:11         ` Jonathan Nieder
2011-04-27  9:49           ` Felipe Contreras
2011-04-27  9:59             ` John Szakmeister
2011-04-27 10:09             ` Felipe Contreras
2011-04-27 21:27               ` [PATCH] completion: move private shopt shim for zsh to __git_ namespace Jonathan Nieder
2011-04-27 22:48                 ` Felipe Contreras
2011-04-27 23:00                   ` Jonathan Nieder
2011-05-06  5:46                 ` Jonathan Nieder
2011-05-06  8:35                   ` Felipe Contreras
2011-05-08 10:48                   ` SZEDER Gábor
2011-04-28 16:01       ` [RFC/PATCH] completion: avoid "words" as variable name for zsh portability SZEDER Gábor
2011-04-28 16:01         ` [PATCH 1/3] bash: don't modify the $cur variable in completion functions SZEDER Gábor
2011-04-28 16:01           ` [PATCH 2/3] bash: remove unnecessary _get_comp_words_by_ref() invocations SZEDER Gábor
2011-04-28 16:01           ` [PATCH 3/3] bash: don't declare 'local words' to make zsh happy SZEDER Gábor
2011-05-03 17:53             ` Felipe Contreras
2011-04-28 20:24         ` [RFC/PATCH] completion: avoid "words" as variable name for zsh portability Felipe Contreras
2011-04-28 20:52           ` Junio C Hamano
2011-04-28 21:27             ` Felipe Contreras
2011-04-27  8:20     ` [PATCH] git-completion: fix zsh support Felipe Contreras
2011-04-27 16:56       ` Junio C Hamano
2011-04-27 17:17         ` Felipe Contreras
2011-04-27  2:21 ` Jonathan Nieder

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110427064033.GB4226@elie \
    --to=jrnieder@gmail.com \
    --cc=felipe.contreras@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=lists@haller-berlin.de \
    --cc=lodatom@gmail.com \
    --cc=szeder@ira.uka.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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 NNTP newsgroup(s).