summaryrefslogtreecommitdiffstats
path: root/indent
diff options
context:
space:
mode:
authorAdam Stankiewicz <sheerun@sher.pl>2017-05-17 11:07:28 +0200
committerAdam Stankiewicz <sheerun@sher.pl>2017-05-17 11:07:28 +0200
commitaf870100716f20ee4daef9cc527a9ecf41b54114 (patch)
tree0859464c3145682cbfc29ad08de4527dd661abf7 /indent
parentef369d45a505403587ea0bae30ce6768ba51398c (diff)
downloadvim-polyglot-af870100716f20ee4daef9cc527a9ecf41b54114.tar.gz
vim-polyglot-af870100716f20ee4daef9cc527a9ecf41b54114.zip
Update
Diffstat (limited to 'indent')
-rw-r--r--indent/ansible.vim5
-rw-r--r--indent/elixir.vim127
-rw-r--r--indent/haskell.vim90
-rw-r--r--indent/javascript.vim262
-rw-r--r--indent/plantuml.vim4
-rw-r--r--indent/ruby.vim96
-rw-r--r--indent/vue.vim59
7 files changed, 357 insertions, 286 deletions
diff --git a/indent/ansible.vim b/indent/ansible.vim
index b3a9642f..d94d3a2c 100644
--- a/indent/ansible.vim
+++ b/indent/ansible.vim
@@ -27,7 +27,12 @@ endif
function GetAnsibleIndent(lnum)
if a:lnum == 1 || !prevnonblank(a:lnum-1)
+ return 0
+ endif
+ if exists("g:ansible_unindent_after_newline")
+ if (a:lnum -1) != prevnonblank(a:lnum - 1)
return 0
+ endif
endif
let prevlnum = prevnonblank(a:lnum - 1)
let maintain = indent(prevlnum)
diff --git a/indent/elixir.vim b/indent/elixir.vim
index d1ea4ad4..0ddaec44 100644
--- a/indent/elixir.vim
+++ b/indent/elixir.vim
@@ -1,97 +1,48 @@
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'elixir') == -1
-setlocal nosmartindent
-setlocal indentexpr=elixir#indent()
-setlocal indentkeys+=0),0],0=\|>,=->
-setlocal indentkeys+=0=end,0=else,0=match,0=elsif,0=catch,0=after,0=rescue
-
-if exists("b:did_indent") || exists("*elixir#indent")
+if exists("b:did_indent")
finish
end
let b:did_indent = 1
-let s:cpo_save = &cpo
-set cpo&vim
-
-function! elixir#indent()
- " initiates the `old_ind` dictionary
- let b:old_ind = get(b:, 'old_ind', {})
- " initiates the `line` dictionary
- let line = s:build_line(v:lnum)
-
- if s:is_beginning_of_file(line)
- " Reset `old_ind` dictionary at the beginning of the file
- let b:old_ind = {}
- " At the start of the file use zero indent.
- return 0
- elseif !s:is_indentable_line(line)
- " Keep last line indentation if the current line does not have an
- " indentable syntax
- return indent(line.last_non_blank.num)
- else
- " Calculates the indenation level based on the rules
- " All the rules are defined in `autoload/elixir/indent.vim`
- let ind = indent(line.last_non_blank.num)
- call s:debug('>>> line = ' . string(line.current))
- call s:debug('>>> ind = ' . ind)
- let ind = s:indent('deindent_case_arrow', ind, line)
- let ind = s:indent('indent_parenthesis', ind, line)
- let ind = s:indent('indent_square_brackets', ind, line)
- let ind = s:indent('indent_brackets', ind, line)
- let ind = s:indent('deindent_opened_symbols', ind, line)
- let ind = s:indent('indent_pipeline_assignment', ind, line)
- let ind = s:indent('indent_pipeline_continuation', ind, line)
- let ind = s:indent('indent_after_pipeline', ind, line)
- let ind = s:indent('indent_assignment', ind, line)
- let ind = s:indent('indent_ending_symbols', ind, line)
- let ind = s:indent('indent_keywords', ind, line)
- let ind = s:indent('deindent_keywords', ind, line)
- let ind = s:indent('deindent_ending_symbols', ind, line)
- let ind = s:indent('indent_case_arrow', ind, line)
- let ind = s:indent('indent_ecto_queries', ind, line)
- call s:debug('<<< final = ' . ind)
- return ind
- end
-endfunction
-
-function s:indent(rule, ind, line)
- let Fn = function('elixir#indent#'.a:rule)
- let ind = Fn(a:ind, a:line)
- call s:debug(a:rule . ' = ' . ind)
- return ind
-endfunction
-
-function s:debug(message)
- if get(g:, 'elixir_indent_debug', 0)
- echom a:message
- end
-endfunction
-
-function! s:is_beginning_of_file(line)
- return a:line.last_non_blank.num == 0
+setlocal indentexpr=elixir#indent(v:lnum)
+
+setlocal indentkeys+=0=end,0=catch,0=rescue,0=after,0=else,=->,0},0],0),0=\|>,0=<>
+" TODO: @jbodah 2017-02-27: all operators should cause reindent when typed
+
+function! elixir#indent(lnum)
+ let lnum = a:lnum
+ let text = getline(lnum)
+ let prev_nb_lnum = prevnonblank(lnum-1)
+ let prev_nb_text = getline(prev_nb_lnum)
+
+ call elixir#indent#debug("==> Indenting line " . lnum)
+ call elixir#indent#debug("text = '" . text . "'")
+
+ let handlers = [
+ \'top_of_file',
+ \'starts_with_end',
+ \'starts_with_mid_or_end_block_keyword',
+ \'following_trailing_do',
+ \'following_trailing_binary_operator',
+ \'starts_with_pipe',
+ \'starts_with_close_bracket',
+ \'starts_with_binary_operator',
+ \'inside_nested_construct',
+ \'starts_with_comment',
+ \'inside_generic_block'
+ \]
+ for handler in handlers
+ call elixir#indent#debug('testing handler elixir#indent#handle_'.handler)
+ let indent = function('elixir#indent#handle_'.handler)(lnum, text, prev_nb_lnum, prev_nb_text)
+ if indent != -1
+ call elixir#indent#debug('line '.lnum.': elixir#indent#handle_'.handler.' returned '.indent)
+ return indent
+ endif
+ endfor
+
+ call elixir#indent#debug("defaulting")
+ return 0
endfunction
-function! s:is_indentable_line(line)
- return elixir#util#is_indentable_at(a:line.current.num, 1)
-endfunction
-
-function! s:build_line(line)
- let line = { 'current': {}, 'last': {}, 'last_non_blank': {} }
- let line.current = s:new_line(a:line)
- let line.last = s:new_line(line.current.num - 1)
- let line.last_non_blank = s:new_line(prevnonblank(line.current.num - 1))
-
- return line
-endfunction
-
-function! s:new_line(num)
- return {
- \ "num": a:num,
- \ "text": getline(a:num)
- \ }
-endfunction
-
-let &cpo = s:cpo_save
-unlet s:cpo_save
-
endif
diff --git a/indent/haskell.vim b/indent/haskell.vim
index 43dc97a6..e63515ce 100644
--- a/indent/haskell.vim
+++ b/indent/haskell.vim
@@ -13,11 +13,7 @@ if exists('b:did_indent')
finish
endif
-if !exists('g:haskell_indent_disable')
- let g:haskell_indent_disable = 0
-endif
-
-if g:haskell_indent_disable != 0
+if get(g:, 'haskell_indent_disable', 0)
finish
endif
@@ -68,7 +64,7 @@ if !exists('g:haskell_indent_guard')
endif
setlocal indentexpr=GetHaskellIndent()
-setlocal indentkeys=0},0),0],!^F,o,O,0\=,0=where,0=let,0=deriving,<space>
+setlocal indentkeys=0},0),0],!^F,o,O,0=where,0=let,0=deriving,<space>
function! s:isInBlock(hlstack)
return index(a:hlstack, 'haskellDelimiter') > -1 || 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
@@ -159,15 +155,6 @@ function! GetHaskellIndent()
return 0
endif
- " " comment indentation
- " if l:line =~ '^\s*--'
- " let l:s = match(l:prevline, '-- ')
- " if l:s > -1
- " endif
- " " if l:prevline =~ '^\s*--'
- " " return match(l:prevline, '\S')
- " " endif
-
" { foo :: Int
" >>,
"
@@ -258,12 +245,16 @@ function! GetHaskellIndent()
" where
" >>foo
"
+ if l:prevline =~ '\C\<where\>\s*$'
+ return match(l:prevline, '\S') + get(g:, 'haskell_indent_after_bare_where', &shiftwidth)
+ endif
+
" do
" >>foo
"
" foo =
" >>bar
- if l:prevline =~ '\C\(\<where\>\|\<do\>\|=\)\s*$'
+ if l:prevline =~ '\C\(\<do\>\|=\)\s*$'
return match(l:prevline, '\S') + &shiftwidth
endif
@@ -279,7 +270,7 @@ function! GetHaskellIndent()
" case foo of
" >>bar -> quux
if l:prevline =~ '\C\<case\>.\+\<of\>\s*$'
- if exists('g:haskell_indent_case_alternative') && g:haskell_indent_case_alternative
+ if get(g:,'haskell_indent_case_alternative', 0)
return match(l:prevline, '\S') + &shiftwidth
else
return match(l:prevline, '\C\<case\>') + g:haskell_indent_case
@@ -321,38 +312,50 @@ function! GetHaskellIndent()
" foo :: Int
" -> Int
+ " >>>>-> Int
+ "
+ " foo :: Monad m
+ " => Functor f
+ " >>>>=> Int
+ "
+ " foo :: Int
+ " -> Int
" foo x
"
" foo
" :: Int
" -> Int
" foo x
- if l:prevline =~ '^\s*[-=]>' && l:line !~ '^\s*[-=]>'
- if s:isInBlock(l:hlstack)
- return match(l:prevline, '[^\s-=>]')
+ if l:prevline =~ '^\s*[-=]>'
+ if l:line =~ '^\s*[-=]>'
+ return match(l:prevline, '[-=]')
else
- let l:m = matchstr(l:line, '^\s*\zs\<\S\+\>\ze')
- let l:l = l:prevline
- let l:c = 1
-
- while v:lnum != l:c
- " fun decl
- if l:l =~ ('^\s*' . l:m . '\(\s*::\|\n\s\+::\)')
- let l:s = match(l:l, l:m)
- if match(l:l, '\C^\s*\<default\>') > -1
- return l:s - 8
- else
- return l:s
+ if s:isInBlock(l:hlstack)
+ return match(l:prevline, '[^-=]')
+ else
+ let l:m = matchstr(l:line, '^\s*\zs\<\S\+\>\ze')
+ let l:l = l:prevline
+ let l:c = 1
+
+ while v:lnum != l:c
+ " fun decl
+ if l:l =~ ('^\s*' . l:m . '\(\s*::\|\n\s\+::\)')
+ let l:s = match(l:l, l:m)
+ if match(l:l, '\C^\s*\<default\>') > -1
+ return l:s - 8
+ else
+ return l:s
+ endif
+ " empty line, stop looking
+ elseif l:l =~ '^$'
+ return 0
endif
- " empty line, stop looking
- elseif l:l =~ '^$'
- return 0
- endif
- let l:c += 1
- let l:l = getline(v:lnum - l:c)
- endwhile
+ let l:c += 1
+ let l:l = getline(v:lnum - l:c)
+ endwhile
- return 0
+ return 0
+ endif
endif
endif
@@ -403,12 +406,17 @@ function! GetHaskellIndent()
" in foo
" where bar
+ "
+ " or
+ "
+ " foo
+ " >>where
if l:line =~ '\C^\s*\<where\>'
if match(l:prevline, '\C^\s\+in\s\+') == 0
return match(l:prevline, 'in') - g:haskell_indent_in
endif
- return match(l:prevline, '\S') + &shiftwidth
+ return match(l:prevline, '\S') + get(g:, 'haskell_indent_before_where', &shiftwidth)
endif
" let x = 1
diff --git a/indent/javascript.vim b/indent/javascript.vim
index 7029ed22..8f922eca 100644
--- a/indent/javascript.vim
+++ b/indent/javascript.vim
@@ -4,7 +4,7 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'javascript') ==
" Language: Javascript
" Maintainer: Chris Paul ( https://github.com/bounceme )
" URL: https://github.com/pangloss/vim-javascript
-" Last Change: March 9, 2017
+" Last Change: May 16, 2017
" Only load this indent file when no other was loaded.
if exists('b:did_indent')
@@ -12,6 +12,10 @@ if exists('b:did_indent')
endif
let b:did_indent = 1
+" indent correctly if inside <script>
+" vim/vim@690afe1 for the switch from cindent
+let b:html_indent_script1 = 'inc'
+
" Now, set up our indentation expression and keys that trigger it.
setlocal indentexpr=GetJavascriptIndent()
setlocal autoindent nolisp nosmartindent
@@ -23,6 +27,13 @@ setlocal indentkeys+=0],0)
let b:undo_indent = 'setlocal indentexpr< smartindent< autoindent< indentkeys<'
+" Regex of syntax group names that are or delimit string or are comments.
+let b:syng_strcom = get(b:,'syng_strcom','string\|comment\|regex\|special\|doc\|template\%(braces\)\@!')
+let b:syng_str = get(b:,'syng_str','string\|template\|special')
+" template strings may want to be excluded when editing graphql:
+" au! Filetype javascript let b:syng_str = '^\%(.*template\)\@!.*string\|special'
+" au! Filetype javascript let b:syng_strcom = '^\%(.*template\)\@!.*string\|comment\|regex\|special\|doc'
+
" Only define the function once.
if exists('*GetJavascriptIndent')
finish
@@ -38,7 +49,7 @@ if exists('*shiftwidth')
endfunction
else
function s:sw()
- return &l:shiftwidth == 0 ? &l:tabstop : &l:shiftwidth
+ return &l:shiftwidth ? &l:shiftwidth : &l:tabstop
endfunction
endif
@@ -46,6 +57,10 @@ endif
" matches before pos.
let s:z = has('patch-7.4.984') ? 'z' : ''
+let s:syng_com = 'comment\|doc'
+" Expression used to check whether we should skip a match with searchpair().
+let s:skip_expr = "s:syn_at(line('.'),col('.')) =~? b:syng_strcom"
+
" searchpair() wrapper
if has('reltime')
function s:GetPair(start,end,flags,skip,time,...)
@@ -57,56 +72,80 @@ else
endfunction
endif
-" Regex of syntax group names that are or delimit string or are comments.
-let s:syng_strcom = 'string\|comment\|regex\|special\|doc\|template\%(braces\)\@!'
-let s:syng_str = 'string\|template\|special'
-let s:syng_com = 'comment\|doc'
-" Expression used to check whether we should skip a match with searchpair().
-let s:skip_expr = "synIDattr(synID(line('.'),col('.'),0),'name') =~? '".s:syng_strcom."'"
+function s:syn_at(l,c)
+ let pos = join([a:l,a:c],',')
+ if has_key(s:synId_cache,pos)
+ return s:synId_cache[pos]
+ endif
+ let s:synId_cache[pos] = synIDattr(synID(a:l,a:c,0),'name')
+ return s:synId_cache[pos]
+endfunction
-function s:parse_cino(f) abort
- return float2nr(eval(substitute(substitute(join(split(
- \ matchstr(&cino,'\C.*'.a:f.'\zs[^,]*'), 's',1), '*'.s:W)
- \ , '^-\=\zs\*','',''), '^-\=\zs\.','0.','')))
+function s:parse_cino(f)
+ let [cin, divider, n] = [strridx(&cino,a:f), 0, '']
+ if cin == -1
+ return
+ endif
+ let [sign, cstr] = &cino[cin+1] ==# '-' ? [-1, &cino[cin+2:]] : [1, &cino[cin+1:]]
+ for c in split(cstr,'\zs')
+ if c ==# '.' && !divider
+ let divider = 1
+ elseif c ==# 's'
+ if n is ''
+ let n = s:W
+ else
+ let n = str2nr(n) * s:W
+ endif
+ break
+ elseif c =~ '\d'
+ let [n, divider] .= [c, 0]
+ else
+ break
+ endif
+ endfor
+ return sign * str2nr(n) / max([str2nr(divider),1])
endfunction
+" Optimized {skip} expr, used only once per GetJavascriptIndent() call
function s:skip_func()
- if getline('.') =~ '\%<'.col('.').'c\/.\{-}\/\|\%>'.col('.').'c[''"]\|\\$'
- return eval(s:skip_expr)
+ if s:topCol == 1 || line('.') < s:scriptTag
+ return {} " E728, used as limit condition for loops and searchpair()
+ endif
+ let s:topCol = col('.')
+ if getline('.') =~ '\%<'.s:topCol.'c\/.\{-}\/\|\%>'.s:topCol.'c[''"]\|\\$'
+ if eval(s:skip_expr)
+ let s:topCol = 0
+ endif
+ return !s:topCol
elseif s:checkIn || search('\m`\|\${\|\*\/','nW'.s:z,s:looksyn)
let s:checkIn = eval(s:skip_expr)
+ if s:checkIn
+ let s:topCol = 0
+ endif
endif
let s:looksyn = line('.')
return s:checkIn
endfunction
-function s:alternatePair(stop)
- let pos = getpos('.')[1:2]
- let pat = '[][(){};]'
- while search('\m'.pat,'bW',a:stop)
+function s:alternatePair()
+ let [l:pos, pat, l:for] = [getpos('.'), '[][(){};]', 3]
+ while search('\m'.pat,'bW')
if s:skip_func() | continue | endif
let idx = stridx('])};',s:looking_at())
- if idx is 3 | let pat = '[{}()]' | continue | endif
- if idx + 1
- if s:GetPair(['\[','(','{'][idx], '])}'[idx],'bW','s:skip_func()',2000,a:stop) <= 0
+ if idx is 3
+ if l:for is 1
+ return s:GetPair('{','}','bW','s:skip_func()',2000) > 0 || setpos('.',l:pos)
+ endif
+ let [pat, l:for] = ['[{}();]', l:for - 1]
+ elseif idx + 1
+ if s:GetPair(['\[','(','{'][idx], '])}'[idx],'bW','s:skip_func()',2000) < 1
break
endif
else
return
endif
endwhile
- call call('cursor',pos)
-endfunction
-
-function s:save_pos(f,...)
- let l:pos = getpos('.')[1:2]
- let ret = call(a:f,a:000)
- call call('cursor',l:pos)
- return ret
-endfunction
-
-function s:syn_at(l,c)
- return synIDattr(synID(a:l,a:c,0),'name')
+ call setpos('.',l:pos)
endfunction
function s:looking_at()
@@ -118,10 +157,10 @@ function s:token()
endfunction
function s:previous_token()
- let l:pos = getpos('.')[1:2]
+ let l:pos = getpos('.')
if search('\m\k\{1,}\|\S','ebW')
- if (getline('.')[col('.')-2:col('.')-1] == '*/' || line('.') != l:pos[0] &&
- \ getline('.') =~ '\%<'.col('.').'c\/\/') && s:syn_at(line('.'),col('.')) =~? s:syng_com
+ if (strpart(getline('.'),col('.')-2,2) == '*/' || line('.') != l:pos[1] &&
+ \ getline('.')[:col('.')-1] =~ '\/\/') && s:syn_at(line('.'),col('.')) =~? s:syng_com
while search('\m\S\ze\_s*\/[/*]','bW')
if s:syn_at(line('.'),col('.')) !~? s:syng_com
return s:token()
@@ -130,51 +169,66 @@ function s:previous_token()
else
return s:token()
endif
+ call setpos('.',l:pos)
endif
- call call('cursor',l:pos)
return ''
endfunction
+for s:__ in ['__previous_token','__IsBlock']
+ function s:{s:__}(...)
+ let l:pos = getpos('.')
+ try
+ return call('s:'.matchstr(expand('<sfile>'),'.*__\zs\w\+'),a:000)
+ catch
+ finally
+ call setpos('.',l:pos)
+ endtry
+ endfunction
+endfor
+
function s:expr_col()
if getline('.')[col('.')-2] == ':'
return 1
endif
- let bal = 0
- while search('\m[{}?:;]','bW')
- if eval(s:skip_expr) | continue | endif
- " switch (looking_at())
- exe { '}': "if s:GetPair('{','}','bW',s:skip_expr,200) <= 0 | return | endif",
- \ ';': "return",
- \ '{': "return getpos('.')[1:2] != b:js_cache[1:] && !s:IsBlock()",
- \ ':': "let bal -= getline('.')[max([col('.')-2,0]):col('.')] !~ '::'",
- \ '?': "let bal += 1 | if bal > 0 | return 1 | endif" }[s:looking_at()]
+ let [bal, l:pos] = [0, getpos('.')]
+ while bal < 1 && search('\m[{}?:;]','bW',s:scriptTag)
+ if eval(s:skip_expr)
+ continue
+ elseif s:looking_at() == ':'
+ let bal -= strpart(getline('.'),col('.')-2,3) !~ '::'
+ elseif s:looking_at() == '?'
+ let bal += 1
+ elseif s:looking_at() == '{' && getpos('.')[1:2] != b:js_cache[1:] && !s:IsBlock()
+ let bal = 1
+ elseif s:looking_at() != '}' || s:GetPair('{','}','bW',s:skip_expr,200) < 1
+ break
+ endif
endwhile
+ call setpos('.',l:pos)
+ return max([bal,0])
endfunction
" configurable regexes that define continuation lines, not including (, {, or [.
let s:opfirst = '^' . get(g:,'javascript_opfirst',
\ '\C\%([<>=,?^%|*/&]\|\([-.:+]\)\1\@!\|!=\|in\%(stanceof\)\=\>\)')
let s:continuation = get(g:,'javascript_continuation',
- \ '\C\%([-+<>=,.~!?/*^%|&:]\|\<\%(typeof\|new\|delete\|void\|in\|instanceof\|await\)\)') . '$'
+ \ '\C\%([<=,.~!?/*^%|&:]\|+\@<!+\|-\@<!-\|=\@<!>\|\<\%(typeof\|new\|delete\|void\|in\|instanceof\|await\)\)') . '$'
function s:continues(ln,con)
- if !cursor(a:ln, match(' '.a:con,s:continuation))
- let teol = s:looking_at()
- if teol == '/'
- return s:syn_at(line('.'),col('.')) !~? 'regex'
- elseif teol =~ '[-+>]'
- return getline('.')[col('.')-2] != tr(teol,'>','=')
- elseif teol =~ '\l'
+ let token = matchstr(a:con[-15:],s:continuation)
+ if strlen(token)
+ call cursor(a:ln,strlen(a:con))
+ if token =~ '[/>]'
+ return s:syn_at(a:ln,col('.')) !~? (token == '>' ? 'jsflow\|^html' : 'regex')
+ elseif token =~ '\l'
return s:previous_token() != '.'
- elseif teol == ':'
+ elseif token == ':'
return s:expr_col()
endif
return 1
endif
endfunction
-" get the line of code stripped of comments and move cursor to the last
-" non-comment char.
function s:Trim(ln)
let pline = substitute(getline(a:ln),'\s*$','','')
let l:max = max([strridx(pline,'//'), strridx(pline,'/*')])
@@ -183,24 +237,28 @@ function s:Trim(ln)
let l:max = max([strridx(pline,'//'), strridx(pline,'/*')])
let pline = substitute(pline[:-2],'\s*$','','')
endwhile
- return pline is '' || cursor(a:ln,strlen(pline)) ? pline : pline
+ return pline
endfunction
" Find line above 'lnum' that isn't empty or in a comment
function s:PrevCodeLine(lnum)
- let [l:pos, l:n] = [getpos('.')[1:2], prevnonblank(a:lnum)]
+ let l:n = prevnonblank(a:lnum)
while l:n
if getline(l:n) =~ '^\s*\/[/*]'
+ if (stridx(getline(l:n),'`') > 0 || getline(l:n-1)[-1:] == '\') &&
+ \ s:syn_at(l:n,1) =~? b:syng_str
+ break
+ endif
let l:n = prevnonblank(l:n-1)
elseif stridx(getline(l:n), '*/') + 1 && s:syn_at(l:n,1) =~? s:syng_com
+ let l:pos = getpos('.')
call cursor(l:n,1)
- keepjumps norm! [*
- let l:n = search('\m\S','nbW')
+ let l:n = search('\m\S\_s*\/\*','nbW')
+ call setpos('.',l:pos)
else
break
endif
endwhile
- call call('cursor',l:pos)
return l:n
endfunction
@@ -210,7 +268,7 @@ function s:Balanced(lnum)
let l:line = getline(a:lnum)
let pos = match(l:line, '[][(){}]', 0)
while pos != -1
- if s:syn_at(a:lnum,pos + 1) !~? s:syng_strcom
+ if s:syn_at(a:lnum,pos + 1) !~? b:syng_strcom
let l:open += match(' ' . l:line[pos],'[[({]')
if l:open < 0
return
@@ -225,6 +283,7 @@ endfunction
function s:OneScope(lnum)
let pline = s:Trim(a:lnum)
+ call cursor(a:lnum,strlen(pline))
let kw = 'else do'
if pline[-1:] == ')' && s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0
if s:previous_token() =~# '^\%(await\|each\)$'
@@ -235,7 +294,27 @@ function s:OneScope(lnum)
endif
endif
return pline[-2:] == '=>' || index(split(kw),s:token()) + 1 &&
- \ s:save_pos('s:previous_token') != '.'
+ \ s:__previous_token() != '.' && !s:doWhile()
+endfunction
+
+function s:doWhile()
+ if expand('<cword>') ==# 'while'
+ let [bal, l:pos] = [0, getpos('.')]
+ call search('\m\<','cbW')
+ while bal < 1 && search('\m\C[{}]\|\<\%(do\|while\)\>','bW')
+ if eval(s:skip_expr)
+ continue
+ elseif s:looking_at() ==# 'd'
+ let bal += s:__IsBlock(1)
+ elseif s:looking_at() ==# 'w'
+ let bal -= s:__previous_token() != '.'
+ elseif s:looking_at() != '}' || s:GetPair('{','}','bW',s:skip_expr,200) < 1
+ break
+ endif
+ endwhile
+ call setpos('.',l:pos)
+ return max([bal,0])
+ endif
endfunction
" returns braceless levels started by 'i' and above lines * &sw. 'num' is the
@@ -259,32 +338,36 @@ function s:iscontOne(i,num,cont)
endfunction
" https://github.com/sweet-js/sweet.js/wiki/design#give-lookbehind-to-the-reader
-function s:IsBlock()
- if s:looking_at() == '{'
+function s:IsBlock(...)
+ if a:0 || s:looking_at() == '{'
let l:n = line('.')
let char = s:previous_token()
if match(s:stack,'\cxml\|jsx') + 1 && s:syn_at(line('.'),col('.')-1) =~? 'xml\|jsx'
return char != '{'
elseif char =~ '\k'
if char ==# 'type'
- return s:previous_token() !~# '^\%(im\|ex\)port$'
+ return s:__previous_token() !~# '^\%(im\|ex\)port$'
endif
return index(split('return const let import export extends yield default delete var await void typeof throw case new of in instanceof')
- \ ,char) < (line('.') != l:n) || s:save_pos('s:previous_token') == '.'
+ \ ,char) < (line('.') != l:n) || s:__previous_token() == '.'
elseif char == '>'
- return getline('.')[col('.')-2] == '=' || s:syn_at(line('.'),col('.')) =~? '^jsflow'
+ return getline('.')[col('.')-2] == '=' || s:syn_at(line('.'),col('.')) =~? 'jsflow\|^html'
+ elseif char == '*'
+ return s:__previous_token() == ':'
elseif char == ':'
- return !s:save_pos('s:expr_col')
+ return !s:expr_col()
elseif char == '/'
return s:syn_at(line('.'),col('.')) =~? 'regex'
endif
- return char !~ '[=~!<*,?^%|&([]' &&
+ return char !~ '[=~!<,.?^%|&([]' &&
\ (char !~ '[-+]' || l:n != line('.') && getline('.')[col('.')-2] == char)
endif
endfunction
+
function GetJavascriptIndent()
let b:js_cache = get(b:,'js_cache',[0,0,0])
+ let s:synId_cache = {}
" Get the current line.
call cursor(v:lnum,1)
let l:line = getline('.')
@@ -299,7 +382,7 @@ function GetJavascriptIndent()
elseif l:line !~ '^\s*\/[/*]'
return -1
endif
- elseif syns =~? s:syng_str
+ elseif syns =~? b:syng_str
if b:js_cache[0] == v:lnum - 1 && s:Balanced(v:lnum-1)
let b:js_cache[0] = v:lnum
endif
@@ -319,37 +402,33 @@ function GetJavascriptIndent()
endif
" the containing paren, bracket, or curly. Many hacks for performance
- let idx = index([']',')','}'],l:line[0])
+ let [ s:scriptTag, idx ] = [ get(get(b:,'hi_indent',{}),'blocklnr'),
+ \ index([']',')','}'],l:line[0]) ]
if b:js_cache[0] >= l:lnum && b:js_cache[0] < v:lnum &&
\ (b:js_cache[0] > l:lnum || s:Balanced(l:lnum))
- call call('cursor',b:js_cache[1:])
+ call call('cursor',b:js_cache[2] ? b:js_cache[1:] : [0,0])
else
- let [s:looksyn, s:checkIn, top] = [v:lnum - 1, 0, (!indent(l:lnum) &&
- \ s:syn_at(l:lnum,1) !~? s:syng_str) * l:lnum]
+ let [s:looksyn, s:checkIn, s:topCol] = [v:lnum - 1, 0, 0]
if idx + 1
- call s:GetPair(['\[','(','{'][idx],'])}'[idx],'bW','s:skip_func()',2000,top)
+ call s:GetPair(['\[','(','{'][idx],'])}'[idx],'bW','s:skip_func()',2000)
elseif getline(v:lnum) !~ '^\S' && syns =~? 'block'
- call s:GetPair('{','}','bW','s:skip_func()',2000,top)
+ call s:GetPair('{','}','bW','s:skip_func()',2000)
else
- call s:alternatePair(top)
+ call s:alternatePair()
endif
endif
- let b:js_cache = [v:lnum] + (line('.') == v:lnum ? [0,0] : getpos('.')[1:2])
+ let b:js_cache = [v:lnum] + (line('.') == v:lnum ? [s:scriptTag,0] : getpos('.')[1:2])
let num = b:js_cache[1]
let [s:W, isOp, bL, switch_offset] = [s:sw(),0,0,0]
- if !num || s:IsBlock()
+ if !b:js_cache[2] || s:IsBlock()
let ilnum = line('.')
- let pline = s:save_pos('s:Trim',l:lnum)
- if num && s:looking_at() == ')' && s:GetPair('(', ')', 'bW', s:skip_expr, 100) > 0
+ let pline = s:Trim(l:lnum)
+ if b:js_cache[2] && s:looking_at() == ')' && s:GetPair('(',')','bW',s:skip_expr,100) > 0
let num = ilnum == num ? line('.') : num
if idx < 0 && s:previous_token() ==# 'switch' && s:previous_token() != '.'
- if &cino !~ ':'
- let switch_offset = s:W
- else
- let switch_offset = max([-indent(num),s:parse_cino(':')])
- endif
+ let switch_offset = &cino !~ ':' ? s:W : max([-indent(num),s:parse_cino(':')])
if pline[-1:] != '.' && l:line =~# '^\%(default\|case\)\>'
return indent(num) + switch_offset
endif
@@ -362,12 +441,13 @@ function GetJavascriptIndent()
endif
elseif idx < 0 && getline(b:js_cache[1])[b:js_cache[2]-1] == '(' && &cino =~ '('
let pval = s:parse_cino('(')
- return !pval ? (s:parse_cino('w') ? 0 : -(!!search('\m\S','W'.s:z,num))) + virtcol('.') :
- \ max([indent('.') + pval + (s:GetPair('(',')','nbrmW',s:skip_expr,100,num) * s:W),0])
+ return !pval || !search('\m\S','nbW',num) && !s:parse_cino('U') ?
+ \ (s:parse_cino('w') ? 0 : -!!search('\m\S','W'.s:z,num)) + virtcol('.') :
+ \ max([indent('.') + pval + s:GetPair('(',')','nbrmW',s:skip_expr,100,num) * s:W,0])
endif
" main return
- if l:line =~ '^\%([])}]\||}\)'
+ if l:line =~ '^[])}]\|^|}'
return max([indent(num),0])
elseif num
return indent(num) + s:W + switch_offset + bL + isOp
diff --git a/indent/plantuml.vim b/indent/plantuml.vim
index b2d3d8c3..a5e6fcdf 100644
--- a/indent/plantuml.vim
+++ b/indent/plantuml.vim
@@ -1,6 +1,6 @@
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'plantuml') == -1
-if exists("b:did_indent")
+if exists('b:did_indent')
finish
endif
let b:did_indent = 1
@@ -9,7 +9,7 @@ setlocal indentexpr=GetPlantUMLIndent()
setlocal indentkeys=o,O,<CR>,<:>,!^F,0end,0else,}
" only define the indent code once
-if exists("*GetPlantUMLIndent")
+if exists('*GetPlantUMLIndent')
finish
endif
diff --git a/indent/ruby.vim b/indent/ruby.vim
index 8fa929be..3617a925 100644
--- a/indent/ruby.vim
+++ b/indent/ruby.vim
@@ -49,22 +49,21 @@ set cpo&vim
" 1. Variables {{{1
" ============
-" Regex of syntax group names that are or delimit strings/symbols or are comments.
-let s:syng_strcom = '\<ruby\%(Regexp\|RegexpDelimiter\|RegexpEscape' .
- \ '\|Symbol\|String\|StringDelimiter\|StringEscape\|ASCIICode' .
- \ '\|Interpolation\|InterpolationDelimiter\|NoInterpolation\|Comment\|Documentation\)\>'
-
-" Regex of syntax group names that are strings.
+" Syntax group names that are strings.
let s:syng_string =
- \ '\<ruby\%(String\|Interpolation\|InterpolationDelimiter\|NoInterpolation\|StringEscape\)\>'
+ \ ['String', 'Interpolation', 'InterpolationDelimiter', 'NoInterpolation', 'StringEscape']
+
+" Syntax group names that are strings or documentation.
+let s:syng_stringdoc = s:syng_string + ['Documentation']
-" Regex of syntax group names that are strings or documentation.
-let s:syng_stringdoc =
- \ '\<ruby\%(String\|Interpolation\|InterpolationDelimiter\|NoInterpolation\|StringEscape\|Documentation\)\>'
+" Syntax group names that are or delimit strings/symbols/regexes or are comments.
+let s:syng_strcom = s:syng_stringdoc +
+ \ ['Regexp', 'RegexpDelimiter', 'RegexpEscape',
+ \ 'Symbol', 'StringDelimiter', 'ASCIICode', 'Comment']
" 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."'"
+ \ 'index(map('.string(s:syng_strcom).',"hlID(''ruby''.v:val)"), synID(line("."),col("."),1)) >= 0'
" Regex used for words that, at the start of a line, add a level of indent.
let s:ruby_indent_keywords =
@@ -152,7 +151,7 @@ let s:leading_operator_regex = '^\s*[.]'
" 2. GetRubyIndent Function {{{1
" =========================
-function GetRubyIndent(...)
+function! GetRubyIndent(...) abort
" 2.1. Setup {{{2
" ----------
@@ -255,7 +254,7 @@ endfunction
" 3. Indenting Logic Callbacks {{{1
" ============================
-function! s:AccessModifier(cline_info)
+function! s:AccessModifier(cline_info) abort
let info = a:cline_info
" If this line is an access modifier keyword, align according to the closest
@@ -279,7 +278,7 @@ function! s:AccessModifier(cline_info)
return -1
endfunction
-function! s:ClosingBracketOnEmptyLine(cline_info)
+function! s:ClosingBracketOnEmptyLine(cline_info) abort
let info = a:cline_info
" If we got a closing bracket on an empty line, find its match and indent
@@ -308,7 +307,7 @@ function! s:ClosingBracketOnEmptyLine(cline_info)
return -1
endfunction
-function! s:BlockComment(cline_info)
+function! s:BlockComment(cline_info) abort
" If we have a =begin or =end set indent to first column.
if match(a:cline_info.cline, '^\s*\%(=begin\|=end\)$') != -1
return 0
@@ -316,7 +315,7 @@ function! s:BlockComment(cline_info)
return -1
endfunction
-function! s:DeindentingKeyword(cline_info)
+function! s:DeindentingKeyword(cline_info) abort
let info = a:cline_info
" If we have a deindenting keyword, find its match and indent to its level.
@@ -357,7 +356,7 @@ function! s:DeindentingKeyword(cline_info)
return -1
endfunction
-function! s:MultilineStringOrLineComment(cline_info)
+function! s:MultilineStringOrLineComment(cline_info) abort
let info = a:cline_info
" If we are in a multi-line string or line-comment, don't do anything to it.
@@ -367,7 +366,7 @@ function! s:MultilineStringOrLineComment(cline_info)
return -1
endfunction
-function! s:ClosingHeredocDelimiter(cline_info)
+function! s:ClosingHeredocDelimiter(cline_info) abort
let info = a:cline_info
" If we are at the closing delimiter of a "<<" heredoc-style string, set the
@@ -381,7 +380,7 @@ function! s:ClosingHeredocDelimiter(cline_info)
return -1
endfunction
-function! s:LeadingOperator(cline_info)
+function! s:LeadingOperator(cline_info) abort
" If the current line starts with a leading operator, add a level of indent.
if s:Match(a:cline_info.clnum, s:leading_operator_regex)
return indent(s:GetMSL(a:cline_info.clnum)) + a:cline_info.sw
@@ -389,7 +388,7 @@ function! s:LeadingOperator(cline_info)
return -1
endfunction
-function! s:EmptyInsideString(pline_info)
+function! s:EmptyInsideString(pline_info) abort
" If the line is empty and inside a string (plnum would not be the real
" prevnonblank in that case), use the previous line's indent
let info = a:pline_info
@@ -400,7 +399,7 @@ function! s:EmptyInsideString(pline_info)
return -1
endfunction
-function! s:StartOfFile(pline_info)
+function! s:StartOfFile(pline_info) abort
" At the start of the file use zero indent.
if a:pline_info.plnum == 0
return 0
@@ -408,7 +407,7 @@ function! s:StartOfFile(pline_info)
return -1
endfunction
-function! s:AfterAccessModifier(pline_info)
+function! s:AfterAccessModifier(pline_info) abort
let info = a:pline_info
if g:ruby_indent_access_modifier_style == 'indent'
@@ -434,7 +433,7 @@ endfunction
" puts "foo"
" end
"
-function! s:ContinuedLine(pline_info)
+function! s:ContinuedLine(pline_info) abort
let info = a:pline_info
let col = s:Match(info.plnum, s:ruby_indent_keywords)
@@ -456,7 +455,7 @@ function! s:ContinuedLine(pline_info)
return -1
endfunction
-function! s:AfterBlockOpening(pline_info)
+function! s:AfterBlockOpening(pline_info) abort
let info = a:pline_info
" If the previous line ended with a block opening, add a level of indent.
@@ -482,7 +481,7 @@ function! s:AfterBlockOpening(pline_info)
return -1
endfunction
-function! s:AfterLeadingOperator(pline_info)
+function! s:AfterLeadingOperator(pline_info) abort
" If the previous line started with a leading operator, use its MSL's level
" of indent
if s:Match(a:pline_info.plnum, s:leading_operator_regex)
@@ -491,7 +490,7 @@ function! s:AfterLeadingOperator(pline_info)
return -1
endfunction
-function! s:AfterHangingSplat(pline_info)
+function! s:AfterHangingSplat(pline_info) abort
let info = a:pline_info
" If the previous line ended with the "*" of a splat, add a level of indent
@@ -501,7 +500,7 @@ function! s:AfterHangingSplat(pline_info)
return -1
endfunction
-function! s:AfterUnbalancedBracket(pline_info)
+function! s:AfterUnbalancedBracket(pline_info) abort
let info = a:pline_info
" If the previous line contained unclosed opening brackets and we are still
@@ -541,7 +540,7 @@ function! s:AfterUnbalancedBracket(pline_info)
return -1
endfunction
-function! s:AfterEndKeyword(pline_info)
+function! s:AfterEndKeyword(pline_info) abort
let info = a:pline_info
" If the previous line ended with an "end", match that "end"s beginning's
" indent.
@@ -562,7 +561,7 @@ function! s:AfterEndKeyword(pline_info)
return -1
endfunction
-function! s:AfterIndentKeyword(pline_info)
+function! s:AfterIndentKeyword(pline_info) abort
let info = a:pline_info
let col = s:Match(info.plnum, s:ruby_indent_keywords)
@@ -589,7 +588,7 @@ function! s:AfterIndentKeyword(pline_info)
return -1
endfunction
-function! s:PreviousNotMSL(msl_info)
+function! s:PreviousNotMSL(msl_info) abort
let info = a:msl_info
" If the previous line wasn't a MSL
@@ -608,7 +607,7 @@ function! s:PreviousNotMSL(msl_info)
return -1
endfunction
-function! s:IndentingKeywordInMSL(msl_info)
+function! s:IndentingKeywordInMSL(msl_info) abort
let info = a:msl_info
" If the MSL line had an indenting keyword in it, add a level of indent.
" TODO: this does not take into account contrived things such as
@@ -632,7 +631,7 @@ function! s:IndentingKeywordInMSL(msl_info)
return -1
endfunction
-function! s:ContinuedHangingOperator(msl_info)
+function! s:ContinuedHangingOperator(msl_info) abort
let info = a:msl_info
" If the previous line ended with [*+/.,-=], but wasn't a block ending or a
@@ -652,32 +651,37 @@ endfunction
" 4. Auxiliary Functions {{{1
" ======================
+function! s:IsInRubyGroup(groups, lnum, col) abort
+ let ids = map(copy(a:groups), 'hlID("ruby".v:val)')
+ return index(ids, synID(a:lnum, a:col, 1)) >= 0
+endfunction
+
" Check if the character at lnum:col is inside a string, comment, or is ascii.
-function s:IsInStringOrComment(lnum, col)
- return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_strcom
+function! s:IsInStringOrComment(lnum, col) abort
+ return s:IsInRubyGroup(s:syng_strcom, a:lnum, a:col)
endfunction
" Check if the character at lnum:col is inside a string.
-function s:IsInString(lnum, col)
- return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_string
+function! s:IsInString(lnum, col) abort
+ return s:IsInRubyGroup(s:syng_string, a:lnum, a:col)
endfunction
" Check if the character at lnum:col is inside a string or documentation.
-function s:IsInStringOrDocumentation(lnum, col)
- return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_stringdoc
+function! s:IsInStringOrDocumentation(lnum, col) abort
+ return s:IsInRubyGroup(s:syng_stringdoc, a:lnum, a:col)
endfunction
" Check if the character at lnum:col is inside a string delimiter
-function s:IsInStringDelimiter(lnum, col)
- return synIDattr(synID(a:lnum, a:col, 1), 'name') == 'rubyStringDelimiter'
+function! s:IsInStringDelimiter(lnum, col) abort
+ return s:IsInRubyGroup(['StringDelimiter'], a:lnum, a:col)
endfunction
-function s:IsAssignment(str, pos)
+function! s:IsAssignment(str, pos) abort
return strpart(a:str, 0, a:pos - 1) =~ '=\s*$'
endfunction
" Find line above 'lnum' that isn't empty, in a comment, or in a string.
-function s:PrevNonBlankNonString(lnum)
+function! s:PrevNonBlankNonString(lnum) abort
let in_block = 0
let lnum = prevnonblank(a:lnum)
while lnum > 0
@@ -702,7 +706,7 @@ function s:PrevNonBlankNonString(lnum)
endfunction
" Find line above 'lnum' that started the continuation 'lnum' may be part of.
-function s:GetMSL(lnum)
+function! s:GetMSL(lnum) abort
" Start on the line we're at and use its indent.
let msl = a:lnum
let lnum = s:PrevNonBlankNonString(a:lnum - 1)
@@ -807,7 +811,7 @@ function s:GetMSL(lnum)
endfunction
" Check if line 'lnum' has more opening brackets than closing ones.
-function s:ExtraBrackets(lnum)
+function! s:ExtraBrackets(lnum) abort
let opening = {'parentheses': [], 'braces': [], 'brackets': []}
let closing = {'parentheses': [], 'braces': [], 'brackets': []}
@@ -869,7 +873,7 @@ function s:ExtraBrackets(lnum)
return [rightmost_opening, rightmost_closing]
endfunction
-function s:Match(lnum, regex)
+function! s:Match(lnum, regex) abort
let line = getline(a:lnum)
let offset = match(line, '\C'.a:regex)
let col = offset + 1
@@ -889,7 +893,7 @@ endfunction
" Locates the containing class/module's definition line, ignoring nested classes
" along the way.
"
-function! s:FindContainingClass()
+function! s:FindContainingClass() abort
let saved_position = getpos('.')
while searchpair(s:end_start_regex, s:end_middle_regex, s:end_end_regex, 'bW',
diff --git a/indent/vue.vim b/indent/vue.vim
index e754ff6b..038996ba 100644
--- a/indent/vue.vim
+++ b/indent/vue.vim
@@ -5,41 +5,64 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'vue') == -1
" Maintainer: Eduardo San Martin Morote
" Author: Adriaan Zonnenberg
-if exists("b:did_indent")
+if exists('b:did_indent')
finish
endif
-" Load indent files for required languages
-for language in ['stylus', 'pug', 'css', 'javascript', 'html', 'coffee']
+function! s:get_indentexpr(language)
unlet! b:did_indent
- exe "runtime! indent/".language.".vim"
- exe "let s:".language."indent = &indentexpr"
+ execute 'runtime! indent/' . a:language . '.vim'
+ return &indentexpr
+endfunction
+
+" The order is important here, tags without attributes go last.
+" HTML is left out, it will be used when there is no match.
+let s:languages = [
+ \ { 'name': 'pug', 'pairs': ['<template lang="pug"', '</template>'] },
+ \ { 'name': 'stylus', 'pairs': ['<style lang="stylus"', '</style>'] },
+ \ { 'name': 'css', 'pairs': ['<style', '</style>'] },
+ \ { 'name': 'coffee', 'pairs': ['<script lang="coffee"', '</script>'] },
+ \ { 'name': 'javascript', 'pairs': ['<script', '</script>'] },
+ \ ]
+
+for language in s:languages
+ " Set 'indentexpr' if the user has an indent file installed for the language
+ if strlen(globpath(&rtp, 'indent/'. language.name .'.vim'))
+ let language.indentexpr = s:get_indentexpr(language.name)
+ endif
endfor
+let s:html_indent = s:get_indentexpr('html')
+
let b:did_indent = 1
setlocal indentexpr=GetVueIndent()
-if exists("*GetVueIndent")
+if exists('*GetVueIndent')
finish
endif
function! GetVueIndent()
- if searchpair('<template lang="pug"', '', '</template>', 'bWr')
- exe "let indent = ".s:pugindent
- elseif searchpair('<style lang="stylus"', '', '</style>', 'bWr')
- exe "let indent = ".s:stylusindent
- elseif searchpair('<style', '', '</style>', 'bWr')
- exe "let indent = ".s:cssindent
- elseif searchpair('<script lang="coffee"', '', '</script>', 'bWr')
- exe "let indent = ".s:coffeeindent
- elseif searchpair('<script', '', '</script>', 'bWr')
- exe "let indent = ".s:javascriptindent
+ for language in s:languages
+ let opening_tag_line = searchpair(language.pairs[0], '', language.pairs[1], 'bWr')
+
+ if opening_tag_line
+ execute 'let indent = ' . get(language, 'indentexpr', -1)
+ break
+ endif
+ endfor
+
+ if exists('l:indent')
+ if (opening_tag_line == prevnonblank(v:lnum - 1) || opening_tag_line == v:lnum)
+ \ || getline(v:lnum) =~ '\v^\s*\</(script|style|template)'
+ return 0
+ endif
else
- exe "let indent = ".s:htmlindent
+ " Couldn't find language, fall back to html
+ execute 'let indent = ' . s:html_indent
endif
- return indent > -1 ? indent : s:htmlindent
+ return indent
endfunction
endif