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

[PATCH] Re: zed-set-filename breaks zed keymap?

Reviving this from a year-ish ago, so including that thread for
context ... please see below.

On Tue, May 26, 2020 at 8:30 PM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> I was trying to get zed-set-file-name to work with my "zed -h" change,
> and discovered that even with plain "zed file" after entering the file
> name into read-from-minibuffer, ^X^W no longer works to exit from zed,
> and a bare return DOES exit it.  Apparently returning from
> read-from-minibuffer does not constitute "the next command" for
> purposes of zle -K restoring the keymap?  Did this work at one time?
> Also, it is possible to execute zed-set-file-name recursively from
> inside read-from-minibuffer, which is a bit strange.

On Tue, May 26, 2020 at 9:25 PM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> The documentation for zed-set-file-name seems contradictory as well.
> In the first paragraph it says:
>      ... because of zed's rebindings you will have to type ^j at the
>      end instead of the return key ...
> but then the second paragraph says
>      While zed-set-file-name is running, zed uses the keymap
>      zed-normal-keymap, which is linked from the main keymap in effect
>      at the time zed initialised its bindings.  (This is to make the
>      return key operate normally.) ...
> The return key does not in fact "operate normally" during
> zed-set-file-name, but something else strange is going on with the
> keymaps.

After some experimentation ...

zed does these things up front:
1. Creates the keymap zed as a copy of main (bindkey -N zed main)
2. Aliases zed-normal-keymap (bindkey -A main zed-normal-keymap)
3. Creates the keymap zed-vicmd as a copy of vicmd

It then eventually runs:  vared -M zed -m zed-vicmd ...

Next bin_vared hides the "main" keymap and renames the keymap passed
for -M as "main", so $KEYMAP is not "zed".

zed-set-file-name then does this:
1. zle -K zed-normal-keymap
2. read-from-minibuffer

However, zle -K is useless, because eventually read-from-minibuffer runs
  zle recursive-edit -K main
and because of vared's dirty trick, this pulls in the "zed" keymap,
not the keymap that read-from-minibuffer actually wanted.

So ... what's the correct fix here?  Shortest is to change
zed-set-file-name to use
  bindkey -A zed-normal-keymap main
Attached patch does that.  Other options:

Change vared to act more like "zle widget -K"?  I don't think that
breaks any promises, but implicitly $KEYMAP has been "main" inside
vared all these years (when not viins).

Change read-from-minibuffer to make its own keymap?  It's unclear how
to accomplish that cleanly when vared has already done its thing,
unless we force an explicit set of keybindings.

Change read-from-minibuffer to pass in the keymap it should bind for
recursive-edit?  How?  -K option to go with the single existing -k

Rewrite zed-set-file-name to invoke zle recursive-edit directly, with
the correct keymap?
diff --git a/Functions/Zle/zed-set-file-name b/Functions/Zle/zed-set-file-name
index da3421e71..c77a9d26e 100644
--- a/Functions/Zle/zed-set-file-name
+++ b/Functions/Zle/zed-set-file-name
@@ -2,8 +2,25 @@ emulate -L zsh
 autoload -Uz read-from-minibuffer
-zle -K zed-normal-keymap
-local REPLY
-read-from-minibuffer "File name: "
+case $curcontext in
+  (zed:::)
+    local curcontext=zed-set-filename:::
+    # The call to vared from zed does the equivalent of
+    #  bindkey -A zed main
+    # which confuses read-from-minibuffer.  Fix it.
+    bindkey -A zed-normal-keymap main;;
+  (zed-set-filename:::)
+    zle -M "zed-set-file-name: may not be called recursively"
+    return 1;;
+  (*)
+    zle -M "zed-set-file-name: not called from within zed"
+    return 1;;
+  local REPLY
+  read-from-minibuffer "File name: "
+  zed_file_name=$REPLY
+} always {
+  # Re-install the zed keymap in the way vared should have all along
+  zle -K zed

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