我在使用Esc的普通模式映射时遇到一个奇怪的问题。

如果您创建的文件escmapvimrc的内容如下:

set nocompatible
set showcmd " Doesn't affect the problem: just makes it easier to see
nnoremap <Esc> :noh<CR><esc>


然后使用以下vimrc启动vim:

vim --noplugin -u escmapvimrc


然后vim将以c命令在操作员等待模式下启动,等待进一步的输入,显示一个空文件,并带有显示:noh的命令行。

如果删除nnoremap行,则问题消失了。

如果调试并逐步执行所有操作,则会得到以下输出: br />
Entering Debug mode.  Type "cont" to continue.
/[...]/escmapvimrc
line 1: set nocompatible
>s
/[...]/escmapvimrc
line 2: set showcmd " Doesn't affect the problem: just makes it easier to see
>s
/[...]/escmapvimrc
line 3: nnoremap <Esc> :noh<CR><esc>
>s
/[...]/escmapvimrc
line 4: End of sourced file
>s
Press ENTER or type command to continue


按Enter键后,将显示Vim启动屏幕,并在下面:

Entering Debug mode.  Type "cont" to continue.
cmd: noh
>s


Vim启动屏幕随后消失,并且如上所述,您处于操作员待定模式。

发生了什么事?

编辑:行为如Vim 7.3中所述。在Vim 7.4.52中,当启动不带文件的Vim时,nmap使Vim以替换模式启动。 (但是,如果Vim 7.4.52是用文件启动的,那么它也将在执行c命令的情况下启动。)不管哪种方式,当删除nmap时,问题都会消失。

评论

我确实用vim重现了此内容,但是命令行对我来说却没有显示:noh。使用gvim进行相同操作不会显示此行为。

清除搜索突出显示的常见映射是:nnoremap :noh

另外,您可以使用/ alksdjflaskj清除搜索突出显示,这也非常快。

#1 楼

Vim在启动期间发送一些特殊的终端代码(通常包含<esc>键)来确定几件事(颜色,bs等)。如果映射了<esc>,这很可能会使返回代码的解析器感到困惑,并且可能会发生奇怪的事情。

因此,仅在正确设置所有内容(例如,通过VimEnter自动命令)后,才能使用上面的地图。

评论


好吧,只要设置了“ term”选项,它们就会被发送。通常这仅在启动期间进行,但在某些情况下可能会在运行时进行设置。

–詹姆斯
15年3月18日在20:25

在这种特殊情况下,这似乎是由may_req_ambiguous_char_width()引起的,该方法仅在启动时调用

–克里斯蒂安·布拉班德(Christian Brabandt)
15年3月18日在21:48

我打算尝试完全尝试这个(这就是为什么我不接受其他答案)。好的,但是确认它应该可以工作。

–丰富
15年3月19日在10:01

尽管VimEnter专门无法正常工作,但这已经成功了。

–丰富
2015年3月20日15:57

@shawnhcorey不。我为什么要?

–克里斯蒂安·布拉班德(Christian Brabandt)
17年2月6日在6:19

#2 楼

Linux终端使用ANSI转义序列(即以<Esc>开头的字符串)将特殊密钥发送到Vim,并且作为应用程序查询其功能的通信协议的一部分。您的映射会对此产生干扰,从而导致这些“奇怪的”行为。

因此,请勿映射<Esc>。使用另一个密钥。该问题在GVIM中不太明显,但我也不推荐在那儿使用。

评论


不幸的是,几乎从我开始使用Vim以来,我就已经有了这种映射,所以到现在为止,它已经很好地烧入了我的肌肉记忆中。不过,感谢您的解释。

–丰富
15年3月18日在14:22

为了后人的缘故,我可能应该补充一点,所描述的问题是我所知道的唯一问题,肯定是由该映射引起的,也是我可以回忆起的Vim唯一的未解决的怪异问题。

–丰富
15年3月18日在14:53

@Rich习惯使用 之类的东西有多困难?

–Random832
15年3月19日在15:28

@ Random832这是一个有趣的想法。

–丰富
15年3月20日在10:18

所有xterm程序都会这样做,因为它们模拟VT-100终端。它与Linux无关。基于BSD而非Linux的iOS也将具有模拟VT-100的xterm。

–shawnhcorey
17年2月5日在21:28

#3 楼

我尝试设置一个自动命令来稍后在启动时设置映射,但是问题仍然出现。*
我最终创建了一个自动命令,使其在我第一次进入插入模式时发生。这显然不是一个完美的解决方案,但是对我来说,它在大多数情况下都会起作用,这似乎是我能做到的最好的方法:
进一步的更新:如果您使用的Vim版本最近, @BLayer对这个重复问题的回答是一个更好的解决方案。 (它使用timers功能来延迟映射的设置,而不是延迟我的“插入”模式。)
更新:在使用下面较长的版本几年没有问题之后,我认为这可能是工程过度的原因,并且从那时起,我就使用了这个简单得多的版本,它每次进入插入模式时都会重置映射:
augroup escape_mapping
  autocmd!
  autocmd InsertEnter * call s:setupEscapeMap()
augroup END

function! s:setupEscapeMap()
  nnoremap <Esc> :noh<CR><Esc>
endfunction

每次进入插入模式时都不需要重置映射,但是
原始版本:
if !exists('g:escape_mapped')  " Only need to set the mapping up once.
  augroup escape_mapping
    autocmd!
    " Create the autocommand, to fire when Insert mode is entered
    autocmd InsertEnter * call s:setupEscapeMap()
  augroup END
endif

function! s:setupEscapeMap()
  " Actually create the mapping
  nnoremap <Esc> :noh<CR><Esc> 

  " Now the map exists, so we won't ever need the autocommand again.
  let g:escape_mapped = 1

  " Tidy up the autocommand and group
  autocmd! escape_mapping InsertEnter *
  augroup! escape_mapping
endfunction

*我尝试将其附加到各种事件上:VimEnterBufReadPostBufWinEnter甚至CursorMoved(! ),但似乎都为时过早。

评论


您是否曾经尝试过TermResponse自动命令?

–克里斯蒂安·布拉班德(Christian Brabandt)
18年7月30日在16:12

@ChristianBrabandt我现在有。这对我来说不是很好:(。

–丰富
20-2-4在9:55

我最近才了解到,并不是所有与终端相关的查询命令都会触发TermResponse,而vim只是发出了该命令。 (t_RV,t_u7,t_RF,t_RB,可能还有其他。)因此,这也可能取决于您的终端

–克里斯蒂安·布拉班德(Christian Brabandt)
20-2-4在10:32

#4 楼

试试这个:

augroup escape_mapping
  autocmd TermResponse * nnoremap <Esc> :noh<CR><esc>
augroup end


cf https://stackoverflow.com/a/16027716/400545

评论


这对我来说不是很好。之后,用它替换我的escapemapvimrc文件中的映射,当Vim启动完成时,我进入命令行模式,命令行包含以下内容::83/94/95 ^ G(即文字CTRL-G在最后)。 :help的这一点似乎表明这可能不是设置映射的最佳时间:请注意,此事件可能是在执行另一个事件的中途触发的,尤其是在文件I / O,shell命令或其他任何需要花费时间的情况下参与。

–丰富
20-2-4在9:53