[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] Failed vim-mode .zshrc experiment
From: |
Greg Chicares |
Subject: |
Re: [lmi] Failed vim-mode .zshrc experiment |
Date: |
Fri, 25 Oct 2019 02:17:53 +0000 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0 |
On 2019-10-24 21:50, Vadim Zeitlin wrote:
> On Thu, 24 Oct 2019 18:59:28 +0000 Greg Chicares <address@hidden> wrote:
[...]
> GC> The intention is just to color $PROMPT based on zle $KEYMAP.
> GC>
> GC> That intention is accomplished, but with a distressing side effect:
> GC> the Home and End keys no longer work as desired.
>
> My initial reaction was to say that it was impossible, but as it
> nevertheless happens to you, I've tried to do as Holmes would have done and
> deduce a possible explanation. Unfortunately the only thing I could come up
> is this: defining your custom zle-line-init widget must have overwritten
> the previous definition of this widget used by zsh which made these keys
> work. This explanation fits all the observable data, so it must be true,
> right?
The same argument has been made for superstring theory; but your
hypothesis is testable.
The identically-defined {zle-line-init, zle-keymap-select} functions
weren't my original idea (I adapted them from stuff I found online).
Removing the zle-line-init function does solve the {Home,End} problem.
However, it exposes other issues that the dual function definition
was probably intended to solve:
(1) When I start a zsh session, say by entering a chroot:
/tmp[0]$schroot --chroot=chroot:bullseye0
ugolyok%
the initial prompt is "${hostname}% ". I could live with that; but...
(2) Then, when I hit Esc to enter vicmd mode, the prompt stays in
that mode, even after I hit Enter to execute a command:
/tmp[0]$-vicmd-$ls >/dev/null
/tmp[0]$-vicmd-$
The goal is to provide a visual $KEYMAP indicator, but if I now type
'x' three times, it doesn't delete three (nonexistent) characters
under the cursor--instead, I see:
/tmp[0]$-vicmd-$xxx
zsh: command not found: xxx
so the prompt lied, and I really was in viins mode.
> The only problem with this beautiful theory is that it doesn't work for
> me: both because your ZLE widgets changes don't break Home/End for me, and
> because they work for me in the first place only because I have custom
> bindings for them. Moreover, I've just created a new user just for testing
> and, even without any .zshrc, your custom ZLE widgets still work and don't
> break Home/End for me. So this is probably not the right explanation, after
> all, but I just have no idea what else could it be, so I'm offering what I
> have.
I tried to reproduce this by replacing the chroot's ~/.zshrc with only
the following; but I observed exactly the same anomalies as originally
reported.
/tmp[0]$-vicmd-$cat ~/.zshrc
bindkey -v
autoload colors && colors
function zle-line-init zle-keymap-select {
local local_prompt='%d[%?]%(!.#.$)'"-${KEYMAP}-$"
if [[ ${KEYMAP} == vicmd ]]; then
prompt="%{$fg_bold[green]%}${local_prompt}%{$reset_color%}"
elif [[ ${KEYMAP} == isearch ]]; then
prompt="ISEARCH${local_prompt}"
else
prompt="${local_prompt}"
fi
zle reset-prompt
}
/tmp[0]$-main-$
This rules out any strange interaction with anything else in ~/.zshrc .
I also tried switching the order of the functions:
-function zle-line-init zle-keymap-select {
+function zle-keymap-select zle-line-init {
-zle -N zle-line-init
-zle -N zle-keymap-select
+zle -N zle-keymap-select
+zle -N zle-line-init
but that made no difference.
> In case this explanation is somehow correct, I can offer two possible
> solutions:
>
> - Either stop defining zle-line-init widget, as it doesn't seem necessary:
> in my, admittedly limited, testing, defining just zle-keymap-select seems
> to be enough and to work as intended.
Alas, that's not enough in the scenario described above.
> - Or check what does the existing widget do, by doing "echo
> $widgets[zle-line-init]", and then do the same thing in your replacement.
> E.g. here the default widget happens to be defined by zle-line-init
> function which does "printf '%s' ${terminfo[smkx]}" (I'll let you dig
> through terminfo manual if you want to know what smkx does entirely, but
> be warned that it's not very exciting) per its definition in
> /etc/zsh/zshrc on Debian systems.
Running that command first in my host system (where I've never defined
any such function), and then in the chroot (where I do define them):
/tmp[0]$echo $widgets[zle-line-init]
user:zle-line-init
/tmp[0]$schroot --chroot=chroot:bullseye0
/tmp[0]$-main-$echo $widgets[zle-line-init]
user:zle-line-init
the output is the same--and different from yours.
And this isn't a zsh anomaly in 'bullseye', because 'buster' uses
the same zsh version:
/tmp[0]$uname -a
Linux ugolyok 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2 (2019-08-28) x86_64
GNU/Linux
/tmp[0]$cat /etc/debian_version
10.1
/tmp[0]$zsh --version
zsh 5.7.1 (x86_64-debian-linux-gnu)
/tmp[0]$
/tmp[0]$schroot --chroot=chroot:bullseye0
/tmp[0]$-main-$uname -a
Linux ugolyok 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2 (2019-08-28) x86_64
GNU/Linux
/tmp[0]$-main-$cat /etc/debian_version
bullseye/sid
/tmp[0]$-main-$zsh --version
zsh 5.7.1 (x86_64-debian-linux-gnu)
I've never altered /etc/zsh/zshrc:
/etc[0]# git log /etc/zsh/zshrc
commit b2fcf7a1e72fc4412134f4545f9906f08ee63f75
Author: Gregory W. Chicares <address@hidden>
Date: Wed Sep 4 13:20:45 2019 +0000
committing changes in /etc made by "apt-get install zsh"
Package changes:
+zsh 5.7.1-1 amd64
+zsh-common 5.7.1-1 all
> The nice thing is that applying one of those solutions might solve the
> problem even if my explanation is wrong, so why not try them?
I have. It seems mysterious that you can't reproduce my anomaly at all,
while I can't seem to get rid of it while still accomplishing my goal.
The motivating problem is that
- when editing files in vim, I rely on "-- INSERT --" at the bottom
of the screen to tell me what mode I'm in;
- in zsh's vim mode, I never know what $KEYMAP I'm using, and I get
confused too easily, so I want a visual indication.
Do you know a better way to solve that problem? Is it a problem that
you just don't have, because you're always aware what mode you're in?
> GC> With this commit, neither Home nor End moves the cursor as expected.
> GC> Instead, Home enters 'vicmd' mode, and End followed by right-arrow
> GC> deletes to end of line.
>
> You can try entering "^V" (<Ctrl-V>) and then "Home" to see what escape
> sequence this key generates for you. Here it generates "^[[1~", i.e.
/tmp[0]$-main-$echo '^[[H' | od -t a
0000000 esc [ H nl
> "<Esc>[1~", and I have
>
> bindkey "^[[1~" beginning-of-line
>
> in my .zshrc (all the characters in the line above are simple ASCII
> characters and not a representation of unprintable characters). This line
> has been in my .zshrc ever since I put it under version control 15 years
> ago, so I don't remember why did I have to add it. Maybe zsh didn't set it
> up correctly back then when using vi mode (as one of the first lines in my
> .zshrc is "bindkey -v", of course). Nowadays it seems that Home/End are
> bound to vi-{beginning,end}-of-line by default in vi mode, which should be
> just fine, but maybe you have some non-default bindings for them somehow?
My ~/.zshrc, for reasons similarly lost in the mists of time, contains:
# These three seem to be set by default:
# bindkey '\e[3~' delete-char # Del
# bindkey '\e[H' beginning-of-line # Home
# bindkey '\e[F' end-of-line # End
I think I might have needed those settings in the last century for cygwin,
and then commented them out when they seemed to have become unnecessary.
Experimentally, I uncomment the bindings for {Home,End}, and now the
anomaly reported earlier seems to have vanished, for viins mode. And that
really does solve my problem, for the most part, because it's in viins
mode that I expect those keys to work (not having used 'bindkey -v' in
the past, I'm really just trying to get viins mode to behave like the
emacs mode to which I'm accustomed). But, having dug through the manual,
I now know how to fix it in vicmd mode, too:
bindkey '\e[H' beginning-of-line # Home
bindkey '\e[F' end-of-line # End
+# Bind those in 'vicmd' mode, too:
+bindkey -M vicmd '\e[H' beginning-of-line # Home
+bindkey -M vicmd '\e[F' end-of-line # End
Now everything seems to work exactly as I had hoped.
> In any case, I'm pretty sure you should be able to resolve the issue by
> explicitly binding whatever code these keys generate for you (which really
> should be the same ones as here, i.e. "<Esc>[1~" and "<Esc>[4~") to the
/tmp[0]$echo "${terminfo[khome]}" |od -t a
0000000 esc O H nl
0000004
/tmp[0]$echo "${terminfo[kend]}" |od -t a
0000000 esc O F nl
0000004
It seems odd that mine don't match yours. But the arch wiki:
https://wiki.archlinux.org/index.php/Home_and_End_keys_not_working#Readline
specifies both yours and mine, as well as some others, and indeed
my /etc/inputrc has:
# allow the use of the Home/End keys
"\e[1~": beginning-of-line
"\e[4~": end-of-line
...uncommented, and the ones I need, commented:
# for non RH/Debian xterm, can't hurt for RH/Debian xterm
# "\eOH": beginning-of-line
# "\eOF": end-of-line
as well as these, uncommented:
$if term=rxvt
"\e[7~": beginning-of-line
"\e[8~": end-of-line
for rxvt if that still exists. This suggests new hypotheses: that
the terminal is responsible; that you didn't reproduce the anomaly I
saw because you're not using Konsole; and that the anomaly vanishes
for me when I change my .zshrc to specify the "non RH/Debian xterm"
codes quoted from /etc/inputrc above, because I am using Konsole.
Those hypotheses can't all be quite true, because I tried
echo "${terminfo[khome]}" |od -t a
in 'uxvt' and got the thing with 'H' (can't paste from that terminal,
but it's definitely an 'H'). But they're at least as true as superstring
theory, and my problem now seems to be solved, so...
> corresponding widgets, but I'm afraid I can't convincingly explain why do
> you see what you're seeing. But maybe just fixing it would be enough?
...so, yes, that's plenty good enough.
Thanks for working through this with me.