Merge commit 'b2743054e9a63bed4577fd10a3fba6fa0b3cc3ec' into main

main
Buddy Sandidge 7 years ago
commit e4092e18ed

@ -1,12 +1,13 @@
If you are reporting an issue that involves any JSX (e.g. *Requisite minimal reproducible example, formatted as plain text :*
<div>{`${example}`}</div>), PLEASE PLEASE PLEASE make sure you have properly
<hr>
#### Optional: concerning jsx.
PLEASE PLEASE PLEASE make sure you have properly
setup and are sourcing this plugin https://github.com/mxw/vim-jsx setup and are sourcing this plugin https://github.com/mxw/vim-jsx
WE DO NOT support JSX automatically, you need another plugin to add get this WE DO NOT support JSX automatically, you need another plugin to add get this
functionality. functionality.
If applicable, include a snippet of code that we can easily copy and paste that
replicates your bug.
Make sure the bug still exists if you disable all other javascript plugins Make sure the bug still exists if you disable all other javascript plugins
except the one noted above, mxw/vim-jsx except the one noted above, mxw/vim-jsx

@ -51,14 +51,16 @@ Default Value: 0
----------------- -----------------
``` ```vim
set foldmethod=syntax augroup javascript_folding
au!
au FileType javascript setlocal foldmethod=syntax
augroup END
``` ```
Enables code folding based on our syntax file. Enables code folding for javascript based on our syntax file.
Please note this can have a dramatic effect on performance and because it is a Please note this can have a dramatic effect on performance.
global vim option, we do not set it ourselves.
## Concealing Characters ## Concealing Characters

