Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backup-restore the current repeat action (.) in VIM

Tags:

vim

I'd like to save the current single-repeat action (this is what happens when you press .), then run a macro, and then restore the . action (because macros usually change it).

Is this possible?

Alternatively, is it possible to write a macro without changing the current . action? I guess I could try to do everything in Command Mode, but I'm not sure if that's possible.

Background: I'm writing a file browser function (like command-T in TextMate, see http://github.com/mdemare/fuzzy_file_finder), and I want to make as few changes as possible to the user's environment, so the changes have to occur in the function. Currently, when you switch files using this function, your . action is overwritten, which is very unwelcome.

like image 703
Michiel de Mare Avatar asked Mar 06 '09 16:03

Michiel de Mare


1 Answers

In VIM you can create a macro that will execute any edits you would typically do in normal mode without disturbing the redo [.] functionality by wrapping those edits in a user defined :function and then executing that function with a :mapped key.

Example

The best way to see it is with an example. Suppose you want to add the text yyy to the end of the current line every time you hit the F2 key, but you don't want this to interfere with the redo command [.].

Here's how to do it:

  1. Open a new vim window and execute the following commands:

    :fu JL()
        normal Ayyy
        endfu
    :map <F2> :call JL()<Enter>
    
  2. Now add some text, let's say xxx, by typing Axxx<Esc>

  3. Now press the [F2] key and you should see xxxyyy

  4. Finally, press the [.] key and you should see xxxyyyxxx

Just what you wanted!

Why this works

This works because of the nature of the way VIM executes the redo command. VIM keeps track of the characters of a command as you type it. When you press the [.] key, it stuffs those characters back into the keyboard buffer to re-execute them. Unfortunately, a simple q macro works the same way -- it stuffs characters into the buffer and by doing so overwrites the redo buffer. The :normal command does this as well, but when placed inside a user defined function we get around this limitation because the code that executes the user defined function saves and restores the redo buffer during the user defined function.

This all happens in eval.c and getchar.c in the VIM source code. Search for saveRedobuff to see what's going on.

like image 99
JohnnyLambada Avatar answered Sep 19 '22 18:09

JohnnyLambada