Skip to content

Commit 997c2b1

Browse files
authored
Merge pull request #679 from pangloss/develop
Develop -> Master
2 parents d736e95 + 23bb9c3 commit 997c2b1

File tree

1 file changed

+114
-116
lines changed

1 file changed

+114
-116
lines changed

indent/javascript.vim

+114-116
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
" Language: Javascript
33
" Maintainer: Chris Paul ( https://github.com/bounceme )
44
" URL: https://github.com/pangloss/vim-javascript
5-
" Last Change: October 9, 2016
5+
" Last Change: October 24, 2016
66

77
" Only load this indent file when no other was loaded.
88
if exists('b:did_indent')
@@ -12,7 +12,7 @@ let b:did_indent = 1
1212

1313
" Now, set up our indentation expression and keys that trigger it.
1414
setlocal indentexpr=GetJavascriptIndent()
15-
setlocal nolisp noautoindent nosmartindent
15+
setlocal autoindent nolisp nosmartindent
1616
setlocal indentkeys=0{,0},0),0],:,!^F,o,O,e
1717
setlocal cinoptions+=j1,J1
1818

@@ -37,9 +37,6 @@ else
3737
endfunction
3838
endif
3939

40-
let s:line_pre = '^\s*\%(\%(\%(\/\*.\{-}\)\=\*\+\/\s*\)\=\)\@>'
41-
let s:line_term = '\s*\%(\%(\/\%(\%(\*.\{-}\*\/\)\|\%(\*\+\)\)\)\s*\)\=$'
42-
4340
let s:expr_case = '\<\%(\%(case\>\s*\S.\{-}\)\|default\)\s*:\C'
4441
" Regex of syntax group names that are or delimit string or are comments.
4542
let s:syng_strcom = '\%(s\%(tring\|pecial\)\|comment\|regex\|doc\|template\)'
@@ -53,114 +50,110 @@ function s:skip_func(lnum)
5350
return !s:free
5451
endif
5552
let s:looksyn = line('.')
56-
return (search('\/','nbW',line('.')) || search('[''"\\]','nW',line('.'))) && eval(s:skip_expr)
53+
return (strridx(getline('.'),'/',col('.')-1) + 1 || search('[''"\\]','nW',s:looksyn)) && eval(s:skip_expr)
5754
endfunction
5855

5956
if has('reltime')
6057
function s:GetPair(start,end,flags,skip,time,...)
6158
return searchpair(a:start,'',a:end,a:flags,a:skip,max([prevnonblank(v:lnum) - 2000,0] + a:000),a:time)
6259
endfunction
6360
else
64-
function s:GetPair(start,end,flags,...)
65-
return searchpair(a:start,'',a:end,a:flags,"line('.') < prevnonblank(v:lnum) - 2000 ? dummy : 0")
61+
function s:GetPair(start,end,flags,skip,...)
62+
return searchpair(a:start,'',a:end,a:flags,a:skip,max([prevnonblank(v:lnum) - 1000,get(a:000,1)]))
6663
endfunction
6764
endif
6865

69-
" indent/python.vim
70-
function s:Trimline(ln)
71-
let pline = getline(a:ln)
72-
let min = match(pline,'\/[/*]') + 1
73-
if min && synIDattr(synID(a:ln, strlen(pline), 0), 'name') =~? '\%(comment\|doc\)'
74-
let max = match(pline,'.*\zs\/[/*]') + 1
75-
while min < max
76-
let col = (min + max) / 2
77-
if synIDattr(synID(a:ln, col, 0), 'name') =~? '\%(comment\|doc\)'
78-
let max = col
79-
else
80-
let min = match(pline,'\/[/*]',col) + 1
81-
endif
82-
endwhile
83-
let pline = strpart(pline, 0, min - 1)
84-
endif
85-
return substitute(pline,'\s*$','','')
66+
function s:Trim(ln)
67+
let pline = substitute(getline(a:ln),'\s*$','','')
68+
let l:max = max([strridx(pline,'//'),strridx(pline,'/*'),0])
69+
while l:max && synIDattr(synID(a:ln, strlen(pline), 0), 'name') =~? '\%(comment\|doc\)'
70+
let pline = substitute(strpart(pline, 0, l:max),'\s*$','','')
71+
let l:max = max([strridx(pline,'//'),strridx(pline,'/*'),0])
72+
endwhile
73+
return pline
8674
endfunction
8775

