Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ftplugin/astro.vim and autoload/astro.vim #3

Merged
merged 1 commit into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions autoload/astro.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
function! astro#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! astro#AstroComments() abort
if astro#IdentifyScope('^---\n\s*\S', '^---\n\n')
\ || astro#IdentifyScope('^\s*<script', '^\s*<\/script>')
" ECMAScript comments
setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,://
setlocal commentstring=//%s

elseif astro#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! astro#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()
\ ->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! astro#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
112 changes: 112 additions & 0 deletions ftplugin/astro.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
" Vim filetype plugin file
" Language: Astro
" Maintainer: Romain Lafourcade <romainlafourcade@gmail.com>
" Last Change: 2022 Dec 5

if exists("b:did_ftplugin")
finish
endif
let b:did_ftplugin = 1

let s:cpo_save = &cpo
set cpo-=C

let b:undo_ftplugin = "setlocal"
\ .. " formatoptions<"
\ .. " path<"
\ .. " suffixesadd<"
\ .. " matchpairs<"
\ .. " comments<"
\ .. " commentstring<"
\ .. " iskeyword<"
\ .. " define<"
\ .. " include<"
\ .. " includeexpr<"

" Create self-resetting autocommand group
augroup Astro
autocmd!
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 astro#CollectPathsFromConfig()

" Find ESM imports
setlocal include=^\\s*\\(import\\\|import\\s\\+[^\/]\\+from\\)\\s\\+['\"]

" Process aliases if file can't be found
setlocal includeexpr=astro#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*[:=,]\)'
\ .. '\|^\s*\(export\s\+\|export\s\+default\s\+\)*\(var\|let\|const\|function\|class\)'
\ .. '\|\<as\>'
\ .. '\|^\C\v\s*%(\@function|\@mixin|\=)|^\s*%(\$[[:alnum:]-]+:|[%.][:alnum:]-]+\s*%(\{|$))@='

" HTML comments by default
setlocal comments=s:<!--,m:\ \ \ \ ,e:-->
setlocal commentstring=<!--%s-->

" Set &comments and &commentstring according to current scope
autocmd Astro CursorMoved <buffer> call astro#AstroComments()

let &cpo = s:cpo_save
unlet s:cpo_save

" vim: textwidth=78 tabstop=8 shiftwidth=4 softtabstop=4 expandtab