Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: key bindings, fixes, docs, tests for vi stuff
- X-seq: zsh-workers 33704
- From: Oliver Kiddle <okiddle@xxxxxxxxxxx>
- To: Zsh workers <zsh-workers@xxxxxxx>
- Subject: PATCH: key bindings, fixes, docs, tests for vi stuff
- Date: Mon, 17 Nov 2014 22:36:00 +0100
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.co.uk; s=s2048; t=1416260161; bh=/Osgk+WqocVDA3YfDqPDADdq9oknod7aEM8ioQXX+X0=; h=From:To:Subject:Date:From:Subject; b=SIEC5irsf8WW5saWRleh75YRipk6wfKAonS5maWAZ/soo0jYtbIKOYG9Qw8BOE/O8xDTw33yi2TpRp0/ZVJ9vp6blw8bKnbT+OJu1+wqi78mB2KStAUf70HbC7hVq2ehsXYRdYUQqdqWDXhePXEivD9WPY84PU0alHcP6BlVs+ujKlHZvDOTYP/EZNy9bnKuycRTPczqX5uWIHH7PfWh9awLwE6WGgH/tUL8V+nJnNatBqf/U4/Fx5j/rbqS2L4RZQykYRQ66nLhqVgNoNAF9IxQgMs3pjf8aMC7/DYPzgm6NJdNtcVzBAY5lbLsI1jZJW7D4fVCJPPu0eMfpeiYiQ==
- Domainkey-signature: a=rsa-sha1; q=dns; c=nofws; s=s2048; d=yahoo.co.uk; b=nvX7eKax1goKCdph1YDA5uSdRpJvGWWf1OLCXundoQ1tN1zIgOV7Gj2BTc4PnFTejmimHbCYh4LOS0NIKJFZH4lCc4mNE10rBCYPQHzlLQlbgqieoJwncqwFVXkzXpm1xVTjaDQbide6fkVTX/htQ3l/YOtmfH1iQVbHGGhUWEtFRrZb8lAK72Ib42qJdHqI5PNOsDyk2ytvjb8aaR0BeTP7LZkPQovt2sIfFvgqs9SfJYaKM+iNsXPmExX5zDpzC/0o6Es+y8IaW2rEjomXpaD96BYqQj2smHe6AflsnjFmFBkw9BDvnM91p18NxAxVETmhcnqK2z5ICOg8HXi/vQ==;
- 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
With this patch, the viopp and visual keymaps are now created by default
with a few keys bound. The patch adds documentation and tests. For
Solaris, I needed to add another stty parameter because it was turning
tabs into spaces. Perhaps I should change the way it prints the buffer
to be fully quoted ($'...' style).
There's also a couple of minor fixes and, as I mentioned before, the
vi-delete/vi-backward-delete changes are backed out as the binding of x
in visual does the same job.
Oliver
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 998bf4a..aa7ff4b 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -60,12 +60,14 @@ or more names. If all of a keymap's names are deleted, it disappears.
findex(bindkey, use of)
tt(bindkey) can be used to manipulate keymap names.
-Initially, there are six keymaps:
+Initially, there are eight keymaps:
startsitem()
sitem(tt(emacs))(EMACS emulation)
sitem(tt(viins))(vi emulation - insert mode)
sitem(tt(vicmd))(vi emulation - command mode)
+sitem(tt(viopp))(vi emulation - operator pending)
+sitem(tt(visual))(vi emulation - selection active)
sitem(tt(isearch))(incremental search mode)
sitem(tt(command))(read a command name)
sitem(tt(.safe))(fallback keymap)
@@ -122,6 +124,21 @@ in user-defined widgets with the tt(read-command) widget, described
ifzman(below)\
ifnzman(in noderef(Miscellaneous) below)\
.
+subsect(Local Keymaps)
+cindex(local keymaps)
+While for normal editing a single keymap is used exclusively, in many
+modes a local keymap allows for some keys to be customised. For example,
+in an incremental search mode, a binding in the tt(isearch) keymap will
+override a binding in the tt(main) keymap but all keys that are not
+overriden can still be used.
+
+If a key sequence is defined in a local keymap, it will hide a key
+sequence in the global keymap that is a prefix of that sequence. An
+example of this occurs with the binding of tt(iw) in tt(viopp) as this
+hides the binding of tt(i) in tt(vicmd). However, a longer sequence in
+the global keymap that shares the same prefix can still apply so for
+example the binding of tt(^Xa) in the global keymap will be unaffected
+by the binding of tt(^Xb) in the local keymap.
texinode(Zle Builtins)(Zle Widgets)(Keymaps)(Zsh Line Editor)
sect(Zle Builtins)
@@ -817,7 +834,10 @@ cursor remains between the new tt($LBUFFER) and the old tt($RBUFFER).
)
vindex(MARK)
item(tt(MARK) (integer))(
-Like tt(CURSOR), but for the mark.
+Like tt(CURSOR), but for the mark. With vi-mode operators that wait for
+a movement command to select a region of text, setting tt(MARK) allows
+the selection to extend in both directions from the the initial cursor
+position.
)
vindex(NUMERIC)
item(tt(NUMERIC) (integer))(
@@ -863,7 +883,9 @@ cursor remains between the old tt($LBUFFER) and the new tt($RBUFFER).
vindex(REGION_ACTIVE)
item(tt(REGION_ACTIVE) (integer))(
Indicates if the region is currently active. It can be assigned 0 or 1
-to deactivate and activate the region respectively;
+to deactivate and activate the region respectively. A value of 2
+activates the region in line-wise mode with the highlighted text
+extending for whole lines only;
ifzman(see em(Character Highlighting) below)\
ifnzman(noderef(Character Highlighting)).
)
@@ -2275,6 +2297,16 @@ item(tt(vi-undo-change) (unbound) (u) (unbound))(
Undo the last text modification.
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.
+)
+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.
+)
tindex(what-cursor-position)
item(tt(what-cursor-position) (^X=) (unbound) (unbound))(
Print the character under the cursor, its code as an octal, decimal and
diff --git a/Src/Zle/zle_bindings.c b/Src/Zle/zle_bindings.c
index 6826913..50a2955 100644
--- a/Src/Zle/zle_bindings.c
+++ b/Src/Zle/zle_bindings.c
@@ -376,7 +376,7 @@ int vicmdbind[128] = {
/* S */ z_vichangewholeline,
/* T */ z_vifindprevcharskip,
/* U */ z_undefinedkey,
- /* V */ z_undefinedkey,
+ /* V */ z_visuallinemode,
/* W */ z_viforwardblankword,
/* X */ z_vibackwarddeletechar,
/* Y */ z_viyankwholeline,
@@ -408,7 +408,7 @@ int vicmdbind[128] = {
/* s */ z_visubstitute,
/* t */ z_vifindnextcharskip,
/* u */ z_viundochange,
- /* v */ z_undefinedkey,
+ /* v */ z_visualmode,
/* w */ z_viforwardword,
/* x */ z_videletechar,
/* y */ z_viyank,
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index 6a71076..216e302 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -1277,8 +1277,10 @@ default_bindings(void)
Keymap vmap = newkeymap(NULL, "viins");
Keymap emap = newkeymap(NULL, "emacs");
Keymap amap = newkeymap(NULL, "vicmd");
+ Keymap oppmap = newkeymap(NULL, "viopp");
+ Keymap vismap = newkeymap(NULL, "visual");
Keymap smap = newkeymap(NULL, ".safe");
- Keymap vimaps[2], kptr;
+ Keymap vimaps[2], vilmaps[2], kptr;
char buf[3], *ed;
int i;
@@ -1332,6 +1334,22 @@ default_bindings(void)
add_cursor_key(kptr, TCLEFTCURSOR, t_vibackwardchar, 'D');
add_cursor_key(kptr, TCRIGHTCURSOR, t_viforwardchar, 'C');
}
+ vilmaps[0] = oppmap;
+ vilmaps[1] = vismap;
+ for (i = 0; i < 2; i++) {
+ /* vi visual selection and operator pending local maps */
+ kptr = vilmaps[i];
+ add_cursor_key(kptr, TCUPCURSOR, t_upline, 'A');
+ add_cursor_key(kptr, TCDOWNCURSOR, t_downline, 'B');
+ bindkey(kptr, "k", refthingy(t_upline), NULL);
+ bindkey(kptr, "j", refthingy(t_downline), NULL);
+ }
+ /* escape in operator pending cancels the operation */
+ bindkey(oppmap, "\33", refthingy(t_vicmdmode), NULL);
+ bindkey(vismap, "o", refthingy(t_exchangepointandmark), NULL);
+ bindkey(vismap, "p", refthingy(t_putreplaceselection), NULL);
+ bindkey(vismap, "x", refthingy(t_videlete), NULL);
+ bindkey(vismap, "~", refthingy(t_vioperswapcase), NULL);
/* emacs mode: arrow keys */
add_cursor_key(emap, TCUPCURSOR, t_uplineorhistory, 'A');
@@ -1373,6 +1391,8 @@ default_bindings(void)
linkkeymap(vmap, "viins", 0);
linkkeymap(emap, "emacs", 0);
linkkeymap(amap, "vicmd", 0);
+ linkkeymap(oppmap, "viopp", 0);
+ linkkeymap(vismap, "visual", 0);
linkkeymap(smap, ".safe", 1);
if (((ed = zgetenv("VISUAL")) && strstr(ed, "vi")) ||
((ed = zgetenv("EDITOR")) && strstr(ed, "vi")))
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index f0351ad..467629d 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -1037,8 +1037,6 @@ zrefresh(void)
region_highlights[0].start = mark;
region_highlights[0].end = zlecs;
}
- if (invicmdmode())
- INCPOS(region_highlights[0].end);
if (region_active == 2) {
int origcs = zlecs;
zlecs = region_highlights[0].end;
@@ -1046,7 +1044,8 @@ zrefresh(void)
zlecs = region_highlights[0].start;
region_highlights[0].start = findbol();
zlecs = origcs;
- }
+ } else if (invicmdmode())
+ INCPOS(region_highlights[0].end);
} else {
region_highlights[0].start = region_highlights[0].end = -1;
}
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index 3a4304c..84cba77 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -258,7 +258,7 @@ getvirange(int wf)
pos = tmp;
}
- if (visual && invicmdmode())
+ if (visual == 1 && invicmdmode())
INCPOS(pos);
/* Was it a line-oriented move? If so, the command will have set *
@@ -389,9 +389,6 @@ videletechar(char **args)
startvichange(-1);
- if (region_active)
- return killregion(args);
-
/* handle negative argument */
if (n < 0) {
int ret;
@@ -804,9 +801,6 @@ vibackwarddeletechar(char **args)
if (invicmdmode())
startvichange(-1);
- if (region_active)
- return killregion(args);
-
/* handle negative argument */
if (n < 0) {
int ret;
diff --git a/Test/X02zlevi.ztst b/Test/X02zlevi.ztst
index 297fb9ae..94afb60 100644
--- a/Test/X02zlevi.ztst
+++ b/Test/X02zlevi.ztst
@@ -273,6 +273,115 @@
>BUFFER: one wo
>CURSOR: 2
+ zletest $'one two\evbcx'
+0:change selection
+>BUFFER: one x
+>CURSOR: 5
+
+ zletest $'four\eOthree\eOtwo\eOone\evjjhCnew'
+0:change character wise selection with C acts linewise
+>BUFFER: new
+>four
+>CURSOR: 3
+
+ zletest $'x testing\ehvbx'
+0:x kills selections
+>BUFFER: x g
+>CURSOR: 2
+
+ zletest $'one two\eyb0vep'
+0:put over selection at start of buffer
+>BUFFER: tw two
+>CURSOR: 1
+
+ zletest $'hello\C-wbye\evhp'
+0:put over selection at end of buffer
+>BUFFER: bhello
+>CURSOR: 5
+
+ zletest $'one\eotwo\eyykVp'
+0:yank linewise and put over linewise selection at start of buffer
+>BUFFER: two
+>two
+>CURSOR: 0
+
+ zletest $'one\eotwo\eothree\eyykVp'
+0:yank linewise and put over linewise selection in middle of buffer
+>BUFFER: one
+>three
+>three
+>CURSOR: 4
+
+ zletest $'two\eOone\eyyjVp'
+0:yank linewise and put over linewise selection at end of buffer
+>BUFFER: one
+>one
+>CURSOR: 4
+
+ zletest $'one\eyhVp'
+0:yank character-wise and put over linewise selection
+>BUFFER: n
+>CURSOR: 0
+
+# vim puts a blank line above in this test
+ zletest $'one\eotwo\eyy0kvlp'
+0:yank linewise and put over character-wise selection at start of buffer
+>BUFFER: two
+>e
+>two
+>CURSOR: 0
+
+ zletest $'one\eyyhvp'
+0:yank linewise and put over character-wise selection in middle of buffer
+>BUFFER: o
+>one
+>e
+>CURSOR: 2
+
+# vim behaviour on this one really looks like a bug
+ zletest $'two\eOone\eyyjvhp'
+0:yank linewise and put over character-wise selection at end of buffer
+>BUFFER: one
+>t
+>one
+>CURSOR: 6
+
+ zletest $'abc123456789\exxxxxxxxxhv"9p0P'
+0:paste last (9th) register over a selection
+>BUFFER: ba9c
+>CURSOR: 0
+
+ zletest $'one\eo\eo\eotwo\ekkVdvd'
+0:delete blank line using selection
+>BUFFER: one
+>two
+>CURSOR: 4
+
+ zletest $'One Two Three\e2bvw~'
+0:toggle case of selection
+>BUFFER: One tWO three
+>CURSOR: 4
+
+ zletest $' ----word ---- word word---- ----\e42|daw30|daw22|daw14|daw2|daw'
+0:delete all word on blanks
+>BUFFER: word
+>CURSOR: 0
+
+ zletest $' word----word word----word word \e38|daw30|daw22|daw14|daw6|daw'
+0:delete all word on alphanumerics
+>BUFFER: --------
+>CURSOR: 4
+
+ zletest $' ----word---- ----word---- ---- \e38|daw30|daw22|daw14|daw6|daw'
+0:delete all word on other characters
+>BUFFER: wordword
+>CURSOR: 4
+
+ zletest $'- word word\e4|2daw'
+0:delete all word with numeric argument
+>BUFFER: -
+>CURSOR: 0
+
%clean
zmodload -ui zsh/zpty
diff --git a/Test/comptest b/Test/comptest
index 654c0f1..c67237a 100644
--- a/Test/comptest
+++ b/Test/comptest
@@ -34,7 +34,7 @@ comptestinit () {
"fpath=( $fpath )" \
"bindkey -$comptest_keymap" \
'LISTMAX=10000000
-stty 38400 columns 80 rows 24 werase undef
+stty 38400 columns 80 rows 24 werase undef tabs
TERM=vt100
KEYTIMEOUT=1
setopt zle
Messages sorted by:
Reverse Date,
Date,
Thread,
Author