Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: bug with camel case and delete-whole-word-match function
On Tue, 26 Jul 2016 20:22:05 +0200
Oliver Kiddle <okiddle@xxxxxxxxxxx> wrote:
> It is the output of the following two:
> mwbs-test ' ' ' word'
> mwbs-test 'word ' ' '
>
> In the latter case, this is:
>
> start: ''
> wd-before-c: 'word'
> ws-before-c: ' '
> ws-after-c: ''
> wd-after-c: ''
> ws-after-w: ''
> end: ' '
>
> So the spaces go in end rather than ws-after-c.
OK, we need to check that there actually is a word after the cursor, as
we should also do before setting is-word-start.
> > +If the option -A is given to tt(match-words-by-style), then
>
> Given that it is the calling functions' responsibility to declare
> matched_words, it could just use ${(t)matched_words} but I'm not
> especially bothered.
Yes, that would probably be neater.
pws
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index c3dec34..8db7395 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -2132,6 +2132,17 @@ non-word characters following that word (7) the remainder of the line. Any
of the elements may be an empty string; the calling function should test
for this to decide whether it can perform its function.
+If the variable tt(matched_words) is defined by the caller to
+tt(match-words-by-style) as an associative array (tt(local -A
+matched_words)), then the seven values given above should be retrieved
+from it as elements named tt(start), tt(word-before-cursor),
+tt(ws-before-cursor), tt(ws-after-cursor), tt(word-after-cursor),
+tt(ws-after-word), and tt(end). In addition the element
+tt(is-word-start) is 1 if the cursor is on the start of a word or
+subword, or on white space before it (the cases can be distinguished by
+testing the tt(ws-after-cursor) element) and 0 otherwise. This form is
+recommended for future compatibility.
+
It is possible to pass options with arguments to tt(match-words-by-style)
to override the use of styles. The options are:
startsitem()
diff --git a/Functions/Zle/delete-whole-word-match b/Functions/Zle/delete-whole-word-match
index aece860..3d52dd3 100644
--- a/Functions/Zle/delete-whole-word-match
+++ b/Functions/Zle/delete-whole-word-match
@@ -12,30 +12,29 @@ emulate -L zsh
setopt extendedglob
local curcontext=:zle:$WIDGET
-local -a matched_words
+local -A matched_words
# Start and end of range of characters to remove.
integer pos1 pos2
autoload -Uz match-words-by-style
match-words-by-style
-if [[ -n "${matched_words[3]}" ]]; then
- # There's whitespace before the cursor, so the word we are deleting
- # starts at the cursor position.
+if (( ${matched_words[is-word-start]} )); then
+ # The word we are deleting starts at the cursor position.
pos1=$CURSOR
else
- # No whitespace before us, so delete any wordcharacters there.
- pos1="${#matched_words[1]}"
+ # Not, so delete any wordcharacters before, too
+ pos1="${#matched_words[start]}"
fi
-if [[ -n "${matched_words[4]}" ]]; then
+if [[ -n "${matched_words[ws-after-cursor]}" ]]; then
# There's whitespace at the cursor position, so only delete
# up to the cursor position.
(( pos2 = CURSOR + 1 ))
else
# No whitespace at the cursor position, so delete the
# current character and any following wordcharacters.
- (( pos2 = CURSOR + ${#matched_words[5]} + 1 ))
+ (( pos2 = CURSOR + ${#matched_words[word-after-cursor]} + 1 ))
fi
# Move the cursor then delete the block in one go for the
diff --git a/Functions/Zle/match-words-by-style b/Functions/Zle/match-words-by-style
index 6cdec75..fc59c27 100644
--- a/Functions/Zle/match-words-by-style
+++ b/Functions/Zle/match-words-by-style
@@ -5,8 +5,16 @@
# <whitespace-after-cursor> <word-after-cursor> <whitespace-after-word>
# <stuff-at-end>
# where the cursor position is always after the third item and `after'
-# is to be interpreted as `after or on'. Some
-# of the array elements will be empty; this depends on the style.
+# is to be interpreted as `after or on'.
+#
+# matched_words may be an associative array, in which case the
+# values above are now given by the elements named start, word-before-cursor,
+# ws-before-cursor, ws-after-cursor, word-after-cursor, ws-after-word,
+# end. In addition, the element is-word-start is 1 if the cursor
+# is on the start of a word; this is non-trivial in the case of subword
+# (camel case) matching as there may be no white space to test.
+#
+# Some of the array elements will be empty; this depends on the style.
# For example
# foo bar rod stick
# ^
@@ -224,11 +232,18 @@ charskip=${(l:skip::?:)}
eval pat2='${RBUFFER##(#b)('${charskip}${spacepat}')('\
${wordpat2}')('${spacepat}')}'
+if [[ -n $match[2] ]]; then
+ ws2=$match[1]
+ word2=$match[2]
+ ws3=$match[3]
+else
+ # No more words, so anything left is white space after cursor.
+ ws2=$RBUFFER
+ pat2=
+fi
-ws2=$match[1]
-word2=$match[2]
-ws3=$match[3]
-
+integer wordstart
+[[ ( -n $ws1 || -n $ws2 ) && -n $word2 ]] && wordstart=1
if [[ $wordstyle = *subword* ]]; then
# Do we have a group of upper case characters at the start
# of word2 (that don't form the entire word)?
@@ -249,6 +264,7 @@ if [[ $wordstyle = *subword* ]]; then
# if it wants.
elif [[ $word2 = (#b)(?[^${~subwordrange}]##)[${~subwordrange}]* ]]; then
(( epos = ${#match[1]} ))
+ (( wordstart = 1 ))
else
(( epos = 0 ))
fi
@@ -262,4 +278,19 @@ if [[ $wordstyle = *subword* ]]; then
fi
fi
-matched_words=("$pat1" "$word1" "$ws1" "$ws2" "$word2" "$ws3" "$pat2")
+# matched_words should be local to caller.
+# Just fix type here.
+if [[ ${(t)matched_words} = *association* ]]; then
+ matched_words=(
+ start "$pat1"
+ word-before-cursor "$word1"
+ ws-before-cursor "$ws1"
+ ws-after-cursor "$ws2"
+ word-after-cursor "$word2"
+ ws-after-word "$ws3"
+ end "$pat2"
+ is-word-start $wordstart
+ )
+else
+ matched_words=("$pat1" "$word1" "$ws1" "$ws2" "$word2" "$ws3" "$pat2")
+fi
Messages sorted by:
Reverse Date,
Date,
Thread,
Author