mirror of
https://github.com/leafOfTree/vim-vue-plugin.git
synced 2025-12-08 21:54:46 +08:00
Refactor the whole plugin
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
README.html
|
||||
test.vue
|
||||
.DS_STORE
|
||||
|
||||
234
autoload/vue.vim
234
autoload/vue.vim
@@ -1,22 +1,78 @@
|
||||
" Since vue#Log and vue#GetConfig are always called
|
||||
" in syntax and indent files,
|
||||
" this file will be sourced when opening the first vue file
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" this file will be sourced on opening the first vue file
|
||||
|
||||
function! s:GetConfig(name, default)
|
||||
let name = 'g:vim_vue_plugin_'.a:name
|
||||
return exists(name) ? eval(name) : a:default
|
||||
let value = exists(name) ? eval(name) : a:default
|
||||
|
||||
if a:name == 'config'
|
||||
let value = s:MergeDefaultWithConfig(value)
|
||||
endif
|
||||
|
||||
return value
|
||||
endfunction
|
||||
|
||||
let s:name = 'vim-vue-plugin'
|
||||
let s:load_full_syntax = s:GetConfig("load_full_syntax", 0)
|
||||
let s:debug = s:GetConfig("debug", 0)
|
||||
function! s:MergeDefaultWithConfig(user)
|
||||
let default = {
|
||||
\'syntax': {
|
||||
\ 'script': ['javascript'],
|
||||
\ 'template': ['html'],
|
||||
\ 'style': ['css'],
|
||||
\},
|
||||
\'attribute': 0,
|
||||
\'keyword': 0,
|
||||
\'foldexpr': 0,
|
||||
\'init_indent': expand('%:e') == 'wpy',
|
||||
\'full_syntax': [],
|
||||
\'debug': 0,
|
||||
\}
|
||||
|
||||
let user = a:user
|
||||
for key in keys(default)
|
||||
if has_key(user, key)
|
||||
let default[key] = user[key]
|
||||
endif
|
||||
endfor
|
||||
return default
|
||||
endfunction
|
||||
|
||||
function! s:CheckVersion()
|
||||
if !exists('g:vim_vue_plugin_config')
|
||||
let message = 'Please check README.md or https://github.com/leafOfTree/vim-vue-plugin'
|
||||
echom '['.s:name.'] '.message
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:Main()
|
||||
let s:name = 'vim-vue-plugin'
|
||||
let s:config = s:GetConfig('config', {})
|
||||
let s:full_syntax = s:config.full_syntax
|
||||
let s:debug = s:config.debug
|
||||
|
||||
call s:CheckVersion()
|
||||
endfunction
|
||||
|
||||
function! vue#Log(msg)
|
||||
if s:debug
|
||||
echom '['.s:name.'] '.a:msg
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! vue#LogWithLnum(msg)
|
||||
if s:debug
|
||||
echom '['.s:name.']['.v:lnum.'] '.a:msg
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! vue#Warn(msg)
|
||||
if s:debug
|
||||
echohl WarningMsg
|
||||
echom '['.s:name.'] '.a:msg
|
||||
echohl None
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! vue#GetConfig(name, default)
|
||||
return s:GetConfig(a:name, a:default)
|
||||
endfunction
|
||||
@@ -39,78 +95,160 @@ if exists('##CursorMoved') && exists('*OnChangeVueSubtype')
|
||||
endfunction
|
||||
endif
|
||||
|
||||
function! s:SynsEOL(lnum)
|
||||
let lnum = prevnonblank(a:lnum)
|
||||
let cnum = strlen(getline(lnum))
|
||||
return map(synstack(lnum, cnum), 'synIDattr(v:val, "name")')
|
||||
function! s:SyntaxListAtEnd(lnum)
|
||||
let plnum = prevnonblank(a:lnum)
|
||||
let col = strlen(getline(plnum))
|
||||
return map(synstack(plnum, col), 'synIDattr(v:val, "name")')
|
||||
endfunction
|
||||
|
||||
function! s:SyntaxAtEnd(lnum)
|
||||
let syns = s:SyntaxListAtEnd(a:lnum)
|
||||
return empty(syns) ? '' : get(syns, 0, '')
|
||||
endfunction
|
||||
|
||||
function! vue#SyntaxSecondAtEnd(lnum)
|
||||
let syns = s:SyntaxListAtEnd(a:lnum)
|
||||
return get(syns, 1, '')
|
||||
endfunction
|
||||
|
||||
function! s:GetBlockTag(lnum)
|
||||
let syntax_name = s:SyntaxAtEnd(a:lnum)
|
||||
let tag = tolower(matchstr(syntax_name, '\u\U\+\zeBlock'))
|
||||
return tag
|
||||
endfunction
|
||||
|
||||
let s:style_with_css_prefix = ['scss', 'less', 'stylus']
|
||||
|
||||
" Adjust syntax name to support emmet-vim by adding css prefix
|
||||
function! vue#AlterSyntaxForEmmetVim(name, syntax)
|
||||
let name = a:name
|
||||
if count(s:style_with_css_prefix, a:syntax) == 1
|
||||
let name = 'css'.toupper(name[0]).name[1:]
|
||||
endif
|
||||
return name
|
||||
endfunction
|
||||
|
||||
" Remove css prefix
|
||||
function! s:RecoverSyntax(syntax_name, syntax)
|
||||
let syntax = a:syntax
|
||||
if syntax == 'css'
|
||||
let next_syntax = tolower(matchstr(a:syntax_name, '^\U\+\zs\u\U\+'))
|
||||
if count(s:style_with_css_prefix, next_syntax) == 1
|
||||
let syntax = next_syntax
|
||||
endif
|
||||
endif
|
||||
return syntax
|
||||
endfunction
|
||||
|
||||
function! s:GetBlockSyntax(lnum)
|
||||
let syntax_name = s:SyntaxAtEnd(a:lnum)
|
||||
let syntax = matchstr(syntax_name, '^\U\+')
|
||||
let syntax = s:RecoverSyntax(syntax_name, syntax)
|
||||
return syntax
|
||||
endfunction
|
||||
|
||||
function! vue#GetBlockTag(lnum)
|
||||
return s:GetBlockTag(a:lnum)
|
||||
endfunction
|
||||
|
||||
function! vue#GetBlockSyntax(lnum)
|
||||
return s:GetBlockSyntax(a:lnum)
|
||||
endfunction
|
||||
|
||||
function! GetVueSubtype()
|
||||
let lnum = line('.')
|
||||
let cursyns = s:SynsEOL(lnum)
|
||||
let syn = !empty(cursyns) ? get(cursyns, 0, '') : ''
|
||||
|
||||
let subtype = matchstr(syn, '\w\+\zeVue')
|
||||
if subtype =~ 'css\w\+'
|
||||
let subtype = subtype[3:]
|
||||
endif
|
||||
let subtype = tolower(subtype)
|
||||
return subtype
|
||||
let syntax = vue#GetBlockSyntax(lnum)
|
||||
return syntax
|
||||
endfunction
|
||||
|
||||
function! GetVueTag(...)
|
||||
let lnum = a:0 > 0 ? a:1 : line('.')
|
||||
let cursyns = s:SynsEOL(lnum)
|
||||
let syn = get(cursyns, 0, '')
|
||||
|
||||
if syn =~ 'VueTemplate'
|
||||
let tag = 'template'
|
||||
elseif syn =~ 'VueScript'
|
||||
let tag = 'script'
|
||||
elseif syn =~ 'VueStyle'
|
||||
let tag = 'style'
|
||||
else
|
||||
let tag = ''
|
||||
endif
|
||||
|
||||
return tag
|
||||
return vue#GetBlockTag(lnum)
|
||||
endfunction
|
||||
|
||||
function! vue#LoadSyntax(group, type)
|
||||
if s:load_full_syntax
|
||||
call vue#LoadFullSyntax(a:group, a:type)
|
||||
function! vue#LoadSyntax(group, syntax)
|
||||
let group = a:group
|
||||
let syntax = a:syntax
|
||||
if count(s:full_syntax, syntax) == 1
|
||||
call vue#LoadFullSyntax(group, syntax)
|
||||
else
|
||||
call vue#LoadDefaultSyntax(a:group, a:type)
|
||||
let loaded = vue#LoadDefaultSyntax(group, syntax)
|
||||
if !loaded
|
||||
call vue#LoadFullSyntax(group, syntax)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! vue#LoadDefaultSyntax(group, type)
|
||||
function! vue#LoadDefaultSyntax(group, syntax)
|
||||
unlet! b:current_syntax
|
||||
let syntaxPaths = ['$VIMRUNTIME', '$VIM/vimfiles', '$HOME/.vim']
|
||||
for path in syntaxPaths
|
||||
let file = expand(path).'/syntax/'.a:type.'.vim'
|
||||
let loaded = 0
|
||||
let syntax_paths = ['$VIMRUNTIME', '$VIM/vimfiles', '$HOME/.vim']
|
||||
for path in syntax_paths
|
||||
let file = expand(path).'/syntax/'.a:syntax.'.vim'
|
||||
if filereadable(file)
|
||||
let loaded = 1
|
||||
execute 'syntax include '.a:group.' '.file
|
||||
endif
|
||||
endfor
|
||||
if loaded
|
||||
call vue#Log(a:syntax.': laod default')
|
||||
else
|
||||
call vue#Warn(a:syntax.': syntax not found in '.string(syntax_paths))
|
||||
call vue#Warn(a:syntax.': load full instead')
|
||||
endif
|
||||
return loaded
|
||||
endfunction
|
||||
|
||||
" Load all syntax files in 'runtimepath'
|
||||
" Useful if there is no default syntax file provided by vim
|
||||
function! vue#LoadFullSyntax(group, type)
|
||||
call s:SetCurrentSyntax(a:type)
|
||||
execute 'syntax include '.a:group.' syntax/'.a:type.'.vim'
|
||||
function! vue#LoadFullSyntax(group, syntax)
|
||||
call vue#Log(a:syntax.': load full')
|
||||
call s:SetCurrentSyntax(a:syntax)
|
||||
execute 'syntax include '.a:group.' syntax/'.a:syntax.'.vim'
|
||||
endfunction
|
||||
|
||||
" Settings to avoid syntax overload
|
||||
function! s:SetCurrentSyntax(type)
|
||||
if a:type == 'coffee'
|
||||
syntax cluster coffeeJS contains=@htmlJavaScript
|
||||
|
||||
" Avoid overload of `javascript.vim`
|
||||
" Avoid `syntax/javascript.vim` in kchmck/vim-coffee-script
|
||||
let b:current_syntax = 'vue'
|
||||
syntax cluster coffeeJS contains=@javascript,@htmlJavaScript
|
||||
else
|
||||
unlet! b:current_syntax
|
||||
endif
|
||||
endfunction
|
||||
"}}}
|
||||
|
||||
function! vue#GetSyntaxList(config_syntax)
|
||||
let syntax_list = []
|
||||
for syntax in values(a:config_syntax)
|
||||
let type = type(syntax)
|
||||
if type == v:t_string
|
||||
if !count(syntax_list, syntax)
|
||||
call add(syntax_list, syntax)
|
||||
endif
|
||||
elseif type == v:t_list && len(syntax)
|
||||
for syn in syntax
|
||||
if !count(syntax_list, syn)
|
||||
call add(syntax_list, syn)
|
||||
endif
|
||||
endfor
|
||||
else
|
||||
echoerr '[vim-vue-plugin] syntax value type'
|
||||
\.' must be either string or list'
|
||||
endif
|
||||
endfor
|
||||
|
||||
" Move basic syntaxes to the end of the list, so we can check
|
||||
" if they are already loaded by other syntax.
|
||||
" Order matters
|
||||
for syntax in ['html', 'javascript', 'css']
|
||||
let idx = index(syntax_list, syntax)
|
||||
if idx >= 0
|
||||
call remove(syntax_list, idx)
|
||||
call add(syntax_list, syntax)
|
||||
endif
|
||||
endfor
|
||||
return syntax_list
|
||||
endfunction
|
||||
|
||||
call s:Main()
|
||||
|
||||
@@ -17,3 +17,4 @@ endif
|
||||
" indentexpr
|
||||
let b:syng_str = '^\%(.*template\)\@!.*string\|special'
|
||||
let b:syng_strcom = '^\%(.*template\)\@!.*string\|comment\|regex\|special\|doc'
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
if exists("b:did_indent")
|
||||
finish
|
||||
endif
|
||||
|
||||
let s:custom_blocks = vue#GetConfig("custom_blocks", {})
|
||||
let s:indent = {}
|
||||
|
||||
function! s:GetSyntaxList()
|
||||
let syntax_list = []
|
||||
for syntax in values(s:custom_blocks)
|
||||
let type = type(syntax)
|
||||
if type == v:t_string
|
||||
if !count(syntax_list, syntax)
|
||||
call add(syntax_list, syntax)
|
||||
endif
|
||||
elseif type == v:t_list && len(syntax)
|
||||
for syn in syntax
|
||||
if !count(syntax_list, syn)
|
||||
call add(syntax_list, syn)
|
||||
endif
|
||||
endfor
|
||||
else
|
||||
echoerr '[vim-vue-plugin] custom_blocks value type'
|
||||
\.' must be either string or list'
|
||||
endif
|
||||
endfor
|
||||
return syntax_list
|
||||
endfunction
|
||||
|
||||
function! s:GetIndentExpr(syntax_list)
|
||||
for syntax in a:syntax_list
|
||||
unlet! b:did_indent
|
||||
execute 'runtime indent/'.syntax.'.vim'
|
||||
let s:indent[syntax] = &l:indentexpr
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! GetVueCustomBlocksIndent(syn)
|
||||
let syntax = matchstr(a:syn, '^\l\+')
|
||||
call vue#Log('custom block syntax: '.syntax)
|
||||
let ind = eval(s:indent[syntax])
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
call s:GetIndentExpr(s:GetSyntaxList())
|
||||
455
indent/vue.vim
455
indent/vue.vim
@@ -1,295 +1,134 @@
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" 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()
|
||||
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
|
||||
call vue#Log('indent: css')
|
||||
let ind = GetCSSIndent()
|
||||
let file = 'indent/'.syntax.'.vim'
|
||||
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)
|
||||
else
|
||||
" Default to JavaScript indent
|
||||
call vue#Log('syntax: javascript')
|
||||
if len(b:javascript_indentexpr)
|
||||
let ind = eval(b:javascript_indentexpr)
|
||||
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
|
||||
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')
|
||||
if curline =~ s:block_tag
|
||||
let ind = 0
|
||||
elseif s:has_init_indent && ind < 1 && s:SynVueScriptOrStyle(cursyn)
|
||||
call vue#Log('add initial indent')
|
||||
endif
|
||||
|
||||
if prevline =~ s:block_tag
|
||||
if prevline !~ s:template_tag
|
||||
let ind = 0
|
||||
endif
|
||||
endif
|
||||
|
||||
return ind
|
||||
endfunction
|
||||
|
||||
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: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:CheckInitIndent(tag, ind)
|
||||
let ind = a:ind
|
||||
let curline = getline(v:lnum)
|
||||
|
||||
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
|
||||
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')
|
||||
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
|
||||
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")')
|
||||
endfunction
|
||||
|
||||
function! s:SynHTML(syn)
|
||||
return a:syn ==? 'htmlVueTemplate'
|
||||
endfunction
|
||||
|
||||
function! s:SynPug(syn)
|
||||
return a:syn ==? 'pugVueTemplate'
|
||||
endfunction
|
||||
|
||||
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)'
|
||||
endfunction
|
||||
|
||||
function! s:PrevMultilineEmptyTag(lnum)
|
||||
let lnum = a:lnum - 1
|
||||
let lnums = [0, 0]
|
||||
@@ -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()
|
||||
|
||||
@@ -16,7 +16,7 @@ let s:keepcpo= &cpo
|
||||
set cpo&vim
|
||||
|
||||
" [-- local settings (must come before aborting the script) --]
|
||||
setlocal indentexpr=XmlIndentGet(v:lnum,1)
|
||||
setlocal indentexpr=XmlIndentGet(v:lnum,0)
|
||||
setlocal indentkeys=o,O,*<Return>,<>>,<<>,/,{,}
|
||||
|
||||
if !exists('b:xml_indent_open')
|
||||
|
||||
3
syntax/patch/coffee.vim
Normal file
3
syntax/patch/coffee.vim
Normal file
@@ -0,0 +1,3 @@
|
||||
silent! syntax clear coffeeConstant
|
||||
syn match coffeeConstant '\v<\u\C[A-Z0-9_]+>' display
|
||||
\ containedin=@coffeeIdentifier
|
||||
14
syntax/patch/css.vim
Normal file
14
syntax/patch/css.vim
Normal file
@@ -0,0 +1,14 @@
|
||||
" Use a different name in order to avoid css syntax interference
|
||||
silent! syntax clear cssUnitDecorators
|
||||
syntax match cssUnitDecorators2
|
||||
\ /\(#\|-\|+\|%\|mm\|cm\|in\|pt\|pc\|em\|ex\|px\|ch\|rem\|vh\|vw\|vmin\|vmax\|dpi\|dppx\|dpcm\|Hz\|kHz\|s\|ms\|deg\|grad\|rad\)\ze\(;\|$\)/
|
||||
\ contained
|
||||
\ containedin=cssAttrRegion,sassCssAttribute,lessCssAttribute,stylusCssAttribute
|
||||
|
||||
silent! syntax clear cssKeyFrameProp
|
||||
syn match cssKeyFrameProp2 /\d*%\|from\|to/
|
||||
\ contained nextgroup=cssDefinition
|
||||
\ containedin=cssAttrRegion,sassCssAttribute,lessCssAttribute,stylusCssAttribute
|
||||
|
||||
highlight default link cssUnitDecorators2 Number
|
||||
highlight default link cssKeyFrameProp2 Constant
|
||||
@@ -3,7 +3,8 @@
|
||||
" Config {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
let s:highlight_vue_attr = vue#GetConfig("highlight_vue_attr", 0)
|
||||
let s:config = vue#GetConfig('config', {})
|
||||
let s:attribute = s:config.attribute
|
||||
"}}}
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
@@ -11,6 +12,15 @@ let s:highlight_vue_attr = vue#GetConfig("highlight_vue_attr", 0)
|
||||
" Syntax highlight {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Clear htmlHead that may cause highlighting out of bounds
|
||||
silent! syntax clear htmlHead
|
||||
|
||||
" html5 data-*
|
||||
syntax match htmlArg '\v<data(-[.a-z0-9]+)+>' containedin=@html
|
||||
|
||||
" Vue ref attribute
|
||||
syntax match htmlArg 'ref' containedin=@html
|
||||
|
||||
" Use syn-match in order to highlight both transition and transition-group
|
||||
" according to syn-priority
|
||||
syntax match VueComponentName containedin=htmlTagN '\v(component|slot|transition)'
|
||||
@@ -36,7 +46,7 @@ syntax region VueExpression
|
||||
\ start="{{"
|
||||
\ end="}}"
|
||||
syntax region VueExpression
|
||||
\ containedin=htmlVueTemplate,pugVueTemplate,VueValue,htmlString,htmlValue
|
||||
\ containedin=htmlTemplateBlock,pugTemplateBlock,VueValue,htmlString,htmlValue
|
||||
\ contains=@simpleJavascriptExpression
|
||||
\ matchgroup=VueBrace
|
||||
\ start="{{"
|
||||
@@ -66,7 +76,7 @@ syntax match javaScriptOperator '\v(*)@<!/(/|*)@!' contained
|
||||
syntax keyword javaScriptOperator delete instanceof typeof void new in of contained
|
||||
|
||||
highlight default link VueAttr htmlTag
|
||||
if s:highlight_vue_attr
|
||||
if s:attribute
|
||||
syntax match VueValue contained '\v\"\zs[^"]+\ze\"'
|
||||
\ contains=VueInject,@simpleJavascriptExpression
|
||||
highlight default link VueKey Type
|
||||
@@ -3,11 +3,9 @@
|
||||
" Config {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
let s:highlight_vue_keyword = vue#GetConfig("highlight_vue_keyword", 0)
|
||||
if !s:highlight_vue_keyword | finish | endif
|
||||
|
||||
let s:has_init_indent = vue#GetConfig("has_init_indent",
|
||||
\ expand("%:e") == 'wpy' ? 1 : 0)
|
||||
let s:config = vue#GetConfig('config', {})
|
||||
let s:keyword = s:config.keyword
|
||||
let s:init_indent = s:config.init_indent
|
||||
"}}}
|
||||
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
@@ -15,9 +13,17 @@ let s:has_init_indent = vue#GetConfig("has_init_indent",
|
||||
" Syntax highlight {{{
|
||||
"
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Number with minus
|
||||
syntax match javaScriptNumber '\v<-?\d+L?>|0[xX][0-9a-fA-F]+>'
|
||||
\ containedin=@javascript display
|
||||
highlight link javaScriptNumber Constant
|
||||
|
||||
" Vue keywords
|
||||
if !s:keyword | finish | endif
|
||||
|
||||
let s:vue_keywords = 'name parent functional delimiters comments components directives filters extends mixins inheritAttrs model props propsData data computed watch methods template render renderError inject provide beforeCreate created beforeMount mounted beforeUpdate updated activated deactivated beforeDestroy destroyed setup beforeUnmount unmounted errorCaptured renderTracked renderTriggered'
|
||||
|
||||
let s:indent = &sw * (1 + s:has_init_indent)
|
||||
let s:indent = &sw * (1 + s:init_indent)
|
||||
let s:keywords_regexp = '\v^\s{'.s:indent.'}(async )?<('
|
||||
\.join(split(s:vue_keywords, ' '), '|')
|
||||
\.')\ze'
|
||||
@@ -26,7 +32,7 @@ let s:keywords_regexp = '\v^\s{'.s:indent.'}(async )?<('
|
||||
let s:useJavaScriptPlugin = hlexists('jsAsyncKeyword')
|
||||
let s:containedin = s:useJavaScriptPlugin
|
||||
\? 'jsObject,jsFuncBlock,@jsExpression'
|
||||
\: 'javascriptVueScript'
|
||||
\: 'javascriptScriptBlock'
|
||||
let s:contains = s:useJavaScriptPlugin
|
||||
\? 'jsAsyncKeyword'
|
||||
\: 'javaScriptReserved'
|
||||
6
syntax/patch/less.vim
Normal file
6
syntax/patch/less.vim
Normal file
@@ -0,0 +1,6 @@
|
||||
" Use emmet-vim css type.
|
||||
silent! syntax clear lessDefinition
|
||||
syntax region cssLessDefinition matchgroup=cssBraces
|
||||
\ contains=@LessSyntax,cssLessDefinition
|
||||
\ contained containedin=cssLessVueStyle
|
||||
\ start="{" end="}"
|
||||
1
syntax/patch/pug.vim
Normal file
1
syntax/patch/pug.vim
Normal file
@@ -0,0 +1 @@
|
||||
syntax cluster htmlJavascript remove=javascriptParenthesisBlock
|
||||
10
syntax/patch/sass.vim
Normal file
10
syntax/patch/sass.vim
Normal file
@@ -0,0 +1,10 @@
|
||||
silent! syntax clear sassDefinition
|
||||
syntax region sassDefinition matchgroup=cssBraces
|
||||
\ contains=@SassSyntax,sassDefinition
|
||||
\ contained containedin=sassVueStyle
|
||||
\ start="{" end="}"
|
||||
|
||||
" Extend to highlight all numbers in expression
|
||||
syntax match cssValueNumber
|
||||
\ /\W\zs\d\+\(\.\d\+\)\?%\?\ze\W/
|
||||
\ contained containedin=sassDefinition
|
||||
13
syntax/patch/scss.vim
Normal file
13
syntax/patch/scss.vim
Normal file
@@ -0,0 +1,13 @@
|
||||
" If not loading https://github.com/cakebaker/scss-syntax.vim
|
||||
if !hlexists('scssNestedProperty')
|
||||
silent! syntax clear scssDefinition
|
||||
syntax region cssScssDefinition transparent matchgroup=cssBraces
|
||||
\ contains=@ScssSyntax,cssScssDefinition
|
||||
\ contained containedin=cssScssVueStyle
|
||||
\ start="{" end="}"
|
||||
|
||||
" Extend to highlight all numbers in expression
|
||||
syntax match cssValueNumber
|
||||
\ /\W\zs\d\+\(\.\d\+\)\?%\?\ze\W/
|
||||
\ contained containedin=cssScssDefinition
|
||||
endif
|
||||
5
syntax/patch/stylus.vim
Normal file
5
syntax/patch/stylus.vim
Normal file
@@ -0,0 +1,5 @@
|
||||
silent! syntax clear stylusDefinition
|
||||
syntax region cssStylusDefinition matchgroup=cssBraces
|
||||
\ contains=@StylusSyntax,cssStylusDefinition
|
||||
\ contained containedin=cssStylusVueStyle
|
||||
\ start="{" end="}"
|
||||
@@ -1,64 +0,0 @@
|
||||
let s:custom_blocks = vue#GetConfig("custom_blocks", {})
|
||||
|
||||
if empty(s:custom_blocks)
|
||||
finish
|
||||
endif
|
||||
|
||||
function! s:LoadSyntax()
|
||||
let syntax_list = []
|
||||
for syntax in values(s:custom_blocks)
|
||||
let type = type(syntax)
|
||||
if type == v:t_string
|
||||
if !count(syntax_list, syntax)
|
||||
call add(syntax_list, syntax)
|
||||
endif
|
||||
elseif type == v:t_list && len(syntax)
|
||||
for syn in syntax
|
||||
if !count(syntax_list, syn)
|
||||
call add(syntax_list, syn)
|
||||
endif
|
||||
endfor
|
||||
else
|
||||
echoerr '[vim-vue-plugin] custom_blocks value type'
|
||||
\.' must be either string or list'
|
||||
endif
|
||||
endfor
|
||||
for syntax in syntax_list
|
||||
let syntaxGroup = '@'.syntax
|
||||
call vue#LoadFullSyntax(syntaxGroup, syntax)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:SetSyntax(block, syntax, lang)
|
||||
let block = a:block
|
||||
let syntax = a:syntax
|
||||
let lang = a:lang
|
||||
|
||||
let region_name = syntax.toupper(block[0]).block[1:].'Block'
|
||||
let syntax_lang = lang ? 'lang=["'']'.syntax.'["''][^>]*' : ''
|
||||
let start = '<'.block.'[^>]*'.syntax_lang.'>'
|
||||
let end = '</'.block.'>'
|
||||
let syntaxGroup = '@'.syntax
|
||||
|
||||
execute 'syntax region '.region_name.' fold matchgroup=vueTag'
|
||||
\.' start=+'.start.'+'
|
||||
\.' end=+'.end.'+'
|
||||
\.' keepend contains='.syntaxGroup
|
||||
endfunction
|
||||
|
||||
function! s:Highlight()
|
||||
for [block, syntax] in items(s:custom_blocks)
|
||||
let type = type(syntax)
|
||||
if type == v:t_string
|
||||
call s:SetSyntax(block, syntax, 0)
|
||||
elseif type == v:t_list && len(syntax)
|
||||
call s:SetSyntax(block, syntax[0], 0)
|
||||
for syn in syntax
|
||||
call s:SetSyntax(block, syn, 1)
|
||||
endfor
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
call s:LoadSyntax()
|
||||
call s:Highlight()
|
||||
403
syntax/vue.vim
403
syntax/vue.vim
@@ -1,306 +1,167 @@
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Vim syntax file
|
||||
"
|
||||
" Language: Vue
|
||||
" Maintainer: leaf <leafvocation@gmail.com>
|
||||
"
|
||||
" CREDITS: Inspired by mxw/vim-jsx.
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
if exists("b:current_syntax") && b:current_syntax == 'vue'
|
||||
if exists('b:current_syntax') && b:current_syntax == 'vue'
|
||||
finish
|
||||
endif
|
||||
|
||||
" For advanced users, this variable can be used to avoid overload
|
||||
let b:current_loading_main_syntax = 'vue'
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Config {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
let s:use_pug = vue#GetConfig("use_pug", 0)
|
||||
let s:use_less = vue#GetConfig("use_less", 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)
|
||||
"}}}
|
||||
" <sfile> is replaced with the file name of the sourced file
|
||||
let s:patch_path = expand('<sfile>:p:h').'/patch'
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Load main syntax {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
function! s:Init()
|
||||
""" Configs
|
||||
let s:config = vue#GetConfig('config', {})
|
||||
let s:config_syntax = s:config.syntax
|
||||
|
||||
" Load syntax/html.vim to syntax group, which loads full JavaScript and CSS
|
||||
" syntax. It defines group @html, @htmlJavaScript, and @htmlCss.
|
||||
call vue#LoadSyntax('@html', 'html')
|
||||
" For advanced users, it can be used to avoid overload
|
||||
let b:current_loading_main_syntax = 'vue'
|
||||
endfunction
|
||||
|
||||
" Avoid overload
|
||||
if !hlexists('cssTagName')
|
||||
call vue#LoadSyntax('@htmlCss', 'css')
|
||||
endif
|
||||
function! s:GetGroupNameForLoading(syntax)
|
||||
return '@'.a:syntax
|
||||
endfunction
|
||||
|
||||
" Avoid overload
|
||||
if !hlexists('javaScriptComment')
|
||||
call vue#Log('load javascript cluster')
|
||||
call vue#LoadSyntax('@htmlJavaScript', 'javascript')
|
||||
endif
|
||||
" Extend group name as
|
||||
" html defines group @htmlJavaScript and @htmlCss.
|
||||
" coffee defines group @coffeeJS.
|
||||
function! s:GetGroupNameForHighlight(syntax)
|
||||
let syntax = a:syntax
|
||||
let name = '@'.a:syntax
|
||||
if syntax == 'javascript'
|
||||
let name = '@javascript,@htmlJavaScript,@coffeeJS'
|
||||
elseif syntax == 'css'
|
||||
let name = '@css,@htmlCss'
|
||||
endif
|
||||
return name
|
||||
endfunction
|
||||
|
||||
" Load vue-html syntax
|
||||
runtime syntax/vue-html.vim
|
||||
function! s:GetSynatxName(block, syntax)
|
||||
let block = a:block
|
||||
let syntax = a:syntax
|
||||
let name = syntax.toupper(block[0]).block[1:].'Block'
|
||||
let name = vue#AlterSyntaxForEmmetVim(name, syntax)
|
||||
return name
|
||||
endfunction
|
||||
|
||||
" Load vue-javascript syntax
|
||||
runtime syntax/vue-javascript.vim
|
||||
"}}}
|
||||
function! s:LoadSyntaxList(syntax_list)
|
||||
for syntax in a:syntax_list
|
||||
let loaded = s:BeforeLoadSyntax(syntax)
|
||||
if !loaded
|
||||
let syntax_group = s:GetGroupNameForLoading(syntax)
|
||||
call vue#LoadSyntax(syntax_group, syntax)
|
||||
endif
|
||||
call s:AfterLoadSyntax(syntax)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Load pre-processors syntax {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" If pug is enabled, load vim-pug syntax
|
||||
if s:use_pug
|
||||
call vue#LoadFullSyntax('@PugSyntax', 'pug')
|
||||
syn cluster htmlJavascript remove=javascriptParenthesisBlock
|
||||
endif
|
||||
" For specific syntax, we need to handle it specially
|
||||
function! s:BeforeLoadSyntax(syntax)
|
||||
let syntax = a:syntax
|
||||
|
||||
" If less is enabled, load less syntax
|
||||
if s:use_less
|
||||
call vue#LoadSyntax('@LessSyntax', 'less')
|
||||
runtime! after/syntax/less.vim
|
||||
endif
|
||||
" Avoid overload if group already exists
|
||||
let loaded = 0
|
||||
if syntax == 'javascript'
|
||||
let loaded = hlexists('javaScriptComment')
|
||||
elseif syntax == 'css'
|
||||
let loaded = hlexists('cssTagName')
|
||||
endif
|
||||
return loaded
|
||||
endfunction
|
||||
|
||||
" If sass is enabled, load sass syntax
|
||||
if s:use_sass
|
||||
call vue#LoadSyntax('@SassSyntax', 'sass')
|
||||
runtime! after/syntax/sass.vim
|
||||
endif
|
||||
function! s:AfterLoadSyntax(syntax)
|
||||
let syntax = a:syntax
|
||||
call s:LoadPatchSyntax(syntax)
|
||||
call s:LoadStyleAfterSyntax(syntax)
|
||||
endfunction
|
||||
|
||||
" If scss is enabled, load sass syntax
|
||||
if s:use_scss
|
||||
call vue#LoadSyntax('@ScssSyntax', 'scss')
|
||||
runtime! after/syntax/scss.vim
|
||||
endif
|
||||
function! s:LoadPatchSyntax(syntax)
|
||||
let file = s:patch_path.'/'.a:syntax.'.vim'
|
||||
if filereadable(file)
|
||||
execute 'syntax include '.file
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" If stylus is enabled, load stylus syntax
|
||||
if s:use_stylus
|
||||
call vue#LoadFullSyntax('@StylusSyntax', 'stylus')
|
||||
runtime! after/syntax/stylus.vim
|
||||
endif
|
||||
function! s:LoadStyleAfterSyntax(syntax)
|
||||
let syntax = a:syntax
|
||||
if count(['scss', 'sass', 'less', 'stylus'], syntax) == 1
|
||||
execute 'runtime! after/syntax/'.syntax.'.vim'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" If CoffeeScript is enabled, load the syntax. Keep name consistent with
|
||||
" vim-coffee-script/after/html.vim
|
||||
if s:use_coffee
|
||||
call vue#LoadFullSyntax('@htmlCoffeeScript', 'coffee')
|
||||
endif
|
||||
function! s:GetSyntaxLangName(syntax)
|
||||
let syntax = a:syntax
|
||||
if syntax == 'typescript'
|
||||
let syntax = 'ts'
|
||||
endif
|
||||
return syntax
|
||||
endfunction
|
||||
|
||||
" If TypeScript is enabled, load the syntax.
|
||||
if s:use_typescript
|
||||
call vue#LoadFullSyntax('@TypeScript', 'typescript')
|
||||
endif
|
||||
"}}}
|
||||
function! s:SetSyntax(block, syntax, lang)
|
||||
let block = a:block
|
||||
let syntax = a:syntax
|
||||
let lang = a:lang
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Syntax highlight {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" All start with html/javascript/css for emmet-vim in-file type detection
|
||||
syntax region htmlVueTemplate fold
|
||||
\ start=+<template[^>]*>+
|
||||
\ end=+^</template>+
|
||||
\ keepend contains=@html
|
||||
" When template code is not well indented
|
||||
syntax region htmlVueTemplate fold
|
||||
\ start=+<template[^>]*>+
|
||||
\ end=+</template>\ze\n\(^$\n\)*<\(script\|style\)+
|
||||
\ keepend contains=@html
|
||||
let name = s:GetSynatxName(block, syntax)
|
||||
let syntax_lang_name = s:GetSyntaxLangName(syntax)
|
||||
let syntax_lang = lang ? 'lang=["'']'.syntax_lang_name.'["''][^>]*' : ''
|
||||
let start = '<'.block.'[^>]*'.syntax_lang.'>'
|
||||
let end = '</'.block.'>'
|
||||
let syntax_group = s:GetGroupNameForHighlight(syntax)
|
||||
|
||||
syntax region javascriptVueScript fold
|
||||
\ start=+<script[^>]*>+
|
||||
\ end=+</script>+
|
||||
\ keepend contains=@htmlJavaScript,jsImport,jsExport,vueTag
|
||||
execute 'syntax region '.name.' fold '
|
||||
\.' start=+'.start.'+'
|
||||
\.' end=+'.end.'+'
|
||||
\.' keepend contains='.syntax_group.', vueTag'
|
||||
endfunction
|
||||
|
||||
function! s:SetBlockSyntax(config_syntax)
|
||||
for [block, syntax] in items(a:config_syntax)
|
||||
let type = type(syntax)
|
||||
if type == v:t_string
|
||||
call s:SetSyntax(block, syntax, 0)
|
||||
elseif type == v:t_list && len(syntax)
|
||||
call s:SetSyntax(block, syntax[0], 0)
|
||||
for syn in syntax
|
||||
call s:SetSyntax(block, syn, 1)
|
||||
endfor
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
syntax region cssVueStyle fold
|
||||
\ start=+<style[^>]*>+
|
||||
\ end=+</style>+
|
||||
\ keepend contains=@htmlCss,vueTag
|
||||
|
||||
" Preprocessors syntax
|
||||
syntax region pugVueTemplate fold
|
||||
\ start=+<template[^>]*lang=["']pug["'][^>]*>+
|
||||
\ end=+</template>+
|
||||
\ keepend contains=@PugSyntax,vueTag
|
||||
|
||||
syntax region coffeeVueScript fold
|
||||
\ start=+<script[^>]*lang=["']coffee["'][^>]*>+
|
||||
\ end=+</script>+
|
||||
\ keepend contains=@htmlCoffeeScript,jsImport,jsExport,vueTag
|
||||
|
||||
syntax region typescriptVueScript fold
|
||||
\ start=+<script[^>]*lang=["']ts["'][^>]*>+
|
||||
\ end=+</script>+
|
||||
\ keepend contains=@TypeScript,vueTag
|
||||
|
||||
syntax region cssLessVueStyle fold
|
||||
\ start=+<style[^>]*lang=["']less["'][^>]*>+
|
||||
\ end=+</style>+
|
||||
\ keepend contains=@LessSyntax,vueTag
|
||||
syntax region sassVueStyle fold
|
||||
\ start=+<style[^>]*lang=["']sass["'][^>]*>+
|
||||
\ end=+</style>+
|
||||
\ keepend contains=@SassSyntax,vueTag
|
||||
syntax region cssScssVueStyle fold
|
||||
\ start=+<style[^>]*lang=["']scss["'][^>]*>+
|
||||
\ end=+</style>+
|
||||
\ keepend contains=@ScssSyntax,vueTag
|
||||
|
||||
" Backward compatiable for `use_sass` option
|
||||
if s:use_sass && !s:use_scss
|
||||
syntax region cssScssVueStyle fold
|
||||
\ start=+<style[^>]*lang=["']scss["'][^>]*>+
|
||||
\ end=+</style>+
|
||||
\ keepend contains=@SassSyntax,vueTag
|
||||
endif
|
||||
|
||||
syntax region cssStylusVueStyle fold
|
||||
\ start=+<style[^>]*lang=["']stylus["'][^>]*>+
|
||||
\ end=+</style>+
|
||||
\ keepend contains=@StylusSyntax,vueTag
|
||||
|
||||
syntax region vueTag fold
|
||||
function! s:HighlightVueTag()
|
||||
syntax region vueTag fold
|
||||
\ start=+^<[^/]+ end=+>+ skip=+></+
|
||||
\ contained contains=htmlTagN,htmlString,htmlArg
|
||||
syntax region vueTag
|
||||
syntax region vueTag
|
||||
\ start=+^</+ end=+>+
|
||||
\ contains=htmlTagN,htmlString,htmlArg
|
||||
\ contained contains=htmlTagN,htmlString,htmlArg
|
||||
highlight default link vueTag htmlTag
|
||||
endfunction
|
||||
|
||||
highlight default link vueTag htmlTag
|
||||
highlight default link cssUnitDecorators2 Number
|
||||
highlight default link cssKeyFrameProp2 Constant
|
||||
"}}}
|
||||
function! s:SetSyntaxSync()
|
||||
syntax sync fromstart
|
||||
endfunction
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Custom blocks {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
runtime syntax/vue-custom-blocks.vim
|
||||
"}}}
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Syntax patch {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
" Patch 7.4.1142
|
||||
if has("patch-7.4-1142")
|
||||
function! s:SetIsKeyword()
|
||||
if has("patch-7.4-1142")
|
||||
if has("win32")
|
||||
syntax iskeyword @,48-57,_,128-167,224-235,$,-
|
||||
else
|
||||
syntax iskeyword @,48-57,_,192-255,$,-
|
||||
endif
|
||||
else
|
||||
else
|
||||
setlocal iskeyword+=-
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Style
|
||||
" Redefine (less|sass|stylus)Definition to highlight <style> correctly and
|
||||
" enable emmet-vim css type.
|
||||
if s:use_less
|
||||
silent! syntax clear lessDefinition
|
||||
syntax region cssLessDefinition matchgroup=cssBraces
|
||||
\ contains=@LessSyntax,cssLessDefinition
|
||||
\ contained containedin=cssLessVueStyle
|
||||
\ start="{" end="}"
|
||||
endif
|
||||
if s:use_sass
|
||||
silent! syntax clear sassDefinition
|
||||
syntax region sassDefinition matchgroup=cssBraces
|
||||
\ contains=@SassSyntax,sassDefinition
|
||||
\ contained containedin=sassVueStyle
|
||||
\ start="{" end="}"
|
||||
function! VimVuePluginSyntaxMain(id)
|
||||
call s:Init()
|
||||
let syntax_list = vue#GetSyntaxList(s:config_syntax)
|
||||
call s:LoadSyntaxList(syntax_list)
|
||||
call s:SetBlockSyntax(s:config_syntax)
|
||||
call s:SetSyntaxSync()
|
||||
call s:SetIsKeyword()
|
||||
call s:HighlightVueTag()
|
||||
endfunction
|
||||
|
||||
" Extend to highlight all numbers in expression
|
||||
syntax match cssValueNumber
|
||||
\ /\W\zs\d\+\(\.\d\+\)\?%\?\ze\W/
|
||||
\ contained containedin=sassDefinition
|
||||
endif
|
||||
" If not loading https://github.com/cakebaker/scss-syntax.vim
|
||||
if s:use_scss && !hlexists('scssNestedProperty')
|
||||
silent! syntax clear scssDefinition
|
||||
syntax region cssScssDefinition transparent matchgroup=cssBraces
|
||||
\ contains=@ScssSyntax,cssScssDefinition
|
||||
\ contained containedin=cssScssVueStyle
|
||||
\ start="{" end="}"
|
||||
|
||||
" Extend to highlight all numbers in expression
|
||||
syntax match cssValueNumber
|
||||
\ /\W\zs\d\+\(\.\d\+\)\?%\?\ze\W/
|
||||
\ contained containedin=cssScssDefinition
|
||||
endif
|
||||
if s:use_stylus
|
||||
silent! syntax clear stylusDefinition
|
||||
syntax region cssStylusDefinition matchgroup=cssBraces
|
||||
\ contains=@StylusSyntax,cssStylusDefinition
|
||||
\ contained containedin=cssStylusVueStyle
|
||||
\ start="{" end="}"
|
||||
endif
|
||||
|
||||
" Use a different name in order to avoid css syntax interference
|
||||
silent! syntax clear cssUnitDecorators
|
||||
syntax match cssUnitDecorators2
|
||||
\ /\(#\|-\|+\|%\|mm\|cm\|in\|pt\|pc\|em\|ex\|px\|ch\|rem\|vh\|vw\|vmin\|vmax\|dpi\|dppx\|dpcm\|Hz\|kHz\|s\|ms\|deg\|grad\|rad\)\ze\(;\|$\)/
|
||||
\ contained
|
||||
\ containedin=cssAttrRegion,sassCssAttribute,lessCssAttribute,stylusCssAttribute
|
||||
|
||||
silent! syntax clear cssKeyFrameProp
|
||||
syn match cssKeyFrameProp2 /\d*%\|from\|to/
|
||||
\ contained nextgroup=cssDefinition
|
||||
\ containedin=cssAttrRegion,sassCssAttribute,lessCssAttribute,stylusCssAttribute
|
||||
|
||||
" Coffee
|
||||
if s:use_coffee
|
||||
silent! syntax clear coffeeConstant
|
||||
syn match coffeeConstant '\v<\u\C[A-Z0-9_]+>' display
|
||||
\ containedin=@coffeeIdentifier
|
||||
endif
|
||||
|
||||
" JavaScript
|
||||
" Number with minus
|
||||
syntax match javaScriptNumber '\v<-?\d+L?>|0[xX][0-9a-fA-F]+>'
|
||||
\ containedin=@javascriptVueScript display
|
||||
|
||||
" HTML
|
||||
" Clear htmlHead that may cause highlighting out of bounds
|
||||
silent! syntax clear htmlHead
|
||||
|
||||
" html5 data-*
|
||||
syntax match htmlArg '\v<data(-[.a-z0-9]+)+>' containedin=@html
|
||||
"}}}
|
||||
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
"
|
||||
" Syntax sync {{{
|
||||
"
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
syntax sync clear
|
||||
syntax sync minlines=100
|
||||
syntax sync match vueHighlight groupthere NONE "</\(script\|template\|style\)"
|
||||
syntax sync match scriptHighlight groupthere javascriptVueScript "<script"
|
||||
syntax sync match scriptHighlight groupthere coffeeVueScript "<script[^>]*lang=["']coffee["'][^>]*>"
|
||||
syntax sync match scriptHighlight groupthere typescriptVueScript "<script[^>]*lang=["']ts["'][^>]*>"
|
||||
syntax sync match templateHighlight groupthere htmlVueTemplate "<template"
|
||||
syntax sync match templateHighlight groupthere pugVueTemplate "<template[^>]*lang=["']pug["'][^>]*>"
|
||||
syntax sync match styleHighlight groupthere cssVueStyle "<style"
|
||||
syntax sync match styleHighlight groupthere cssLessVueStyle "<style[^>]*lang=["']less["'][^>]*>"
|
||||
syntax sync match styleHighlight groupthere sassVueStyle "<style[^>]*lang=["']sass["'][^>]*>"
|
||||
syntax sync match styleHighlight groupthere cssScssVueStyle "<style[^>]*lang=["']scss["'][^>]*>"
|
||||
syntax sync match styleHighlight groupthere cssStylusVueStyle "<style[^>]*lang=["']stylus["'][^>]*>"
|
||||
"}}}
|
||||
" call timer_start(10, 'VimVuePluginSyntaxMain')
|
||||
call VimVuePluginSyntaxMain(0)
|
||||
|
||||
let b:current_syntax = 'vue'
|
||||
" vim: fdm=marker
|
||||
|
||||
Reference in New Issue
Block a user