mirror of
https://github.com/leafOfTree/vim-vue-plugin.git
synced 2025-12-08 13:44:46 +08:00
Refactor the whole plugin
This commit is contained in:
443
indent/vue.vim
443
indent/vue.vim
@@ -1,293 +1,132 @@
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Vim indent file
|
||||
"
|
||||
" Language: Vue
|
||||
" Maintainer: leafOfTree <leafvocation@gmail.com>
|
||||
"
|
||||
" CREDITS: Inspired by mxw/vim-jsx.
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
if exists("b:did_indent")
|
||||
finish
|
||||
endif
|
||||
if exists('b:did_indent') | finish |endif
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Config {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
let s:use_pug = vue#GetConfig("use_pug", 0)
|
||||
let s:use_sass = vue#GetConfig("use_sass", 0)
|
||||
let s:use_scss = vue#GetConfig("use_scss", 0)
|
||||
let s:use_stylus = vue#GetConfig("use_stylus", 0)
|
||||
let s:use_coffee = vue#GetConfig("use_coffee", 0)
|
||||
let s:use_typescript = vue#GetConfig("use_typescript", 0)
|
||||
let s:has_init_indent = vue#GetConfig("has_init_indent",
|
||||
\ expand("%:e") == 'wpy' ? 1 : 0)
|
||||
let s:custom_blocks = vue#GetConfig("custom_blocks", {})
|
||||
let s:use_custom_blocks = !empty(s:custom_blocks)
|
||||
"}}}
|
||||
function! s:Init()
|
||||
""" Configs
|
||||
let s:config = vue#GetConfig('config', {})
|
||||
let s:config_syntax = s:config.syntax
|
||||
let s:enable_init_indent = s:config.init_indent
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Variables {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Let <template> handled by HTML
|
||||
let s:vue_tag_start = '\v^\s*\<(script|style)'
|
||||
let s:vue_tag_end = '\v^\s*\<\/(script|style)'
|
||||
let s:template_tag = '\v^\s*\<\/?template'
|
||||
let s:empty_tagname = '(area|base|br|col|embed|hr|input|img|keygen|link|meta|param|source|track|wbr)'
|
||||
let s:empty_tag = '\v\<'.s:empty_tagname.'[^/]*\>'
|
||||
let s:empty_tag_start = '\v\<'.s:empty_tagname.'[^\>]*$'
|
||||
let s:empty_tag_end = '\v^\s*[^\<\>\/]*\/?\>\s*'
|
||||
let s:tag_start = '\v^\s*\<\w*'
|
||||
let s:tag_end = '\v^\s*\/?\>\s*' " />
|
||||
let s:full_tag_end = '\v^\s*\<\/' " </...>
|
||||
|
||||
"}}}
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Load indent method {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Save shiftwidth
|
||||
let s:sw = &sw
|
||||
|
||||
" Use lib/indent/ files for compatibility
|
||||
unlet! b:did_indent
|
||||
runtime lib/indent/xml.vim
|
||||
|
||||
unlet! b:did_indent
|
||||
runtime lib/indent/css.vim
|
||||
|
||||
" Use normal indent files
|
||||
unlet! b:did_indent
|
||||
runtime! indent/javascript.vim
|
||||
let b:javascript_indentexpr = &indentexpr
|
||||
|
||||
if s:use_custom_blocks
|
||||
unlet! b:did_indent
|
||||
runtime indent/vue-custom-blocks.vim
|
||||
let s:vue_custom_blocks_tag = '<\/\?'.join(keys(s:custom_blocks), '\|')
|
||||
endif
|
||||
|
||||
if s:use_pug
|
||||
unlet! b:did_indent
|
||||
let s:save_formatoptions = &formatoptions
|
||||
runtime! indent/pug.vim
|
||||
let &formatoptions = s:save_formatoptions
|
||||
endif
|
||||
|
||||
if s:use_sass
|
||||
unlet! b:did_indent
|
||||
runtime! indent/sass.vim
|
||||
endif
|
||||
|
||||
if s:use_scss
|
||||
unlet! b:did_indent
|
||||
runtime! indent/scss.vim
|
||||
endif
|
||||
|
||||
if s:use_stylus
|
||||
unlet! b:did_indent
|
||||
runtime! indent/stylus.vim
|
||||
endif
|
||||
|
||||
if s:use_coffee
|
||||
unlet! b:did_indent
|
||||
runtime! indent/coffee.vim
|
||||
endif
|
||||
|
||||
if s:use_typescript
|
||||
unlet! b:did_indent
|
||||
runtime! indent/typescript.vim
|
||||
endif
|
||||
|
||||
" Recover shiftwidth
|
||||
let &sw = s:sw
|
||||
"}}}
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Settings {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" JavaScript indentkeys
|
||||
setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e,:
|
||||
" XML indentkeys
|
||||
setlocal indentkeys+=*<Return>,<>>,<<>,/
|
||||
setlocal indentexpr=GetVueIndent()
|
||||
"}}}
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Functions {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
function! GetVueIndent()
|
||||
let ind = s:GetIndentBySyntax()
|
||||
let ind = s:AdjustIndent(ind)
|
||||
call vue#Log('indent: '.ind)
|
||||
return ind
|
||||
""" Variables
|
||||
let s:indent = {}
|
||||
let s:block_tag = '<\/\?'.join(keys(s:config_syntax), '\|')
|
||||
" Let <template> handled by HTML
|
||||
let s:template_tag = '\v^\s*\<\/?template'
|
||||
let s:vue_tag_start = '\v^\s*\<(script|style)'
|
||||
let s:vue_tag_end = '\v^\s*\<\/(script|style)'
|
||||
let s:empty_tagname = '(area|base|br|col|embed|hr|input|img|'
|
||||
\.'keygen|link|meta|param|source|track|wbr)'
|
||||
let s:empty_tag = '\v\<'.s:empty_tagname.'[^/]*\>'
|
||||
let s:empty_tag_start = '\v\<'.s:empty_tagname.'[^\>]*$'
|
||||
let s:empty_tag_end = '\v^\s*[^\<\>\/]*\/?\>\s*'
|
||||
let s:tag_start = '\v^\s*\<\w*' " <
|
||||
let s:tag_end = '\v^\s*\/?\>\s*' " />
|
||||
let s:full_tag_end = '\v^\s*\<\/' " </...>
|
||||
endfunction
|
||||
|
||||
function! s:GetIndentBySyntax()
|
||||
let prevlnum = prevnonblank(v:lnum - 1)
|
||||
let prevline = getline(prevlnum)
|
||||
let curline = getline(v:lnum)
|
||||
let cursyn = get(s:SynsEOL(v:lnum), 0, '')
|
||||
function! s:SetVueIndent()
|
||||
""" Settings
|
||||
" JavaScript indentkeys
|
||||
setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e,:
|
||||
" XML indentkeys
|
||||
setlocal indentkeys+=*<Return>,<>>,<<>,/
|
||||
setlocal indentexpr=GetVueIndent()
|
||||
endfunction
|
||||
|
||||
if s:SynHTML(cursyn)
|
||||
call vue#Log('syntax: html')
|
||||
let ind = s:GetHTMLIndent(prevlnum, prevline, curline)
|
||||
elseif s:SynPug(cursyn)
|
||||
call vue#Log('syntax: pug')
|
||||
let ind = GetPugIndent()
|
||||
elseif s:SynCoffee(cursyn)
|
||||
call vue#Log('syntax: coffee')
|
||||
let ind = GetCoffeeIndent(v:lnum)
|
||||
elseif s:SynTypeScript(cursyn)
|
||||
call vue#Log('syntax: typescript')
|
||||
let ind = GetTypescriptIndent()
|
||||
elseif s:SynSASS(cursyn)
|
||||
call vue#Log('syntax: sass')
|
||||
let ind = GetSassIndent()
|
||||
elseif s:SynSCSS(cursyn)
|
||||
call vue#Log('syntax: scss')
|
||||
if exists('*GetSCSSIndent')
|
||||
call vue#Log('indent: scss')
|
||||
let ind = GetSCSSIndent()
|
||||
else
|
||||
call vue#Log('indent: css')
|
||||
let ind = GetCSSIndent()
|
||||
endif
|
||||
elseif s:SynStylus(cursyn)
|
||||
call vue#Log('syntax: stylus')
|
||||
let ind = GetStylusIndent()
|
||||
elseif s:SynStyle(cursyn)
|
||||
call vue#Log('syntax: css')
|
||||
let ind = GetCSSIndent()
|
||||
elseif s:use_custom_blocks && s:SynCustomBlocks(cursyn)
|
||||
call vue#Log('syntax: custom blocks')
|
||||
let ind = GetVueCustomBlocksIndent(cursyn)
|
||||
function! s:GetIndentFile(syntax)
|
||||
let syntax = a:syntax
|
||||
" lib/indent/* files are preversed from previous version vim
|
||||
if syntax == 'html'
|
||||
let file = 'lib/indent/xml.vim'
|
||||
elseif syntax == 'css'
|
||||
let file = 'lib/indent/css.vim'
|
||||
else
|
||||
" Default to JavaScript indent
|
||||
call vue#Log('syntax: javascript')
|
||||
if len(b:javascript_indentexpr)
|
||||
let ind = eval(b:javascript_indentexpr)
|
||||
else
|
||||
let ind = cindent(v:lnum)
|
||||
endif
|
||||
let file = 'indent/'.syntax.'.vim'
|
||||
endif
|
||||
return file
|
||||
endfunction
|
||||
|
||||
function! s:SetIndentExpr(syntax_list)
|
||||
let saved_shiftwidth = &shiftwidth
|
||||
let saved_formatoptions = &formatoptions
|
||||
|
||||
for syntax in a:syntax_list
|
||||
unlet! b:did_indent
|
||||
let &l:indentexpr = ''
|
||||
execute 'runtime '.s:GetIndentFile(syntax)
|
||||
let s:indent[syntax] = &l:indentexpr
|
||||
endfor
|
||||
|
||||
let &shiftwidth = saved_shiftwidth
|
||||
let &formatoptions = saved_formatoptions
|
||||
endfunction
|
||||
|
||||
function! s:GetBlockIndent(syntax)
|
||||
let syntax = a:syntax
|
||||
let indentexpr = get(s:indent, syntax)
|
||||
if !empty(indentexpr)
|
||||
let ind = eval(indentexpr)
|
||||
else
|
||||
call vue#LogWithLnum('indentexpr not found for '.syntax.', use cindent')
|
||||
let ind = cindent(v:lnum)
|
||||
endif
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! s:AdjustIndent(ind)
|
||||
let ind = a:ind
|
||||
let prevline = getline(prevnonblank(v:lnum - 1))
|
||||
function! s:GetIndentByContext()
|
||||
let ind = -1
|
||||
let prevline = getline(s:PrevNonBlankNonComment(v:lnum))
|
||||
let curline = getline(v:lnum)
|
||||
let cursyn = get(s:SynsEOL(v:lnum), 0, '')
|
||||
|
||||
if curline =~? s:vue_tag_start
|
||||
\ || curline =~? s:vue_tag_end
|
||||
\ || prevline =~? s:vue_tag_end
|
||||
\ || (curline =~ s:template_tag && s:SynPug(cursyn))
|
||||
call vue#Log('current line is vue tag or previous line is vue end tag')
|
||||
call vue#Log(', or current line is pug template tag')
|
||||
let ind = 0
|
||||
elseif s:has_init_indent && ind < 1 && s:SynVueScriptOrStyle(cursyn)
|
||||
call vue#Log('add initial indent')
|
||||
let ind = &sw
|
||||
elseif getline(s:PrevNonBlacnkNonComment(v:lnum)) =~? s:vue_tag_start
|
||||
call vue#Log('previous line is vue tag start')
|
||||
let ind = 0
|
||||
elseif s:use_custom_blocks && curline =~ s:vue_custom_blocks_tag
|
||||
call vue#Log('current line is vue custom blocks tag')
|
||||
if curline =~ s:block_tag
|
||||
let ind = 0
|
||||
endif
|
||||
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! s:GetHTMLIndent(prevlnum, prevline, curline)
|
||||
let prevlnum = a:prevlnum
|
||||
let prevline = a:prevline
|
||||
let curline = a:curline
|
||||
|
||||
let ind = XmlIndentGet(v:lnum, 0)
|
||||
if prevline =~? s:empty_tag
|
||||
call vue#Log('previous line is an empty tag')
|
||||
let ind = ind - &sw
|
||||
endif
|
||||
|
||||
" Align '/>' and '>' with '<' for multiline tags.
|
||||
if curline =~? s:tag_end
|
||||
let ind = ind - &sw
|
||||
endif
|
||||
" Then correct the indentation of any element following '/>' or '>'.
|
||||
if prevline =~? s:tag_end
|
||||
let ind = ind + &sw
|
||||
|
||||
" Decrease indent if prevlines are a multiline empty tag
|
||||
let [start, end] = s:PrevMultilineEmptyTag(v:lnum)
|
||||
if end == prevlnum
|
||||
call vue#Log('previous line is a multiline empty tag')
|
||||
if curline =~? s:full_tag_end
|
||||
let ind = indent(v:lnum - 1) - &sw
|
||||
else
|
||||
let ind = indent(v:lnum - 1)
|
||||
endif
|
||||
if prevline =~ s:block_tag
|
||||
if prevline !~ s:template_tag
|
||||
let ind = 0
|
||||
endif
|
||||
endif
|
||||
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! s:SynsEOL(lnum)
|
||||
let lnum = prevnonblank(a:lnum)
|
||||
let col = strlen(getline(lnum))
|
||||
return map(synstack(lnum, col), 'synIDattr(v:val, "name")')
|
||||
function! s:PrevNonBlankNonComment(lnum)
|
||||
let lnum = a:lnum - 1
|
||||
let prevlnum = prevnonblank(lnum)
|
||||
let prevsyn = vue#SyntaxSecondAtEnd(prevlnum)
|
||||
while prevsyn =~? 'comment' && lnum > 1
|
||||
let lnum = lnum - 1
|
||||
let prevlnum = prevnonblank(lnum)
|
||||
let prevsyn = vue#SyntaxSecondAtEnd(prevlnum)
|
||||
endwhile
|
||||
return prevlnum
|
||||
endfunction
|
||||
|
||||
function! s:SynHTML(syn)
|
||||
return a:syn ==? 'htmlVueTemplate'
|
||||
function! s:AdjustBlockIndent(syntax, ind)
|
||||
let block = a:block
|
||||
let syntax = a:syntax
|
||||
let ind = a:ind
|
||||
|
||||
if syntax == 'html'
|
||||
let ind = s:AdjustHTMLIndent(ind)
|
||||
endif
|
||||
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! s:SynPug(syn)
|
||||
return a:syn ==? 'pugVueTemplate'
|
||||
endfunction
|
||||
function! s:CheckInitIndent(tag, ind)
|
||||
let ind = a:ind
|
||||
let curline = getline(v:lnum)
|
||||
|
||||
function! s:SynCoffee(syn)
|
||||
return a:syn ==? 'coffeeVueScript'
|
||||
endfunction
|
||||
|
||||
function! s:SynTypeScript(syn)
|
||||
return a:syn ==? 'typescriptVueScript'
|
||||
endfunction
|
||||
|
||||
function! s:SynSASS(syn)
|
||||
return a:syn ==? 'sassVueStyle'
|
||||
endfunction
|
||||
|
||||
function! s:SynSCSS(syn)
|
||||
return a:syn ==? 'cssScssVueStyle'
|
||||
endfunction
|
||||
|
||||
function! s:SynStylus(syn)
|
||||
return a:syn ==? 'cssStylusVueStyle'
|
||||
endfunction
|
||||
|
||||
function! s:SynStyle(syn)
|
||||
return a:syn =~? 'VueStyle'
|
||||
endfunction
|
||||
|
||||
function! s:SynCustomBlocks(syn)
|
||||
return a:syn =~? 'Block'
|
||||
endfunction
|
||||
|
||||
function! s:SynVueScriptOrStyle(syn)
|
||||
return a:syn =~? '\v(VueStyle)|(VueScript)'
|
||||
let add = s:enable_init_indent
|
||||
\&& ind == 0
|
||||
\&& count(['style', 'script'], a:tag) == 1
|
||||
\&& curline !~ s:block_tag
|
||||
if add
|
||||
call vue#LogWithLnum('add initial indent')
|
||||
let ind = &sw
|
||||
endif
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! s:PrevMultilineEmptyTag(lnum)
|
||||
@@ -312,27 +151,59 @@ function! s:PrevMultilineEmptyTag(lnum)
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! s:PrevNonBlacnkNonComment(lnum)
|
||||
let curline = getline(a:lnum)
|
||||
let cursyns = s:SynsEOL(a:lnum)
|
||||
let cursyn = get(cursyns, 1, '')
|
||||
if cursyn =~? 'comment' && !empty(curline)
|
||||
return prevnonblank(a:lnum - 1)
|
||||
function! s:AdjustHTMLIndent(ind)
|
||||
let ind = a:ind
|
||||
let prevlnum = prevnonblank(v:lnum - 1)
|
||||
let prevline = getline(prevlnum)
|
||||
let curline = getline(v:lnum)
|
||||
|
||||
if prevline =~? s:empty_tag
|
||||
call vue#LogWithLnum('previous line is an empty tag')
|
||||
let ind = ind - &sw
|
||||
endif
|
||||
|
||||
let lnum = a:lnum - 1
|
||||
let prevlnum = prevnonblank(lnum)
|
||||
let prevsyns = s:SynsEOL(prevlnum)
|
||||
let prevsyn = get(prevsyns, 1, '')
|
||||
while prevsyn =~? 'comment' && lnum > 1
|
||||
let lnum = lnum - 1
|
||||
let prevlnum = prevnonblank(lnum)
|
||||
let prevsyns = s:SynsEOL(prevlnum)
|
||||
let prevsyn = get(prevsyns, 1, '')
|
||||
endwhile
|
||||
return prevlnum
|
||||
endfunction
|
||||
"}}}
|
||||
" Align '/>' and '>' with '<'
|
||||
if curline =~? s:tag_end
|
||||
let ind = ind - &sw
|
||||
endif
|
||||
" Then correct the indentation of any element following '/>' or '>'.
|
||||
if prevline =~? s:tag_end
|
||||
let ind = ind + &sw
|
||||
|
||||
let b:did_indent = 1
|
||||
" vim: fdm=marker
|
||||
" Decrease indent if prevlines are a multiline empty tag
|
||||
let [start, end] = s:PrevMultilineEmptyTag(v:lnum)
|
||||
if prevlnum == end
|
||||
call vue#LogWithLnum('previous line is a multiline empty tag')
|
||||
let ind = indent(v:lnum - 1)
|
||||
if curline =~? s:full_tag_end
|
||||
let ind = ind - &sw
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! GetVueIndent()
|
||||
let ind = s:GetIndentByContext()
|
||||
if ind == -1
|
||||
let syntax = vue#GetBlockSyntax(v:lnum)
|
||||
let ind = s:GetBlockIndent(syntax)
|
||||
let ind = s:AdjustBlockIndent(syntax, ind)
|
||||
call vue#LogWithLnum('syntax '.syntax.', ind '.ind)
|
||||
else
|
||||
call vue#LogWithLnum('context, ind '.ind)
|
||||
endif
|
||||
|
||||
let tag = vue#GetBlockTag(v:lnum)
|
||||
let ind = s:CheckInitIndent(tag, ind)
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
function! s:Main()
|
||||
call s:Init()
|
||||
let syntax_list = vue#GetSyntaxList(s:config_syntax)
|
||||
call s:SetIndentExpr(syntax_list)
|
||||
call s:SetVueIndent()
|
||||
endfunction
|
||||
|
||||
call s:Main()
|
||||
|
||||
Reference in New Issue
Block a user