在进入普通模式或ESC映射时触发光标定位和选择

时间:2014-03-15 15:17:50

标签: python vim vim-plugin

任何人都知道如何在转到Normal时从python触发光标定位和选择?

这是the script,我必须注释掉 ESC 映射in this commit

相关的插件源代码如下:

# -*- coding: utf-8 -*-

import re
import vim

#How can we fetch the first param on going to normal Mode without problems?!
vim.command( "inoremap <silent> <buffer> <esc> <c-\><c-n>:py clang_complete.firstParam()<cr>" )

r = re.compile( "@[^@]+\$" )

def firstParam():
  line = vim.current.line
  row, col = vim.current.window.cursor

  result = r.search(line)
  if result is None:
    vim.command('call feedkeys("\<esc>", "n")')
    return

  selectParams( *result.span() )

def selectParams( start, end  ):
  row, _ = vim.current.window.cursor
  vim.current.window.cursor = row, start
  isInclusive = vim.options["selection"] == "inclusive"
  vim.command( 'call feedkeys("\<c-\>\<c-n>v%dl\<c-g>", "n")' %
               ( end - start - isInclusive ) )

ESC 映射在插入模式下终端中的箭头键出现问题,并且提供simple InsertLeave自动命令并不能正常工作,它的运行速度比映射慢得多并且没有正确设置光标定位来进行选择,因此选择位置错误。

我也考虑采用另一种方法来做同样的事情。

1 个答案:

答案 0 :(得分:2)

TL; DR,set ttimeout=100(或更少)和InsertLeave自动命令将更快地处理(具体地说,在那么多毫秒内)。

:imap <Esc>会导致光标键和功能键在插入模式下停止工作,所以不要这样做。使用改进的超时,使用InsertLeave自动命令应该是要走的路。我试着帮助解决你提到的光标定位问题,但是没有足够的解释来解决这个问题。

vim中有很多与响应按 Esc 相关的设置。 Vim可能会因为两个主要原因而逃脱:

  1. 用户单独按下了escape,或
  2. 用户按下了产生转义序列的箭头键或功能键。
  3. 当它在插入模式下看到转义时,vim不能立即离开插入模式但必须等待查明是否

    1. 由功能键生成的转义序列的一部分,或
    2. 多键映射的一部分。
    3. 为了实现快速逃脱处理,您可以设置 noesckeys 选项,以关闭对特殊键<Left><Right><F1>的识别,插入模式等。当vim处于兼容模式时(没有vimrc时你得到的)这是默认行为,并解释了为什么你的InsertLeave自动命令被立即处理。该文档指出 esckeys 设置不会影响导致第二个主题的映射处理。

      Vim允许您为一系列键创建映射,即使该序列的某些前缀已经映射到某个其他操作(通过另一个用户映射或默认操作)。当vim看到一个键时,它会查看是否有以该键开头的映射。如果只有一个并且它本身就是密钥,则可以立即处理映射。如果有多个以键开头的映射,那么vim必须等待,看看你是否完成了其中一个映射。

      除了上面讨论的 esckeys 之外,Vim还有几个选项来控制它是否等待以及持续多长时间。这些是

      1. 超时,它控制vim是否使用超时来确定映射是否完整;
      2. ttimeout ,它控制vim是否使用超时来判断转义序列是否完整;
      3. timeoutlen ,它控制vim等待映射完成的时间;和
      4. ttimeoutlen ,它控制vim等待转义序列完成的时间。
      5. 超时关闭( notimeout )时,vim将无限期地等待映射完成。例如,如果设置了 notimeout 并且您有一个映射:inoremap teh\ the\来修复此常见类型(实际上您实际上会使用iabbrev),并且您输入了 t e h 在您按 Space 之前,不会向缓冲区添加任何内容,在这种情况下,映射会发生并且the被添加到缓冲区;或者按其他键,导致添加原始teh,然后处理下一个键。

        仅当 notimeout 设置时才会查看 ttimeout 选项(只要设置了 timeout ,vim就会使用超时)。设置 nottimeout 后,vim会在获得转义后无限期地等待,看它是否是转义序列的一部分。如果您设置 notimeout nottimeout showmode ,您可以看到在插入模式下按 Esc 时vim保持插入模式,直到某个其他键被按下,它不是转义序列的一部分。一个愚蠢的技巧是使用这些设置键入 Esc O * D (确保您在xterm中)并观察光标向左移动。

        最后,当它使用超时时,vim使用 timeoutlen ttimeoutlen 来决定等待的时间。默认设置为timeoutlen=1000,表示暂停一秒,ttimeoutlen=-1表示使用超时的值。现在,对于映射,一秒钟可能没问题但是比识别转义序列所需的时间长。 Vim并没有真正离开插入模式,直到它看到逃脱并且相关的超时已经过期。奇怪的是,vim会在看到转义后立即删除 showmode 插入模式指示符但不会在超时过后直接触发InsertLeave(如果在超时之前看到映射/转义序列,它会添加指示符到期)。 vim文档建议尝试ttimeoutlen=100,但我认为你可以更短,例如50,没有任何问题搞乱特殊键。

        现在我已经研究了这个,我会四处走动,确保我设置ttimeoutlen=50我使用vim的所有地方,甚至可能更低 timeoutlen 。< / p>