@ -2,7 +2,7 @@
" Language: Javascript " Language: Javascript
" Maintainer: Chris Paul ( https://github.com/bounceme ) " Maintainer: Chris Paul ( https://github.com/bounceme )
" URL: https://github.com/pangloss/vim-javascript " URL: https://github.com/pangloss/vim-javascript
" Last Change: August 12, 2017 " Last Change: December 4, 2017
" Only load this indent file when no other was loaded. " Only load this indent file when no other was loaded.
if exists('b:did_indent') if exists('b:did_indent')
@ -10,10 +10,6 @@ if exists('b:did_indent')
endif endif
let b:did_indent = 1 let b:did_indent = 1
" indent correctly if inside <script>
" vim/vim@690afe1 for the switch from cindent
let b:html_indent_script1 = 'inc'
" Now, set up our indentation expression and keys that trigger it. " Now, set up our indentation expression and keys that trigger it.
setlocal indentexpr=GetJavascriptIndent() setlocal indentexpr=GetJavascriptIndent()
setlocal autoindent nolisp nosmartindent setlocal autoindent nolisp nosmartindent
@ -25,13 +21,6 @@ setlocal indentkeys+=0],0)
let b:undo_indent = 'setlocal indentexpr< smartindent< autoindent< indentkeys<' let b:undo_indent = 'setlocal indentexpr< smartindent< autoindent< indentkeys<'
" Regex of syntax group names that are or delimit string or are comments.
let b:syng_strcom = get(b:,'syng_strcom','string\|comment\|regex\|special\|doc\|template\%(braces\)\@!')
let b:syng_str = get(b:,'syng_str','string\|template\|special')
" template strings may want to be excluded when editing graphql:
" au! Filetype javascript let b:syng_str = '^\%(.*template\)\@!.*string\|special'
" au! Filetype javascript let b:syng_strcom = '^\%(.*template\)\@!.*string\|comment\|regex\|special\|doc'
" Only define the function once. " Only define the function once.
if exists('*GetJavascriptIndent') if exists('*GetJavascriptIndent')
finish finish
@ -40,6 +29,23 @@ endif
let s:cpo_save = &cpo let s:cpo_save = &cpo
set cpo&vim set cpo&vim
" indent correctly if inside <script>
" vim/vim@690afe1 for the switch from cindent
" overridden with b:html_indent_script1
call extend(g:,{'html_indent_script1': 'inc'},'keep')
" Regex of syntax group names that are or delimit string or are comments.
let s:bvars = {
\ 'syng_strcom': 'string\|comment\|regex\|special\|doc\|template\%(braces\)\@!',
\ 'syng_str': 'string\|template\|special' }
" template strings may want to be excluded when editing graphql:
" au! Filetype javascript let b:syng_str = '^\%(.*template\)\@!.*string\|special'
" au! Filetype javascript let b:syng_strcom = '^\%(.*template\)\@!.*string\|comment\|regex\|special\|doc'
function s:GetVars()
call extend(b:,extend(s:bvars,{'js_cache': [0,0,0]}),'keep')
endfunction
" Get shiftwidth value " Get shiftwidth value
if exists('*shiftwidth') if exists('*shiftwidth')
function s:sw() function s:sw()
@ -55,20 +61,19 @@ endif
" matches before pos. " matches before pos.
let s:z = has('patch-7.4.984') ? 'z' : '' let s:z = has('patch-7.4.984') ? 'z' : ''
let s:syng_com = 'comment\|doc'
" Expression used to check whether we should skip a match with searchpair(). " Expression used to check whether we should skip a match with searchpair().
let s:skip_expr = "s:SynAt(line('.'),col('.')) =~? b:syng_strcom" let s:skip_expr = "s:SynAt(line('.'),col('.')) =~? b:syng_strcom"
let s:in_comm = s:skip_expr[:-14] . "'comment\\|doc'"
let s:rel = has('reltime')
" searchpair() wrapper " searchpair() wrapper
if has('reltime') if s:rel
function s:GetPair(start,end,flags,skip,time,...) function s:GetPair(start,end,flags,skip)
return searchpair('\m'.(a:start == '[' ? '\[' : a:start),'','\m'.a:end, return searchpair('\m'.a:start,'','\m'.a:end,a:flags,a:skip,s:l1,a:skip ==# 's:SkipFunc()' ? 2000 : 200)
\ a:flags,a:skip,max([prevnonblank(v:lnum) - 2000,0] + a:000),a:time)
endfunction endfunction
else else
function s:GetPair(start,end,flags,skip,...) function s:GetPair(start,end,flags,skip)
return searchpair('\m'.(a:start == '[' ? '\[' : a:start),'','\m'.a:end, return searchpair('\m'.a:start,'','\m'.a:end,a:flags,a:skip,s:l1)
\ a:flags,a:skip,max([prevnonblank(v:lnum) - 1000,0,get(a:000,1)]))
endfunction endfunction
endif endif
@ -82,60 +87,55 @@ function s:SynAt(l,c)
endfunction endfunction
function s:ParseCino(f) function s:ParseCino(f)
let [cin, divider, n] = [strridx(&cino,a:f), 0, ''] let [divider, n, cstr] = [0] + matchlist(&cino,
if cin == -1 \ '\%(.*,\)\=\%(\%d'.char2nr(a:f).'\(-\)\=\([.s0-9]*\)\)\=')[1:2]
return
endif
let [sign, cstr] = &cino[cin+1] == '-' ? [-1, &cino[cin+2:]] : [1, &cino[cin+1:]]
for c in split(cstr,'\zs') for c in split(cstr,'\zs')
if c == '.' && !divider if c == '.' && !divider
let divider = 1 let divider = 1
elseif c ==# 's' elseif c ==# 's'
if n is '' if n !~ '\d'
let n = s:sw() return n . s:sw() + 0
else
let n = str2nr(n) * s:sw()
endif endif
let n = str2nr(n) * s:sw()
break break
elseif c =~ '\d'
let [n, divider] .= [c, 0]
else else
break let [n, divider] .= [c, 0]
endif endif
endfor endfor
return sign * str2nr(n) / max([str2nr(divider),1]) return str2nr(n) / max([str2nr(divider),1])
endfunction endfunction
" Optimized {skip} expr, only callable from the search loop which " Optimized {skip} expr, only callable from the search loop which
" GetJavascriptIndent does to find the containing [[{(] (relies on s:vars) " GetJavascriptIndent does to find the containing [[{(] (side-effects)
function s:SkipFunc() function s:SkipFunc()
if s:top_col == 1 if s:top_col == 1
throw 'out of bounds' throw 'out of bounds'
endif elseif s:check_in
let s:top_col = 0
if s:check_in
if eval(s:skip_expr) if eval(s:skip_expr)
return 1 return 1
endif endif
let s:check_in = 0 let s:check_in = 0
elseif getline('.') =~ '\%<'.col('.').'c\/.\{-}\/\|\%>'.col('.').'c[''"]\|\\$' elseif getline('.') =~ '\%<'.col('.').'c\/.\{-}\/\|\%>'.col('.').'c[''"]\|\\$'
if eval(s:skip_expr) if eval(s:skip_expr)
let s:looksyn = line('.')
return 1 return 1
endif endif
elseif search('\m`\|\${\|\*\/','nW'.s:z,s:looksyn) && eval(s:skip_expr) elseif search('\m`\|\${\|\*\/','nW'.s:z,s:looksyn)
let s:check_in = 1 if eval(s:skip_expr)
return 1 let s:check_in = 1
return 1
endif
else
let s:synid_cache[:] += [[line2byte('.') + col('.') - 1], ['']]
endif endif
let [s:looksyn, s:top_col] = getpos('.')[1:2] let [s:looksyn, s:top_col] = getpos('.')[1:2]
endfunction endfunction
function s:AlternatePair() function s:AlternatePair()
let [pat, l:for] = ['[][(){};]', 2] let [pat, l:for] = ['[][(){};]', 2]
while s:SearchLoop('\m'.pat,'bW',s:script_tag,'s:SkipFunc()') while s:SearchLoop(pat,'bW','s:SkipFunc()')
if s:LookingAt() == ';' if s:LookingAt() == ';'
if !l:for if !l:for
if s:GetPair('{','}','bW','s:SkipFunc()',2000,s:script_tag) if s:GetPair('{','}','bW','s:SkipFunc()')
return return
endif endif
break break
@ -146,7 +146,7 @@ function s:AlternatePair()
let idx = stridx('])}',s:LookingAt()) let idx = stridx('])}',s:LookingAt())
if idx == -1 if idx == -1
return return
elseif !s:GetPair('[({'[idx],'])}'[idx],'bW','s:SkipFunc()',2000,s:script_tag) elseif !s:GetPair(['\[','(','{'][idx],'])}'[idx],'bW','s:SkipFunc()')
break break
endif endif
endif endif
@ -166,61 +166,64 @@ function s:Token()
return s:LookingAt() =~ '\k' ? expand('<cword>') : s:LookingAt() return s:LookingAt() =~ '\k' ? expand('<cword>') : s:LookingAt()
endfunction endfunction
function s:PreviousToken() function s:PreviousToken(...)
let l:pos = getpos('.') let [l:pos, tok] = [getpos('.'), '']
if search('\m\k\{1,}\|\S','ebW') if search('\m\k\{1,}\|\S','ebW')
if (strpart(getline('.'),col('.')-2,2) == '*/' || line('.') != l:pos[1] && if getline('.')[col('.')-2:col('.')-1] == '*/'
\ getline('.')[:col('.')-1] =~ '\/\/') && s:SynAt(line('.'),col('.')) =~? s:syng_com if eval(s:in_comm) && !s:SearchLoop('\S\ze\_s*\/[/*]','bW',s:in_comm)
if s:SearchLoop('\m\S\ze\_s*\/[/*]','bW',"s:SynAt(line('.'),col('.')) =~? s:syng_com") call setpos('.',l:pos)
return s:Token() else
let tok = s:Token()
endif endif
call setpos('.',l:pos)
else else
return s:Token() let two = a:0 || line('.') != l:pos[1] ? strridx(getline('.')[:col('.')],'//') + 1 : 0
if two && eval(s:in_comm)
call cursor(0,two)
let tok = s:PreviousToken(1)
if tok is ''
call setpos('.',l:pos)
endif
else
let tok = s:Token()
endif
endif endif
endif endif
return '' return tok
endfunction endfunction
function s:Pure(f,...) function s:Pure(f,...)
let l:pos = getpos('.') return eval("[call(a:f,a:000),cursor(a:firstline,".col('.').")][0]")
let ret = call(a:f,a:000)
call setpos('.',l:pos)
return ret
endfunction endfunction
function s:SearchLoop(...) function s:SearchLoop(pat,flags,expr)
let l:pos = getpos('.') return s:GetPair(a:pat,'\_$.',a:flags,a:expr)
while call('search',a:000[:-2]) " search flags [^nc]
if !eval(a:000[-1])
return line('.')
endif
endwhile
call setpos('.',l:pos)
endfunction endfunction
function s:ExprCol() function s:ExprCol()
if getline('.')[col('.')-2] == ':' if getline('.')[col('.')-2] == ':'
return 1 return 1
endif endif
let [bal, l:pos] = [0, getpos('.')] let bal = 0
while s:SearchLoop('\m[{}?:]','bW',s:script_tag,s:skip_expr) while s:SearchLoop('[{}?:]','bW',s:skip_expr)
if s:LookingAt() == ':' if s:LookingAt() == ':'
let bal -= strpart(getline('.'),col('.')-2,3) !~ '::' if getline('.')[col('.')-2] == ':'
call cursor(0,col('.')-1)
continue
endif
let bal -= 1
elseif s:LookingAt() == '?' elseif s:LookingAt() == '?'
let bal += 1 if getline('.')[col('.'):col('.')+1] =~ '^\.\d\@!'
if bal == 1 continue
break elseif !bal
return 1
endif endif
let bal += 1
elseif s:LookingAt() == '{' elseif s:LookingAt() == '{'
let bal = !s:IsBlock() return !s:IsBlock()
break elseif !s:GetPair('{','}','bW',s:skip_expr)
elseif !s:GetPair('{','}','bW',s:skip_expr,200)
break break
endif endif
endwhile endwhile
call setpos('.',l:pos)
return s:Nat(bal)
endfunction endfunction
" configurable regexes that define continuation lines, not including (, {, or [. " configurable regexes that define continuation lines, not including (, {, or [.
@ -229,167 +232,146 @@ let s:opfirst = '^' . get(g:,'javascript_opfirst',
let s:continuation = get(g:,'javascript_continuation', let s:continuation = get(g:,'javascript_continuation',
\ '\C\%([<=,.~!?/*^%|&:]\|+\@<!+\|-\@<!-\|=\@<!>\|\<\%(typeof\|new\|delete\|void\|in\|instanceof\|await\)\)') . '$' \ '\C\%([<=,.~!?/*^%|&:]\|+\@<!+\|-\@<!-\|=\@<!>\|\<\%(typeof\|new\|delete\|void\|in\|instanceof\|await\)\)') . '$'
function s:Continues(ln,con) function s:Continues()
let tok = matchstr(a:con[-15:],s:continuation) let tok = matchstr(strpart(getline('.'),col('.')-15,15),s:continuation)
if tok =~ '[a-z:]' if tok =~ '[a-z:]'
call cursor(a:ln, len(a:con))
return tok == ':' ? s:ExprCol() : s:PreviousToken() != '.' return tok == ':' ? s:ExprCol() : s:PreviousToken() != '.'
elseif tok !~ '[/>]' elseif tok !~ '[/>]'
return tok isnot '' return tok isnot ''
endif endif
return s:SynAt(a:ln, len(a:con)) !~? (tok == '>' ? 'jsflow\|^html' : 'regex') return s:SynAt(line('.'),col('.')) !~? (tok == '>' ? 'jsflow\|^html' : 'regex')
endfunction
function s:Trim(ln)
let divi = split(getline(a:ln),'\s\+$\|\S\zs\ze\s*\/[/*]')
while len(divi) > 1 && s:SynAt(a:ln, len(join(divi,''))) =~? s:syng_com
call remove(divi,-1)
endwhile
return join(divi,'')
endfunction
" Find line above 'lnum' that isn't empty or in a comment
function s:PrevCodeLine(lnum)
let [l:multi, l:n, l:pos] = [0, prevnonblank(a:lnum), getpos('.')]
while l:n
if getline(l:n) =~ '^\s*\/[/*]' && (getline(l:n) !~ '`' &&
\ getline(l:n-1)[-1:] != '\' || s:SynAt(l:n,1) !~? b:syng_str)
let l:n = prevnonblank(l:n-1)
continue
elseif l:multi || getline(l:n) =~ '\*\/'
call cursor(l:n,1)
if search('\m\/\*\|\(\*\/\)','bWp') == 1 && s:SynAt(l:n,1) =~? s:syng_com
let [l:multi, l:n] = [1, line('.')]
continue
endif
endif
break
endwhile
call setpos('.',l:pos)
return l:n
endfunction endfunction
" Check if line 'lnum' has a balanced amount of parentheses. " Check if line 'lnum' has a balanced amount of parentheses.
function s:Balanced(lnum) function s:Balanced(lnum,line)
let [l:open, l:line] = [0, getline(a:lnum)] let l:open = 0
let pos = match(l:line, '[][(){}]') let pos = match(a:line, '[][(){}]')
while pos != -1 while pos != -1
if s:SynAt(a:lnum,pos + 1) !~? b:syng_strcom if s:SynAt(a:lnum,pos + 1) !~? b:syng_strcom
let l:open += match(' ' . l:line[pos],'[[({]') let l:open += matchend(a:line[pos],'[[({]')
if l:open < 0 if l:open < 0
return return
endif endif
endif endif
let pos = match(l:line, l:open ? let pos = match(a:line, !l:open ? '[][(){}]' : '()' =~ a:line[pos] ?
\ matchstr(['[][]','[()]','[{}]'],l:line[pos]) : \ '[()]' : '{}' =~ a:line[pos] ? '[{}]' : '[][]', pos + 1)
\ '[][(){}]', pos + 1)
endwhile endwhile
return !l:open return !l:open
endfunction endfunction
function s:OneScope(lnum) function s:OneScope()
call cursor(a:lnum, len(s:Trim(a:lnum))) if s:LookingAt() == ')' && s:GetPair('(', ')', 'bW', s:skip_expr)
if s:LookingAt() == ')' && s:GetPair('(', ')', 'bW', s:skip_expr, 100)
let tok = s:PreviousToken() let tok = s:PreviousToken()
return (tok =~# '^\%(for\|if\|let\|while\|with\)$' || return (count(split('for if let while with'),tok) ||
\ tok =~# '^await$\|^each$' && s:PreviousToken() ==# 'for') && \ tok =~# '^await$\|^each$' && s:PreviousToken() ==# 'for') &&
\ s:Pure('s:PreviousToken') != '.' && !(tok == 'while' && s:DoWhile()) \ s:Pure('s:PreviousToken') != '.' && !(tok == 'while' && s:DoWhile())
elseif s:Token() =~# '^else$\|^do$' elseif s:Token() =~# '^else$\|^do$'
return s:Pure('s:PreviousToken') != '.' return s:Pure('s:PreviousToken') != '.'
elseif strpart(getline('.'),col('.')-2,2) == '=>'
call cursor(0,col('.')-1)
return s:PreviousToken() != ')' || s:GetPair('(', ')', 'bW', s:skip_expr)
endif endif
return strpart(getline('.'),col('.')-2,2) == '=>'
endfunction endfunction
function s:DoWhile() function s:DoWhile()
let cpos = searchpos('\m\<','cbW') let cpos = searchpos('\m\<','cbW')
if s:SearchLoop('\m\C[{}]\|\<\%(do\|while\)\>','bW',s:skip_expr) while s:SearchLoop('\C[{}]\|\<\%(do\|while\)\>','bW',s:skip_expr)
if s:{s:LookingAt() == '}' && s:GetPair('{','}','bW',s:skip_expr,200) ? if s:LookingAt() =~ '\a'
\ 'Previous' : ''}Token() ==# 'do' && s:IsBlock() if s:Pure('s:IsBlock')
return 1 if s:LookingAt() ==# 'd'
return 1
endif
break
endif
elseif s:LookingAt() != '}' || !s:GetPair('{','}','bW',s:skip_expr)
break
endif endif
call call('cursor',cpos) endwhile
endif call call('cursor',cpos)
endfunction endfunction
" returns braceless levels started by 'i' and above lines * &sw. 'num' is the " returns total offset from braceless contexts. 'num' is the lineNr which
" lineNr which encloses the entire context, 'cont' if whether line 'i' + 1 is " encloses the entire context, 'cont' if whether a:firstline is a continued
" a continued expression, which could have started in a braceless context " expression, which could have started in a braceless context
function s:IsContOne(i,num,cont) function s:IsContOne(cont)
let [l:i, l:num, b_l] = [a:i, a:num + !a:num, 0] let [l:num, pind] = b:js_cache[1] ?
let pind = a:num ? indent(a:num) + s:sw() : 0 \ [b:js_cache[1], indent(b:js_cache[1]) + s:sw()] : [1,0]
let ind = indent(a:i) + (a:cont ? 0 : s:sw()) let [ind, b_l] = [indent('.') + !a:cont, 0]
while l:i > l:num && ind > pind || l:i == l:num while line('.') > l:num && ind > pind || line('.') == l:num
if indent(l:i) < ind && s:OneScope(l:i) if indent('.') < ind && s:OneScope()
let b_l += 1 let b_l += 1
let l:i = line('.') elseif !a:cont || b_l || ind < indent(a:firstline)
elseif !a:cont || b_l || ind < indent(a:i) break
else
call cursor(0,1)
endif
let ind = min([ind, indent('.')])
if s:PreviousToken() is ''
break break
endif endif
let ind = min([ind, indent(l:i)])
let l:i = s:PrevCodeLine(l:i - 1)
endwhile endwhile
return b_l return b_l
endfunction endfunction
function s:IsSwitch() function s:IsSwitch()
return s:PreviousToken() !~ '[.*]' && return search('\m\C\%'.join(b:js_cache[1:],'l\%').
\ (!s:GetPair('{','}','cbW',s:skip_expr,100) || s:IsBlock() && \ 'c{\_s*\%(\%(\/\/.*\_$\|\/\*\_.\{-}\*\/\)\@>\_s*\)*\%(case\|default\)\>','nW'.s:z)
\ (s:Token() !~ '^\K\k*$' || expand('<cword>') !=# 'class' &&
\ s:PreviousToken() !~# '^class$\|^extends$' || s:PreviousToken() == '.'))
endfunction endfunction
" https://github.com/sweet-js/sweet.js/wiki/design#give-lookbehind-to-the-reader " https://github.com/sweet-js/sweet.js/wiki/design#give-lookbehind-to-the-reader
function s:IsBlock() function s:IsBlock()
let l:n = line('.')
let tok = s:PreviousToken() let tok = s:PreviousToken()
if match(s:stack,'\cxml\|jsx') != -1 && s:SynAt(line('.'),col('.')-1) =~? 'xml\|jsx' if join(s:stack) =~? 'xml\|jsx' && s:SynAt(line('.'),col('.')-1) =~? 'xml\|jsx'
let s:in_jsx = 1
return tok != '{' return tok != '{'
elseif tok =~ '\k' elseif tok =~ '\k'
if tok ==# 'type' if tok ==# 'type'
return s:Pure('eval',"s:PreviousToken() !~# '^\\%(im\\|ex\\)port$' || s:PreviousToken() == '.'") return s:Pure('eval',"s:PreviousToken() !~# '^\\%(im\\|ex\\)port$' || s:PreviousToken() == '.'")
elseif tok ==# 'of'
return s:Pure('eval',"!s:GetPair('[[({]','[])}]','bW',s:skip_expr) || s:LookingAt() != '(' ||"
\ ."s:{s:PreviousToken() ==# 'await' ? 'Previous' : ''}Token() !=# 'for' || s:PreviousToken() == '.'")
endif endif
return index(split('return const let import export extends yield default delete var await void typeof throw case new of in instanceof') return index(split('return const let import export extends yield default delete var await void typeof throw case new in instanceof')
\ ,tok) < (line('.') != l:n) || s:Pure('s:PreviousToken') == '.' \ ,tok) < (line('.') != a:firstline) || s:Pure('s:PreviousToken') == '.'
elseif tok == '>' elseif tok == '>'
return getline('.')[col('.')-2] == '=' || s:SynAt(line('.'),col('.')) =~? 'jsflow\|^html' return getline('.')[col('.')-2] == '=' || s:SynAt(line('.'),col('.')) =~? 'jsflow\|^html'
elseif tok == '*' elseif tok == '*'
return s:Pure('s:PreviousToken') == ':' return s:Pure('s:PreviousToken') == ':'
elseif tok == ':' elseif tok == ':'
return !s:ExprCol() return s:Pure('eval',"s:PreviousToken() =~ '^\\K\\k*$' && !s:ExprCol()")
elseif tok == '/' elseif tok == '/'
return s:SynAt(line('.'),col('.')) =~? 'regex' return s:SynAt(line('.'),col('.')) =~? 'regex'
elseif tok !~ '[=~!<,.?^%|&([]' elseif tok !~ '[=~!<,.?^%|&([]'
return tok !~ '[-+]' || l:n != line('.') && getline('.')[col('.')-2] == tok return tok !~ '[-+]' || line('.') != a:firstline && getline('.')[col('.')-2] == tok
endif endif
endfunction endfunction
function GetJavascriptIndent() function GetJavascriptIndent()
let [b:js_cache, s:synid_cache, l:line, s:stack] = [ call s:GetVars()
\ get(b:,'js_cache',[0,0,0]), let s:synid_cache = [[],[]]
\ [[],[]], let l:line = getline(v:lnum)
\ getline(v:lnum),
\ map(synstack(v:lnum,1),"synIDattr(v:val,'name')"),
\ ]
" use synstack as it validates syn state and works in an empty line " use synstack as it validates syn state and works in an empty line
let syns = get(s:stack,-1,'') let s:stack = [''] + map(synstack(v:lnum,1),"synIDattr(v:val,'name')")
" start with strings,comments,etc. " start with strings,comments,etc.
if syns =~? s:syng_com if s:stack[-1] =~? 'comment\|doc'
if l:line =~ '^\s*\*' if l:line !~ '^\s*\/[/*]'
return cindent(v:lnum) return l:line =~ '^\s*\*' ? cindent(v:lnum) : -1
elseif l:line !~ '^\s*\/[/*]'
return -1
endif endif
elseif syns =~? b:syng_str elseif s:stack[-1] =~? b:syng_str
if b:js_cache[0] == v:lnum - 1 && s:Balanced(v:lnum-1) if b:js_cache[0] == v:lnum - 1 && s:Balanced(v:lnum-1,getline(v:lnum-1))
let b:js_cache[0] = v:lnum let b:js_cache[0] = v:lnum
endif endif
return -1 return -1
endif endif
let l:lnum = s:PrevCodeLine(v:lnum - 1)
if !l:lnum let s:l1 = max([0,prevnonblank(v:lnum) - (s:rel ? 2000 : 1000),
\ get(get(b:,'hi_indent',{}),'blocklnr')])
call cursor(v:lnum,1)
if s:PreviousToken() is ''
return return
endif endif
let [l:lnum, lcol, pline] = getpos('.')[1:2] + [getline('.')[:col('.')-1]]
let l:line = substitute(l:line,'^\s*','','') let l:line = substitute(l:line,'^\s*','','')
let l:line_raw = l:line let l:line_raw = l:line
@ -401,34 +383,34 @@ function GetJavascriptIndent()
endif endif
" the containing paren, bracket, or curly. Many hacks for performance " the containing paren, bracket, or curly. Many hacks for performance
let [ s:script_tag, idx ] = [ get(get(b:,'hi_indent',{}),'blocklnr'), call cursor(v:lnum,1)
\ index([']',')','}'],l:line[0]) ] let idx = index([']',')','}'],l:line[0])
if b:js_cache[0] > l:lnum && b:js_cache[0] < v:lnum || if b:js_cache[0] > l:lnum && b:js_cache[0] < v:lnum ||
\ b:js_cache[0] == l:lnum && s:Balanced(l:lnum) \ b:js_cache[0] == l:lnum && s:Balanced(l:lnum,pline)
call call('cursor',b:js_cache[2] ? b:js_cache[1:] : [v:lnum,1]) call call('cursor',b:js_cache[1:])
else else
call cursor(v:lnum,1) let [s:looksyn, s:top_col, s:check_in, s:l1] = [v:lnum - 1,0,0,
let [s:looksyn, s:check_in, s:top_col] = [v:lnum - 1, 0, 0] \ max([s:l1, &smc ? search('\m^.\{'.&smc.',}','nbW',s:l1 + 1) + 1 : 0])]
try try
if idx != -1 if idx != -1
call s:GetPair('[({'[idx],'])}'[idx],'bW','s:SkipFunc()',2000,s:script_tag) call s:GetPair(['\[','(','{'][idx],'])}'[idx],'bW','s:SkipFunc()')
elseif getline(v:lnum) !~ '^\S' && syns =~? 'block' elseif getline(v:lnum) !~ '^\S' && s:stack[-1] =~? 'block\|^jsobject$'
call s:GetPair('{','}','bW','s:SkipFunc()',2000,s:script_tag) call s:GetPair('{','}','bW','s:SkipFunc()')
else else
call s:AlternatePair() call s:AlternatePair()
endif endif
catch catch /^\Cout of bounds$/
call cursor(v:lnum,1) call cursor(v:lnum,1)
endtry endtry
let b:js_cache[1:] = line('.') == v:lnum ? [0,0] : getpos('.')[1:2]
endif endif
let b:js_cache = [v:lnum] + (line('.') == v:lnum ? [s:script_tag,0] : getpos('.')[1:2]) let [b:js_cache[0], num] = [v:lnum, b:js_cache[1]]
let num = b:js_cache[1]
let [num_ind, is_op, b_l, l:switch_offset] = [s:Nat(indent(num)),0,0,0] let [num_ind, is_op, b_l, l:switch_offset, s:in_jsx] = [s:Nat(indent(num)),0,0,0,0]
if !b:js_cache[2] || s:LookingAt() == '{' && s:IsBlock() if !num || s:LookingAt() == '{' && s:IsBlock()
let [ilnum, pline] = [line('.'), s:Trim(l:lnum)] let ilnum = line('.')
if b:js_cache[2] && s:LookingAt() == ')' && s:GetPair('(',')','bW',s:skip_expr,100) if num && !s:in_jsx && s:LookingAt() == ')' && s:GetPair('(',')','bW',s:skip_expr)
if ilnum == num if ilnum == num
let [num, num_ind] = [line('.'), indent('.')] let [num, num_ind] = [line('.'), indent('.')]
endif endif
@ -442,20 +424,26 @@ function GetJavascriptIndent()
endif endif
endif endif
if idx == -1 && pline[-1:] !~ '[{;]' if idx == -1 && pline[-1:] !~ '[{;]'
call cursor(l:lnum, lcol)
let sol = matchstr(l:line,s:opfirst) let sol = matchstr(l:line,s:opfirst)
if sol =~# '^\%(in\%(stanceof\)\=\|\*\)$' if sol is '' || sol == '/' && s:SynAt(v:lnum,
call cursor(l:lnum, len(pline)) \ 1 + len(getline(v:lnum)) - len(l:line)) =~? 'regex'
if pline[-1:] == '}' && s:GetPair('{','}','bW',s:skip_expr,200) && s:IsBlock() if s:Continues()
return num_ind + s:sw() let is_op = s:sw()
endif endif
let is_op = s:sw() elseif num && sol =~# '^\%(in\%(stanceof\)\=\|\*\)$' &&
elseif sol isnot '' || s:Continues(l:lnum,pline) \ s:LookingAt() == '}' && s:GetPair('{','}','bW',s:skip_expr) &&
\ s:PreviousToken() == ')' && s:GetPair('(',')','bW',s:skip_expr) &&
\ (s:PreviousToken() == ']' || s:LookingAt() =~ '\k' &&
\ s:{s:PreviousToken() == '*' ? 'Previous' : ''}Token() !=# 'function')
return num_ind + s:sw()
else
let is_op = s:sw() let is_op = s:sw()
endif endif
let b_l = s:Nat(s:IsContOne(l:lnum,b:js_cache[1],is_op) - call cursor(l:lnum, lcol)
\ (!is_op && l:line =~ '^{')) * s:sw() let b_l = s:Nat(s:IsContOne(is_op) - (!is_op && l:line =~ '^{')) * s:sw()
endif endif
elseif idx == -1 && getline(b:js_cache[1])[b:js_cache[2]-1] == '(' && &cino =~ '(' && elseif idx == -1 && s:LookingAt() == '(' && &cino =~ '(' &&
\ (search('\m\S','nbW',num) || s:ParseCino('U')) \ (search('\m\S','nbW',num) || s:ParseCino('U'))
let pval = s:ParseCino('(') let pval = s:ParseCino('(')
if !pval if !pval
@ -465,15 +453,15 @@ function GetJavascriptIndent()
endif endif
return Wval ? s:Nat(num_ind + Wval) : vcol return Wval ? s:Nat(num_ind + Wval) : vcol
endif endif
return s:Nat(num_ind + pval + s:GetPair('(',')','nbrmW',s:skip_expr,100,num) * s:sw()) return s:Nat(num_ind + pval + searchpair('\m(','','\m)','nbrmW',s:skip_expr,num) * s:sw())
endif endif
" main return " main return
if l:line =~ '^[])}]\|^|}' if l:line =~ '^[])}]\|^|}'
if l:line_raw[0] == ')' && getline(b:js_cache[1])[b:js_cache[2]-1] == '(' if l:line_raw[0] == ')'
if s:ParseCino('M') if s:ParseCino('M')
return indent(l:lnum) return indent(l:lnum)
elseif &cino =~# 'm' && !s:ParseCino('m') elseif num && &cino =~# 'm' && !s:ParseCino('m')
return virtcol('.') - 1 return virtcol('.') - 1
endif endif
endif endif
@ -481,6 +469,10 @@ function GetJavascriptIndent()
elseif num elseif num
return s:Nat(num_ind + get(l:,'case_offset',s:sw()) + l:switch_offset + b_l + is_op) return s:Nat(num_ind + get(l:,'case_offset',s:sw()) + l:switch_offset + b_l + is_op)
endif endif
let nest = get(get(b:,'hi_indent',{}),'blocklnr')
if nest
return indent(nest) + s:sw() + b_l + is_op
endif
return b_l + is_op return b_l + is_op
endfunction endfunction

@ -24,17 +24,17 @@ syntax sync fromstart
" syntax case ignore " syntax case ignore
syntax case match syntax case match
syntax match jsNoise /[:,\;]\{1}/ syntax match jsNoise /[:,;]/
syntax match jsNoise /[\.]\{1}/ skipwhite skipempty nextgroup=jsObjectProp,jsFuncCall,jsPrototype,jsTaggedTemplate syntax match jsNoise /\./ skipwhite skipempty nextgroup=jsObjectProp,jsFuncCall,jsPrototype,jsTaggedTemplate
syntax match jsObjectProp contained /\<[a-zA-Z_$][0-9a-zA-Z_$]*\>/ syntax match jsObjectProp contained /\<\K\k*/
syntax match jsFuncCall /\k\+\%(\s*(\)\@=/ syntax match jsFuncCall /\<\K\k*\ze\s*(/
syntax match jsParensError /[)}\]]/ syntax match jsParensError /[)}\]]/
" Program Keywords " Program Keywords
syntax keyword jsStorageClass const var let skipwhite skipempty nextgroup=jsDestructuringBlock,jsDestructuringArray,jsVariableDef syntax keyword jsStorageClass const var let skipwhite skipempty nextgroup=jsDestructuringBlock,jsDestructuringArray,jsVariableDef
syntax match jsVariableDef contained /\k\+/ skipwhite skipempty nextgroup=jsFlowDefinition syntax match jsVariableDef contained /\<\K\k*/ skipwhite skipempty nextgroup=jsFlowDefinition
syntax keyword jsOperator delete instanceof typeof void new in of skipwhite skipempty nextgroup=@jsExpression syntax keyword jsOperator delete instanceof typeof void new in of skipwhite skipempty nextgroup=@jsExpression
syntax match jsOperator /[\!\|\&\+\-\<\>\=\%\/\*\~\^]\{1}/ skipwhite skipempty nextgroup=@jsExpression syntax match jsOperator "[-!|&+<>=%/*~^]" skipwhite skipempty nextgroup=@jsExpression
syntax match jsOperator /::/ skipwhite skipempty nextgroup=@jsExpression syntax match jsOperator /::/ skipwhite skipempty nextgroup=@jsExpression
syntax keyword jsBooleanTrue true syntax keyword jsBooleanTrue true
syntax keyword jsBooleanFalse false syntax keyword jsBooleanFalse false
@ -42,7 +42,7 @@ syntax keyword jsBooleanFalse false
" Modules " Modules
syntax keyword jsImport import skipwhite skipempty nextgroup=jsModuleAsterisk,jsModuleKeyword,jsModuleGroup,jsFlowImportType syntax keyword jsImport import skipwhite skipempty nextgroup=jsModuleAsterisk,jsModuleKeyword,jsModuleGroup,jsFlowImportType
syntax keyword jsExport export skipwhite skipempty nextgroup=@jsAll,jsModuleGroup,jsExportDefault,jsModuleAsterisk,jsModuleKeyword,jsFlowTypeStatement syntax keyword jsExport export skipwhite skipempty nextgroup=@jsAll,jsModuleGroup,jsExportDefault,jsModuleAsterisk,jsModuleKeyword,jsFlowTypeStatement
syntax match jsModuleKeyword contained /\k\+/ skipwhite skipempty nextgroup=jsModuleAs,jsFrom,jsModuleComma syntax match jsModuleKeyword contained /\<\K\k*/ skipwhite skipempty nextgroup=jsModuleAs,jsFrom,jsModuleComma
syntax keyword jsExportDefault contained default skipwhite skipempty nextgroup=@jsExpression syntax keyword jsExportDefault contained default skipwhite skipempty nextgroup=@jsExpression
syntax keyword jsExportDefaultGroup contained default skipwhite skipempty nextgroup=jsModuleAs,jsFrom,jsModuleComma syntax keyword jsExportDefaultGroup contained default skipwhite skipempty nextgroup=jsModuleAs,jsFrom,jsModuleComma
syntax match jsModuleAsterisk contained /\*/ skipwhite skipempty nextgroup=jsModuleKeyword,jsModuleAs,jsFrom syntax match jsModuleAsterisk contained /\*/ skipwhite skipempty nextgroup=jsModuleKeyword,jsModuleAs,jsFrom
@ -51,44 +51,37 @@ syntax keyword jsFrom contained from skipwhite skipempty nextgroup
syntax match jsModuleComma contained /,/ skipwhite skipempty nextgroup=jsModuleKeyword,jsModuleAsterisk,jsModuleGroup,jsFlowTypeKeyword syntax match jsModuleComma contained /,/ skipwhite skipempty nextgroup=jsModuleKeyword,jsModuleAsterisk,jsModuleGroup,jsFlowTypeKeyword
" Strings, Templates, Numbers " Strings, Templates, Numbers
syntax region jsString start=+"+ skip=+\\\("\|$\)+ end=+"\|$+ contains=jsSpecial,@Spell extend syntax region jsString start=+\z(["']\)+ skip=+\\\%(\z1\|$\)+ end=+\z1\|$+ contains=jsSpecial,@Spell extend
syntax region jsString start=+'+ skip=+\\\('\|$\)+ end=+'\|$+ contains=jsSpecial,@Spell extend syntax region jsTemplateString start=+`+ skip=+\\`+ end=+`+ contains=jsTemplateExpression,jsSpecial,@Spell extend
syntax region jsTemplateString start=+`+ skip=+\\\(`\|$\)+ end=+`+ contains=jsTemplateExpression,jsSpecial,@Spell extend syntax match jsTaggedTemplate /\<\K\k*\ze`/ nextgroup=jsTemplateString
syntax match jsTaggedTemplate /\k\+\%(`\)\@=/ nextgroup=jsTemplateString syntax match jsNumber /\c\<\%(\d\+\%(e[+-]\=\d\+\)\=\|0b[01]\+\|0o\o\+\|0x\x\+\)\>/
syntax match jsNumber /\<\d\+\%([eE][+-]\=\d\+\)\=\>\|\<0[bB][01]\+\>\|\<0[oO]\o\+\>\|\<0[xX]\x\+\>/
syntax keyword jsNumber Infinity syntax keyword jsNumber Infinity
syntax match jsFloat /\<\%(\d\+\.\d\+\|\d\+\.\|\.\d\+\)\%([eE][+-]\=\d\+\)\=\>/ syntax match jsFloat /\c\<\%(\d\+\.\d\+\|\d\+\.\|\.\d\+\)\%(e[+-]\=\d\+\)\=\>/
" Regular Expressions " Regular Expressions
syntax match jsSpecial contained "\v\\%(0|\\x\x\{2\}\|\\u\x\{4\}\|\c[A-Z]|.)" syntax match jsSpecial contained "\v\\%(x\x\x|u%(\x{4}|\{\x{4,5}})|c\u|.)"
syntax region jsTemplateExpression contained matchgroup=jsTemplateBraces start=+${+ end=+}+ contains=@jsExpression keepend syntax region jsTemplateExpression contained matchgroup=jsTemplateBraces start=+${+ end=+}+ contains=@jsExpression keepend
syntax region jsRegexpCharClass contained start=+\[+ skip=+\\.+ end=+\]+ syntax region jsRegexpCharClass contained start=+\[+ skip=+\\.+ end=+\]+ contains=jsSpecial
syntax match jsRegexpBoundary contained "\v%(\<@![\^$]|\\[bB])" syntax match jsRegexpBoundary contained "\v\c[$^]|\\b"
syntax match jsRegexpBackRef contained "\v\\[1-9][0-9]*" syntax match jsRegexpBackRef contained "\v\\[1-9]\d*"
syntax match jsRegexpQuantifier contained "\v\\@<!%([?*+]|\{\d+%(,|,\d+)?})\??" syntax match jsRegexpQuantifier contained "\v[^\\]%([?*+]|\{\d+%(,\d*)?})\??"lc=1
syntax match jsRegexpOr contained "\v\<@!\|" syntax match jsRegexpOr contained "|"
syntax match jsRegexpMod contained "\v\(@<=\?[:=!>]" syntax match jsRegexpMod contained "\v\(\?[:=!>]"lc=1
syntax region jsRegexpGroup contained start="\\\@<!(" skip="\\.\|\[\(\\.\|[^]]\)*\]" end="\\\@<!)" contains=jsRegexpCharClass,@jsRegexpSpecial keepend syntax region jsRegexpGroup contained start="[^\\]("lc=1 skip="\\.\|\[\(\\.\|[^]]\+\)\]" end=")" contains=jsRegexpCharClass,@jsRegexpSpecial keepend
if v:version > 703 || v:version == 603 && has("patch1088") syntax region jsRegexpString start=+\%(\%(\<return\|\<typeof\|\_[^)\]'"[:blank:][:alnum:]_$]\)\s*\)\@<=/\ze[^*/]+ skip=+\\.\|\[[^]]\{1,}\]+ end=+/[gimyus]\{,6}+ contains=jsRegexpCharClass,jsRegexpGroup,@jsRegexpSpecial oneline keepend extend
syntax region jsRegexpString start=+\%(\%(\%(return\|case\)\s\+\)\@50<=\|\%(\%([)\]"']\|\d\|\w\)\s*\)\@50<!\)/\(\*\|/\)\@!+ skip=+\\.\|\[\%(\\.\|[^]]\)*\]+ end=+/[gimyu]\{,5}+ contains=jsRegexpCharClass,jsRegexpGroup,@jsRegexpSpecial oneline keepend extend
else
syntax region jsRegexpString start=+\%(\%(\%(return\|case\)\s\+\)\@<=\|\%(\%([)\]"']\|\d\|\w\)\s*\)\@<!\)/\(\*\|/\)\@!+ skip=+\\.\|\[\%(\\.\|[^]]\)*\]+ end=+/[gimyu]\{,5}+ contains=jsRegexpCharClass,jsRegexpGroup,@jsRegexpSpecial oneline keepend extend
endif
syntax cluster jsRegexpSpecial contains=jsSpecial,jsRegexpBoundary,jsRegexpBackRef,jsRegexpQuantifier,jsRegexpOr,jsRegexpMod syntax cluster jsRegexpSpecial contains=jsSpecial,jsRegexpBoundary,jsRegexpBackRef,jsRegexpQuantifier,jsRegexpOr,jsRegexpMod
" Objects " Objects
syntax match jsObjectKey contained /\<[0-9a-zA-Z_$]*\>\(\s*:\)\@=/ contains=jsFunctionKey skipwhite skipempty nextgroup=jsObjectValue syntax match jsObjectKey contained /\<\k*\ze\s*:/ contains=jsFunctionKey skipwhite skipempty nextgroup=jsObjectValue
syntax match jsObjectColon contained /:/ skipwhite skipempty syntax match jsObjectColon contained /:/ skipwhite skipempty
syntax region jsObjectKeyString contained start=+"+ skip=+\\\("\|$\)+ end=+"\|$+ contains=jsSpecial,@Spell skipwhite skipempty nextgroup=jsObjectValue syntax region jsObjectKeyString contained start=+\z(["']\)+ skip=+\\\%(\z1\|$\)+ end=+\z1\|$+ contains=jsSpecial,@Spell skipwhite skipempty nextgroup=jsObjectValue
syntax region jsObjectKeyString contained start=+'+ skip=+\\\('\|$\)+ end=+'\|$+ contains=jsSpecial,@Spell skipwhite skipempty nextgroup=jsObjectValue
syntax region jsObjectKeyComputed contained matchgroup=jsBrackets start=/\[/ end=/]/ contains=@jsExpression skipwhite skipempty nextgroup=jsObjectValue,jsFuncArgs extend syntax region jsObjectKeyComputed contained matchgroup=jsBrackets start=/\[/ end=/]/ contains=@jsExpression skipwhite skipempty nextgroup=jsObjectValue,jsFuncArgs extend
syntax match jsObjectSeparator contained /,/ syntax match jsObjectSeparator contained /,/
syntax region jsObjectValue contained matchgroup=jsNoise start=/:/ end=/\%(,\|}\)\@=/ contains=@jsExpression extend syntax region jsObjectValue contained matchgroup=jsNoise start=/:/ end=/[,}]\@=/ contains=@jsExpression extend
syntax match jsObjectFuncName contained /\<[a-zA-Z_$][0-9a-zA-Z_$]*\>[\r\n\t ]*(\@=/ skipwhite skipempty nextgroup=jsFuncArgs syntax match jsObjectFuncName contained /\<\K\k*\ze\_s*(/ skipwhite skipempty nextgroup=jsFuncArgs
syntax match jsFunctionKey contained /\<[a-zA-Z_$][0-9a-zA-Z_$]*\>\(\s*:\s*function\s*\)\@=/ syntax match jsFunctionKey contained /\<\K\k*\ze\s*:\s*function\>/
syntax match jsObjectMethodType contained /\%(get\|set\)\%( \k\+\)\@=/ skipwhite skipempty nextgroup=jsObjectFuncName syntax match jsObjectMethodType contained /\<[gs]et\ze\s\+\K\k*/ skipwhite skipempty nextgroup=jsObjectFuncName
syntax region jsObjectStringKey contained start=+"+ skip=+\\\("\|$\)+ end=+"\|$+ contains=jsSpecial,@Spell extend skipwhite skipempty nextgroup=jsFuncArgs,jsObjectValue syntax region jsObjectStringKey contained start=+\z(["']\)+ skip=+\\\%(\z1\|$\)+ end=+\z1\|$+ contains=jsSpecial,@Spell extend skipwhite skipempty nextgroup=jsFuncArgs,jsObjectValue
syntax region jsObjectStringKey contained start=+'+ skip=+\\\('\|$\)+ end=+'\|$+ contains=jsSpecial,@Spell extend skipwhite skipempty nextgroup=jsFuncArgs,jsObjectValue
exe 'syntax keyword jsNull null '.(exists('g:javascript_conceal_null') ? 'conceal cchar='.g:javascript_conceal_null : '') exe 'syntax keyword jsNull null '.(exists('g:javascript_conceal_null') ? 'conceal cchar='.g:javascript_conceal_null : '')
exe 'syntax keyword jsReturn return contained '.(exists('g:javascript_conceal_return') ? 'conceal cchar='.g:javascript_conceal_return : '').' skipwhite skipempty nextgroup=@jsExpression' exe 'syntax keyword jsReturn return contained '.(exists('g:javascript_conceal_return') ? 'conceal cchar='.g:javascript_conceal_return : '').' skipwhite skipempty nextgroup=@jsExpression'
@ -99,25 +92,25 @@ exe 'syntax keyword jsThis this '.(exists('g:javascript_conceal
exe 'syntax keyword jsSuper super contained '.(exists('g:javascript_conceal_super') ? 'conceal cchar='.g:javascript_conceal_super : '') exe 'syntax keyword jsSuper super contained '.(exists('g:javascript_conceal_super') ? 'conceal cchar='.g:javascript_conceal_super : '')
" Statement Keywords " Statement Keywords
syntax match jsBlockLabel /\<[a-zA-Z_$][0-9a-zA-Z_$]*\>\s*::\@!/ contains=jsNoise skipwhite skipempty nextgroup=jsBlock syntax match jsBlockLabel /\<\K\k*\s*::\@!/ contains=jsNoise skipwhite skipempty nextgroup=jsBlock
syntax match jsBlockLabelKey contained /\<[a-zA-Z_$][0-9a-zA-Z_$]*\>\%(\s*\%(;\|\n\)\)\@=/ syntax match jsBlockLabelKey contained /\<\K\k*\ze\s*\_[;]/
syntax keyword jsStatement contained with yield debugger syntax keyword jsStatement contained with yield debugger
syntax keyword jsStatement contained break continue skipwhite skipempty nextgroup=jsBlockLabelKey syntax keyword jsStatement contained break continue skipwhite skipempty nextgroup=jsBlockLabelKey
syntax keyword jsConditional if skipwhite skipempty nextgroup=jsParenIfElse syntax keyword jsConditional if skipwhite skipempty nextgroup=jsParenIfElse
syntax keyword jsConditional else skipwhite skipempty nextgroup=jsCommentIfElse,jsIfElseBlock syntax keyword jsConditional else skipwhite skipempty nextgroup=jsCommentIfElse,jsIfElseBlock
syntax keyword jsConditional switch skipwhite skipempty nextgroup=jsParenSwitch syntax keyword jsConditional switch skipwhite skipempty nextgroup=jsParenSwitch
syntax keyword jsRepeat while for skipwhite skipempty nextgroup=jsParenRepeat,jsForAwait syntax keyword jsRepeat while for skipwhite skipempty nextgroup=jsParenRepeat,jsForAwait
syntax keyword jsDo do skipwhite skipempty nextgroup=jsRepeatBlock syntax keyword jsDo do skipwhite skipempty nextgroup=jsRepeatBlock
syntax region jsSwitchCase contained matchgroup=jsLabel start=/\<\%(case\|default\)\>/ end=/:\@=/ contains=@jsExpression,jsLabel skipwhite skipempty nextgroup=jsSwitchColon keepend syntax region jsSwitchCase contained matchgroup=jsLabel start=/\<\%(case\|default\)\>/ end=/:\@=/ contains=@jsExpression,jsLabel skipwhite skipempty nextgroup=jsSwitchColon keepend
syntax keyword jsTry try skipwhite skipempty nextgroup=jsTryCatchBlock syntax keyword jsTry try skipwhite skipempty nextgroup=jsTryCatchBlock
syntax keyword jsFinally contained finally skipwhite skipempty nextgroup=jsFinallyBlock syntax keyword jsFinally contained finally skipwhite skipempty nextgroup=jsFinallyBlock
syntax keyword jsCatch contained catch skipwhite skipempty nextgroup=jsParenCatch syntax keyword jsCatch contained catch skipwhite skipempty nextgroup=jsParenCatch
syntax keyword jsException throw syntax keyword jsException throw
syntax keyword jsAsyncKeyword async await syntax keyword jsAsyncKeyword async await
syntax match jsSwitchColon contained /::\@!/ skipwhite skipempty nextgroup=jsSwitchBlock syntax match jsSwitchColon contained /::\@!/ skipwhite skipempty nextgroup=jsSwitchBlock
" Keywords " Keywords
syntax keyword jsGlobalObjects Array Boolean Date Function Iterator Number Object Symbol Map WeakMap Set RegExp String Proxy Promise Buffer ParallelArray ArrayBuffer DataView Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray JSON Math console document window Intl Collator DateTimeFormat NumberFormat fetch syntax keyword jsGlobalObjects Array Boolean Date Function Iterator Number Object Symbol Map WeakMap Set WeakSet RegExp String Proxy Promise Buffer ParallelArray ArrayBuffer DataView Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray JSON Math console document window Intl Collator DateTimeFormat NumberFormat fetch
syntax keyword jsGlobalNodeObjects module exports global process __dirname __filename syntax keyword jsGlobalNodeObjects module exports global process __dirname __filename
syntax match jsGlobalNodeObjects /\<require\>/ containedin=jsFuncCall syntax match jsGlobalNodeObjects /\<require\>/ containedin=jsFuncCall
syntax keyword jsExceptions Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError syntax keyword jsExceptions Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError
@ -162,68 +155,68 @@ syntax region jsBlock matchgroup=jsBraces s
syntax region jsModuleGroup contained matchgroup=jsModuleBraces start=/{/ end=/}/ contains=jsModuleKeyword,jsModuleComma,jsModuleAs,jsComment,jsFlowTypeKeyword skipwhite skipempty nextgroup=jsFrom fold syntax region jsModuleGroup contained matchgroup=jsModuleBraces start=/{/ end=/}/ contains=jsModuleKeyword,jsModuleComma,jsModuleAs,jsComment,jsFlowTypeKeyword skipwhite skipempty nextgroup=jsFrom fold
syntax region jsSpreadExpression contained matchgroup=jsSpreadOperator start=/\.\.\./ end=/[,}\]]\@=/ contains=@jsExpression syntax region jsSpreadExpression contained matchgroup=jsSpreadOperator start=/\.\.\./ end=/[,}\]]\@=/ contains=@jsExpression
syntax region jsRestExpression contained matchgroup=jsRestOperator start=/\.\.\./ end=/[,)]\@=/ syntax region jsRestExpression contained matchgroup=jsRestOperator start=/\.\.\./ end=/[,)]\@=/
syntax region jsTernaryIf matchgroup=jsTernaryIfOperator start=/?/ end=/\%(:\|[\}]\@=\)/ contains=@jsExpression extend skipwhite skipempty nextgroup=@jsExpression syntax region jsTernaryIf matchgroup=jsTernaryIfOperator start=/?/ end=/\%(:\|}\@=\)/ contains=@jsExpression extend skipwhite skipempty nextgroup=@jsExpression
syntax match jsOperator /?\.\ze\_D/
syntax match jsGenerator contained /\*/ skipwhite skipempty nextgroup=jsFuncName,jsFuncArgs syntax match jsGenerator contained /\*/ skipwhite skipempty nextgroup=jsFuncName,jsFuncArgs,jsFlowFunctionGroup
syntax match jsFuncName contained /\<[a-zA-Z_$][0-9a-zA-Z_$]*\>/ skipwhite skipempty nextgroup=jsFuncArgs,jsFlowFunctionGroup syntax match jsFuncName contained /\<\K\k*/ skipwhite skipempty nextgroup=jsFuncArgs,jsFlowFunctionGroup
syntax region jsFuncArgExpression contained matchgroup=jsFuncArgOperator start=/=/ end=/[,)]\@=/ contains=@jsExpression extend syntax region jsFuncArgExpression contained matchgroup=jsFuncArgOperator start=/=/ end=/[,)]\@=/ contains=@jsExpression extend
syntax match jsFuncArgCommas contained ',' syntax match jsFuncArgCommas contained ','
syntax keyword jsArguments contained arguments syntax keyword jsArguments contained arguments
syntax keyword jsForAwait contained await skipwhite skipempty nextgroup=jsParenRepeat syntax keyword jsForAwait contained await skipwhite skipempty nextgroup=jsParenRepeat
" Matches a single keyword argument with no parens " Matches a single keyword argument with no parens
syntax match jsArrowFuncArgs /\k\+\s*\%(=>\)\@=/ skipwhite contains=jsFuncArgs skipwhite skipempty nextgroup=jsArrowFunction extend syntax match jsArrowFuncArgs /\<\K\k*\ze\s*=>/ skipwhite contains=jsFuncArgs skipwhite skipempty nextgroup=jsArrowFunction extend
" Matches a series of arguments surrounded in parens " Matches a series of arguments surrounded in parens
syntax match jsArrowFuncArgs /([^()]*)\s*\(=>\)\@=/ contains=jsFuncArgs skipempty skipwhite nextgroup=jsArrowFunction extend syntax match jsArrowFuncArgs /([^()]*)\ze\s*=>/ contains=jsFuncArgs skipempty skipwhite nextgroup=jsArrowFunction extend
exe 'syntax match jsFunction /\<function\>/ skipwhite skipempty nextgroup=jsGenerator,jsFuncName,jsFuncArgs skipwhite '.(exists('g:javascript_conceal_function') ? 'conceal cchar='.g:javascript_conceal_function : '') exe 'syntax match jsFunction /\<function\>/ skipwhite skipempty nextgroup=jsGenerator,jsFuncName,jsFuncArgs,jsFlowFunctionGroup skipwhite '.(exists('g:javascript_conceal_function') ? 'conceal cchar='.g:javascript_conceal_function : '')
exe 'syntax match jsArrowFunction /=>/ skipwhite skipempty nextgroup=jsFuncBlock,jsCommentFunction '.(exists('g:javascript_conceal_arrow_function') ? 'conceal cchar='.g:javascript_conceal_arrow_function : '') exe 'syntax match jsArrowFunction /=>/ skipwhite skipempty nextgroup=jsFuncBlock,jsCommentFunction '.(exists('g:javascript_conceal_arrow_function') ? 'conceal cchar='.g:javascript_conceal_arrow_function : '')
exe 'syntax match jsArrowFunction /()\s*\(=>\)\@=/ skipwhite skipempty nextgroup=jsArrowFunction '.(exists('g:javascript_conceal_noarg_arrow_function') ? 'conceal cchar='.g:javascript_conceal_noarg_arrow_function : '').(' contains=jsArrowFuncArgs') exe 'syntax match jsArrowFunction /()\ze\s*=>/ skipwhite skipempty nextgroup=jsArrowFunction '.(exists('g:javascript_conceal_noarg_arrow_function') ? 'conceal cchar='.g:javascript_conceal_noarg_arrow_function : '')
exe 'syntax match jsArrowFunction /_\s*\(=>\)\@=/ skipwhite skipempty nextgroup=jsArrowFunction '.(exists('g:javascript_conceal_underscore_arrow_function') ? 'conceal cchar='.g:javascript_conceal_underscore_arrow_function : '') exe 'syntax match jsArrowFunction /_\ze\s*=>/ skipwhite skipempty nextgroup=jsArrowFunction '.(exists('g:javascript_conceal_underscore_arrow_function') ? 'conceal cchar='.g:javascript_conceal_underscore_arrow_function : '')
" Classes " Classes
syntax keyword jsClassKeyword contained class syntax keyword jsClassKeyword contained class
syntax keyword jsExtendsKeyword contained extends skipwhite skipempty nextgroup=@jsExpression syntax keyword jsExtendsKeyword contained extends skipwhite skipempty nextgroup=@jsExpression
syntax match jsClassNoise contained /\./ syntax match jsClassNoise contained /\./
syntax match jsClassMethodType contained /\%(get\|set\|static\)\%( \k\+\)\@=/ skipwhite skipempty nextgroup=jsAsyncKeyword,jsFuncName,jsClassProperty syntax match jsClassMethodType contained /\<\%([gs]et\|static\)\ze\s\+\K\k*/ skipwhite skipempty nextgroup=jsAsyncKeyword,jsFuncName,jsClassProperty
syntax region jsClassDefinition start=/\<class\>/ end=/\(\<extends\>\s\+\)\@<!{\@=/ contains=jsClassKeyword,jsExtendsKeyword,jsClassNoise,@jsExpression,jsFlowClassGroup skipwhite skipempty nextgroup=jsCommentClass,jsClassBlock,jsFlowClassGroup syntax region jsClassDefinition start=/\<class\>/ end=/\(\<extends\>\s\+\)\@<!{\@=/ contains=jsClassKeyword,jsExtendsKeyword,jsClassNoise,@jsExpression,jsFlowClassGroup skipwhite skipempty nextgroup=jsCommentClass,jsClassBlock,jsFlowClassGroup
syntax match jsClassProperty contained /\<[0-9a-zA-Z_$]*\>\(\s*[=:]\)\@=/ skipwhite skipempty nextgroup=jsClassValue,jsFlowClassDef syntax match jsClassProperty contained /\<\K\k*\ze\s*=/ skipwhite skipempty nextgroup=jsClassValue,jsFlowClassDef
syntax region jsClassValue contained start=/=/ end=/\%(;\|}\|\n\)\@=/ contains=@jsExpression syntax region jsClassValue contained start=/=/ end=/\_[;}]\@=/ contains=@jsExpression
syntax region jsClassPropertyComputed contained matchgroup=jsBrackets start=/\[/ end=/]/ contains=@jsExpression skipwhite skipempty nextgroup=jsFuncArgs,jsClassValue extend syntax region jsClassPropertyComputed contained matchgroup=jsBrackets start=/\[/ end=/]/ contains=@jsExpression skipwhite skipempty nextgroup=jsFuncArgs,jsClassValue extend
syntax match jsClassFuncName contained /\<[a-zA-Z_$][0-9a-zA-Z_$]*\>\%(\s*(\)\@=/ skipwhite skipempty nextgroup=jsFuncArgs syntax match jsClassFuncName contained /\<\K\k*\ze\s*(/ skipwhite skipempty nextgroup=jsFuncArgs
syntax region jsClassStringKey contained start=+"+ skip=+\\\("\|$\)+ end=+"\|$+ contains=jsSpecial,@Spell extend skipwhite skipempty nextgroup=jsFuncArgs syntax region jsClassStringKey contained start=+\z(["']\)+ skip=+\\\%(\z1\|$\)+ end=+\z1\|$+ contains=jsSpecial,@Spell extend skipwhite skipempty nextgroup=jsFuncArgs
syntax region jsClassStringKey contained start=+'+ skip=+\\\('\|$\)+ end=+'\|$+ contains=jsSpecial,@Spell extend skipwhite skipempty nextgroup=jsFuncArgs
" Destructuring " Destructuring
syntax match jsDestructuringPropertyValue contained /\<[0-9a-zA-Z_$]*\>/ syntax match jsDestructuringPropertyValue contained /\k\+/
syntax match jsDestructuringProperty contained /\<[0-9a-zA-Z_$]*\>\(\s*=\)\@=/ skipwhite skipempty nextgroup=jsDestructuringValue syntax match jsDestructuringProperty contained /\k\+\ze\s*=/ skipwhite skipempty nextgroup=jsDestructuringValue
syntax match jsDestructuringAssignment contained /\<[0-9a-zA-Z_$]*\>\(\s*:\)\@=/ skipwhite skipempty nextgroup=jsDestructuringValueAssignment syntax match jsDestructuringAssignment contained /\k\+\ze\s*:/ skipwhite skipempty nextgroup=jsDestructuringValueAssignment
syntax region jsDestructuringValue contained start=/=/ end=/[,}\]]\@=/ contains=@jsExpression extend syntax region jsDestructuringValue contained start=/=/ end=/[,}\]]\@=/ contains=@jsExpression extend
syntax region jsDestructuringValueAssignment contained start=/:/ end=/[,}=]\@=/ contains=jsDestructuringPropertyValue,jsDestructuringBlock,jsNoise,jsDestructuringNoise skipwhite skipempty nextgroup=jsDestructuringValue extend syntax region jsDestructuringValueAssignment contained start=/:/ end=/[,}=]\@=/ contains=jsDestructuringPropertyValue,jsDestructuringBlock,jsNoise,jsDestructuringNoise skipwhite skipempty nextgroup=jsDestructuringValue extend
syntax match jsDestructuringNoise contained /[,\[\]]/ syntax match jsDestructuringNoise contained /[,[\]]/
syntax region jsDestructuringPropertyComputed contained matchgroup=jsBrackets start=/\[/ end=/]/ contains=@jsExpression skipwhite skipempty nextgroup=jsDestructuringValue,jsDestructuringNoise extend fold syntax region jsDestructuringPropertyComputed contained matchgroup=jsBrackets start=/\[/ end=/]/ contains=@jsExpression skipwhite skipempty nextgroup=jsDestructuringValue,jsDestructuringNoise extend fold
" Comments " Comments
syntax keyword jsCommentTodo contained TODO FIXME XXX TBD syntax keyword jsCommentTodo contained TODO FIXME XXX TBD
syntax region jsComment start=/\/\// end=/$/ contains=jsCommentTodo,@Spell extend keepend syntax region jsComment start=+//+ end=/$/ contains=jsCommentTodo,@Spell extend keepend
syntax region jsComment start=/\/\*/ end=/\*\// contains=jsCommentTodo,@Spell fold extend keepend syntax region jsComment start=+/\*+ end=+\*/+ contains=jsCommentTodo,@Spell fold extend keepend
syntax region jsEnvComment start=/\%^#!/ end=/$/ display syntax region jsEnvComment start=/\%^#!/ end=/$/ display
" Specialized Comments - These are special comment regexes that are used in " Specialized Comments - These are special comment regexes that are used in
" odd places that maintain the proper nextgroup functionality. It sucks we " odd places that maintain the proper nextgroup functionality. It sucks we
" can't make jsComment a skippable type of group for nextgroup " can't make jsComment a skippable type of group for nextgroup
syntax region jsCommentFunction contained start=/\/\// end=/$/ contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsFuncBlock,jsFlowReturn extend keepend syntax region jsCommentFunction contained start=+//+ end=/$/ contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsFuncBlock,jsFlowReturn extend keepend
syntax region jsCommentFunction contained start=/\/\*/ end=/\*\// contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsFuncBlock,jsFlowReturn fold extend keepend syntax region jsCommentFunction contained start=+/\*+ end=+\*/+ contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsFuncBlock,jsFlowReturn fold extend keepend
syntax region jsCommentClass contained start=/\/\// end=/$/ contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsClassBlock,jsFlowClassGroup extend keepend syntax region jsCommentClass contained start=+//+ end=/$/ contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsClassBlock,jsFlowClassGroup extend keepend
syntax region jsCommentClass contained start=/\/\*/ end=/\*\// contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsClassBlock,jsFlowClassGroup fold extend keepend syntax region jsCommentClass contained start=+/\*+ end=+\*/+ contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsClassBlock,jsFlowClassGroup fold extend keepend
syntax region jsCommentIfElse contained start=/\/\// end=/$/ contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsIfElseBlock extend keepend syntax region jsCommentIfElse contained start=+//+ end=/$/ contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsIfElseBlock extend keepend
syntax region jsCommentIfElse contained start=/\/\*/ end=/\*\// contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsIfElseBlock fold extend keepend syntax region jsCommentIfElse contained start=+/\*+ end=+\*/+ contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsIfElseBlock fold extend keepend
syntax region jsCommentRepeat contained start=/\/\// end=/$/ contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsRepeatBlock extend keepend syntax region jsCommentRepeat contained start=+//+ end=/$/ contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsRepeatBlock extend keepend
syntax region jsCommentRepeat contained start=/\/\*/ end=/\*\// contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsRepeatBlock fold extend keepend syntax region jsCommentRepeat contained start=+/\*+ end=+\*/+ contains=jsCommentTodo,@Spell skipwhite skipempty nextgroup=jsRepeatBlock fold extend keepend
" Decorators " Decorators
syntax match jsDecorator /^\s*@/ nextgroup=jsDecoratorFunction syntax match jsDecorator /^\s*@/ nextgroup=jsDecoratorFunction
syntax match jsDecoratorFunction contained /[a-zA-Z_][a-zA-Z0-9_.]*/ nextgroup=jsParenDecorator syntax match jsDecoratorFunction contained /\h[a-zA-Z0-9_.]*/ nextgroup=jsParenDecorator
if exists("javascript_plugin_jsdoc") if exists("javascript_plugin_jsdoc")
runtime extras/jsdoc.vim runtime extras/jsdoc.vim
@ -237,8 +230,8 @@ if exists("javascript_plugin_flow")
runtime extras/flow.vim runtime extras/flow.vim
endif endif
syntax cluster jsExpression contains=jsBracket,jsParen,jsObject,jsTernaryIf,jsTaggedTemplate,jsTemplateString,jsString,jsRegexpString,jsNumber,jsFloat,jsOperator,jsBooleanTrue,jsBooleanFalse,jsNull,jsFunction,jsArrowFunction,jsGlobalObjects,jsExceptions,jsFutureKeys,jsDomErrNo,jsDomNodeConsts,jsHtmlEvents,jsFuncCall,jsUndefined,jsNan,jsPrototype,jsBuiltins,jsNoise,jsClassDefinition,jsArrowFunction,jsArrowFuncArgs,jsParensError,jsComment,jsArguments,jsThis,jsSuper,jsDo,jsForAwait,jsAsyncKeyword syntax cluster jsExpression contains=jsBracket,jsParen,jsObject,jsTernaryIf,jsTaggedTemplate,jsTemplateString,jsString,jsRegexpString,jsNumber,jsFloat,jsOperator,jsBooleanTrue,jsBooleanFalse,jsNull,jsFunction,jsArrowFunction,jsGlobalObjects,jsExceptions,jsFutureKeys,jsDomErrNo,jsDomNodeConsts,jsHtmlEvents,jsFuncCall,jsUndefined,jsNan,jsPrototype,jsBuiltins,jsNoise,jsClassDefinition,jsArrowFunction,jsArrowFuncArgs,jsParensError,jsComment,jsArguments,jsThis,jsSuper,jsDo,jsForAwait,jsAsyncKeyword,jsStatement
syntax cluster jsAll contains=@jsExpression,jsStorageClass,jsConditional,jsRepeat,jsReturn,jsStatement,jsException,jsTry,jsNoise,jsBlockLabel syntax cluster jsAll contains=@jsExpression,jsStorageClass,jsConditional,jsRepeat,jsReturn,jsException,jsTry,jsNoise,jsBlockLabel
" Define the default highlighting. " Define the default highlighting.
" For version 5.7 and earlier: only when not done already " For version 5.7 and earlier: only when not done already

Loading…
Cancel
Save