首先祝大家新年快乐!
一直都感觉Vim下快捷键不够用,于是在某一天,我开始使用Alt开头的组合键,然后发现了问题——
在很多终端中,Alt 组合键发送的是 Esc 前缀键码,而图形界面中则是置位最高位。举例来说,Alt-x在图形界面下向Vim发送的是ø
(在Vim插入模式下使用Ctrl-V Alt-x可以看到),其编码为0xf1
,而x的编码为0x78
,区别在于前者二进制编码的最高位是 1,而后者是 0。
而在gnome-terminal、konsole中则是另外一番景象。Alt-x和快速地按Esc x的效果是一样的,仅有xterm 和 rxvt 等终端可选地支持像图形界面的那样处理(参见Vim手册:help :map-alt-keys)。而且,使用置位最高位的终端将导致shell中的Alt-f之类的键绑定失效。
Emacs能处理这种不一致,但Vim不能,于是我一直是使用脚本,使得在终端下和图形界面下使用不同的键绑定。这样图形界面下没什么问题,但终端下比较郁闷:因为映射了Esc开头的键,而Esc是用于回到普通模式的,于是每次按Esc想退回到普通模式时都得等一秒('timeoutlen的值)。这个值又不能设小,不然\ww这种需要多次按键的映射就难用了。
前些天,偶然在帮助文档里看到了这个:
*:set-termcap* *E522* 需要 {option} 的地方,可以使用 "t_xx" 形式来设置终端选项。这些选项覆盖相应的 termcap 值。设置后,可以用于映射。如果 "xx" 包含特殊字符,须用 <t_xx> 形式: > :set <t_#4>=^[Ot 也可用来翻译普通键的特殊键码。例如,如果 Alt-b 产生 <esc>b,可用: > :set <m-b>=^[b (这里 ^[ 是真正的 <esc>,用 CTRL-V <esc> 来输入) 这个方法优于映射之处在于它能适用于所有情况。
也就是说,可以在终端下把Alt组合键都设置到Esc开头的键码,这样一是不用每次设置键映射时设置两个,更重要的是,其本质变了:这样的设置不是键映射,而是指定键码!这样会使用'ttimeoutlen'的值来等待后续键码,和映射无关了,我完全可以把它设置得很小。于是写出新的脚本:
1 " escalt.vim 控制台下让用 <M-x> 也可用 2 " Author: lilydjwg <lilydjwgATgmail.com> 3 " Last Change: 2010年12月15日 4 " ---------------------------------------------------------- 5 " Load Once: 6 if &cp || exists("g:loaded_escalt") || has("gui_running") 7 finish 8 endif 9 let s:keepcpo = &cpo 10 let g:loaded_escalt = 1 11 set cpo&vim 12 " ---------------------------------------------------------- 13 " Functions: 14 function Escalt_console() 15 for i in range(65, 90) + range(97, 122) 16 exe "set <M-".nr2char(i).">=\<Esc>".nr2char(i) 17 endfor 18 set ttimeoutlen=50 19 if &term =~ 'xterm' 20 set <F1>=^[OP 21 set <F2>=^[OQ 22 set <F3>=^[OR 23 set <F4>=^[OS 24 set <Home>=^[OH 25 set <End>=^[OF 26 endif 27 for i in ["", "c", "i", "x"] 28 exe i . "map Ï1;2P <S-F1>" 29 exe i . "map Ï1;2Q <S-F2>" 30 exe i . "map Ï1;2R <S-F3>" 31 exe i . "map Ï1;2S <S-F4>" 32 endfor 33 endfunction 34 " ---------------------------------------------------------- 35 " Call Functions: 36 call Escalt_console() 37 " ---------------------------------------------------------- 38 " Restoration And Modelines: 39 let &cpo= s:keepcpo 40 unlet s:keepcpo 41 " vim:fdm=expr:fde=getline(v\:lnum-1)=~'\\v"\\s*-{20,}'?'>1'\:1
注意到其中对于F1到F4等键进行了特殊的设置。没办法,这几个键特殊,这样设置我觉得是最优的解了。设置'ttybuiltin'也可以,但是经过一些时间的试用后发现有副作用,具体是什么我忘记了。
PS: SyntaxHighlighter 不支持 Vimscript,还好 Vim 有TOhtml
命令。
最新脚本在 GitHub 有。直接复制上面高亮过的代码是不行的。