summaryrefslogtreecommitdiffstats
path: root/indent
diff options
context:
space:
mode:
Diffstat (limited to 'indent')
-rw-r--r--indent/eelixir.vim19
-rw-r--r--indent/elixir.vim255
-rw-r--r--indent/eruby.vim7
-rw-r--r--indent/haskell.vim85
-rw-r--r--indent/javascript.vim200
-rw-r--r--indent/perl6.vim131
-rw-r--r--indent/plantuml.vim58
-rw-r--r--indent/ruby.vim41
-rw-r--r--indent/scala.vim9
9 files changed, 435 insertions, 370 deletions
diff --git a/indent/eelixir.vim b/indent/eelixir.vim
index d9538425..b80edc98 100644
--- a/indent/eelixir.vim
+++ b/indent/eelixir.vim
@@ -8,6 +8,9 @@ runtime! indent/elixir.vim
unlet! b:did_indent
setlocal indentexpr=
+let s:cpo_save = &cpo
+set cpo&vim
+
if exists("b:eelixir_subtype")
exe "runtime! indent/".b:eelixir_subtype.".vim"
else
@@ -53,19 +56,21 @@ function! GetEelixirIndent(...)
let line = getline(lnum)
let cline = getline(v:lnum)
if cline =~# '^\s*<%\s*\%(end\|else\|elsif\|catch\|after\|rescue\)\>.*%>'
- let ind = ind - &sw
+ let ind -= &sw
elseif line =~# '\S\s*<%\s*end\s*%>'
- let ind = ind - &sw
+ let ind -= &sw
endif
- if line =~# '<%[=%]\=\s*.*\<do\s*%>'
- let ind = ind + &sw
- elseif line =~# '<%\s*\%(else\|elsif\|catch\|after\|rescue\)\>.*%>'
- let ind = ind + &sw
+ if line =~# '<%[=%]\=\s*.*\(\<do\|->\)\s*%>' ||
+ \ line =~# '<%\s*\%(else\|elsif\|catch\|after\|rescue\)\>.*%>'
+ let ind += &sw
endif
if cline =~# '^\s*%>\s*$'
- let ind = ind - &sw
+ let ind -= &sw
endif
return ind
endfunction
+let &cpo = s:cpo_save
+unlet s:cpo_save
+
endif
diff --git a/indent/elixir.vim b/indent/elixir.vim
index 7ccaea12..3e7b6de0 100644
--- a/indent/elixir.vim
+++ b/indent/elixir.vim
@@ -2,141 +2,198 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'elixir') == -1
if exists("b:did_indent")
finish
-endif
+end
let b:did_indent = 1
setlocal nosmartindent
setlocal indentexpr=GetElixirIndent()
-setlocal indentkeys+=0),0],0=end,0=else,0=match,0=elsif,0=catch,0=after,0=rescue
+setlocal indentkeys+=0),0],0=end,0=else,0=match,0=elsif,0=catch,0=after,0=rescue,0=\|>
if exists("*GetElixirIndent")
finish
-endif
+end
let s:cpo_save = &cpo
set cpo&vim
-let s:no_colon_before = ':\@<!'
-let s:no_colon_after = ':\@!'
-let s:symbols_end = '\]\|}\|)'
-let s:symbols_start = '\[\|{\|('
-let s:arrow = '^.*->$'
-let s:skip_syntax = '\%(Comment\|String\)$'
-let s:block_skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '".s:skip_syntax."'"
-let s:block_start = '\<\%(do\|fn\)\>'
-let s:block_middle = 'else\|match\|elsif\|catch\|after\|rescue'
-let s:block_end = 'end'
-let s:starts_with_pipeline = '^\s*|>.*$'
+let s:no_colon_before = ':\@<!'
+let s:no_colon_after = ':\@!'
+let s:symbols_end = '\]\|}\|)'
+let s:symbols_start = '\[\|{\|('
+let s:arrow = '^.*->$'
+let s:skip_syntax = '\%(Comment\|String\)$'
+let s:block_skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '".s:skip_syntax."'"
+let s:block_start = '\<\%(do\|fn\)\>'
+let s:block_middle = 'else\|match\|elsif\|catch\|after\|rescue'
+let s:block_end = 'end'
+let s:starts_with_pipeline = '^\s*|>.*$'
let s:ending_with_assignment = '=\s*$'
-let s:indent_keywords = '\<'.s:no_colon_before.'\%('.s:block_start.'\|'.s:block_middle.'\)$'.'\|'.s:arrow
+let s:indent_keywords = '\<'.s:no_colon_before.'\%('.s:block_start.'\|'.s:block_middle.'\)$'.'\|'.s:arrow
let s:deindent_keywords = '^\s*\<\%('.s:block_end.'\|'.s:block_middle.'\)\>'.'\|'.s:arrow
-let s:pair_start = '\<\%('.s:no_colon_before.s:block_start.'\)\>'.s:no_colon_after
-let s:pair_middle = '\<\%('.s:block_middle.'\)\>'.s:no_colon_after.'\zs'
-let s:pair_end = '\<\%('.s:no_colon_before.s:block_end.'\)\>\zs'
-
-let s:inside_block = 0
-
-function! GetElixirIndent()
- let lnum = prevnonblank(v:lnum - 1)
-
- " At the start of the file use zero indent.
- if lnum == 0
- return 0
- endif
-
- let opened_symbol = 0
- let current_line = getline(v:lnum)
- let last_line = getline(lnum)
- let ind = indent(lnum)
+let s:pair_start = '\<\%('.s:no_colon_before.s:block_start.'\)\>'.s:no_colon_after
+let s:pair_middle = '^\s*\%('.s:block_middle.'\)\>'.s:no_colon_after.'\zs'
+let s:pair_end = '\<\%('.s:no_colon_before.s:block_end.'\)\>\zs'
+function! s:is_indentable_syntax()
" TODO: Remove these 2 lines
" I don't know why, but for the test on spec/indent/lists_spec.rb:24.
" Vim is making some mess on parsing the syntax of 'end', it is being
" recognized as 'elixirString' when should be recognized as 'elixirBlock'.
+ call synID(s:current_line_ref, 1, 1)
" This forces vim to sync the syntax.
- call synID(v:lnum, 1, 1)
syntax sync fromstart
- if synIDattr(synID(v:lnum, 1, 1), "name") !~ s:skip_syntax
-
- if last_line !~ s:arrow
- let split_line = split(last_line, '\zs')
- let opened_symbol += count(split_line, '(') - count(split_line, ')')
- let opened_symbol += count(split_line, '[') - count(split_line, ']')
- let opened_symbol += count(split_line, '{') - count(split_line, '}')
- end
+ return synIDattr(synID(s:current_line_ref, 1, 1), "name")
+ \ !~ s:skip_syntax
+endfunction
- " if start symbol is followed by a character, indent based on the
- " whitespace after the symbol, otherwise use the default shiftwidth
- if last_line =~ '\('.s:symbols_start.'\).'
- let opened_prefix = matchlist(last_line, '\('.s:symbols_start.'\)\s*')[0]
- let ind += (opened_symbol * strlen(opened_prefix))
+function! s:indent_opened_symbol(ind)
+ if s:opened_symbol > 0
+ if s:pending_parenthesis > 0
+ \ && s:last_line !~ '^\s*def'
+ \ && s:last_line !~ s:arrow
+ let b:old_ind = a:ind
+ return matchend(s:last_line, '(')
+ " if start symbol is followed by a character, indent based on the
+ " whitespace after the symbol, otherwise use the default shiftwidth
+ " Avoid negative indentation index
+ elseif s:last_line =~ '\('.s:symbols_start.'\).'
+ let regex = '\('.s:symbols_start.'\)\s*'
+ let opened_prefix = matchlist(s:last_line, regex)[0]
+ return a:ind + (s:opened_symbol * strlen(opened_prefix))
else
- let ind += (opened_symbol * &sw)
- endif
-
- if last_line =~ '^\s*\('.s:symbols_end.'\)' || last_line =~ s:indent_keywords
- let ind += &sw
- endif
+ return a:ind + (s:opened_symbol * &sw)
+ end
+ elseif s:opened_symbol < 0
+ let ind = get(b:, 'old_ind', a:ind + (s:opened_symbol * &sw))
+ let ind = float2nr(ceil(floor(ind)/&sw)*&sw)
+ return ind <= 0 ? 0 : ind
+ else
+ return a:ind
+ end
+endfunction
- if current_line =~ '^\s*\('.s:symbols_end.'\)'
- let ind -= &sw
- endif
+function! s:indent_last_line_end_symbol_or_indent_keyword(ind)
+ if s:last_line =~ '^\s*\('.s:symbols_end.'\)'
+ \ || s:last_line =~ s:indent_keywords
+ return a:ind + &sw
+ else
+ return a:ind
+ end
+endfunction
- if last_line =~ s:ending_with_assignment && opened_symbol == 0
- let b:old_ind = indent(lnum)
- let ind += &sw
- end
+function! s:indent_symbols_ending(ind)
+ if s:current_line =~ '^\s*\('.s:symbols_end.'\)'
+ return a:ind - &sw
+ else
+ return a:ind
+ end
+endfunction
- " if line starts with pipeline
- " and last line ends with a pipeline,
- " align them
- if last_line =~ '|>.*$' &&
- \ current_line =~ s:starts_with_pipeline
- let ind = float2nr(match(last_line, '|>') / &sw) * &sw
+function! s:indent_assignment(ind)
+ if s:last_line =~ s:ending_with_assignment
+ let b:old_ind = indent(s:last_line_ref) " FIXME: side effect
+ return a:ind + &sw
+ else
+ return a:ind
+ end
+endfunction
+function! s:indent_pipeline(ind)
+ if s:last_line =~ s:starts_with_pipeline
+ \ && s:current_line =~ s:starts_with_pipeline
+ indent(s:last_line_ref)
+ elseif s:current_line =~ s:starts_with_pipeline
+ \ && s:last_line =~ '^[^=]\+=.\+$'
+ let b:old_ind = indent(s:last_line_ref)
" if line starts with pipeline
" and last line is an attribution
" indents pipeline in same level as attribution
- elseif current_line =~ s:starts_with_pipeline &&
- \ last_line =~ '^[^=]\+=.\+$'
-
- if !exists('b:old_ind') || b:old_ind == 0
- let b:old_ind = indent(lnum)
- end
- let ind = float2nr(matchend(last_line, '=\s*[^ ]') / &sw) * &sw
- endif
-
- " if last line starts with pipeline
- " and current line doesn't start with pipeline
- " returns the indentation before the pipeline
- if last_line =~ s:starts_with_pipeline &&
- \ current_line !~ s:starts_with_pipeline
- let ind = b:old_ind
- endif
-
- if current_line =~ s:deindent_keywords
- let bslnum = searchpair(
- \ s:pair_start,
- \ s:pair_middle,
- \ s:pair_end,
- \ 'nbW',
- \ s:block_skip
- \ )
-
- let ind = indent(bslnum)
- endif
+ return match(s:last_line, '=\s*\zs[^ ]')
+ else
+ return a:ind
+ end
+endfunction
+
+function! s:indent_after_pipeline(ind)
+ if s:last_line =~ s:starts_with_pipeline
+ if empty(substitute(s:current_line, ' ', '', 'g'))
+ \ || s:current_line =~ s:starts_with_pipeline
+ return indent(s:last_line_ref)
+ elseif s:last_line !~ s:indent_keywords
+ return b:old_ind
+ else
+ return a:ind
+ end
+ else
+ return a:ind
+ end
+endfunction
+
+function! s:deindent_keyword(ind)
+ if s:current_line =~ s:deindent_keywords
+ let bslnum = searchpair(
+ \ s:pair_start,
+ \ s:pair_middle,
+ \ s:pair_end,
+ \ 'nbW',
+ \ s:block_skip
+ \ )
+
+ return indent(bslnum)
+ else
+ return a:ind
+ end
+endfunction
+function! s:indent_arrow(ind)
+ if s:current_line =~ s:arrow
" indent case statements '->'
- if current_line =~ s:arrow
- let ind += &sw
- endif
- endif
+ return a:ind + &sw
+ else
+ return a:ind
+ end
+endfunction
- return ind
+function! GetElixirIndent()
+ let s:current_line_ref = v:lnum
+ let s:last_line_ref = prevnonblank(s:current_line_ref - 1)
+ let s:current_line = getline(s:current_line_ref)
+ let s:last_line = getline(s:last_line_ref)
+ let s:pending_parenthesis = 0
+ let s:opened_symbol = 0
+
+ if s:last_line !~ s:arrow
+ let splitted_line = split(s:last_line, '\zs')
+ let s:pending_parenthesis =
+ \ + count(splitted_line, '(') - count(splitted_line, ')')
+ let s:opened_symbol =
+ \ + s:pending_parenthesis
+ \ + count(splitted_line, '[') - count(splitted_line, ']')
+ \ + count(splitted_line, '{') - count(splitted_line, '}')
+ end
+
+ if s:last_line_ref == 0
+ " At the start of the file use zero indent.
+ return 0
+ elseif !s:is_indentable_syntax()
+ " Current syntax is not indentable, keep last line indentation
+ return indent(s:last_line_ref)
+ else
+ let ind = indent(s:last_line_ref)
+ let ind = s:indent_opened_symbol(ind)
+ let ind = s:indent_symbols_ending(ind)
+ let ind = s:indent_pipeline(ind)
+ let ind = s:indent_after_pipeline(ind)
+ let ind = s:indent_assignment(ind)
+ let ind = s:indent_last_line_end_symbol_or_indent_keyword(ind)
+ let ind = s:deindent_keyword(ind)
+ let ind = s:indent_arrow(ind)
+ return ind
+ end
endfunction
let &cpo = s:cpo_save
diff --git a/indent/eruby.vim b/indent/eruby.vim
index 82313a08..3736f529 100644
--- a/indent/eruby.vim
+++ b/indent/eruby.vim
@@ -43,6 +43,10 @@ if exists("*GetErubyIndent")
finish
endif
+" this file uses line continuations
+let s:cpo_sav = &cpo
+set cpo&vim
+
function! GetErubyIndent(...)
" The value of a single shift-width
if exists('*shiftwidth')
@@ -101,6 +105,9 @@ function! GetErubyIndent(...)
return ind
endfunction
+let &cpo = s:cpo_sav
+unlet! s:cpo_sav
+
" vim:set sw=2 sts=2 ts=8 noet:
endif
diff --git a/indent/haskell.vim b/indent/haskell.vim
index 7aa94367..ebdab5e7 100644
--- a/indent/haskell.vim
+++ b/indent/haskell.vim
@@ -63,15 +63,32 @@ setlocal indentexpr=GetHaskellIndent()
setlocal indentkeys=0{,0},0(,0),0[,0],!^F,o,O,0\=,0=where,0=let,0=deriving,<space>
function! s:isInBlock(hlstack)
- return index(a:hlstack, 'haskellParens') > -1 || index(a:hlstack, 'haskellBrackets') > -1 || index(a:hlstack, 'haskellBlock') > -1
+ return index(a:hlstack, 'haskellParens') > -1 || index(a:hlstack, 'haskellBrackets') > -1 || index(a:hlstack, 'haskellBlock') > -1 || index(a:hlstack, 'haskellBlockComment') > -1 || index(a:hlstack, 'haskellPragma') > -1
+endfunction
+
+function! s:stripTrailingComment(line)
+ if a:line =~ '^\s*--\(-\+\|\s\+\)' || a:line =~ '^\s*{-'
+ return a:line
+ else
+ let l:stripped = split(a:line, '-- ')
+ if len(l:stripped) > 1
+ return substitute(l:stripped[0], '\s*$', '', '')
+ else
+ return a:line
+ endif
+ endif
+endfunction
+
+function! s:isSYN(grp, line, col)
+ return index(s:getHLStack(a:line, a:col), a:grp) != -1
endfunction
function! s:getNesting(hlstack)
- return filter(a:hlstack, 'v:val == "haskellBlock" || v:val == "haskellBrackets" || v:val == "haskellParens"')
+ return filter(a:hlstack, 'v:val == "haskellBlock" || v:val == "haskellBrackets" || v:val == "haskellParens" || v:val == "haskellBlockComment" || v:val == "haskellPragma" ')
endfunction
-function! s:getHLStack()
- return map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')
+function! s:getHLStack(line, col)
+ return map(synstack(a:line, a:col), 'synIDattr(v:val, "name")')
endfunction
" indent matching character
@@ -110,14 +127,14 @@ function! s:indentGuard(pos, prevline)
endfunction
function! GetHaskellIndent()
- let l:hlstack = s:getHLStack()
+ let l:hlstack = s:getHLStack(line('.'), col('.'))
" do not indent in strings and quasiquotes
if index(l:hlstack, 'haskellQuasiQuote') > -1 || index(l:hlstack, 'haskellBlockComment') > -1
return -1
endif
- let l:prevline = getline(v:lnum - 1)
+ let l:prevline = s:stripTrailingComment(getline(v:lnum - 1))
let l:line = getline(v:lnum)
" indent multiline strings
@@ -138,6 +155,9 @@ function! GetHaskellIndent()
if l:line =~ '^\s*--'
return match(l:prevline, '-- ')
endif
+ if l:prevline =~ '^\s*--'
+ return match(l:prevline, '\S')
+ endif
" { foo :: Int
" >>,
@@ -149,14 +169,18 @@ function! GetHaskellIndent()
if s:isInBlock(l:hlstack)
normal! 0
call search(',', 'cW')
- let l:n = s:getNesting(s:getHLStack())
+ let l:n = s:getNesting(s:getHLStack(line('.'), col('.')))
call search('[([{]', 'bW')
+ let l:cl = line('.')
+ let l:cc = col('.')
- while l:n != s:getNesting(s:getHLStack())
+ while l:n != s:getNesting(s:getHLStack(l:cl, l:cc)) || s:isSYN('haskellString', l:cl, l:cc) || s:isSYN('haskellChar', l:cl, l:cc)
call search('[([{]', 'bW')
+ let l:cl = line('.')
+ let l:cc = col('.')
endwhile
- return col('.') - 1
+ return l:cc - 1
else
let l:s = s:indentGuard(match(l:line, ','), l:prevline)
if l:s > -1
@@ -192,11 +216,20 @@ function! GetHaskellIndent()
" >>>>y = 2
if l:prevline =~ '\C\<let\>\s\+.\+$'
if l:line =~ '\C^\s*\<let\>'
- return match(l:prevline, '\C\<let\>')
+ let l:s = match(l:prevline, '\C\<let\>')
+ if s:isSYN('haskellLet', v:lnum - 1, l:s + 1)
+ return l:s
+ endif
elseif l:line =~ '\C^\s*\<in\>'
- return match(l:prevline, '\C\<let\>') + g:haskell_indent_in
+ let l:s = match(l:prevline, '\C\<let\>')
+ if s:isSYN('haskellLet', v:lnum - 1, l:s + 1)
+ return l:s + g:haskell_indent_in
+ endif
else
- return match(l:prevline, '\C\<let\>') + g:haskell_indent_let
+ let l:s = match(l:prevline, '\C\<let\>')
+ if s:isSYN('haskellLet', v:lnum - 1, l:s + 1)
+ return l:s + g:haskell_indent_let
+ endif
endif
endif
@@ -225,20 +258,13 @@ function! GetHaskellIndent()
return match(l:prevline, '\S') + &shiftwidth
endif
- "" where foo
- "" >>>>>>bar
- if l:prevline =~ '\C\<where\>\s\+\S\+.*$'
- if l:line =~ '^\s*[=-]>\s' && l:prevline =~ ' :: '
- return match(l:prevline, ':: ')
- else
- return match(l:prevline, '\C\<where\>') + g:haskell_indent_where
- endif
- endif
-
" do foo
" >>>bar
if l:prevline =~ '\C\<do\>\s\+\S\+.*$'
- return match(l:prevline, '\C\<do\>') + g:haskell_indent_do
+ let l:s = match(l:prevline, '\C\<do\>')
+ if s:isSYN('haskellKeyword', v:lnum - 1, l:s + 1)
+ return l:s + g:haskell_indent_do
+ endif
endif
" case foo of
@@ -247,6 +273,19 @@ function! GetHaskellIndent()
return match(l:prevline, '\C\<case\>') + g:haskell_indent_case
endif
+ "" where foo
+ "" >>>>>>bar
+ if l:prevline =~ '\C\<where\>\s\+\S\+.*$'
+ if l:line =~ '^\s*[=-]>\s' && l:prevline =~ ' :: '
+ return match(l:prevline, ':: ')
+ else
+ let l:s = match(l:prevline, '\C\<where\>')
+ if s:isSYN('haskellWhere', v:lnum - 1, l:s + 1)
+ return l:s + g:haskell_indent_where
+ endif
+ endif
+ endif
+
" newtype Foo = Foo
" >>deriving
if l:prevline =~ '\C\s*\<\(newtype\|data\)\>[^{]\+' && l:line =~ '\C^\s*\<deriving\>'
diff --git a/indent/javascript.vim b/indent/javascript.vim
index add0dfb1..e8573790 100644
--- a/indent/javascript.vim
+++ b/indent/javascript.vim
@@ -2,26 +2,26 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'javascript') ==
" Vim indent file
" Language: Javascript
-" Maintainer: vim-javascript community
-" URL: https://github.com/pangloss/vim-javascript
-" Acknowledgement: Based off of vim-ruby maintained by Nikolai Weibull http://vim-ruby.rubyforge.org
+" Maintainer: vim-javascript community
+" URL: https://github.com/pangloss/vim-javascript
+" Last Change: August 20, 2016
" Only load this indent file when no other was loaded.
-if exists("b:did_indent")
+if exists('b:did_indent')
finish
endif
let b:did_indent = 1
" Now, set up our indentation expression and keys that trigger it.
setlocal indentexpr=GetJavascriptIndent()
-setlocal nolisp
+setlocal nolisp noautoindent nosmartindent
setlocal indentkeys=0{,0},0),0],:,!^F,o,O,e
setlocal cinoptions+=j1,J1
-let b:undo_indent = 'setlocal indentexpr< indentkeys< cinoptions<'
+let b:undo_indent = 'setlocal indentexpr< smartindent< autoindent< indentkeys< cinoptions<'
" Only define the function once.
-if exists("*GetJavascriptIndent")
+if exists('*GetJavascriptIndent')
finish
endif
@@ -30,125 +30,120 @@ set cpo&vim
" Get shiftwidth value
if exists('*shiftwidth')
- func s:sw()
+ function s:sw()
return shiftwidth()
- endfunc
+ endfunction
else
- func s:sw()
+ function s:sw()
return &sw
- endfunc
+ endfunction
endif
-let s:line_pre = '^\s*\%(\/\*.*\*\/\s*\)*'
-let s:expr_case = s:line_pre . '\%(\%(case\>.*\)\|default\)\s*:\C'
+let s:line_pre = '^\s*\%(\%(\%(\/\*.\{-}\)\=\*\+\/\s*\)\=\)\@>'
+let s:expr_case = s:line_pre . '\%(\%(case\>.\+\)\|default\)\s*:'
" Regex of syntax group names that are or delimit string or are comments.
-let s:syng_strcom = '\%(string\|regex\|special\|doc\|comment\|template\)\c'
+let s:syng_strcom = '\%(s\%(tring\|pecial\)\|comment\|regex\|doc\|template\)'
" Regex of syntax group names that are strings or documentation.
-let s:syng_comment = '\%(comment\|doc\)\c'
+let s:syng_comment = '\%(comment\|doc\)'
" Expression used to check whether we should skip a match with searchpair().
-let s:skip_expr = "line('.') < (prevnonblank(v:lnum) - 2000) ? dummy : s:IsSyn(line('.'),col('.'),'')"
+let s:skip_expr = "synIDattr(synID(line('.'),col('.'),0),'name') =~? '".s:syng_strcom."'"
-func s:lookForParens(start,end,flags,time)
- try
- return searchpair(a:start,'',a:end,a:flags,s:skip_expr,0,a:time)
- catch /E118/
- return searchpair(a:start,'',a:end,a:flags,0,0)
- endtry
-endfunc
+if has('reltime')
+ function s:GetPair(start,end,flags,time)
+ return searchpair(a:start,'',a:end,a:flags,s:skip_expr,max([prevnonblank(v:lnum) - 2000,0]),a:time)
+ endfunction
+else
+ function s:GetPair(start,end,flags,n)
+ return searchpair(a:start,'',a:end,a:flags,0,max([prevnonblank(v:lnum) - 2000,0]))
+ endfunction
+endif
-let s:line_term = '\s*\%(\%(:\@<!\/\/.*\)\=\|\%(\/\*.*\*\/\s*\)*\)$'
+let s:line_term = '\s*\%(\%(\/\%(\%(\*.\{-}\*\/\)\|\%(\*\+\)\)\)\s*\)\=$'
" configurable regexes that define continuation lines, not including (, {, or [.
if !exists('g:javascript_opfirst')
- let g:javascript_opfirst = '\%([,:?^%]\|\([-/.+]\)\%(\1\|\*\|\/\)\@!\|\*\/\@!\|=>\@!\||\|&\|in\%(stanceof\)\=\>\)\C'
+ let g:javascript_opfirst = '\%([<>,:?^%|*&]\|\([-/.+]\)\1\@!\|=>\@!\|in\%(stanceof\)\=\>\)'
endif
-let g:javascript_opfirst = s:line_pre . g:javascript_opfirst
-
if !exists('g:javascript_continuation')
- let g:javascript_continuation = '\%([*,.?:^%]\|+\@<!+\|-\@<!-\|\*\@<!\/\|=\||\|&\|\<in\%(stanceof\)\=\)\C'
+ let g:javascript_continuation = '\%([<=,.?/*:^%|&]\|+\@<!+\|-\@<!-\|=\@<!>\|\<in\%(stanceof\)\=\)'
endif
+
+let g:javascript_opfirst = s:line_pre . g:javascript_opfirst
let g:javascript_continuation .= s:line_term
-function s:Onescope(lnum,text,add)
- return a:text =~ '\%(\<else\|\<do\|=>' . (a:add ? '\|\<try\|\<finally' : '' ) . '\)\C' . s:line_term ||
- \ (a:add && a:text =~ s:line_pre . s:line_term && getline(s:PrevCodeLine(a:lnum - 1)) =~ ')' . s:line_term) ||
- \ (cursor(a:lnum, match(a:text, ')' . s:line_term)) > -1 &&
- \ s:lookForParens('(', ')', 'cbW', 100) > 0 &&
- \ search((a:add ? '\%(function\*\|[A-Za-z_$][0-9A-Za-z_$]*\)\C' :
- \ '\<\%(for\%(\s+each\)\=\|if\|let\|switch\|while\|with\)\C') . '\_s*\%#','bW')) &&
- \ (a:add || (expand("<cword>") == 'while' ? !s:lookForParens('\<do\>\C', '\<while\>\C','bW',100) : 1))
+function s:OneScope(lnum,text,add)
+ return a:text =~# '\%(\<else\|\<do\|=>\)' . s:line_term ? 'no b' :
+ \ ((a:add && a:text =~ s:line_pre . '$' && search('\%' . s:PrevCodeLine(a:lnum - 1) . 'l.)' . s:line_term)) ||
+ \ cursor(a:lnum, match(a:text, ')' . s:line_term)) > -1) &&
+ \ s:GetPair('(', ')', 'cbW', 100) > 0 && search('\C\l\+\_s*\%#','bW') &&
+ \ (a:add || ((expand('<cword>') !=# 'while' || !s:GetPair('\C\<do\>', '\C\<while\>','nbW',100)) &&
+ \ expand('cword') !=# 'each' || search('\C\<for\_s\+\%#','nbW'))) ? expand('<cword>') : ''
endfunction
-" Auxiliary Functions {{{2
-
-" Check if the character at lnum:col is inside a string, comment, or is ascii.
-function s:IsSyn(lnum, col, reg)
- return synIDattr(synID(a:lnum, a:col, 1), 'name') =~? (a:reg != '' ? a:reg : s:syng_strcom)
+" https://github.com/sweet-js/sweet.js/wiki/design#give-lookbehind-to-the-reader
+function s:IsBlock()
+ return getline(line('.'))[col('.')-1] == '{' && !search(
+ \ '\C\%(\<return\s*\|\%([-=~!<*+,.?^%|&\[(]\|=\@<!>\|\*\@<!\/\|\<\%(var\|const\|let\|yield\|delete\|void\|t\%(ypeof\|hrow\)\|new\|\<in\%(stanceof\)\=\)\)\_s*\)\%#','bnW') &&
+ \ (!search(':\_s*\%#','bW') || (!s:GetPair('[({[]','[])}]','bW',200) || s:IsBlock()))
endfunction
+" Auxiliary Functions {{{2
+
" Find line above 'lnum' that isn't empty, in a comment, or in a string.
function s:PrevCodeLine(lnum)
- let lnum = prevnonblank(a:lnum)
- while lnum > 0
- if !s:IsSyn(lnum, matchend(getline(lnum), '^\s*[^''"]'),'')
- break
+ let l:lnum = prevnonblank(a:lnum)
+ while l:lnum
+ if synIDattr(synID(l:lnum,matchend(getline(l:lnum), '^\s*[^''"]'),0),'name') !~? s:syng_strcom
+ return l:lnum
endif
- let lnum = prevnonblank(lnum - 1)
+ let l:lnum = prevnonblank(l:lnum - 1)
endwhile
- return lnum
endfunction
-" Check if line 'lnum' has more opening brackets than closing ones.
-function s:LineHasOpeningBrackets(lnum)
- let open_0 = 0
- let open_2 = 0
- let open_4 = 0
- let line = getline(a:lnum)
- let pos = match(line, '[][(){}]', 0)
- let last = 0
+" Check if line 'lnum' has a balanced amount of parentheses.
+function s:Balanced(lnum)
+ let [open_0,open_2,open_4] = [0,0,0]
+ let l:line = getline(a:lnum)
+ let pos = match(l:line, '[][(){}]', 0)
while pos != -1
- if !s:IsSyn(a:lnum, pos + 1, '')
- let idx = stridx('(){}[]', line[pos])
+ if synIDattr(synID(a:lnum,pos + 1,0),'name') !~? s:syng_strcom
+ let idx = stridx('(){}[]', l:line[pos])
if idx % 2 == 0
let open_{idx} = open_{idx} + 1
- let last = pos
else
let open_{idx - 1} = open_{idx - 1} - 1
endif
endif
- let pos = match(line, '[][(){}]', pos + 1)
+ let pos = match(l:line, '[][(){}]', pos + 1)
endwhile
- return [(open_0 > 0 ? 1 : (open_0 == 0 ? 0 : 2)) . (open_2 > 0 ? 1 : (open_2 == 0 ? 0 : 2)) .
- \ (open_4 > 0 ? 1 : (open_4 == 0 ? 0 : 2)), last]
+ return (!open_4 + !open_2 + !open_0) - 2
endfunction
" }}}
function GetJavascriptIndent()
if !exists('b:js_cache')
let b:js_cache = [0,0,0]
- end
- " Get the current line.
- let line = getline(v:lnum)
- " previous nonblank line number
- let prevline = prevnonblank(v:lnum - 1)
- " previous line of code
- let lnum = s:PrevCodeLine(v:lnum - 1)
- if lnum == 0
- return 0
endif
+ " Get the current line.
+ let l:line = getline(v:lnum)
+ let syns = synIDattr(synID(v:lnum, 1, 0), 'name')
" start with strings,comments,etc.{{{2
- if (line !~ '^[''"`]' && s:IsSyn(v:lnum,1,'string\|template')) ||
- \ (line !~ '^\s*[/*]' && s:IsSyn(v:lnum,1,s:syng_comment))
+ if (l:line !~ '^[''"`]' && syns =~? '\%(string\|template\)') ||
+ \ (l:line !~ '^\s*[/*]' && syns =~? s:syng_comment)
return -1
endif
- if line !~ '^\%(\/\*\|\s*\/\/\)' && s:IsSyn(v:lnum,1,s:syng_comment)
+ if l:line !~ '^\%(\/\*\|\s*\/\/\)' && syns =~? s:syng_comment
return cindent(v:lnum)
endif
+ let l:lnum = s:PrevCodeLine(v:lnum - 1)
+ if l:lnum == 0
+ return 0
+ endif
- if (line =~ s:expr_case)
+ if (l:line =~# s:expr_case)
let cpo_switch = &cpo
set cpo+=%
let ind = cindent(v:lnum)
@@ -157,41 +152,42 @@ function GetJavascriptIndent()
endif
"}}}
- " the containing paren, bracket, curly
- let pcounts = [0]
- if b:js_cache[0] >= lnum && b:js_cache[0] <= v:lnum && b:js_cache[0] &&
- \ (b:js_cache[0] > lnum || map(pcounts,'s:LineHasOpeningBrackets(lnum)')[0][0] !~ '2')
- let num = pcounts[0][0] =~ '1' ? lnum : b:js_cache[1]
- if pcounts[0][0] =~'1'
- call cursor(lnum,pcounts[0][1])
- end
+ " the containing paren, bracket, curly. Memoize, last lineNr either has the
+ " same scope or starts a new one, unless if it closed a scope.
+ call cursor(v:lnum,1)
+ if b:js_cache[0] >= l:lnum && b:js_cache[0] < v:lnum && b:js_cache[0] &&
+ \ (b:js_cache[0] > l:lnum || s:Balanced(l:lnum) > 0)
+ let num = b:js_cache[1]
+ elseif syns != '' && l:line[0] =~ '\s'
+ let pattern = syns =~? 'block' ? ['{','}'] : syns =~? 'jsparen' ? ['(',')'] :
+ \ syns =~? 'jsbracket'? ['\[','\]'] : ['[({[]','[])}]']
+ let num = s:GetPair(pattern[0],pattern[1],'bW',2000)
else
- call cursor(v:lnum,1)
- let syns = synIDattr(synID(v:lnum, 1, 1), 'name')
- if line[0] =~ '\s' && syns != ''
- let pattern = syns =~? 'funcblock' ? ['{','}'] : syns =~? 'jsparen' ? ['(',')'] : syns =~? 'jsbracket'? ['\[','\]'] :
- \ ['(\|{\|\[',')\|}\|\]']
- let num = s:lookForParens(pattern[0],pattern[1],'bW',2000)
- else
- let num = s:lookForParens('(\|{\|\[',')\|}\|\]','bW',2000)
- end
- end
+ let num = s:GetPair('[({[]','[])}]','bW',2000)
+ endif
let b:js_cache = [v:lnum,num,line('.') == v:lnum ? b:js_cache[2] : col('.')]
- " most significant part
- if line =~ s:line_pre . '[])}]'
+ if l:line =~ s:line_pre . '[])}]'
return indent(num)
- end
- let inb = num == 0 ? 1 : s:Onescope(num, strpart(getline(num),0,b:js_cache[2] - 1),1)
- let switch_offset = (!inb || num == 0) || expand("<cword>") != 'switch' ? 0 : &cino !~ ':' || !has('float') ? s:sw() :
- \ float2nr(str2float(matchstr(&cino,'.*:\zs[-0-9.]*')) * (match(&cino,'.*:\zs[^,]*s') ? s:sw() : 1))
- if ((line =~ g:javascript_opfirst ||
- \ (getline(lnum) =~ g:javascript_continuation && getline(lnum) !~ s:expr_case)) &&
- \ inb) || (s:Onescope(lnum,getline(lnum),0) && line !~ s:line_pre . '{')
+ endif
+
+ call cursor(b:js_cache[1],b:js_cache[2])
+
+ let swcase = getline(l:lnum) =~# s:expr_case
+ let pline = swcase ? getline(l:lnum) : substitute(getline(l:lnum), '\%(:\@<!\/\/.*\)$', '','')
+ let inb = num == 0 || num < l:lnum && ((l:line !~ s:line_pre . ',' && pline !~ ',' . s:line_term) || s:IsBlock())
+ let switch_offset = num == 0 || s:OneScope(num, strpart(getline(num),0,b:js_cache[2] - 1),1) !=# 'switch' ? 0 :
+ \ &cino !~ ':' || !has('float') ? s:sw() :
+ \ float2nr(str2float(matchstr(&cino,'.*:\zs[-0-9.]*')) * (&cino =~# '.*:[^,]*s' ? s:sw() : 1))
+
+ " most significant, find the indent amount
+ if inb && !swcase && ((l:line =~# g:javascript_opfirst || pline =~# g:javascript_continuation) ||
+ \ num < l:lnum && s:OneScope(l:lnum,pline,0) =~# '\<\%(for\|each\|if\|let\|no\sb\|w\%(hile\|ith\)\)\>' &&
+ \ l:line !~ s:line_pre . '{')
return (num > 0 ? indent(num) : -s:sw()) + (s:sw() * 2) + switch_offset
elseif num > 0
return indent(num) + s:sw() + switch_offset
- end
+ endif
endfunction
diff --git a/indent/perl6.vim b/indent/perl6.vim
deleted file mode 100644
index 78c6011d..00000000
--- a/indent/perl6.vim
+++ /dev/null
@@ -1,131 +0,0 @@
-if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'perl') == -1
-
-" Vim indent file
-" Language: Perl 6
-" Maintainer: vim-perl <vim-perl@googlegroups.com>
-" Homepage: http://github.com/vim-perl/vim-perl
-" Bugs/requests: http://github.com/vim-perl/vim-perl/issues
-" Last Change: {{LAST_CHANGE}}
-" Contributors: Andy Lester <andy@petdance.com>
-" Hinrik Örn Sigurðsson <hinrik.sig@gmail.com>
-"
-" Adapted from indent/perl.vim by Rafael Garcia-Suarez <rgarciasuarez@free.fr>
-
-" Suggestions and improvements by :
-" Aaron J. Sherman (use syntax for hints)
-" Artem Chuprina (play nice with folding)
-" TODO:
-" This file still relies on stuff from the Perl 5 syntax file, which Perl 6
-" does not use.
-"
-" Things that are not or not properly indented (yet) :
-" - Continued statements
-" print "foo",
-" "bar";
-" print "foo"
-" if bar();
-" - Multiline regular expressions (m//x)
-" (The following probably needs modifying the perl syntax file)
-" - qw() lists
-" - Heredocs with terminators that don't match \I\i*
-
-" Only load this indent file when no other was loaded.
-if exists("b:did_indent")
- finish
-endif
-let b:did_indent = 1
-
-" Is syntax highlighting active ?
-let b:indent_use_syntax = has("syntax")
-
-setlocal indentexpr=GetPerl6Indent()
-
-" we reset it first because the Perl 5 indent file might have been loaded due
-" to a .pl/pm file extension, and indent files don't clean up afterwards
-setlocal indentkeys&
-
-setlocal indentkeys+=0=,0),0],0>,0»,0=or,0=and
-if !b:indent_use_syntax
- setlocal indentkeys+=0=EO
-endif
-
-let s:cpo_save = &cpo
-set cpo-=C
-
-function! GetPerl6Indent()
-
- " Get the line to be indented
- let cline = getline(v:lnum)
-
- " Indent POD markers to column 0
- if cline =~ '^\s*=\L\@!'
- return 0
- endif
-
- " Get current syntax item at the line's first char
- let csynid = ''
- if b:indent_use_syntax
- let csynid = synIDattr(synID(v:lnum,1,0),"name")
- endif
-
- " Don't reindent POD and heredocs
- if csynid =~ "^p6Pod"
- return indent(v:lnum)
- endif
-
-
- " Now get the indent of the previous perl line.
-
- " Find a non-blank line above the current line.
- let lnum = prevnonblank(v:lnum - 1)
- " Hit the start of the file, use zero indent.
- if lnum == 0
- return 0
- endif
- let line = getline(lnum)
- let ind = indent(lnum)
- " Skip heredocs, POD, and comments on 1st column
- if b:indent_use_syntax
- let skippin = 2
- while skippin
- let synid = synIDattr(synID(lnum,1,0),"name")
- if (synid =~ "^p6Pod" || synid =~ "p6Comment")
- let lnum = prevnonblank(lnum - 1)
- if lnum == 0
- return 0
- endif
- let line = getline(lnum)
- let ind = indent(lnum)
- let skippin = 1
- else
- let skippin = 0
- endif
- endwhile
- endif
-
- if line =~ '[<«\[{(]\s*\(#[^)}\]»>]*\)\=$'
- let ind = ind + &sw
- endif
- if cline =~ '^\s*[)}\]»>]'
- let ind = ind - &sw
- endif
-
- " Indent lines that begin with 'or' or 'and'
- if cline =~ '^\s*\(or\|and\)\>'
- if line !~ '^\s*\(or\|and\)\>'
- let ind = ind + &sw
- endif
- elseif line =~ '^\s*\(or\|and\)\>'
- let ind = ind - &sw
- endif
-
- return ind
-
-endfunction
-
-let &cpo = s:cpo_save
-unlet s:cpo_save
-
-" vim:ts=8:sts=4:sw=4:expandtab:ft=vim
-
-endif
diff --git a/indent/plantuml.vim b/indent/plantuml.vim
new file mode 100644
index 00000000..3e0f455d
--- /dev/null
+++ b/indent/plantuml.vim
@@ -0,0 +1,58 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'plantuml') == -1
+
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal indentexpr=GetPlantUMLIndent()
+setlocal indentkeys=o,O,<CR>,<:>,!^F,0end,0else,}
+
+" only define the indent code once
+if exists("*GetPlantUMLIndent")
+ finish
+endif
+
+let s:incIndent =
+ \ '^\s*\(loop\|alt\|opt\|group\|critical\|else\|legend\|box\)\>\|' .
+ \ '^\s*\([hr]\?note\|ref\)\>[^:]*$\|' .
+ \ '^\s*title\s*$\|' .
+ \ '^\s*skinparam\>.*{\s*$\|' .
+ \ '^\s*state\>.*{'
+
+let s:decIndent = '^\s*\(end\|else\|}\)'
+
+function! GetPlantUMLIndent(...) abort
+ "for current line, use arg if given or v:lnum otherwise
+ let clnum = a:0 ? a:1 : v:lnum
+
+ if !s:insidePlantUMLTags(clnum)
+ return indent(clnum)
+ endif
+
+ let pnum = prevnonblank(clnum-1)
+ let pindent = indent(pnum)
+ let pline = getline(pnum)
+ let cline = getline(clnum)
+
+ if cline =~ s:decIndent
+ if pline =~ s:incIndent
+ return pindent
+ else
+ return pindent - shiftwidth()
+ endif
+
+ elseif pline =~ s:incIndent
+ return pindent + shiftwidth()
+ endif
+
+ return pindent
+
+endfunction
+
+function! s:insidePlantUMLTags(lnum) abort
+ call cursor(a:lnum, 1)
+ return search('@startuml', 'Wbn') && search('@enduml', 'Wn')
+endfunction
+
+endif
diff --git a/indent/ruby.vim b/indent/ruby.vim
index da622c1c..8d8fa2e9 100644
--- a/indent/ruby.vim
+++ b/indent/ruby.vim
@@ -94,11 +94,12 @@ let s:end_skip_expr = s:skip_expr .
\ ' && getline(".") =~ "^\\s*\\<\\(while\\|until\\|for\\):\\@!\\>")'
" Regex that defines continuation lines, not including (, {, or [.
-let s:non_bracket_continuation_regex = '\%([\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)\s*\%(#.*\)\=$'
+let s:non_bracket_continuation_regex =
+ \ '\%([\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|:\@<![^[:alnum:]:][|&?]\|||\|&&\)\s*\%(#.*\)\=$'
" Regex that defines continuation lines.
let s:continuation_regex =
- \ '\%(%\@<![({[\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)\s*\%(#.*\)\=$'
+ \ '\%(%\@<![({[\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|:\@<![^[:alnum:]:][|&?]\|||\|&&\)\s*\%(#.*\)\=$'
" Regex that defines continuable keywords
let s:continuable_regex =
@@ -108,6 +109,12 @@ let s:continuable_regex =
" Regex that defines bracket continuations
let s:bracket_continuation_regex = '%\@<!\%([({[]\)\s*\%(#.*\)\=$'
+" Regex that defines dot continuations
+let s:dot_continuation_regex = '%\@<!\.\s*\%(#.*\)\=$'
+
+" Regex that defines backslash continuations
+let s:backslash_continuation_regex = '%\@<!\\\s*$'
+
" Regex that defines end of bracket continuation followed by another continuation
let s:bracket_switch_continuation_regex = '^\([^(]\+\zs).\+\)\+'.s:continuation_regex
@@ -196,7 +203,17 @@ function s:GetMSL(lnum)
" Otherwise, terminate search as we have found our MSL already.
let line = getline(lnum)
- if s:Match(msl, s:leading_operator_regex)
+ if !s:Match(msl, s:backslash_continuation_regex) &&
+ \ s:Match(lnum, s:backslash_continuation_regex)
+ " If the current line doesn't end in a backslash, but the previous one
+ " does, look for that line's msl
+ "
+ " Example:
+ " foo = "bar" \
+ " "baz"
+ "
+ let msl = lnum
+ elseif s:Match(msl, s:leading_operator_regex)
" If the current line starts with a leading operator, keep its indent
" and keep looking for an MSL.
let msl = lnum
@@ -221,18 +238,30 @@ function s:GetMSL(lnum)
" three
"
let msl = lnum
+ elseif s:Match(lnum, s:dot_continuation_regex) &&
+ \ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex))
+ " If the current line is a bracket continuation or a block-starter, but
+ " the previous is a dot, keep going to see if the previous line is the
+ " start of another continuation.
+ "
+ " Example:
+ " parent.
+ " method_call {
+ " three
+ "
+ let msl = lnum
elseif s:Match(lnum, s:non_bracket_continuation_regex) &&
\ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex))
" If the current line is a bracket continuation or a block-starter, but
- " the previous is a non-bracket one, keep going to see if the previous
- " line is a part of another continuation.
+ " the previous is a non-bracket one, respect the previous' indentation,
+ " and stop here.
"
" Example:
" method_call one,
" two {
" three
"
- let msl = lnum
+ return lnum
elseif s:Match(lnum, s:bracket_continuation_regex) &&
\ (s:Match(msl, s:bracket_continuation_regex) || s:Match(msl, s:block_continuation_regex))
" If both lines are bracket continuations (the current may also be a
diff --git a/indent/scala.vim b/indent/scala.vim
index 6f5d1da9..da6c2f5c 100644
--- a/indent/scala.vim
+++ b/indent/scala.vim
@@ -378,12 +378,17 @@ function! GetScalaIndent()
let prevline = scala#GetLine(prevlnum)
let curlnum = v:lnum
let curline = scala#GetLine(curlnum)
+ if get(g:, 'scala_scaladoc_indent', 0)
+ let star_indent = 2
+ else
+ let star_indent = 1
+ end
if prevline =~ '^\s*/\*\*'
if prevline =~ '\*/\s*$'
return ind
else
- return ind + 1
+ return ind + star_indent
endif
endif
@@ -538,7 +543,7 @@ function! GetScalaIndent()
if prevline =~ '^\s*\*/'
\ || prevline =~ '*/\s*$'
call scala#ConditionalConfirm("18")
- let ind = ind - 1
+ let ind = ind - star_indent
endif
if scala#LineEndsInIncomplete(prevline)