在VIM中备份并恢复当前的重复操作(.)

7
我想保存当前的单次重复操作(按下"."时发生的操作),然后运行宏,最后恢复"."操作(因为宏通常会更改它)。这是否可行?
或者,是否可能编写一个宏而不更改当前的"."操作?我猜我可以尝试在命令模式下完成所有操作,但我不确定是否可能。
背景:我正在编写一个文件浏览器功能(类似于TextMate中的command-T,请参见http://github.com/mdemare/fuzzy_file_finder),并且希望尽可能少地更改用户环境,因此更改必须在该功能中发生。目前,当您使用此功能切换文件时,您的"."操作将被覆盖,这是非常不受欢迎的。
3个回答

10

在VIM中,您可以创建一个宏,该宏将执行在 normal 模式下通常要执行的任何编辑,而不会干扰重做 [.] 功能,方法是将这些编辑包装在用户定义的: function 中,然后使用: map映射的键来执行该函数。

示例

最好通过一个示例来看看它。 假设您想每次按F2键时将文本 yyy 添加到当前行的末尾,但您不希望此干扰重做命令 [.] 。

操作步骤如下:

  1. 打开一个新的vim窗口并执行以下命令:

  2. :fu JL()
        normal Ayyy
        endfu
    :map <F2> :call JL()<Enter>
    
  3. 现在添加一些文本,比如说xxx,通过输入 Axxx<Esc> 来实现。

  4. 现在按下[F2]键,您应该会看到xxxyyy

  5. 最后,按下[.]键,您应该会看到xxxyyyxxx

这正是你想要的!

为什么这样做有效

这是因为VIM执行重复命令的方式的特性。当您输入命令时,VIM会跟踪命令的字符。当您按下[.]键时,它将这些字符装入键盘缓冲区以重新执行它们。不幸的是,简单的q宏也是同样的道理——它将字符装入缓冲区,并通过这种方式覆盖了重复缓冲区。:normal命令也是如此,但是当它位于用户定义的函数内部时,我们可以绕过这个限制,因为执行用户定义的函数的代码在用户定义函数期间保存和恢复了重复缓冲区。

所有这些都发生在VIM源代码中的eval.cgetchar.c中。搜索saveRedobuff以了解其中的具体情况。


安息吧,布拉姆·穆伦纳尔。他是vim的创作者。 - JohnnyLambada

4
您可以将操作记录到寄存器中以备后用。按下q,然后输入一个寄存器a-zA-Z0-9"都是有效的寄存器标识符),执行所需的命令/操作,然后按q停止录制。通过按@后跟寄存器来调用命令。
有关更详细的说明,请参阅Vim文档中的复杂重复部分。
注意:不幸的是,序列qa.qu不能完全达到您想要的效果,因为 . 命令会重复当前最后一个动作,而不是命令录制时的最后一个动作。

我知道,那不是我想表达的意思。那就是我所说的宏,它改变了 . 的操作。 - Michiel de Mare

4
我能想到的唯一帮助您的方法是:将“."重新映射以保存操作历史记录,必要时可以进行调用。有关这些想法,请参见repeat.vim插件。

如何通过重新映射“.”来检索最后一个操作?最后一个操作是如何存储/修改的? - Judge Maygarden
@monjardin:我并不真正知道那些答案,但我曾经遇到过一个看起来可能会做这些事情的vim插件,所以我提到它作为一个可能的灵感来源。 - Caleb Huitt - cjhuitt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接