在 vimrc 中映射 <esc> 会导致奇怪的箭头行为
Posted
技术标签:
【中文标题】在 vimrc 中映射 <esc> 会导致奇怪的箭头行为【英文标题】:Mapping <esc> in vimrc causes bizarre arrow behaviour 【发布时间】:2012-08-10 01:34:53 【问题描述】:我是一个快乐的 VIM 用户,尽管我承认我离流利还很远。我发现了这个不错的帖子: Vim clear last search highlighting 我想如果我不必每次搜索时都敲出随机字符序列,我会成为一个更好的人。现在,我也在使用这里的 vimrc 配置:
http://amix.dk/vim/vimrc.html
我遇到的问题是,当我将行 nnoremap <esc> :noh<return><esc>
添加到它时(它似乎在我放置的地方没有什么区别)当我在命令模式下使用箭头时,我会出现尴尬的行为,即来自的字母A 到 D 出现在换行符中,我切换到插入模式。
必须有一些映射冲突,但对于我的生活,我无法弄清楚它在哪里。
编辑:从答案中可以看出 Ultimate vimrc 部分不相关,即使它是唯一的 vimrc 条目,提到的 nnoremap
命令也会导致箭头行为改变。将标题更改为内容更丰富的标题。
PS。我知道我不应该使用箭头,希望有一天我能到达那里。
【问题讨论】:
我已经看到了您在使用数字键盘时所描述的内容,但从未看到箭头光标键。 如果您真的想停止使用箭头键,只需重新映射它们以不执行任何操作 (example)。 我愿意,但这种方法对我来说仍然有点过于激进:) 【参考方案1】:映射
nnoremap <esc> :noh<return><esc>
会与所谓的“灰色键”冲突,我认为它应该只在 GVim 中使用,或者由不使用箭头等特殊键的人在终端 Vim 中使用。
据我所知(和猜测)Vim 是如何处理键的,我想说这是不可能的。要让 Vim 识别特殊键,它的所有组件都应该排成一行,所以当你按 左箭头 时,Vim 会得到以下代码序列:
但是在你的映射 Arrow Left 之后变成:
: n o h l
[ D
Vim 看到两个单独的序列并将
所以我建议您将:noh
映射到其他一些键序列(例如,映射到以<leader>
开头的一个,参见:help mapleader
;我不建议您使用F 键,使用它们和使用它们一样糟糕使用箭头键)。
【讨论】:
很高兴知道它是如何工作的,即使我不得不接受另一种解决方案。<c-l>
是一个常见的映射。 nnoremap <c-l> <c-l>:noh<cr>
我一直是map <silent> <Leader><Leader> :nohlsearch<cr>
的粉丝,但当然这都是偏好。
mouse=a也有类似问题【参考方案2】:
此解决方案保留 ESC 到 :nohlsearch
的映射。
this answer explaining why this is happening 上的评论告诉我们,根本原因是 vim 的 TermResponse 行为。这可以通过将映射包装在 TermResponse 事件的自动命令中来补偿。
这可确保在设置术语响应之后之后才发生绑定,从而防止 Esc 也将类似]>1;3201;0c
的字符串发送到vim。
将 vimrc 中的行改为:
augroup no_highlight
autocmd TermResponse * nnoremap <esc> :noh<return><esc>
augroup END
augroup 命令不是绝对必要的,但是当你重新加载你的 vimrc 而不退出 vim 时,它们可以防止多重映射。
编辑:如果您还使用 Gvim 或 Macvim 等图形 vim,则不会触发 TermResponse 事件。假设您使用单个 vimrc,您将需要一些额外的代码,例如
if has('gui_running')
nnoremap <silent> <esc> :nohlsearch<return><esc>
else
" code from above
augroup no_highlight
autocmd TermResponse * nnoremap <esc> :noh<return><esc>
augroup END
end
【讨论】:
就我而言,只需注释掉这一行: nnoremap原因已经解释得很好,但没有提到解决方案。但是有一个直的。
如果你明确告诉 Vim 有从 <esc>[
开始的键序列
:nnoremap <silent><esc> :noh<CR>
:nnoremap <esc>[ <esc>[
当单个 <esc>
被按下时,Vim 将等待一秒钟(或不同的时间,参见 :h 'timeoutlen'
)或下一个键(例如第二个 <esc>
),然后才用 :noh<CR>
替换它.
【讨论】:
:nnoremap <esc>^[ <esc>^[
这两行是否可以包含在.vimrc
文件中,如果可以,按字面意思表示还是需要修改?
半年后...@fanuch 或任何其他想知道的人:是的,这两行当然可以放在你的 .vimrc 中。只需省略起始冒号,并确保您没有在映射的右侧添加任何注释(在上面或下面是一个好主意,以提醒您为什么拥有它们或它们是什么做)。半年后,哦,好吧
这是解决这个问题和其他相关问题的天才方法。
不幸的是,它在 Vim on Git Bash(MSYS2,Windows 10)上不起作用。【参考方案4】:
问题是,当您按下箭头时,终端会发出类似<Esc>OA
的信息。支持终端的 Vim 部分似乎使用与您使用的相同的映射机制来完成工作:nmap <Esc>OA
不会告诉您任何内容,call feedkeys("\eOA")
将向上移动一行,call feedkeys("\eOA", 'n')
将在当前行之外添加字母 A。由于您的映射不可映射,因此您禁止 vim 使用 <Esc>
作为密钥的一部分。问题是您在这里需要可重新映射的映射,但只有在以lhs
开头的情况下才可以在不递归的情况下进行可重新映射的映射,但<Esc>:noh<CR>OA
不起作用。我认为下面的代码会(它使用<expr>
并具有副作用使<Esc>
成为实际rhs
的第一个字符并仍然启动:noh
),但实际上它没有:
function s:NoHlSearch()
nohlsearch
return "\e"
endfunction
nmap <expr> <Esc> <SID>NoHlSearch()
。我不知道如何解决包含 lhs
但一开始没有的非递归可重映射映射的问题。
【讨论】:
【参考方案5】:我运气不错
if $TERM =~ 'xterm'
set noek
endif
nnoremap <silent> <esc> <esc>:noh<cr>
缺点是插入模式下不能使用功能键。
:h ek
【讨论】:
不幸的是它对我做了同样的事情:( 尝试不使用 if 语句。所以只需set noek
和nnoremap <silent> <esc> <esc>:noh<cr>
对不起。这对我和我的终端都有效。我猜你有不同的键码被发送。你知道你的 $TERM 是什么吗?
@PeterRincker:根据文档(和我的测试),此选项仅适用于插入模式。你确定它对你有什么改变吗?
抱歉,这对您不起作用。 @xaizek:适用于我使用它的机器。如果我每次在终端中打开 vim 时取出 set noek
,它将以一些初始命令开始。我知道至少是2c
b/c 我有set showcmd
。以上是关于在 vimrc 中映射 <esc> 会导致奇怪的箭头行为的主要内容,如果未能解决你的问题,请参考以下文章