git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv2] completion: make compatible with zsh
@ 2010-08-27  2:45 Mark Lodato
  2010-08-28 10:43 ` Ævar Arnfjörð Bjarmason
  2010-08-30 14:19 ` SZEDER Gábor
  0 siblings, 2 replies; 5+ messages in thread
From: Mark Lodato @ 2010-08-27  2:45 UTC (permalink / raw)
  To: Shawn O. Pearce
  Cc: git, avarab, Jonathan Nieder, Andrew Sayers, SZEDER Gábor

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>
---

Those on the CC list either responded to the original patch or are the authors
of the lines affected by this patch:
    - Andrew wrote __git_ps1_show_upstream().
    - SZEDER wrote the part using 'declare -F'.

 contrib/completion/git-completion.bash |   50 +++++++++++++++++++++++++++++--
 1 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 6756990..6a7aae6 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -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 [[ -z $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
-- 
1.7.2.2

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCHv2] completion: make compatible with zsh
  2010-08-27  2:45 [PATCHv2] completion: make compatible with zsh Mark Lodato
@ 2010-08-28 10:43 ` Ævar Arnfjörð Bjarmason
  2010-08-30 14:19 ` SZEDER Gábor
  1 sibling, 0 replies; 5+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2010-08-28 10:43 UTC (permalink / raw)
  To: Mark Lodato
  Cc: Shawn O. Pearce, git, Jonathan Nieder, Andrew Sayers,
	SZEDER Gábor

On Fri, Aug 27, 2010 at 02:45, Mark Lodato <lodatom@gmail.com> wrote:
> Modify git-completion.bash so that it also works with zsh when using
> bashcompinit.  In particular:

FWIW:

Reviewed-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCHv2] completion: make compatible with zsh
  2010-08-27  2:45 [PATCHv2] completion: make compatible with zsh Mark Lodato
  2010-08-28 10:43 ` Ævar Arnfjörð Bjarmason
@ 2010-08-30 14:19 ` SZEDER Gábor
  2010-08-31  0:55   ` Mark Lodato
  1 sibling, 1 reply; 5+ messages in thread
From: SZEDER Gábor @ 2010-08-30 14:19 UTC (permalink / raw)
  To: Mark Lodato; +Cc: Shawn O. Pearce, git, avarab, Jonathan Nieder, Andrew Sayers

Hi,


On Thu, Aug 26, 2010 at 10:45:56PM -0400, Mark Lodato wrote:
> 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.

> @@ -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
>  }

I chose -F back then because it does not print the definition of the
completion function, so there is less stuff to throw away immediately.
However, the run-time difference seems to be barely measureable (i.e.
'time declare -f _git_config >/dev/null' vs. 'declare -F _git_config
 >/dev/null' sometimes shows 0.001s difference), so I'm fine with this
change.


> @@ -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 [[ -z $ZSH_VERSION ]]; then

-z?  I think you wanted to use -n here, like at the other places.

Nit: why "if [[ ... ]]"?  FWIW "if [ ... ]" would be enough.

> +	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
> -- 
> 1.7.2.2
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCHv2] completion: make compatible with zsh
  2010-08-30 14:19 ` SZEDER Gábor
@ 2010-08-31  0:55   ` Mark Lodato
  2010-08-31  7:52     ` Peter Kjellerstedt
  0 siblings, 1 reply; 5+ messages in thread
From: Mark Lodato @ 2010-08-31  0:55 UTC (permalink / raw)
  To: SZEDER Gábor
  Cc: Shawn O. Pearce, git, avarab, Jonathan Nieder, Andrew Sayers

2010/8/30 SZEDER Gábor <szeder@ira.uka.de>
> On Thu, Aug 26, 2010 at 10:45:56PM -0400, Mark Lodato wrote:
> > @@ -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 [[ -z $ZSH_VERSION ]]; then
>
> -z?  I think you wanted to use -n here, like at the other places.

Oh, yes, sorry.  This was a mistake.  Thanks for catching it.


> Nit: why "if [[ ... ]]"?  FWIW "if [ ... ]" would be enough.

Because you don't need to quote variables with [[ ... ]] --- e.g. [
$lines = 0 ] fails, though in this case this feature does not matter
--- and because [[ ... ]] is faster.

Bash 4.1.5:
> time (for (( i = 0; i < 200000; i++ )); do [ -z $foo ]; done)
real    0m3.430s
user    0m3.240s
sys     0m0.180s
> time (for (( i = 0; i < 200000; i++ )); do [[ -z $foo ]]; done)
real    0m2.219s
user    0m2.090s
sys     0m0.100s

Zsh 4.3.10:
> time (for (( i = 0; i < 2000000; i++ )); do [ -z $foo ]; done)
(; for ((i = 0; i < 2000000; i++ )) do; [ -z $foo ]; done; )  13.56s
user 1.64s system 99% cpu 15.327 total
> time (for (( i = 0; i < 2000000; i++ )); do [[ -z $foo ]]; done)
(; for ((i = 0; i < 2000000; i++ )) do; [[ -z $foo ]]; done; )  4.62s
user 0.01s system 99% cpu 4.644 total

Is there a reason to prefer [ ... ] ?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCHv2] completion: make compatible with zsh
  2010-08-31  0:55   ` Mark Lodato
@ 2010-08-31  7:52     ` Peter Kjellerstedt
  0 siblings, 0 replies; 5+ messages in thread
From: Peter Kjellerstedt @ 2010-08-31  7:52 UTC (permalink / raw)
  To: Mark Lodato, SZEDER Gábor
  Cc: Shawn O. Pearce, git@vger.kernel.org, avarab@gmail.com,
	Jonathan Nieder, Andrew Sayers

> -----Original Message-----
> From: git-owner@vger.kernel.org [mailto:git-owner@vger.kernel.org] On
> Behalf Of Mark Lodato
> Sent: den 31 augusti 2010 02:56
> To: SZEDER Gábor
> Cc: Shawn O. Pearce; git@vger.kernel.org; avarab@gmail.com; Jonathan
> Nieder; Andrew Sayers
> Subject: Re: [PATCHv2] completion: make compatible with zsh
> 
> 2010/8/30 SZEDER Gábor <szeder@ira.uka.de>
> > On Thu, Aug 26, 2010 at 10:45:56PM -0400, Mark Lodato wrote:
> > > @@ -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 [[ -z $ZSH_VERSION ]]; then
> >
> > -z?  I think you wanted to use -n here, like at the other places.
> 
> Oh, yes, sorry.  This was a mistake.  Thanks for catching it.
> 
> 
> > Nit: why "if [[ ... ]]"?  FWIW "if [ ... ]" would be enough.
> 
> Because you don't need to quote variables with [[ ... ]] --- e.g. [
> $lines = 0 ] fails, though in this case this feature does not matter
> --- and because [[ ... ]] is faster.
> 
> Bash 4.1.5:
> > time (for (( i = 0; i < 200000; i++ )); do [ -z $foo ]; done)
> real    0m3.430s
> user    0m3.240s
> sys     0m0.180s
> > time (for (( i = 0; i < 200000; i++ )); do [[ -z $foo ]]; done)
> real    0m2.219s
> user    0m2.090s
> sys     0m0.100s
> 
> Zsh 4.3.10:
> > time (for (( i = 0; i < 2000000; i++ )); do [ -z $foo ]; done)
> (; for ((i = 0; i < 2000000; i++ )) do; [ -z $foo ]; done; )  13.56s
> user 1.64s system 99% cpu 15.327 total
> > time (for (( i = 0; i < 2000000; i++ )); do [[ -z $foo ]]; done)
> (; for ((i = 0; i < 2000000; i++ )) do; [[ -z $foo ]]; done; )  4.62s
> user 0.01s system 99% cpu 4.644 total
> 
> Is there a reason to prefer [ ... ] ?

The [ command is defined by POSIX, while [[ is an extension to the 
shell language implemented by bash (and zsh). Thus the [[ construct 
would fail on a stricter POSIX implementation of the shell language, 
e.g., as implemented by dash. Thus to be POSIX compliant (which is
required for shell scripts installed by a multi system supporting 
application like git), the [[ construct cannot be used. 

Of course, this does not really apply to a script explicitly written 
for bash, but that is the common reason to prefer [ over [[ in shell 
scripts.

//Peter


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-08-31  7:56 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-08-27  2:45 [PATCHv2] completion: make compatible with zsh Mark Lodato
2010-08-28 10:43 ` Ævar Arnfjörð Bjarmason
2010-08-30 14:19 ` SZEDER Gábor
2010-08-31  0:55   ` Mark Lodato
2010-08-31  7:52     ` Peter Kjellerstedt

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).