text-object (say mt
) that selects the name of matching tags?
It's hard to think about handling this one with a text object, because a text object is all about selecting some text and then the operation will act on that selection. There's not really a way to select both matching tags at the same time, or to apply the same operation to both...
Having said that, there are ways you can handle that tag replacement. (With or without plug-ins.)
vim-surround plug-in
One plug-in that can help you here is vim-surround by Tim Pope, which includes a cs
operation to "change surroundings".
If your cursor is anywhere over your <div id="foo">
, you can use cst
followed by <section id="foo">
to execute your desired replacement. vim-surround is smart to locate the matching closing tag and replace it with </section>
as you would expect.
One downside of this approach is that you need to write the whole new tag, including the id="foo"
attribute that you were keeping from the original tag. For this particular example, it's not that bad, but it can get quite inconvenient if you have a long list of long attributes...
UPDATE: From your own answer, I see that using a tag replacement without the ending >
will preserve the attributes. So using cst
followed by <section
and pressing "Enter" does exactly what you want. That's awesome!
vim-surround is very generic, in fact it allows you to manage about all kinds of surroundings... You could even replace the tags with double quotes or with a pair of {
and }
brackets if you wanted to. So that comes at the cost of its support for tags not going as far as you might have liked it to...
using %
from matchit
It's true that once you replace a tag, you're no longer able to use %
to jump to the matching closing tag to fix it anymore...
But that doesn't mean you can't use it to fix this particular case!
Simply jump first. Then fix the end tag, and jump back to your previous location (not using the %
motion, but ''
or Ctrl+O
) and then replace the matching block.
For example, with the cursor on top of div
, you can use
%
: Jump to matching closing tag, cursor will be on /
of </div>
l
: Move cursor right, inside the div
tag name.
ciw
: Replace a word. To change the tag name.
section
: Enter the new tag name.
<Esc>
: Leave insert mode.
<C-O>
: Move to last cursor position in jump list.
.
: Repeat the last ciw
operation.
You're done!
So while it's true that %
will be broken to get you to the matching tag after you replace one of them, it doesn't mean you can't use it for this purpose, just use it first, while it works, then use a different method to jump back to the original location after it will have stopped working.
honorable mention: emmet-vim plug-in
If you're editing HTML, you should strongly consider adopting the emmet-vim plug-in by Yasuhiro Matsumoto, which makes generating HTML tag structures much easier by allowing you to expand abbreviations.
While emmet-vim doesn't seem to have a direct operation to handle this particular case, you should be able to use a combination of removing a tag followed by adding a new tag, or a similar sequence of commands to achieve this particular goal.
One advantage of emmet-vim over vim-surround is that it's specifically tailored for HTML tags, so you can abbreviate a lot of the syntax and it will expand tags and attributes for you.
In this particular case, using the %
from matchit to find the closing tag and a jump back motion still seems like the best alternative. But for complex HTML manipulation, you'll want emmet-vim.