Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: allow vi line/characterwise mode to be forced
- X-seq: zsh-workers 33924
- From: Oliver Kiddle <okiddle@xxxxxxxxxxx>
- To: Zsh workers <zsh-workers@xxxxxxx>
- Subject: PATCH: allow vi line/characterwise mode to be forced
- Date: Mon, 08 Dec 2014 00:48:17 +0100
- 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==;
- List-help: <mailto:zsh-workers-help@zsh.org>
- List-id: Zsh Workers List <zsh-workers.zsh.org>
- List-post: <mailto:zsh-workers@zsh.org>
- Mailing-list: contact zsh-workers-help@xxxxxxx; run by ezmlm
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
Messages sorted by:
Reverse Date,
Date,
Thread,
Author