diff options
Diffstat (limited to 'ftplugin')
-rw-r--r-- | ftplugin/svelte.vim | 50 | ||||
-rw-r--r-- | ftplugin/svelte/fold.vim | 131 |
2 files changed, 145 insertions, 36 deletions
diff --git a/ftplugin/svelte.vim b/ftplugin/svelte.vim index cf32ef5b..051e085d 100644 --- a/ftplugin/svelte.vim +++ b/ftplugin/svelte.vim @@ -2,46 +2,24 @@ if polyglot#init#is_disabled(expand('<sfile>:p'), 'svelte', 'ftplugin/svelte.vim finish endif -" Vim filetype plugin -" Language: Svelte 3 (HTML/JavaScript) -" Author: Evan Lecklider <evan@lecklider.com> -" Maintainer: Evan Lecklide <evan@lecklider.com> -" URL: https://github.com/evanleck/vim-svelte -if (exists('b:did_ftplugin')) - finish -endif +if exists("b:did_ftplugin") | finish | endif let b:did_ftplugin = 1 -" Matchit support -if exists('loaded_matchit') && !exists('b:match_words') - let b:match_ignorecase = 0 +if !has('nvim') + setlocal matchpairs+=<:> +endif - " In order: - " - " 1. Svelte control flow keywords. - " 2. Parens. - " 3-5. HTML tags pulled from Vim itself. - " - " https://github.com/vim/vim/blob/5259275347667a90fb88d8ea74331f88ad68edfc/runtime/ftplugin/html.vim#L29-L35 - let b:match_words = - \ '#\%(if\|await\|each\)\>:\:\%(else\|catch\|then\)\>:\/\%(if\|await\|each\)\>,' . - \ '{:},' . +if exists("loaded_matchit") + let b:match_ignorecase = 1 + let b:match_words = '<:>,' . \ '<\@<=[ou]l\>[^>]*\%(>\|$\):<\@<=li\>:<\@<=/[ou]l>,' . \ '<\@<=dl\>[^>]*\%(>\|$\):<\@<=d[td]\>:<\@<=/dl>,' . - \ '<\@<=\([^/][^ \t>]*\)[^>]*\%(>\|$\):<\@<=/\1>' + \ '<\@<=\([^/][^ \t>]*\)[^>]*\%(>\|$\):<\@<=/\1>,' . + \ '{#\(if\|each\)[^}]*}:{\:else[^}]*}:{\/\(if\|each\)},' . + \ '{#await[^}]*}:{\:then[^}]*}:{\/await},' endif -" ALE fixing and linting. -if exists('g:loaded_ale') - if !exists('b:ale_fixers') - let b:ale_fixers = ['eslint', 'prettier', 'prettier_standard'] - endif - - if !exists('b:ale_linter_aliases') - let b:ale_linter_aliases = ['css', 'javascript'] - endif - - if !exists('b:ale_linters') - let b:ale_linters = ['stylelint', 'eslint'] - endif -endif +" Indent correctly with template string for vim-javascript/builtin +" indentexpr +let b:syng_str = '^\%(.*template\)\@!.*string\|special' +let b:syng_strcom = '^\%(.*template\)\@!.*string\|comment\|regex\|special\|doc' diff --git a/ftplugin/svelte/fold.vim b/ftplugin/svelte/fold.vim new file mode 100644 index 00000000..2732660a --- /dev/null +++ b/ftplugin/svelte/fold.vim @@ -0,0 +1,131 @@ +if polyglot#init#is_disabled(expand('<sfile>:p'), 'svelte', 'ftplugin/svelte/fold.vim') + finish +endif + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" +" Config {{{ +" +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +let s:use_foldexpr = exists("g:vim_svelte_plugin_use_foldexpr") + \ && g:vim_svelte_plugin_use_foldexpr == 1 +"}}} + +if !s:use_foldexpr | finish | endif + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" +" Settings {{{ +" +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +setlocal foldmethod=expr +setlocal foldexpr=GetSvelteFold(v:lnum) +"}}} + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" +" Variables {{{ +" +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +let s:empty_line = '\v^\s*$' +let s:block_end = '\v^\s*}|]|\)' +let s:svelte_tag_start = '\v^\<\w+' +let s:svelte_tag_end = '\v^\<\/\w+' +let s:svelte_internal_blocks = '\v:(else|then|catch)' +"}}} + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" +" Functions {{{ +" +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" see :h fold-expr +" value meaning +" 0 the line is not in a fold +" 1, 2, .. the line is in a fold with this level +" -1 the fold level is undefined, use the fold level of a +" line before or after this line, whichever is the +" lowest. +" "=" use fold level from the previous line +" "a1", "a2", .. add one, two, .. to the fold level of the previous +" line, use the result for the current line +" "s1", "s2", .. subtract one, two, .. from the fold level of the +" previous line, use the result for the next line +" ">1", ">2", .. a fold with this level starts at this line +" "<1", "<2", .. a fold with this level ends at this line +function! GetSvelteFold(lnum) + let this_line = getline(a:lnum) + let next_line = getline(a:lnum + 1) + + " Handle empty lines + if this_line =~ s:empty_line + return -1 + endif + + " Handle start/end tags + if this_line =~ s:svelte_tag_start + return '>1' + endif + if this_line =~ s:svelte_tag_end + " If return '<1', fold will get incorrect with prev line + return 1 + endif + + " Fold by indent + if a:lnum > 1 + let prev_indent = s:IndentLevel(a:lnum - 1) + else + let prev_indent = 0 + endif + let this_indent = s:IndentLevel(a:lnum) + let next_indent = s:IndentLevel(s:NextNonBlankLine(a:lnum)) + + " Fold separately on blocks + if this_line =~ s:svelte_internal_blocks + return '>'.next_indent + endif + + if GetSvelteTag(a:lnum) == 'script' + " Handle closing '}' + if this_line =~ '\v^\s*},?\s*$' + return '<'.prev_indent + endif + + " --this + " ----next + if this_indent < next_indent + return '>'.next_indent + endif + + " ----this + " --next + if this_indent >= next_indent + return this_indent + endif + else + " Template or style + return this_indent + endif +endfunction + +function! s:IndentLevel(lnum) + " Add 1 to indentLevel, so start/end tags can fold properly + return indent(a:lnum) / &shiftwidth + 1 +endfunction + +function! s:NextNonBlankLine(lnum) + let next_line = a:lnum + 1 + let last_line = line('$') + + while next_line <= last_line + if getline(next_line) =~ '\v\S' + return next_line + endif + + let next_line += 1 + endwhile + + return 0 +endfunction +"}}} +" vim: fdm=marker |