2
2
" Language: Javascript
3
3
" Maintainer: Chris Paul ( https://github.com/bounceme )
4
4
" URL: https://github.com/pangloss/vim-javascript
5
- " Last Change: October 24 , 2016
5
+ " Last Change: November 6 , 2016
6
6
7
7
" Only load this indent file when no other was loaded.
8
8
if exists (' b:did_indent' )
37
37
endfunction
38
38
endif
39
39
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'
43
41
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'
44
44
" Expression used to check whether we should skip a match with searchpair().
45
45
let s: skip_expr = " synIDattr(synID(line('.'),col('.'),0),'name') =~? '" .s: syng_strcom ." '"
46
46
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' " )
49
49
let s: looksyn = s: free ? line (' .' ) : s: looksyn
50
50
return ! s: free
51
51
endif
52
52
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' " )
54
54
endfunction
55
55
56
56
if has (' reltime' )
63
63
endfunction
64
64
endif
65
65
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
+
66
79
function s: Trim (ln )
67
80
let pline = substitute (getline (a: ln ),' \s*$' ,' ' ,' ' )
68
81
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'
70
83
let pline = substitute (strpart (pline, 0 , l: max ),' \s*$' ,' ' ,' ' )
71
84
let l: max = max ([strridx (pline,' //' ),strridx (pline,' /*' ),0 ])
72
85
endwhile
@@ -75,15 +88,20 @@ endfunction
75
88
76
89
" configurable regexes that define continuation lines, not including (, {, or [.
77
90
let s: opfirst = ' ^' . get (g: ,' javascript_opfirst' ,
78
- \ ' \%([<>,?^%|*&]\|\/[/*]\@! \|\([-.:+]\)\1\@!\|=>\@!\|in\%(stanceof\)\=\>\)' )
91
+ \ ' \%([<>,?^%|*/&] \|\([-.:+]\)\1\@!\|=>\@!\|in\%(stanceof\)\=\>\)' )
79
92
let s: continuation = get (g: ,' javascript_continuation' ,
80
93
\ ' \%([<=,.?/*^%|&:]\|+\@<!+\|-\@<!-\|=\@<!>\|\<in\%(stanceof\)\=\)' ) . ' $'
81
94
82
95
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
87
105
endfunction
88
106
89
107
function s: iscontOne (i ,num,cont)
@@ -94,66 +112,49 @@ function s:iscontOne(i,num,cont)
94
112
while l: i >= l: num && (! l: cont || ind > pind)
95
113
if indent (l: i ) < ind " first line always true for !a:cont, false for !!a:cont
96
114
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
103
115
let bL += s: W
104
116
let [l: cont , l: i ] = [0 , line (' .' )]
105
117
elseif ! l: cont
106
118
break
107
119
endif
108
- let ind = indent (l: i )
109
120
elseif ! a: cont
110
121
break
111
122
endif
123
+ let ind = min ([ind, indent (l: i )])
112
124
let l: i = s: PrevCodeLine (l: i - 1 )
113
125
endwhile
114
126
return bL
115
127
endfunction
116
128
117
129
" 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 ' '
148
135
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 () !~ ' [,{]' )
149
145
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 ))
150
148
endfunction
151
149
152
150
" Find line above 'lnum' that isn't empty, in a comment, or in a string.
153
151
function s: PrevCodeLine (lnum)
154
152
let l: lnum = prevnonblank (a: lnum )
155
153
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
157
158
return l: lnum
158
159
endif
159
160
let l: lnum = prevnonblank (l: lnum - 1 )
@@ -167,13 +168,9 @@ function s:Balanced(lnum)
167
168
let pos = match (l: line , ' [][(){}]' , 0 )
168
169
while pos != -1
169
170
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
177
174
endif
178
175
endif
179
176
let pos = match (l: line , ' [][(){}]' , pos + 1 )
@@ -182,30 +179,27 @@ function s:Balanced(lnum)
182
179
endfunction
183
180
184
181
function GetJavascriptIndent ()
185
- try
186
- let save_magic = &magic
187
- set magic
188
182
let b: js_cache = get (b: ,' js_cache' ,[0 ,0 ,0 ])
189
183
" Get the current line.
190
184
let l: line = getline (v: lnum )
191
185
let syns = synIDattr (synID (v: lnum , 1 , 0 ), ' name' )
192
186
193
187
" start with strings,comments,etc.
194
- if syns = ~? ' \%( comment\|doc\) '
188
+ if syns = ~? ' comment\|doc'
195
189
if l: line = ~ ' ^\s*\*'
196
190
return cindent (v: lnum )
197
191
elseif l: line !~ ' ^\s*\/'
198
192
return -1
199
193
endif
200
- elseif syns = ~? ' \%( string\|template\) ' && l: line !~ ' ^['' "]'
194
+ elseif syns = ~? ' string\|template' && l: line !~ ' ^['' "]'
201
195
return -1
202
196
endif
203
197
let l: lnum = s: PrevCodeLine (v: lnum - 1 )
204
198
if ! l: lnum
205
- return 0
199
+ return
206
200
endif
207
201
208
- let l: line = substitute (l: line ,' ^\s*\%(\/\*.\{-}\*\/\s*\)*' ,' ' ,' ' )
202
+ let l: line = substitute (substitute ( l: line ,' ^\s*\%(\/\*.\{-}\*\/\s*\)* ' , ' ' , ' ' ), ' ^\/[/*]. *' ,' ' ,' ' )
209
203
210
204
" the containing paren, bracket, curly. Many hacks for performance
211
205
call cursor (v: lnum ,1 )
@@ -227,7 +221,7 @@ function GetJavascriptIndent()
227
221
endif
228
222
229
223
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 () == ' )'
231
225
call s: GetPair (' (' ,' )' ,' bW' ,s: skip_expr ,200 )
232
226
endif
233
227
return indent (line (' .' ))
@@ -237,31 +231,19 @@ function GetJavascriptIndent()
237
231
let num = b: js_cache [1 ]
238
232
239
233
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
254
241
endif
242
+ let stmt = pline !~# s: case_stmt . ' $'
255
243
endif
256
- else
257
- let stmt = 1
258
244
endif
259
245
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
265
247
let isOp = l: line = ~# s: opfirst || pline = ~# s: continuation
266
248
let bL = s: iscontOne (l: lnum ,num,isOp)
267
249
let bL -= (bL && l: line [0 ] == ' {' ) * s: W
@@ -274,10 +256,6 @@ function GetJavascriptIndent()
274
256
return indent (num) + s: W + switch_offset + bL
275
257
endif
276
258
return bL
277
-
278
- finally
279
- let &magic = save_magic
280
- endtry
281
259
endfunction
282
260
283
261
let &cpo = s: cpo_save
0 commit comments