8876
" configurable regexes that define continuation lines, not including (, {, or [.
89-
if !exists('g:javascript_opfirst')
90-
let g:javascript_opfirst = '\%([<>,?^%|*&]\|\/[/*]\@!\|\([-.:+]\)\1\@!\|=>\@!\|in\%(stanceof\)\=\>\)'
91-
endif
92-
if !exists('g:javascript_continuation')
93-
let g:javascript_continuation = '\%([<=,.?/*^%|&:]\|+\@<!+\|-\@<!-\|=\@<!>\|\<in\%(stanceof\)\=\)'
94-
endif
95-
96-
let g:javascript_opfirst = '^' . g:javascript_opfirst
97-
let g:javascript_continuation .= '$'
77+
let s:opfirst = '^' . get(g:,'javascript_opfirst',
78+
\ '\%([<>,?^%|*&]\|\/[/*]\@!\|\([-.:+]\)\1\@!\|=>\@!\|in\%(stanceof\)\=\>\)')
79+
let s:continuation = get(g:,'javascript_continuation',
80+
\ '\%([<=,.?/*^%|&:]\|+\@<!+\|-\@<!-\|=\@<!>\|\<in\%(stanceof\)\=\)') . '$'
9881

9982
function s:OneScope(lnum,text)
100-
return cursor(a:lnum, match(' ' . a:text, '\%(\<else\|\<do\|=>\)$')) > -1 ||
101-
\ cursor(a:lnum, match(' ' . a:text, ')$')) > -1 &&
83+
return cursor(a:lnum, match(' ' . a:text, '\%(\<else\|\<do\|=>\)$')) + 1 ||
84+
\ cursor(a:lnum, match(' ' . a:text, ')$')) + 1 &&
10285
\ s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0 &&
10386
\ search('\C\<\%(for\%(\_s\+\%(await\|each\)\)\=\|if\|let\|w\%(hile\|ith\)\)\_s*\%#','bW')
10487
endfunction
10588

10689
function s:iscontOne(i,num,cont)
10790
let [l:i, l:cont, l:num] = [a:i, a:cont, a:num + !a:num]
108-
let pind = a:num ? indent(l:num) : -s:W
109-
let ind = indent(l:i) + (!l:cont * s:W)
91+
let pind = a:num ? indent(l:num) + s:W : 0
92+
let ind = indent(l:i) + (a:cont ? 0 : s:W)
11093
let bL = 0
111-
while l:i >= l:num && (!l:cont || ind > pind + s:W)
94+
while l:i >= l:num && (!l:cont || ind > pind)
11295
if indent(l:i) < ind " first line always true for !a:cont, false for !!a:cont
113-
if s:OneScope(l:i,s:Trimline(l:i))
96+
if s:OneScope(l:i,s:Trim(l:i))
11497
if expand('<cword>') ==# 'while' &&
115-
\ s:GetPair(s:line_pre . '\C\<do\>','\C\<while\>','bW',s:skip_expr,100,l:num + !!a:num) > 0
98+
\ s:GetPair('\C\<do\>','\C\<while\>','bW','line2byte(line(".")) + col(".") <'
99+
\ . (line2byte(l:num) + b:js_cache[2]) . '||'
100+
\ . s:skip_expr . '|| !s:IsBlock()',100,l:num) > 0
116101
return 0
117102
endif
118-
let bL += 1
103+
let bL += s:W
119104
let [l:cont, l:i] = [0, line('.')]
120105
elseif !l:cont
121106
break
122107
endif
123108
let ind = indent(l:i)
109+
elseif !a:cont
110+
break
124111
endif
125112
let l:i = s:PrevCodeLine(l:i - 1)
126113
endwhile
127-
return bL * s:W
114+
return bL
128115
endfunction
129116

130117
" https://github.com/sweet-js/sweet.js/wiki/design#give-lookbehind-to-the-reader
131118
function s:IsBlock()
132-
if getline(line('.'))[col('.')-1] == '{'
133-
if search('\C\<return\s*\%#','nbW')
134-
return 0
135-
endif
136-
if search('\*\/\_s*\%#','bW') && synIDattr(synID(line('.'),col('.'),0),'name') =~? 'comment'
137-
call searchpair('\/\*','','\*\/','bW')
119+
let l:ln = line('.')
120+
if search('\S','bW')
121+
let char = getline('.')[col('.')-1]
122+
let pchar = getline('.')[col('.')-2]
123+
let syn = synIDattr(synID(line('.'),col('.')-1,0),'name')
124+
if pchar . char == '*/' && syn =~? 'comment'
125+
if !search('\/\*','bW') || !search('\S','bW')
126+
return 1
127+
endif
128+
let char = getline('.')[col('.')-1]
129+
let pchar = getline('.')[col('.')-2]
130+
let syn = synIDattr(synID(line('.'),col('.')-1,0),'name')
138131
endif
139-
if search('\S','bW')
140-
let char = getline(line('.'))[col('.')-1]
141-
if char =~# '\l'
142-
return expand('<cword>') !~#
143-
\ '^\%(var\|const\|let\|\%(im\|ex\)port\|yield\|de\%(fault\|lete\)\|void\|t\%(ypeof\|hrow\)\|new\|in\%(stanceof\)\=\)$'
144-
elseif char == '>'
145-
return search('=\%#','bW') || synIDattr(synID(line('.'),col('.'),0),'name') =~? 'flownoise'
146-
elseif char == ':'
147-
return strpart(getline(line('.')),0,col('.')) =~# s:expr_case . '$'
148-
elseif char == '{'
149-
return s:IsBlock()
150-
else
151-
return char !~# '[-=~!<*+,./?^%|&\[(]'
132+
if syn =~? '\%(xml\|jsx\)'
133+
return char != '{'
134+
elseif char =~# '\l'
135+
if line('.') == l:ln && expand('<cword>') ==# 'return'
136+
return 0
152137
endif
138+
return index(split('const let import export yield default delete var void typeof throw new in instanceof')
139+
\ , expand('<cword>')) < 0
140+
elseif char == '>'
141+
return pchar == '=' || syn =~? '^jsflow'
142+
elseif char == ':'
143+
return strpart(getline('.'),0,col('.')) =~# s:expr_case . '$'
153144
else
154-
return 1
145+
return stridx('-=~!<*+,/?^%|&([',char) < 0
155146
endif
147+
else
148+
return 1
156149
endif
157150
endfunction
158151

159152
" Find line above 'lnum' that isn't empty, in a comment, or in a string.
160153
function s:PrevCodeLine(lnum)
161154
let l:lnum = prevnonblank(a:lnum)
162155
while l:lnum
163-
if synIDattr(synID(l:lnum,matchend(getline(l:lnum), '^\s*[^''"]'),0),'name') !~? s:syng_strcom
156+
if synIDattr(synID(l:lnum,matchend(getline(l:lnum), '^\s*[^''"`]'),0),'name') !~? s:syng_strcom
164157
return l:lnum
165158
endif
166159
let l:lnum = prevnonblank(l:lnum - 1)
@@ -169,33 +162,30 @@ endfunction
169162

