如何调试映射?


64

我在这里看到很多问题,其中用户的映射不起作用,并且在大多数情况下,原因非常相似。

我建议将此问题作为此类问题的参考,以给出调试映射的完整过程。如果用户遇到映射问题,则可以将其重定向到此处以消除最常见的问题。

当然,仍然会有一些特殊情况,这将需要专门的问题,在此不再赘述。

Answers:


88

您的映射未完成应做的工作或行为与预期不同,请按照以下步骤进行故障排除:

检查密钥是否有效地映射到它应该做什么

Vim提供了一个命令:map。默认情况下(未提供任何参数时),该命令将显示当前创建的所有映射。这是命令结果的示例:

<code>:map </ code>的结果

一如既往,文档是您的朋友: :h map-listing

您可以在第一列中看到映射的模式(n正常模式, v视觉模式等),第二列显示映射的键,最后一列显示映射到的键。请注意,在映射的动作可能会出现一些其他字符之前,了解它们非常重要:

  • * 表示它不可重映射(即它不是递归映射,请参见此know when to use nore答案的后面)
  • & 指示仅脚本本地映射是可重映射的
  • @ 指示本地缓冲区映射

在寻求有关映射的帮助时,添加此信息是一件好事,因为它可以帮助其他人了解您的映射行为。

这是可能的提示限制与的姐妹的命令的特定模式:map,例如:vmap:nmap:omap等。

现在,将搜索限制为有问题的映射,您可以将要调试的键序列作为命令的参数传递,如下所示:

:map j
:map <Leader>m
:map <F5>

请注意,<Leader>密钥将被列表中的实际值替换。

如果命令的结果表明您的密钥已正确映射,则可能意味着问题不是出自Vim,而是出自您的终端或桌面环境。请参阅检查您的映射是否确实被Vim拦截的部分

如果命令结果显示您的键未正确映射,请参见以下部分。

检查什么覆盖了您的映射

:map命令的另一个方便用法是将其与结合使用verbose:这将提示最后一个修改了映射的文件。

例如,请参见以下两个屏幕截图,它们是以下结果的:verbose map:第一个是my修改的映射.vimrc,第二个是插件创建的映射:

来自vimrc的映射集

来自插件的映射集

现在,如果您看到另一个脚本修改了映射,则必须查看是否可以删除它或修改其行为。(请注意,某些插件提供变量来启用/禁用其映射,但是不幸的是,并非所有插件都可以这样做)

如果最后一个更改映射的文件是your .vimrc,请确保没有其他行也为同一键定义了映射。该.vimrc文件将愉快地使用文件中的最后一个类型覆盖所有映射。

检查您的映射是否确实被Vim拦截

几种情况可能表明Vim没有拦截您的密钥:

  • 该命令:map显示您的键已正确映射,但按不执行任何操作。
  • 您的映射可在gVim(GUI)上运行,但在终端Vim中不执行任何操作
  • 您的映射可在已定义的终端模拟器上运行,而不能在其他终端模拟器上运行
  • 您的映射可在已定义的操作系统上运行,但不能在另一个操作系统上运行。

它可能是由以下两个原因之一引起的:

  • 在Vim之前有一些东西截获了它:它可以是不同的应用程序:您的OS,您的桌面环境,您的终端仿真器,Tmux(如果使用的话)...

    要解决此问题,您应该:

    • .tmux.conf如果您使用tmux,请尝试暂时删除您的
    • 请参阅您的终端或桌面环境的文档。

    您还可以引用姐妹站点,例如超级用户Unix和LinuxaskUbuntu等。

    如果这是问题所在,那么您有两种解决方案:要么花费(大量)时间来更改导致问题的应用程序的行为,要么找到要映射的另一个组合键,而该组合不会被其他应用程序拦截。

  • 您的终端仿真器无法处理您要映射的键组合:终端仿真器的实现方式不同,其中一些无法处理某些特定的键组合。(他们之所以不能这样做的原因不在此问题的范围内,有关更多详细信息,请参阅他们的文档或前面提到的姐妹网站)。

    在这种情况下,您没有很多解决方案:要么更改您的密钥,再由终端正确处理,要么更改终端仿真器。

检查常见的陷阱

