diff options
author | Adam Stankiewicz <sheerun@sher.pl> | 2016-05-03 12:56:11 +0200 |
---|---|---|
committer | Adam Stankiewicz <sheerun@sher.pl> | 2016-05-03 12:56:11 +0200 |
commit | 8cd62b9eab04cd80998a810c103b80d49fc64a89 (patch) | |
tree | 231115681ec694907a923745892508358ff529be /indent/javascript.vim | |
parent | 93e3f020a9637b3df9109348cef5fcc3e0bbda43 (diff) | |
download | vim-polyglot-8cd62b9eab04cd80998a810c103b80d49fc64a89.tar.gz vim-polyglot-8cd62b9eab04cd80998a810c103b80d49fc64a89.zip |
Change javascript provider to pangloss/vim-javascript, closes #80v2.9.0
Diffstat (limited to 'indent/javascript.vim')
-rw-r--r-- | indent/javascript.vim | 182 |
1 files changed, 146 insertions, 36 deletions
diff --git a/indent/javascript.vim b/indent/javascript.vim index dedc41fa..90e84cb5 100644 --- a/indent/javascript.vim +++ b/indent/javascript.vim @@ -18,7 +18,7 @@ setlocal nosmartindent " Now, set up our indentation expression and keys that trigger it. setlocal indentexpr=GetJavascriptIndent() setlocal formatexpr=Fixedgq(v:lnum,v:count) -setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e +setlocal indentkeys=0{,0},0),0],0\,:,!^F,o,O,e " Only define the function once. if exists("*GetJavascriptIndent") @@ -28,13 +28,27 @@ endif let s:cpo_save = &cpo set cpo&vim +" Get shiftwidth value +if exists('*shiftwidth') + func s:sw() + return shiftwidth() + endfunc +else + func s:sw() + return &sw + endfunc +endif + " 1. Variables {{{1 " ============ -let s:js_keywords = '^\s*\(break\|case\|catch\|continue\|debugger\|default\|delete\|do\|else\|finally\|for\|function\|if\|in\|instanceof\|new\|return\|switch\|this\|throw\|try\|typeof\|var\|void\|while\|with\)' - +let s:js_keywords = '^\s*\(break\|catch\|const\|continue\|debugger\|delete\|do\|else\|finally\|for\|function\|if\|in\|instanceof\|let\|new\|return\|switch\|this\|throw\|try\|typeof\|var\|void\|while\|with\)' +let s:expr_case = '^\s*\(case\s\+[^\:]*\|default\)\s*:\s*' " Regex of syntax group names that are or delimit string or are comments. -let s:syng_strcom = 'string\|regex\|comment\c' +let s:syng_strcom = '\%(\%(template\)\@<!string\|regex\|comment\)\c' + +" Regex of syntax group names that are or delimit template strings +let s:syng_template = 'template\c' " Regex of syntax group names that are strings. let s:syng_string = 'regex\c' @@ -51,25 +65,34 @@ let s:skip_expr = "synIDattr(synID(line('.'),col('.'),1),'name') =~ '".s:syng_st let s:line_term = '\s*\%(\%(\/\/\).*\)\=$' " Regex that defines continuation lines, not including (, {, or [. -let s:continuation_regex = '\%([\\*+/.:]\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\|[^=]=[^=].*,\)' . s:line_term +let s:continuation_regex = '\%([\\*/.:]\|+\@<!+\|-\@<!-\|\%(<%\)\@<!=\|\W[|&?]\|||\|&&\|[^=]=[^=>].*,\)' . s:line_term " Regex that defines continuation lines. " TODO: this needs to deal with if ...: and so on -let s:msl_regex = s:continuation_regex +let s:msl_regex = s:continuation_regex.'\|'.s:expr_case -let s:one_line_scope_regex = '\<\%(if\|else\|for\|while\)\>[^{;]*' . s:line_term +let s:one_line_scope_regex = '\%(\%(\<else\>\|\<\%(if\|for\|while\)\>\s*(\%([^()]*\|[^()]*(\%([^()]*\|[^()]*(\%([^()]*\|[^()]*([^()]*)[^()]*\))[^()]*\))[^()]*\))\)\|=>\)' . s:line_term " Regex that defines blocks. -let s:block_regex = '\%([{[]\)\s*\%(|\%([*@]\=\h\w*,\=\s*\)\%(,\s*[*@]\=\h\w*\)*|\)\=' . s:line_term +let s:block_regex = '\%([{([]\)\s*\%(|\%([*@]\=\h\w*,\=\s*\)\%(,\s*[*@]\=\h\w*\)*|\)\=' . s:line_term + +let s:operator_first = '^\s*\%([*/.:?]\|\([-+]\)\1\@!\|||\|&&\)' -let s:var_stmt = '^\s*var' +let s:var_stmt = '^\s*\%(const\|let\|var\)' let s:comma_first = '^\s*,' let s:comma_last = ',\s*$' -let s:ternary = '^\s\+[?|:]' -let s:ternary_q = '^\s\+?' - +let s:case_indent = s:sw() +let s:case_indent_after = s:sw() +let s:m = matchlist(&cinoptions, ':\(.\)') +if (len(s:m) > 2) + let s:case_indent = s:m[1] +endif +let s:m = matchlist(&cinoptions, '=\(.\)') +if (len(s:m) > 2) + let s:case_indent_after = s:m[1] +endif " 2. Auxiliary Functions {{{1 " ====================== @@ -83,6 +106,11 @@ function s:IsInString(lnum, col) return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_string endfunction +" Check if the character at lnum:col is inside a template string. +function s:IsInTempl(lnum, col) + return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_template +endfunction + " Check if the character at lnum:col is inside a multi-line comment. function s:IsInMultilineComment(lnum, col) return !s:IsLineComment(a:lnum, a:col) && synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_multiline @@ -101,13 +129,13 @@ function s:PrevNonBlankNonString(lnum) " Go in and out of blocks comments as necessary. " If the line isn't empty (with opt. comment) or in a string, end search. let line = getline(lnum) - if line =~ '/\*' + if s:IsInMultilineComment(lnum, matchend(line, '/\*') - 1) if in_block let in_block = 0 else break endif - elseif !in_block && line =~ '\*/' + elseif !in_block && s:IsInMultilineComment(lnum, matchend(line, '\*/') - 1) let in_block = 1 elseif !in_block && line !~ '^\s*\%(//\).*$' && !(s:IsInStringOrComment(lnum, 1) && s:IsInStringOrComment(lnum, strlen(line))) break @@ -127,9 +155,21 @@ function s:GetMSL(lnum, in_one_line_scope) " Otherwise, terminate search as we have found our MSL already. let line = getline(lnum) let col = match(line, s:msl_regex) + 1 + let line2 = getline(msl) + let col2 = matchend(line2, ')') if (col > 0 && !s:IsInStringOrComment(lnum, col)) || s:IsInString(lnum, strlen(line)) let msl = lnum + + " if there are more closing brackets, continue from the line which has the matching opening bracket + elseif col2 > 0 && !s:IsInStringOrComment(msl, col2) && s:LineHasOpeningBrackets(msl)[0] == '2' && !a:in_one_line_scope + call cursor(msl, 1) + if searchpair('(', '', ')', 'bW', s:skip_expr) > 0 + let lnum = line('.') + let msl = lnum + endif + else + " Don't use lines that are part of a one line scope as msl unless the " flag in_one_line_scope is set to 1 " @@ -140,7 +180,7 @@ function s:GetMSL(lnum, in_one_line_scope) if msl_one_line == 0 break endif - endif + end let lnum = s:PrevNonBlankNonString(lnum - 1) endwhile return msl @@ -193,9 +233,9 @@ function s:GetVarIndent(lnum) " if the previous line doesn't end in a comma, return to regular indent if (line !~ s:comma_last) - return indent(prev_lnum) - &sw + return indent(prev_lnum) - s:sw() else - return indent(lvar) + &sw + return indent(lvar) + s:sw() endif endif @@ -221,7 +261,7 @@ function s:LineHasOpeningBrackets(lnum) endif let pos = match(line, '[][(){}]', pos + 1) endwhile - return (open_0 > 0) . (open_2 > 0) . (open_4 > 0) + return (open_0 > 0 ? 1 : (open_0 == 0 ? 0 : 2)) . (open_2 > 0) . (open_4 > 0) endfunction function s:Match(lnum, regex) @@ -302,6 +342,17 @@ function GetJavascriptIndent() " previous nonblank line number let prevline = prevnonblank(v:lnum - 1) + if (line =~ s:expr_case) + if (getline(prevline) =~ s:expr_case) + return indent(prevline) + else + if (getline(prevline) =~ s:block_regex) + return indent(prevline) + s:case_indent + else + return indent(prevline) - s:case_indent_after + endif + endif + endif " If we got a closing bracket on an empty line, find its match and indent " according to it. For parentheses we indent to its column - 1, for the " others we indent to the containing line's MSL's level. Return -1 if fail. @@ -323,7 +374,7 @@ function GetJavascriptIndent() return indent(prevline) " otherwise we indent 1 level else - return indent(lvar) + &sw + return indent(lvar) + s:sw() endif endif endif @@ -342,15 +393,51 @@ function GetJavascriptIndent() " If the line is comma first, dedent 1 level if (getline(prevline) =~ s:comma_first) - return indent(prevline) - &sw + return indent(prevline) - s:sw() + endif + if (getline(prevline) =~ s:expr_case) + return indent(prevline) + s:case_indent_after endif - if (line =~ s:ternary) - if (getline(prevline) =~ s:ternary_q) + " If line starts with an operator... + if (s:Match(v:lnum, s:operator_first)) + if (s:Match(prevline, s:operator_first)) + " and so does previous line, don't indent return indent(prevline) - else - return indent(prevline) + &sw + end + let counts = s:LineHasOpeningBrackets(prevline) + if counts[0] == '2' + call cursor(prevline, 1) + " Search for the opening tag + let mnum = searchpair('(', '', ')', 'bW', s:skip_expr) + if mnum > 0 && s:Match(mnum, s:operator_first) + return indent(mnum) + end + elseif counts[0] != '1' && counts[1] != '1' && counts[2] != '1' + " otherwise, indent 1 level + return indent(prevline) + s:sw() + end + " If previous line starts with an operator... + elseif s:Match(prevline, s:operator_first) && !s:Match(prevline, s:comma_last) && !s:Match(prevline, '};\=' . s:line_term) + let counts = s:LineHasOpeningBrackets(prevline) + if counts[0] == '2' && counts[1] == '1' + call cursor(prevline, 1) + " Search for the opening tag + let mnum = searchpair('(', '', ')', 'bW', s:skip_expr) + if mnum > 0 && !s:Match(mnum, s:operator_first) + return indent(mnum) + s:sw() + end + elseif counts[0] != '1' && counts[1] != '1' && counts[2] != '1' + return indent(prevline) - s:sw() + end + end + + if getline(prevline) =~ '^\s*`$' && s:IsInTempl(v:lnum, 1) + if line !~ '^\s*`$' + return indent(prevline) + s:sw() endif + elseif line =~ '^\s*`$' && s:IsInTempl(prevline, 1) + return indent(prevline) - s:sw() endif " If we are in a multi-line comment, cindent does the right thing. @@ -387,48 +474,71 @@ function GetJavascriptIndent() return 0 endif - " Set up variables for current line. - let line = getline(lnum) - let ind = indent(lnum) " If the previous line ended with a block opening, add a level of indent. if s:Match(lnum, s:block_regex) - return indent(s:GetMSL(lnum, 0)) + &sw + if (line =~ s:expr_case) + return indent(s:GetMSL(lnum, 0)) + s:sw()/2 + else + return indent(s:GetMSL(lnum, 0)) + s:sw() + endif endif + " Set up variables for current line. + let line = getline(lnum) + let ind = indent(lnum) " If the previous line contained an opening bracket, and we are still in it, " add indent depending on the bracket type. if line =~ '[[({]' let counts = s:LineHasOpeningBrackets(lnum) if counts[0] == '1' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 - if col('.') + 1 == col('$') - return ind + &sw + if col('.') + 1 == col('$') || line =~ s:one_line_scope_regex + return ind + s:sw() else return virtcol('.') endif - elseif counts[1] == '1' || counts[2] == '1' - return ind + &sw + elseif counts[1] == '1' || counts[2] == '1' && counts[0] != '2' + return ind + s:sw() else call cursor(v:lnum, vcol) end - endif + elseif line =~ '.\+};\=' . s:line_term + call cursor(lnum, 1) + " Search for the opening tag + let mnum = searchpair('{', '', '}', 'bW', s:skip_expr) + if mnum > 0 + return indent(s:GetMSL(mnum, 0)) + end + elseif line =~ '.\+);\=' || line =~ s:comma_last + let counts = s:LineHasOpeningBrackets(lnum) + if counts[0] == '2' + call cursor(lnum, 1) + " Search for the opening tag + let mnum = searchpair('(', '', ')', 'bW', s:skip_expr) + if mnum > 0 + return indent(s:GetMSL(mnum, 0)) + end + elseif line !~ s:var_stmt + return indent(prevline) + end + end " 3.4. Work on the MSL line. {{{2 " -------------------------- let ind_con = ind - let ind = s:IndentWithContinuation(lnum, ind_con, &sw) + let ind = s:IndentWithContinuation(lnum, ind_con, s:sw()) " }}}2 " " let ols = s:InOneLineScope(lnum) if ols > 0 - let ind = ind + &sw + let ind = ind + s:sw() else let ols = s:ExitingOneLineScope(lnum) while ols > 0 && ind > 0 - let ind = ind - &sw + let ind = ind - s:sw() let ols = s:InOneLineScope(ols - 1) endwhile endif |