diff options
| author | Adam Stankiewicz <sheerun@sher.pl> | 2016-07-26 14:06:32 +0200 | 
|---|---|---|
| committer | Adam Stankiewicz <sheerun@sher.pl> | 2016-07-26 14:06:32 +0200 | 
| commit | cb574b283fd19eea20d95c768b64c6b805d81690 (patch) | |
| tree | d948536dd865ce76bdec248d221b58dc1789c79f | |
| parent | b9ce3df4cd3a93a3ff309301771afbbe92984492 (diff) | |
| download | vim-polyglot-cb574b283fd19eea20d95c768b64c6b805d81690.tar.gz vim-polyglot-cb574b283fd19eea20d95c768b64c6b805d81690.zip | |
Add livescript, closes #135
Diffstat (limited to '')
| -rw-r--r-- | README.md | 1 | ||||
| -rwxr-xr-x | build | 1 | ||||
| -rw-r--r-- | compiler/ls.vim | 78 | ||||
| -rw-r--r-- | extras/flow.vim | 46 | ||||
| -rw-r--r-- | extras/jsdoc.vim | 43 | ||||
| -rw-r--r-- | extras/ngdoc.vim | 7 | ||||
| -rw-r--r-- | ftdetect/polyglot.vim | 13 | ||||
| -rw-r--r-- | ftplugin/ls.vim | 208 | ||||
| -rw-r--r-- | indent/ls.vim | 268 | ||||
| -rw-r--r-- | syntax/ls.vim | 140 | 
10 files changed, 805 insertions, 0 deletions
| @@ -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) @@ -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 diff --git a/compiler/ls.vim b/compiler/ls.vim new file mode 100644 index 00000000..df792917 --- /dev/null +++ b/compiler/ls.vim @@ -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 diff --git a/extras/flow.vim b/extras/flow.vim index a18c8825..6ce7ed99 100644 --- a/extras/flow.vim +++ b/extras/flow.vim @@ -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 diff --git a/extras/jsdoc.vim b/extras/jsdoc.vim index c5d7a572..7ce5f62d 100644 --- a/extras/jsdoc.vim +++ b/extras/jsdoc.vim @@ -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 diff --git a/extras/ngdoc.vim b/extras/ngdoc.vim index be314a80..7065cb81 100644 --- a/extras/ngdoc.vim +++ b/extras/ngdoc.vim @@ -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 diff --git a/ftdetect/polyglot.vim b/ftdetect/polyglot.vim index 6e032523..caa6ad5e 100644 --- a/ftdetect/polyglot.vim +++ b/ftdetect/polyglot.vim @@ -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 diff --git a/ftplugin/ls.vim b/ftplugin/ls.vim new file mode 100644 index 00000000..6ce6b57a --- /dev/null +++ b/ftplugin/ls.vim @@ -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 diff --git a/indent/ls.vim b/indent/ls.vim new file mode 100644 index 00000000..240eab07 --- /dev/null +++ b/indent/ls.vim @@ -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 diff --git a/syntax/ls.vim b/syntax/ls.vim new file mode 100644 index 00000000..c3edf65e --- /dev/null +++ b/syntax/ls.vim @@ -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 | 
