You need to set the tmux window option xterm-keys
so that tmux will pass these keys through to its terminals. You probably want to put this in your ~/.tmux.conf
:
set-window-option -g xterm-keys on
Vim will usually automatically set up its handling of these keys when TERM is xterm
-something, but it skips this since TERM is screen-256color
. You can manually configure these keys in your ~/.vimrc
like this:
if &term =~ '^screen'
" tmux will send xterm-style keys when its xterm-keys option is on
execute "set <xUp>=\e[1;*A"
execute "set <xDown>=\e[1;*B"
execute "set <xRight>=\e[1;*C"
execute "set <xLeft>=\e[1;*D"
endif
At least that way you do not have to map all the various combinations.
I have seen a problem like this when using multi-byte (UTF-8 encoded) characters in the prompt, but only when tmux’s utf8
window option is turned off.
To identify such characters look for any “fancy” shapes, special symbols, or accented characters that are outside the ASCII repertoire (i.e. any Unicode codepoint beyond U+007F).
To check whether the utf8
option is active use this command in a window that is having the problem:
tmux show-option -gw utf8 \; show-option -w utf8
(or at a tmux :
prompt without the leading tmux
and without the backslash)
If it shows two values, then the second one is the active value for that window. The first (or only) value is the global value that will be used if there is no window-local value established.
If you are seeing a different value from the one established by your configuration file, then you probably need to restart your server (or iff the changes made by your configuration file are idempotent, then you can source
it: tmux source ~/.tmux.conf
).
The problem arises because (without utf8
enabled) tmux and your external terminal emulator have a different idea of how many columns are used to display each multibyte character. tmux expects a multibyte character to take up multiple columns (one for each byte), but your external emulator is probably configured to recognize it as a single UTF-8 character and thus will render it in a single column.
The problem is especially visible in a zsh prompt because zsh is careful to track where the cursor is so that is knows when the line will break and what it needs to do to properly redraw the prompt. Unfortunately, the mismatch between (non-utf8
) tmux and the (UTF-8 configured) external emulator causes tmux to report a cursor position that is several columns to the right of the expected position (one extra space for each extra byte in every multibyte character in the prompt).
Enabling utf8
in tmux fixes the problem because both tmux and the external emulator will recognize the sequences for each multibyte UTF-8 codepoint as taking up a single column. Reconfiguring your external emulator to use a single-byte encoding would also fix the discrepancy, but at the cost of not being able to properly view UTF-8 encoded data (although such a view does basically show you what tmux is “thinking” when utf8
is off).
Best Answer
Bash
This is possible, but not through inputrc. (This file belongs to the Readline library, which – although mostly known from Bash – is actually a generic text input library used by many different programs and doesn't really deal with shell-specific things like "running a command".)
Instead, this is a custom action provided by Bash itself (not available in other Readline-using programs), and has to be defined using Bash's
bind
builtin, specifically, the-x
option:Zsh
Zsh's ZLE is different, in that it is specifically part of the actual zsh shell, but it also doesn't have a straightforward "execute command" option. Instead, you have to define a custom ZLE widget, which can only call a shell function, and then bind that to a key.
Define a function that runs the thing.
When running an interactive program, its stdin must be redirected from
/dev/tty
(otherwise it'll read EOF and immediately quit), andzle -I
must be called to "invalidate" the screen contents when the program exits (otherwise the cursor will be in the wrong location). For example:Define a widget that calls the function.
If the function name is not provided, it's assumed to be the same as the widget name.
Bind a key to the widget.
It seems that
-v
selects Vi insert mode;-a
selects Vi command mode.Sources:
man zshzle