aboutsummaryrefslogtreecommitdiff
path: root/runtime/indent
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2017-04-29 01:41:29 +0200
committerGitHub <noreply@github.com>2017-04-29 01:41:29 +0200
commit9f6d693e263b617cd1a1772e42911cd5a0b1675b (patch)
tree593d3c9d968be92bc1ed8a445e6856079ef546ed /runtime/indent
parent59be0b42806c39131f76f89c554f0a24e82514a8 (diff)
parent53419673154a98b705cfa80590099a247cc9df49 (diff)
downloadrneovim-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.vim2
-rw-r--r--runtime/indent/cucumber.vim21
-rw-r--r--runtime/indent/eruby.vim43
-rw-r--r--runtime/indent/fortran.vim15
-rw-r--r--runtime/indent/gitconfig.vim9
-rw-r--r--runtime/indent/haml.vim7
-rw-r--r--runtime/indent/html.vim2
-rw-r--r--runtime/indent/liquid.vim11
-rw-r--r--runtime/indent/mf.vim6
-rw-r--r--runtime/indent/mp.vim483
-rw-r--r--runtime/indent/ruby.vim232
-rw-r--r--runtime/indent/sass.vim6
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