Skip to content

Develop -> Master #472

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
Jun 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
120352b
readability changes in the indent script (#450)
bounceme May 30, 2016
12bbaba
timeout the paren searching (#453)
bounceme May 31, 2016
51bf45f
limiting for slow function and operator fix (#455)
bounceme Jun 2, 2016
d00e8dd
get a correct indent for initial operator first
bounceme Jun 2, 2016
06d8d16
Improve jsClassMethodDefinition matches
amadeus Jun 3, 2016
c9dc41f
working detection of object/array properties (#460)
bounceme Jun 3, 2016
943d90b
spread operator doesn't change indent (#462)
bounceme Jun 3, 2016
ec96793
First attempted pass at jsObjectBlock
amadeus Apr 29, 2016
671e605
Notes and general cleanup
amadeus Jun 5, 2016
6c2de10
Removing DOM CSS stuff
amadeus Jun 5, 2016
a0d1abc
More refactoring
amadeus Jun 5, 2016
c48323a
Tons of syntax block granularity
amadeus Jun 6, 2016
533beaa
Bug fixes and tweaks
amadeus Jun 6, 2016
da492ea
Improvements to import/exports syntax matching
amadeus Jun 6, 2016
99d658f
Code style tweaks
amadeus Jun 6, 2016
9550877
jsTaggedTemplate tweaks
amadeus Jun 6, 2016
79b73b3
Whitespace
amadeus Jun 6, 2016
c3a505b
First pass at fix for #433
amadeus Jun 6, 2016
a0155f5
First pass at fixing/supporting #425 & #393
amadeus Jun 6, 2016
648e924
Add support for spread operator
amadeus Jun 6, 2016
8679129
Renaming jsArray to jsBracket
amadeus Jun 6, 2016
4251230
Changing a TODO to a DISCUSS
amadeus Jun 6, 2016
37cdc8c
Improvements to jsClassValue endcase
amadeus Jun 6, 2016
e618248
Unlinking jsFutureKeys
amadeus Jun 6, 2016
8aea863
Debugger is no longer a future keys
amadeus Jun 8, 2016
5a0ae76
Misc tweaks
amadeus Jun 9, 2016
fc38746
Potential fix for jsClassValue region
amadeus Jun 11, 2016
e38617a
Fix computed class properties
amadeus Jun 11, 2016
ceb3341
Make ternary handling more robust
amadeus Jun 11, 2016
8e710ba
changes according to #466 (#463)
bounceme Jun 11, 2016
9e5b60a
Pulling version number out of README
amadeus Jun 14, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# vim-javascript v1.0.0
# vim-javascript

JavaScript bundle for vim, this bundle provides syntax highlighting and
improved indentation.
Expand Down
201 changes: 85 additions & 116 deletions indent/javascript.vim
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,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\,*<Return>,:,!^F,o,O,e
setlocal cinoptions+=j1,J1

" Only define the function once.
Expand All @@ -42,23 +42,28 @@ endif
" ============

let s:line_pre = '^\s*\%(\/\*.*\*\/\s*\)*'
let s:js_keywords = s:line_pre . '\%(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\)\>\C'
let s:js_keywords = s:line_pre . '\%(break\|import\|export\|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\)\>\C'
let s:expr_case = s:line_pre . '\%(case\s\+[^\:]*\|default\)\s*:\s*\C'
" Regex of syntax group names that are or delimit string or are comments.
let s:syng_strcom = '\%(string\|regex\|comment\|template\)\c'
let s:syng_strcom = '\%(string\|regex\|special\|comment\|template\)\c'

" Regex of syntax group names that are strings.
let s:syng_string = 'regex\c'

" Regex of syntax group names that are strings or documentation.
let s:syng_multiline = '\%(comment\|doc\)\c'

" Regex of syntax group names that are line comment.
let s:syng_linecom = 'linecomment\c'
let s:syng_comment = '\%(comment\|doc\)\c'

" Expression used to check whether we should skip a match with searchpair().
let s:skip_expr = "synIDattr(synID(line('.'),col('.'),1),'name') =~ '".s:syng_strcom."'"

func s:lookForParens(start,end,flags,stop)
try
return searchpair(a:start,'',a:end,a:flags,s:skip_expr,a:stop,300)
catch /E118/
return searchpair(a:start,'',a:end,a:flags,0,a:stop)
endtry
endfunc

let s:line_term = '\s*\%(\%(\/\/.*\)\=\|\%(\/\*.*\*\/\s*\)*\)$'

" Regex that defines continuation lines, not including (, {, or [.
Expand All @@ -73,7 +78,7 @@ function s:Onescope(lnum)
let mypos = col('.')
call cursor(a:lnum, 1)
if search('\<\%(while\|for\|if\)\>\s*(\C', 'ce', a:lnum) > 0 &&
\ searchpair('(', '', ')', 'W', s:skip_expr, a:lnum) > 0 &&
\ s:lookForParens('(', ')', 'W', a:lnum) > 0 &&
\ col('.') == strlen(s:RemoveTrailingComments(getline(a:lnum)))
call cursor(a:lnum, mypos)
return 1
Expand All @@ -86,7 +91,7 @@ endfunction
" Regex that defines blocks.
let s:block_regex = '[{([]' . s:line_term

let s:operator_first = s:line_pre . '\%([.,:?]\|\([-/+*]\)\%(\1\|\*\|\/\)\@!\|||\|&&\)'
let s:operator_first = s:line_pre . '\%([,:?]\|\([-/.+*]\)\%(\1\|\*\|\/\)\@!\|||\|&&\)'

let s:var_stmt = s:line_pre . '\%(const\|let\|var\)\s\+\C'

Expand All @@ -106,32 +111,23 @@ function s:IsInString(lnum, col)
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
endfunction

" Check if the character at lnum:col is a line comment.
function s:IsLineComment(lnum, col)
return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_linecom
function s:IsInComment(lnum, col)
return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_comment
endfunction

" Find line above 'lnum' that isn't empty, in a comment, or in a string.
function s:PrevNonBlankNonString(lnum)
let in_block = 0
let lnum = prevnonblank(a:lnum)
while lnum > 0
" 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 s:IsInMultilineComment(lnum, matchend(line, '^\s*/\*') - 1) && line !~ s:line_pre . '$'
if in_block
let in_block = 0
else
break
endif
elseif !in_block && s:IsInMultilineComment(lnum, match(line, '\*/\s*$') + 1) && line !~ s:line_pre . '$'
let in_block = 1
elseif !in_block && line !~ s:line_pre . '\%(//\).*$' && !(s:IsInStringOrComment(lnum, 1) && s:IsInStringOrComment(lnum, strlen(line)))
let com = match(line, '\%(\/\*.*\)\@<!\*\/') + 1
if s:IsInComment(lnum, com)
call cursor(lnum, com)
let parlnum = search('\%(\/\/.*\)\@<!\/\*', 'nbW')
if parlnum > 0
let lnum = parlnum
end
elseif line !~ '^' . s:line_term && !s:IsInStringOrComment(lnum,1)
break
endif
let lnum = prevnonblank(lnum - 1)
Expand All @@ -148,21 +144,18 @@ function s:GetMSL(lnum, in_one_line_scope)
" If we have a continuation line, or we're in a string, use line as MSL.
" Otherwise, terminate search as we have found our MSL already.
let line = getline(lnum)
let col = match(line, s:continuation_regex) + 1
let coal = match(line, s:comma_last) + 1
let line2 = getline(msl)
let col2 = matchend(line2, ')')
if ((col > 0 && !s:IsInStringOrComment(lnum, col) || coal > 0 && !s:IsInStringOrComment(lnum,coal)) &&
if ((s:Match(lnum,s:continuation_regex) || s:Match(lnum, s:comma_last)) &&
\ !s:Match(lnum, s:expr_case)) || 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
if s:Match(lnum, s:line_pre . '[]})]') && !a:in_one_line_scope
call cursor(lnum,1)
let parlnum = s:lookForParens('(\|{\|\[', ')\|}\|\]', 'nbW', 0)
if parlnum > 0
let lnum = parlnum
continue
end
end

else

Expand Down Expand Up @@ -191,18 +184,22 @@ endfunction
" Find if the string is inside var statement (but not the first string)
function s:InMultiVarStatement(lnum, cont, prev)
let lnum = s:PrevNonBlankNonString(a:lnum - 1)
let cont = a:cont
let prev = a:prev

" let type = synIDattr(synID(lnum, indent(lnum) + 1, 0), 'name')

" loop through previous expressions to find a var statement
while lnum > 0 && (s:Match(lnum, s:comma_last) ||(a:cont && getline(lnum) =~ s:line_pre . '}') ||
\ s:Match(lnum,s:continuation_regex)) || (a:prev && (s:Match(a:prev, s:comma_last) ||
\ s:Match(a:prev,s:continuation_regex)))
while lnum > 0 && (s:Match(lnum, s:comma_last) ||(cont && getline(lnum) =~ s:line_pre . '[]})]') ||
\ s:Match(lnum,s:continuation_regex)) || (prev && (s:Match(prev, s:comma_last) ||
\ s:Match(prev,s:continuation_regex)))
" if the line is a js keyword
if a:cont
if cont
let cont = 0
call cursor(lnum,1)
if searchpair('{', '', '}', 'bW', s:skip_expr) > 0
let lnum = line('.')
let parlnum = s:lookForParens('(\|{\|\[', ')\|}\|\]', 'nbW', 0)
if parlnum > 0
let lnum = parlnum
end
end
if s:Match(lnum, s:js_keywords)
Expand All @@ -219,33 +216,13 @@ function s:InMultiVarStatement(lnum, cont, prev)
end
endif
let lnum = s:PrevNonBlankNonString(lnum - 1)
let prev = prev && lnum > 0 ? prev : 0
endwhile

" beginning of program, not a var
return 0
endfunction

" Find line above with beginning of the var statement or returns 0 if it's not"{{{2
" this statement
" function s:GetVarIndent(lnum)
" let lvar = s:InMultiVarStatement(a:lnum, 0,0)
" let prev_lnum = s:PrevNonBlankNonString(a:lnum - 1)

" if lvar
" let line = s:RemoveTrailingComments(getline(prev_lnum))

" " if the previous line doesn't end in a comma, return to regular indent
" if (line !~ s:comma_last)
" return indent(prev_lnum) - s:sw()
" else
" return indent(lvar) + s:sw()
" endif
" endif

" return -1
" endfunction"}}}


" Check if line 'lnum' has more opening brackets than closing ones.
function s:LineHasOpeningBrackets(lnum)
let open_0 = 0
Expand Down Expand Up @@ -345,20 +322,22 @@ function GetJavascriptIndent()
let line = getline(v:lnum)
" previous nonblank line number
let prevline = prevnonblank(v:lnum - 1)

" previous line of code
let lnum = s:PrevNonBlankNonString(v:lnum - 1)

" to not change multiline string values
if synIDattr(synID(v:lnum, 1, 1), 'name') =~? 'string\|template' && line !~ s:line_pre . '[''"`]'
return indent(v:lnum)
if line !~ '^[''"`]' && synIDattr(synID(v:lnum, 1, 1), 'name') =~? 'string\|template'
return -1
endif

" If we are in a multi-line comment, cindent does the right thing.
if s:IsInMultilineComment(v:lnum, 1) && !s:IsLineComment(v:lnum, 1) &&
\ s:IsInMultilineComment(v:lnum, match(line, '\s*$')) && line !~ '^\/\*'
if line !~ '^\%(\/\*\|\s*\/\/\)' && s:IsInComment(v:lnum, 1)
return cindent(v:lnum)
endif

" single opening bracket will assume you want a c style of indenting
if s:Match(v:lnum, s:line_pre . '{' . s:line_term)
if s:Match(v:lnum, s:line_pre . '{' . s:line_term) && !s:Match(lnum,s:block_regex) &&
\ !s:Match(lnum,s:comma_last)
return cindent(v:lnum)
endif

Expand All @@ -373,47 +352,48 @@ function GetJavascriptIndent()
let col = matchend(line, s:line_pre . '[]})]')
if col > 0 && !s:IsInStringOrComment(v:lnum, col)
call cursor(v:lnum, col)


let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2)
if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0
let ind = s:InMultiVarStatement(line('.'), 0, 0) ? indent(line('.')) : indent(s:GetMSL(line('.'), 0))
let parlnum = s:lookForParens('(\|{\|\[', ')\|}\|\]', 'nbW', 0)
if parlnum > 0
let ind = s:InMultiVarStatement(parlnum, 0, 0) ? indent(parlnum) : indent(s:GetMSL(parlnum, 0))
endif
return ind
endif


" If line starts with an operator...
if (line =~ s:operator_first)
if (s:Match(prevline, s:operator_first))
if (s:Match(lnum, s:operator_first))
" and so does previous line, don't indent
return indent(prevline)
return indent(lnum)
end
let counts = s:LineHasOpeningBrackets(prevline)
if counts[0] == '2' || counts[1] == '2' || counts[2] == '2'
call cursor(prevline, 1)
let counts = s:LineHasOpeningBrackets(lnum)
if counts =~ '2'
call cursor(lnum, 1)
" Search for the opening tag
let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2)
if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0 && s:Match(line('.'), s:operator_first)
return indent(line('.'))
let parlnum = s:lookForParens('(\|{\|\[', ')\|}\|\]', 'nbW', 0)
if parlnum > 0
return !s:Match(parlnum, s:operator_first) &&
\ synIDattr(synID(v:lnum, 1, 1), 'name') !~? 'jsbracket\|jsparen\|jsobject' ?
\ indent(lnum) + s:sw() : indent(parlnum)
end
elseif counts[0] != '1' && counts[1] != '1' && counts[2] != '1'
" otherwise, indent 1 level
return indent(prevline) + s:sw()
elseif synIDattr(synID(v:lnum, 1, 1), 'name') !~? 'jsbracket\|jsparen\|jsobject'
" otherwise, if not in an key/val;array item;param, indent 1 level
return indent(lnum) + s:sw()
end

" If previous line starts with an operator...
elseif (s:Match(prevline, s:operator_first) && !s:Match(prevline,s:continuation_regex))||getline(prevline) =~ ');\=' . s:line_term
let counts = s:LineHasOpeningBrackets(prevline)
if counts[0] == '2' && !s:Match(prevline, s:operator_first)
call cursor(prevline, 1)
elseif (s:Match(lnum, s:operator_first) && !s:Match(lnum,s:continuation_regex))||getline(lnum) =~ ');\=' . s:line_term
let counts = s:LineHasOpeningBrackets(lnum)
if counts[0] == '2' && !s:Match(lnum, s:operator_first)
call cursor(lnum, 1)
" Search for the opening tag
let mnum = searchpair('(', '', ')', 'bW', s:skip_expr)
let mnum = s:lookForParens('(', ')', 'nbW', 0)
if mnum > 0 && s:Match(mnum, s:operator_first)
return indent(mnum) - s:sw()
end
elseif s:Match(prevline, s:operator_first)
if counts[0] != '1' && counts[1] != '1' && counts[2] != '1'
return indent(prevline) - s:sw()
elseif s:Match(lnum, s:operator_first)
if counts !~ '1'
return indent(lnum) - s:sw()
end
end
end
Expand All @@ -424,12 +404,12 @@ function GetJavascriptIndent()
" If the line is empty and the previous nonblank line was a multi-line
" comment, use that comment's indent. Deduct one char to account for the
" space in ' */'.
if line =~ '^\s*$' && s:IsInMultilineComment(prevline, 1)
if line =~ '^\s*$' && getline(prevline) !~ '\%(\%(^\s*\/\/\|\/\*\).*\)\@<!\*\/' &&
\ s:IsInComment(prevline, 1)
return indent(prevline) - 1
endif

" Find a non-blank, non-multi-line string line above the current line.
let lnum = s:PrevNonBlankNonString(v:lnum - 1)

" If the line is empty and inside a string, use the previous line.
if line =~ '^\s*$' && lnum != prevline
Expand All @@ -454,25 +434,14 @@ function GetJavascriptIndent()
" add indent depending on the bracket type.
if s:Match(lnum, '[[({})\]]')
let counts = s:LineHasOpeningBrackets(lnum)
if counts[0] == '2'
call cursor(lnum, 1)
" Search for the opening tag
if searchpair('(', '', ')', 'bW', s:skip_expr) > 0
return indent(s:GetMSL(line('.'), 0))
end
elseif counts[1] == '2' && !s:Match(lnum, s:line_pre . '}')
call cursor(lnum, 1)
" Search for the opening tag
if searchpair('{', '', '}', 'bW', s:skip_expr) > 0
return indent(s:GetMSL(line('.'), 0))
end
elseif counts[2] == '2' && !s:Match(lnum, s:line_pre . ']')
if counts =~ '2'
call cursor(lnum, 1)
" Search for the opening tag
if searchpair('\[', '', '\]', 'bW', s:skip_expr) > 0
return indent(s:GetMSL(line('.'), 0))
let parlnum = s:lookForParens('(\|{\|\[', ')\|}\|\]', 'nbW', 0)
if parlnum > 0 && !s:InMultiVarStatement(parlnum,0,0)
return indent(s:GetMSL(parlnum, 0))
end
elseif counts[1] == '1' || counts[2] == '1' || counts[0] == '1' || s:Onescope(lnum)
elseif counts =~ '1' || s:Onescope(lnum)
return ind + s:sw()
else
call cursor(v:lnum, vcol)
Expand Down Expand Up @@ -525,7 +494,7 @@ function! Fixedgq(lnum, count)
endif

" This gq is only meant to do code with strings, not comments
if s:IsLineComment(a:lnum, l:first_char) || s:IsInMultilineComment(a:lnum, l:first_char)
if s:IsInComment(a:lnum, l:first_char)
return 1
endif

Expand Down
Loading