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.
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 :map
command 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 use g
and v
for 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 f
command, which (f)inds a specified character; and/or the t
command, which jumps un(t)il a character. f
jumps up to a character, where t
jumps just before a character. So, with f"
we can jump to the first double-quote of a string, and then using t"
we can jump until just before the second double quote. So, the sequence f"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 "a
to 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 ^M
it is not intended to mean an actual ^
followed by an actual M
but rather a single key that represents the Enter key.
So now, we can make our two key mappings. Let's bind v
to do steps 1 and 2, and g
to do steps 3 and 4.
:map v /^Description "/^Mf"l"ayt"
:map g /^TEXT "/^Mf"ldt""aP
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 v
key to do steps 1 and 2, and the g
key 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.
You can map the following sequence to an unused key (such as F2), and then press it as many times as you want.
:map <F2> /^Description "(.*)"<CR>y//e/^TEXT "(.*)-<CR>Pd//e
Optionally, you could add <F2>
to the end, so that it will run recursively until the match fails.
:map <F2> /^Description "(.*)"<CR>y//e/^TEXT "(.*)-<CR>Pd//e<F2>
Let's break this down to see what's happening. This moves to the beginning of your first search:
/^Description "(.*)"<CR>
This yanks until the end of your first search.
y//e
This is your second search:
/^TEXT "(.*)-<CR>
This puts what you yanked just before the cursor, moves one character to the right, and then deletes until the end of your second search.
Pld//e
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With