Reputation: 143
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?
Upvotes: 8
Views: 1562
Reputation: 76715
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.
Upvotes: 5
Reputation: 5241
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
Upvotes: 5