zsh-users
 help / color / mirror / code / Atom feed
* Word-forward/word-backward as in bash / emacs
@ 2012-06-03 20:28 Konstantine Rybnikov
  2012-06-03 21:36 ` Peter Stephenson
  0 siblings, 1 reply; 4+ messages in thread
From: Konstantine Rybnikov @ 2012-06-03 20:28 UTC (permalink / raw)
  To: zsh-users

Hi!

I've tried to use zsh several times, but there was always one thing that 
bugged me every time -- it's word-forward/word-backward inconsistency 
with bash, emacs or other several programs.

Here, I asked my question at stackoverflow.com 
http://stackoverflow.com/questions/10847255/how-to-make-zsh-forward-word-behaviour-same-as-in-bash-emacs

Only answer I got is to do "select-word-style bash", which is absolutely 
not the same as bash (I also provided an example there that explains "why").

Hope to get an answer here. Thanks!


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

* Re: Word-forward/word-backward as in bash / emacs
  2012-06-03 20:28 Word-forward/word-backward as in bash / emacs Konstantine Rybnikov
@ 2012-06-03 21:36 ` Peter Stephenson
  2012-06-03 22:43   ` Konstantine Rybnikov
  0 siblings, 1 reply; 4+ messages in thread
From: Peter Stephenson @ 2012-06-03 21:36 UTC (permalink / raw)
  To: zsh-users

On Sun, 03 Jun 2012 23:28:03 +0300
Konstantine Rybnikov <k-bx@k-bx.com> wrote:
> Only answer I got is to do "select-word-style bash", which is absolutely 
> not the same as bash (I also provided an example there that explains "why").

So, with "select-word-style bash" that forward-word thing is the only
difference, right?  It seemed to be when I tried your example.

I actually noted forward-word was a bit funny when I wrote the function
forward-word-match that implements it when you uses select-word-style.
See if this does the trick --- it patches the function forward-word-match
which will be installed in your $fpath.

I've made the old behaviour a separate (non-default) option for the sake
of this, but if this is what's needed we probably need to think a bit
more about when it should apply.  The original behaviour works better
with zsh's normal set up because then more characters are considered
part of a word, so skipping non-word-characters at the start is less
likely to have side effects.

One possibility would be to reverse the sense of the option (to
skip-whitespace-first), but to set it to "true" from select word-style
if it's not explicitly set and the new style is "bash".  That keeps
compatibility in both cases.  However, there are other ways of doing it.

(I also standardised the indentation while I was there, so there's more
changed than is really necessary.)

Index: Functions/Zle/forward-word-match
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Zle/forward-word-match,v
retrieving revision 1.3
diff -p -u -r1.3 forward-word-match
--- Functions/Zle/forward-word-match	28 Jul 2010 13:33:59 -0000	1.3
+++ Functions/Zle/forward-word-match	3 Jun 2012 21:22:36 -0000
@@ -8,32 +8,35 @@ local -a matched_words
 integer count=${NUMERIC:-1}
 
 if (( count < 0 )); then
-    (( NUMERIC = -count ))
-    zle ${WIDGET/forward/backward}
-    return
+  (( NUMERIC = -count ))
+  zle ${WIDGET/forward/backward}
+  return
 fi
 
 while (( count-- )); do
-
-    match-words-by-style
-
+  match-words-by-style
+ 
+  if zstyle -t $curcontext skip-whitespace-last; then
     # For some reason forward-word doesn't work like the other word
     # commands; it skips whitespace only after any matched word
     # characters.
-
     if [[ -n $matched_words[4] ]]; then
-        # just skip the whitespace
-	word=$matched_words[4]
-    else
-        # skip the word and trailing whitespace
-	word=$matched_words[5]$matched_words[6]
-    fi
-
-    if [[ -n $word ]]; then
-	(( CURSOR += ${#word} ))
+      # just skip the whitespace
+      word=$matched_words[4]
     else
-	return 1
+      # skip the word and trailing whitespace
+      word=$matched_words[5]$matched_words[6]
     fi
+  else
+    # more standard behaviour: skip leading whitespace and the word.
+    word=$matched_words[4]$matched_words[5]
+  fi
+
+  if [[ -n $word ]]; then
+    (( CURSOR += ${#word} ))
+  else
+    return 1
+  fi
 done
 
 return 0


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

* Re: Word-forward/word-backward as in bash / emacs
  2012-06-03 21:36 ` Peter Stephenson
