在vim中更改HTML标签,但保留属性(surround)

57

假设我有一个标签(光标在*处):

<h1 class="blah" id="moo">H*ello!</h1>

我希望您能将其改为:

*<h2 class="blah" id="moo">Hello</h2>
例如更改标签类型,但保留所有元素。 使用 surround.vim,我可以执行以下操作:
cst<h2>

但是这会改变 HTML 的内容:

*<h2>Hello</h2>

只更改标签,但保留所有属性是否可能?周围的文档似乎没有类似这样的内容...


3
如果你只想把 tag1 改为 tag2,我建议保持简单并使用 s/// - timss
好的观点!如果标签内容跨越多行,那么这只是一些额外的工作,我希望有一个答案可以减少移动/行号调整。谢谢 :) - cazgp
@timss 不,你必须这样做两次(一次是为了开标签,一次是为了闭标签),这是不必要的手动操作。 - user1804599
@рытфолд 完全不用担心,只需使用s/h1/h2/gset gdefault即可。 - timss
5个回答

135
在保留属性的情况下替换标签功能已经被添加到Surround.vim中,点击这里查看详情。cst<p>可以替换整个标签,而不带关闭括号的cst<p则会保留属性。

感谢您的回答。没有闭合标签也能按预期工作。 - Eskinder

46
你可以使用cstt,它将在底部显示<并输入标签名称但不包括>
在这种情况下,输入cstth2并按Enter键。

2
太好了!我也想知道这为什么有效。来自vim-surround的“cst”很有意义,但额外的“t”是做什么用的? - brianz
我认为额外的t来自标签。比如将tag更改为tag。 - Alexandru
如果不使用feedkeys,无法为其创建热键,例如:vim.keymap.set({"n", "x"}, "<leader>w", function() vim.fn.feedkeys("cstt") end, {noremap = true}) - run_the_race
无法在不使用feedkeys的情况下为其创建快捷键,例如:vim.keymap.set({"n",“x”},“<leader>w”,function() vim.fn.feedkeys(“cstt”)end,{noremap = true}) - run_the_race

7
我有一个 xml.vim 插件 (https://github.com/othree/xml.vim)。如果你也有这个插件,那么你的需求会很简单。
只需要将光标移动到标签上,按下 <leader>c (小写 c),然后输入新的标签名称,只有标签名称会被更改。
如果你按下 <leader>C (大写 C),不仅可以重命名标签/元素,而且原始属性也会被删除。

接受这个答案,因为我之前不知道这个插件,它充满了HTML/XML的好处(并回答了原始问题)。谢谢! - cazgp
请注意,现在的 <LocalLeader>c 默认为 \c - jeff_kile

2
“Surround”没有这个功能。您可以提取属性,然后在键入替换标签时使用“<c-r>”将它们带回来,但这有点麻烦。
我建议使用新的映射和函数来自动化此任务。以下是提供映射的代码,也称为更改周围元素。将其放在您的~/.vimrc文件中,或者如果您感到过度组织,则放在~/.vim/after/plugin/surround_change_element.vim中。
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>

注意:如果您通过g:surround_101b:surround_101创建了一些使用e的环境,则此操作将覆盖某些情况。如果是这种情况,请将映射从cse更改为其他内容,例如csn用于更改周围节点。

编辑

截至2015年2月22日,此答案已过时。请参见@Wojtek Kruszewski的帖子或:h surround-replacements以了解如何使用surround原生方法执行此操作。


这就是为什么我需要学习vim脚本!我会在有机会的时候看一下,看看发生了什么。谢谢 :) - cazgp
@nabn 感谢您的跟进。我已经编辑了这篇文章。 - Peter Rincker
1
@cazgp Tim Pope 掌握了 VimScript,这样我们就不必 #牺牲 了。 - Wojtek Kruszewski

1
在我的情况下,我会尝试使用matchit.vim或者text-object

使用matchit.vim解决方案:

matchit.vim已经包含在vim中。

source $VIMRUNTIME/macros/matchit.vim

然后执行0l%%lr2<Ctrl-o>llr20

文本对象解决方案:

您还可以在替换之前将HTML内容转移到寄存器中。

dit:.s/h1/h2/g<Ctrl-o>P0


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接