1

In Textmate I can do something like when I have the following:

<div>
    <p>new

If I press optshift. it will add in the matching tag. So when I press it once, it will look like:

<div>
    <p>new</p>

If I press it a second time:

<div>
    <p>new</p></div>

And if I press it a third time, nothing will happen as there are no open tags. What is the best way to do this in vim?

2 Answers 2

4

In vim, you can complete open html tags and close tags using omni-completion, invoked via ctrl-xctrl-o. To do this though, you must first type < or </ depending on which tag you want. For close, the tag corresponding to the nearest unclosed open tag will be chosen, for example:

<div>
  <p>asdf</p>
</[]    <-- PRESS ctrl-x ctrl-o HERE

This is a little bit inconvenient, so we can make a mapping for close tag:

inoremap <c-b> </<c-x><c-o>

Pressing ctrl-b in insert mode will enter the desired close tag. This map works, but isn't ideal because it will enter </> when no close tab is appropriate. We can modify the map to help

inoremap <c-b> <c-\><c-o>a</<c-x><c-o><c-r>=get(v:completed_item, 'word', '>') ==# '>' ? "\<lt>c-u>" : ''<cr>

The idea behind this map is if only > was inserted, backspace the inserted text. The point of <c-\><c-o>a is to limit the amount backspaced over with <c-u>.

1
  • I did not know about <c-\>, I feel like a whole new world has just opened before me. Thanks!
    – Biggybi
    Apr 29, 2020 at 1:00
4

You could use the plugin called vim-closetag which does exactly this.

The big advantage over the default omni-completion is you don't need to type as much.

The matching closing tag will be automatically inserted after your cursor. Just type > by default to insert a new line between those new tags, pretty convenient.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.