aboutsummaryrefslogtreecommitdiff
path: root/vim/indent
diff options
context:
space:
mode:
authorBen Beltran <ben@freshout.us>2012-10-08 11:44:10 -0500
committerBen Beltran <ben@freshout.us>2012-10-08 11:44:10 -0500
commit0d23b6e515a01a5782532351821ebfa11f3d6cf2 (patch)
treeaa395b7e50ccb533d6b48b809016ac06f2d5bc8c /vim/indent
parenta91731eac872b7837c2821341db5888702125cef (diff)
Add vim again :)
Diffstat (limited to 'vim/indent')
-rw-r--r--vim/indent/coffee.vim322
-rw-r--r--vim/indent/cucumber.vim74
-rw-r--r--vim/indent/gitconfig.vim36
-rw-r--r--vim/indent/haml.vim73
-rw-r--r--vim/indent/javascript.vim328
-rw-r--r--vim/indent/puppet.vim76
-rw-r--r--vim/indent/sass.vim40
-rw-r--r--vim/indent/scala.vim83
-rw-r--r--vim/indent/scss.vim12
9 files changed, 1044 insertions, 0 deletions
diff --git a/vim/indent/coffee.vim b/vim/indent/coffee.vim
new file mode 100644
index 0000000..f60cfdd
--- /dev/null
+++ b/vim/indent/coffee.vim
@@ -0,0 +1,322 @@
+" Language: CoffeeScript
+" Maintainer: Mick Koch <kchmck@gmail.com>
+" URL: http://github.com/kchmck/vim-coffee-script
+" License: WTFPL
+
+if exists("b:did_indent")
+ finish
+endif
+
+let b:did_indent = 1
+
+setlocal autoindent
+setlocal indentexpr=GetCoffeeIndent(v:lnum)
+" Make sure GetCoffeeIndent is run when these are typed so they can be
+" indented or outdented.
+setlocal indentkeys+=0],0),0.,=else,=when,=catch,=finally
+
+" Only define the function once.
+if exists("*GetCoffeeIndent")
+ finish
+endif
+
+" Keywords to indent after
+let s:INDENT_AFTER_KEYWORD = '^\%(if\|unless\|else\|for\|while\|until\|'
+\ . 'loop\|switch\|when\|try\|catch\|finally\|'
+\ . 'class\)\>'
+
+" Operators to indent after
+let s:INDENT_AFTER_OPERATOR = '\%([([{:=]\|[-=]>\)$'
+
+" Keywords and operators that continue a line
+let s:CONTINUATION = '\<\%(is\|isnt\|and\|or\)\>$'
+\ . '\|'
+\ . '\%(-\@<!-\|+\@<!+\|<\|[-=]\@<!>\|\*\|/\@<!/\|%\||\|'
+\ . '&\|,\|\.\@<!\.\)$'
+
+" Operators that block continuation indenting
+let s:CONTINUATION_BLOCK = '[([{:=]$'
+
+" A continuation dot access
+let s:DOT_ACCESS = '^\.'
+
+" Keywords to outdent after
+let s:OUTDENT_AFTER = '^\%(return\|break\|continue\|throw\)\>'
+
+" A compound assignment like `... = if ...`
+let s:COMPOUND_ASSIGNMENT = '[:=]\s*\%(if\|unless\|for\|while\|until\|'
+\ . 'switch\|try\|class\)\>'
+
+" A postfix condition like `return ... if ...`.
+let s:POSTFIX_CONDITION = '\S\s\+\zs\<\%(if\|unless\)\>'
+
+" A single-line else statement like `else ...` but not `else if ...
+let s:SINGLE_LINE_ELSE = '^else\s\+\%(\<\%(if\|unless\)\>\)\@!'
+
+" Max lines to look back for a match
+let s:MAX_LOOKBACK = 50
+
+" Syntax names for strings
+let s:SYNTAX_STRING = 'coffee\%(String\|AssignString\|Embed\|Regex\|Heregex\|'
+\ . 'Heredoc\)'
+
+" Syntax names for comments
+let s:SYNTAX_COMMENT = 'coffee\%(Comment\|BlockComment\|HeregexComment\)'
+
+" Syntax names for strings and comments
+let s:SYNTAX_STRING_COMMENT = s:SYNTAX_STRING . '\|' . s:SYNTAX_COMMENT
+
+" Get the linked syntax name of a character.
+function! s:SyntaxName(linenum, col)
+ return synIDattr(synID(a:linenum, a:col, 1), 'name')
+endfunction
+
+" Check if a character is in a comment.
+function! s:IsComment(linenum, col)
+ return s:SyntaxName(a:linenum, a:col) =~ s:SYNTAX_COMMENT
+endfunction
+
+" Check if a character is in a string.
+function! s:IsString(linenum, col)
+ return s:SyntaxName(a:linenum, a:col) =~ s:SYNTAX_STRING
+endfunction
+
+" Check if a character is in a comment or string.
+function! s:IsCommentOrString(linenum, col)
+ return s:SyntaxName(a:linenum, a:col) =~ s:SYNTAX_STRING_COMMENT
+endfunction
+
+" Check if a whole line is a comment.
+function! s:IsCommentLine(linenum)
+ " Check the first non-whitespace character.
+ return s:IsComment(a:linenum, indent(a:linenum) + 1)
+endfunction
+
+" Repeatedly search a line for a regex until one is found outside a string or
+" comment.
+function! s:SmartSearch(linenum, regex)
+ " Start at the first column.
+ let col = 0
+
+ " Search until there are no more matches, unless a good match is found.
+ while 1
+ call cursor(a:linenum, col + 1)
+ let [_, col] = searchpos(a:regex, 'cn', a:linenum)
+
+ " No more matches.
+ if !col
+ break
+ endif
+
+ if !s:IsCommentOrString(a:linenum, col)
+ return 1
+ endif
+ endwhile
+
+ " No good match found.
+ return 0
+endfunction
+
+" Skip a match if it's in a comment or string, is a single-line statement that
+" isn't adjacent, or is a postfix condition.
+function! s:ShouldSkip(startlinenum, linenum, col)
+ if s:IsCommentOrString(a:linenum, a:col)
+ return 1
+ endif
+
+ " Check for a single-line statement that isn't adjacent.
+ if s:SmartSearch(a:linenum, '\<then\>') && a:startlinenum - a:linenum > 1
+ return 1
+ endif
+
+ if s:SmartSearch(a:linenum, s:POSTFIX_CONDITION) &&
+ \ !s:SmartSearch(a:linenum, s:COMPOUND_ASSIGNMENT)
+ return 1
+ endif
+
+ return 0
+endfunction
+
+" Find the farthest line to look back to, capped to line 1 (zero and negative
+" numbers cause bad things).
+function! s:MaxLookback(startlinenum)
+ return max([1, a:startlinenum - s:MAX_LOOKBACK])
+endfunction
+
+" Get the skip expression for searchpair().
+function! s:SkipExpr(startlinenum)
+ return "s:ShouldSkip(" . a:startlinenum . ", line('.'), col('.'))"
+endfunction
+
+" Search for pairs of text.
+function! s:SearchPair(start, end)
+ " The cursor must be in the first column for regexes to match.
+ call cursor(0, 1)
+
+ let startlinenum = line('.')
+
+ " Don't need the W flag since MaxLookback caps the search to line 1.
+ return searchpair(a:start, '', a:end, 'bcn',
+ \ s:SkipExpr(startlinenum),
+ \ s:MaxLookback(startlinenum))
+endfunction
+
+" Try to find a previous matching line.
+function! s:GetMatch(curline)
+ let firstchar = a:curline[0]
+
+ if firstchar == '}'
+ return s:SearchPair('{', '}')
+ elseif firstchar == ')'
+ return s:SearchPair('(', ')')
+ elseif firstchar == ']'
+ return s:SearchPair('\[', '\]')
+ elseif a:curline =~ '^else\>'
+ return s:SearchPair('\<\%(if\|unless\|when\)\>', '\<else\>')
+ elseif a:curline =~ '^catch\>'
+ return s:SearchPair('\<try\>', '\<catch\>')
+ elseif a:curline =~ '^finally\>'
+ return s:SearchPair('\<try\>', '\<finally\>')
+ endif
+
+ return 0
+endfunction
+
+" Get the nearest previous line that isn't a comment.
+function! s:GetPrevNormalLine(startlinenum)
+ let curlinenum = a:startlinenum
+
+ while curlinenum > 0
+ let curlinenum = prevnonblank(curlinenum - 1)
+
+ if !s:IsCommentLine(curlinenum)
+ return curlinenum
+ endif
+ endwhile
+
+ return 0
+endfunction
+
+" Try to find a comment in a line.
+function! s:FindComment(linenum)
+ let col = 0
+
+ while 1
+ call cursor(a:linenum, col + 1)
+ let [_, col] = searchpos('#', 'cn', a:linenum)
+
+ if !col
+ break
+ endif
+
+ if s:IsComment(a:linenum, col)
+ return col
+ endif
+ endwhile
+
+ return 0
+endfunction
+
+" Get a line without comments or surrounding whitespace.
+function! s:GetTrimmedLine(linenum)
+ let comment = s:FindComment(a:linenum)
+ let line = getline(a:linenum)
+
+ if comment
+ " Subtract 1 to get to the column before the comment and another 1 for
+ " zero-based indexing.
+ let line = line[:comment - 2]
+ endif
+
+ return substitute(substitute(line, '^\s\+', '', ''),
+ \ '\s\+$', '', '')
+endfunction
+
+function! s:GetCoffeeIndent(curlinenum)
+ let prevlinenum = s:GetPrevNormalLine(a:curlinenum)
+
+ " Don't do anything if there's no previous line.
+ if !prevlinenum
+ return -1
+ endif
+
+ let curline = s:GetTrimmedLine(a:curlinenum)
+
+ " Try to find a previous matching statement. This handles outdenting.
+ let matchlinenum = s:GetMatch(curline)
+
+ if matchlinenum
+ return indent(matchlinenum)
+ endif
+
+ " Try to find a matching `when`.
+ if curline =~ '^when\>' && !s:SmartSearch(prevlinenum, '\<switch\>')
+ let linenum = a:curlinenum
+
+ while linenum > 0
+ let linenum = s:GetPrevNormalLine(linenum)
+
+ if getline(linenum) =~ '^\s*when\>'
+ return indent(linenum)
+ endif
+ endwhile
+
+ return -1
+ endif
+
+ let prevline = s:GetTrimmedLine(prevlinenum)
+ let previndent = indent(prevlinenum)
+
+ " Always indent after these operators.
+ if prevline =~ s:INDENT_AFTER_OPERATOR
+ return previndent + &shiftwidth
+ endif
+
+ " Indent after a continuation if it's the first.
+ if prevline =~ s:CONTINUATION
+ let prevprevlinenum = s:GetPrevNormalLine(prevlinenum)
+ let prevprevline = s:GetTrimmedLine(prevprevlinenum)
+
+ if prevprevline !~ s:CONTINUATION && prevprevline !~ s:CONTINUATION_BLOCK
+ return previndent + &shiftwidth
+ endif
+
+ return -1
+ endif
+
+ " Indent after these keywords and compound assignments if they aren't a
+ " single-line statement.
+ if prevline =~ s:INDENT_AFTER_KEYWORD || prevline =~ s:COMPOUND_ASSIGNMENT
+ if !s:SmartSearch(prevlinenum, '\<then\>') && prevline !~ s:SINGLE_LINE_ELSE
+ return previndent + &shiftwidth
+ endif
+
+ return -1
+ endif
+
+ " Indent a dot access if it's the first.
+ if curline =~ s:DOT_ACCESS && prevline !~ s:DOT_ACCESS
+ return previndent + &shiftwidth
+ endif
+
+ " Outdent after these keywords if they don't have a postfix condition or are
+ " a single-line statement.
+ if prevline =~ s:OUTDENT_AFTER
+ if !s:SmartSearch(prevlinenum, s:POSTFIX_CONDITION) ||
+ \ s:SmartSearch(prevlinenum, '\<then\>')
+ return previndent - &shiftwidth
+ endif
+ endif
+
+ " No indenting or outdenting is needed.
+ return -1
+endfunction
+
+" Wrap s:GetCoffeeIndent to keep the cursor position.
+function! GetCoffeeIndent(curlinenum)
+ let oldcursor = getpos('.')
+ let indent = s:GetCoffeeIndent(a:curlinenum)
+ call setpos('.', oldcursor)
+
+ return indent
+endfunction
diff --git a/vim/indent/cucumber.vim b/vim/indent/cucumber.vim
new file mode 100644
index 0000000..802d224
--- /dev/null
+++ b/vim/indent/cucumber.vim
@@ -0,0 +1,74 @@
+" Vim indent file
+" Language: Cucumber
+" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
+" Last Change: 2010 May 21
+
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal autoindent
+setlocal indentexpr=GetCucumberIndent()
+setlocal indentkeys=o,O,*<Return>,<:>,0<Bar>,0#,=,!^F
+
+let b:undo_indent = 'setl ai< inde< indk<'
+
+" Only define the function once.
+if exists("*GetCucumberIndent")
+ finish
+endif
+
+function! s:syn(lnum)
+ return synIDattr(synID(a:lnum,1+indent(a:lnum),1),'name')
+endfunction
+
+function! GetCucumberIndent()
+ let line = getline(prevnonblank(v:lnum-1))
+ let cline = getline(v:lnum)
+ let nline = getline(nextnonblank(v:lnum+1))
+ let syn = s:syn(prevnonblank(v:lnum-1))
+ let csyn = s:syn(v:lnum)
+ let nsyn = s:syn(nextnonblank(v:lnum+1))
+ if csyn ==# 'cucumberFeature' || cline =~# '^\s*Feature:'
+ " feature heading
+ return 0
+ elseif csyn ==# 'cucumberExamples' || cline =~# '^\s*\%(Examples\|Scenarios\):'
+ " examples heading
+ return 2 * &sw
+ elseif csyn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || cline =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):'
+ " background, scenario or outline heading
+ return &sw
+ elseif syn ==# 'cucumberFeature' || line =~# '^\s*Feature:'
+ " line after feature heading
+ return &sw
+ elseif syn ==# 'cucumberExamples' || line =~# '^\s*\%(Examples\|Scenarios\):'
+ " line after examples heading
+ 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
+ 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
+ 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
+ elseif cline =~# '^\s*[^|]' && line =~# '^\s*|'
+ " line after a table, relative unindent
+ 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
+ endif
+ return indent(prevnonblank(v:lnum-1))
+endfunction
+
+" vim:set sts=2 sw=2:
diff --git a/vim/indent/gitconfig.vim b/vim/indent/gitconfig.vim
new file mode 100644
index 0000000..e190fc3
--- /dev/null
+++ b/vim/indent/gitconfig.vim
@@ -0,0 +1,36 @@
+" Vim indent file
+" Language: git config file
+" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
+
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal autoindent
+setlocal indentexpr=GetGitconfigIndent()
+setlocal indentkeys=o,O,*<Return>,0[,],0;,0#,=,!^F
+
+let b:undo_indent = 'setl ai< inde< indk<'
+
+" Only define the function once.
+if exists("*GetGitconfigIndent")
+ finish
+endif
+
+function! GetGitconfigIndent()
+ 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
+ elseif cline =~ '^\s*\['
+ return 0
+ elseif cline =~ '^\s*\a'
+ return &sw
+ elseif cline == '' && line =~ '^\['
+ return &sw
+ else
+ return -1
+ endif
+endfunction
diff --git a/vim/indent/haml.vim b/vim/indent/haml.vim
new file mode 100644
index 0000000..58c0307
--- /dev/null
+++ b/vim/indent/haml.vim
@@ -0,0 +1,73 @@
+" Vim indent file
+" Language: Haml
+" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
+" Last Change: 2010 May 21
+
+if exists("b:did_indent")
+ finish
+endif
+runtime! indent/ruby.vim
+unlet! b:did_indent
+let b:did_indent = 1
+
+setlocal autoindent sw=2 et
+setlocal indentexpr=GetHamlIndent()
+setlocal indentkeys=o,O,*<Return>,},],0),!^F,=end,=else,=elsif,=rescue,=ensure,=when
+
+" Only define the function once.
+if exists("*GetHamlIndent")
+ finish
+endif
+
+let s:attributes = '\%({.\{-\}}\|\[.\{-\}\]\)'
+let s:tag = '\%([%.#][[:alnum:]_-]\+\|'.s:attributes.'\)*[<>]*'
+
+if !exists('g:haml_self_closing_tags')
+ let g:haml_self_closing_tags = 'meta|link|img|hr|br'
+endif
+
+function! GetHamlIndent()
+ let lnum = prevnonblank(v:lnum-1)
+ if lnum == 0
+ return 0
+ endif
+ let line = substitute(getline(lnum),'\s\+$','','')
+ let cline = substitute(substitute(getline(v:lnum),'\s\+$','',''),'^\s\+','','')
+ let lastcol = strlen(line)
+ let line = substitute(line,'^\s\+','','')
+ let indent = indent(lnum)
+ let cindent = indent(v:lnum)
+ if cline =~# '\v^-\s*%(elsif|else|when)>'
+ let indent = cindent < indent ? cindent : indent - &sw
+ endif
+ let increase = indent + &sw
+ if indent == indent(lnum)
+ let indent = cindent <= indent ? -1 : increase
+ endif
+
+ let group = synIDattr(synID(lnum,lastcol,1),'name')
+
+ if line =~ '^!!!'
+ return indent
+ elseif line =~ '^/\%(\[[^]]*\]\)\=$'
+ return increase
+ elseif group == 'hamlFilter'
+ return increase
+ elseif line =~ '^'.s:tag.'[&!]\=[=~-]\s*\%(\%(if\|else\|elsif\|unless\|case\|when\|while\|until\|for\|begin\|module\|class\|def\)\>\%(.*\<end\>\)\@!\|.*do\%(\s*|[^|]*|\)\=\s*$\)'
+ return increase
+ elseif line =~ '^'.s:tag.'[&!]\=[=~-].*,\s*$'
+ return increase
+ elseif line == '-#'
+ return increase
+ elseif group =~? '\v^(hamlSelfCloser)$' || line =~? '^%\v%('.g:haml_self_closing_tags.')>'
+ return indent
+ elseif group =~? '\v^%(hamlTag|hamlAttributesDelimiter|hamlObjectDelimiter|hamlClass|hamlId|htmlTagName|htmlSpecialTagName)$'
+ return increase
+ elseif synIDattr(synID(v:lnum,1,1),'name') ==? 'hamlRubyFilter'
+ return GetRubyIndent()
+ else
+ return indent
+ endif
+endfunction
+
+" vim:set sw=2:
diff --git a/vim/indent/javascript.vim b/vim/indent/javascript.vim
new file mode 100644
index 0000000..b34deee
--- /dev/null
+++ b/vim/indent/javascript.vim
@@ -0,0 +1,328 @@
+" Vim indent file
+" Language: Javascript
+" Maintainer: Darrick Wiebe <darrick at innatesoftware.com>
+" URL: http://github.com/pangloss/vim-javascript
+" Version: 1.0.0
+" Last Change: August 31, 2009
+" Acknowledgement: Based off of vim-ruby maintained by Nikolai Weibull http://vim-ruby.rubyforge.org
+
+" 0. Initialization {{{1
+" =================
+
+" Only load this indent file when no other was loaded.
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal nosmartindent
+
+" Now, set up our indentation expression and keys that trigger it.
+setlocal indentexpr=GetJavascriptIndent()
+setlocal indentkeys=0{,0},0),0],!^F,o,O,e
+
+" Only define the function once.
+if exists("*GetJavascriptIndent")
+ finish
+endif
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+" 1. Variables {{{1
+" ============
+
+" Regex of syntax group names that are or delimit string or are comments.
+let s:syng_strcom = 'javaScript\%(String\|RegexpString\|CommentTodo\|LineComment\|Comment\|DocComment\)'
+
+" Regex of syntax group names that are strings.
+let s:syng_string = 'javaScript\%(RegexpString\)'
+
+" Regex of syntax group names that are strings or documentation.
+let s:syng_stringdoc = 'javaScriptDocComment\|javaScriptComment'
+
+" Expression used to check whether we should skip a match with searchpair().
+let s:skip_expr = "synIDattr(synID(line('.'),col('.'),1),'name') =~ '".s:syng_strcom."'"
+
+let s:line_term = '\s*\%(\%(\/\/\).*\)\=$'
+
+" Regex that defines continuation lines, not including (, {, or [.
+let s:continuation_regex = '\%([\\*+/.:]\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)' . s:line_term
+
+" Regex that defines continuation lines.
+" TODO: this needs to deal with if ...: and so on
+let s:msl_regex = '\%([\\*+/.:([]\|\%(<%\)\@<![=-]\|\W[|&?]\|||\|&&\)' . s:line_term
+
+let s:one_line_scope_regex = '\<\%(if\|else\|for\|while\)\>[^{;]*' . s:line_term
+
+" Regex that defines blocks.
+let s:block_regex = '\%({\)\s*\%(|\%([*@]\=\h\w*,\=\s*\)\%(,\s*[*@]\=\h\w*\)*|\)\=' . s:line_term
+
+" 2. Auxiliary Functions {{{1
+" ======================
+
+" Check if the character at lnum:col is inside a string, comment, or is ascii.
+function s:IsInStringOrComment(lnum, col)
+ return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_strcom
+endfunction
+
+" Check if the character at lnum:col is inside a string.
+function s:IsInString(lnum, col)
+ return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_string
+endfunction
+
+" Check if the character at lnum:col is inside a string or documentation.
+function s:IsInStringOrDocumentation(lnum, col)
+ return synIDattr(synID(a:lnum, a:col, 1), 'name') =~ s:syng_stringdoc
+endfunction
+
+" Find line above 'lnum' that isn't empty, in a comment, or in a string.
+function s:PrevNonBlankNonString(lnum)
+ let in_block = 0
+ let lnum = prevnonblank(a:lnum)
+ while lnum > 0
+ " Go in and out of blocks comments as necessary.
+ " If the line isn't empty (with opt. comment) or in a string, end search.
+ let line = getline(lnum)
+ if line =~ '/\*'
+ if in_block
+ let in_block = 0
+ else
+ break
+ endif
+ elseif !in_block && line =~ '\*/'
+ let in_block = 1
+ elseif !in_block && line !~ '^\s*\%(//\).*$' && !(s:IsInStringOrComment(lnum, 1) && s:IsInStringOrComment(lnum, strlen(line)))
+ break
+ endif
+ let lnum = prevnonblank(lnum - 1)
+ endwhile
+ return lnum
+endfunction
+
+" Find line above 'lnum' that started the continuation 'lnum' may be part of.
+function s:GetMSL(lnum, in_one_line_scope)
+ " Start on the line we're at and use its indent.
+ let msl = a:lnum
+ 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.
+ " Otherwise, terminate search as we have found our MSL already.
+ let line = getline(lnum)
+ let col = match(line, s:msl_regex) + 1
+ if (col > 0 && !s:IsInStringOrComment(lnum, col)) || s:IsInString(lnum, strlen(line))
+ let msl = lnum
+ else
+ " Don't use lines that are part of a one line scope as msl unless the
+ " flag in_one_line_scope is set to 1
+ "
+ if a:in_one_line_scope
+ break
+ end
+ let msl_one_line = s:Match(lnum, s:one_line_scope_regex)
+ if msl_one_line == 0
+ break
+ endif
+ endif
+ let lnum = s:PrevNonBlankNonString(lnum - 1)
+ endwhile
+ return msl
+endfunction
+
+" Check if line 'lnum' has more opening brackets than closing ones.
+function s:LineHasOpeningBrackets(lnum)
+ let open_0 = 0
+ let open_2 = 0
+ let open_4 = 0
+ let line = getline(a:lnum)
+ let pos = match(line, '[][(){}]', 0)
+ while pos != -1
+ if !s:IsInStringOrComment(a:lnum, pos + 1)
+ let idx = stridx('(){}[]', line[pos])
+ if idx % 2 == 0
+ let open_{idx} = open_{idx} + 1
+ else
+ let open_{idx - 1} = open_{idx - 1} - 1
+ endif
+ endif
+ let pos = match(line, '[][(){}]', pos + 1)
+ endwhile
+ return (open_0 > 0) . (open_2 > 0) . (open_4 > 0)
+endfunction
+
+function s:Match(lnum, regex)
+ let col = match(getline(a:lnum), a:regex) + 1
+ return col > 0 && !s:IsInStringOrComment(a:lnum, col) ? col : 0
+endfunction
+
+function s:IndentWithContinuation(lnum, ind, width)
+ " Set up variables to use and search for MSL to the previous line.
+ let p_lnum = a:lnum
+ let lnum = s:GetMSL(a:lnum, 1)
+ let line = getline(line)
+
+ " If the previous line wasn't a MSL and is continuation return its indent.
+ " TODO: the || s:IsInString() thing worries me a bit.
+ if p_lnum != lnum
+ if s:Match(p_lnum,s:continuation_regex)||s:IsInString(p_lnum,strlen(line))
+ return a:ind
+ endif
+ endif
+
+ " Set up more variables now that we know we aren't continuation bound.
+ let msl_ind = indent(lnum)
+
+ " If the previous line ended with [*+/.-=], start a continuation that
+ " indents an extra level.
+ if s:Match(lnum, s:continuation_regex)
+ if lnum == p_lnum
+ return msl_ind + a:width
+ else
+ return msl_ind
+ endif
+ endif
+
+ return a:ind
+endfunction
+
+function s:InOneLineScope(lnum)
+ let msl = s:GetMSL(a:lnum, 1)
+ if msl > 0 && s:Match(msl, s:one_line_scope_regex)
+ return msl
+ endif
+ return 0
+endfunction
+
+function s:ExitingOneLineScope(lnum)
+ let msl = s:GetMSL(a:lnum, 1)
+ if msl > 0
+ " if the current line is in a one line scope ..
+ if s:Match(msl, s:one_line_scope_regex)
+ return 0
+ else
+ let prev_msl = s:GetMSL(msl - 1, 1)
+ if s:Match(prev_msl, s:one_line_scope_regex)
+ return prev_msl
+ endif
+ endif
+ endif
+ return 0
+endfunction
+
+" 3. GetJavascriptIndent Function {{{1
+" =========================
+
+function GetJavascriptIndent()
+ " 3.1. Setup {{{2
+ " ----------
+
+ " Set up variables for restoring position in file. Could use v:lnum here.
+ let vcol = col('.')
+
+ " 3.2. Work on the current line {{{2
+ " -----------------------------
+
+ " Get the current line.
+ let line = getline(v:lnum)
+ let ind = -1
+
+
+ " 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(v:lnum, col)
+ call cursor(v:lnum, 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
+ else
+ let ind = indent(s:GetMSL(line('.'), 0))
+ endif
+ endif
+ return ind
+ endif
+
+ " If we have a /* or */ set indent to first column.
+ if match(line, '^\s*\%(/\*\|\*/\)$') != -1
+ return 0
+ endif
+
+ " If we are in a multi-line string or line-comment, don't do anything to it.
+ if s:IsInStringOrDocumentation(v:lnum, matchend(line, '^\s*') + 1)
+ return indent('.')
+ 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(v:lnum - 1)
+
+ " If the line is empty and inside a string, use the previous line.
+ if line =~ '^\s*$' && lnum != prevnonblank(v:lnum - 1)
+ return indent(prevnonblank(v:lnum))
+ endif
+
+ " At the start of the file use zero indent.
+ if lnum == 0
+ return 0
+ endif
+
+ " Set up variables for current line.
+ let line = getline(lnum)
+ let ind = indent(lnum)
+
+ " 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, 0)) + &sw
+ endif
+
+ " If the previous line contained an opening bracket, and we are still in it,
+ " add indent depending on the bracket type.
+ if line =~ '[[({]'
+ let counts = s:LineHasOpeningBrackets(lnum)
+ if counts[0] == '1' && searchpair('(', '', ')', 'bW', s:skip_expr) > 0
+ if col('.') + 1 == col('$')
+ return ind + &sw
+ else
+ return virtcol('.')
+ endif
+ elseif counts[1] == '1' || counts[2] == '1'
+ return ind + &sw
+ else
+ call cursor(v:lnum, vcol)
+ end
+ endif
+
+ " 3.4. Work on the MSL line. {{{2
+ " --------------------------
+
+ let ind_con = ind
+ let ind = s:IndentWithContinuation(lnum, ind_con, &sw)
+
+ " }}}2
+ "
+ "
+ let ols = s:InOneLineScope(lnum)
+ if ols > 0
+ let ind = ind + &sw
+ else
+ let ols = s:ExitingOneLineScope(lnum)
+ while ols > 0 && ind > 0
+ let ind = ind - &sw
+ let ols = s:InOneLineScope(ols - 1)
+ endwhile
+ endif
+
+ return ind
+endfunction
+
+" }}}1
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
+
+" vim:set sw=2 sts=2 ts=8 noet:
+
diff --git a/vim/indent/puppet.vim b/vim/indent/puppet.vim
new file mode 100644
index 0000000..689e068
--- /dev/null
+++ b/vim/indent/puppet.vim
@@ -0,0 +1,76 @@
+" Vim indent file
+" Language: Puppet
+" Maintainer: Todd Zullinger <tmz@pobox.com>
+" Last Change: 2009 Aug 19
+" vim: set sw=4 sts=4:
+
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal autoindent smartindent
+setlocal indentexpr=GetPuppetIndent()
+setlocal indentkeys+=0],0)
+
+if exists("*GetPuppetIndent")
+ finish
+endif
+
+" Check if a line is part of an include 'block', e.g.:
+" include foo,
+" bar,
+" baz
+function! s:PartOfInclude(lnum)
+ let lnum = a:lnum
+ while lnum
+ let lnum = lnum - 1
+ let line = getline(lnum)
+ if line !~ ',$'
+ break
+ endif
+ if line =~ '^\s*include\s\+[^,]\+,$'
+ return 1
+ endif
+ endwhile
+ return 0
+endfunction
+
+function! s:OpenBrace(lnum)
+ call cursor(a:lnum, 1)
+ return searchpair('{\|\[\|(', '', '}\|\]\|)', 'nbW')
+endfunction
+
+function! GetPuppetIndent()
+ let pnum = prevnonblank(v:lnum - 1)
+ if pnum == 0
+ return 0
+ endif
+
+ let line = getline(v:lnum)
+ let pline = getline(pnum)
+ let ind = indent(pnum)
+
+ if pline =~ '^\s*#'
+ return ind
+ endif
+
+ if pline =~ '\({\|\[\|(\|:\)$'
+ let ind += &sw
+ elseif pline =~ ';$' && pline !~ '[^:]\+:.*[=+]>.*'
+ let ind -= &sw
+ elseif pline =~ '^\s*include\s\+.*,$'
+ let ind += &sw
+ endif
+
+ if pline !~ ',$' && s:PartOfInclude(pnum)
+ let ind -= &sw
+ endif
+
+ " Match } }, }; ] ]: )
+ if line =~ '^\s*\(}\(,\|;\)\?$\|]:\?$\|)\)'
+ let ind = indent(s:OpenBrace(v:lnum))
+ endif
+
+ return ind
+endfunction
diff --git a/vim/indent/sass.vim b/vim/indent/sass.vim
new file mode 100644
index 0000000..1da8319
--- /dev/null
+++ b/vim/indent/sass.vim
@@ -0,0 +1,40 @@
+" Vim indent file
+" Language: Sass
+" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
+" Last Change: 2010 May 21
+
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal autoindent sw=2 et
+setlocal indentexpr=GetSassIndent()
+setlocal indentkeys=o,O,*<Return>,<:>,!^F
+
+" Only define the function once.
+if exists("*GetSassIndent")
+ finish
+endif
+
+let s:property = '^\s*:\|^\s*[[:alnum:]#{}-]\+\%(:\|\s*=\)'
+let s:extend = '^\s*\%(@extend\|@include\|+\)'
+
+function! GetSassIndent()
+ let lnum = prevnonblank(v:lnum-1)
+ let line = substitute(getline(lnum),'\s\+$','','')
+ let cline = substitute(substitute(getline(v:lnum),'\s\+$','',''),'^\s\+','','')
+ let lastcol = strlen(line)
+ let line = substitute(line,'^\s\+','','')
+ 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
+ else
+ return -1
+ endif
+endfunction
+
+" vim:set sw=2:
diff --git a/vim/indent/scala.vim b/vim/indent/scala.vim
new file mode 100644
index 0000000..45266a0
--- /dev/null
+++ b/vim/indent/scala.vim
@@ -0,0 +1,83 @@
+" Vim indent file
+" Language : Scala (http://scala-lang.org/)
+" Maintainer : Stefan Matthias Aust
+" Last Change: 2006 Apr 13
+
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal indentexpr=GetScalaIndent()
+
+setlocal indentkeys=0{,0},0),!^F,<>>,<CR>
+
+setlocal autoindent sw=2 et
+
+if exists("*GetScalaIndent")
+ finish
+endif
+
+function! CountParens(line)
+ let line = substitute(a:line, '"\(.\|\\"\)*"', '', 'g')
+ let open = substitute(line, '[^(]', '', 'g')
+ let close = substitute(line, '[^)]', '', 'g')
+ return strlen(open) - strlen(close)
+endfunction
+
+function! GetScalaIndent()
+ " Find a non-blank line above the current line.
+ let lnum = prevnonblank(v:lnum - 1)
+
+ " Hit the start of the file, use zero indent.
+ if lnum == 0
+ return 0
+ endif
+
+ let ind = indent(lnum)
+ let prevline = getline(lnum)
+
+ "Indent html literals
+ if prevline !~ '/>\s*$' && prevline =~ '^\s*<[a-zA-Z][^>]*>\s*$'
+ return ind + &shiftwidth
+ endif
+
+ " Add a 'shiftwidth' after lines that start a block
+ " If if, for or while end with ), this is a one-line block
+ " If val, var, def end with =, this is a one-line block
+ if prevline =~ '^\s*\<\(\(else\s\+\)\?if\|for\|while\|va[lr]\|def\)\>.*[)=]\s*$'
+ \ || prevline =~ '^\s*\<else\>\s*$'
+ \ || prevline =~ '{\s*$'
+ let ind = ind + &shiftwidth
+ endif
+
+ " If parenthesis are unbalanced, indent or dedent
+ let c = CountParens(prevline)
+ echo c
+ if c > 0
+ let ind = ind + &shiftwidth
+ elseif c < 0
+ let ind = ind - &shiftwidth
+ endif
+
+ " Dedent after if, for, while and val, var, def without block
+ let pprevline = getline(prevnonblank(lnum - 1))
+ if pprevline =~ '^\s*\<\(\(else\s\+\)\?if\|for\|while\|va[lr]\|def\)\>.*[)=]\s*$'
+ \ || pprevline =~ '^\s*\<else\>\s*$'
+ let ind = ind - &shiftwidth
+ endif
+
+ " Align 'for' clauses nicely
+ if prevline =~ '^\s*\<for\> (.*;\s*$'
+ let ind = ind - &shiftwidth + 5
+ endif
+
+ " Subtract a 'shiftwidth' on '}' or html
+ let thisline = getline(v:lnum)
+ if thisline =~ '^\s*[})]'
+ \ || thisline =~ '^\s*</[a-zA-Z][^>]*>'
+ let ind = ind - &shiftwidth
+ endif
+
+ return ind
+endfunction
diff --git a/vim/indent/scss.vim b/vim/indent/scss.vim
new file mode 100644
index 0000000..82bba49
--- /dev/null
+++ b/vim/indent/scss.vim
@@ -0,0 +1,12 @@
+" Vim indent file
+" Language: SCSS
+" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
+" Last Change: 2010 Jul 26
+
+if exists("b:did_indent")
+ finish
+endif
+
+runtime! indent/css.vim
+
+" vim:set sw=2: