Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Oddities with "viopp" keymap

I hardly ever use vi-mode so I had mostly forgotten that the viopp keymap
even exists.  However, it has some strange behavior.  I arrived here by
being curious what would happen if I pasted text while in the viopp map,
since bracketed-paste is not bound in that keymap.

For one thing, if I define a widget like this:

zviopp() { zle -M $KEYMAP; zle select-a-shell-word }
zle -N zviopp
bindkey -M viopp ^W zviopp

And then invoke, say, "d^E", the word under the cursor is deleted as I
would expect, but the keymap is reported as "vicmd" by "zle -M".  I don't
think it's clearly documented that local keymaps never appear in $KEYMAP.

Next thing ... if I begin an action such as "d" that selects viopp as the
local keymap, and then hit ESC to abort the action and go back to vicmd
(the binding for ^[ in viopp is vi-cmd-mode) the editor ends up in a state
where I can't leave the current line; in fact vi-cmd-mode is a no-op when
in a local keymap, because invicmdmode() doesn't check localkeymap.

In fact, pressing any key that doesn't select something will put you into
this state ("dv", "du", "d^L", etc.) because the global virangeflag is
never cleared on an error.

The patch below seems to fix this.  With that in place, "d" followed by a
paste simply shoves the pasted text into the kill ring where it can be
retrieved with "p".  This is a bit mystifying but I'm not sure what else
to suggest.

Slightly more unexpected (for a vi user, not for me knowing how the code
is written) is that (from command mode) a digit followed by a paste
applies quotes rather than repeating the paste <digit> times.  I'm not
going to attempt to decide whether we should change that, either.

The patch:

diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index 1a11ca7..42dc46e 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -224,6 +224,7 @@ getvirange(int wf)
 	    ZS_memcpy(zleline, lastline, zlell = lastll);
 	    zlecs = pos;
 	    mark = mpos;
+	    virangeflag = 0;
 	    return -1;
@@ -232,6 +233,7 @@ getvirange(int wf)
 	if (!zlell || (zlecs == pos && (mark == -1 || mark == zlecs) &&
 		    virangeflag != 2) || ret == -1) {
 	    mark = mpos;
+	    virangeflag = 0;
 	    return -1;
 	virangeflag = 0;

Messages sorted by: Reverse Date, Date, Thread, Author