简体   繁体   中英

Vim cursor position after expanding html tag

I most IDEs and modern text editors (Sublime Text 3) the cursor is correctly indented after inserting a newline in between an html tag (aka 'expanding" the tag):

Before:

<div>|</div>

After pressing CR:

<div>
    |
</div>

But in Vim, this is what I get:

<div>
|</div>

How can I get the same behaviour in Vim like in most other editors (see above)?

The only correct behavior of <CR> in insert mode is to break the line at the cursor.

What you want is an enhanced behavior and you need to add something to your config to get it: a mapping, a short function or a full fledged plugin.

When I started to use vim, that behavior was actually one of the first things I added to my vimrc. I've changed it many times in the past but this mapping has been quite stable for a while:

inoremap <leader><CR> <CR><C-o>==<C-o>O

I've used <leader><CR> to keep the normal behavior of <CR> .


Here is a small function that seems to do what you want:

function! Expander()
  let line   = getline(".")
  let col    = col(".")
  let first  = line[col-2]
  let second = line[col-1]
  let third  = line[col]

  if first ==# ">"
    if second ==# "<" && third ==# "/"
      return "\<CR>\<C-o>==\<C-o>O"

    else
      return "\<CR>"

    endif

  else
    return "\<CR>"

  endif

endfunction

inoremap <expr> <CR> Expander()

This little snippet will remap Enter in insert mode to test whether or not the cursor is between > and < and act accordingly if it is. Depending on your indent settings the \<Tab> may need to be removed.

It will not play nice with other plugins that might be also be mapping the Enter key so be aware that there is probably more work to do if you want that compatibility.

function EnterOrIndentTag()
  let line = getline(".")
  let col = getpos(".")[2]
  let before = line[col-2]
  let after = line[col-1]

  if before == ">" && after == "<"
    return "\<Enter>\<C-o>O\<Tab>"
  endif
   return "\<Enter>"
endfunction

inoremap <expr> <Enter> EnterOrIndentTag()

I have only tested the simple cases (beginning of the line, end of the line, inside and outside of >< ), there are probably edge cases that this would not catch.

@RandyMorris and @romainl have posted good solutions for your exact problem.

There are some other possibilities you might be interested in if you are typing out these tags yourself: there's the ragtag.vim plugin for HTML/XML editing.

With ragtag.vim you type this to create your "before" situation (in insert mode):

div<C-X><Space>

To create your "after" situation you would instead type:

div<C-X><Enter>

So if you know beforehand that you are going to "expand" the tag, typing just the element name and the combo Ctrl X followed by Enter is enough.

There are also other more advanced plugins to save keystrokes when editing HTML, such as ZenCoding.vim and Sparkup .

Since no one have mentioned it I will. There is excellent plugin that does exactly that delemitmate

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM