summaryrefslogtreecommitdiffstats
path: root/ftplugin
diff options
context:
space:
mode:
Diffstat (limited to 'ftplugin')
-rw-r--r--ftplugin/svelte.vim50
-rw-r--r--ftplugin/svelte/fold.vim131
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