Home/End Keys Do Not Work in Tmux

Home/End keys do not work in tmux

It appears the main problem is with using xterm-256color for $TERM. I switched $TERM to screen-256color and the problem went away.

In tmux, how do I bind the End and Home keys to other functions?

xterm-style terminals send two different sequences for each of Up, Down, Right, Left, Home, and End. In “normal cursor keys” mode, the sequences start with ^[[ (ESC [); in “application cursor keys” mode, the sequences start with ^[O (ESC O). The sequence for End ends with F, so it is ^[[F under “normal cursor keys” mode and ^[OF under “application cursor keys” mode.

tmux 1.8 recognizes both of these sequences by default, so you should not need to do anything special have tmux 1.8 reliably recognize xterm-style Home and End sequences (i.e. no need for the terminal-overrides hack described below).


The rest of this post describes a way to get these keys working work tmux versions prior to 1.8.


Versions of tmux prior to 1.8 only recognize End when sees the sequence provided in the kend capability of your attached terminal’s terminfo entry (as specified by TERM when you attach to a tmux session). By default, tmux switches the client terminal to “normal cursor keys” mode1. This ends up meaning that tmux will not recognize End because the terminal sends the “normal cursor keys” sequence but tmux only knows about the “application cursor keys” sequence (from kend).

Basically, tmux seems to expect that Home and End are not affected by the cursor key mode. This incompatibility with xterm-style terminals results in the key not being recognized properly2.

There is a kind of loop-hole here that you can use to verify that this is happening: run tput smkx (or start Emacs or Vim) in your active pane. As long as that pane is active, tmux should recognize Home and End. This happens because smkx sends a sequence to tmux that causes it to send smkx to the client (which switches the client into “application cursor keys” mode, which sends sequences for Home and End that tmux will be able to match against the sequences from khome and kend). This is not a very good workaround, however, because the “application” vs. “normal” state will also be set and reset by interactive or full-screen programs (e.g. Emacs and Vim) when they start/resume and exit/suspend.

A better workaround would be to use tmux’s terminal-overrides option to change kend (and khome) to the “normal” sequences and remove “application cursor keys” changes from smkx and rmkx (to prevent switching to “application cursor keys” mode, where Home and End would send the (now unrecognized) sequences). The arrow keys have special support, so they will always be recognized (assuming xterm-style sequences). If you are using TERM=xterm=256color to connect to tmux, you could do this in your (~/.tmux.conf):

set-option -ga terminal-overrides ',xterm-256color:kend=\E[F:khome=\E[H:smkx=\E=:rmkx=\E>'

(Note: because of the way terminfo entries are processed by tmux you will need to disconnect all your existing xterm-256color clients before the overrides will take effect. Also the values for smkx and rmkx used above assume that the keypad mode sequence is all that remains once the cursor keys mode sequence has been removed from each.)

Ultimately, this is probably a bug in tmux. It should probably either

  • include Home and End in the special support that the arrow keys get for recognizing both normal mode and application mode sequences, or
  • always put the client terminal in “keyboard transmit” mode, and send the appropriate sequence for TERM=screen depending on whether the pane has requested normal or application cursor or keypad mode3.

1 Actually, it sends the terminfo capability rmkx (”end keyboard transmit mode”), which—for xterm-like terminfo entries—switches to “normal cursor keys” mode and “normal kaypad” mode.

2 Because the ^[[F sequence is not recognized as a single key, it ends up being processed as two “key combinations”: ^[[ (ESC [, which is treated as M-[), and a plain F.

3 The revision control history indicates that this method (always in keyboard transmit mode, emulate cursor/keypad modes for each pane) was used at one point in the past. I am not clear why it was changed to the current behavior (track keypad mode of the active pane); there may have been some problem with this approach.

With $TERM='screen-256color' under tmux, HOME and END keys don't work. Why?

The above mapping solution doesn't affect the command mode or visual mode. The following is a more ideal solution until either tmux or vim fixes the bug (put in your .vimrc):

""""""""""""""
" tmux fixes "
""""""""""""""
" Handle tmux $TERM quirks in vim
if $TERM =~ '^screen-256color'
map <Esc>OH <Home>
map! <Esc>OH <Home>
map <Esc>OF <End>
map! <Esc>OF <End>
endif

Fix key settings (Home/End/Insert/Delete) in .zshrc when running Zsh in Terminator Terminal Emulator

To know the code of a key, execute cat, press enter, press the key, then Ctrl+C.

For me, Home sends ^[[H and End ^[[F, so i can put i my .zshrc in my home dir

bindkey  "^[[H"   beginning-of-line
bindkey "^[[F" end-of-line
bindkey "^[[3~" delete-char

These codes could change with the terminal emulator you use.

autoload zkbd ; zkbd will create a file with an array of keycodes to use, like bindkey "${key[Home]}" beginning-of-line, and you can source a different file depending on the terminal.

Home/End keys in zsh don't work with putty

I found it's a combination:

One

The ZSH developers do not think that ZSH should define the actions of the Home, End, Del, ... keys.

Debian and Ubuntu fix this by defining the normal actions the average user would expect in the global /etc/zsh/zshrc file. Following the relevant code (it is the same on Debian and Ubuntu):

if [[ "$TERM" != emacs ]]; then
[[ -z "$terminfo[kdch1]" ]] || bindkey -M emacs "$terminfo[kdch1]" delete-char
[[ -z "$terminfo[khome]" ]] || bindkey -M emacs "$terminfo[khome]" beginning-of-line
[[ -z "$terminfo[kend]" ]] || bindkey -M emacs "$terminfo[kend]" end-of-line
[[ -z "$terminfo[kich1]" ]] || bindkey -M emacs "$terminfo[kich1]" overwrite-mode
[[ -z "$terminfo[kdch1]" ]] || bindkey -M vicmd "$terminfo[kdch1]" vi-delete-char
[[ -z "$terminfo[khome]" ]] || bindkey -M vicmd "$terminfo[khome]" vi-beginning-of-line
[[ -z "$terminfo[kend]" ]] || bindkey -M vicmd "$terminfo[kend]" vi-end-of-line
[[ -z "$terminfo[kich1]" ]] || bindkey -M vicmd "$terminfo[kich1]" overwrite-mode

[[ -z "$terminfo[cuu1]" ]] || bindkey -M viins "$terminfo[cuu1]" vi-up-line-or-history
[[ -z "$terminfo[cuf1]" ]] || bindkey -M viins "$terminfo[cuf1]" vi-forward-char
[[ -z "$terminfo[kcuu1]" ]] || bindkey -M viins "$terminfo[kcuu1]" vi-up-line-or-history
[[ -z "$terminfo[kcud1]" ]] || bindkey -M viins "$terminfo[kcud1]" vi-down-line-or-history
[[ -z "$terminfo[kcuf1]" ]] || bindkey -M viins "$terminfo[kcuf1]" vi-forward-char
[[ -z "$terminfo[kcub1]" ]] || bindkey -M viins "$terminfo[kcub1]" vi-backward-char

# ncurses fogyatekos
[[ "$terminfo[kcuu1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcuu1]/O/[}" vi-up-line-or-history
[[ "$terminfo[kcud1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcud1]/O/[}" vi-down-line-or-history
[[ "$terminfo[kcuf1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcuf1]/O/[}" vi-forward-char
[[ "$terminfo[kcub1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcub1]/O/[}" vi-backward-char
[[ "$terminfo[khome]" == "^[O"* ]] && bindkey -M viins "${terminfo[khome]/O/[}" beginning-of-line
[[ "$terminfo[kend]" == "^[O"* ]] && bindkey -M viins "${terminfo[kend]/O/[}" end-of-line
[[ "$terminfo[khome]" == "^[O"* ]] && bindkey -M emacs "${terminfo[khome]/O/[}" beginning-of-line
[[ "$terminfo[kend]" == "^[O"* ]] && bindkey -M emacs "${terminfo[kend]/O/[}" end-of-line
fi

So, if you are connecting to a Debian or Ubuntu box, you don't have to do anything. Everything should work automagically (if not, see below).

But... if you are connecting to another box (e.g. FreeBSD), there might be no user friendly default zshrc. The solution is of course to add the lines from the Debian/Ubuntu zshrc to your own .zshrc.

Two

Putty sends xterm as terminal type to the remote host. But messes up somewhere and doesn't send the correct control codes for Home, End, ... that one would expect from an xterm. Or an xterm terminal isn't expected to send those or whatever... (Del key does work in xterm however, if you configure it in ZSH). Also notice that your Numpad-keys act funny in Vim for example with xterm terminal.

The solution is to configure Putty to send another terminal type. I've tried xterm-color and linux. xterm-color fixed the Home/End problem, but the Numpad was still funny. Setting it to linux fixed both problems.

You can set terminal type in Putty under Connection -> Data. Do not be tempted to set your terminal type in your .zshrc with export TERM=linux, that is just wrong. The terminal type should be specified by your terminal app. So that if, for example, you connect from a Mac box with a Mac SSH client it can set it's own terminal type.

Notice that TERM specifies your terminal type and has nothing to do with the host you are connecting to. I can set my terminal type to linux in Putty and connect to FreeBSD servers without problems.

So, fix both these things and you should be fine :)

home\ end keys in xterm not behaving correctly

The problem is unrelated to any possible setting in .inputrc (that doesn't scroll your screen up and down, though you could scroll through the command-history, etc).

If it's xterm (and not some other terminal), you can fix this with the translations resource, e.g., by using xev to identify the names for the home/end keys (probably just home and end), and using those names in a translation like this (in your X resources):

*VT100*translations:    #override \n\
<key>home: string(0x1b) string("[1~") \n\
<key>end: string(0x1b) string("[4~") \n

Solaris used to do this for the page-up/page-down keys, and (for instance) if you are using an old version such as Solaris 10, the advice in the xterm FAQ Why can't I use the pageup/pagedown keys? is relevant.

Further reading:

  • .Xresources or .Xdefaults? may be helpful. Most of the comments on X resources assume that you use X only locally, on a desktop. If your use is more general than that, .Xdefaults (usually with the hostname appended) is the place to start. Otherwise, .Xresources is useful.

  • Sven Maschek's XTerm app-defaults file



Related Topics



Leave a reply



Submit