22" Language: Javascript
33" Maintainer: vim-javascript community
44" URL: https://github.com/pangloss/vim-javascript
5- " Last Change: August 20 , 2016
5+ " Last Change: September 4 , 2016
66
77" Only load this indent file when no other was loaded.
88if exists (' b:did_indent' )
3838endif
3939
4040let s: line_pre = ' ^\s*\%(\%(\%(\/\*.\{-}\)\=\*\+\/\s*\)\=\)\@>'
41- let s: expr_case = s: line_pre . ' \%(\%(case\>.\+\)\|default\)\s*:'
41+ let s: expr_case = s: line_pre . ' \%(\%(case\>.\+\)\|default\)\s*:\C '
4242" Regex of syntax group names that are or delimit string or are comments.
4343let s: syng_strcom = ' \%(s\%(tring\|pecial\)\|comment\|regex\|doc\|template\)'
4444
@@ -47,13 +47,20 @@ let s:syng_comment = '\%(comment\|doc\)'
4747
4848" Expression used to check whether we should skip a match with searchpair().
4949let s: skip_expr = " synIDattr(synID(line('.'),col('.'),0),'name') =~? '" .s: syng_strcom ." '"
50+ function s: skip_func (lnum)
51+ if ! s: free || getline (line (' .' )) = ~ ' ['' /"\\]' || search (' `' ,' nW' ,a: lnum ) || search (' \*\/' ,' nW' ,a: lnum )
52+ let s: free = ! eval (s: skip_expr )
53+ endif
54+ let s: looksyn = s: free ? line (' .' ) : s: looksyn
55+ return ! s: free
56+ endfunction
5057
5158if has (' reltime' )
52- function s: GetPair (start ,end ,flags,time)
53- return searchpair (a: start ,' ' ,a: end ,a: flags ,s: skip_expr ,max ([prevnonblank (v: lnum ) - 2000 ,0 ]),a: time )
59+ function s: GetPair (start ,end ,flags,skip , time)
60+ return searchpair (a: start ,' ' ,a: end ,a: flags ,a: skip ,max ([prevnonblank (v: lnum ) - 2000 ,0 ]),a: time )
5461 endfunction
5562else
56- function s: GetPair (start ,end ,flags,n )
63+ function s: GetPair (start ,end ,flags,... )
5764 return searchpair (a: start ,' ' ,a: end ,a: flags ,0 ,max ([prevnonblank (v: lnum ) - 2000 ,0 ]))
5865 endfunction
5966endif
@@ -62,29 +69,28 @@ let s:line_term = '\s*\%(\%(\/\%(\%(\*.\{-}\*\/\)\|\%(\*\+\)\)\)\s*\)\=$'
6269
6370" configurable regexes that define continuation lines, not including (, {, or [.
6471if ! exists (' g:javascript_opfirst' )
65- let g: javascript_opfirst = ' \%([<>,: ?^%|*&]\|\([-/. +]\)\1\@!\|=>\@!\|in\%(stanceof\)\=\>\)'
72+ let g: javascript_opfirst = ' \%([<>,?^%|*&]\|\/[^/*]\|\ ([-.: +]\)\1\@!\|=>\@!\|in\%(stanceof\)\=\>\)'
6673endif
6774if ! exists (' g:javascript_continuation' )
68- let g: javascript_continuation = ' \%([<=,.?/*: ^%|&]\|+\@<!+\|-\@<!-\|=\@<!>\|\<in\%(stanceof\)\=\)'
75+ let g: javascript_continuation = ' \%([<=,.?/*^%|&: ]\|+\@<!+\|-\@<!-\|=\@<!>\|\<in\%(stanceof\)\=\)'
6976endif
7077
7178let g: javascript_opfirst = s: line_pre . g: javascript_opfirst
7279let g: javascript_continuation .= s: line_term
7380
74- function s: OneScope (lnum,text, add )
81+ function s: OneScope (lnum,text)
7582 return a: text = ~# ' \%(\<else\|\<do\|=>\)' . s: line_term ? ' no b' :
76- \ ((a: add && a: text = ~ s: line_pre . ' $' && search (' \%' . s: PrevCodeLine (a: lnum - 1 ) . ' l.)' . s: line_term )) ||
77- \ cursor (a: lnum , match (a: text , ' )' . s: line_term )) > -1 ) &&
78- \ s: GetPair (' (' , ' )' , ' cbW' , 100 ) > 0 && search (' \C\l\+\_s*\%#' ,' bW' ) &&
79- \ (a: add || ((expand (' <cword>' ) !=# ' while' || ! s: GetPair (' \C\<do\>' , ' \C\<while\>' ,' nbW' ,100 )) &&
80- \ expand (' cword' ) !=# ' each' || search (' \C\<for\_s\+\%#' ,' nbW' ))) ? expand (' <cword>' ) : ' '
83+ \ cursor (a: lnum , match (' ' . a: text , ' )' . s: line_term )) > -1 &&
84+ \ s: GetPair (' (' , ' )' , ' bW' , s: skip_expr , 100 ) > 0 && search (' \C\l\+\_s*\%#' ,' bW' ) &&
85+ \ (expand (' <cword>' ) !=# ' while' || s: GetPair (' \C\<do\>' , ' \C\<while\>' ,' nbW' ,s: skip_expr ,100 ) <= 0 ) &&
86+ \ (expand (' <cword>' ) !=# ' each' || search (' \C\<for\_s\+\%#' ,' nbW' )) ? expand (' <cword>' ) : ' '
8187endfunction
8288
8389" https://github.com/sweet-js/sweet.js/wiki/design#give-lookbehind-to-the-reader
8490function s: IsBlock ()
8591 return getline (line (' .' ))[col (' .' )-1 ] == ' {' && ! search (
86- \ ' \C\%(\<return\s*\|\%([-=~!<*+,.?^%|&\[(]\|=\@<!>\|\*\@<!\/\|\<\%(var\|const\|let\|yield\|delete\|void\|t\%(ypeof\|hrow\)\|new\|\< in\%(stanceof\)\=\)\)\_s*\)\%#' ,' bnW' ) &&
87- \ (! search (' : \_s*\%#' ,' bW ' ) || ( ! s: GetPair (' [({[] ' ,' [])}] ' , ' bW' , 200 ) || s: IsBlock () ))
92+ \ ' \C\%(\<return\s*\|\%([-=~!<*+,.?^%|&\[(]\|=\@<!>\|\*\@<!\/\|\<\%(var\|const\|let\|import\|export\%(\_s\+default\)\=\| yield\|delete\|void\|t\%(ypeof\|hrow\)\|new\|in\%(stanceof\)\=\)\)\_s*\)\%#' ,' bnW' ) &&
93+ \ (search (s: expr_case . ' \_s*\%#' ,' nbW ' ) || ! search (' [{:]\_s*\%# ' ,' bW' ) || s: IsBlock ())
8894endfunction
8995
9096" Auxiliary Functions {{{2
@@ -109,9 +115,12 @@ function s:Balanced(lnum)
109115 if synIDattr (synID (a: lnum ,pos + 1 ,0 ),' name' ) !~? s: syng_strcom
110116 let idx = stridx (' (){}[]' , l: line [pos])
111117 if idx % 2 == 0
112- let open_{idx} = open_{idx} + 1
118+ let open_{idx} += 1
113119 else
114- let open_{idx - 1 } = open_{idx - 1 } - 1
120+ let open_{idx - 1 } -= 1
121+ if open_{idx - 1 } < 0
122+ return 0
123+ endif
115124 endif
116125 endif
117126 let pos = match (l: line , ' [][(){}]' , pos + 1 )
@@ -129,7 +138,7 @@ function GetJavascriptIndent()
129138 let syns = synIDattr (synID (v: lnum , 1 , 0 ), ' name' )
130139
131140 " start with strings,comments,etc.{{{2
132- if (l: line !~ ' ^['' "` ]' && syns = ~? ' \%(string\|template\)' ) ||
141+ if (l: line !~ ' ^['' "]' && syns = ~? ' \%(string\|template\)' ) ||
133142 \ (l: line !~ ' ^\s*[/*]' && syns = ~? s: syng_comment )
134143 return -1
135144 endif
@@ -152,36 +161,37 @@ function GetJavascriptIndent()
152161
153162 " the containing paren, bracket, curly. Memoize, last lineNr either has the
154163 " same scope or starts a new one, unless if it closed a scope.
164+ let [s: looksyn ,s: free ] = [v: lnum - 1 ,1 ]
155165 call cursor (v: lnum ,1 )
156- if b: js_cache [0 ] >= l : lnum && b: js_cache [0 ] < v : lnum && b: js_cache [ 0 ] &&
166+ if b: js_cache [0 ] < v : lnum && b: js_cache [0 ] >= l : lnum &&
157167 \ (b: js_cache [0 ] > l: lnum || s: Balanced (l: lnum ) > 0 )
158168 let num = b: js_cache [1 ]
159169 elseif syns != ' ' && l: line [0 ] = ~ ' \s'
160170 let pattern = syns = ~? ' block' ? [' {' ,' }' ] : syns = ~? ' jsparen' ? [' (' ,' )' ] :
161171 \ syns = ~? ' jsbracket' ? [' \[' ,' \]' ] : [' [({[]' ,' [])}]' ]
162- let num = s: GetPair (pattern[0 ],pattern[1 ],' bW' ,2000 )
172+ let num = s: GetPair (pattern[0 ],pattern[1 ],' bW' ,' s:skip_func(s:looksyn) ' , 2000 )
163173 else
164- let num = s: GetPair (' [({[]' ,' [])}]' ,' bW' ,2000 )
174+ let num = s: GetPair (' [({[]' ,' [])}]' ,' bW' ,' s:skip_func(s:looksyn) ' , 2000 )
165175 endif
176+
166177 let b: js_cache = [v: lnum ,num,line (' .' ) == v: lnum ? b: js_cache [2 ] : col (' .' )]
167178
168179 if l: line = ~ s: line_pre . ' [])}]'
169180 return indent (num)
170181 endif
171182
183+ let pline = substitute (substitute (getline (l: lnum ),s: expr_case ,' \=repeat(" ",strlen(submatch(0)))' ,' ' ), ' \%(:\@<!\/\/.*\)$' , ' ' ,' ' )
172184 call cursor (b: js_cache [1 ],b: js_cache [2 ])
173-
174- let swcase = getline (l: lnum ) = ~# s: expr_case
175- let pline = swcase ? getline (l: lnum ) : substitute (getline (l: lnum ), ' \%(:\@<!\/\/.*\)$' , ' ' ,' ' )
176- let inb = num == 0 || num < l: lnum && ((l: line !~ s: line_pre . ' ,' && pline !~ ' ,' . s: line_term ) || s: IsBlock ())
177- let switch_offset = num == 0 || s: OneScope (num, strpart (getline (num),0 ,b: js_cache [2 ] - 1 ),1 ) !=# ' switch' ? 0 :
178- \ &cino !~ ' :' || ! has (' float' ) ? s: sw () :
185+ let switch_offset = num <= 0 || ! (search (' )\_s*\%#' ,' bW' ) &&
186+ \ s: GetPair (' (' , ' )' , ' bW' , s: skip_expr , 100 ) > 0 && search (' \C\<switch\_s*\%#' ,' bW' )) ? 0 :
187+ \ &cino !~ ' :' || ! has (' float' ) ? s: sw () :
179188 \ float2nr (str2float (matchstr (&cino ,' .*:\zs[-0-9.]*' )) * (&cino = ~# ' .*:[^,]*s' ? s: sw () : 1 ))
180189
181190 " most significant, find the indent amount
182- if inb && ! swcase && ((l: line = ~# g: javascript_opfirst || pline = ~# g: javascript_continuation ) ||
183- \ num < l: lnum && s: OneScope (l: lnum ,pline,0 ) = ~# ' \<\%(for\|each\|if\|let\|no\sb\|w\%(hile\|ith\)\)\>' &&
184- \ l: line !~ s: line_pre . ' {' )
191+ let isOp = l: line = ~# g: javascript_opfirst || pline = ~# g: javascript_continuation
192+ if isOp && (num <= 0 || cursor (b: js_cache [1 ],b: js_cache [2 ]) || s: IsBlock ()) ||
193+ \ s: OneScope (l: lnum ,pline) = ~# ' \<\%(for\|each\|if\|let\|no\sb\|w\%(hile\|ith\)\)\>' &&
194+ \ l: line !~ s: line_pre . ' {'
185195 return (num > 0 ? indent (num) : - s: sw ()) + (s: sw () * 2 ) + switch_offset
186196 elseif num > 0
187197 return indent (num) + s: sw () + switch_offset
0 commit comments