From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1171 invoked by alias); 27 Jul 2016 08:54:31 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 38954 Received: (qmail 22860 invoked from network); 27 Jul 2016 08:54:31 -0000 X-Qmail-Scanner-Diagnostics: from mailout2.w1.samsung.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.99.2/21882. spamassassin: 3.4.1. Clear:RC:0(210.118.77.12):SA:0(-1.3/5.0):. Processed in 0.289191 secs); 27 Jul 2016 08:54:31 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=RP_MATCHES_RCVD autolearn=unavailable autolearn_force=no version=3.4.1 X-Envelope-From: p.stephenson@samsung.com X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: none (ns1.primenet.com.au: domain at samsung.com does not designate permitted sender hosts) X-AuditID: cbfec7f4-f796c6d000001486-a3-579876c0438a Date: Wed, 27 Jul 2016 09:54:21 +0100 From: Peter Stephenson To: zsh-workers@zsh.org Subject: Re: bug with camel case and delete-whole-word-match function Message-id: <20160727095421.5c919e22@pwslap01u.europe.root.pri> In-reply-to: <57127.1469557325@hydra.kiddle.eu> References: <588168129.3340906.1467709726474.JavaMail.yahoo.ref@mail.yahoo.com> <588168129.3340906.1467709726474.JavaMail.yahoo@mail.yahoo.com> <20160705111900.7e1599f0@pwslap01u.europe.root.pri> <5374.1469315162@hydra.kiddle.eu> <20160726145224.7910b718@pwslap01u.europe.root.pri> <57127.1469557325@hydra.kiddle.eu> Organization: Samsung Cambridge Solution Centre X-Mailer: Claws Mail 3.7.9 (GTK+ 2.22.0; i386-redhat-linux-gnu) MIME-version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7bit X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrELMWRmVeSWpSXmKPExsVy+t/xy7oHymaEG6zqkrY42PyQyYHRY9XB D0wBjFFcNimpOZllqUX6dglcGRv2bmcumGZQsfLsa7YGxi+qXYycHBICJhI3lh1mhbDFJC7c W8/WxcjFISSwlFFi5vwn7BDODCaJ5kmHGCGcc4wSbXsXskA4Zxklds1ezAjSzyKgKjFh5WR2 EJtNwFBi6qbZYHERAXGJs2vPs4DYwgKuEp1fj4Lt4xWwl7jctgyshlNAX2LHvANMEEOPMUl8 enmFGSTBD5S4+vcTE8SB9hIzr5xhhGgWlPgx+R7YUGYBLYnN25pYIWx5ic1r3oL1CgmoS9y4 u5t9AqPwLCQts5C0zELSsoCReRWjaGppckFxUnquoV5xYm5xaV66XnJ+7iZGSEh/2cG4+JjV IUYBDkYlHt4H26eHC7EmlhVX5h5ilOBgVhLhfVc0I1yINyWxsiq1KD++qDQntfgQozQHi5I4 79xd70OEBNITS1KzU1MLUotgskwcnFINjJ27fRyaevN/TV9y/0K2RPYS69iteXcmHZVoci2+ b8V5KyREZov93o77uY9PMbhqS2/+d5zHIHjFDxXxey+l4k6oBi7OWd3Pyrf7+9G78/giZc/+ Xrd6KjNnXqWHbG3gjoj+O3Wpx5qmWPEFBQonZzCl1iznfrJy6mpjxZf2Nt92Zq7MYJ+yTYml OCPRUIu5qDgRAP78SzdlAgAA On Tue, 26 Jul 2016 20:22:05 +0200 Oliver Kiddle 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 @@ # # # 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