Vim:为啥 noremap 在插入模式下不起作用?

Posted

技术标签:

【中文标题】Vim:为啥 noremap 在插入模式下不起作用?【英文标题】:Vim: Why does noremap not work in insert mode?Vim:为什么 noremap 在插入模式下不起作用? 【发布时间】:2012-10-08 19:47:21 【问题描述】:

考虑使用解除箭头键的绑定

 noremap <Left>  <NOP>
 noremap <Right> <NOP>
 noremap <Up>    <NOP>
 noremap <Down>  <NOP>

这在正常模式下工作,但在插入模式下工作:仍然可以使用箭头键导航。作为对策,必须包括

 inoremap <Left>  <NOP>
 inoremap <Right> <NOP>
 inoremap <Up>    <NOP>
 inoremap <Down>  <NOP>

但这对我来说真的没有意义,因为我假设mapnoremap 应该在所有模式下工作,而在前面加上n/v/x/s/o/i/l/c 指定映射只在该特定模式下工作。这是有原因的吗?

【问题讨论】:

【参考方案1】:
:help map-overview

map(和 noremap)用于正常、可视、选择和操作员挂起模式。

【讨论】:

啊!感谢当然是有道理的。 I had based my question off the answer located here, but I'll edit it 所以没有人像我一样得到错误的想法。 没有包罗万象的模态图,而不是同时发布mapmap!,是否有原因? @nil:原因可能是您的禁用功能示例是相同映射在所有模式下都具有相同效果的极少数情况之一。 我从map-overview 通读到小节的末尾,这有点困难,却发现下一节是1.4 LISTING MAPPINGS (:help map-listing),实际上提供了比map-overview 更好的概览!【参考方案2】:

为什么没有包罗万象的模态地图,而不是同时发布地图和地图!

这很容易解释:在插入模式映射中,Vim 不会自动切换到正常模式(您可能希望保持插入模式,尽管文本翻译通常通过:iabb 完成,而不是通过:imap),所以适用的命令集是完全不同的。例如,在普通模式下Ctrl-U向上滚动,但在插入模式下它会删除行中输入的字符!

&lt;C-O&gt; 这样的前缀会暂时从插入模式切换到普通模式。实际上,甚至经常需要为命令行模式定义不同的前缀,如下例所示:

noremap <C-Tab> :<C-U>tabnext<CR>
inoremap <C-Tab> <C-O>:tabnext<CR>
cnoremap <C-Tab> <C-C>:tabnext<CR>

因此,在定义映射时,请始终考虑在哪些模式下需要它们以及是否需要重新映射(:nmap:noremap,更喜欢后者)。

【讨论】:

目前还不清楚您的块引用“为什么没有包罗万象的模态地图,而不是同时发布地图和地图!”在 Paul Ruane 的回答中引用了 nil's comment 的一部分。 所以显然我应该评论这个答案而不是修复它。尽管 nil 的原始句子在语法上是正确的,但 nil 评论中的引文阅读不正确。 &lt;C-O&gt;&lt;C-C&gt; 不是前缀;他们不必在一开始。 nmap 不是noremap 的递归等价物,因此可以通过将nmap 更改为map 或说“*map*noremap”来改进它。我在编辑中修复了这些问题,但被拒绝了。我似乎总是因为编辑太少或编辑太多而受到指责。我赢不了版主。 SE太*官僚了。【参考方案3】:

与您的预期相反,noremapmap 实际上并不适用于所有模式。基于来自:help map-listing 的非常有用的总结,这里列出了可以作为mapnoremapunmapmapclear 的前缀(或在! 的情况下为后缀)的字符列表,以及它们适用的模式:

(无)– 正常、可视、选择和操作员待定 n – 正常 v – 视觉和选择 x – 视觉 s – 选择 o – 运营商待定 ! – 插入和命令行 i - 插入 c – 命令行 l – ":lmap" 用于插入、命令行和 Lang-Arg 的映射

因此,noremap 映射在插入或命令行模式下无效,并且不加考虑,在可视、选择或运算符挂起模式下也可能无法正常工作。

但是,映射可以调整为在不同的模式下工作,只需更改模式并返回映射即可。例如,发出命令行命令但仅在正常模式下工作的noremap 映射可以调整为也可以在其他模式下工作,如下例所示:

noremap <C-Tab> :<C-U>set list!<CR>
inoremap <C-Tab> <C-O>:set list!<CR>
cnoremap <C-Tab> <C-C>:set list!<CR>:<Up>

noremap 适用于 Normal、Visual、Select 和 Operator-pending 模式,:&lt;C-U&gt; 进入命令行模式然后清除当前行以防 Vim 插入范围; inoremap 适用于插入模式,&lt;C-O&gt;: 暂时退出普通模式,然后进入命令行模式;而cnoremap适用于命令行模式,对于该模式&lt;C-C&gt;:退出并重新进入命令行模式以清除该行,但与&lt;C-U&gt;不同,将其保留在命令历史记录中,以便:&lt;Up&gt;可以带上它返回。

这三个映射涵盖了所有六种模式。 (显然 'Lang-Arg' 不是一种模式。)在某些极端情况下它不起作用,但也有一些情况下它在我认为它不会起作用的情况下起作用,而我没有不明白为什么。此外,大多数模式都会丢失一些小东西,比如选择和待处理的操作符,即使映射的命令不会丢失这些东西。例如,在插入模式下,我不明白为什么我给出的示例需要将当前编辑分解为撤消/重做历史中的单独更改(尝试输入i123&lt;C-O&gt;&lt;Esc&gt;456&lt;Esc&gt;u)。老实说,使用键映射以这种方式运行命令对我来说似乎有点 hack,但我不知道其他方式。

【讨论】:

以上是关于Vim:为啥 noremap 在插入模式下不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥消息处理程序在调试模式下不起作用?

为啥 SMS Retriever API 在发布模式下不起作用?

为啥 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);在横向模式下不起作用?

为啥 selectAnnotation 在这种情况下不起作用?

为啥 DISTINCT 在这种情况下不起作用? (SQL)

为啥这个 if 语句在这种情况下不起作用? [关闭]