summaryrefslogtreecommitdiffstats
path: root/indent/javascript.vim
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--indent/javascript.vim120
1 files changed, 69 insertions, 51 deletions
diff --git a/indent/javascript.vim b/indent/javascript.vim
index 728fa117..f6fda1dc 100644
--- a/indent/javascript.vim
+++ b/indent/javascript.vim
@@ -12,10 +12,6 @@ if exists('b:did_indent')
endif
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.
setlocal indentexpr=GetJavascriptIndent()
setlocal autoindent nolisp nosmartindent
@@ -27,13 +23,6 @@ setlocal indentkeys+=0],0)
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.
if exists('*GetJavascriptIndent')
finish
@@ -42,6 +31,23 @@ endif
let s:cpo_save = &cpo
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
if exists('*shiftwidth')
function s:sw()
@@ -106,9 +112,7 @@ endfunction
function s:SkipFunc()
if s:top_col == 1
throw 'out of bounds'
- endif
- let s:top_col = 0
- if s:check_in
+ elseif s:check_in
if eval(s:skip_expr)
return 1
endif
@@ -161,19 +165,29 @@ function s:Token()
return s:LookingAt() =~ '\k' ? expand('<cword>') : s:LookingAt()
endfunction
-function s:PreviousToken()
- let l:col = col('.')
+function s:PreviousToken(...)
+ let [l:pos, tok] = [getpos('.'), '']
if search('\m\k\{1,}\|\S','ebW')
- if search('\m\*\%#\/\|\/\/\%<'.a:firstline.'l','nbW',line('.')) && eval(s:in_comm)
- if s:SearchLoop('\S\ze\_s*\/[/*]','bW',s:in_comm)
- return s:Token()
+ if getline('.')[col('.')-2:col('.')-1] == '*/'
+ if eval(s:in_comm) && !s:SearchLoop('\S\ze\_s*\/[/*]','bW',s:in_comm)
+ call setpos('.',l:pos)
+ else
+ let tok = s:Token()
endif
- call cursor(a:firstline, l:col)
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
- return ''
+ return tok
endfunction
function s:Pure(f,...)
@@ -217,15 +231,14 @@ let s:opfirst = '^' . get(g:,'javascript_opfirst',
let s:continuation = get(g:,'javascript_continuation',
\ '\C\%([<=,.~!?/*^%|&:]\|+\@<!+\|-\@<!-\|=\@<!>\|\<\%(typeof\|new\|delete\|void\|in\|instanceof\|await\)\)') . '$'
-function s:Continues(ln,con)
- let tok = matchstr(a:con[-15:],s:continuation)
+function s:Continues()
+ let tok = matchstr(strpart(getline('.'),col('.')-15,15),s:continuation)
if tok =~ '[a-z:]'
- call cursor(a:ln, len(a:con))
return tok == ':' ? s:ExprCol() : s:PreviousToken() != '.'
elseif tok !~ '[/>]'
return tok isnot ''
endif
- return s:SynAt(a:ln, len(a:con)) !~? (tok == '>' ? 'jsflow\|^html' : 'regex')
+ return s:SynAt(line('.'),col('.')) !~? (tok == '>' ? 'jsflow\|^html' : 'regex')
endfunction
" Check if line 'lnum' has a balanced amount of parentheses.
@@ -259,21 +272,27 @@ endfunction
function s:DoWhile()
let cpos = searchpos('\m\<','cbW')
- if s:SearchLoop('\C[{}]\|\<\%(do\|while\)\>','bW',s:skip_expr)
- if s:{s:LookingAt() == '}' && s:GetPair('{','}','bW',s:skip_expr) ?
- \ 'Previous' : ''}Token() ==# 'do' && s:IsBlock()
- return 1
+ while s:SearchLoop('\C[{}]\|\<\%(do\|while\)\>','bW',s:skip_expr)
+ if s:LookingAt() =~ '\a'
+ if s:Pure('s:IsBlock')
+ if s:LookingAt() ==# 'd'
+ return 1
+ endif
+ break
+ endif
+ elseif s:LookingAt() != '}' || !s:GetPair('{','}','bW',s:skip_expr)
+ break
endif
- call call('cursor',cpos)
- endif
+ endwhile
+ call call('cursor',cpos)
endfunction
" returns total offset from braceless contexts. 'num' is the lineNr which
" encloses the entire context, 'cont' if whether a:firstline is a continued
" expression, which could have started in a braceless context
-function s:IsContOne(num,cont)
- let [l:num, b_l] = [a:num + !a:num, 0]
- let pind = a:num ? indent(a:num) + s:sw() : 0
+function s:IsContOne(cont)
+ let [l:num, b_l] = [b:js_cache[1] + !b:js_cache[1], 0]
+ let pind = b:js_cache[1] ? indent(b:js_cache[1]) + s:sw() : 0
let ind = indent('.') + !a:cont
while line('.') > l:num && ind > pind || line('.') == l:num
if indent('.') < ind && s:OneScope()
@@ -300,6 +319,7 @@ endfunction
function s:IsBlock()
let tok = s:PreviousToken()
if join(s:stack) =~? 'xml\|jsx' && s:SynAt(line('.'),col('.')-1) =~? 'xml\|jsx'
+ let s:in_jsx = 1
return tok != '{'
elseif tok =~ '\k'
if tok ==# 'type'
@@ -324,7 +344,7 @@ function s:IsBlock()
endfunction
function GetJavascriptIndent()
- let b:js_cache = get(b:,'js_cache',[0,0,0])
+ call s:GetVars()
let s:synid_cache = [[],[]]
let l:line = getline(v:lnum)
" use synstack as it validates syn state and works in an empty line
@@ -386,10 +406,10 @@ function GetJavascriptIndent()
let [b:js_cache[0], num] = [v:lnum, 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 !num || s:LookingAt() == '{' && s:IsBlock()
let ilnum = line('.')
- if num && s:LookingAt() == ')' && s:GetPair('(',')','bW',s:skip_expr)
+ if num && !s:in_jsx && s:LookingAt() == ')' && s:GetPair('(',')','bW',s:skip_expr)
if ilnum == num
let [num, num_ind] = [line('.'), indent('.')]
endif
@@ -403,26 +423,24 @@ function GetJavascriptIndent()
endif
endif
if idx == -1 && pline[-1:] !~ '[{;]'
+ call cursor(l:lnum, len(pline))
let sol = matchstr(l:line,s:opfirst)
if sol is '' || sol == '/' && s:SynAt(v:lnum,
\ 1 + len(getline(v:lnum)) - len(l:line)) =~? 'regex'
- if s:Continues(l:lnum,pline)
+ if s:Continues()
let is_op = s:sw()
endif
- elseif num && sol =~# '^\%(in\%(stanceof\)\=\|\*\)$'
- call cursor(l:lnum, len(pline))
- if s:LookingAt() == '}' && s:GetPair('{','}','bW',s:skip_expr) &&
- \ s:PreviousToken() == ')' && s:GetPair('(',')','bW',s:skip_expr) &&
- \ (s:PreviousToken() == ']' || s:Token() =~ '\k' &&
- \ s:{s:PreviousToken() == '*' ? 'Previous' : ''}Token() !=# 'function')
- return num_ind + s:sw()
- endif
- let is_op = s:sw()
+ elseif num && sol =~# '^\%(in\%(stanceof\)\=\|\*\)$' &&
+ \ 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()
endif
call cursor(l:lnum, len(pline))
- let b_l = s:Nat(s:IsContOne(b:js_cache[1],is_op) - (!is_op && l:line =~ '^{')) * s:sw()
+ let b_l = s:Nat(s:IsContOne(is_op) - (!is_op && l:line =~ '^{')) * s:sw()
endif
elseif idx.s:LookingAt().&cino =~ '^-1(.*(' && (search('\m\S','nbW',num) || s:ParseCino('U'))
let pval = s:ParseCino('(')
@@ -438,10 +456,10 @@ function GetJavascriptIndent()
" main return
if l:line =~ '^[])}]\|^|}'
- if l:line_raw[0] == ')' && getline(num)[b:js_cache[2]-1] == '('
+ if l:line_raw[0] == ')'
if s:ParseCino('M')
return indent(l:lnum)
- elseif &cino =~# 'm' && !s:ParseCino('m')
+ elseif num && &cino =~# 'm' && !s:ParseCino('m')
return virtcol('.') - 1
endif
endif