From 067e07e137d26ca6bc3f8496fe7bd569500d7fa4 Mon Sep 17 00:00:00 2001 From: Adam Stankiewicz Date: Wed, 14 Apr 2021 12:11:13 +0200 Subject: Change svelte provider, fixes #700 --- README.md | 2 +- autoload/svelte.vim | 71 +++++++++ ftplugin/svelte.vim | 50 ++----- ftplugin/svelte/fold.vim | 131 +++++++++++++++++ indent/svelte.vim | 373 ++++++++++++++++++++++++++++++++--------------- packages.yaml | 2 +- syntax/svelte-html.vim | 127 ++++++++++++++++ syntax/svelte.vim | 341 +++++++++++++++++++++++++++++++------------ 8 files changed, 850 insertions(+), 247 deletions(-) create mode 100644 autoload/svelte.vim create mode 100644 ftplugin/svelte/fold.vim create mode 100644 syntax/svelte-html.vim diff --git a/README.md b/README.md index 86ac7b58..40674dd3 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,7 @@ On top of all language packs from [vim repository](https://github.com/vim/vim/tr - [smt2](https://github.com/bohlender/vim-smt2) (SMT syntax highlighting for smt2 and smt files) - [solidity](https://github.com/TovarishFin/vim-solidity) (Solidity syntax highlighting for sol files) - [stylus](https://github.com/wavded/vim-stylus) (Stylus syntax highlighting for styl and stylus files) -- [svelte](https://github.com/evanleck/vim-svelte/tree/main) (Svelte syntax highlighting for svelte files) +- [svelte](https://github.com/leafOfTree/vim-svelte-plugin) (Svelte syntax highlighting for svelte files) - [svg-indent](https://github.com/jasonshell/vim-svg-indent) - [svg](https://github.com/vim-scripts/svg.vim) (SVG syntax highlighting for svg files) - [swift](https://github.com/keith/swift.vim) (Swift syntax highlighting for swift files) diff --git a/autoload/svelte.vim b/autoload/svelte.vim new file mode 100644 index 00000000..60d31469 --- /dev/null +++ b/autoload/svelte.vim @@ -0,0 +1,71 @@ +if polyglot#init#is_disabled(expand(':p'), 'svelte', 'autoload/svelte.vim') + finish +endif + +let s:name = 'vim-svelte-plugin' +let s:debug = exists("g:vim_svelte_plugin_debug") + \ && g:vim_svelte_plugin_debug == 1 + +function! svelte#GetConfig(name, default) + let name = 'g:vim_svelte_plugin_'.a:name + return exists(name) ? eval(name) : a:default +endfunction + +" Since svelte#Log and svelte#GetConfig are always called +" in syntax and indent files, +" this file will be sourced when opening the first svelte file +if exists('##CursorMoved') && exists('*OnChangeSvelteSubtype') + augroup vim_svelte_plugin + autocmd! + autocmd CursorMoved,CursorMovedI,WinEnter *.svelte + \ call s:CheckSubtype() + augroup END + + let s:subtype = '' + function! s:CheckSubtype() + let subtype = GetSvelteSubtype() + + if s:subtype != subtype + call OnChangeSvelteSubtype(subtype) + let s:subtype = subtype + endif + 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")') +endfunction + +function! GetSvelteSubtype() + let lnum = line('.') + let cursyns = s:SynsEOL(lnum) + let syn = !empty(cursyns) ? get(cursyns, 0, '') : '' + + let subtype = matchstr(syn, '\w\+\zeSvelte') + if subtype =~ 'css\w\+' + " For cssScss, cssLess, ... + let subtype = subtype[3:] + endif + let subtype = tolower(subtype) + return subtype +endfunction + +function! GetSvelteTag(...) + let lnum = a:0 > 0 ? a:1 : line('.') + let cursyns = s:SynsEOL(lnum) + let syn = get(cursyns, 0, '') + + if syn =~ 'SvelteTemplate' + let tag = 'template' + elseif syn =~ 'SvelteScript' + let tag = 'script' + elseif syn =~ 'SvelteStyle' + let tag = 'style' + else + let tag = '' + endif + + return tag +endfunction 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(':p'), 'svelte', 'ftplugin/svelte.vim finish endif -" Vim filetype plugin -" Language: Svelte 3 (HTML/JavaScript) -" Author: Evan Lecklider -" Maintainer: Evan Lecklide -" 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(':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 diff --git a/indent/svelte.vim b/indent/svelte.vim index cb01c424..047d1479 100644 --- a/indent/svelte.vim +++ b/indent/svelte.vim @@ -2,160 +2,301 @@ if polyglot#init#is_disabled(expand(':p'), 'svelte', 'indent/svelte.vim') finish endif +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Vim indent file -" Language: Svelte 3 (HTML/JavaScript) -" Author: Evan Lecklider -" Maintainer: Evan Lecklide -" URL: https://github.com/evanleck/vim-svelte - +" +" Language: Svelte +" Maintainer: leafOfTree +" +" CREDITS: Inspired by mxw/vim-jsx. +" +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" if exists("b:did_indent") finish endif -if !exists('g:svelte_indent_script') - let g:svelte_indent_script = 1 -endif +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" +" Variables {{{ +" +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +let s:name = 'vim-svelte-plugin' +" Let + + \ keepend contains=@PugSyntax,svelteTag + +syntax region coffeeSvelteScript fold + \ start=+]*lang="coffee"[^>]*>+ + \ end=++ + \ keepend contains=@htmlCoffeeScript,jsImport,jsExport,svelteTag + +syntax region typescriptSvelteScript fold + \ start=+]*lang="\(ts\|typescript\)"[^>]*>+ + \ end=++ + \ keepend contains=@TypeScript,svelteTag + +syntax region cssLessSvelteStyle fold + \ start=+]*lang="less"[^>]*>+ + \ end=++ + \ keepend contains=@LessSyntax,svelteTag +syntax region cssSassSvelteStyle fold + \ start=+]*lang="sass"[^>]*>+ + \ end=++ + \ keepend contains=@SassSyntax,svelteTag +syntax region cssScssSvelteStyle fold + \ start=+]*lang="scss"[^>]*>+ + \ end=++ + \ keepend contains=@SassSyntax,svelteTag + +syntax region svelteTag + \ start=+^<[^/]+ end=+>+ skip=+>+ + \ contained contains=htmlTagN,htmlString,htmlArg +syntax keyword svelteKeyword $ contained + +highlight default link svelteTag htmlTag +highlight default link svelteKeyword Keyword +highlight default link cssUnitDecorators2 Number +highlight default link cssKeyFrameProp2 Constant +"}}} + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" +" Syntax patch {{{ +" +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Patch 7.4.1142 +if has("patch-7.4-1142") + if has("win32") + syn iskeyword @,48-57,_,128-167,224-235,$ else - return 0 + syn iskeyword @,48-57,_,192-255,$ endif -endfunction +endif -" Default tag definitions. -let s:languages = [ - \ { 'name': 'less', 'tag': 'style' }, - \ { 'name': 'scss', 'tag': 'style' }, - \ { 'name': 'sass', 'tag': 'style' }, - \ { 'name': 'stylus', 'tag': 'style' }, - \ { 'name': 'typescript', 'tag': 'script' }, - \ ] - -" Add global tag definitions to our defaults. -if exists('g:svelte_preprocessor_tags') && type(g:svelte_preprocessor_tags) == v:t_list - let s:languages += g:svelte_preprocessor_tags +" Style +" Redefine (less|sass)Definition to highlight