170163
" Check if line 'lnum' has a balanced amount of parentheses.
171164
function s:Balanced(lnum)
172-
let [open_0,open_2,open_4] = [0,0,0]
165+
let l:open = 0
173166
let l:line = getline(a:lnum)
174167
let pos = match(l:line, '[][(){}]', 0)
175168
while pos != -1
176169
if synIDattr(synID(a:lnum,pos + 1,0),'name') !~? s:syng_strcom
177-
let idx = stridx('(){}[]', l:line[pos])
178-
if !(idx % 2)
179-
let open_{idx} += 1
170+
if stridx('[({',l:line[pos]) + 1
171+
let l:open += 1
180172
else
181-
let open_{idx - 1} -= 1
182-
if open_{idx - 1} < 0
173+
let l:open -= 1
174+
if l:open < 0
183175
return 0
184176
endif
185177
endif
186178
endif
187179
let pos = match(l:line, '[][(){}]', pos + 1)
188180
endwhile
189-
return !(open_4 || open_2 || open_0)
181+
return !l:open
190182
endfunction
191183

192184
function GetJavascriptIndent()
193185
try
194186
let save_magic = &magic
195187
set magic
196-
if !exists('b:js_cache')
197-
let b:js_cache = [0,0,0]
198-
endif
188+
let b:js_cache = get(b:,'js_cache',[0,0,0])
199189
" Get the current line.
200190
let l:line = getline(v:lnum)
201191
let syns = synIDattr(synID(v:lnum, 1, 0), 'name')
@@ -211,76 +201,84 @@ function GetJavascriptIndent()
211201
return -1
212202
endif
213203
let l:lnum = s:PrevCodeLine(v:lnum - 1)
214-
if l:lnum == 0
204+
if !l:lnum
215205
return 0
216206
endif
217207

218208
let l:line = substitute(l:line,'^\s*\%(\/\*.\{-}\*\/\s*\)*','','')
219209

220-
if l:line =~# '^' . s:expr_case
221-
let cpo_switch = &cpo
222-
set cpo+=%
223-
let ind = cindent(v:lnum)
224-
let &cpo = cpo_switch
225-
return ind
226-
endif
227-
228-
" the containing paren, bracket, curly. Memoize, last lineNr either has the
229-
" same scope or starts a new one, unless if it closed a scope.
210+
" the containing paren, bracket, curly. Many hacks for performance
230211
call cursor(v:lnum,1)
231-
if getline(l:lnum) !~ '^\S'
212+
let idx = strlen(l:line) ? stridx('])}',l:line[0]) : -1
213+
if indent(l:lnum)
232214
let [s:looksyn,s:free] = [v:lnum - 1,1]
233215
if b:js_cache[0] >= l:lnum && b:js_cache[0] < v:lnum &&
234216
\ (b:js_cache[0] > l:lnum || s:Balanced(l:lnum))
235-
let num = b:js_cache[1]
236-
elseif l:line =~ '^[])}]'
237-
let id = stridx('])}',l:line[0])
238-
let num = s:GetPair(escape('[({'[id],'['), escape('])}'[id],']'),'bW','s:skip_func(s:looksyn)',2000)
239-
elseif syns != '' && getline(v:lnum)[0] =~ '\s'
240-
let pattern = syns =~? 'block' ? ['{','}'] : syns =~? 'jsparen' ? ['(',')'] :
241-
\ syns =~? 'jsbracket'? ['\[','\]'] : ['[({[]','[])}]']
242-
let num = s:GetPair(pattern[0],pattern[1],'bW','s:skip_func(s:looksyn)',2000)
217+
call call('cursor',b:js_cache[1:])
218+
elseif idx + 1
219+
call s:GetPair(['\[','(','{'][idx], '])}'[idx],'bW','s:skip_func(s:looksyn)',2000)
220+
elseif indent(v:lnum) && syns =~? 'block'
221+
call s:GetPair('{','}','bW','s:skip_func(s:looksyn)',2000)
243222
else
244-
let num = s:GetPair('[({[]','[])}]','bW','s:skip_func(s:looksyn)',2000)
223+
call s:GetPair('[({[]','[])}]','bW','s:skip_func(s:looksyn)',2000)
245224
endif
246225
else
247-
let num = s:GetPair('[({[]','[])}]','bW',s:skip_expr,200,l:lnum)
226+
call s:GetPair('[({[]','[])}]','bW',s:skip_expr,200,l:lnum)
248227
endif
249228

