Add livescript, closes #135
This commit is contained in:
parent
b9ce3df4cd
commit
cb574b283f
@ -65,6 +65,7 @@ Optionally download one of the [releases](https://github.com/sheerun/vim-polyglo
|
||||
- [latex](https://github.com/LaTeX-Box-Team/LaTeX-Box) (syntax, indent, ftplugin)
|
||||
- [less](https://github.com/groenewege/vim-less) (syntax, indent, ftplugin, ftdetect)
|
||||
- [liquid](https://github.com/tpope/vim-liquid) (syntax, indent, ftplugin, ftdetect)
|
||||
- [livescript](https://github.com/gkz/vim-ls) (syntax, indent, compiler, ftplugin, ftdetect)
|
||||
- [lua](https://github.com/tbastos/vim-lua) (syntax, indent)
|
||||
- [mako](https://github.com/sophacles/vim-bundle-mako) (syntax, indent, ftplugin, ftdetect)
|
||||
- [markdown](https://github.com/plasticboy/vim-markdown) (syntax, ftdetect)
|
||||
|
1
build
1
build
@ -139,6 +139,7 @@ PACKS="
|
||||
latex:LaTeX-Box-Team/LaTeX-Box
|
||||
less:groenewege/vim-less
|
||||
liquid:tpope/vim-liquid
|
||||
livescript:gkz/vim-ls
|
||||
lua:tbastos/vim-lua
|
||||
mako:sophacles/vim-bundle-mako
|
||||
markdown:plasticboy/vim-markdown:_SYNTAX
|
||||
|
78
compiler/ls.vim
Normal file
78
compiler/ls.vim
Normal file
@ -0,0 +1,78 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'livescript') == -1
|
||||
|
||||
" Language: LiveScript
|
||||
" Maintainer: George Zahariev
|
||||
" URL: http://github.com/gkz/vim-ls
|
||||
" License: WTFPL
|
||||
|
||||
if exists('current_compiler')
|
||||
finish
|
||||
endif
|
||||
|
||||
let current_compiler = 'ls'
|
||||
" Pattern to check if livescript is the compiler
|
||||
let s:pat = '^' . current_compiler
|
||||
|
||||
" Path to LiveScript compiler
|
||||
if !exists('livescript_compiler')
|
||||
let livescript_compiler = 'lsc'
|
||||
endif
|
||||
|
||||
if !exists('livescript_make_options')
|
||||
let livescript_make_options = ''
|
||||
endif
|
||||
|
||||
" Get a `makeprg` for the current filename. This is needed to support filenames
|
||||
" with spaces and quotes, but also not break generic `make`.
|
||||
function! s:GetMakePrg()
|
||||
return g:livescript_compiler . ' -c ' . g:livescript_make_options . ' $* '
|
||||
\ . fnameescape(expand('%'))
|
||||
endfunction
|
||||
|
||||
" Set `makeprg` and return 1 if coffee is still the compiler, else return 0.
|
||||
function! s:SetMakePrg()
|
||||
if &l:makeprg =~ s:pat
|
||||
let &l:makeprg = s:GetMakePrg()
|
||||
elseif &g:makeprg =~ s:pat
|
||||
let &g:makeprg = s:GetMakePrg()
|
||||
else
|
||||
return 0
|
||||
endif
|
||||
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
" Set a dummy compiler so we can check whether to set locally or globally.
|
||||
CompilerSet makeprg=ls
|
||||
call s:SetMakePrg()
|
||||
|
||||
CompilerSet errorformat=%EFailed\ at:\ %f,
|
||||
\%ECan't\ find:\ %f,
|
||||
\%CSyntaxError:\ %m\ on\ line\ %l,
|
||||
\%CError:\ Parse\ error\ on\ line\ %l:\ %m,
|
||||
\%C,%C\ %.%#
|
||||
|
||||
" Compile the current file.
|
||||
command! -bang -bar -nargs=* LiveScriptMake make<bang> <args>
|
||||
|
||||
" Set `makeprg` on rename since we embed the filename in the setting.
|
||||
augroup LiveScriptUpdateMakePrg
|
||||
autocmd!
|
||||
|
||||
" Update `makeprg` if livescript is still the compiler, else stop running this
|
||||
" function.
|
||||
function! s:UpdateMakePrg()
|
||||
if !s:SetMakePrg()
|
||||
autocmd! LiveScriptUpdateMakePrg
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Set autocmd locally if compiler was set locally.
|
||||
if &l:makeprg =~ s:pat
|
||||
autocmd BufFilePost,BufWritePost <buffer> call s:UpdateMakePrg()
|
||||
else
|
||||
autocmd BufFilePost,BufWritePost call s:UpdateMakePrg()
|
||||
endif
|
||||
augroup END
|
||||
|
||||
endif
|
@ -44,3 +44,49 @@ if version >= 508 || !exists("did_javascript_syn_inits")
|
||||
endif
|
||||
|
||||
endif
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'javascript') == -1
|
||||
|
||||
syntax region jsFlowTypeStatement start=/type/ end=/=/ oneline skipwhite skipempty nextgroup=jsFlowTypeObject
|
||||
syntax region jsFlowDeclareBlock start=/declare/ end=/[;\n]/ oneline contains=jsFlow,jsFlowDeclareKeyword,jsFlowStorageClass
|
||||
syntax region jsFlow start=/:/ end=/\%(\%([),=;\n]\|{\%(.*}\)\@!\|\%({.*}\)\@<=\s*{\)\@=\|void\)/ contains=@jsFlowCluster oneline skipwhite skipempty nextgroup=jsFuncBlock
|
||||
syntax region jsFlowReturn contained start=/:/ end=/\%(\S\s*\%({\%(.*}\)\@!\)\@=\|\n\)/ contains=@jsFlowCluster oneline skipwhite skipempty nextgroup=jsFuncBlock keepend
|
||||
syntax region jsFlowTypeObject contained start=/{/ end=/}/ contains=jsFlowTypeKey skipwhite skipempty nextgroup=jsFunctionBlock extend
|
||||
syntax match jsFlowTypeKey contained /\<[0-9a-zA-Z_$?]*\>\(\s*:\)\@=/ skipwhite skipempty nextgroup=jsFlowTypeValue
|
||||
syntax region jsFlowTypeValue contained matchgroup=jsFlowNoise start=/:/ end=/[,}]/ contains=@jsFlowCluster
|
||||
syntax region jsFlowObject contained matchgroup=jsFlowNoise start=/{/ end=/}/ oneline contains=@jsFlowCluster
|
||||
syntax region jsFlowArray contained matchgroup=jsFlowNoise start=/\[/ end=/\]/ oneline contains=@jsFlowCluster
|
||||
syntax region jsFlowArrow contained matchgroup=jsFlowNoise start=/(/ end=/)\s*=>/ oneline contains=@jsFlowCluster
|
||||
syntax keyword jsFlowDeclareKeyword contained declare
|
||||
syntax keyword jsFlowType contained boolean number string null void any mixed JSON array function object Array
|
||||
syntax match jsFlowClassProperty contained /\<[0-9a-zA-Z_$]*\>:\@=/ skipwhite skipempty nextgroup=jsFlow
|
||||
syntax match jsFlowNoise contained /[:;,<>]/
|
||||
syntax cluster jsFlowCluster contains=jsFlowType,jsFlowArray,jsFlowObject,jsFlowNoise,jsFlowArrow
|
||||
syntax keyword jsFlowStorageClass contained const var let
|
||||
syntax region jsFlowParenRegion contained start=/:\s*(/ end=/)\%(\s*:\)\@=/ oneline contains=@jsFlowCluster skipwhite skipempty nextgroup=jsObjectValue
|
||||
syntax region jsFlowClass contained matchgroup=jsFlowNoise start=/</ end=/>/ oneline contains=@jsFlowCluster skipwhite skipempty nextgroup=jsClassBlock
|
||||
|
||||
if version >= 508 || !exists("did_javascript_syn_inits")
|
||||
if version < 508
|
||||
let did_javascript_syn_inits = 1
|
||||
command -nargs=+ HiLink hi link <args>
|
||||
else
|
||||
command -nargs=+ HiLink hi def link <args>
|
||||
endif
|
||||
HiLink jsFlow PreProc
|
||||
HiLink jsFlowReturn PreProc
|
||||
HiLink jsFlowArray PreProc
|
||||
HiLink jsFlowDeclareBlock PreProc
|
||||
HiLink jsFlowObject PreProc
|
||||
HiLink jsFlowParenRegion PreProc
|
||||
HiLink jsFlowClass PreProc
|
||||
HiLink jsFlowTypeObject PreProc
|
||||
HiLink jsFlowTypeKey PreProc
|
||||
HiLink jsFlowTypeValue PreProc
|
||||
HiLink jsFlowClassProperty jsClassProperty
|
||||
HiLink jsFlowType Type
|
||||
HiLink jsFlowDeclareKeyword Type
|
||||
HiLink jsFlowNoise Noise
|
||||
delcommand HiLink
|
||||
endif
|
||||
|
||||
endif
|
||||
|
@ -41,3 +41,46 @@ if version >= 508 || !exists("did_javascript_syn_inits")
|
||||
endif
|
||||
|
||||
endif
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'javascript') == -1
|
||||
|
||||
"" syntax coloring for javadoc comments (HTML)
|
||||
syntax region jsComment matchgroup=jsComment start="/\*\s*" end="\*/" contains=jsDocTags,jsCommentTodo,jsCvsTag,@jsHtml,@Spell fold
|
||||
|
||||
" tags containing a param
|
||||
syntax match jsDocTags contained "@\(alias\|api\|augments\|borrows\|class\|constructs\|default\|defaultvalue\|emits\|exception\|exports\|extends\|fires\|kind\|link\|listens\|member\|member[oO]f\|mixes\|module\|name\|namespace\|requires\|template\|throws\|var\|variation\|version\)\>" skipwhite nextgroup=jsDocParam
|
||||
" tags containing type and param
|
||||
syntax match jsDocTags contained "@\(arg\|argument\|cfg\|param\|property\|prop\)\>" skipwhite nextgroup=jsDocType
|
||||
" tags containing type but no param
|
||||
syntax match jsDocTags contained "@\(callback\|define\|enum\|external\|implements\|this\|type\|typedef\|return\|returns\)\>" skipwhite nextgroup=jsDocTypeNoParam
|
||||
" tags containing references
|
||||
syntax match jsDocTags contained "@\(lends\|see\|tutorial\)\>" skipwhite nextgroup=jsDocSeeTag
|
||||
" other tags (no extra syntax)
|
||||
syntax match jsDocTags contained "@\(abstract\|access\|accessor\|author\|classdesc\|constant\|const\|constructor\|copyright\|deprecated\|desc\|description\|dict\|event\|example\|file\|file[oO]verview\|final\|function\|global\|ignore\|inheritDoc\|inner\|instance\|interface\|license\|localdoc\|method\|mixin\|nosideeffects\|override\|overview\|preserve\|private\|protected\|public\|readonly\|since\|static\|struct\|todo\|summary\|undocumented\|virtual\)\>"
|
||||
|
||||
syntax region jsDocType contained matchgroup=jsDocTypeBrackets start="{" end="}" contains=jsDocTypeRecord oneline skipwhite nextgroup=jsDocParam
|
||||
syntax match jsDocType contained "\%(#\|\"\|\w\|\.\|:\|\/\)\+" skipwhite nextgroup=jsDocParam
|
||||
syntax region jsDocTypeRecord contained start=/{/ end=/}/ contains=jsDocTypeRecord extend
|
||||
syntax region jsDocTypeRecord contained start=/\[/ end=/\]/ contains=jsDocTypeRecord extend
|
||||
syntax region jsDocTypeNoParam contained start="{" end="}" oneline
|
||||
syntax match jsDocTypeNoParam contained "\%(#\|\"\|\w\|\.\|:\|\/\)\+"
|
||||
syntax match jsDocParam contained "\%(#\|\$\|-\|'\|\"\|{.\{-}}\|\w\|\.\|:\|\/\|\[.{-}]\|=\)\+"
|
||||
syntax region jsDocSeeTag contained matchgroup=jsDocSeeTag start="{" end="}" contains=jsDocTags
|
||||
|
||||
if version >= 508 || !exists("did_javascript_syn_inits")
|
||||
if version < 508
|
||||
let did_javascript_syn_inits = 1
|
||||
command -nargs=+ HiLink hi link <args>
|
||||
else
|
||||
command -nargs=+ HiLink hi def link <args>
|
||||
endif
|
||||
HiLink jsDocTags Special
|
||||
HiLink jsDocSeeTag Function
|
||||
HiLink jsDocType Type
|
||||
HiLink jsDocTypeBrackets jsDocType
|
||||
HiLink jsDocTypeRecord jsDocType
|
||||
HiLink jsDocTypeNoParam Type
|
||||
HiLink jsDocParam Label
|
||||
delcommand HiLink
|
||||
endif
|
||||
|
||||
endif
|
||||
|
@ -5,3 +5,10 @@ syntax match jsDocType contained "\%(#\|\$\|\w\|\"\|-\|\.\|:\|\/\)\+" n
|
||||
syntax match jsDocParam contained "\%(#\|\$\|\w\|\"\|-\|\.\|:\|{\|}\|\/\|\[\|]\|=\)\+"
|
||||
|
||||
endif
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'javascript') == -1
|
||||
|
||||
syntax match jsDocTags contained /@\(link\|method[oO]f\|ngdoc\|ng[iI]nject\|restrict\)/ nextgroup=jsDocParam skipwhite
|
||||
syntax match jsDocType contained "\%(#\|\$\|\w\|\"\|-\|\.\|:\|\/\)\+" nextgroup=jsDocParam skipwhite
|
||||
syntax match jsDocParam contained "\%(#\|\$\|\w\|\"\|-\|\.\|:\|{\|}\|\/\|\[\|]\|=\)\+"
|
||||
|
||||
endif
|
||||
|
@ -475,6 +475,19 @@ au BufNewFile,BufRead */templates/**.liquid,*/layout/**.liquid,*/snippets/**.liq
|
||||
|
||||
endif
|
||||
|
||||
" ftdetect/ls.vim
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'livescript') == -1
|
||||
|
||||
" Language: LiveScript
|
||||
" Maintainer: George Zahariev
|
||||
" URL: http://github.com/gkz/vim-ls
|
||||
" License: WTFPL
|
||||
"
|
||||
autocmd BufNewFile,BufRead *.ls set filetype=ls
|
||||
autocmd BufNewFile,BufRead *Slakefile set filetype=ls
|
||||
|
||||
endif
|
||||
|
||||
" ftdetect/mako.vim
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'mako') == -1
|
||||
|
||||
|
208
ftplugin/ls.vim
Normal file
208
ftplugin/ls.vim
Normal file
@ -0,0 +1,208 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'livescript') == -1
|
||||
|
||||
" Language: LiveScript
|
||||
" Maintainer: George Zahariev
|
||||
" URL: http://github.com/gkz/vim-ls
|
||||
" License: WTFPL
|
||||
"
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
endif
|
||||
|
||||
let b:did_ftplugin = 1
|
||||
|
||||
setlocal formatoptions-=t formatoptions+=croql
|
||||
setlocal comments=:#
|
||||
setlocal commentstring=#\ %s
|
||||
setlocal omnifunc=javascriptcomplete#CompleteJS
|
||||
|
||||
" Enable LiveScriptMake if it won't overwrite any settings.
|
||||
if !len(&l:makeprg)
|
||||
compiler ls
|
||||
endif
|
||||
|
||||
" Check here too in case the compiler above isn't loaded.
|
||||
if !exists('livescript_compiler')
|
||||
let livescript_compiler = 'lsc'
|
||||
endif
|
||||
|
||||
" Reset the LiveScriptCompile variables for the current buffer.
|
||||
function! s:LiveScriptCompileResetVars()
|
||||
" Compiled output buffer
|
||||
let b:livescript_compile_buf = -1
|
||||
let b:livescript_compile_pos = []
|
||||
|
||||
" If LiveScriptCompile is watching a buffer
|
||||
let b:livescript_compile_watch = 0
|
||||
endfunction
|
||||
|
||||
" Clean things up in the source buffer.
|
||||
function! s:LiveScriptCompileClose()
|
||||
exec bufwinnr(b:livescript_compile_src_buf) 'wincmd w'
|
||||
silent! autocmd! LiveScriptCompileAuWatch * <buffer>
|
||||
call s:LiveScriptCompileResetVars()
|
||||
endfunction
|
||||
|
||||
" Update the LiveScriptCompile buffer given some input lines.
|
||||
function! s:LiveScriptCompileUpdate(startline, endline)
|
||||
let input = join(getline(a:startline, a:endline), "\n")
|
||||
|
||||
" Move to the LiveScriptCompile buffer.
|
||||
exec bufwinnr(b:livescript_compile_buf) 'wincmd w'
|
||||
|
||||
" LiveScript doesn't like empty input.
|
||||
if !len(input)
|
||||
return
|
||||
endif
|
||||
|
||||
" Compile input.
|
||||
let output = system(g:livescript_compiler . ' -scb 2>&1', input)
|
||||
|
||||
" Be sure we're in the LiveScriptCompile buffer before overwriting.
|
||||
if exists('b:livescript_compile_buf')
|
||||
echoerr 'LiveScriptCompile buffers are messed up'
|
||||
return
|
||||
endif
|
||||
|
||||
" Replace buffer contents with new output and delete the last empty line.
|
||||
setlocal modifiable
|
||||
exec '% delete _'
|
||||
put! =output
|
||||
exec '$ delete _'
|
||||
setlocal nomodifiable
|
||||
|
||||
" Highlight as JavaScript if there is no compile error.
|
||||
if v:shell_error
|
||||
setlocal filetype=
|
||||
else
|
||||
setlocal filetype=javascript
|
||||
endif
|
||||
|
||||
call setpos('.', b:livescript_compile_pos)
|
||||
endfunction
|
||||
|
||||
" Update the LiveScriptCompile buffer with the whole source buffer.
|
||||
function! s:LiveScriptCompileWatchUpdate()
|
||||
call s:LiveScriptCompileUpdate(1, '$')
|
||||
exec bufwinnr(b:livescript_compile_src_buf) 'wincmd w'
|
||||
endfunction
|
||||
|
||||
" Peek at compiled LiveScript in a scratch buffer. We handle ranges like this
|
||||
" to prevent the cursor from being moved (and its position saved) before the
|
||||
" function is called.
|
||||
function! s:LiveScriptCompile(startline, endline, args)
|
||||
if !executable(g:livescript_compiler)
|
||||
echoerr "Can't find LiveScript compiler `" . g:livescript_compiler . "`"
|
||||
return
|
||||
endif
|
||||
|
||||
" If in the LiveScriptCompile buffer, switch back to the source buffer and
|
||||
" continue.
|
||||
if !exists('b:livescript_compile_buf')
|
||||
exec bufwinnr(b:livescript_compile_src_buf) 'wincmd w'
|
||||
endif
|
||||
|
||||
" Parse arguments.
|
||||
let watch = a:args =~ '\<watch\>'
|
||||
let unwatch = a:args =~ '\<unwatch\>'
|
||||
let size = str2nr(matchstr(a:args, '\<\d\+\>'))
|
||||
|
||||
" Determine default split direction.
|
||||
if exists('g:livescript_compile_vert')
|
||||
let vert = 1
|
||||
else
|
||||
let vert = a:args =~ '\<vert\%[ical]\>'
|
||||
endif
|
||||
|
||||
" Remove any watch listeners.
|
||||
silent! autocmd! LiveScriptCompileAuWatch * <buffer>
|
||||
|
||||
" If just unwatching, don't compile.
|
||||
if unwatch
|
||||
let b:livescript_compile_watch = 0
|
||||
return
|
||||
endif
|
||||
|
||||
if watch
|
||||
let b:livescript_compile_watch = 1
|
||||
endif
|
||||
|
||||
" Build the LiveScriptCompile buffer if it doesn't exist.
|
||||
if bufwinnr(b:livescript_compile_buf) == -1
|
||||
let src_buf = bufnr('%')
|
||||
let src_win = bufwinnr(src_buf)
|
||||
|
||||
" Create the new window and resize it.
|
||||
if vert
|
||||
let width = size ? size : winwidth(src_win) / 2
|
||||
|
||||
belowright vertical new
|
||||
exec 'vertical resize' width
|
||||
else
|
||||
" Try to guess the compiled output's height.
|
||||
let height = size ? size : min([winheight(src_win) / 2,
|
||||
\ a:endline - a:startline + 5])
|
||||
|
||||
belowright new
|
||||
exec 'resize' height
|
||||
endif
|
||||
|
||||
" We're now in the scratch buffer, so set it up.
|
||||
setlocal bufhidden=wipe buftype=nofile
|
||||
setlocal nobuflisted nomodifiable noswapfile nowrap
|
||||
|
||||
autocmd BufWipeout <buffer> call s:LiveScriptCompileClose()
|
||||
" Save the cursor when leaving the LiveScriptCompile buffer.
|
||||
autocmd BufLeave <buffer> let b:livescript_compile_pos = getpos('.')
|
||||
|
||||
nnoremap <buffer> <silent> q :hide<CR>
|
||||
|
||||
let b:livescript_compile_src_buf = src_buf
|
||||
let buf = bufnr('%')
|
||||
|
||||
" Go back to the source buffer and set it up.
|
||||
exec bufwinnr(b:livescript_compile_src_buf) 'wincmd w'
|
||||
let b:livescript_compile_buf = buf
|
||||
endif
|
||||
|
||||
if b:livescript_compile_watch
|
||||
call s:LiveScriptCompileWatchUpdate()
|
||||
|
||||
augroup LiveScriptCompileAuWatch
|
||||
autocmd InsertLeave <buffer> call s:LiveScriptCompileWatchUpdate()
|
||||
autocmd BufWritePost <buffer> call s:LiveScriptCompileWatchUpdate()
|
||||
augroup END
|
||||
else
|
||||
call s:LiveScriptCompileUpdate(a:startline, a:endline)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Complete arguments for the LiveScriptCompile command.
|
||||
function! s:LiveScriptCompileComplete(arg, cmdline, cursor)
|
||||
let args = ['unwatch', 'vertical', 'watch']
|
||||
|
||||
if !len(a:arg)
|
||||
return args
|
||||
endif
|
||||
|
||||
let match = '^' . a:arg
|
||||
|
||||
for arg in args
|
||||
if arg =~ match
|
||||
return [arg]
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" Don't overwrite the CoffeeCompile variables.
|
||||
if !exists("s:livescript_compile_buf")
|
||||
call s:LiveScriptCompileResetVars()
|
||||
endif
|
||||
|
||||
" Peek at compiled LiveScript.
|
||||
command! -range=% -bar -nargs=* -complete=customlist,s:LiveScriptCompileComplete
|
||||
\ LiveScriptCompile call s:LiveScriptCompile(<line1>, <line2>, <q-args>)
|
||||
" Run some LiveScript.
|
||||
command! -range=% -bar LiveScriptRun <line1>,<line2>:w !lsc -sp
|
||||
|
||||
endif
|
268
indent/ls.vim
Normal file
268
indent/ls.vim
Normal file
@ -0,0 +1,268 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'livescript') == -1
|
||||
|
||||
" Language: LiveScript
|
||||
" Maintainer: George Zahariev
|
||||
" URL: http://github.com/gkz/vim-ls
|
||||
" License: WTFPL
|
||||
|
||||
if exists("b:did_indent")
|
||||
finish
|
||||
endif
|
||||
|
||||
let b:did_indent = 1
|
||||
|
||||
setlocal autoindent
|
||||
setlocal indentexpr=GetLiveScriptIndent(v:lnum)
|
||||
" Make sure GetLiveScriptIndent is run when these are typed so they can be
|
||||
" indented or outdented.
|
||||
setlocal indentkeys+=0],0),0.,=else,=when,=catch,=finally
|
||||
|
||||
" Only define the function once.
|
||||
if exists("*GetLiveScriptIndent")
|
||||
finish
|
||||
endif
|
||||
|
||||
" Keywords to indent after
|
||||
let s:INDENT_AFTER_KEYWORD = '^\%(if\|unless\|else\|for\|while\|until\|'
|
||||
\ . 'loop\|case\|default\|try\|catch\|finally\|'
|
||||
\ . 'class\|do\|new\|let\|with\|function\)\>'
|
||||
|
||||
" Operators to indent after
|
||||
let s:INDENT_AFTER_OPERATOR = '\%([([{:=]\|[-=]>\)$'
|
||||
|
||||
" Keywords and operators that continue a line
|
||||
let s:CONTINUATION = '\<\%(is\|isnt\|and\|or\|do\)\>$'
|
||||
\ . '\|'
|
||||
\ . '\%(-\@<!-\|+\@<!+\|<\|[-~]\@<!>\|\*\|/\@<!/\|%\||\|'
|
||||
\ . '&\|,\|\.\@<!\.\)$'
|
||||
|
||||
" Operators that block continuation indenting
|
||||
let s:CONTINUATION_BLOCK = '[([{:=]$'
|
||||
|
||||
" A continuation dot access
|
||||
let s:DOT_ACCESS = '^\.'
|
||||
|
||||
" Keywords to outdent after
|
||||
let s:OUTDENT_AFTER = '^\%(return\|break\|continue\|throw\)\>'
|
||||
|
||||
" A compound assignment like `... = if ...`
|
||||
let s:COMPOUND_ASSIGNMENT = '[:=]\s*\%(if\|unless\|for\|while\|until\|'
|
||||
\ . 'try\|class\|do\|new\|let\|with\)\>'
|
||||
|
||||
" A postfix condition like `return ... if ...`.
|
||||
let s:POSTFIX_CONDITION = '\S\s\+\zs\<\%(if\|unless\)\>'
|
||||
|
||||
" A single-line else statement like `else ...` but not `else if ...
|
||||
let s:SINGLE_LINE_ELSE = '^else\s\+\%(\<\%(if\|unless\)\>\)\@!'
|
||||
|
||||
" Max lines to look back for a match
|
||||
let s:MAX_LOOKBACK = 50
|
||||
|
||||
" Get the linked syntax name of a character.
|
||||
function! s:SyntaxName(linenum, col)
|
||||
return synIDattr(synIDtrans(synID(a:linenum, a:col, 1)), 'name')
|
||||
endfunction
|
||||
|
||||
" Check if a character is in a comment.
|
||||
function! s:IsComment(linenum, col)
|
||||
return s:SyntaxName(a:linenum, a:col) == 'Comment'
|
||||
endfunction
|
||||
|
||||
" Check if a character is in a string.
|
||||
function! s:IsString(linenum, col)
|
||||
return s:SyntaxName(a:linenum, a:col) == 'Constant'
|
||||
endfunction
|
||||
|
||||
" Check if a character is in a comment or string.
|
||||
function! s:IsCommentOrString(linenum, col)
|
||||
return s:SyntaxName(a:linenum, a:col) =~ 'Comment\|Constant'
|
||||
endfunction
|
||||
|
||||
" Check if a whole line is a comment.
|
||||
function! s:IsCommentLine(linenum)
|
||||
" Check the first non-whitespace character.
|
||||
return s:IsComment(a:linenum, indent(a:linenum) + 1)
|
||||
endfunction
|
||||
|
||||
" Repeatedly search a line for a regex until one is found outside a string or
|
||||
" comment.
|
||||
function! s:SmartSearch(linenum, regex)
|
||||
" Start at the first column.
|
||||
let col = 0
|
||||
|
||||
" Search until there are no more matches, unless a good match is found.
|
||||
while 1
|
||||
call cursor(a:linenum, col + 1)
|
||||
let [_, col] = searchpos(a:regex, 'cn', a:linenum)
|
||||
|
||||
" No more matches.
|
||||
if !col
|
||||
break
|
||||
endif
|
||||
|
||||
if !s:IsCommentOrString(a:linenum, col)
|
||||
return 1
|
||||
endif
|
||||
endwhile
|
||||
|
||||
" No good match found.
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" Skip a match if it's in a comment or string, is a single-line statement that
|
||||
" isn't adjacent, or is a postfix condition.
|
||||
function! s:ShouldSkip(startlinenum, linenum, col)
|
||||
if s:IsCommentOrString(a:linenum, a:col)
|
||||
return 1
|
||||
endif
|
||||
|
||||
" Check for a single-line statement that isn't adjacent.
|
||||
if s:SmartSearch(a:linenum, '\<then\>') && a:startlinenum - a:linenum > 1
|
||||
return 1
|
||||
endif
|
||||
|
||||
if s:SmartSearch(a:linenum, s:POSTFIX_CONDITION) &&
|
||||
\ !s:SmartSearch(a:linenum, s:COMPOUND_ASSIGNMENT)
|
||||
return 1
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" Find the farthest line to look back to, capped to line 1 (zero and negative
|
||||
" numbers cause bad things).
|
||||
function! s:MaxLookback(startlinenum)
|
||||
return max([1, a:startlinenum - s:MAX_LOOKBACK])
|
||||
endfunction
|
||||
|
||||
" Get the skip expression for searchpair().
|
||||
function! s:SkipExpr(startlinenum)
|
||||
return "s:ShouldSkip(" . a:startlinenum . ", line('.'), col('.'))"
|
||||
endfunction
|
||||
|
||||
" Search for pairs of text.
|
||||
function! s:SearchPair(start, end)
|
||||
" The cursor must be in the first column for regexes to match.
|
||||
call cursor(0, 1)
|
||||
|
||||
let startlinenum = line('.')
|
||||
|
||||
" Don't need the W flag since MaxLookback caps the search to line 1.
|
||||
return searchpair(a:start, '', a:end, 'bcn',
|
||||
\ s:SkipExpr(startlinenum),
|
||||
\ s:MaxLookback(startlinenum))
|
||||
endfunction
|
||||
|
||||
" Try to find a previous matching line.
|
||||
function! s:GetMatch(curline)
|
||||
let firstchar = a:curline[0]
|
||||
|
||||
if firstchar == '}'
|
||||
return s:SearchPair('{', '}')
|
||||
elseif firstchar == ')'
|
||||
return s:SearchPair('(', ')')
|
||||
elseif firstchar == ']'
|
||||
return s:SearchPair('\[', '\]')
|
||||
elseif a:curline =~ '^else\>'
|
||||
return s:SearchPair('\<\%(if\|unless\|case\|when\)\>', '\<else\>')
|
||||
elseif a:curline =~ '^catch\>'
|
||||
return s:SearchPair('\<try\>', '\<catch\>')
|
||||
elseif a:curline =~ '^finally\>'
|
||||
return s:SearchPair('\<try\>', '\<finally\>')
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" Get the nearest previous line that isn't a comment.
|
||||
function! s:GetPrevNormalLine(startlinenum)
|
||||
let curlinenum = a:startlinenum
|
||||
|
||||
while curlinenum > 0
|
||||
let curlinenum = prevnonblank(curlinenum - 1)
|
||||
|
||||
if !s:IsCommentLine(curlinenum)
|
||||
return curlinenum
|
||||
endif
|
||||
endwhile
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" Get the contents of a line without leading or trailing whitespace.
|
||||
function! s:GetTrimmedLine(linenum)
|
||||
return substitute(substitute(getline(a:linenum), '^\s\+', '', ''),
|
||||
\ '\s\+$', '', '')
|
||||
endfunction
|
||||
|
||||
function! s:GetLiveScriptIndent(curlinenum)
|
||||
let prevlinenum = s:GetPrevNormalLine(a:curlinenum)
|
||||
|
||||
" Don't do anything if there's no previous line.
|
||||
if !prevlinenum
|
||||
return -1
|
||||
endif
|
||||
|
||||
let curline = s:GetTrimmedLine(a:curlinenum)
|
||||
|
||||
" Try to find a previous matching statement. This handles outdenting.
|
||||
let matchlinenum = s:GetMatch(curline)
|
||||
|
||||
if matchlinenum
|
||||
return indent(matchlinenum)
|
||||
endif
|
||||
|
||||
let prevline = s:GetTrimmedLine(prevlinenum)
|
||||
let previndent = indent(prevlinenum)
|
||||
|
||||
" Always indent after these operators.
|
||||
if prevline =~ s:INDENT_AFTER_OPERATOR
|
||||
return previndent + &shiftwidth
|
||||
endif
|
||||
|
||||
" Indent after a continuation if it's the first.
|
||||
if prevline =~ s:CONTINUATION
|
||||
let prevprevlinenum = s:GetPrevNormalLine(prevlinenum)
|
||||
let prevprevline = s:GetTrimmedLine(prevprevlinenum)
|
||||
|
||||
if prevprevline !~ s:CONTINUATION && prevprevline !~ s:CONTINUATION_BLOCK
|
||||
return previndent + &shiftwidth
|
||||
endif
|
||||
endif
|
||||
|
||||
" Indent after these keywords and compound assignments if they aren't a
|
||||
" single-line statement.
|
||||
if prevline =~ s:INDENT_AFTER_KEYWORD || prevline =~ s:COMPOUND_ASSIGNMENT
|
||||
if !s:SmartSearch(prevlinenum, '\<then\>') && prevline !~ s:SINGLE_LINE_ELSE
|
||||
return previndent + &shiftwidth
|
||||
endif
|
||||
endif
|
||||
|
||||
" Indent a dot access if it's the first.
|
||||
if curline =~ s:DOT_ACCESS && prevline !~ s:DOT_ACCESS
|
||||
return previndent + &shiftwidth
|
||||
endif
|
||||
|
||||
" Outdent after these keywords if they don't have a postfix condition and
|
||||
" aren't a single-line statement.
|
||||
if prevline =~ s:OUTDENT_AFTER
|
||||
if !s:SmartSearch(prevlinenum, s:POSTFIX_CONDITION) ||
|
||||
\ s:SmartSearch(prevlinenum, '\<then\>')
|
||||
return previndent - &shiftwidth
|
||||
endif
|
||||
endif
|
||||
|
||||
" No indenting or outdenting is needed.
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
" Wrap s:GetLiveScriptIndent to keep the cursor position.
|
||||
function! GetLiveScriptIndent(curlinenum)
|
||||
let oldcursor = getpos('.')
|
||||
let indent = s:GetLiveScriptIndent(a:curlinenum)
|
||||
call setpos('.', oldcursor)
|
||||
|
||||
return indent
|
||||
endfunction
|
||||
|
||||
endif
|
140
syntax/ls.vim
Normal file
140
syntax/ls.vim
Normal file
@ -0,0 +1,140 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'livescript') == -1
|
||||
|
||||
" Language: LiveScript "
|
||||
" Maintainer: George Zahariev
|
||||
" URL: http://github.com/gkz/vim-ls
|
||||
" License: WTFPL
|
||||
|
||||
if exists('b:current_syntax') && b:current_syntax == 'livescript'
|
||||
finish
|
||||
endif
|
||||
|
||||
let b:current_syntax = "ls"
|
||||
|
||||
" Highlight long strings.
|
||||
syntax sync minlines=100
|
||||
|
||||
setlocal iskeyword=48-57,A-Z,$,a-z,_,-
|
||||
|
||||
syntax match lsIdentifier /[$A-Za-z_]\k*\(-[a-zA-Z]\+\)*/
|
||||
highlight default link lsIdentifier Identifier
|
||||
|
||||
" These are 'matches' rather than 'keywords' because vim's highlighting priority
|
||||
" for keywords (the highest) causes them to be wrongly highlighted when used as
|
||||
" dot-properties.
|
||||
syntax match lsStatement /\<\%(return\|break\|continue\|throw\)\>/
|
||||
highlight default link lsStatement Statement
|
||||
|
||||
syntax match lsRepeat /\<\%(for\%( own\| ever\)\?\|while\|until\)\>/
|
||||
highlight default link lsRepeat Repeat
|
||||
|
||||
syntax match lsConditional /\<\%(if\|else\|unless\|switch\|case\|when\|default\|match\)\>/
|
||||
highlight default link lsConditional Conditional
|
||||
|
||||
syntax match lsException /\<\%(try\|catch\|finally\)\>/
|
||||
highlight default link lsException Exception
|
||||
|
||||
syntax match lsKeyword /\<\%(new\|in\%(stanceof\)\?\|typeof\|delete\|and\|o[fr]\|not\|xor\|is\|isnt\|imp\%(ort\%( all\)\?\|lements\)\|extends\|loop\|from\|to\|til\|by\|do\|then\|function\|class\|let\|with\|export\|const\|var\|eval\|super\|fallthrough\|debugger\|where\|yield\)\>/
|
||||
highlight default link lsKeyword Keyword
|
||||
|
||||
syntax match lsBoolean /\<\%(true\|false\|yes\|no\|on\|off\|null\|void\)\>/
|
||||
highlight default link lsBoolean Boolean
|
||||
|
||||
" Matches context variables.
|
||||
syntax match lsContext /\<\%(this\|arguments\|it\|that\|constructor\|prototype\|superclass\)\>/
|
||||
highlight default link lsContext Type
|
||||
|
||||
" Keywords reserved by the language
|
||||
syntax cluster lsReserved contains=lsStatement,lsRepeat,lsConditional,
|
||||
\ lsException,lsOperator,lsKeyword,lsBoolean
|
||||
|
||||
" Matches ECMAScript 5 built-in globals.
|
||||
syntax match lsGlobal /\<\%(Array\|Boolean\|Date\|Function\|JSON\|Math\|Number\|Object\|RegExp\|String\|\%(Syntax\|Type\|URI\)\?Error\|is\%(NaN\|Finite\)\|parse\%(Int\|Float\)\|\%(en\|de\)codeURI\%(Component\)\?\)\>/
|
||||
highlight default link lsGlobal Structure
|
||||
|
||||
syntax region lsString start=/"/ skip=/\\\\\|\\"/ end=/"/ contains=@lsInterpString
|
||||
syntax region lsString start=/'/ skip=/\\\\\|\\'/ end=/'/ contains=@lsSimpleString
|
||||
highlight default link lsString String
|
||||
|
||||
" Matches decimal/floating-point numbers like 10.42e-8.
|
||||
syntax match lsFloat
|
||||
\ /\%(\<-\?\|-\)\zs\d[0-9_]*\%(\.\d[0-9_]*\)\?\%(e[+-]\?\d[0-9_]*\)\?\%([a-zA-Z$][$a-zA-Z0-9_]*\)\?/
|
||||
\ contains=lsNumberComment
|
||||
highlight default link lsFloat Float
|
||||
syntax match lsNumberComment /\d\+\zs\%(e[+-]\?\d\)\@![a-zA-Z$][$a-zA-Z0-9_]*/ contained
|
||||
highlight default link lsNumberComment Comment
|
||||
" Matches hex numbers like 0xfff, 0x000.
|
||||
syntax match lsNumber /\%(\<-\?\|-\)\zs0x\x\+/
|
||||
" Matches N radix numbers like 2@1010.
|
||||
syntax match lsNumber
|
||||
\ /\%(\<-\?\|-\)\zs\%(\d*\)\~[0-9A-Za-z][0-9A-Za-z_]*/
|
||||
highlight default link lsNumber Number
|
||||
|
||||
" Displays an error for reserved words.
|
||||
syntax match lsReservedError /\<\%(enum\|interface\|package\|private\|protected\|public\|static\)\>/
|
||||
highlight default link lsReservedError Error
|
||||
|
||||
syntax keyword lsTodo TODO FIXME XXX contained
|
||||
highlight default link lsTodo Todo
|
||||
|
||||
syntax match lsComment /#.*/ contains=@Spell,lsTodo
|
||||
syntax region lsComment start=/\/\*/ end=/\*\// contains=@Spell,lsTodo
|
||||
highlight default link lsComment Comment
|
||||
|
||||
syntax region lsInfixFunc start=/`/ end=/`/
|
||||
highlight default link lsInfixFunc Identifier
|
||||
|
||||
syntax region lsInterpolation matchgroup=lsInterpDelim
|
||||
\ start=/\#{/ end=/}/
|
||||
\ contained contains=TOP
|
||||
highlight default link lsInterpDelim Delimiter
|
||||
|
||||
" Matches escape sequences like \000, \x00, \u0000, \n.
|
||||
syntax match lsEscape /\\\d\d\d\|\\x\x\{2\}\|\\u\x\{4\}\|\\./ contained
|
||||
highlight default link lsEscape SpecialChar
|
||||
|
||||
syntax match lsVarInterpolation /#[$A-Za-z_]\k*\(-[a-zA-Z]\+\)*/ contained
|
||||
highlight default link lsVarInterpolation Identifier
|
||||
|
||||
" What is in a non-interpolated string
|
||||
syntax cluster lsSimpleString contains=@Spell,lsEscape
|
||||
" What is in an interpolated string
|
||||
syntax cluster lsInterpString contains=@lsSimpleString,
|
||||
\ lsInterpolation,lsVarInterpolation
|
||||
|
||||
syntax region lsRegex start=/\%(\%()\|\i\@<!\d\)\s*\|\i\)\@<!\/\*\@!/
|
||||
\ skip=/\[[^]]\{-}\/[^]]\{-}\]/
|
||||
\ end=/\/[gimy$]\{,4}/
|
||||
\ oneline contains=@lsSimpleString
|
||||
syntax region lsHeregex start=/\/\// end=/\/\/[gimy$?]\{,4}/ contains=@lsInterpString,lsComment,lsSpaceError fold
|
||||
highlight default link lsHeregex lsRegex
|
||||
highlight default link lsRegex String
|
||||
|
||||
syntax region lsHeredoc start=/"""/ end=/"""/ contains=@lsInterpString fold
|
||||
syntax region lsHeredoc start=/'''/ end=/'''/ contains=@lsSimpleString fold
|
||||
highlight default link lsHeredoc String
|
||||
|
||||
syntax match lsWord /\\\S[^ \t\r,;)}\]]*/
|
||||
highlight default link lsWord String
|
||||
|
||||
syntax region lsWords start=/<\[/ end=/\]>/ contains=fold
|
||||
highlight default link lsWords String
|
||||
|
||||
" Reserved words can be used as property names.
|
||||
syntax match lsProp /[$A-Za-z_]\k*[ \t]*:[:=]\@!/
|
||||
highlight default link lsProp Label
|
||||
|
||||
syntax match lsKey
|
||||
\ /\%(\.\@<!\.\%(=\?\s*\|\.\)\|[]})@?]\|::\)\zs\k\+/
|
||||
\ transparent
|
||||
\ contains=ALLBUT,lsNumberComment,lsIdentifier,lsContext,lsGlobal,lsReservedError,@lsReserved
|
||||
|
||||
" Displays an error for trailing whitespace.
|
||||
syntax match lsSpaceError /\s\+$/ display
|
||||
highlight default link lsSpaceError Error
|
||||
|
||||
if !exists('b:current_syntax')
|
||||
let b:current_syntax = 'livescript'
|
||||
endif
|
||||
|
||||
endif
|
Loading…
Reference in New Issue
Block a user