summaryrefslogtreecommitdiffstats
path: root/indent/javascript.vim
diff options
context:
space:
mode:
authorAdam Stankiewicz <sheerun@sher.pl>2016-05-03 12:56:11 +0200
committerAdam Stankiewicz <sheerun@sher.pl>2016-05-03 12:56:11 +0200
commit8cd62b9eab04cd80998a810c103b80d49fc64a89 (patch)
tree231115681ec694907a923745892508358ff529be /indent/javascript.vim
parent93e3f020a9637b3df9109348cef5fcc3e0bbda43 (diff)
downloadvim-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.vim182
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