From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29608 invoked by alias); 7 Dec 2014 23:54:21 -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: 33924 Received: (qmail 6627 invoked from network); 7 Dec 2014 23:54:18 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.co.uk; s=s2048; t=1417996099; bh=FjL9GeXIq1XFDb5Slz7HQu+gXWDwjUR5yja4D+s7r/g=; h=From:To:Subject:Date:From:Subject; b=HwtjuRvBrGYaBvmwqd2QTv2BPrx9Xf6S8WevRWDvlSaUTNCOf2NICJ/xTIat5uf5w2HD8qiE0wl+NR3n8Ma6a/Nd6J2CYEkwTrONYUjrz/qtxqFHy6PFjwRgvGb6M7z3Ct7Z1GinoaT1AHVVgo5kobATulqsyi4x7blXxvuXOK92SIHTMr4RBQB9dcj3qe645QzxS4eblGP9ua5yMc0vgedHsmIlyjrFBwYw8I4Fhwm5aFD1p495NNFv3ZsSEJCuyuZhHm6nyMXYNqOt24JU81QICHUHkxRr0kWP9lhsR9UYhKZGxBDDJ3qdVtEoSqwP++rLk02TeAhmp18sUxkYxg== DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s2048; d=yahoo.co.uk; b=H5WYYykvGltr5e2Q8xws5s/CmZavsOCTdF/YEoWVBieyb983Ty/iAaayzKTDMZOY5x2w0pp/wLdcYpSPK2JCTRc0gdP3DOXmyNm+aQhAv39cb36pad1ONPg9/NKmHxJ1zqLg7PQ2u/CBc8+HMqSgyxidvhxDWher43wrEI6g8CI64cqWA2bRqILcD7twPrluom7lamPDKxJcyPYUudVSZSu6soVZZlFDE5CgKZ8E0FbPWVAXpkKw9grBRfHJk12dbqKunFKH03IFzkb0ZrtTDwtkXN4FzXcMgEU+Ofypsizgn2Rw2uqhUTyfFmzGT1OWsNyckxsH7i2xLd7ayG4PzA==; X-Yahoo-Newman-Id: 991459.74186.bm@smtp107.mail.ir2.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: rXXZovAVM1kdxHC.KCKKwZWADBvlSmv0f38vuJdTRQ7ML2O bvSM.doFuMPUvd9t046hjQ3UHeJESYGnZxjBPyUIiQzZZuPAOEpDxMPs4u9Z SHuhL6LBufe3lSoHA3sxK3bkv5PQ07IwgRetz6T091p16ywbBiBGF04gxEso HrQY4X0ueFfd1cf4JcXTCaJc1313YogdkHZS3DqciHVxgdBiw_CKNzHmSgB8 MKrs4bKSuX6p5nSAcKmS01GfRoYNu3W8ZampPZNn4jx3Na4y8WvVuONiFCb1 Fwf8Y96BUQQHkwrSBF53NH47HZ0Yj1mlZ1zqOwoao8NRU1VSwRrbmxUhpY5Y DK72.IYJyeW7C6fIVkFHP2cDqC7x0s4gsq5HbUOQ032LJ2TYEabNaM0aZfMI GIWHN.k1MqiubiQzMotYuuOwC2LEXAycHyPXBp3ec.ocXTzeeyH2vXyjVD.z HKonLgEQjxX8kEWsmTcQ9hd8o1JQ80zFj..3tGP8FaOzHJFU0oYQghyUi02s 0RWA8HeLIYhTqNgp_FDaCKG8a07wsAQ-- X-Yahoo-SMTP: opAkk_CswBAce_kJ3nIPlH80cJI- From: Oliver Kiddle To: Zsh workers Subject: PATCH: allow vi line/characterwise mode to be forced MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <18888.1417996097.1@thecus.kiddle.eu> Date: Mon, 08 Dec 2014 00:48:17 +0100 Message-ID: <18889.1417996097@thecus.kiddle.eu> Vim lets you force a movement to be interpreted as line or character-wise using v or V so, for example, dvj will join the beginning of the current line to the end of the next line. The patch below adds this to the visual-mode and visual-line-mode widgets. We could have separate widgets bound in viopp but that seems a bit overkill for what is perhaps a fairly obscure feature. Any thoughts on that? In the process, I noticed that for a character-wise movement where the text ends with a newline, the newline is not operated upon. This applies in vi if you've set a mark at the beginning of a line. I've put in a fix for that. Furthermore vi-goto-mark-line is a line-wise movement in vi by default. Oliver diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 3693ec9..f952642 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -2301,12 +2301,16 @@ If repeated, redo the modification. tindex(visual-mode) item(tt(visual-mode) (unbound) (v) (unbound))( Toggle vim-style visual selection mode. If line-wise visual mode is -currently enabled then it is changed to being character-wise. +currently enabled then it is changed to being character-wise. If used +following an operator, it forces the subsequent movement command to be +treated as a character-wise movement. ) tindex(visual-line-mode) item(tt(visual-line-mode) (unbound) (V) (unbound))( Toggle vim-style line-wise visual selection mode. If character-wise -visual mode is currently enabled then it is changed to being line-wise. +visual mode is currently enabled then it is changed to being line-wise. If used +following an operator, it forces the subsequent movement command to be +treated as a line-wise movement. ) tindex(what-cursor-position) item(tt(what-cursor-position) (^X=) (unbound) (unbound))( diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list index b3d1c92..a84d4dd 100644 --- a/Src/Zle/iwidgets.list +++ b/Src/Zle/iwidgets.list @@ -156,7 +156,7 @@ "vi-forward-word-end", viforwardwordend, 0 "vi-goto-column", vigotocolumn, 0 "vi-goto-mark", vigotomark, 0 -"vi-goto-mark-line", vigotomarkline, 0 +"vi-goto-mark-line", vigotomarkline, ZLE_LINEMOVE "vi-history-search-backward", vihistorysearchbackward, 0 "vi-history-search-forward", vihistorysearchforward, 0 "vi-indent", viindent, ZLE_LASTCOL diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h index 8a85ee3..a46b52d 100644 --- a/Src/Zle/zle.h +++ b/Src/Zle/zle.h @@ -243,6 +243,8 @@ struct modifier { #define MOD_VIAPP (1<<3) /* appending to the vi cut buffer */ #define MOD_NEG (1<<4) /* last command was negate argument */ #define MOD_NULL (1<<5) /* throw away text for the vi cut buffer */ +#define MOD_CHAR (1<<6) /* force character-wise movement */ +#define MOD_LINE (1<<7) /* force line-wise movement */ /* current modifier status */ diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c index 939cfb1..d751c43 100644 --- a/Src/Zle/zle_move.c +++ b/Src/Zle/zle_move.c @@ -511,6 +511,12 @@ exchangepointandmark(UNUSED(char **args)) int visualmode(UNUSED(char **args)) { + if (virangeflag) { + prefixflag = 1; + zmod.flags &= ~MOD_LINE; + zmod.flags |= MOD_CHAR; + return 0; + } switch (region_active) { case 1: region_active = 0; @@ -529,6 +535,12 @@ visualmode(UNUSED(char **args)) int visuallinemode(UNUSED(char **args)) { + if (virangeflag) { + prefixflag = 1; + zmod.flags &= ~MOD_CHAR; + zmod.flags |= MOD_LINE; + return 0; + } switch (region_active) { case 2: region_active = 0; diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index 249e38f..1a11ca7 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -259,15 +259,24 @@ getvirange(int wf) /* Was it a line-oriented move? If so, the command will have set * * the vilinerange flag. In this case, entire lines are taken, * * rather than just the sequence of characters delimited by pos * - * and zlecs. The terminating newline is left out of the range, * + * and zlecs. The terminating newline is left out of the range, * * which the real command must deal with appropriately. At this * * point we just need to make the range encompass entire lines. */ - if(vilinerange) { + vilinerange = (zmod.flags & MOD_LINE) || + (vilinerange && !(zmod.flags & MOD_CHAR)); + if (vilinerange) { int newcs = findbol(); lastcol = zlecs - newcs; zlecs = pos; pos = findeol(); zlecs = newcs; + } else if (!visual) { + /* for a character-wise move don't include a newline at the * + * end of the range */ + int prev = pos; + DECPOS(prev); + if (zleline[prev] == ZWC('\n')) + pos = prev; } return pos; } diff --git a/Test/X02zlevi.ztst b/Test/X02zlevi.ztst index 5204311..62cf954 100644 --- a/Test/X02zlevi.ztst +++ b/Test/X02zlevi.ztst @@ -286,6 +286,27 @@ >BUFFER: one wo >CURSOR: 2 + zletest $'keepnot\eo unwanted\ekhhcvj ' +0:force character-wise change to join lines +>BUFFER: keep wanted +>CURSOR: 5 + + zletest $'}\eOkeep{del\eF{dvj' +0:character-wise delete to beginning of line leaves the newline' +>BUFFER: keep +>} +>CURSOR: 3 + + zletest $'keep\eOdel\edVh' +0:force line-wise delete of line +>BUFFER: keep +>CURSOR: 0 + + zletest $'one two three\eFwdVawaX' +0:line-wise force of a text object +>BUFFER: X +>CURSOR: 1 + zletest $'one two\evbcx' 0:change selection >BUFFER: one x