@ 2012-06-03 22:43   ` Konstantine Rybnikov
  2012-06-03 23:45     ` Peter Stephenson
  0 siblings, 1 reply; 4+ messages in thread
From: Konstantine Rybnikov @ 2012-06-03 22:43 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-users

06/04/2012 12:36 AM, Peter Stephenson написал:
> On Sun, 03 Jun 2012 23:28:03 +0300
> Konstantine Rybnikov<k-bx@k-bx.com>  wrote:
>> Only answer I got is to do "select-word-style bash", which is absolutely
>> not the same as bash (I also provided an example there that explains "why").
> So, with "select-word-style bash" that forward-word thing is the only
> difference, right?  It seemed to be when I tried your example.
>
> I actually noted forward-word was a bit funny when I wrote the function
> forward-word-match that implements it when you uses select-word-style.
> See if this does the trick --- it patches the function forward-word-match
> which will be installed in your $fpath.
>
> I've made the old behaviour a separate (non-default) option for the sake
> of this, but if this is what's needed we probably need to think a bit
> more about when it should apply.  The original behaviour works better
> with zsh's normal set up because then more characters are considered
> part of a word, so skipping non-word-characters at the start is less
> likely to have side effects.
>
> One possibility would be to reverse the sense of the option (to
> skip-whitespace-first), but to set it to "true" from select word-style
> if it's not explicitly set and the new style is "bash".  That keeps
> compatibility in both cases.  However, there are other ways of doing it.
>
> (I also standardised the indentation while I was there, so there's more
> changed than is really necessary.)
>
> Index: Functions/Zle/forward-word-match
> ===================================================================
> RCS file: /cvsroot/zsh/zsh/Functions/Zle/forward-word-match,v
> retrieving revision 1.3
> diff -p -u -r1.3 forward-word-match
> --- Functions/Zle/forward-word-match	28 Jul 2010 13:33:59 -0000	1.3
> +++ Functions/Zle/forward-word-match	3 Jun 2012 21:22:36 -0000
> @@ -8,32 +8,35 @@ local -a matched_words
>   integer count=${NUMERIC:-1}
>
>   if (( count<  0 )); then
> -    (( NUMERIC = -count ))
> -    zle ${WIDGET/forward/backward}
> -    return
> +  (( NUMERIC = -count ))
> +  zle ${WIDGET/forward/backward}
> +  return
>   fi
>
>   while (( count-- )); do
> -
> -    match-words-by-style
> -
> +  match-words-by-style
> +
> +  if zstyle -t $curcontext skip-whitespace-last; then
>       # For some reason forward-word doesn't work like the other word
>       # commands; it skips whitespace only after any matched word
>       # characters.
> -
>       if [[ -n $matched_words[4] ]]; then
> -        # just skip the whitespace
> -	word=$matched_words[4]
> -    else
> -        # skip the word and trailing whitespace
> -	word=$matched_words[5]$matched_words[6]
> -    fi
> -
> -    if [[ -n $word ]]; then
> -	(( CURSOR += ${#word} ))
> +      # just skip the whitespace
> +      word=$matched_words[4]
>       else
> -	return 1
> +      # skip the word and trailing whitespace
> +      word=$matched_words[5]$matched_words[6]
>       fi
> +  else
> +    # more standard behaviour: skip leading whitespace and the word.
> +    word=$matched_words[4]$matched_words[5]
> +  fi
> +
> +  if [[ -n $word ]]; then
> +    (( CURSOR += ${#word} ))
> +  else
> +    return 1
> +  fi
>   done
>
>   return 0
Ok, it looks like Moritz Bunkus updated he's answer with working 
implementation of forward-word-match. You're right, the only difference 
if forward-word things.

Just tried your patch -- yes, looks like it works as expected. Thanks!


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

* Re: Word-forward/word-backward as in bash / emacs
  2012-06-03 22:43   ` Konstantine Rybnikov
@ 2012-06-03 23:45     ` Peter Stephenson
  0 siblings, 0 replies; 4+ messages in thread
From: Peter Stephenson @ 2012-06-03 23:45 UTC (permalink / raw)
  To: zsh-users

On Mon, 04 Jun 2012 01:43:47 +0300
Konstantine Rybnikov <k-bx@k-bx.com> wrote:
> Just tried your patch -- yes, looks like it works as expected. Thanks!

Good, here's a more complete patch.

Rather than second-guess what the user wants with the style, which isn't
really how select-word-style works (it's designed to be explicit about
setting things up), this just sets the style differently for bash
compatibility, and the documentation notes you can override this by
setting it in a more specific context (for a style, a longer pattern is
considered more specific).

Index: Doc/Zsh/contrib.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/contrib.yo,v
retrieving revision 1.142
diff -p -u -r1.142 contrib.yo
--- Doc/Zsh/contrib.yo	8 May 2012 16:50:26 -0000	1.142
+++ Doc/Zsh/contrib.yo	3 Jun 2012 23:39:22 -0000
@@ -1734,6 +1734,16 @@ context is examined and if it contains t
 the cursor is considered, else the word after cursor is considered. Some
 examples are given below.
 
+The style tt(skip-whitespace-first) is only used with the
+tt(forward-word) widget.  If it is set to true, then tt(forward-word)
+skips any non-word-characters, followed by any non-word-characters:
+this is similar to the behaviour of other word-orientated widgets,
+and also that used by other editors, however it differs from the
+standard zsh behaviour.  When using tt(select-word-style) the widget
+is set in the context tt(:zle:*) to tt(true) if the word style is
+tt(bash) and tt(false) otherwise.  It may be overridden by setting it in
+the more specific context tt(:zle:forward-word*).
+
 Here are some examples of use of the styles, actually taken from the
 simplified interface in tt(select-word-style):
 
Index: Functions/Zle/forward-word-match
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Zle/forward-word-match,v
retrieving revision 1.3
diff -p -u -r1.3 forward-word-match
--- Functions/Zle/forward-word-match	28 Jul 2010 13:33:59 -0000	1.3
+++ Functions/Zle/forward-word-match	3 Jun 2012 23:39:22 -0000
@@ -8,32 +8,36 @@ local -a matched_words
 integer count=${NUMERIC:-1}
 
 if (( count < 0 )); then
-    (( NUMERIC = -count ))
-    zle ${WIDGET/forward/backward}
-    return
+  (( NUMERIC = -count ))
+  zle ${WIDGET/forward/backward}
+  return
 fi
 
 while (( count-- )); do
-
-    match-words-by-style
-
+  match-words-by-style
+ 
+  if zstyle -t $curcontext skip-whitespace-first; then
+    # Standard non-zsh behaviour: skip leading whitespace and the word.
+    word=$matched_words[4]$matched_words[5]
+  else
+    # Traditional zsh behaviour.
     # For some reason forward-word doesn't work like the other word
     # commands; it skips whitespace only after any matched word
     # characters.
-
     if [[ -n $matched_words[4] ]]; then
-        # just skip the whitespace
-	word=$matched_words[4]
+      # just skip the whitespace
+      word=$matched_words[4]
     else
-        # skip the word and trailing whitespace
-	word=$matched_words[5]$matched_words[6]
+      # skip the word and trailing whitespace
+      word=$matched_words[5]$matched_words[6]
     fi
+  fi
 
-    if [[ -n $word ]]; then
-	(( CURSOR += ${#word} ))
-    else
-	return 1
-    fi
+  if [[ -n $word ]]; then
+    (( CURSOR += ${#word} ))
+  else
+    return 1
+  fi
 done
 
 return 0
Index: Functions/Zle/select-word-style
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Zle/select-word-style,v
retrieving revision 1.4
diff -p -u -r1.4 select-word-style
--- Functions/Zle/select-word-style	28 Jul 2010 13:33:59 -0000	1.4
+++ Functions/Zle/select-word-style	3 Jun 2012 23:39:22 -0000
@@ -4,71 +4,75 @@ setopt extendedglob
 local -a word_functions
 
 word_functions=(backward-kill-word backward-word
-    capitalize-word down-case-word
-    forward-word kill-word
-    transpose-words up-case-word)
+  capitalize-word down-case-word
+  forward-word kill-word
+  transpose-words up-case-word)
 
 [[ -z $1 ]] && autoload -Uz read-from-minibuffer
 
-local REPLY detail f wordstyle
+local REPLY detail f wordstyle teststyle
 
 if ! zle -l $word_functions[1]; then
-    for f in $word_functions; do
-	autoload -Uz $f-match
-	zle -N $f $f-match
-    done
+  for f in $word_functions; do
+    autoload -Uz $f-match
+    zle -N $f $f-match
+  done
 fi
 
 
 while true; do
-
-    if [[ -n $WIDGET && -z $1 ]]; then
-	read-from-minibuffer -k1 "Word styles (hit return for more detail):
+  if [[ -n $WIDGET && -z $1 ]]; then
+    read-from-minibuffer -k1 "Word styles (hit return for more detail):
 (b)ash (n)ormal (s)hell (w)hitespace (d)efault (q)uit
 (B), (N), (S), (W) as above with subword matching
 ${detail}? " || return 1
-    else
-	REPLY=$1
-    fi
-
-    detail=
+  else
+    REPLY=$1
+  fi
+
+  detail=
+
+  case $REPLY in
+    ([bB]*)
+    # bash style
+    wordstyle=standard
+    zstyle ':zle:*' word-chars ''
+    zstyle ':zle:*' skip-whitespace-first true
+    ;;
+
+    ([nN]*)
+    # normal zsh style
+    wordstyle=standard
+    zstyle ':zle:*' word-chars "$WORDCHARS"
+    zstyle ':zle:*' skip-whitespace-first false
+    ;;
+
+    ([sS]*)
+    # shell command arguments or special tokens
+    wordstyle=shell
+    zstyle ':zle:*' skip-whitespace-first false
+    ;;
+
+    ([wW]*)
+    # whitespace-delimited
+    wordstyle=space
+    zstyle ':zle:*' skip-whitespace-first false
+    ;;
+
+    (d*)
+    # default: could also return widgets to builtins here
+    wordstyle=
+    zstyle -d ':zle:*' word-chars
+    zstyle -d ':zle:*' skip-whitespace-first
+    ;;
+
+    (q*)
+    # quit without setting
+    return 1
+    ;;
 
-    case $REPLY in
-	([bB]*)
-	# bash style
-	wordstyle=standard
-	zstyle ':zle:*' word-chars ''
-	;;
-
-	([nN]*)
-	# normal zsh style
-	wordstyle=standard
-	zstyle ':zle:*' word-chars "$WORDCHARS"
-	;;
-
-	([sS]*)
-	# shell command arguments or special tokens
-	wordstyle=shell
-	;;
-
-	([wW]*)
-	# whitespace-delimited
-	wordstyle=space
-	;;
-
-	(d*)
-	# default: could also return widgets to builtins here
-	wordstyle=
-	zstyle -d ':zle:*' word-chars
-	;;
-
-	(q*)
-	# quit without setting
-	return 1
-	;;
-
-	(*)
-	detail="\
+    (*)
+    detail="\
 (b)ash:       Word characters are alphanumerics only
 (n)ormal:     Word characters are alphanumerics plus \$WORDCHARS
 (s)hell:      Words are command arguments using shell syntax
@@ -76,21 +80,21 @@ ${detail}? " || return 1
 (d)efault:    Use default, no special handling (usually same as \`n')
 (q)uit:       Quit without setting a new style
 "
-	if [[ -z $WIDGET || -n $1 ]]; then
-	    print "Usage: $0 word-style
+    if [[ -z $WIDGET || -n $1 ]]; then
+      print "Usage: $0 word-style
 where word-style is one of the characters in parentheses:
 $detail" >&2
-	    return 1
-	fi
-	continue
-	;;
-    esac
-
-    if [[ -n $wordstyle ]]; then
-      if [[ $REPLY = [[:upper:]]* ]]; then
-	wordstyle+=-subword
-      fi
-      zstyle ':zle:*' word-style $wordstyle
+      return 1
+    fi
+    continue
+    ;;
+  esac
+
+  if [[ -n $wordstyle ]]; then
+    if [[ $REPLY = [[:upper:]]* ]]; then
+      wordstyle+=-subword
     fi
-    return
+    zstyle ':zle:*' word-style $wordstyle
+  fi
+  return
 done

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


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

end of thread, other threads:[~2012-06-03 23:51 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-03 20:28 Word-forward/word-backward as in bash / emacs Konstantine Rybnikov
2012-06-03 21:36 ` Peter Stephenson
2012-06-03 22:43   ` Konstantine Rybnikov
2012-06-03 23:45     ` Peter Stephenson

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

	https://git.vuxu.org/mirror/zsh/

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