Skip to content

Commit 3abb9ae

Browse files
authored
Merge pull request #696 from pangloss/develop
Develop -> Master
2 parents 997c2b1 + 419f0d6 commit 3abb9ae

File tree

2 files changed

+70
-92
lines changed

2 files changed

+70
-92
lines changed

indent/javascript.vim

+69-91
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 24, 2016
5+
" Last Change: November 6, 2016
66

77
" Only load this indent file when no other was loaded.
88
if exists('b:did_indent')
@@ -37,20 +37,20 @@ else
3737
endfunction
3838
endif
3939

40-
let s:expr_case = '\<\%(\%(case\>\s*\S.\{-}\)\|default\)\s*:\C'
41-
" Regex of syntax group names that are or delimit string or are comments.
42-
let s:syng_strcom = '\%(s\%(tring\|pecial\)\|comment\|regex\|doc\|template\)'
40+
let s:case_stmt = '\<\%(case\>\s*[^ \t:].*\|default\s*\):\C'
4341

42+
" Regex of syntax group names that are or delimit string or are comments.
43+
let s:syng_strcom = 'string\|comment\|regex\|special\|doc\|template'
4444
" Expression used to check whether we should skip a match with searchpair().
4545
let s:skip_expr = "synIDattr(synID(line('.'),col('.'),0),'name') =~? '".s:syng_strcom."'"
4646
function s:skip_func(lnum)
47-
if !s:free || search('`','nW',a:lnum) || search('\*\/','nW',a:lnum)
48-
let s:free = !eval(s:skip_expr)
47+
if !s:free || search('`\|\*\/','nW',a:lnum)
48+
let s:free = !eval(s:skip_expr . " . '\\|html'")
4949
let s:looksyn = s:free ? line('.') : s:looksyn
5050
return !s:free
5151
endif
5252
let s:looksyn = line('.')
53-
return (strridx(getline('.'),'/',col('.')-1) + 1 || search('[''"\\]','nW',s:looksyn)) && eval(s:skip_expr)
53+
return (search('\/','nbW',s:looksyn) || search('[''"\\]','nW',s:looksyn)) && eval(s:skip_expr . " . '\\|html'")
5454
endfunction
5555

5656
if has('reltime')
@@ -63,10 +63,23 @@ else
6363
endfunction
6464
endif
6565

66+
function s:current_char()
67+
return getline('.')[col('.')-1]
68+
endfunction
69+
70+
function s:token()
71+
return s:current_char() =~ '\k' ? expand('<cword>') : s:current_char()
72+
endfunction
73+
74+
" NOTE: moves the cursor
75+
function s:previous_token()
76+
return search('\<\|[][`^!"%-/:-?{-~]','bW') ? s:token() : ''
77+
endfunction
78+
6679
function s:Trim(ln)
6780
let pline = substitute(getline(a:ln),'\s*$','','')
6881
let l:max = max([strridx(pline,'//'),strridx(pline,'/*'),0])
69-
while l:max && synIDattr(synID(a:ln, strlen(pline), 0), 'name') =~? '\%(comment\|doc\)'
82+
while l:max && synIDattr(synID(a:ln, strlen(pline), 0), 'name') =~? 'comment\|doc'
7083
let pline = substitute(strpart(pline, 0, l:max),'\s*$','','')
7184
let l:max = max([strridx(pline,'//'),strridx(pline,'/*'),0])
7285
endwhile
@@ -75,15 +88,20 @@ endfunction
7588

7689
" configurable regexes that define continuation lines, not including (, {, or [.
7790
let s:opfirst = '^' . get(g:,'javascript_opfirst',
78-
\ '\%([<>,?^%|*&]\|\/[/*]\@!\|\([-.:+]\)\1\@!\|=>\@!\|in\%(stanceof\)\=\>\)')
91+
\ '\%([<>,?^%|*/&]\|\([-.:+]\)\1\@!\|=>\@!\|in\%(stanceof\)\=\>\)')
7992
let s:continuation = get(g:,'javascript_continuation',
8093
\ '\%([<=,.?/*^%|&:]\|+\@<!+\|-\@<!-\|=\@<!>\|\<in\%(stanceof\)\=\)') . '$'
8194

8295
function s:OneScope(lnum,text)
83-
return cursor(a:lnum, match(' ' . a:text, '\%(\<else\|\<do\|=>\)$')) + 1 ||
84-
\ cursor(a:lnum, match(' ' . a:text, ')$')) + 1 &&
85-
\ s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0 &&
86-
\ search('\C\<\%(for\%(\_s\+\%(await\|each\)\)\=\|if\|let\|w\%(hile\|ith\)\)\_s*\%#','bW')
96+
if cursor(a:lnum, match(' ' . a:text, ')$')) + 1 &&
97+
\ s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0
98+
let token = s:previous_token()
99+
if index(split('await each'),token) + 1
100+
return s:previous_token() ==# 'for'
101+
endif
102+
return index(split('for if let while with'),token) + 1
103+
endif
104+
return cursor(a:lnum, match(' ' . a:text, '\%(\<else\|\<do\|=>\)$\C')) + 1
87105
endfunction
88106

89107
function s:iscontOne(i,num,cont)
@@ -94,66 +112,49 @@ function s:iscontOne(i,num,cont)
94112
while l:i >= l:num && (!l:cont || ind > pind)
95113
if indent(l:i) < ind " first line always true for !a:cont, false for !!a:cont
96114
if s:OneScope(l:i,s:Trim(l:i))
97-
if expand('<cword>') ==# 'while' &&
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
101-
return 0
102-
endif
103115
let bL += s:W
104116
let [l:cont, l:i] = [0, line('.')]
105117
elseif !l:cont
106118
break
107119
endif
108-
let ind = indent(l:i)
109120
elseif !a:cont
110121
break
111122
endif
123+
let ind = min([ind, indent(l:i)])
112124
let l:i = s:PrevCodeLine(l:i - 1)
113125
endwhile
114126
return bL
115127
endfunction
116128

117129
" https://github.com/sweet-js/sweet.js/wiki/design#give-lookbehind-to-the-reader
118-
function s:IsBlock()
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')
131-
endif
132-
if syn =~? '\%(xml\|jsx\)'
133-
return char != '{'
134-
elseif char =~# '\l'
135-
if line('.') == l:ln && expand('<cword>') ==# 'return'
136-
return 0
137-
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 . '$'
144-
else
145-
return stridx('-=~!<*+,/?^%|&([',char) < 0
146-
endif
147-
else
130+
function s:IsBlock(...)
131+
let l:ln = get(a:000,0,line('.'))
132+
let char = s:previous_token()
133+
let syn = char =~ '[{>/]' || l:ln != line('.') ? synIDattr(synID(line('.'),col('.')-(char == '{'),0),'name') : ''
134+
if char is ''
148135
return 1
136+
elseif syn =~? 'xml\|jsx'
137+
return char != '{'
138+
elseif syn =~? 'comment'
139+
return search('\/[/*]','bW') && s:IsBlock(l:ln)
140+
elseif char == '>'
141+
return getline('.')[col('.')-2] == '=' || syn =~? '^jsflow'
142+
elseif char == ':'
143+
return cursor(0,match(' ' . strpart(getline('.'),0,col('.')),'.*\zs' . s:case_stmt . '$')) + 1 &&
144+
\ (expand('<cword>') !=# 'default' || s:previous_token() !~ '[,{]')
149145
endif
146+
return index(split('return const let import export yield default delete var void typeof throw new in instanceof'
147+
\ . ' - = ~ ! < * + , / ? ^ % | & ( ['), char) < (0 + (line('.') != l:ln))
150148
endfunction
151149

152150
" Find line above 'lnum' that isn't empty, in a comment, or in a string.
153151
function s:PrevCodeLine(lnum)
154152
let l:lnum = prevnonblank(a:lnum)
155153
while l:lnum
156-
if synIDattr(synID(l:lnum,matchend(getline(l:lnum), '^\s*[^''"`]'),0),'name') !~? s:syng_strcom
154+
let syn = synIDattr(synID(l:lnum,matchend(getline(l:lnum), '^\s*[^''"`]'),0),'name')
155+
if syn =~? 'html'
156+
return
157+
elseif syn !~? s:syng_strcom
157158
return l:lnum
158159
endif
159160
let l:lnum = prevnonblank(l:lnum - 1)
@@ -167,13 +168,9 @@ function s:Balanced(lnum)
167168
let pos = match(l:line, '[][(){}]', 0)
168169
while pos != -1
169170
if synIDattr(synID(a:lnum,pos + 1,0),'name') !~? s:syng_strcom
170-
if stridx('[({',l:line[pos]) + 1
171-
let l:open += 1
172-
else
173-
let l:open -= 1
174-
if l:open < 0
175-
return 0
176-
endif
171+
let l:open += match(' ' . l:line[pos],'[[({]')
172+
if l:open < 0
173+
return
177174
endif
178175
endif
179176
let pos = match(l:line, '[][(){}]', pos + 1)
@@ -182,30 +179,27 @@ function s:Balanced(lnum)
182179
endfunction
183180

184181
function GetJavascriptIndent()
185-
try
186-
let save_magic = &magic
187-
set magic
188182
let b:js_cache = get(b:,'js_cache',[0,0,0])
189183
" Get the current line.
190184
let l:line = getline(v:lnum)
191185
let syns = synIDattr(synID(v:lnum, 1, 0), 'name')
192186

193187
" start with strings,comments,etc.
194-
if syns =~? '\%(comment\|doc\)'
188+
if syns =~? 'comment\|doc'
195189
if l:line =~ '^\s*\*'
196190
return cindent(v:lnum)
197191
elseif l:line !~ '^\s*\/'
198192
return -1
199193
endif
200-
elseif syns =~? '\%(string\|template\)' && l:line !~ '^[''"]'
194+
elseif syns =~? 'string\|template' && l:line !~ '^[''"]'
201195
return -1
202196
endif
203197
let l:lnum = s:PrevCodeLine(v:lnum - 1)
204198
if !l:lnum
205-
return 0
199+
return
206200
endif
207201

208-
let l:line = substitute(l:line,'^\s*\%(\/\*.\{-}\*\/\s*\)*','','')
202+
let l:line = substitute(substitute(l:line,'^\s*\%(\/\*.\{-}\*\/\s*\)*','',''),'^\/[/*].*','','')
209203

210204
" the containing paren, bracket, curly. Many hacks for performance
211205
call cursor(v:lnum,1)
@@ -227,7 +221,7 @@ function GetJavascriptIndent()
227221
endif
228222

229223
if idx + 1
230-
if idx == 2 && search('\S','bW',line('.')) && getline('.')[col('.')-1] == ')'
224+
if idx == 2 && search('\S','bW',line('.')) && s:current_char() == ')'
231225
call s:GetPair('(',')','bW',s:skip_expr,200)
232226
endif
233227
return indent(line('.'))
@@ -237,31 +231,19 @@ function GetJavascriptIndent()
237231
let num = b:js_cache[1]
238232

239233
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
234+
if num && s:current_char() == '{' && s:IsBlock()
235+
let stmt = 1
236+
if s:current_char() == ')' && s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0 && s:previous_token() ==# 'switch'
237+
let switch_offset = &cino !~ ':' || !has('float') ? s:W :
238+
\ float2nr(str2float(matchstr(&cino,'.*:\zs[-0-9.]*')) * (&cino =~# '.*:[^,]*s' ? s:W : 1))
239+
if l:line =~# '^' . s:case_stmt
240+
return indent(num) + switch_offset
254241
endif
242+
let stmt = pline !~# s:case_stmt . '$'
255243
endif
256-
else
257-
let stmt = 1
258244
endif
259245

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
246+
if stmt || !num
265247
let isOp = l:line =~# s:opfirst || pline =~# s:continuation
266248
let bL = s:iscontOne(l:lnum,num,isOp)
267249
let bL -= (bL && l:line[0] == '{') * s:W
@@ -274,10 +256,6 @@ function GetJavascriptIndent()
274256
return indent(num) + s:W + switch_offset + bL
275257
endif
276258
return bL
277-
278-
finally
279-
let &magic = save_magic
280-
endtry
281259
endfunction
282260

283261
let &cpo = s:cpo_save

syntax/javascript.vim

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ syntax keyword jsAsyncKeyword async await
112112
syntax match jsSwitchColon contained /:/ skipwhite skipempty nextgroup=jsSwitchBlock
113113

114114
" Keywords
115-
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
115+
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
116116
syntax keyword jsGlobalNodeObjects module exports global process
117117
syntax match jsGlobalNodeObjects /require/ containedin=jsFuncCall
118118
syntax keyword jsExceptions Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError

0 commit comments

Comments
 (0)