Vim Tips Wiki
Register
Advertisement
Tip 1129 Printable Monobook Previous Next

created 2006 · complexity basic · author Matt Zyzik · version 6.0


Xterm, by default, sets eightBitInput to true, meaning that the eighth bit is set for meta characters (combinations with the Alt key, for instance). Not all terminals have this feature enabled by default, and therefore work differently (they send an Esc before the character key).

So for the xterm, with enables the eight bit, you can just do something like:

map <m-a> ggVG

However, with a terminal that is in 7 bit mode, you have to do this:

set <m-a>=<press Ctrl-V><press Meta-A>
map <m-a> ggVG
" the ^[ is an Esc char that comes before the 'a'
" In most default configs, ^[a may be typed by pressing first <C-v>, then <M-a>

My tip is to just set all terminals to work in 8 bit mode. Here are two examples:

Eterm -8
rxvt --meta8

See also[]

URxvt[]

Put this in your session initialization script (~/.{xsession, xinitrc}, etc.):

#!/usr/bin/env bash


# Meta Keys:
# The ECMA-35 standard prefixes control sequences containing a high
# eighth-bit with <Esc> to disambiguate from unicode input, which also
# utilizes a high eigth-bit (overlapping ranges). This necessitates
# the use of timings to differentiate and <Esc>-prefixes control
# sequence and <Esc> preceding unrelated keys. Unfortunately the
# timing mechanism is unable to differentiate between macros and
# bindings from actual control sequences as in all cases timing is
# near-zero. Furthermore programs without accurate timers break
# unexpectedly and often randomly, such as vim. Neovim can be
# configured without any breakage, as can tmux. However it is simpler
# - if willing to forego working unicode input - to simply disble
# ECMA-35 and send meta-sequences as eight-bit high.
# Unfortunately URxvt simply passes eight-bit high control-sequences
# untouched, letting higher layers assume they are the beginning of
# unicode byte-sequences. This breaks these sequences. XTerm avoids
# this ambiguity by automatically converting the eight-bit high
# control sequence to appropriate byte sequences using the current
# locale. URxvt can be harcoded to mimic this behaviour, but not in a
# locale-independent fashion. If locales change, the following
# bindings will be broken.
# Summary:
#   * Specific to the current locale
#   * Breaks UTF-8 input

read -r -d '' PyURxvtMeta8 <<-'EOF'
	#!/usr/bin/env python3
	
	import locale
	
	locale.setlocale(locale.LC_ALL, "")
	encoding = locale.getlocale()[1]
	
	# ASCII range
	for i in range(32, 128):
	    seq = "".join("\{:o}".format(j) for j in chr(i + (1<<7)).encode(encoding))
	    key = "{:#06X}".format(i)
	    print("urxvt*keysym.Meta-{}: {}".format(key, seq))
EOF

xrdb -merge <(python3 <<<"$PyURxvtMeta8")

This is only one of several possible approaches to mapping <Meta> combinations in vim using URxvt. See below for more.

Comments[]

Also, these are the settings I use in my /etc/inputrc:

set meta-flag on
set input-meta on
set convert-meta on
set output-meta on

These are so that alt keys like <m-b>, <m-f>, <m-d> will work well in shell.

Note: The above inputrc flags do not seem to work, as setting convert-meta to on prevents the user from entering in the escape sequence. Vim appears to go into visual mode when Ctrl-v is pressed. If convert-meta is set to off, then escape characters can be entered. Please expand this documentation to explain how Putty users can use meta characters correctly in Vim.

The only version that works for me (Vim 7.1 on Ubuntu 8.04 x86, connected to by Putty 0.60 on Windows XP 32bit):

Line in .vimrc to map for example "Alt-RightArrowKey" to "switch to next open file":

:map ^[<Right> :hide bn<CR>

Crucial: To get the ^[ press Ctrl-V and Ctrl-[

See :help key-notation for more key special names like "<Right>".

klaus thorn

Comment: This is also the only method that works for me in Vim 7.4. I use the following two mappings, also with Ctrl-v Ctrl-[ to produce the ^[ character.

cnoremap ^[b <S-Left>
cnoremap ^[f <S-Right>

Jack O'Connor


Using urxvt (rxvt-unicode) with --meta8 the alt key combinations gave cryptic characters (mostly with accents, like ì) as output instead of the Alt key mapping. Solution:

set termencoding=latin1

I guess the "set-8-bit" thing originates from the non-unicode version and only works for latin1. Input of special chars works as before.

sebastian

"Cryptic characters" for Alt+printable keys are not a bug, it's a known and documented behaviour. Since Vim represents the Alt key as the high bit, it cannot tell the difference between an ASCII key with Alt (let's say Alt-a, where a, lowercase-a-for-alfa, has the ASCII value 0x61) and the high-bit counterpart of that key (in this case the character with value 0xE1, which in Latin1 or UTF-8 is á i.e. small-a-acute). This may mean an easy way to type accented characters in Insert mode even if you only have a en-US QWERTY keyboard with no accents on it, but usually it means that you should refrain from using Alt+printable keys as {lhs} of an Insert- or Command-line-mode mapping if you want to be able to type accented letters (in Normal mode it's usually OK since accented letters have no default bindings in that mode... but read further). OTOH, of course, if your OS's "national settings" ($LC_CTYPE) say that your "character set" is neither Western nor Unicode, Vim will see that and do the appropriate conversion for that $LC_CTYPE (which is the right thing to do for Insert mode) and (if 'encoding' is set internally to UTF-8) the Alt-key mappings will get skewed, which is another reason to stay away from Alt+printable key combinations in Vim.
As for 'termencoding', by default it is empty, which means "use 'encoding' which is set at startup to your OS-defined locale. On Windows 'termencoding' doesn't matter because Vim always asks for the Unicode version of anything you type, but on other OSes it is crucial to save the "old" 'encoding' setting in 'termencoding' before you change 'encoding' — for instance before you set it to UTF-8 if it was initially something else. If you don't, the OS will send you characters in the unchanged locale and Vim will interpret them as UTF-8; conversely, Vim will send UTF-8 for display on the console and the OS will interpret it in your $LC_CTYPE locale — and in both cases, the result will be gibberish. For more details on this kind of stuff, see Working with Unicode. — Tonymec 17:11, March 6, 2010 (UTC)

I am using xterm and have utf8 locale. I gave up to fix Alt-mapping using vim's facilities and remaped keys I need using xterm resources. For example to map Alt+f to Ctrl+Left_Arrow and Alt+b to Ctrl+Right_arrow I added to ~/.Xresources following lines:

XTerm*VT100.translations: #override \n\
	Meta<Key>f: string("^[[1;5C") \n\
	Meta<Key>b: string("^[[1;5D")

Corresponding Urxvt settings are:

URxvt*keysym.Meta-f: \033[1;5C
URxvt*keysym.Meta-b: \033[1;5D
URxvt*keysym.Meta-0x6c1: \033[1;5C
URxvt*keysym.Meta-0x6c9: \033[1;5D

Last two lines maps same keys in cyrrilic layout. They can be detected by xev program.

Note:

  • To type "^[[1;5C" I entered insert mode, pressed Ctrl+V, then Ctrl+Left_arrow. Copypaste probably will not work.
  • Of cause, It changes every console application's reactions, not only vim's one.

sergey


I followed sergey's approach of configuring URxvt through Xdefaults because Vim's key reassignment facilities simply did not work. My Xdefaults snippet is below, cheers. ~sunaku

! emulate XTerm for proper recognition of key combinations in Vim
!URxvt.keysym.Up              : \033[A  !breaks arrow keys in Vim
!URxvt.keysym.Down            : \033[B  !breaks arrow keys in Vim
!URxvt.keysym.Right           : \033[C  !breaks arrow keys in Vim
!URxvt.keysym.Left            : \033[D  !breaks arrow keys in Vim
!URxvt.keysym.Page_Up         : \033[5~ !breaks scrolling in Rxvt
!URxvt.keysym.Page_Down       : \033[6~ !breaks scrolling in Rxvt
!URxvt.keysym.Home            : \033[H  !breaks navigation in Vim
!URxvt.keysym.End             : \033[F  !breaks navigation in Vim
URxvt.keysym.S-Up             : \033[1;2A
URxvt.keysym.S-Down           : \033[1;2B
URxvt.keysym.S-Right          : \033[1;2C
URxvt.keysym.S-Left           : \033[1;2D
!URxvt.keysym.S-Page_Up       : captured by terminal for scrolling
!URxvt.keysym.S-Page_Down     : captured by terminal for scrolling
URxvt.keysym.S-Home           : \033[1;2H
URxvt.keysym.S-End            : \033[1;2F
URxvt.keysym.M-Up             : \033[1;3A
URxvt.keysym.M-Down           : \033[1;3B
URxvt.keysym.M-Right          : \033[1;3C
URxvt.keysym.M-Left           : \033[1;3D
URxvt.keysym.M-Page_Up        : \033[5;3~
URxvt.keysym.M-Page_Down      : \033[6;3~
URxvt.keysym.M-Home           : \033[1;3H
URxvt.keysym.M-End            : \033[1;3F
URxvt.keysym.M-S-Up           : \033[1;4A
URxvt.keysym.M-S-Down         : \033[1;4B
URxvt.keysym.M-S-Right        : \033[1;4C
URxvt.keysym.M-S-Left         : \033[1;4D
!URxvt.keysym.M-S-Page_Up     : seen as Rxvt.keysym.S-Page_Up
!URxvt.keysym.M-S-Page_Down   : seen as Rxvt.keysym.S-Page_Down
URxvt.keysym.M-S-Home         : \033[1;4H
URxvt.keysym.M-S-End          : \033[1;4F
URxvt.keysym.C-Up             : \033[1;5A
URxvt.keysym.C-Down           : \033[1;5B
URxvt.keysym.C-Right          : \033[1;5C
URxvt.keysym.C-Left           : \033[1;5D
URxvt.keysym.C-Page_Up        : \033[5;5~
URxvt.keysym.C-Page_Down      : \033[6;5~
URxvt.keysym.C-Home           : \033[1;5H
URxvt.keysym.C-End            : \033[1;5F
URxvt.keysym.C-S-Up           : \033[1;6A
URxvt.keysym.C-S-Down         : \033[1;6B
URxvt.keysym.C-S-Right        : \033[1;6C
URxvt.keysym.C-S-Left         : \033[1;6D
!URxvt.keysym.C-S-Page_Up     : seen as Rxvt.keysym.S-Page_Up
!URxvt.keysym.C-S-Page_Down   : seen as Rxvt.keysym.S-Page_Down
URxvt.keysym.C-S-Home         : \033[1;6H
URxvt.keysym.C-S-End          : \033[1;6F
URxvt.keysym.M-C-Up           : \033[1;7A
URxvt.keysym.M-C-Down         : \033[1;7B
URxvt.keysym.M-C-Right        : \033[1;7C
URxvt.keysym.M-C-Left         : \033[1;7D
URxvt.keysym.M-C-Page_Up      : \033[5;7~
URxvt.keysym.M-C-Page_Down    : \033[6;7~
URxvt.keysym.M-C-Home         : \033[1;7H
URxvt.keysym.M-C-End          : \033[1;7F
URxvt.keysym.M-C-S-Up         : \033[1;8A
URxvt.keysym.M-C-S-Down       : \033[1;8B
URxvt.keysym.M-C-S-Right      : \033[1;8C
URxvt.keysym.M-C-S-Left       : \033[1;8D
!URxvt.keysym.M-C-S-Page_Up   : seen as Rxvt.keysym.S-Page_Up
!URxvt.keysym.M-C-S-Page_Down : seen as Rxvt.keysym.S-Page_Down
URxvt.keysym.M-C-S-Home       : \033[1;8H
URxvt.keysym.M-C-S-End        : \033[1;8F

Mapping meta key (<M-Down>, <M-Up>, etc) within tmux in vim, I added to ~/.tmux.conf following lines:

set -g default-terminal "xterm"
set -g xterm-keys on

If sunaku's URxvt config works in a new terminal but stops working when you start screen, remember to try the tips from GNU_Screen_integration.

Advertisement