映射中的一些问题经常发生,并且主要与vimscript语法有关。如果您的映射有意外行为,请记住检查以下几点:

  • 不要在与地图相同的行上添加评论,而应在上面的行上添加评论。例:

    不要那样做:

    inoremap ii <esc>    " ii to go back into normal mode
    

    Vim会将空格,"和注释视为映射的一部分,这将导致意外行为。

    而是这样做:

    " ii to go back into normal mode
    inoremap ii <esc>
    

    这更容易阅读,并且不会弄乱您的映射。

  • 不要使用来传递命令|。例:

    不要那样做:

    nnoremap <Leader>x :w | !% python -m json.tools
    

    Vim会将管道|视为命令终止:当您找到源时.vimrcnnoremap <Leader>x :w将创建映射,然后!% python -m json.tools将执行外部命令。

    而是这样做:

    nnoremap <Leader>x :w <bar> !% python -m json.tools
    

    请参阅有关的说明<bar>

  • 知道何时使用nore总是

    LearnVimscriptTheHardWay解释清楚漂亮:不要使用mapnmapvmap等...总是喜欢诺雷版本:noremapnnoremapvnoremap,等...为什么呢?nore代表non-recursive映射,这意味着即使您重新映射,映射的右侧也将被视为内置功能。例:

    假设您要映射>以删除行并-增加行的缩进量。如果您不使用非递归映射,则可以这样做:

    不要那样做

    nmap > dd
    nmap - >
    

    当您点击时,>您的行将被删除,这很好。但是,当您点击时,-行也会被删除而不是缩进。为什么?因为Vim理解“我收到了-我应该翻译成的热门歌曲,而我>反过来又应该翻译成dd”。

    而是那样做

    nnoremap > dd
    nnoremap - >
    

    这样Vim会翻译-成,>并且不会因为导致尝试进行任何其他翻译nore

    在某些情况下,您需要使用递归映射表单,但是编辑注释 “总是”可能是一个夸张的答案,但这并不是很常见。为了澄清,我将从这个答案中引用@romainl :

    仅当您打算在映射中使用任何其他映射时,才使用递归映射。如果不使用,则使用非递归映射。

  • 请记住,一些关键的组合是等效:由于所产生的一些关键组合将通过的Vim被解释为另一个关键十六进制代码。例如

    • <C-h> 相当于 <backspace>
    • <C-j><enter>
    • 在法国的键盘<M-a>是一样的á,并与所有的也是一样 <m-的映射。正如@LucHermitte在评论中指出的那样,使用此类映射(如vim-latex)的插件存在问题。
    • <C-S-a>等价于 <C-a>。无法将Ctrl +大写字母与Ctrl +小写字母分开映射,这是终端发送ASCII码的方式。

    如果您的映射似乎影响另一个键,请尝试使用另一个lhs组合,如果这样可以解决问题,请检查将哪些十六进制代码发送到Vim。

  • 检查领导者是否正确定义:如果涉及的映射<leader>不起作用,并且您使用命令更改了领导者mapleader,请检查领导者的定义是否在映射定义之前完成。否则,Vim会尝试使用您认为不是的键来创建映射。另外,如果您想使用空格键作为领导者(这是最新的),请确保使用正确的符号:let mapleader = "\<Space>"

您的映射仍然不起作用?

如果您已完成此答案的所有步骤,但映射仍无法按您希望的方式工作,则可能需要在此站点上寻求帮助。

为了帮助人们帮助您,您记得提供一些关键信息,例如:

  • 您用来定义映射的命令。
  • 您期望映射做什么。
  • 问题的精确描述:

    对于尝试帮助您的人来说,“它不起作用”不会真正有用。如果映射没有执行任何操作,或者其行为与预期不同,则应进行精确调整。

  • 还要指出您实际上已经按照此处描述的步骤进行操作,并且获得的结果:map:verbose map

所有这些将为您和网站用户节省大量时间。


一个有用的命令: :unmap

有时在不退出Vim来帮助调试其行为的情况下重置映射可能很有用。

为此,您可以使用该命令:unmap <key>删除将分配给<key>“正常”,“可视”和“运行中”模式的映射。:iunmap将删除插入模式的映射。有关其他模式,请参见:help :unmap


参考文献

映射的绝佳入门:learningvimscriptthehardway(以及Vim的许多其他方面)

商务部::h mapping:h :map

Vim常见问题解答的第20节是关于映射的,其中包含一些有趣的问题:

还有一个好处:有关在映射中查找要使用哪些键的最佳做法的问题


2
按照主持人的建议与其他用户分享我的经验。并且因为I see a lot of questions on here where a user has a mapping which doesn't work and most of the time the reasons are pretty similar正如我在问题的第一行中所说的那样,所以收集这些原因应该可以减少关于映射的重复问题的数量。
statox

1
vim-latex和法语键盘反复出现的问题:<m-i>évim相同,并且所有meta + key都相同:它们与不同的变音符号相关。
卢克·赫米特

1
当我们使用:map {sequence}->来请求缓冲区本地映射时,知道如何读取缓冲区本地映射也很重要*
卢克·赫米特

2
有时我们真的想调试发生的事情。通常,当映射调用插头映射或名称无法记住的函数或具有复杂参数的函数时。在这种情况下,我们可以执行::debug normal {keysequence}(无任何爆炸),或:debug i{keysequence}插入模式映射等。如果密钥序列包含了诸如特殊键的东西(<cr><left><c-x><m-i><leader>...)。然后,我们需要使用execute +双引号+反斜杠-> :debug execute "normal \<leader>\<cr>Z"
卢克·赫米特

2
关于元序列,这是FAQ的古老观点,因为vim-latex确实选择使用<m-i>。大多数用户不使用元键,因为他们非常注重在终端上运行Vim -在此不能简单地使用元键。我们需要使用gvim或macvim来注意该问题。
卢克·赫米特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.