Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Zsh in Emacs edit mode comes with the default key binding ALT + Backspace to delete a word on the right side of the cursor and ALT + D to delete a word on the left side. I would like to add the latter function to ALT + DEL additionally.

I tried to use the terminfo database to set the escape sequence for the key combination for every $TERM correctly. In man terminfo I read about kDC3 being the Capname which I probably need to use for ALT + DEL.

I added the following line to my ~/.zshrc:

bindkey -e `tput kDC3` kill-word

This works nicely when I connect to my machine directly through SSH ($TERM is xterm). But when I start Zsh inside a Tmux-session ($TERM is screen) I get the following error message:

tput: unknown terminfo capability 'kDC3'

Could that really mean that it's impossible to bind anything to ALT + DEL in Tmux? Or am I just doing something wrong? Maybe kDC3 is not the correct sequence?

I'm running Debian Wheezy Beta 4 x86_64.

share|improve this question
up vote 4 down vote accepted

The first problem is that your terminfo entry for screen does not define a kDC3 capability; this is probably typical. You can either add this capability to your own custom screen entry, or you can “hard code” the sequences in your bindkey commands.


Adding the capabilities may help other programs know about the keys, but it decentralizes your configuration (it would be easy to forget about this customization when you manually replicate your configuration to a new machine or user account). You can extract the appropriate entries with infocmp and build a new entry with tic:

{ infocmp -xT screen ; infocmp -x1T xterm | grep -E '^\tkDC[3-8]?=' ; } >/tmp/s
tic -x /tmp/s

If you run tic as a user that has write access to your terminfo directory (e.g. /usr/share/terminfo), then the new entry will be placed there (probably overwriting the original entry); otherwise, it will be placed under ~/.terminfo (or TERMINFO, if you have that environment variable set).

For completeness, you may want to use (UP|DN|RIT|LFT|PRV|NXT|HOM|END|IC|DC) instead of DC in the grep pattern to capture the modified versions of Up, Down, Right, Left, PageUp, PageDown, Home, End, Insert, and Delete.


If you dislike the configuration decentralization caused by customizing your terminfo entry, then you can “hard code” the value instead. To make it a bit better, you can check for kDC3 first:

bindkey -e ${$(tput kDC3 2>/dev/null):-'\e[3;3~'} kill-word

To restrict this “hard coding” to just screen-based TERM values:

altdel=$(tput kDC3 2>/dev/null)
[[ -z $altdel && $TERM == screen(|-*) ]] && altdel='\e[3;3~'
[[ -n $altdel ]] && bindkey -e $altdel kill-word
unset altdel

This will work as long as your terminal emulator (stack) ends up generating the xterm-style sequence for the modified key.


Once to have a binding, you will still need to turn on the xterm-keys option in tmux so that it will generate the xterm-style sequences for keys passed into its panes. E.g. in your ~/.tmux.conf:

set-option -wg xterm-keys on
share|improve this answer
    
Thanks. Is there a plausible reason for xterm-keys not being enabled by default and the capability not being setup by default? – aef Dec 7 '12 at 18:42
    
I think they are related. The screen terminfo entry documents the codes the screen program understands and generates; I do not think that screen understands, nor generates the xterm-style codes (though it does appear to pass them through), so they are not part of the screen terminfo entry. The xterm-keys option represents an extension to the basic screen capabilities (that tmux advertises by using TERM=screen), so it is off-by-default (maybe it could be on-by-default when (e.g.) TERM=tmux, if tmux ever decides to fork its own terminfo entry). – Chris Johnsen Dec 7 '12 at 19:18

It depends:

  • ncurses supports extended (user-definable) terminal capabilities.
  • kDC3 is an extended terminal capability.
  • None of tmux, zsh or emacs know anything at all about kDC3.
  • although tmux has kDC3 in a table, it does not call use_extended_names to enable the feature.
  • ncurses tput would know about kDC3, if it is defined in the current terminal description.

The screen program (which tmux imitates) also knows nothing about kDC3. It is a termcap application, and (for itself) pays attention only to 2-character names. However, screen has a feature which addresses the question directly: in the manual (16.1 Choosing the termcap entry for a window) it tells how it chooses the setting for TERM inside the screen session:

When screen tries to figure out a terminal name for itself, it first looks for an entry named screen.term, where term is the contents of your $TERM variable. If no such entry exists, screen tries screen (or screen-w, if the terminal is wide (132 cols or more)). If even this entry cannot be found, vt100 is used as a substitute.

The idea is that if you have a terminal which doesn't support an important feature (e.g. delete char or clear to EOS) you can build a new termcap/terminfo entry for screen (named screen.dumbterm) in which this capability has been disabled. If this entry is installed on your machines you are able to do a rlogin and still keep the correct termcap/terminfo entry. The terminal name is put in the $TERM variable of all new windows. screen also sets the $TERMCAP variable reflecting the capabilities of the virtual terminal emulated. Furthermore, the variable $WINDOW is set to the window number of each window.

ncurses' terminal database exploits this feature to provide the most common variants of screen with xterm and other terminals which are similar but have different function keys, such as konsole, vte (e.g., gnome-terminal), rxvt. Except for rxvt, the others still set TERM to xterm.

In a default configuration, you may not have those terminal descriptions available (and screen would blithely continue to set TERM=screen and provoke users into bug reports much like this question). Debian, for instance, in its ncurses-base terminfo package provides only a minimal set of terminal descriptions. You would have to install ncurses-term to get the complete terminal database.

The terminal description for screen, of course, does not describe any extended function keys. It does include these extended capabilities, by the way:

AX, G0, E0=\E(B, S0=\E(%p1%c,

but none of these applications (except tput) does anything with them.

tmux complicates this by not completely matching the behavior of screen: it does not check for the alternate names which ncurses provides. Without explaining why, its manual page says

The TERM environment variable must be set to “screen” for all programs running inside tmux. New windows will automatically have “TERM=screen” added to their environment, but care must be taken not to reset this in shell start-up files.

The likely reason is that the developer did not want to guarantee the behavior (for screen updates) of terminal capabilities not found in screen. Function keys are a different matter. You can modify the terminal description as suggested, though that has proven to be moe of a problem than a solution:

The suggested script, by the way, does not appear to work. Showing a corrected script would be pointless, given all of the background for this problem. Rather than piecemeal tweaks to the terminal database, I would be inclined to have a case statement in the shell initialization that checked for TERM set to screen, and check if there is a better alternative already in the terminal database. Doing that correctly is made more complicated by developers' refusal to set TERM according to their terminal's capabilities, but you can get most of the way there by looking at the COLORTERM environment variable.

For your amusement:

share|improve this answer

From what ive seen of the internals of tmux it doesnt seem to pay much attention to terminfo settings and the like. For example if you turn on xterm mode:

set-window-option -g xterm-keys on

the actual escape sequences corresponding to various keys are hardcoded into the program and are probably different from what infocmp xterm would tell you.

On top of this tmux ignores everything above F20 because it only has a certain set of keys that it will recognise hardcoded in. So something like this

set-option -g terminal-overrides "screen:kf34=\033[21;5~"

or

tmux bind-key -t emacs-copy F34 page-up

isnt going to accomplish anything, no matter what xterm or tput is spitting out. At least thats the way it seems to be at present.

I'm not sure if the same issue is effecting something like kDC3 but it seems quite possible.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.