Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vim: Run multiple commands based off of one :global command

Tags:

vim

vi

ex

Apologies if this has been posted already, for I cannot find an answer, even on the vim wiki.

Is there a way I can run multiple commands in vim command-line mode off of a single :g search?

For example,

:%g/foo/ s/bar/\=@a/g | exe "norm /cat\<enter>\"ayiw"

Which (for what I intend it to do) should, on every line matching foo, replace bar with the contents of register a, and then find the next iteration of cat (even if it is many lines ahead), and put the surrounding word into register a.

Instead, this specific syntax completes the subsitution command using the current contents of the initial a register, and then executes the normal mode command on a single line (after the substitution has been completed).

This example is not my specific use-case but shows one instance where this functionality is useful. I realize I could put it all into a single exe, i.e., %g/foo/exe "norm :s/bar/\\=@a/g\<enter>/cat\<enter>\"ayiw", but I would like to do it the first way, as I feel it is more flexible.


I would prefer to do this using vanilla vim, but if a plugin exists for this, that is an okay alternative. Does anybody know if there is syntax to do such a thing?

like image 296
Miles Avatar asked Oct 29 '22 04:10

Miles


2 Answers

Okay a "little bit" dirty, but does this work for you?

:let list = split(execute('g/cat/p'), '\n') | g/foo/ s/bar/\=matchstr(remove(list, 0), '\s\d\+\s\zs.*')/g

It first reads all occurences of cat save them in a list. Then replace the first bar with the first cat... and so on.

The dirty part ist the matchstr command. the g//p also returns a number for the result so the list looks like this:

 1 cat
 2 cat
 3 cat
 ...

that's why we have to remove a bit from the front. I would love to hear if someone knows a clean solution for that (I am also interested in a clean vimscript solution, does not have to be a oneliner).

like image 142
Doktor OSwaldo Avatar answered Nov 22 '22 12:11

Doktor OSwaldo


You can do this (at least for multiple :s commands applied to a single :g). Example:

" SHORT STORY TITLES to single word of CapitalizedWords within <h3>s
.,$g/^\L\+$/s/[^A-Z0-9 ]\+//ge|s/\u\+/\L&/ge|s/\<\l\+\>/\u&/ge|s/ \+//ge|s/.*/<h3>&<\/h3>/
like image 44
user985675 Avatar answered Nov 22 '22 12:11

user985675