diff options
Diffstat (limited to 'indent')
-rw-r--r-- | indent/crystal.vim | 279 | ||||
-rw-r--r-- | indent/ecrystal.vim | 3 | ||||
-rw-r--r-- | indent/plantuml.vim | 2 |
3 files changed, 51 insertions, 233 deletions
diff --git a/indent/crystal.vim b/indent/crystal.vim index 96cdd586..c69b2a28 100644 --- a/indent/crystal.vim +++ b/indent/crystal.vim @@ -1,21 +1,21 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'crystal') == -1 +" Initialization {{{1 +" ============== + " Only load this indent file when no other was loaded. if exists('b:did_indent') finish endif + let b:did_indent = 1 setlocal nosmartindent " Now, set up our indentation expression and keys that trigger it. setlocal indentexpr=GetCrystalIndent(v:lnum) -setlocal indentkeys=0{,0},0),0],!^F,o,O,e,:,. +setlocal indentkeys=0{,0},0),0],!^F,o,O,e,. setlocal indentkeys+==end,=else,=elsif,=when,=ensure,=rescue -setlocal indentkeys+==private,=protected - -let s:cpo_save = &cpo -set cpo&vim " Only define the function once. if exists('*GetCrystalIndent') @@ -26,7 +26,7 @@ endif if exists('*shiftwidth') let s:sw = function('shiftwidth') else - function s:sw() + function! s:sw() return &shiftwidth endfunction endif @@ -34,262 +34,81 @@ endif " GetCrystalIndent Function {{{1 " ========================= -function GetCrystalIndent(...) +function! GetCrystalIndent(...) abort " Setup {{{2 " ----- + let indent_info = {} + + " The value of a single shift-width + let indent_info.sw = s:sw() + " For the current line, use the first argument if given, else v:lnum - let clnum = a:0 ? a:1 : v:lnum + let indent_info.clnum = a:0 ? a:1 : v:lnum + let indent_info.cline = getline(indent_info.clnum) - " Set up variables for restoring position in file - let vcol = col('.') + " Set up variables for restoring position in file. + let indent_info.col = col('.') " Work on the current line {{{2 " ------------------------ - " Get the current line. - let line = getline(clnum) - let ind = -1 + for callback_name in g:crystal#indent#curr_line_callbacks + let indent = call(function(callback_name), [indent_info]) - " 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. - let col = matchend(line, '^\s*[]})]') - if col > 0 && !crystal#indent#IsInStringOrComment(clnum, col) - call cursor(clnum, col) - let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2) - if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', g:crystal#indent#skip_expr) - if line[col-1] ==# ')' && col('.') != col('$') - 1 - let ind = virtcol('.') - 1 - else - let ind = indent(crystal#indent#GetMSL(line('.'))) - endif + if indent >= 0 + return indent endif - return ind - endif - - " If we have a deindenting keyword, find its match and indent to its level. - " TODO: this is messy - if crystal#indent#Match(clnum, g:crystal#indent#crystal_deindent_keywords) - call cursor(clnum, 1) - if searchpair( - \ g:crystal#indent#end_start_regex, - \ g:crystal#indent#end_middle_regex, - \ g:crystal#indent#end_end_regex, - \ 'bW', g:crystal#indent#skip_expr) - let msl = crystal#indent#GetMSL(line('.')) - let line = getline(line('.')) - - if strpart(line, 0, col('.') - 1) =~# '=\s*$' && - \ strpart(line, col('.') - 1, 2) !~# 'do' - " assignment to case/begin/etc, on the same line, hanging indent - let ind = virtcol('.') - 1 - elseif getline(msl) =~# '=\s*\(#.*\)\=$' - " in the case of assignment to the msl, align to the starting line, - " not to the msl - let ind = indent(line('.')) - else - " align to the msl - let ind = indent(msl) - endif - endif - return ind - endif - - " If we are in a multi-line string, don't do anything to it. - if crystal#indent#IsInString(clnum, matchend(line, '^\s*') + 1) - return indent('.') - endif - - " If we are at the closing delimiter of a "<<" heredoc-style string, set the - " indent to 0. - if line =~# '^\k\+\s*$' - \ && crystal#indent#IsInStringDelimiter(clnum, 1) - \ && search('\V<<'.line, 'nbW') - return 0 - endif - - " If the current line starts with a leading operator, add a level of indent. - if crystal#indent#Match(clnum, g:crystal#indent#leading_operator_regex) - return indent(crystal#indent#GetMSL(clnum)) + s:sw() - endif + endfor " Work on the previous line. {{{2 " -------------------------- - " Find a non-blank, non-multi-line string line above the current line. - let lnum = crystal#indent#PrevNonBlankNonString(clnum - 1) - - " If the line is empty and inside a string, use the previous line. - if line =~# '^\s*$' && lnum != prevnonblank(clnum - 1) - return indent(prevnonblank(clnum)) - endif - - " At the start of the file use zero indent. - if lnum == 0 - return 0 - endif - - " Set up variables for the previous line. - let line = getline(lnum) - let ind = indent(lnum) + " Special case: we don't need the real PrevNonBlank for an empty line + " inside a string. And that call can be quite expensive in that + " particular situation. + let indent = crystal#indent#EmptyInsideString(indent_info) - if crystal#indent#Match(lnum, g:crystal#indent#continuable_regex) && - \ crystal#indent#Match(lnum, g:crystal#indent#continuation_regex) - return indent(crystal#indent#GetMSL(lnum)) + s:sw() * 2 + if indent >= 0 + return indent endif - " If the previous line ended with a block opening, add a level of indent. - if crystal#indent#Match(lnum, g:crystal#indent#block_regex) - let msl = crystal#indent#GetMSL(lnum) + " Previous line number + let indent_info.plnum = crystal#indent#PrevNonBlank(indent_info.clnum - 1) + let indent_info.pline = getline(indent_info.plnum) - if getline(msl) =~# '=\s*\(#.*\)\=$' - " in the case of assignment to the msl, align to the starting line, - " not to the msl - let ind = indent(lnum) + s:sw() - else - let ind = indent(msl) + s:sw() - endif - return ind - endif - - " If the previous line started with a leading operator, use its MSL's level - " of indent - if crystal#indent#Match(lnum, g:crystal#indent#leading_operator_regex) - return indent(crystal#indent#GetMSL(lnum)) - endif - - " If the previous line ended with the "*" of a splat, add a level of indent - if line =~ g:crystal#indent#splat_regex - return indent(lnum) + s:sw() - endif + for callback_name in g:crystal#indent#prev_line_callbacks + let indent = call(function(callback_name), [indent_info]) - " If the previous line contained unclosed opening brackets and we are still - " in them, find the rightmost one and add indent depending on the bracket - " type. - " - " If it contained hanging closing brackets, find the rightmost one, find its - " match and indent according to that. - if line =~# '[[({]' || line =~# '[])]\s*\%(#.*\)\=$' - let [opening, closing] = crystal#indent#ExtraBrackets(lnum) - - if opening.pos != -1 - if opening.type ==# '(' && searchpair('(', '', ')', 'bW', g:crystal#indent#skip_expr) - if col('.') + 1 == col('$') - return ind + s:sw() - else - return virtcol('.') - endif - else - let nonspace = matchend(line, '\S', opening.pos + 1) - 1 - return nonspace > 0 ? nonspace : ind + s:sw() - endif - elseif closing.pos != -1 - call cursor(lnum, closing.pos + 1) - keepjumps normal! % - - if crystal#indent#Match(line('.'), g:crystal#indent#crystal_indent_keywords) - return indent('.') + s:sw() - else - return indent('.') - endif - else - call cursor(clnum, vcol) - end - endif - - " If the previous line ended with an "end", match that "end"s beginning's - " indent. - let col = crystal#indent#Match(lnum, g:crystal#indent#end_end_regex) - if col - call cursor(lnum, col) - if searchpair( - \ g:crystal#indent#end_start_regex, - \ g:crystal#indent#end_middle_regex, - \ g:crystal#indent#end_end_regex, - \ 'bW', - \ g:crystal#indent#skip_expr) - let n = line('.') - let ind = indent('.') - let msl = crystal#indent#GetMSL(n) - if msl != n - let ind = indent(msl) - end - return ind + if indent >= 0 + return indent endif - end + endfor - let col = crystal#indent#Match(lnum, g:crystal#indent#crystal_indent_keywords) - if col - call cursor(lnum, col) - let ind = virtcol('.') - 1 + s:sw() - " TODO: make this better (we need to count them) (or, if a searchpair - " fails, we know that something is lacking an end and thus we indent a - " level - if crystal#indent#Match(lnum, g:crystal#indent#end_end_regex) - let ind = indent('.') - endif - return ind - endif - - " Work on the MSL line. {{{2 - " --------------------- - - " Set up variables to use and search for MSL to the previous line. - let p_lnum = lnum - let lnum = crystal#indent#GetMSL(lnum) - - " If the previous line wasn't a MSL. - if p_lnum != lnum - " If previous line ends bracket and begins non-bracket continuation decrease indent by 1. - if crystal#indent#Match(p_lnum, g:crystal#indent#bracket_switch_continuation_regex) - return ind - 1 - " If previous line is a continuation return its indent. - " TODO: the || crystal#indent#IsInString() thing worries me a bit. - elseif crystal#indent#Match(p_lnum, g:crystal#indent#non_bracket_continuation_regex) || - \ crystal#indent#IsInString(p_lnum,strlen(line)) - return ind - endif - endif + " Work on the MSL. {{{2 + " ---------------- - " Set up more variables, now that we know we wasn't continuation bound. - let line = getline(lnum) - let msl_ind = indent(lnum) + " Most Significant line based on the previous one -- in case it's a + " contination of something above + let indent_info.plnum_msl = crystal#indent#GetMSL(indent_info.plnum) + let indent_info.pline_msl = getline(indent_info.plnum_msl) - " 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 - " module Foo; class Bar; end - if crystal#indent#Match(lnum, g:crystal#indent#crystal_indent_keywords) - let ind = msl_ind + s:sw() - if crystal#indent#Match(lnum, g:crystal#indent#end_end_regex) - let ind = ind - s:sw() - endif - return ind - endif + for callback_name in g:crystal#indent#msl_callbacks + let indent = call(function(callback_name), [indent_info]) - " If the previous line ended with an operator -- but wasn't a block - " ending, closing bracket, or type declaration -- indent one extra - " level. - if crystal#indent#Match(lnum, g:crystal#indent#non_bracket_continuation_regex) && - \ !crystal#indent#Match(lnum, '^\s*\([\])}]\|end\)') - if lnum == p_lnum - let ind = msl_ind + s:sw() - else - let ind = msl_ind + if indent >= 0 + return indent endif - return ind - endif + endfor " }}}2 - return ind + " By default, just return the previous line's indent + return indent(indent_info.plnum) endfunction " }}}1 -let &cpo = s:cpo_save -unlet s:cpo_save - -" vim:set sw=2 sts=2 ts=8 et: +" vim:sw=2 sts=2 ts=8 fdm=marker et: endif diff --git a/indent/ecrystal.vim b/indent/ecrystal.vim index 0d474587..9826cd7c 100644 --- a/indent/ecrystal.vim +++ b/indent/ecrystal.vim @@ -71,8 +71,7 @@ let s:ecr_control_open = '<%%\@!-\=[=#]\@!' let s:ecr_comment_open = '<%%\@!-\=#' let s:ecr_indent_regex = - \ '\<\%(if\|unless\|else\|elsif\|case\|for\|when\|while\|until\|begin\|do\|rescue\|ensure\|' . - \ 'class\|module\|struct\|lib\|enum\|union\)\>' + \ '\<\%(if\|unless\|else\|elsif\|case\|when\|while\|until\|begin\|do\|rescue\|ensure\|\)\>' let s:ecr_dedent_regex = \ '\<\%(end\|else\|elsif\|when\|rescue\|ensure\)\>' diff --git a/indent/plantuml.vim b/indent/plantuml.vim index 0d17276e..0553e706 100644 --- a/indent/plantuml.vim +++ b/indent/plantuml.vim @@ -77,7 +77,7 @@ endfunction function! s:getIncIndent() abort " Function to determine the s:incIndent pattern return - \ '^\s*\%(class\|entity\|object\|interface\|partition\|rectangle\|enum\|namespace\|package\)\>.*{\s*$\|' . + \ '^\s*\%(artifact\|class\|cloud\|database\|entity\|enum\|file\|folder\|frame\|interface\|namespace\|node\|object\|package\|partition\|rectangle\|skinparam\|state\|storage\|together\)\>.*{\s*$\|' . \ '^\s*\%(loop\|alt\|opt\|group\|critical\|else\|legend\|box\|if\|while\|fork\|split\)\>\|' . \ '^\s*ref\>[^:]*$\|' . \ '^\s*[hr]\?note\>\%(\%("[^"]*" \<as\>\)\@![^:]\)*$\|' . |