Print
Category: Uncategorised
Hits: 5224

PROBLEM

in terminals, the home and end keys are not working when zsh is the shell. for bash it works in the same terminal, so must be possible to use those keys. must have been something that does bash differently than zsh.

INVESTIGATION

the documentation says zsh uses "terminfo" to configure its keybindings:

andre@nairobi ~ % vim /etc/zsh/zshrc
key=(
    Home     "${terminfo[khome]}"
    End      "${terminfo[kend]}"
    Insert   "${terminfo[kich1]}"
    Delete   "${terminfo[kdch1]}"
    Up       "${terminfo[kcuu1]}"
    Down     "${terminfo[kcud1]}"
    Left     "${terminfo[kcub1]}"
    Right    "${terminfo[kcuf1]}"
    PageUp   "${terminfo[kpp]}"
    PageDown "${terminfo[knp]}"
    BackTab  "${terminfo[kcbt]}"
)

on my system, the khome and kend variables are not set:

andre@nairobi ~ % for k in "${(@k)terminfo}"; do echo $k; done | sort | grep -E '(khome|kend|kich1|kbs|kdch1|kcuu1|kcud1|kcub1|kcuf1|kpp|knp)'
kbs
kcub1
kcud1
kcuf1
kcuu1
kdch1
kich1
knp
kpp

but why? lets see how the terminfo database is built.

andre@nairobi /etc/terminfo % cat README
This directory is for system-local terminfo descriptions. By default,
ncurses will search ${HOME}/.terminfo first, then /etc/terminfo (this
directory), then /lib/terminfo, and last not least /usr/share/terminfo.

let's see what terminfo applies currently. that one we will try to fix.

andre@nairobi /lib/terminfo % echo $TERM
xterm-color

find the config file:

andre@nairobi /lib/terminfo % for i in ${HOME}/.terminfo /etc/terminfo /lib/terminfo /usr/share/terminfo; do echo; echo "$i"; find $i -type f -name "xterm-color" -ls; done

/home/andre/.terminfo
find: `/home/andre/.terminfo': No such file or directory

/etc/terminfo

/lib/terminfo
1049857    4 -rw-r--r--   1 root     root         1569 Sep 17  2014 /lib/terminfo/x/xterm-color

/usr/share/terminfo

check what is set in this terminfo entry:
we can see the same keys as they are listed above.

andre@nairobi ~ % infocmp
============ xterm-color | grep -Eo '(khome|kend|kich1|kbs|kdch1|kcuu1|kcud1|kcub1|kcuf1|kpp|knp)=[^,]*,' | sort
kbs=\177,
kcub1=\EOD,
kcud1=\EOB,
kcuf1=\EOC,
kcuu1=\EOA,
kdch1=\E[3~,
kich1=\E[2~,
knp=\E[6~,
kpp=\E[5~,

SOLUTION

lets see if we can add the missing capability into the terminfo database.
as shown here: https://www.jbase.com/r5/knowledgebase/howto/general/common/CreateTerminfo/modify.htm

we can start with a copy in ${HOME}/.terminfo dir to start experimenting, without modifying system files.

but first we need to find out what are the proper sequences we add.
when pressing left-arrow, right-arrow, bild-auf, bild-ab, home and end using showkey -a, i get this output:

andre@nairobi ~/tmp % showkey -a
Press any keys - Ctrl-D will terminate this program
^[[D     27 0033 0x1b    # left-arrow
^[[C     27 0033 0x1b    # right-arrow
^[[5~    27 0033 0x1b    # page up
^[[6~    27 0033 0x1b    # page down
^[[H     27 0033 0x1b    # home
^[[F     27 0033 0x1b    # end

looks like we can add the entries of home and end like this.
e.g. Left-Arrow cursor key:

output of showkey -a:              "^[[D"
corresponding entry in dump: "kcub1=\EOD,"

i guess we can replace the "^[[" by "\EO" to obtain the correct values for khome and kend. lets dump the entry and modify it:

andre@nairobi ~ % cd ~/tmp/
andre@nairobi ~/tmp % infocmp xterm-color > xterm-color.ti
andre@nairobi ~/tmp % cp xterm-color.ti xterm-color.ti.orig
andre@nairobi ~/tmp % vim xterm-color.ti

the keys in the dump file are sorted, lets add it in order:

for Home: add "khome=\EOH, " between "kfnd=\E[1~, kich1=\E[2~":
for End:  and "kend=\EOF, "  between "kdch1=\E[3~, kf1=\E[11~,":

in my case, the modifications were:

andre@nairobi ~/tmp % diff xterm-color.ti xterm-color.ti.orig
15c15
<       kdch1=\E[3~, kend=\EOF, kf1=\E[11~, kf10=\E[21~, kf11=\E[23~,
---
>       kdch1=\E[3~, kf1=\E[11~, kf10=\E[21~, kf11=\E[23~,
20c20
<       kfnd=\E[1~, khome=\EOH, kich1=\E[2~, kmous=\E[M, knp=\E[6~, kpp=\E[5~,
---
>       kfnd=\E[1~, kich1=\E[2~, kmous=\E[M, knp=\E[6~, kpp=\E[5~,

compile the .ti file and check if it was created in the users terminfo:

andre@nairobi ~/tmp % mkdir -p ${HOME}/.terminfo/x
andre@nairobi ~/tmp % tic xterm-color.ti
andre@nairobi ~/tmp % find ~/.terminfo -type f -ls
1329052    4 -rw-r--r--   1 andre    andre        1443 Mar 18 13:20 /home/andre/.terminfo/x/xterm-color

make sure you have this in your .zshrc or /etc/zsh/zshrc:

# put cursor to end of line when end is pressed
bindkey "${key[End]}" end-of-line

# put cursor to start of line when home is pressed
bindkey "${key[Home]}" beginning-of-line

start a new xterm (! note, not only a new shell in the same terminal) and check if the keys are now present:

andre@nairobi ~ % infocmp xterm-color | grep -Eo '(khome|kend|kcub1)=[^,]*,' | sort
kcub1=\EOD,
kend=\EOF,
khome=\EOH,

now, check if your home and end keys are finally working!

!!!!! YES, AFTER SO MANY YEARS !!!!!