Subject: Re: [PATCH] enable number argument for transpose-words
From: Peter Stephenson <[email-masked]>
To: [email-masked]
Date: Mon, 15 Aug 2016 09:39:47 +0100
List-Id: Zsh Workers List <zsh-workers.zsh.org>

On Mon, 15 Aug 2016 10:22:50 +0800
Han Pingtian <[email-masked]> wrote:
> > diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
> > index eaca1b3..aa219dc 100644
> > --- a/Doc/Zsh/zle.yo
> > +++ b/Doc/Zsh/zle.yo
> > @@ -1948,6 +1948,12 @@ to the left.
> >  tindex(transpose-words)
> >  item(tt(transpose-words) (tt(ESC-T ESC-t)) (unbound) (unbound))(
> >  Exchange the current word with the one before it.
> > +
> > +With a positive numeric argument em(N), the word before the cursor is
> > +transposed with the following em(N) words.
> > +
> > +With a negative numeric argument em(-N), the word after the cursor
> > +is transposed with the preceding em(N) words.
> >  )
> >  tindex(vi-unindent)
> >  item(tt(vi-unindent) (unbound) (tt(<)) (unbound))(
> Thanks. But both positive and negative numeric argument would transpose
> current word with preceding N/-N word. The negative argument only make
> cursor doesn't change its position after the transpostion.

Ah, I had the key bound as

zle -N transpose-words-between transpose-words-about-point-match
bindkey '\et' transpose-words-between

with the following function (there are lots of different possible
behaviours in this case).

I'll find a form of words for the new standard behaviour.

pws

# Transpose words, matching the words using match-words-by-style, q.v.
# The group of word characters preceeding the cursor (not necessarily
# immediately) are transposed with the group of word characters following
# the cursor (again, not necessarily immediately).
#
# Note the style skip-chars, used in the context of the current widget.
# This gives a number of character starting from the cursor position
# which are never considered part of a word and hence are always left
# alone.  The default is 0 and typically the only useful alternative
# is one.  This would have the effect that `fooXbar' with the cursor
# on X would be turned into `barXfoo' with the cursor still on the X,
# regardless of what the character X is.

autoload match-words-by-style

local curcontext=":zle:$WIDGET" skip
local -a matched_words
integer count=${NUMERIC:-1} neg

(( count < 0 )) && (( count = -count, neg = 1 ))

while (( count-- > 0 )); do
    match-words-by-style

    [[ -z "$matched_words[2]$matched_words[5]" ]] && return 1

    if (( !${NUMERIC:-0} )); then
	# No prefix, don't advance cursor.
	LBUFFER="$matched_words[1]$matched_words[5]$matched_words[3]"
	RBUFFER="$matched_words[4]$matched_words[2]${(j..)matched_words[6,7]}"
    elif (( neg )); then
	LBUFFER="$matched_words[1]"
	RBUFFER="$matched_words[5]${(j..)matched_words[3,4]}\
$matched_words[2]${(j..)matched_words[6,7]}"
    else
	LBUFFER="$matched_words[1]$matched_words[5]${(j..)matched_words[3,4]}\
$matched_words[2]"
	RBUFFER="${(j..)matched_words[6,7]}"
    fi

done

return 0