最好不要映射ESC。如果你要截获退出输入的话,考虑使用InsertLeave事件。
2009/10/16 yetist <yet...@gmail.com>:
--
Wu Yongwei
URL: http://wyw.dcweb.cn/
---- 看不大明白,请大侠再解释一下。哪种模式下输入 cat,cat 是什么命令,插入这些字符是 Vim 的 bug 么?
---- 我遇到了同样的问题。我觉得 Vim 补全模式的操作太复杂不够直观,所以用 inoremap 加上按键映射函数,在 Vim 补全模式的
基础上做了个自定义补全模式。做的过分了些,把下面这些键都给映射了:
inoremap <expr> ^[ g:ImodeMap_Escape()
inoremap <expr> ^M g:ImodeMap_Enter()
inoremap <expr> <Space> g:ImodeMap_Space()
inoremap <expr> <Tab> g:ImodeMap_Tab()
inoremap <expr> i g:ImodeMap_i()
inoremap <expr> k g:ImodeMap_k()
inoremap <expr> j g:ImodeMap_j()
inoremap <expr> l g:ImodeMap_l()
inoremap <expr> ^H g:ImodeMap_Ctrl_h()
inoremap <expr> ^J g:ImodeMap_Ctrl_j()
inoremap <expr> ^K g:ImodeMap_Ctrl_k()
inoremap <expr> ^L g:ImodeMap_Ctrl_l()
inoremap <expr> ^F pumvisible() ? "<Pagedown>" : "^F"
inoremap <expr> ^B pumvisible() ? "<Pageup>" : "^B"
---- 然后,用下面这些数据结构用来记录 自定义补全模式 的状态
"============================================================
"======= 当前所处的 Insert 模式下的自定义子模式
"======= 'completion' 代表自定义补全模式
"============================================================
let g:crtUserMode= 'none'
"============================================================
"======= 这部分是专属于 自定义补全模式 的数据结构
"============================================================
let g:myCplData= {}
" Vim 的 15 种补全模式分成四组,method A~D。这个变量记录当前在哪一组。
let g:myCplData.crtMethod= 'methodC'
" 下面两组子数据结构是相对应的,前一个用来在后一个内部寻址。
let g:myCplData.crtModeIdx= {}
let g:myCplData.crtModeIdx.methodA= 0
let g:myCplData.crtModeIdx.methodB= 0
let g:myCplData.crtModeIdx.methodC= 0
let g:myCplData.crtModeIdx.methodD= 0
" 这些是 15 种补全模式的缩略代号
let g:myCplData.modeString= {}
let g:myCplData.modeString.methodA= 'KHS'
let g:myCplData.modeString.methodB= 'FVTID'
let g:myCplData.modeString.methodC= 'pnPNL'
let g:myCplData.modeString.methodD= 'UO'
---- 下面是两个按键映射函数的例子:
---- ^K 按键的作用是进入第三个模式组群(methodC,一共有 'pnPNL' 五种补全模式),它的按键映射函数是这样写的:
" map 到 ^K 上
function! g:ImodeMap_Ctrl_k()
" 无论当前是否处于补全模式,都执行相同操作
if (g:crtUserMode =~ 'none') || (g:crtUserMode =~
'completion')
let g:crtUserMode= 'completion'
" 总是从该 method 的第一个 mode 进入,而不是最近一次使用的 mode。
let g:myCplData.crtMethod= 'methodC'
let g:myCplData.crtModeIdx.methodC= 0
" 临时变量,当前的 Vim 补全模式
let crtCplMode=
\ g:myCplData.modeString.methodC[g:myCplData.crtModeIdx.methodC]
return (crtCplMode == 'p') ? "^E^P" :
\ (crtCplMode == 'n') ? "^E^N" :
\ (crtCplMode == 'P') ? "^E^X^P" :
\ (crtCplMode == 'N') ? "^E^X^N" :
\ (crtCplMode == 'L') ? "^E^X^L" :
\ (crtCplMode == 'T') ? "^E^X^]" :
\ (crtCplMode == 'I') ? "^E^X^I" :
\ (crtCplMode == 'D') ? "^E^X^D" :
\ (crtCplMode == 'V') ? "^E^X^V" :
\ (crtCplMode == 'F') ? "^E^X^F" :
\ (crtCplMode == 'U') ? "^E^X^U" :
\ (crtCplMode == 'O') ? "^E^X^O" :
\ (crtCplMode == 'K') ? "^E^X^K" :
\ (crtCplMode == 'H') ? "^E^X^T" :
\ (crtCplMode == 'S') ? "^E^X^S" :
\ "^R=g:ImodeMessage('error! Completion Mode
unrecognizable')^M"
else
return "^R=g:ImodeMessage('No! What mode are you in right
now?')^M"
endif
endfunction
---- <Esc> 按键的作用是:第一次按退出 自定义补全模式,回到 Insert 模式。第二次按退出 Insert 模式,回到
Normal 模式。它的按键映射函数是这样的:
" map 到 <Esc> 上
function! g:ImodeMap_Escape()
if g:crtUserMode =~ 'none'
return "^["
elseif g:crtUserMode =~ 'completion'
" 回归 Insert 模式前,在自定义补全模式下通过 match 命令设置的任何高亮都要取消。
match none
let g:crtUserMode= 'none'
return "^E"
else
return "^R=g:ImodeMessage('No! What mode are you in right
now ?')^M"
endif
endfunction
---- 其他的按键映射函数写法类似。这些东西前两天刚写好,还没来得及作许多测试。初步用下来,大部分情况下操作都跟设想的一样,比较方便。但是今
天遇到一回,症状跟上面所说的很相似,就是按这些键的时候,会输入些莫名其妙的字符,不知是从哪来的。
---- 比如:我的程序里已经有了这样一句:
inoremap <expr> \\ g:ImodeMapShowLineRange()
然后下面在定义这个函数的时候,假设已经输入了以下部分:
function! g:ImodeMapShowL
然后按 ^K 来进行补全,但是结果却是插入了一个看上去没有任何关联的字符,比如:
function! g:ImodeMapShowLt
同时消息栏会说找不到匹配。而诡异的是,如果把这行 copy 到另外一处再进行同样操作,就又正常了。
---- 我被难到了,刚好这个贴子有讲到类似的问题,希望能找到答案。谢谢。
$ cat
^[[A^[[B^[[D^[[C
也就是说,在应用程序里,你按上箭头,得到的键码是:ESC,[,A。注意里面包含了ESC(Ctrl-[)。
2009/10/17 蓝色基因 <bluege...@gmail.com>:
--
'iminsert' 'imi' number (default 0, 2 when an input method is supported)
local to buffer
{not in Vi}
Specifies whether :lmap or an Input Method (IM) is to be used in
Insert mode. Valid values:
0 :lmap is off and IM is off
1 :lmap is ON and IM is off
2 :lmap is off and IM is ON
2 is available only when compiled with the |+multi_byte_ime|, |+xim|
or |global-ime|.
⋯⋯
最后一句话说明,Linux下你至少需要把multi_byte_ime和xim两个特性编译进去。
2009/10/16 闲耘 <hoto...@gmail.com>:
> Windows
> :h IME
> (Windows IME 支持) *multibyte-ime* *IME*
> {仅对 Windows GUI 有效,而且编译时需加入 |+multi_byte_ime| 特性}
> ...
--