Sławosz
Sławosz

Reputation: 11687

How to provide parameter in vim macro

Is it possible to provide some parameter when recording a macro in vim via prompt or some other ways?

Edit: I have such code:

foo
bar

And I would like to surround each with ruby block:

expect do
  foo
end.to raise_error(CustomClass)

expect do
  foo
end.to raise_error(OtherCustomClass)

So, it is easy to create a macro that will result with: expect do foo end.to raise_error()

expect do
  foo
end.to raise_error()

But it will be nice to have prompt that will be used to set raise_error method parameter. In each use of macro this parameter will be different.

Upvotes: 8

Views: 6275

Answers (4)

ELLIOTTCABLE
ELLIOTTCABLE

Reputation: 18029

Very particularly in the OP's situation, where you really only have precisely two variable pieces of content, I find the easiest method to be a bastardisation of @mkomitee's approach above.

Instead of manually saving the two ‘parameters’ into registers before each usage of the macro, I prefer to type the “first parameter,” visual-select it, evaluate the macro, then type the “second parameter.” To achieve this, I start the macro with a deletion command (a simple d, assuming you're always going to invoke the macro in visual-mode, for instance); then finish it with a command that switches to insert mode (like c or i), and finally, while still in insert mode, a Ctrl-O q to cause the macro to also leave Vim in insert mode when it's done.

As a slightly simple example, if the two “parameters” are single words, here's the keystrokes to create (and then invoke) a macro to manipulate widget.snog() to a parameterised widgetFoo.fooSnog(bar):

  • foob qq "zdwwe're now recording to the q register, with the first ‘argument’ in z

  • "aPprefix-paste from a fixed register used elsewhere in the document

    widget.snog()‸
    
  • ^ea␣Ctrl-rEscb~hxpaste the first arg, and capitalize

    widget‸Foo.snog()
    
  • 2w~b"zPcapitalize existing word, then paste the first arg again

    widgetFoo.fo‸oSnog()
    
  • $Ctrl-Oqmove to the last position, enter insert-mode, and end the macro

    widgetFoo.fooSnog(‸)
    

After finishing the first instance with bar, we can now use it several times:

  • obazEscbset up our first ‘argument’,

    widgetFoo.fooSnog(bar)
    ‸baz
    
  • @qquuxEscinvoke the macro, and finish with the second one

    widgetFoo.fooSnog(bar)
    widgetBaz.bazSnog(quux‸)
    
  • ocorgeEscb@@graultEscrepeat a third time

    widgetFoo.fooSnog(bar)
    widgetBaz.bazSnog(quux)
    widgetCorge.corgeSnog(grault‸)
    
  • ogarplyEscb@@waldoEsc… and so on

    widgetFoo.fooSnog(bar)
    widgetBaz.bazSnog(quux)
    widgetCorge.corgeSnog(grault)
    widgetGarply.garplySnog(waldo‸)
    

Of course, it looks laborious, typed out in such a long fashion — but it's surprisingly few key-strokes in practice, and very easy to train into your fingers.


tl;dr: type the first argument; enter macro-recording before deleting it into a register; manipulate your text as desired; then leave vim in insert-mode at the position of the second argument with Ctrl-Oq.

Upvotes: 2

Developer
Developer

Reputation: 1041

If you need to generate a code, which is the case, the best way for this is to use vim snippets. You can configure snippet to put cursor where you need when you [tab].

Upvotes: 0

mkomitee
mkomitee

Reputation: 760

While I agree with everyone else that if you need this feature, you're probably going about things inefficiently, it is possible to insert a variable text string into a document as part of a macro. The trick is to store the text you want to use in your macro in a register.

  1. yank some text into a named register, for example "xyw to yank a word into the x register
  2. record your macro, qq, when you want to place the variable text, put it, for example "xp to put the text in the x register into the document where the cursor is
  3. now, when you play your q macro, @q, it will use whatever is currently in the x register, so you can yank different text into the x register, play your q macro, and the newly yanked text will be used.

Upvotes: 9

Benoit
Benoit

Reputation: 79175

If you are talking about recording a macro with qx...q, this is not possible.

However you could still do : :let @y = substitute(@x, 'old_pattern', 'replacement', 'g') and then use @y.

You could also define a function:

function Play(myArg)
   execute 'normal sequence_of_characters' . a:myArg . 'other_sequence_of_characters'
endfunction

call Play('foo')

Upvotes: 6

Related Questions