Putty 里正确设置 ALT(Meta) 键
此处感谢此帖 终端里正确设置 ALT 键和 BS 键 的作者,同时也在此作一下整理与备份。
背景
本人工作环境使用windows+putty通过ssh连接服务器,在配置vim的Auto-pairs插件的时候,无意中被<M-p>这类快捷键无效的问题难住。经过一些分析与对比,发现是ALT(Meta)键无法正确发送给终端造成的,试过很多种方法并未能解决此问题。
调查
网上找了一些文件后得知,不管你在终端下使用vim,neovim,emacs,nano或者zsh,你都会碰到使用ALT键的情况(终端下叫做Meta键),而由于历史原因,大部分终端软件的默认设置都无法正确使用ALT键。
要在终端下正确使用ALT键最简单的做法是:首先将终端软件的 “使用ALT键作为Meta键” 的功能打开,意思是如果你在终端下按下ALT+X,那么终端软件将会发送<ESC>,x两个字节过去,字节码为:0x27,0x78。
使用如下命令可以察看发送的字节码:
1
$ showkey -a
试了一下ALT+X,果然是0x27, 0x78。
各终端解决
SecureCRT和Xshell都有设置解决此类问题,如“Use ALT key as Meta key”,勾上就行。
其他终端软件里,可以按如下的方法来尝试:
Putty/MinTTY默认ALT+X就是发送<ESC>,x过去;Mac下面的iTerm2/Terminal.app需要跟XShell/SecureCRT一样设置一下;Ubuntu下面的GnomeTerminal默认也是发送<ESC>,x过去的;任意平台下面的
xterm可以配置~/.Xdefaults来设置这个行为。唯有
vim,由于历史原因,需要在你的.vimrc里加一段键盘码配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
function! Terminal_MetaMode(mode)
set ttimeout
if $TMUX != ''
set ttimeoutlen=30
elseif &ttimeoutlen > 80 || &ttimeoutlen <= 0
set ttimeoutlen=80
endif
if has('nvim') || has('gui_running')
return
endif
function! s:metacode(mode, key)
if a:mode == 0
exec "set <M-".a:key.">=\e".a:key
else
exec "set <M-".a:key.">=\e]{0}".a:key."~"
endif
endfunc
for i in range(10)
call s:metacode(a:mode, nr2char(char2nr('0') + i))
endfor
for i in range(26)
call s:metacode(a:mode, nr2char(char2nr('a') + i))
call s:metacode(a:mode, nr2char(char2nr('A') + i))
endfor
if a:mode != 0
for c in [',', '.', '/', ';', '[', ']', '{', '}']
call s:metacode(a:mode, c)
endfor
for c in ['?', ':', '-', '_']
call s:metacode(a:mode, c)
endfor
else
for c in [',', '.', '/', ';', '{', '}']
call s:metacode(a:mode, c)
endfor
for c in ['?', ':', '-', '_']
call s:metacode(a:mode, c)
endfor
endif
endfunc
call Terminal_MetaMode(0)
到此,vim中ALT组合键<M-p>或<A-p>等就可以工作了。