1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
" Vim filetype plugin file
" Language: Astro
" Maintainer: Romain Lafourcade <romainlafourcade@gmail.com>
" Last Change: 2024 Apr 21
if exists("b:did_ftplugin")
finish
endif
let b:did_ftplugin = 1
let s:cpo_save = &cpo
set cpo-=C
function! s:IdentifyScope(start, end) abort
let pos_start = searchpairpos(a:start, '', a:end, 'bnW')
let pos_end = searchpairpos(a:start, '', a:end, 'nW')
return pos_start != [0, 0]
\ && pos_end != [0, 0]
\ && pos_start[0] != getpos('.')[1]
endfunction
function! s:AstroComments() abort
if s:IdentifyScope('^---\n\s*\S', '^---\n\n')
\ || s:IdentifyScope('^\s*<script', '^\s*<\/script>')
" ECMAScript comments
setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,://
setlocal commentstring=//%s
elseif s:IdentifyScope('^\s*<style', '^\s*<\/style>')
" CSS comments
setlocal comments=s1:/*,mb:*,ex:*/
setlocal commentstring=/*%s*/
else
" HTML comments
setlocal comments=s:<!--,m:\ \ \ \ ,e:-->
setlocal commentstring=<!--%s-->
endif
endfunction
" https://code.visualstudio.com/docs/languages/jsconfig
function! s:CollectPathsFromConfig() abort
let config_json = findfile('tsconfig.json', '.;')
if empty(config_json)
let config_json = findfile('jsconfig.json', '.;')
if empty(config_json)
return
endif
endif
let paths_from_config = config_json
\ ->readfile()
\ ->filter({ _, val -> val =~ '^\s*[\[\]{}"0-9]' })
\ ->join()
\ ->json_decode()
\ ->get('compilerOptions', {})
\ ->get('paths', {})
if !empty(paths_from_config)
let b:astro_paths = paths_from_config
\ ->map({key, val -> [
\ key->glob2regpat(),
\ val[0]->substitute('\/\*$', '', '')
\ ]})
\ ->values()
endif
let b:undo_ftplugin ..= " | unlet! b:astro_paths"
endfunction
function! s:AstroInclude(filename) abort
let decorated_filename = a:filename
\ ->substitute("^", "@", "")
let found_path = b:
\ ->get("astro_paths", [])
\ ->indexof({ key, val -> decorated_filename =~ val[0]})
if found_path != -1
let alias = b:astro_paths[found_path][0]
let path = b:astro_paths[found_path][1]
\ ->substitute('\(\/\)*$', '/', '')
return decorated_filename
\ ->substitute(alias, path, '')
endif
return a:filename
endfunction
let b:undo_ftplugin = "setlocal"
\ .. " formatoptions<"
\ .. " path<"
\ .. " suffixesadd<"
\ .. " matchpairs<"
\ .. " comments<"
\ .. " commentstring<"
\ .. " iskeyword<"
\ .. " define<"
\ .. " include<"
\ .. " includeexpr<"
" Create self-resetting autocommand group
augroup Astro
autocmd! * <buffer>
augroup END
" Set 'formatoptions' to break comment lines but not other lines,
" and insert the comment leader when hitting <CR> or using "o".
setlocal formatoptions-=t
setlocal formatoptions+=croql
" Remove irrelevant part of 'path'.
setlocal path-=/usr/include
" Seed 'path' with default directories for :find, gf, etc.
setlocal path+=src/**
setlocal path+=public/**
" Help Vim find extension-less filenames
let &l:suffixesadd =
\ ".astro"
\ .. ",.js,.jsx,.es,.es6,.cjs,.mjs,.jsm"
\ .. ",.json"
\ .. ",.scss,.sass,.css"
\ .. ",.svelte"
\ .. ",.ts,.tsx,.d.ts"
\ .. ",.vue"
" From $VIMRUNTIME/ftplugin/html.vim
setlocal matchpairs+=<:>
" Matchit configuration
if exists("loaded_matchit")
let b:match_ignorecase = 0
" From $VIMRUNTIME/ftplugin/javascript.vim
let b:match_words =
\ '\<do\>:\<while\>,'
\ .. '<\@<=\([^ \t>/]\+\)\%(\s\+[^>]*\%([^/]>\|$\)\|>\|$\):<\@<=/\1>,'
\ .. '<\@<=\%([^ \t>/]\+\)\%(\s\+[^/>]*\|$\):/>'
" From $VIMRUNTIME/ftplugin/html.vim
let b:match_words ..=
\ '<!--:-->,'
\ .. '<:>,'
\ .. '<\@<=[ou]l\>[^>]*\%(>\|$\):<\@<=li\>:<\@<=/[ou]l>,'
\ .. '<\@<=dl\>[^>]*\%(>\|$\):<\@<=d[td]\>:<\@<=/dl>,'
\ .. '<\@<=\([^/!][^ \t>]*\)[^>]*\%(>\|$\):<\@<=/\1>'
let b:undo_ftplugin ..= " | unlet! b:match_ignorecase b:match_words"
endif
" Change what constitutes a word, mainly useful for CSS/SASS
setlocal iskeyword+=-
setlocal iskeyword+=$
setlocal iskeyword+=%
" Define paths/aliases for module resolution
call s:CollectPathsFromConfig()
" Find ESM imports
setlocal include=^\\s*\\(import\\\|import\\s\\+[^\/]\\+from\\)\\s\\+['\"]
" Process aliases if file can't be found
setlocal includeexpr=s:AstroInclude(v:fname)
" Set 'define' to a comprehensive value
" From $VIMRUNTIME/ftplugin/javascript.vim and
" $VIMRUNTIME/ftplugin/sass.vim
let &l:define =
\ '\(^\s*(*async\s\+function\|(*function\)'
\ .. '\|^\s*\(\*\|static\|async\|get\|set\|\i\+\.\)'
\ .. '\|^\s*\(\ze\i\+\)\(([^)]*).*{$\|\s*[:=,]\)'
" Set &comments and &commentstring according to current scope
autocmd Astro CursorMoved <buffer> call s:AstroComments()
let &cpo = s:cpo_save
unlet s:cpo_save
" vim: textwidth=78 tabstop=8 shiftwidth=4 softtabstop=4 expandtab
|