Change HTML tag in vim, but keeping the attributes (surround)
Let's say I have a tag (and cursor at *):
<h1 class="blah" id="moo">H*ello!</h1>
I want to change it to:
*<h2 class="blah" id="moo">Hello</h2>
i.e. Change the type of tag, but keep all the elements.
Using surround.vim, I could do:
cst<h2>
but that changes the HTML to:
*<h2>Hello</h2>
Is just changing the tag possible, but keeping all the attributes? Surround documentation doesn't seem to contain anything like this...
Solution 1:
Replacing tag while keeping attributes has been added to Surround.vim
cst<p>
replaces whole tag, while cst<p
(without closing bracket) keeps attributes.
Solution 2:
You can use cstt
and it'll display <
on the bottom and type the tag name without >
in this case, cstth2
and hit enter.
Solution 3:
I have xml.vim plugin (https://github.com/othree/xml.vim) . If you had it too, your requirement is rather easy.
Just move cursor to tag, press <leader>c
(lowercase c), then input new tagname, only tag name will be changed.
If you press <leader>C
(Big C), also rename the tag/element, but also original attributes are removed.
Solution 4:
Surround does not have this built in. You can yank the attributes and then use <c-r>"
when typing out the replacement tag to bring them back, but that is a bit lame.
I propose a new mapping and function that will automate this task. The following will provide the cse
mapping, aka change surrounding element. Put this in a your ~/.vimrc
file or maybe ~/.vim/after/plugin/surround_change_element.vim
if you feel overly orangized.
function! s:ChangeElement()
execute "normal! vat\<esc>"
call setpos('.', getpos("'<"))
let restore = @"
normal! yi>
let attributes = substitute(@", '^[^ ]*', '', '')
let @" = restore
let dounmapb = 0
if !maparg(">","c")
let dounmapb = 1
" Hide from AsNeeded
exe "cn"."oremap > <CR>"
endif
let tag = input('<', '')
if dounmapb
silent! cunmap >
endif
let tag = substitute(tag, '>*$', '', '')
exe "normal cst<" . tag . attributes . ">"
endfunction
nnoremap cse :call <SID>ChangeElement()<cr>
Note: this will shadow some cases of surroundings with e
if you have any created via g:surround_101
or b:surround_101
. If that is the case change the mapping form cse
to something else maybe csn
for change surrounding node.
EDIT
As of February 22, 2015 this answer is out of date. Please see @Wojtek Kruszewski post or :h surround-replacements
for how to do this natively with surround.
Solution 5:
In my case, I would try matchit.vim
or text-object
.
matchit.vim solution:
matchit.vim
is included in vim.
source $VIMRUNTIME/macros/matchit.vim
and then 0l%%lr2<Ctrl-o>llr20
.
text-object solution:
You can also evacuate html content to the register before replace them.
dit:.s/h1/h2/g<Ctrl-o>P0