250-
let num = (num > 0) * num
251-
if l:line =~ '^[])}]'
252-
return !!num * indent(num)
229+
if idx + 1
230+
if idx == 2 && search('\S','bW',line('.')) && getline('.')[col('.')-1] == ')'
231+
call s:GetPair('(',')','bW',s:skip_expr,200)
232+
endif
233+
return indent(line('.'))
253234
endif
254-
let b:js_cache = [v:lnum,num,line('.') == v:lnum ? b:js_cache[2] : col('.')]
255235

256-
call cursor(v:lnum,1)
257-
if l:line =~# '^while\>' && s:GetPair(s:line_pre . '\C\<do\>','\C\<while\>','bW',s:skip_expr,100,num + 1) > 0
258-
return indent(line('.'))
236+
let b:js_cache = [v:lnum] + (line('.') == v:lnum ? [0,0] : [line('.'),col('.')])
237+
let num = b:js_cache[1]
238+
239+
let [s:W, pline, isOp, stmt, bL, switch_offset] = [s:sw(), s:Trim(l:lnum),0,0,0,0]
240+
if num
241+
if getline('.')[col('.')-1] == '{'
242+
if search(')\_s*\%#','bW')
243+
let stmt = 1
244+
if s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0 && search('\C\<switch\_s*\%#','bW')
245+
let switch_offset = &cino !~ ':' || !has('float') ? s:W :
246+
\ float2nr(str2float(matchstr(&cino,'.*:\zs[-0-9.]*')) * (&cino =~# '.*:[^,]*s' ? s:W : 1))
247+
if l:line =~# '^' . s:expr_case
248+
return indent(num) + switch_offset
249+
endif
250+
let stmt = pline !~# s:expr_case . '$'
251+
endif
252+
elseif s:IsBlock()
253+
let stmt = 1
254+
endif
255+
endif
256+
else
257+
let stmt = 1
259258
endif
260259

261-
let s:W = s:sw()
262-
let pline = s:Trimline(l:lnum)
263-
call cursor(b:js_cache[1],b:js_cache[2])
264-
let switch_offset = !num || !(search(')\_s*\%#','bW') &&
265-
\ s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0 && search('\C\<switch\_s*\%#','bW')) ? 0 :
266-
\ &cino !~ ':' || !has('float') ? s:W :
267-
\ float2nr(str2float(matchstr(&cino,'.*:\zs[-0-9.]*')) * (&cino =~# '.*:[^,]*s' ? s:W : 1))
260+
if stmt
261+
call cursor(v:lnum,1)
262+
if l:line =~# '^while\>' && s:GetPair('\C\<do\>','\C\<while\>','bW',s:skip_expr . '|| !s:IsBlock()',100,num + 1) > 0
263+
return indent(line('.'))
264+
endif
265+
let isOp = l:line =~# s:opfirst || pline =~# s:continuation
266+
let bL = s:iscontOne(l:lnum,num,isOp)
267+
let bL -= (bL && l:line[0] == '{') * s:W
268+
endif
268269

269-
" most significant, find the indent amount
270-
let isOp = l:line =~# g:javascript_opfirst || pline !~# s:expr_case . '$' && pline =~# g:javascript_continuation
271-
let bL = s:iscontOne(l:lnum,num,isOp)
272-
let bL -= (bL && l:line =~ '^{') * s:W
273-
if isOp && (!num || cursor(b:js_cache[1],b:js_cache[2]) || s:IsBlock())
270+
" main return
271+
if isOp
274272
return (num ? indent(num) : -s:W) + (s:W * 2) + switch_offset + bL
275273
elseif num
276274
return indent(num) + s:W + switch_offset + bL
277275
endif
278276
return bL
277+
279278
finally
280279
let &magic = save_magic
281280
endtry
282281
endfunction
283282

284-
285283
let &cpo = s:cpo_save
286284
unlet s:cpo_save

0 commit comments

Comments
 (0)