From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29959 invoked by alias); 23 Jul 2016 23:12:03 -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: 38929 Received: (qmail 10431 invoked from network); 23 Jul 2016 23:12:03 -0000 X-Qmail-Scanner-Diagnostics: from nm31-vm8.bullet.mail.ir2.yahoo.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(212.82.97.95):SA:0(0.0/5.0):. Processed in 0.329115 secs); 23 Jul 2016 23:12:03 -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=0.0 required=5.0 tests=FREEMAIL_FROM,SPF_PASS, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.1 X-Envelope-From: okiddle@yahoo.co.uk X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at _spf.mail.yahoo.com designates 212.82.97.95 as permitted sender) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.co.uk; s=s2048; t=1469315162; bh=UTCfRThy6J3tqS3UzzinllMBM4YeT4jQA+LC1oeWwOU=; h=In-reply-to:From:References:To:Subject:Date:From:Subject; b=fm6KOSn/rem/dzGYwCsu57IJXQ4EewLhOrKQ+UgK2sB+LudjctptAzIWWK3MhmpmoSzf6KwgT3wRydGDMNEYzF5Jxz1YXpjFLH2UMADNxm4JuKuvtqeYQ2g1dt7oAB//aUrOkTe5/JswNhyyNnmD3AocD5K35mtuNMhcr361FqPCFljw6vC94dngPaZzbbUgi5WCR7KA63a/6BSvHyGX6mpdFmiBekBkPkjjIeeue7ZeSoymHhWCzOrCeiq+C2U283nYpLa1TNAQYtg48stTDJaXAHUvDXREDzRRTVBUlOAdh+U2mPuW3NdK8dVZo/CL8iCTwFfSiWsSGtTzNFaMXw== X-Yahoo-Newman-Id: 757953.40433.bm@smtp117.mail.ir2.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: ZOkUI1sVM1ksC37eqb1ePpBvT7.0pxD86IQggLjyc9ihF6S wUqF0BqM32YqtLeFattGdZhqUFlvyqNA6tHCdUWGzqcgV5hrrv_dQJIx95dU 1AlX_PQ8fqjOQslvrdxJKkxEosPyhZmrYQpDLXsxQ4ypzaWnnaDbL915vrXQ zF4sC5Cp7lZHwlQgDUIhilqZP68rwAuW_s7z1VC5WYk.Cn45L_hA3F.b3P6. 3.VbhvWQyZ_8HmPotxtaFI90k.p9waS1obrRcysBpmWZ4d.3ELjPHnbRi4pD 1M3BUK6KCzCdB43gJHbrIljeKDyYtuo12T_4VY7rxXFxu3hjj5QHPIKw1eIh 5xnEp.IjpmiWMhTaSFsY8aAwBS_JDJheR5riRSlWMgeHH8SwG6Zsgf902rty a0z8jVM12.gvAPVxnyi07tpB4wCbDHBYH1bWPEx07Nv8Fke1G0L0wfFdx44J fRg6HRiW10EjYcvX07lcSzu1hMkw.QX222dMmMC7pybXuk_6VNHF9SHO9wab tyc2W.BiVLVjfMUQat4kcWu1iP12pRzeY0DK4BU0yWFc- X-Yahoo-SMTP: opAkk_CswBAce_kJ3nIPlH80cJI- In-reply-to: <20160705111900.7e1599f0@pwslap01u.europe.root.pri> From: Oliver Kiddle References: <588168129.3340906.1467709726474.JavaMail.yahoo.ref@mail.yahoo.com> <588168129.3340906.1467709726474.JavaMail.yahoo@mail.yahoo.com> <20160705111900.7e1599f0@pwslap01u.europe.root.pri> To: zsh-workers@zsh.org Subject: Re: bug with camel case and delete-whole-word-match function MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <5373.1469315161.1@hydra.kiddle.eu> Date: Sun, 24 Jul 2016 01:06:02 +0200 Message-ID: <5374.1469315162@hydra.kiddle.eu> On 5 Jul, Peter wrote: > If you have "ThisIsSomeWords" > However, if you're on the "S", you get "Is" before and "Some" after. > Again there's no white space, so there's nothing to indicate to the > calling function that these are two separate words rather than bits of > the same word. So I think we'd need to add some extra signalling from > match-words-by-style to indicate "I'm at a word start" whether or not > there's white space, which needs some thinking about. Do we need to keep the existing seven elements of matched_words unchanged for backwards compatibility? Not that I can think of a particularly obvious way to augment it for this case. May be just a 1/0 indicator for start of word is the simplest. It also seems to lack having a field. I've attached a patch for a select-word-match function which uses the mechanism for a vim style text object. In the process, I've found a couple of other issues with match-words-by-style: One is that if the cursor is in the middle of a block of whitespace at the end of the line, the 4th element (whitespace after cursor) is empty while element 7 contains the whitespace. A similar issue occurs at the start of the line - element 1 contains whitespace while element 3 doesn't. The other issue is that with the shell word style, it'll put whitespace at the end of element 5 instead of in element 6. Oliver diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 1d2b7ca..c3dec34 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1940,6 +1940,8 @@ tindex(transpose-words-match) tindex(capitalize-word-match) tindex(up-case-word-match) tindex(down-case-word-match) +tindex(delete-whole-word-match) +tindex(select-word-match) tindex(select-word-style) tindex(match-word-context) tindex(match-words-by-style) @@ -1947,12 +1949,14 @@ xitem(tt(forward-word-match), tt(backward-word-match)) xitem(tt(kill-word-match), tt(backward-kill-word-match)) xitem(tt(transpose-words-match), tt(capitalize-word-match)) xitem(tt(up-case-word-match), tt(down-case-word-match)) +xitem(tt(delete-whole-word-match), tt(select-word-match)) item(tt(select-word-style), tt(match-word-context), tt(match-words-by-style))( -The eight `tt(-match)' functions are drop-in replacements for the +The first eight `tt(-match)' functions are drop-in replacements for the builtin widgets without the suffix. By default they behave in a similar way. However, by the use of styles and the function tt(select-word-style), -the way words are matched can be altered. For comparison, the widgets -described in ifzman(zmanref(zshzle) under Text Objects)\ +the way words are matched can be altered. tt(select-word-match) is intended +to be used as a text object in vi mode but with custom word styles. For +comparison, the widgets described in ifzman(zmanref(zshzle) under Text Objects)\ ifnzman(noderef(Text Objects)) use fixed definitions of words, compatible with the tt(vim) editor. @@ -1960,7 +1964,7 @@ The simplest way of configuring the functions is to use tt(select-word-style), which can either be called as a normal function with the appropriate argument, or invoked as a user-defined widget that will prompt for the first character of the word style to be used. The first -time it is invoked, the eight tt(-match) functions will automatically +time it is invoked, the first eight tt(-match) functions will automatically replace the builtin versions, so they do not need to be loaded explicitly. The word styles available are as follows. Only the first character diff --git a/Functions/Zle/select-word-match b/Functions/Zle/select-word-match new file mode 100644 index 0000000..24620c9 --- /dev/null +++ b/Functions/Zle/select-word-match @@ -0,0 +1,121 @@ +# Select the entire word around the cursor. Intended for use as +# a vim-style text object in vi mode but with customisable +# word boundaries. +# +# For example: +# autoload -U select-word-match +# zle -N select-in-camel select-word-match +# bindkey -M viopp ic select-in-camel +# zstyle ':zle:*-camel' word-style normal-subword + +emulate -L zsh +setopt extendedglob + +local curcontext=:zle:$WIDGET +local -a matched_words +# Start and end of range of characters +integer pos1 pos2 num=${NUMERIC:-1} +local style word + +# choose between inner word or a word style of widget +for style in $1 ${${WIDGET#*-}[1]} $KEYS[1] "i"; do + [[ $style = [ai] ]] && break +done + +autoload -Uz match-words-by-style + +while (( num-- )); do + if (( MARK > CURSOR )); then + # if cursor is at the start of the selection, just move back a word + match-words-by-style + if [[ $style = i && -n $matched_words[3] ]]; then + word=$matched_words[3] + else + word=$matched_words[2]$matched_words[3] + fi + if [[ -n $word ]]; then + (( CURSOR -= ${#word} )) + else + return 1 + fi + elif (( MARK >= 0 && MARK < CURSOR )); then + # cursor at the end, move forward a word + (( CURSOR+1 == $#BUFFER )) && return 1 + (( CURSOR++ )) + match-words-by-style + if [[ -n $matched_words[4] ]]; then + if [[ $style = i ]]; then + # just skip the whitespace + word=$matched_words[4] + else + # skip the whitespace plus word + word=$matched_words[4]$matched_words[5] + fi + else + if [[ $style = i ]]; then + # skip the word + word=$matched_words[5] + else + # skip word and following whitespace + word=$matched_words[5]$matched_words[6] + fi + fi + (( CURSOR += ${#word} - 1 )) + else + match-words-by-style + + if [[ -n "${matched_words[3]}" ]]; then + # There's whitespace before the cursor, so the word we are selecting + # starts at the cursor position. + pos1=$CURSOR + else + # No whitespace before us, so select any wordcharacters there. + pos1="${#matched_words[1]}" + fi + + if [[ -n "${matched_words[4]}" ]]; then + if [[ -n "${matched_words[3]}" ]] || (( CURSOR == 0 )); then + # whitespace either side, select it + (( pos1 = CURSOR - ${#matched_words[3]} )) + (( pos2 = CURSOR + ${#matched_words[4]} )) + else + # There's whitespace at the cursor position, so only select + # up to the cursor position. + (( pos2 = CURSOR + 1 )) + fi + else + # No whitespace at the cursor position, so select the + # current character and any following wordcharacters. + (( pos2 = CURSOR + ${#matched_words[5]} )) + fi + + if [[ $style = a ]]; then + if [[ -n "${matched_words[4]}" && ( -n "${matched_words[3]}" || CURSOR -eq 0 ) ]]; then + # in the middle of whitespace so grab a word + if [[ -n "${matched_words[5]}" ]]; then + (( pos2 += ${#matched_words[5]} )) # preferably the one after + else + (( pos1 -= ${#matched_words[2]} )) # otherwise the one before + fi + elif [[ -n "${matched_words[6]}" ]]; then + (( pos2 += ${#matched_words[6]} )) + elif [[ -n "${matched_words[3]}" ]]; then + # couldn't grab whitespace forwards so try backwards + (( pos1 -= ${#matched_words[3]} )) + elif (( pos1 > 0 )); then + # There might have been whitespace before the word + (( CURSOR = pos1 )) + match-words-by-style + if [[ -n "${matched_words[3]}" ]]; then + (( pos1 -= ${#matched_words[3]} )) + fi + fi + fi + + (( MARK = pos1, CURSOR = pos2-1 )) + fi +done + +if [[ $KEYMAP == vicmd ]] && (( !REGION_ACTIVE )); then + (( CURSOR++ )) # Need to include cursor position for operators +fi