diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2017-04-29 01:41:29 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-29 01:41:29 +0200 |
commit | 9f6d693e263b617cd1a1772e42911cd5a0b1675b (patch) | |
tree | 593d3c9d968be92bc1ed8a445e6856079ef546ed /runtime/indent | |
parent | 59be0b42806c39131f76f89c554f0a24e82514a8 (diff) | |
parent | 53419673154a98b705cfa80590099a247cc9df49 (diff) | |
download | rneovim-9f6d693e263b617cd1a1772e42911cd5a0b1675b.tar.gz rneovim-9f6d693e263b617cd1a1772e42911cd5a0b1675b.tar.bz2 rneovim-9f6d693e263b617cd1a1772e42911cd5a0b1675b.zip |
Merge #6613 from justinmk/vim-patches
Diffstat (limited to 'runtime/indent')
-rw-r--r-- | runtime/indent/cdl.vim | 2 | ||||
-rw-r--r-- | runtime/indent/cucumber.vim | 21 | ||||
-rw-r--r-- | runtime/indent/eruby.vim | 43 | ||||
-rw-r--r-- | runtime/indent/fortran.vim | 15 | ||||
-rw-r--r-- | runtime/indent/gitconfig.vim | 9 | ||||
-rw-r--r-- | runtime/indent/haml.vim | 7 | ||||
-rw-r--r-- | runtime/indent/html.vim | 2 | ||||
-rw-r--r-- | runtime/indent/liquid.vim | 11 | ||||
-rw-r--r-- | runtime/indent/mf.vim | 6 | ||||
-rw-r--r-- | runtime/indent/mp.vim | 483 | ||||
-rw-r--r-- | runtime/indent/ruby.vim | 232 | ||||
-rw-r--r-- | runtime/indent/sass.vim | 6 |
12 files changed, 591 insertions, 246 deletions
diff --git a/runtime/indent/cdl.vim b/runtime/indent/cdl.vim index db2b9052b2..5ec2a7b21a 100644 --- a/runtime/indent/cdl.vim +++ b/runtime/indent/cdl.vim @@ -16,7 +16,7 @@ if exists("*CdlGetIndent") "finish endif -" find out if an "...=..." expresion its an asignment (or a conditional) +" find out if an "...=..." expresion is an assignment (or a conditional) " it scans 'line' first, and then the previos lines fun! CdlAsignment(lnum, line) let f = -1 diff --git a/runtime/indent/cucumber.vim b/runtime/indent/cucumber.vim index 965c7786ed..999b8d6a76 100644 --- a/runtime/indent/cucumber.vim +++ b/runtime/indent/cucumber.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: Cucumber " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:did_indent") finish @@ -27,6 +27,7 @@ function! GetCucumberIndent() let line = getline(prevnonblank(v:lnum-1)) let cline = getline(v:lnum) let nline = getline(nextnonblank(v:lnum+1)) + let sw = exists('*shiftwidth') ? shiftwidth() : &sw let syn = s:syn(prevnonblank(v:lnum-1)) let csyn = s:syn(v:lnum) let nsyn = s:syn(nextnonblank(v:lnum+1)) @@ -35,38 +36,38 @@ function! GetCucumberIndent() return 0 elseif csyn ==# 'cucumberExamples' || cline =~# '^\s*\%(Examples\|Scenarios\):' " examples heading - return 2 * &sw + return 2 * sw elseif csyn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || cline =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):' " background, scenario or outline heading - return &sw + return sw elseif syn ==# 'cucumberFeature' || line =~# '^\s*Feature:' " line after feature heading - return &sw + return sw elseif syn ==# 'cucumberExamples' || line =~# '^\s*\%(Examples\|Scenarios\):' " line after examples heading - return 3 * &sw + return 3 * sw elseif syn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || line =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):' " line after background, scenario or outline heading - return 2 * &sw + return 2 * sw elseif cline =~# '^\s*[@#]' && (nsyn == 'cucumberFeature' || nline =~# '^\s*Feature:' || indent(prevnonblank(v:lnum-1)) <= 0) " tag or comment before a feature heading return 0 elseif cline =~# '^\s*@' " other tags - return &sw + return sw elseif cline =~# '^\s*[#|]' && line =~# '^\s*|' " mid-table " preserve indent return indent(prevnonblank(v:lnum-1)) elseif cline =~# '^\s*|' && line =~# '^\s*[^|]' " first line of a table, relative indent - return indent(prevnonblank(v:lnum-1)) + &sw + return indent(prevnonblank(v:lnum-1)) + sw elseif cline =~# '^\s*[^|]' && line =~# '^\s*|' " line after a table, relative unindent - return indent(prevnonblank(v:lnum-1)) - &sw + return indent(prevnonblank(v:lnum-1)) - sw elseif cline =~# '^\s*#' && getline(v:lnum-1) =~ '^\s*$' && (nsyn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || nline =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):') " comments on scenarios - return &sw + return sw endif return indent(prevnonblank(v:lnum-1)) endfunction diff --git a/runtime/indent/eruby.vim b/runtime/indent/eruby.vim index 80cab7000e..afabd4fe5b 100644 --- a/runtime/indent/eruby.vim +++ b/runtime/indent/eruby.vim @@ -19,6 +19,9 @@ else endif unlet! b:did_indent +" Force HTML indent to not keep state. +let b:html_indent_usestate = 0 + if &l:indentexpr == '' if &l:cindent let &l:indentexpr = 'cindent(v:lnum)' @@ -38,7 +41,18 @@ 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') + let sw = shiftwidth() + else + let sw = &sw + endif + if a:0 && a:1 == '.' let v:lnum = line('.') elseif a:0 && a:1 =~ '^\d' @@ -52,31 +66,44 @@ function! GetErubyIndent(...) let ind = GetRubyIndent(v:lnum) else exe "let ind = ".b:eruby_subtype_indentexpr + + " Workaround for Andy Wokula's HTML indent. This should be removed after + " some time, since the newest version is fixed in a different way. + if b:eruby_subtype_indentexpr =~# '^HtmlIndent(' + \ && exists('b:indent') + \ && type(b:indent) == type({}) + \ && has_key(b:indent, 'lnum') + " Force HTML indent to not keep state + let b:indent.lnum = -1 + endif endif let lnum = prevnonblank(v:lnum-1) let line = getline(lnum) let cline = getline(v:lnum) if cline =~# '^\s*<%[-=]\=\s*\%(}\|end\|else\|\%(ensure\|rescue\|elsif\|when\).\{-\}\)\s*\%([-=]\=%>\|$\)' - let ind = ind - &sw + let ind = ind - sw endif if line =~# '\S\s*<%[-=]\=\s*\%(}\|end\).\{-\}\s*\%([-=]\=%>\|$\)' - let ind = ind - &sw + let ind = ind - sw endif if line =~# '\%({\|\<do\)\%(\s*|[^|]*|\)\=\s*[-=]\=%>' - let ind = ind + &sw + let ind = ind + sw elseif line =~# '<%[-=]\=\s*\%(module\|class\|def\|if\|for\|while\|until\|else\|elsif\|case\|when\|unless\|begin\|ensure\|rescue\)\>.*%>' - let ind = ind + &sw + let ind = ind + sw endif if line =~# '^\s*<%[=#-]\=\s*$' && cline !~# '^\s*end\>' - let ind = ind + &sw + let ind = ind + sw endif - if line !~# '^\s*<%' && line =~# '%>\s*$' - let ind = ind - &sw + if line !~# '^\s*<%' && line =~# '%>\s*$' && line !~# '^\s*end\>' + let ind = ind - sw endif if cline =~# '^\s*[-=]\=%>\s*$' - let ind = ind - &sw + let ind = ind - sw endif return ind endfunction +let &cpo = s:cpo_sav +unlet! s:cpo_sav + " vim:set sw=2 sts=2 ts=8 noet: diff --git a/runtime/indent/fortran.vim b/runtime/indent/fortran.vim index be2f0866d5..c9bee78a6e 100644 --- a/runtime/indent/fortran.vim +++ b/runtime/indent/fortran.vim @@ -1,11 +1,12 @@ " Vim indent file " Language: Fortran 2008 (and older: Fortran 2003, 95, 90, and 77) -" Version: 0.45 -" Last Change: 2016 Aug. 18 +" Version: 0.46 +" Last Change: 2016 Sep. 27 " Maintainer: Ajit J. Thakkar <ajit@unb.ca>; <http://www2.unb.ca/~ajit/> " Usage: For instructions, do :help fortran-indent from Vim " Credits: -" Useful suggestions were made by: Albert Oliver Serra and Takuya Fujiwara. +" Useful suggestions were made, in chronological order, by: +" Albert Oliver Serra, Takuya Fujiwara and Philipp Edelmann. " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -121,7 +122,8 @@ function FortranGetIndent(lnum) let prefix='\(\(pure\|impure\|elemental\|recursive\)\s\+\)\{,2}' let type='\(\(integer\|real\|double\s\+precision\|complex\|logical' \.'\|character\|type\|class\)\s*\S*\s\+\)\=' - if prevstat =~? '^\s*\(module\|contains\/submodule\|program\)\>' + if prevstat =~? '^\s*\(contains\|submodule\|program\)\>' + \ ||prevstat =~? '^\s*'.'module\>\(\s*\procedure\)\@!' \ ||prevstat =~? '^\s*'.prefix.'subroutine\>' \ ||prevstat =~? '^\s*'.prefix.type.'function\>' \ ||prevstat =~? '^\s*'.type.prefix.'function\>' @@ -129,7 +131,7 @@ function FortranGetIndent(lnum) endif if getline(v:lnum) =~? '^\s*contains\>' \ ||getline(v:lnum)=~? '^\s*end\s*' - \ .'\(function\|subroutine\|module\/submodule\|program\)\>' + \ .'\(function\|subroutine\|module\|submodule\|program\)\>' let ind = ind - shiftwidth() endif endif @@ -152,9 +154,6 @@ function FortranGetIndent(lnum) if prevstat =~ '&\s*$' && prev2stat !~ '&\s*$' let ind = ind + shiftwidth() endif - if prevstat =~ '&\s*$' && prevstat =~ '\<else\s*if\>' - let ind = ind - shiftwidth() - endif "Line after last continuation line if prevstat !~ '&\s*$' && prev2stat =~ '&\s*$' && prevstat !~? '\<then\>' let ind = ind - shiftwidth() diff --git a/runtime/indent/gitconfig.vim b/runtime/indent/gitconfig.vim index 7d5d44b779..480c96d1b9 100644 --- a/runtime/indent/gitconfig.vim +++ b/runtime/indent/gitconfig.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: git config file " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:did_indent") finish @@ -20,17 +20,18 @@ if exists("*GetGitconfigIndent") endif function! GetGitconfigIndent() + let sw = exists('*shiftwidth') ? shiftwidth() : &sw let line = getline(prevnonblank(v:lnum-1)) let cline = getline(v:lnum) if line =~ '\\\@<!\%(\\\\\)*\\$' " odd number of slashes, in a line continuation - return 2 * &sw + return 2 * sw elseif cline =~ '^\s*\[' return 0 elseif cline =~ '^\s*\a' - return &sw + return sw elseif cline == '' && line =~ '^\[' - return &sw + return sw else return -1 endif diff --git a/runtime/indent/haml.vim b/runtime/indent/haml.vim index c47a8a59c7..c3935af9e9 100644 --- a/runtime/indent/haml.vim +++ b/runtime/indent/haml.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: Haml " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:did_indent") finish @@ -37,10 +37,11 @@ function! GetHamlIndent() let line = substitute(line,'^\s\+','','') let indent = indent(lnum) let cindent = indent(v:lnum) + let sw = exists('*shiftwidth') ? shiftwidth() : &sw if cline =~# '\v^-\s*%(elsif|else|when)>' - let indent = cindent < indent ? cindent : indent - &sw + let indent = cindent < indent ? cindent : indent - sw endif - let increase = indent + &sw + let increase = indent + sw if indent == indent(lnum) let indent = cindent <= indent ? -1 : increase endif diff --git a/runtime/indent/html.vim b/runtime/indent/html.vim index 828bc3120b..13adaae54c 100644 --- a/runtime/indent/html.vim +++ b/runtime/indent/html.vim @@ -749,7 +749,7 @@ func! s:CssPrevNonComment(lnum, stopline) while 1 let ccol = match(getline(lnum), '\*/') if ccol < 0 - " No comment end thus its something else. + " No comment end thus it's something else. return lnum endif call cursor(lnum, ccol + 1) diff --git a/runtime/indent/liquid.vim b/runtime/indent/liquid.vim index 01e7223696..f8e1c83079 100644 --- a/runtime/indent/liquid.vim +++ b/runtime/indent/liquid.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: Liquid " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists('b:did_indent') finish @@ -54,9 +54,10 @@ function! GetLiquidIndent(...) let line = substitute(line,'\C^\%(\s*{%\s*end\w*\s*%}\)\+','','') let line .= matchstr(cline,'\C^\%(\s*{%\s*end\w*\s*%}\)\+') let cline = substitute(cline,'\C^\%(\s*{%\s*end\w*\s*%}\)\+','','') - let ind += &sw * s:count(line,'{%\s*\%(if\|elsif\|else\|unless\|ifchanged\|case\|when\|for\|empty\|tablerow\|capture\)\>') - let ind -= &sw * s:count(line,'{%\s*end\%(if\|unless\|ifchanged\|case\|for\|tablerow\|capture\)\>') - let ind -= &sw * s:count(cline,'{%\s*\%(elsif\|else\|when\|empty\)\>') - let ind -= &sw * s:count(cline,'{%\s*end\w*$') + let sw = exists('*shiftwidth') ? shiftwidth() : &sw + let ind += sw * s:count(line,'{%\s*\%(if\|elsif\|else\|unless\|ifchanged\|case\|when\|for\|empty\|tablerow\|capture\)\>') + let ind -= sw * s:count(line,'{%\s*end\%(if\|unless\|ifchanged\|case\|for\|tablerow\|capture\)\>') + let ind -= sw * s:count(cline,'{%\s*\%(elsif\|else\|when\|empty\)\>') + let ind -= sw * s:count(cline,'{%\s*end\w*$') return ind endfunction diff --git a/runtime/indent/mf.vim b/runtime/indent/mf.vim new file mode 100644 index 0000000000..88737f4e9f --- /dev/null +++ b/runtime/indent/mf.vim @@ -0,0 +1,6 @@ +" METAFONT indent file +" Language: METAFONT +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Last Change: 2016 Oct 1 + +runtime! indent/mp.vim diff --git a/runtime/indent/mp.vim b/runtime/indent/mp.vim index a118eb8b60..86fa2539c1 100644 --- a/runtime/indent/mp.vim +++ b/runtime/indent/mp.vim @@ -1,56 +1,19 @@ " MetaPost indent file -" Language: MetaPost -" Maintainer: Eugene Minkovskii <emin@mccme.ru> -" Last Change: 2012 May 18 -" Version: 0.1 -" ========================================================================== - -" Identation Rules: {{{1 -" First of all, MetaPost language don't expect any identation rules. -" This screept need for you only if you (not MetaPost) need to do -" exactly code. If you don't need to use indentation, see -" :help filetype-indent-off -" -" Note: Every rules of identation in MetaPost or TeX languages (and in some -" other of course) is very subjective. I can release only my vision of this -" promlem. -" -" .......................................................................... -" Example of correct (by me) identation {{{2 -" shiftwidth=4 -" ========================================================================== -" for i=0 upto 99: -" z[i] = (0,1u) rotated (i*360/100); -" endfor -" draw z0 -- z10 -- z20 -" withpen ... % <- 2sw because breaked line -" withcolor ...; % <- same as previous -" draw z0 for i=1 upto 99: -" -- z[i] % <- 1sw from left end of 'for' satement -" endfor withpen ... % <- 0sw from left end of 'for' satement -" withcolor ...; % <- 2sw because breaked line -" draw if One: % <- This is internal if (like 'for' above) -" one -" elsif Other: -" other -" fi withpen ...; -" if one: % <- This is external if -" draw one; -" elseif other: -" draw other; -" fi -" draw z0; draw z1; -" }}} -" }}} +" Language: MetaPost +" Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> +" Former Maintainers: Eugene Minkovskii <emin@mccme.ru> +" Last Change: 2016 Oct 2, 4:13pm +" Version: 0.2 -" Only load this indent file when no other was loaded. if exists("b:did_indent") finish endif let b:did_indent = 1 setlocal indentexpr=GetMetaPostIndent() -setlocal indentkeys+=;,<:>,=if,=for,=def,=end,=else,=fi +setlocal indentkeys+==end,=else,=fi,=fill,0),0] + +let b:undo_indent = "setl indentkeys< indentexpr<" " Only define the function once. if exists("*GetMetaPostIndent") @@ -59,151 +22,337 @@ endif let s:keepcpo= &cpo set cpo&vim -" Auxiliary Definitions: {{{1 -function! MetaNextNonblankNoncomment(pos) - " Like nextnonblank() but ignore comment lines - let tmp = nextnonblank(a:pos) - while tmp && getline(tmp) =~ '^\s*%' - let tmp = nextnonblank(tmp+1) +function GetMetaPostIndent() + let ignorecase_save = &ignorecase + try + let &ignorecase = 0 + return GetMetaPostIndentIntern() + finally + let &ignorecase = ignorecase_save + endtry +endfunc + +" Regexps {{{ +" Note: the next three variables are made global so that a user may add +" further keywords. +" +" Example: +" +" Put these in ~/.vim/after/indent/mp.vim +" +" let g:mp_open_tag .= '\|\<begintest\>' +" let g:mp_close_tag .= '\|\<endtest\>' + +" Expressions starting indented blocks +let g:mp_open_tag = '' + \ . '\<if\>' + \ . '\|\<else\%[if]\>' + \ . '\|\<for\%(\|ever\|suffixes\)\>' + \ . '\|\<begingroup\>' + \ . '\|\<\%(\|var\|primary\|secondary\|tertiary\)def\>' + \ . '\|^\s*\<begin\%(fig\|graph\|glyph\|char\|logochar\)\>' + \ . '\|[([{]' + +" Expressions ending indented blocks +let g:mp_close_tag = '' + \ . '\<fi\>' + \ . '\|\<else\%[if]\>' + \ . '\|\<end\%(\|for\|group\|def\|fig\|char\|glyph\|graph\)\>' + \ . '\|[)\]}]' + +" Statements that may span multiple lines and are ended by a semicolon. To +" keep this list short, statements that are unlikely to be very long or are +" not very common (e.g., keywords like `interim` or `showtoken`) are not +" included. +" +" The regex for assignments and equations (the last branch) is tricky, because +" it must not match things like `for i :=`, `if a=b`, `def...=`, etc... It is +" not perfect, but it works reasonably well. +let g:mp_statement = '' + \ . '\<\%(\|un\|cut\)draw\>' + \ . '\|\<\%(\|un\)fill\%[draw]\>' + \ . '\|\<draw\%(dbl\)\=arrow\>' + \ . '\|\<clip\>' + \ . '\|\<addto\>' + \ . '\|\<save\>' + \ . '\|\<setbounds\>' + \ . '\|\<message\>' + \ . '\|\<errmessage\>' + \ . '\|\<errhelp\>' + \ . '\|\<fontmapline\>' + \ . '\|\<pickup\>' + \ . '\|\<show\>' + \ . '\|\<special\>' + \ . '\|\<write\>' + \ . '\|\%(^\|;\)\%([^;=]*\%('.g:mp_open_tag.'\)\)\@!.\{-}:\==' + +" A line ends with zero or more spaces, possibly followed by a comment. +let s:eol = '\s*\%($\|%\)' +" }}} + +" Auxiliary functions {{{ +" Returns 1 if (0-based) position immediately preceding `pos` in `line` is +" inside a string or a comment; returns 0 otherwise. + +" This is the function that is called more often when indenting, so it is +" critical that it is efficient. The method we use is significantly faster +" than using syntax attributes, and more general (it does not require +" syntax_items). It is also faster than using a single regex matching an even +" number of quotes. It helps that MetaPost strings cannot span more than one +" line and cannot contain escaped quotes. +function! s:CommentOrString(line, pos) + let in_string = 0 + let q = stridx(a:line, '"') + let c = stridx(a:line, '%') + while q >= 0 && q < a:pos + if c >= 0 && c < q + if in_string " Find next percent symbol + let c = stridx(a:line, '%', q + 1) + else " Inside comment + return 1 + endif + endif + let in_string = 1 - in_string + let q = stridx(a:line, '"', q + 1) " Find next quote endwhile - return tmp + return in_string || (c >= 0 && c <= a:pos) endfunction -function! MetaPrevNonblankNoncomment(pos) - " Like prevnonblank() but ignore comment lines - let tmp = prevnonblank(a:pos) - while tmp && getline(tmp) =~ '^\s*%' - let tmp = prevnonblank(tmp-1) +" Find the first non-comment non-blank line before the current line. +function! s:PrevNonBlankNonComment(lnum) + let l:lnum = prevnonblank(a:lnum - 1) + while getline(l:lnum) =~# '^\s*%' + let l:lnum = prevnonblank(l:lnum - 1) endwhile - return tmp + return l:lnum endfunction -function! MetaSearchNoncomment(pattern, ...) - " Like search() but ignore commented areas - if a:0 - let flags = a:1 - elseif &wrapscan - let flags = "w" - else - let flags = "W" - endif - let cl = line(".") - let cc = col(".") - let tmp = search(a:pattern, flags) - while tmp && synIDattr(synID(line("."), col("."), 1), "name") =~ - \ 'm[fp]\(Comment\|TeXinsert\|String\)' - let tmp = search(a:pattern, flags) +" Returns true if the last tag appearing in the line is an open tag; returns +" false otherwise. +function! s:LastTagIsOpen(line) + let o = s:LastValidMatchEnd(a:line, g:mp_open_tag, 0) + if o == - 1 | return v:false | endif + return s:LastValidMatchEnd(a:line, g:mp_close_tag, o) < 0 +endfunction + +" A simple, efficient and quite effective heuristics is used to test whether +" a line should cause the next line to be indented: count the "opening tags" +" (if, for, def, ...) in the line, count the "closing tags" (endif, endfor, +" ...) in the line, and compute the difference. We call the result the +" "weight" of the line. If the weight is positive, then the next line should +" most likely be indented. Note that `else` and `elseif` are both opening and +" closing tags, so they "cancel out" in almost all cases, the only exception +" being a leading `else[if]`, which is counted as an opening tag, but not as +" a closing tag (so that, for instance, a line containing a single `else:` +" will have weight equal to one, not zero). We do not treat a trailing +" `else[if]` in any special way, because lines ending with an open tag are +" dealt with separately before this function is called (see +" GetMetaPostIndentIntern()). +" +" Example: +" +" forsuffixes $=a,b: if x.$ = y.$ : draw else: fill fi +" % This line will be indented because |{forsuffixes,if,else}| > |{else,fi}| (3 > 2) +" endfor + +function! s:Weight(line) + let [o, i] = [0, s:ValidMatchEnd(a:line, g:mp_open_tag, 0)] + while i > 0 + let o += 1 + let i = s:ValidMatchEnd(a:line, g:mp_open_tag, i) + endwhile + let [c, i] = [0, matchend(a:line, '^\s*\<else\%[if]\>')] " Skip a leading else[if] + let i = s:ValidMatchEnd(a:line, g:mp_close_tag, i) + while i > 0 + let c += 1 + let i = s:ValidMatchEnd(a:line, g:mp_close_tag, i) + endwhile + return o - c +endfunction + +" Similar to matchend(), but skips strings and comments. +" line: a String +function! s:ValidMatchEnd(line, pat, start) + let i = matchend(a:line, a:pat, a:start) + while i > 0 && s:CommentOrString(a:line, i) + let i = matchend(a:line, a:pat, i) + endwhile + return i +endfunction + +" Like s:ValidMatchEnd(), but returns the end position of the last (i.e., +" rightmost) match. +function! s:LastValidMatchEnd(line, pat, start) + let last_found = -1 + let i = matchend(a:line, a:pat, a:start) + while i > 0 + if !s:CommentOrString(a:line, i) + let last_found = i + endif + let i = matchend(a:line, a:pat, i) endwhile - if !tmp - call cursor(cl,cc) + return last_found +endfunction + +function! s:DecreaseIndentOnClosingTag(curr_indent) + let cur_text = getline(v:lnum) + if cur_text =~# '^\s*\%('.g:mp_close_tag.'\)' + return max([a:curr_indent - shiftwidth(), 0]) endif - return tmp + return a:curr_indent endfunction " }}} -function! GetMetaPostIndent() - " not indent in comment ??? - if synIDattr(synID(line("."), col("."), 1), "name") =~ - \ 'm[fp]\(Comment\|TeXinsert\|String\)' +" Main function {{{ +" +" Note: Every rule of indentation in MetaPost is very subjective. We might get +" creative, but things get murky very soon (there are too many corner cases). +" So, we provide a means for the user to decide what to do when this script +" doesn't get it. We use a simple idea: use '%>', '%<' and '%=' to explicitly +" control indentation. The '<' and '>' symbols may be repeated many times +" (e.g., '%>>' will cause the next line to be indented twice). +" +" By using '%>...', '%<...' and '%=', the indentation the user wants is +" preserved by commands like gg=G, even if it does not follow the rules of +" this script. +" +" Example: +" +" def foo = +" makepen( +" subpath(T-n,t) of r %> +" shifted .5down %> +" --subpath(t,T) of r shifted .5up -- cycle %<<< +" ) +" withcolor black +" enddef +" +" The default indentation of the previous example would be: +" +" def foo = +" makepen( +" subpath(T-n,t) of r +" shifted .5down +" --subpath(t,T) of r shifted .5up -- cycle +" ) +" withcolor black +" enddef +" +" Personally, I prefer the latter, but anyway... +function! GetMetaPostIndentIntern() + " Do not touch indentation inside verbatimtex/btex.. etex blocks. + if synIDattr(synID(v:lnum, 1, 1), "name") =~# '^mpTeXinsert$\|^tex\|^Delimiter' return -1 endif - " Some RegExps: {{{1 - " end_of_item: all of end by ';' - " + all of end by :endfor, :enddef, :endfig, :endgroup, :fi - " + all of start by :beginfig(num), :begingroup - " + all of start by :for, :if, :else, :elseif and end by ':' - " + all of start by :def, :vardef and end by '=' - let end_of_item = '\(' . - \ ';\|' . - \ '\<\(end\(for\|def\|fig\|group\)\|fi\)\>\|' . - \ '\<begin\(group\>\|fig\s*(\s*\d\+\s*)\)\|' . - \ '\<\(for\|if\|else\(if\)\=\)\>.\+:\|' . - \ '\<\(var\)\=def\>.\+=' . '\)' - " }}} - " Save: current position {{{1 - let cl = line (".") - let cc = col (".") - let cs = getline(".") - " if it is :beginfig or :endfig use zero indent - if cs =~ '^\s*\(begin\|end\)fig\>' - return 0 - endif - " }}} - " Initialise: ind variable {{{1 - " search previous item not in current line - let p_semicol_l = MetaSearchNoncomment(end_of_item,"bW") - while p_semicol_l == cl - let p_semicol_l = MetaSearchNoncomment(end_of_item,"bW") - endwhile - " if this is first item in program use zero indent - if !p_semicol_l + + " This is the reference line relative to which the current line is indented + " (but see below). + let lnum = s:PrevNonBlankNonComment(v:lnum) + + " At the start of the file use zero indent. + if lnum == 0 return 0 endif - " if this is multiline item, remember first indent - if MetaNextNonblankNoncomment(p_semicol_l+1) < cl - let ind = indent(MetaNextNonblankNoncomment(p_semicol_l+1)) - " else --- search pre-previous item for search first line in previous item - else - " search pre-previous item not in current line - let pp_semicol_l = MetaSearchNoncomment(end_of_item,"bW") - while pp_semicol_l == p_semicol_l - let pp_semicol_l = MetaSearchNoncomment(end_of_item,"bW") - endwhile - " if we find pre-previous item, remember indent of previous item - " else --- remember zero - if pp_semicol_l - let ind = indent(MetaNextNonblankNoncomment(line(".")+1)) - else - let ind = 0 + + let prev_text = getline(lnum) + + " User-defined overrides take precedence over anything else. + " See above for an example. + let j = match(prev_text, '%[<>=]') + if j > 0 + let i = strlen(matchstr(prev_text, '%>\+', j)) - 1 + if i > 0 + return indent(lnum) + i * shiftwidth() + endif + + let i = strlen(matchstr(prev_text, '%<\+', j)) - 1 + if i > 0 + return max([indent(lnum) - i * shiftwidth(), 0]) + endif + + if match(prev_text, '%=', j) + return indent(lnum) endif endif - " }}} - " Increase Indent: {{{1 - " if it is an internal/external :for or :if statements {{{2 - let pnn_s = getline(MetaPrevNonblankNoncomment(cl-1)) - if pnn_s =~ '\<\(for\|if\)\>.\+:\s*\($\|%\)' - let ind = match(pnn_s, '\<\(for\|if\)\>.\+:\s*\($\|%\)') + &sw - " }}} - " if it is a :def, :vardef, :beginfig, :begingroup, :else, :elseif {{{2 - elseif pnn_s =~ '^\s*\(' . - \ '\(var\)\=def\|' . - \ 'begin\(group\|fig\s*(\s*\d\+\s*)\)\|' . - \ 'else\(if\)\=' . '\)\>' - let ind = ind + &sw - " }}} - " if it is a broken line {{{2 - elseif pnn_s !~ end_of_item.'\s*\($\|%\)' - let ind = ind + (2 * &sw) + + " If the reference line ends with an open tag, indent. + " + " Example: + " + " if c: + " 0 + " else: + " 1 + " fi if c2: % Note that this line has weight equal to zero. + " ... % This line will be indented + if s:LastTagIsOpen(prev_text) + return s:DecreaseIndentOnClosingTag(indent(lnum) + shiftwidth()) endif - " }}} - " }}} - " Decrease Indent: {{{1 - " if this is :endfor or :enddef statements {{{2 - " this is correct because :def cannot be inside :for - if cs =~ '\<end\(for\|def\)\=\>' - call MetaSearchNoncomment('\<for\>.\+:\s*\($\|%\)' . '\|' . - \ '^\s*\(var\)\=def\>',"bW") - if col(".") > 1 - let ind = col(".") - 1 + + " Lines with a positive weight are unbalanced and should likely be indented. + " + " Example: + " + " def f = enddef for i = 1 upto 5: if x[i] > 0: 1 else: 2 fi + " ... % This line will be indented (because of the unterminated `for`) + if s:Weight(prev_text) > 0 + return s:DecreaseIndentOnClosingTag(indent(lnum) + shiftwidth()) + endif + + " Unterminated statements cause indentation to kick in. + " + " Example: + " + " draw unitsquare + " withcolor black; % This line is indented because of `draw`. + " x := a + b + c + " + d + e; % This line is indented because of `:=`. + " + let i = s:LastValidMatchEnd(prev_text, g:mp_statement, 0) + if i >= 0 " Does the line contain a statement? + if s:ValidMatchEnd(prev_text, ';', i) < 0 " Is the statement unterminated? + return indent(lnum) + shiftwidth() else - let ind = indent(".") + return s:DecreaseIndentOnClosingTag(indent(lnum)) endif - " }}} - " if this is :fi, :else, :elseif statements {{{2 - elseif cs =~ '\<\(else\(if\)\=\|fi\)\>' - call MetaSearchNoncomment('\<if\>.\+:\s*\($\|%\)',"bW") - let ind = col(".") - 1 - " }}} - " if this is :endgroup statement {{{2 - elseif cs =~ '^\s*endgroup\>' - let ind = ind - &sw endif - " }}} - " }}} - return ind + " Deal with the special case of a statement spanning multiple lines. If the + " current reference line L ends with a semicolon, search backwards for + " another semicolon or a statement keyword. If the latter is found first, + " its line is used as the reference line for indenting the current line + " instead of L. + " + " Example: + " + " if cond: + " draw if a: z0 else: z1 fi + " shifted S + " scaled T; % L + " + " for i = 1 upto 3: % <-- Current line: this gets the same indent as `draw ...` + " + " NOTE: we get here only if L does not contain a statement (among those + " listed in g:mp_statement). + if s:ValidMatchEnd(prev_text, ';'.s:eol, 0) >= 0 " L ends with a semicolon + let stm_lnum = s:PrevNonBlankNonComment(lnum) + while stm_lnum > 0 + let prev_text = getline(stm_lnum) + let sc_pos = s:LastValidMatchEnd(prev_text, ';', 0) + let stm_pos = s:ValidMatchEnd(prev_text, g:mp_statement, sc_pos) + if stm_pos > sc_pos + let lnum = stm_lnum + break + elseif sc_pos > stm_pos + break + endif + let stm_lnum = s:PrevNonBlankNonComment(stm_lnum) + endwhile + endif + + return s:DecreaseIndentOnClosingTag(indent(lnum)) endfunction -" +" }}} let &cpo = s:keepcpo unlet s:keepcpo diff --git a/runtime/indent/ruby.vim b/runtime/indent/ruby.vim index 095b3a43c6..a97f4828d6 100644 --- a/runtime/indent/ruby.vim +++ b/runtime/indent/ruby.vim @@ -13,12 +13,23 @@ if exists("b:did_indent") endif let b:did_indent = 1 +if !exists('g:ruby_indent_access_modifier_style') + " Possible values: "normal", "indent", "outdent" + let g:ruby_indent_access_modifier_style = 'normal' +endif + +if !exists('g:ruby_indent_block_style') + " Possible values: "expression", "do" + let g:ruby_indent_block_style = 'expression' +endif + setlocal nosmartindent " Now, set up our indentation expression and keys that trigger it. setlocal indentexpr=GetRubyIndent(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,==begin,==end +setlocal indentkeys+==private,=protected,=public " Only define the function once. if exists("*GetRubyIndent") @@ -34,7 +45,7 @@ set cpo&vim " 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\|NoInterpolation\|Comment\|Documentation\)\>' + \ '\|Interpolation\|InterpolationDelimiter\|NoInterpolation\|Comment\|Documentation\)\>' " Regex of syntax group names that are strings. let s:syng_string = @@ -49,9 +60,10 @@ let s:skip_expr = \ "synIDattr(synID(line('.'),col('.'),1),'name') =~ '".s:syng_strcom."'" " Regex used for words that, at the start of a line, add a level of indent. -let s:ruby_indent_keywords = '^\s*\zs\<\%(module\|class\|def\|if\|for' . - \ '\|while\|until\|else\|elsif\|case\|when\|unless\|begin\|ensure' . - \ '\|rescue\):\@!\>' . +let s:ruby_indent_keywords = + \ '^\s*\zs\<\%(module\|class\|if\|for' . + \ '\|while\|until\|else\|elsif\|case\|when\|unless\|begin\|ensure\|rescue' . + \ '\|\%(public\|protected\|private\)\=\s*def\):\@!\>' . \ '\|\%([=,*/%+-]\|<<\|>>\|:\s\)\s*\zs' . \ '\<\%(if\|for\|while\|until\|case\|unless\|begin\):\@!\>' @@ -64,7 +76,8 @@ let s:ruby_deindent_keywords = " TODO: the do here should be restricted somewhat (only at end of line)? let s:end_start_regex = \ '\C\%(^\s*\|[=,*/%+\-|;{]\|<<\|>>\|:\s\)\s*\zs' . - \ '\<\%(module\|class\|def\|if\|for\|while\|until\|case\|unless\|begin\):\@!\>' . + \ '\<\%(module\|class\|if\|for\|while\|until\|case\|unless\|begin' . + \ '\|\%(public\|protected\|private\)\=\s*def\):\@!\>' . \ '\|\%(^\|[^.:@$]\)\@<=\<do:\@!\>' " Regex that defines the middle-match for the 'end' keyword. @@ -79,19 +92,39 @@ 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. -" TODO: this needs to deal with if ...: and so on let s:continuation_regex = - \ '\%(%\@<![({[\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)\s*\%(#.*\)\=$' + \ '\%(%\@<![({[\\.,:*/%+]\|\<and\|\<or\|\%(<%\)\@<![=-]\|:\@<![^[:alnum:]:][|&?]\|||\|&&\)\s*\%(#.*\)\=$' + +" Regex that defines continuable keywords +let s:continuable_regex = + \ '\C\%(^\s*\|[=,*/%+\-|;{]\|<<\|>>\|:\s\)\s*\zs' . + \ '\<\%(if\|for\|while\|until\|unless\):\@!\>' " 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 + " Regex that defines the first part of a splat pattern let s:splat_regex = '[[,(]\s*\*\s*\%(#.*\)\=$' +" Regex that describes all indent access modifiers +let s:access_modifier_regex = '\C^\s*\%(public\|protected\|private\)\s*\%(#.*\)\=$' + +" Regex that describes the indent access modifiers (excludes public) +let s:indent_access_modifier_regex = '\C^\s*\%(protected\|private\)\s*\%(#.*\)\=$' + " Regex that defines blocks. " " Note that there's a slight problem with this regex and s:continuation_regex. @@ -102,10 +135,13 @@ let s:splat_regex = '[[,(]\s*\*\s*\%(#.*\)\=$' " The reason is that the pipe matches a hanging "|" operator. " let s:block_regex = - \ '\%(\<do:\@!\>\|%\@<!{\)\s*\%(|\s*(*\s*\%([*@&]\=\h\w*,\=\s*\)\%(,\s*(*\s*[*@&]\=\h\w*\s*)*\s*\)*|\)\=\s*\%(#.*\)\=$' + \ '\%(\<do:\@!\>\|%\@<!{\)\s*\%(|[^|]*|\)\=\s*\%(#.*\)\=$' 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 " ====================== @@ -165,7 +201,21 @@ function s:GetMSL(lnum) " Otherwise, terminate search as we have found our MSL already. let line = getline(lnum) - if s:Match(lnum, s:splat_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 + elseif s:Match(lnum, s:splat_regex) " If the above line looks like the "*" of a splat, use the current one's " indentation. " @@ -175,7 +225,7 @@ function s:GetMSL(lnum) " something " return msl - elseif s:Match(line, s:non_bracket_continuation_regex) && + elseif s:Match(lnum, s:non_bracket_continuation_regex) && \ s:Match(msl, s:non_bracket_continuation_regex) " If the current line is a non-bracket continuation and so is the " previous one, keep its indent and continue looking for an MSL. @@ -186,6 +236,18 @@ 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 @@ -299,18 +361,39 @@ function s:ExtraBrackets(lnum) endfunction function s:Match(lnum, regex) - let col = match(getline(a:lnum), '\C'.a:regex) + 1 - return col > 0 && !s:IsInStringOrComment(a:lnum, col) ? col : 0 + let line = getline(a:lnum) + let offset = match(line, '\C'.a:regex) + let col = offset + 1 + + while offset > -1 && s:IsInStringOrComment(a:lnum, col) + let offset = match(line, '\C'.a:regex, offset + 1) + let col = offset + 1 + endwhile + + if offset > -1 + return col + else + return 0 + endif endfunction -function s:MatchLast(lnum, regex) - let line = getline(a:lnum) - let col = match(line, '.*\zs' . a:regex) - while col != -1 && s:IsInStringOrComment(a:lnum, col) - let line = strpart(line, 0, col) - let col = match(line, '.*' . a:regex) +" Locates the containing class/module's definition line, ignoring nested classes +" along the way. +" +function! s:FindContainingClass() + let saved_position = getpos('.') + + while searchpair(s:end_start_regex, s:end_middle_regex, s:end_end_regex, 'bW', + \ s:end_skip_expr) > 0 + if expand('<cword>') =~# '\<class\|module\>' + let found_lnum = line('.') + call setpos('.', saved_position) + return found_lnum + endif endwhile - return col + 1 + + call setpos('.', saved_position) + return 0 endfunction " 3. GetRubyIndent Function {{{1 @@ -320,6 +403,13 @@ 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 @@ -333,6 +423,24 @@ function GetRubyIndent(...) 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. @@ -343,7 +451,9 @@ function GetRubyIndent(...) if searchpair(escape(bs[0], '\['), '', bs[1], 'bW', s:skip_expr) > 0 if line[col-1]==')' && col('.') != col('$') - 1 let ind = virtcol('.') - 1 - else + 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 @@ -366,10 +476,17 @@ function GetRubyIndent(...) 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 @@ -389,6 +506,11 @@ function GetRubyIndent(...) 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 " ------------------------------- @@ -409,14 +531,50 @@ function GetRubyIndent(...) 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) - return indent(s:GetMSL(lnum)) + &sw + 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 + return indent(lnum) + sw endif " If the previous line contained unclosed opening brackets and we are still @@ -431,22 +589,22 @@ function GetRubyIndent(...) if opening.pos != -1 if opening.type == '(' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0 if col('.') + 1 == col('$') - return ind + &sw + return ind + sw else return virtcol('.') endif else let nonspace = matchend(line, '\S', opening.pos + 1) - 1 - return nonspace > 0 ? nonspace : ind + &sw + 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 + return indent('.') + sw else - return indent('.') + return indent(s:GetMSL(line('.'))) endif else call cursor(clnum, vcol) @@ -473,7 +631,7 @@ function GetRubyIndent(...) let col = s:Match(lnum, s:ruby_indent_keywords) if col > 0 call cursor(lnum, col) - let ind = virtcol('.') - 1 + &sw + 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 @@ -490,10 +648,14 @@ function GetRubyIndent(...) let p_lnum = lnum let lnum = s:GetMSL(lnum) - " If the previous line wasn't a MSL and is continuation return its indent. - " TODO: the || s:IsInString() thing worries me a bit. + " If the previous line wasn't a MSL. if p_lnum != lnum - if s:Match(p_lnum, s:non_bracket_continuation_regex) || s:IsInString(p_lnum,strlen(line)) + " 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 @@ -506,9 +668,9 @@ function GetRubyIndent(...) " 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 + let ind = msl_ind + sw if s:Match(lnum, s:end_end_regex) - let ind = ind - &sw + let ind = ind - sw endif return ind endif @@ -517,7 +679,7 @@ function GetRubyIndent(...) " 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 + let ind = msl_ind + sw else let ind = msl_ind endif diff --git a/runtime/indent/sass.vim b/runtime/indent/sass.vim index b6e2e66e8a..d87b371fdd 100644 --- a/runtime/indent/sass.vim +++ b/runtime/indent/sass.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: Sass " Maintainer: Tim Pope <vimNOSPAM@tpope.org> -" Last Change: 2013 May 30 +" Last Change: 2016 Aug 29 if exists("b:did_indent") finish @@ -29,9 +29,7 @@ function! GetSassIndent() let indent = indent(lnum) let cindent = indent(v:lnum) if line !~ s:property && line !~ s:extend && cline =~ s:property - return indent + &sw - "elseif line =~ s:property && cline !~ s:property - "return indent - &sw + return indent + (exists('*shiftwidth') ? shiftwidth() : &sw) else return -1 endif |