I find my myself frequently with a problems that need to combine regular expressions, some kind of movement, and copying and pasting. I’m sure there is some way to do this in vim but I haven’t seen anything bringing it all together. As an example right now the problem I am trying to solve is like this.
- Find a line that is /^Description “(.*)”/
- Save the captured text
- Go to the line that is /^TEXT “(.*)-/
- Replace the captured text above with the captured text from step 2
- Repeat as necessary moving forward through the file
Does anyone know of a way to quickly automate this type of task in VIM?
I haven’t learned all the new-fangled vim-only features; I learned vi before vim and this solution will work in any vi-ish editor. There might be an even better solution using vim features, perhaps.
What I would usually do in this case is use the
:mapcommand to bind several keys, each one doing part of the above. You need to pick some keys you can live without for a while; I often usegandvfor this. @Neil Forrester suggested using function keys, which is a great idea.Now, you showed regular expression patterns with parens indicating a match group. (In vi or vim, you actually need to put a backslash before each paren to make it “magic”; see the documentation.) For this solution, however, I am instead going to use the
fcommand, which (f)inds a specified character; and/or thetcommand, which jumps un(t)il a character.fjumps up to a character, wheretjumps just before a character. So, withf"we can jump to the first double-quote of a string, and then usingt"we can jump until just before the second double quote. So, the sequencef"lyt"would find the first double-quote, move one char to the right, then yank everything until the next double quote. But, let’s store the yanked text into one of the 26 named buffers; let’s just use buffer “a”:f"l"ayt"This is a little bit confusing, because we must use"ato refer to named buffer “a” but we have lots of other"characters that we are looking for.Also, within a “map” you may need to record a keystroke for the Enter key. The way you do that is to hit Ctrl+V, then hit the Enter key. This will display as
^M. In my code below, if you see^Mit is not intended to mean an actual^followed by an actualMbut rather a single key that represents the Enter key.So now, we can make our two key mappings. Let’s bind
vto do steps 1 and 2, andgto do steps 3 and 4.Don’t forget, use Ctrl+V and Enter rather than actually typing ^M, so you can’t just copy/paste the above without editing it.
Now, use the
vkey to do steps 1 and 2, and thegkey to do steps 3 and 4. By alternately hitting the two keys you can do a lot pretty quick.There might also be a way to do this by using scripting in vim, but on the other hand, you might just want to write a short Python script (or your favorite language) if you want to script this. The two key macros, above, really do provide a fast way to do this sort of thing in vim.
vim has some sort of feature for recording keys as you type them, which I think can be used to quickly create this sort of macro.