diff options
author | Adam Stankiewicz <sheerun@sher.pl> | 2017-03-23 11:28:19 +0100 |
---|---|---|
committer | Adam Stankiewicz <sheerun@sher.pl> | 2017-03-23 11:28:28 +0100 |
commit | 0801eac01aab5940fc1e4409ba749383cc353bc2 (patch) | |
tree | 9034c9f6cd0c7592a09e6c65521c6948c3a983af /indent/ruby.vim | |
parent | 9f735b1fe77072e001a593f7f6660703bf4a8c9c (diff) | |
download | vim-polyglot-0801eac01aab5940fc1e4409ba749383cc353bc2.tar.gz vim-polyglot-0801eac01aab5940fc1e4409ba749383cc353bc2.zip |
Update
Diffstat (limited to 'indent/ruby.vim')
-rw-r--r-- | indent/ruby.vim | 808 |
1 files changed, 510 insertions, 298 deletions
diff --git a/indent/ruby.vim b/indent/ruby.vim index 84067fe9..8fa929be 100644 --- a/indent/ruby.vim +++ b/indent/ruby.vim @@ -20,6 +20,11 @@ if !exists('g:ruby_indent_access_modifier_style') let g:ruby_indent_access_modifier_style = 'normal' endif +if !exists('g:ruby_indent_assignment_style') + " Possible values: "variable", "hanging" + let g:ruby_indent_assignment_style = 'hanging' +endif + if !exists('g:ruby_indent_block_style') " Possible values: "expression", "do" let g:ruby_indent_block_style = 'expression' @@ -144,7 +149,507 @@ let s:block_continuation_regex = '^\s*[^])}\t ].*'.s:block_regex " Regex that describes a leading operator (only a method call's dot for now) let s:leading_operator_regex = '^\s*[.]' -" 2. Auxiliary Functions {{{1 +" 2. GetRubyIndent Function {{{1 +" ========================= + +function GetRubyIndent(...) + " 2.1. Setup {{{2 + " ---------- + + let indent_info = {} + + " The value of a single shift-width + if exists('*shiftwidth') + let indent_info.sw = shiftwidth() + else + let indent_info.sw = &sw + endif + + " For the current line, use the first argument if given, else 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. Could use clnum here. + let indent_info.col = col('.') + + " 2.2. Work on the current line {{{2 + " ----------------------------- + let indent_callback_names = [ + \ 's:AccessModifier', + \ 's:ClosingBracketOnEmptyLine', + \ 's:BlockComment', + \ 's:DeindentingKeyword', + \ 's:MultilineStringOrLineComment', + \ 's:ClosingHeredocDelimiter', + \ 's:LeadingOperator', + \ ] + + for callback_name in indent_callback_names +" Decho "Running: ".callback_name + let indent = call(function(callback_name), [indent_info]) + + if indent >= 0 +" Decho "Match: ".callback_name." indent=".indent." info=".string(indent_info) + return indent + endif + endfor + + " 2.3. Work on the previous line. {{{2 + " ------------------------------- + let indent_callback_names = [ + \ 's:EmptyInsideString', + \ 's:StartOfFile', + \ 's:AfterAccessModifier', + \ 's:ContinuedLine', + \ 's:AfterBlockOpening', + \ 's:AfterHangingSplat', + \ 's:AfterUnbalancedBracket', + \ 's:AfterLeadingOperator', + \ 's:AfterEndKeyword', + \ 's:AfterIndentKeyword', + \ ] + + " Previous line number + let indent_info.plnum = s:PrevNonBlankNonString(indent_info.clnum - 1) + let indent_info.pline = getline(indent_info.plnum) + + for callback_name in indent_callback_names +" Decho "Running: ".callback_name + let indent = call(function(callback_name), [indent_info]) + + if indent >= 0 +" Decho "Match: ".callback_name." indent=".indent." info=".string(indent_info) + return indent + endif + endfor + + " 2.4. Work on the MSL line. {{{2 + " -------------------------- + let indent_callback_names = [ + \ 's:PreviousNotMSL', + \ 's:IndentingKeywordInMSL', + \ 's:ContinuedHangingOperator', + \ ] + + " Most Significant line based on the previous one -- in case it's a + " contination of something above + let indent_info.plnum_msl = s:GetMSL(indent_info.plnum) + + for callback_name in indent_callback_names +" Decho "Running: ".callback_name + let indent = call(function(callback_name), [indent_info]) + + if indent >= 0 +" Decho "Match: ".callback_name." indent=".indent." info=".string(indent_info) + return indent + endif + endfor + + " }}}2 + + " By default, just return the previous line's indent +" Decho "Default case matched" + return indent(indent_info.plnum) +endfunction + +" 3. Indenting Logic Callbacks {{{1 +" ============================ + +function! s:AccessModifier(cline_info) + let info = a:cline_info + + " If this line is an access modifier keyword, align according to the closest + " class declaration. + if g:ruby_indent_access_modifier_style == 'indent' + if s:Match(info.clnum, s:access_modifier_regex) + let class_lnum = s:FindContainingClass() + if class_lnum > 0 + return indent(class_lnum) + info.sw + endif + endif + elseif g:ruby_indent_access_modifier_style == 'outdent' + if s:Match(info.clnum, s:access_modifier_regex) + let class_lnum = s:FindContainingClass() + if class_lnum > 0 + return indent(class_lnum) + endif + endif + endif + + return -1 +endfunction + +function! s:ClosingBracketOnEmptyLine(cline_info) + let info = a:cline_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(info.cline, '^\s*[]})]') + + if col > 0 && !s:IsInStringOrComment(info.clnum, col) + call cursor(info.clnum, col) + let closing_bracket = info.cline[col - 1] + let bracket_pair = strpart('(){}[]', stridx(')}]', closing_bracket) * 2, 2) + + if searchpair(escape(bracket_pair[0], '\['), '', bracket_pair[1], 'bW', s:skip_expr) > 0 + if closing_bracket == ')' && col('.') != col('$') - 1 + let ind = virtcol('.') - 1 + elseif g:ruby_indent_block_style == 'do' + let ind = indent(line('.')) + else " g:ruby_indent_block_style == 'expression' + let ind = indent(s:GetMSL(line('.'))) + endif + endif + + return ind + endif + + return -1 +endfunction + +function! s:BlockComment(cline_info) + " If we have a =begin or =end set indent to first column. + if match(a:cline_info.cline, '^\s*\%(=begin\|=end\)$') != -1 + return 0 + endif + return -1 +endfunction + +function! s:DeindentingKeyword(cline_info) + let info = a:cline_info + + " If we have a deindenting keyword, find its match and indent to its level. + " TODO: this is messy + if s:Match(info.clnum, s:ruby_deindent_keywords) + call cursor(info.clnum, 1) + + if searchpair(s:end_start_regex, s:end_middle_regex, s:end_end_regex, 'bW', + \ s:end_skip_expr) > 0 + let msl = s:GetMSL(line('.')) + let line = getline(line('.')) + + if s:IsAssignment(line, col('.')) && + \ strpart(line, col('.') - 1, 2) !~ 'do' + " assignment to case/begin/etc, on the same line + if g:ruby_indent_assignment_style == 'hanging' + " hanging indent + let ind = virtcol('.') - 1 + else + " align with variable + let ind = indent(line('.')) + endif + elseif g:ruby_indent_block_style == 'do' + " align to line of the "do", not to the MSL + let ind = indent(line('.')) + 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 + + return -1 +endfunction + +function! s:MultilineStringOrLineComment(cline_info) + let info = a:cline_info + + " If we are in a multi-line string or line-comment, don't do anything to it. + if s:IsInStringOrDocumentation(info.clnum, matchend(info.cline, '^\s*') + 1) + return indent(info.clnum) + endif + return -1 +endfunction + +function! s:ClosingHeredocDelimiter(cline_info) + let info = a:cline_info + + " If we are at the closing delimiter of a "<<" heredoc-style string, set the + " indent to 0. + if info.cline =~ '^\k\+\s*$' + \ && s:IsInStringDelimiter(info.clnum, 1) + \ && search('\V<<'.info.cline, 'nbW') > 0 + return 0 + endif + + return -1 +endfunction + +function! s:LeadingOperator(cline_info) + " 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 + endif + return -1 +endfunction + +function! s:EmptyInsideString(pline_info) + " 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 + + if info.cline =~ '^\s*$' && info.plnum != prevnonblank(info.clnum - 1) + return indent(prevnonblank(info.clnum)) + endif + return -1 +endfunction + +function! s:StartOfFile(pline_info) + " At the start of the file use zero indent. + if a:pline_info.plnum == 0 + return 0 + endif + return -1 +endfunction + +function! s:AfterAccessModifier(pline_info) + let info = a:pline_info + + if g:ruby_indent_access_modifier_style == 'indent' + " If the previous line was a private/protected keyword, add a + " level of indent. + if s:Match(info.plnum, s:indent_access_modifier_regex) + return indent(info.plnum) + info.sw + endif + elseif g:ruby_indent_access_modifier_style == 'outdent' + " If the previous line was a private/protected/public keyword, add + " a level of indent, since the keyword has been out-dented. + if s:Match(info.plnum, s:access_modifier_regex) + return indent(info.plnum) + info.sw + endif + endif + return -1 +endfunction + +" Example: +" +" if foo || bar || +" baz || bing +" puts "foo" +" end +" +function! s:ContinuedLine(pline_info) + let info = a:pline_info + + let col = s:Match(info.plnum, s:ruby_indent_keywords) + if s:Match(info.plnum, s:continuable_regex) && + \ s:Match(info.plnum, s:continuation_regex) + if col > 0 && s:IsAssignment(info.pline, col) + if g:ruby_indent_assignment_style == 'hanging' + " hanging indent + let ind = col - 1 + else + " align with variable + let ind = indent(info.plnum) + endif + else + let ind = indent(s:GetMSL(info.plnum)) + endif + return ind + info.sw + info.sw + endif + return -1 +endfunction + +function! s:AfterBlockOpening(pline_info) + let info = a:pline_info + + " If the previous line ended with a block opening, add a level of indent. + if s:Match(info.plnum, s:block_regex) + if g:ruby_indent_block_style == 'do' + " don't align to the msl, align to the "do" + let ind = indent(info.plnum) + info.sw + else + let plnum_msl = s:GetMSL(info.plnum) + + if getline(plnum_msl) =~ '=\s*\(#.*\)\=$' + " in the case of assignment to the msl, align to the starting line, + " not to the msl + let ind = indent(info.plnum) + info.sw + else + let ind = indent(plnum_msl) + info.sw + endif + endif + + return ind + endif + + return -1 +endfunction + +function! s:AfterLeadingOperator(pline_info) + " 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) + return indent(s:GetMSL(a:pline_info.plnum)) + endif + return -1 +endfunction + +function! s:AfterHangingSplat(pline_info) + let info = a:pline_info + + " If the previous line ended with the "*" of a splat, add a level of indent + if info.pline =~ s:splat_regex + return indent(info.plnum) + info.sw + endif + return -1 +endfunction + +function! s:AfterUnbalancedBracket(pline_info) + let info = a:pline_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 info.pline =~ '[[({]' || info.pline =~ '[])}]\s*\%(#.*\)\=$' + let [opening, closing] = s:ExtraBrackets(info.plnum) + + if opening.pos != -1 + if opening.type == '(' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 + if col('.') + 1 == col('$') + return indent(info.plnum) + info.sw + else + return virtcol('.') + endif + else + let nonspace = matchend(info.pline, '\S', opening.pos + 1) - 1 + return nonspace > 0 ? nonspace : indent(info.plnum) + info.sw + endif + elseif closing.pos != -1 + call cursor(info.plnum, closing.pos + 1) + normal! % + + if s:Match(line('.'), s:ruby_indent_keywords) + return indent('.') + info.sw + else + return indent(s:GetMSL(line('.'))) + endif + else + call cursor(info.clnum, info.col) + end + endif + + return -1 +endfunction + +function! s:AfterEndKeyword(pline_info) + let info = a:pline_info + " If the previous line ended with an "end", match that "end"s beginning's + " indent. + let col = s:Match(info.plnum, '\%(^\|[^.:@$]\)\<end\>\s*\%(#.*\)\=$') + if col > 0 + call cursor(info.plnum, col) + if searchpair(s:end_start_regex, '', s:end_end_regex, 'bW', + \ s:end_skip_expr) > 0 + let n = line('.') + let ind = indent('.') + let msl = s:GetMSL(n) + if msl != n + let ind = indent(msl) + end + return ind + endif + end + return -1 +endfunction + +function! s:AfterIndentKeyword(pline_info) + let info = a:pline_info + let col = s:Match(info.plnum, s:ruby_indent_keywords) + + if col > 0 + call cursor(info.plnum, col) + let ind = virtcol('.') - 1 + info.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 s:Match(info.plnum, s:end_end_regex) + let ind = indent('.') + elseif s:IsAssignment(info.pline, col) + if g:ruby_indent_assignment_style == 'hanging' + " hanging indent + let ind = col + info.sw - 1 + else + " align with variable + let ind = indent(info.plnum) + info.sw + endif + endif + return ind + endif + + return -1 +endfunction + +function! s:PreviousNotMSL(msl_info) + let info = a:msl_info + + " If the previous line wasn't a MSL + if info.plnum != info.plnum_msl + " If previous line ends bracket and begins non-bracket continuation decrease indent by 1. + if s:Match(info.plnum, s:bracket_switch_continuation_regex) + " TODO (2016-10-07) Wrong/unused? How could it be "1"? + return indent(info.plnum) - 1 + " If previous line is a continuation return its indent. + " TODO: the || s:IsInString() thing worries me a bit. + elseif s:Match(info.plnum, s:non_bracket_continuation_regex) || s:IsInString(info.plnum, strlen(line)) + return indent(info.plnum) + endif + endif + + return -1 +endfunction + +function! s:IndentingKeywordInMSL(msl_info) + 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 + " module Foo; class Bar; end + let col = s:Match(info.plnum_msl, s:ruby_indent_keywords) + if col > 0 + let ind = indent(info.plnum_msl) + info.sw + if s:Match(info.plnum_msl, s:end_end_regex) + let ind = ind - info.sw + elseif s:IsAssignment(getline(info.plnum_msl), col) + if g:ruby_indent_assignment_style == 'hanging' + " hanging indent + let ind = col + info.sw - 1 + else + " align with variable + let ind = indent(info.plnum_msl) + info.sw + endif + endif + return ind + endif + return -1 +endfunction + +function! s:ContinuedHangingOperator(msl_info) + let info = a:msl_info + + " If the previous line ended with [*+/.,-=], but wasn't a block ending or a + " closing bracket, indent one extra level. + if s:Match(info.plnum_msl, s:non_bracket_continuation_regex) && !s:Match(info.plnum_msl, '^\s*\([\])}]\|end\)') + if info.plnum_msl == info.plnum + let ind = indent(info.plnum_msl) + info.sw + else + let ind = indent(info.plnum_msl) + endif + return ind + endif + + return -1 +endfunction + +" 4. Auxiliary Functions {{{1 " ====================== " Check if the character at lnum:col is inside a string, comment, or is ascii. @@ -167,6 +672,10 @@ function s:IsInStringDelimiter(lnum, col) return synIDattr(synID(a:lnum, a:col, 1), 'name') == 'rubyStringDelimiter' endfunction +function s:IsAssignment(str, pos) + 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) let in_block = 0 @@ -196,7 +705,6 @@ endfunction function s:GetMSL(lnum) " Start on the line we're at and use its indent. let msl = a:lnum - let msl_body = getline(msl) let lnum = s:PrevNonBlankNonString(a:lnum - 1) while lnum > 0 " If we have a continuation line, or we're in a string, use line as MSL. @@ -293,7 +801,6 @@ function s:GetMSL(lnum) endif endif - let msl_body = getline(msl) let lnum = s:PrevNonBlankNonString(lnum - 1) endwhile return msl @@ -398,301 +905,6 @@ function! s:FindContainingClass() return 0 endfunction -" 3. GetRubyIndent Function {{{1 -" ========================= - -function GetRubyIndent(...) - " 3.1. Setup {{{2 - " ---------- - - " The value of a single shift-width - if exists('*shiftwidth') - let sw = shiftwidth() - else - let sw = &sw - endif - - " For the current line, use the first argument if given, else v:lnum - let clnum = a:0 ? a:1 : v:lnum - - " Set up variables for restoring position in file. Could use clnum here. - let vcol = col('.') - - " 3.2. Work on the current line {{{2 - " ----------------------------- - - " Get the current line. - let line = getline(clnum) - let ind = -1 - - " If this line is an access modifier keyword, align according to the closest - " class declaration. - if g:ruby_indent_access_modifier_style == 'indent' - if s:Match(clnum, s:access_modifier_regex) - let class_line = s:FindContainingClass() - if class_line > 0 - return indent(class_line) + sw - endif - endif - elseif g:ruby_indent_access_modifier_style == 'outdent' - if s:Match(clnum, s:access_modifier_regex) - let class_line = s:FindContainingClass() - if class_line > 0 - return indent(class_line) - endif - endif - endif - - " If we got a closing bracket on an empty line, find its match and indent - " according to it. For parentheses we indent to its column - 1, for the - " others we indent to the containing line's MSL's level. Return -1 if fail. - let col = matchend(line, '^\s*[]})]') - if col > 0 && !s:IsInStringOrComment(clnum, col) - call cursor(clnum, col) - let bs = strpart('(){}[]', stridx(')}]', line[col - 1]) * 2, 2) - if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0 - if line[col-1]==')' && col('.') != col('$') - 1 - let ind = virtcol('.') - 1 - elseif g:ruby_indent_block_style == 'do' - let ind = indent(line('.')) - else " g:ruby_indent_block_style == 'expression' - let ind = indent(s:GetMSL(line('.'))) - endif - endif - return ind - endif - - " If we have a =begin or =end set indent to first column. - if match(line, '^\s*\%(=begin\|=end\)$') != -1 - return 0 - endif - - " If we have a deindenting keyword, find its match and indent to its level. - " TODO: this is messy - if s:Match(clnum, s:ruby_deindent_keywords) - call cursor(clnum, 1) - if searchpair(s:end_start_regex, s:end_middle_regex, s:end_end_regex, 'bW', - \ s:end_skip_expr) > 0 - let msl = s: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 g:ruby_indent_block_style == 'do' - " align to line of the "do", not to the MSL - let ind = indent(line('.')) - 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 or line-comment, don't do anything to it. - if s:IsInStringOrDocumentation(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*$' - \ && s:IsInStringDelimiter(clnum, 1) - \ && search('\V<<'.line, 'nbW') > 0 - return 0 - endif - - " If the current line starts with a leading operator, add a level of indent. - if s:Match(clnum, s:leading_operator_regex) - return indent(s:GetMSL(clnum)) + sw - endif - - " 3.3. Work on the previous line. {{{2 - " ------------------------------- - - " Find a non-blank, non-multi-line string line above the current line. - let lnum = s: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) - - if g:ruby_indent_access_modifier_style == 'indent' - " If the previous line was a private/protected keyword, add a - " level of indent. - if s:Match(lnum, s:indent_access_modifier_regex) - return indent(lnum) + sw - endif - elseif g:ruby_indent_access_modifier_style == 'outdent' - " If the previous line was a private/protected/public keyword, add - " a level of indent, since the keyword has been out-dented. - if s:Match(lnum, s:access_modifier_regex) - return indent(lnum) + sw - endif - endif - - if s:Match(lnum, s:continuable_regex) && s:Match(lnum, s:continuation_regex) - return indent(s:GetMSL(lnum)) + sw + sw - endif - - " If the previous line ended with a block opening, add a level of indent. - if s:Match(lnum, s:block_regex) - let msl = s:GetMSL(lnum) - - if g:ruby_indent_block_style == 'do' - " don't align to the msl, align to the "do" - let ind = indent(lnum) + sw - elseif getline(msl) =~ '=\s*\(#.*\)\=$' - " in the case of assignment to the msl, align to the starting line, - " not to the msl - let ind = indent(lnum) + sw - else - let ind = indent(msl) + sw - endif - return ind - endif - - " If the previous line started with a leading operator, use its MSL's level - " of indent - if s:Match(lnum, s:leading_operator_regex) - return indent(s:GetMSL(lnum)) - endif - - " If the previous line ended with the "*" of a splat, add a level of indent - if line =~ s:splat_regex - return indent(lnum) + sw - endif - - " 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] = s:ExtraBrackets(lnum) - - if opening.pos != -1 - if opening.type == '(' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 - if col('.') + 1 == col('$') - return ind + sw - else - return virtcol('.') - endif - else - let nonspace = matchend(line, '\S', opening.pos + 1) - 1 - return nonspace > 0 ? nonspace : ind + sw - endif - elseif closing.pos != -1 - call cursor(lnum, closing.pos + 1) - normal! % - - if s:Match(line('.'), s:ruby_indent_keywords) - return indent('.') + sw - else - return indent(s:GetMSL(line('.'))) - 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 = s:Match(lnum, '\%(^\|[^.:@$]\)\<end\>\s*\%(#.*\)\=$') - if col > 0 - call cursor(lnum, col) - if searchpair(s:end_start_regex, '', s:end_end_regex, 'bW', - \ s:end_skip_expr) > 0 - let n = line('.') - let ind = indent('.') - let msl = s:GetMSL(n) - if msl != n - let ind = indent(msl) - end - return ind - endif - end - - let col = s:Match(lnum, s:ruby_indent_keywords) - if col > 0 - call cursor(lnum, col) - let ind = virtcol('.') - 1 + 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 s:Match(lnum, s:end_end_regex) - let ind = indent('.') - endif - return ind - endif - - " 3.4. 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 = s: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 s:Match(p_lnum, s:bracket_switch_continuation_regex) - return ind - 1 - " If previous line is a continuation return its indent. - " TODO: the || s:IsInString() thing worries me a bit. - elseif s:Match(p_lnum, s:non_bracket_continuation_regex) || s:IsInString(p_lnum,strlen(line)) - return ind - endif - endif - - " Set up more variables, now that we know we wasn't continuation bound. - let line = getline(lnum) - let msl_ind = indent(lnum) - - " 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 s:Match(lnum, s:ruby_indent_keywords) - let ind = msl_ind + sw - if s:Match(lnum, s:end_end_regex) - let ind = ind - sw - endif - return ind - endif - - " If the previous line ended with [*+/.,-=], but wasn't a block ending or a - " closing bracket, indent one extra level. - if s:Match(lnum, s:non_bracket_continuation_regex) && !s:Match(lnum, '^\s*\([\])}]\|end\)') - if lnum == p_lnum - let ind = msl_ind + sw - else - let ind = msl_ind - endif - return ind - endif - - " }}}2 - - return ind -endfunction - " }}}1 let &cpo = s:cpo_save |