summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Stankiewicz <sheerun@sher.pl>2013-09-12 17:02:41 +0200
committerAdam Stankiewicz <sheerun@sher.pl>2013-09-12 17:02:41 +0200
commit0a4fcd12b6227ae9975d64353025e55e2e0caddf (patch)
treee7fd30c6aab1ecb25f0867acb43e3a403c5f4878
parent49b050f04240628288ee09b453280c522507477f (diff)
downloadvim-polyglot-0a4fcd12b6227ae9975d64353025e55e2e0caddf.tar.gz
vim-polyglot-0a4fcd12b6227ae9975d64353025e55e2e0caddf.zip
Add scala and sbt support
Diffstat (limited to '')
-rw-r--r--after/syntax/help.vim8
-rwxr-xr-xbuild.sh2
-rw-r--r--ftdetect/sbt.vim6
-rw-r--r--ftdetect/scala.vim8
-rw-r--r--ftplugin/scala.vim166
-rw-r--r--ftplugin/scala.xpt.vim29
-rw-r--r--indent/scala.vim593
-rw-r--r--syntax/sbt.vim31
-rw-r--r--syntax/scala.vim192
9 files changed, 1035 insertions, 0 deletions
diff --git a/after/syntax/help.vim b/after/syntax/help.vim
new file mode 100644
index 00000000..b352a1e6
--- /dev/null
+++ b/after/syntax/help.vim
@@ -0,0 +1,8 @@
+let b:current_syntax = ''
+unlet b:current_syntax
+syntax include @ScalaCode syntax/scala.vim
+if has('conceal')
+ syntax region rgnScala matchgroup=Ignore concealends start='!sc!' end='!/sc!' contains=@ScalaCode
+else
+ syntax region rgnScala matchgroup=Ignore start='!sc!' end='!/sc!' contains=@ScalaCode
+endif
diff --git a/build.sh b/build.sh
index 3b02b4da..4ad42e00 100755
--- a/build.sh
+++ b/build.sh
@@ -57,6 +57,8 @@ syntax 'vim-scripts/octave.vim--' &
syntax 'uggedal/go-vim' &
syntax 'spf13/PIV' &
syntax 'briancollins/vim-jst' &
+syntax 'derekwyatt/vim-scala' &
+syntax 'derekwyatt/vim-sbt' &
wait
diff --git a/ftdetect/sbt.vim b/ftdetect/sbt.vim
new file mode 100644
index 00000000..a508530c
--- /dev/null
+++ b/ftdetect/sbt.vim
@@ -0,0 +1,6 @@
+" Vim detect file
+" Language: sbt
+" Maintainer: Derek Wyatt <derek@{myfirstname}{mylastname}.org>
+" Last Change: 2012 Jan 19
+
+au BufRead,BufNewFile *.sbt set filetype=sbt
diff --git a/ftdetect/scala.vim b/ftdetect/scala.vim
new file mode 100644
index 00000000..997a701e
--- /dev/null
+++ b/ftdetect/scala.vim
@@ -0,0 +1,8 @@
+fun! s:DetectScala()
+ if getline(1) == '#!/usr/bin/env scala'
+ set filetype=scala
+ endif
+endfun
+
+au BufRead,BufNewFile *.scala,*.sbt set filetype=scala
+au BufRead,BufNewFile * call s:DetectScala()
diff --git a/ftplugin/scala.vim b/ftplugin/scala.vim
new file mode 100644
index 00000000..cdd1a74d
--- /dev/null
+++ b/ftplugin/scala.vim
@@ -0,0 +1,166 @@
+setlocal textwidth=140
+setlocal shiftwidth=2
+setlocal softtabstop=2
+setlocal expandtab
+setlocal formatoptions=tcqr
+setlocal commentstring=//%s
+
+set makeprg=sbt\ -Dsbt.log.noformat=true\ compile
+set efm=%E\ %#[error]\ %f:%l:\ %m,%C\ %#[error]\ %p^,%-C%.%#,%Z,
+ \%W\ %#[warn]\ %f:%l:\ %m,%C\ %#[warn]\ %p^,%-C%.%#,%Z,
+ \%-G%.%#
+
+if globpath(&rtp, 'plugin/fuf.vim') != ''
+ "
+ " FuzzyFinder stuff
+ "
+ "
+ " SanitizeDirForFuzzyFinder()
+ "
+ " This is really just a convenience function to clean up any stray '/'
+ " characters in the path, should they be there.
+ "
+ function! scala#SanitizeDirForFuzzyFinder(dir)
+ let dir = expand(a:dir)
+ let dir = substitute(dir, '/\+$', '', '')
+ let dir = substitute(dir, '/\+', '/', '')
+
+ return dir
+ endfunction
+
+ "
+ " GetDirForFuzzyFinder()
+ "
+ " Given a directory to start 'from', walk up the hierarchy, looking for a path
+ " that matches the 'addon' you want to see.
+ "
+ " If nothing can be found, then we just return the 'from' so we don't really get
+ " the advantage of a hint, but just let the user start from wherever he was
+ " starting from anyway.
+ "
+ function! scala#GetDirForFuzzyFinder(from, addon)
+ let from = scala#SanitizeDirForFuzzyFinder(a:from)
+ let addon = expand(a:addon)
+ let addon = substitute(addon, '^/\+', '', '')
+ let found = ''
+ " If the addon is right here, then we win
+ if isdirectory(from . '/' . addon)
+ let found = from . '/' . addon
+ else
+ let dirs = split(from, '/')
+ if !has('win32') && !has('win64')
+ let dirs[0] = '/' . dirs[0]
+ endif
+ " Walk up the tree and see if it's anywhere there
+ for n in range(len(dirs) - 1, 0, -1)
+ let path = join(dirs[0:n], '/')
+ if isdirectory(path . '/' . addon)
+ let found = path . '/' . addon
+ break
+ endif
+ endfor
+ endif
+ " If we found it, then let's see if we can go deeper
+ "
+ " For example, we may have found component_name/include
+ " but what if that directory only has a single directory
+ " in it, and that subdirectory only has a single directory
+ " in it, etc... ? This can happen when you're segmenting
+ " by namespace like this:
+ "
+ " component_name/include/org/vim/CoolClass.h
+ "
+ " You may find yourself always typing '' from the
+ " 'include' directory just to go into 'org/vim' so let's
+ " just eliminate the need to hit the ''.
+ if found != ''
+ let tempfrom = found
+ let globbed = globpath(tempfrom, '*')
+ while len(split(globbed, "\n")) == 1
+ let tempfrom = globbed
+ let globbed = globpath(tempfrom, '*')
+ endwhile
+ let found = scala#SanitizeDirForFuzzyFinder(tempfrom) . '/'
+ else
+ let found = from
+ endif
+
+ return found
+ endfunction
+
+ "
+ " GetTestDirForFuzzyFinder()
+ "
+ " Now overload GetDirForFuzzyFinder() specifically for the test directory (I'm
+ " really only interested in going down into test/src 90% of the time, so let's
+ " hit that 90% and leave the other 10% to couple of extra keystrokes)
+ "
+ function! scala#GetTestDirForFuzzyFinder(from)
+ return scala#GetDirForFuzzyFinder(a:from, 'src/test/scala/')
+ endfunction
+
+ "
+ " GetMainDirForFuzzyFinder()
+ "
+ " Now overload GetDirForFuzzyFinder() specifically for the main directory.
+ "
+ function! scala#GetMainDirForFuzzyFinder(from)
+ return scala#GetDirForFuzzyFinder(a:from, 'src/main/scala/')
+ endfunction
+
+ "
+ " GetRootDirForFuzzyFinder()
+ "
+ " Now overload GetDirForFuzzyFinder() specifically for the root directory.
+ "
+ function! scala#GetRootDirForFuzzyFinder(from)
+ return scala#GetDirForFuzzyFinder(a:from, 'src/../')
+ endfunction
+
+ nnoremap <buffer> <silent> ,ft :FufFile <c-r>=scala#GetTestDirForFuzzyFinder('%:p:h')<cr><cr>
+ nnoremap <buffer> <silent> ,fs :FufFile <c-r>=scala#GetMainDirForFuzzyFinder('%:p:h')<cr><cr>
+ nnoremap <buffer> <silent> ,fr :FufFile <c-r>=scala#GetRootDirForFuzzyFinder('%:p:h')<cr><cr>
+endif
+
+" If you want to disable the default key mappings, write the following line in
+" your ~/.vimrc
+" let g:scala_use_default_keymappings = 0
+if get(g:, 'scala_use_default_keymappings', 1)
+ nnoremap <buffer> ,jt :call JustifyCurrentLine()<cr>
+endif
+
+"
+" TagBar
+"
+let g:tagbar_type_scala = {
+ \ 'ctagstype' : 'scala',
+ \ 'kinds' : [
+ \ 'p:packages:1',
+ \ 'V:values',
+ \ 'v:variables',
+ \ 'T:types',
+ \ 't:traits',
+ \ 'o:objects',
+ \ 'a:aclasses',
+ \ 'c:classes',
+ \ 'r:cclasses',
+ \ 'm:methods'
+ \ ],
+ \ 'sro' : '.',
+ \ 'kind2scope' : {
+ \ 'T' : 'type',
+ \ 't' : 'trait',
+ \ 'o' : 'object',
+ \ 'a' : 'abstract class',
+ \ 'c' : 'class',
+ \ 'r' : 'case class'
+ \ },
+ \ 'scope2kind' : {
+ \ 'type' : 'T',
+ \ 'trait' : 't',
+ \ 'object' : 'o',
+ \ 'abstract class' : 'a',
+ \ 'class' : 'c',
+ \ 'case class' : 'r'
+ \ }
+\ }
diff --git a/ftplugin/scala.xpt.vim b/ftplugin/scala.xpt.vim
new file mode 100644
index 00000000..09d2b594
--- /dev/null
+++ b/ftplugin/scala.xpt.vim
@@ -0,0 +1,29 @@
+
+XPTemplate priority=lang
+
+XPTvar $BRif ' '
+XPTvar $BRel \n
+XPTvar $BRloop ' '
+XPTvar $BRfun ' '
+
+XPTinclude
+ \ _common/personal
+ \ java/java
+
+XPT cake hint=Cake\ Pattern
+XSET trait|def=Some
+XSET derived|def=Real
+trait `trait^Component {
+ trait `trait^ {
+ `body^
+ }
+
+ val `trait^SV('(.)', '\l\1', '')^^: `trait^
+}
+
+trait `derived^`trait^Component extends `trait^Component {
+
+ override lazy val `trait^SV('(.)', '\l\1', '')^^ = new `trait^ {
+ `body2^
+ }
+}
diff --git a/indent/scala.vim b/indent/scala.vim
new file mode 100644
index 00000000..da490ace
--- /dev/null
+++ b/indent/scala.vim
@@ -0,0 +1,593 @@
+" Vim indent file
+" Language : Scala (http://scala-lang.org/)
+" Original Author : Stefan Matthias Aust
+" Modifications by : Derek Wyatt
+" Last Change: 2011 Mar 19 (Derek Wyatt)
+
+"if exists("b:did_indent")
+" finish
+"endif
+"let b:did_indent = 1
+
+setlocal indentexpr=GetScalaIndent()
+setlocal indentkeys=0{,0},0),!^F,<>>,o,O,e,=case,<CR>
+setlocal autoindent
+
+"if exists("*GetScalaIndent")
+" finish
+"endif
+
+let s:defMatcher = '\%(\%(private\|protected\)\%(\[[^\]]*\]\)\?\s\+\|abstract\s\+\|override\s\+\)*\<def\>'
+let s:funcNameMatcher = '\w\+'
+let s:typeSpecMatcher = '\%(\s*\[\_[^\]]*\]\)'
+let s:defArgMatcher = '\%((\_.\{-})\)'
+let s:returnTypeMatcher = '\%(:\s*\w\+' . s:typeSpecMatcher . '\?\)'
+let g:fullDefMatcher = '^\s*' . s:defMatcher . '\s\+' . s:funcNameMatcher . '\s*' . s:typeSpecMatcher . '\?\s*' . s:defArgMatcher . '\?\s*' . s:returnTypeMatcher . '\?\s*[={]'
+
+function! scala#ConditionalConfirm(msg)
+ if 0
+ call confirm(a:msg)
+ endif
+endfunction
+
+function! scala#GetLine(lnum)
+ let line = substitute(getline(a:lnum), '//.*$', '', '')
+ let line = substitute(line, '"[^"]*"', '""', 'g')
+ return line
+endfunction
+
+function! scala#CountBrackets(line, openBracket, closedBracket)
+ let line = substitute(a:line, '"\(.\|\\"\)*"', '', 'g')
+ let open = substitute(line, '[^' . a:openBracket . ']', '', 'g')
+ let close = substitute(line, '[^' . a:closedBracket . ']', '', 'g')
+ return strlen(open) - strlen(close)
+endfunction
+
+function! scala#CountParens(line)
+ return scala#CountBrackets(a:line, '(', ')')
+endfunction
+
+function! scala#CountCurlies(line)
+ return scala#CountBrackets(a:line, '{', '}')
+endfunction
+
+function! scala#LineEndsInIncomplete(line)
+ if a:line =~ '[.,]\s*$'
+ return 1
+ else
+ return 0
+ endif
+endfunction
+
+function! scala#LineIsAClosingXML(line)
+ if a:line =~ '^\s*</\w'
+ return 1
+ else
+ return 0
+ endif
+endfunction
+
+function! scala#LineCompletesXML(lnum, line)
+ let savedpos = getpos('.')
+ call setpos('.', [savedpos[0], a:lnum, 0, savedpos[3]])
+ let tag = substitute(a:line, '^.*</\([^>]*\)>.*$', '\1', '')
+ let [lineNum, colnum] = searchpairpos('<' . tag . '>', '', '</' . tag . '>', 'Wbn')
+ call setpos('.', savedpos)
+ let pline = scala#GetLine(prevnonblank(lineNum - 1))
+ if pline =~ '=\s*$'
+ return 1
+ else
+ return 0
+ endif
+endfunction
+
+function! scala#IsParentCase()
+ let savedpos = getpos('.')
+ call setpos('.', [savedpos[0], savedpos[1], 0, savedpos[3]])
+ let [l, c] = searchpos('^\s*\%(' . s:defMatcher . '\|\%(\<case\>\)\)', 'bnW')
+ let retvalue = -1
+ if l != 0 && search('\%' . l . 'l\s*\<case\>', 'bnW')
+ let retvalue = l
+ endif
+ call setpos('.', savedpos)
+ return retvalue
+endfunction
+
+function! scala#CurlyMatcher()
+ let matchline = scala#GetLineThatMatchesBracket('{', '}')
+ if scala#CountParens(scala#GetLine(matchline)) < 0
+ let savedpos = getpos('.')
+ call setpos('.', [savedpos[0], matchline, 9999, savedpos[3]])
+ call searchpos('{', 'Wb')
+ call searchpos(')', 'Wb')
+ let [lnum, colnum] = searchpairpos('(', '', ')', 'Wbn')
+ call setpos('.', savedpos)
+ let line = scala#GetLine(lnum)
+ if line =~ '^\s*' . s:defMatcher
+ return lnum
+ else
+ return matchline
+ endif
+ else
+ return matchline
+ endif
+endfunction
+
+function! scala#GetLineAndColumnThatMatchesCurly()
+ return scala#GetLineAndColumnThatMatchesBracket('{', '}')
+endfunction
+
+function! scala#GetLineAndColumnThatMatchesParen()
+ return scala#GetLineAndColumnThatMatchesBracket('(', ')')
+endfunction
+
+function! scala#GetLineAndColumnThatMatchesBracket(openBracket, closedBracket)
+ let savedpos = getpos('.')
+ let curline = scala#GetLine(line('.'))
+ if curline =~ a:closedBracket . '.*' . a:openBracket . '.*' . a:closedBracket
+ call setpos('.', [savedpos[0], savedpos[1], 0, savedpos[3]])
+ call searchpos(a:closedBracket . '\ze[^' . a:closedBracket . a:openBracket . ']*' . a:openBracket, 'W')
+ else
+ call setpos('.', [savedpos[0], savedpos[1], 9999, savedpos[3]])
+ call searchpos(a:closedBracket, 'Wb')
+ endif
+ let [lnum, colnum] = searchpairpos(a:openBracket, '', a:closedBracket, 'Wbn')
+ call setpos('.', savedpos)
+ return [lnum, colnum]
+endfunction
+
+function! scala#GetLineThatMatchesCurly()
+ return scala#GetLineThatMatchesBracket('{', '}')
+endfunction
+
+function! scala#GetLineThatMatchesParen()
+ return scala#GetLineThatMatchesBracket('(', ')')
+endfunction
+
+function! scala#GetLineThatMatchesBracket(openBracket, closedBracket)
+ let [lnum, colnum] = scala#GetLineAndColumnThatMatchesBracket(a:openBracket, a:closedBracket)
+ return lnum
+endfunction
+
+function! scala#NumberOfBraceGroups(line)
+ let line = substitute(a:line, '[^()]', '', 'g')
+ if strlen(line) == 0
+ return 0
+ endif
+ let line = substitute(line, '^)*', '', 'g')
+ if strlen(line) == 0
+ return 0
+ endif
+ let line = substitute(line, '^(', '', 'g')
+ if strlen(line) == 0
+ return 0
+ endif
+ let c = 1
+ let counter = 0
+ let groupCount = 0
+ while counter < strlen(line)
+ let char = strpart(line, counter, 1)
+ if char == '('
+ let c = c + 1
+ elseif char == ')'
+ let c = c - 1
+ endif
+ if c == 0
+ let groupCount = groupCount + 1
+ endif
+ let counter = counter + 1
+ endwhile
+ return groupCount
+endfunction
+
+function! scala#MatchesIncompleteDefValr(line)
+ if a:line =~ '^\s*\%(' . s:defMatcher . '\|\<va[lr]\>\).*[=({]\s*$'
+ return 1
+ else
+ return 0
+ endif
+endfunction
+
+function! scala#LineIsCompleteIf(line)
+ if scala#CountBrackets(a:line, '{', '}') == 0 &&
+ \ scala#CountBrackets(a:line, '(', ')') == 0 &&
+ \ a:line =~ '^\s*\<if\>\s*([^)]*)\s*\S.*$'
+ return 1
+ else
+ return 0
+ endif
+endfunction
+
+function! scala#LineCompletesIfElse(lnum, line)
+ if a:line =~ '^\s*\%(\<if\>\|\%(}\s*\)\?\<else\>\)'
+ return 0
+ endif
+ let result = search('^\%(\s*\<if\>\s*(.*).*\n\|\s*\<if\>\s*(.*)\s*\n.*\n\)\%(\s*\<else\>\s*\<if\>\s*(.*)\s*\n.*\n\)*\%(\s*\<else\>\s*\n\|\s*\<else\>[^{]*\n\)\?\%' . a:lnum . 'l', 'Wbn')
+ if result != 0 && scala#GetLine(prevnonblank(a:lnum - 1)) !~ '{\s*$'
+ return result
+ endif
+ return 0
+endfunction
+
+function! scala#GetPrevCodeLine(lnum)
+ " This needs to skip comment lines
+ return prevnonblank(a:lnum - 1)
+endfunction
+
+function! scala#InvertBracketType(openBracket, closedBracket)
+ if a:openBracket == '('
+ return [ '{', '}' ]
+ else
+ return [ '(', ')' ]
+ endif
+endfunction
+
+function! scala#Testhelper(lnum, line, openBracket, closedBracket, iteration)
+ let bracketCount = scala#CountBrackets(a:line, a:openBracket, a:closedBracket)
+ " There are more '}' braces than '{' on this line so it may be completing the function definition
+ if bracketCount < 0
+ let [matchedLNum, matchedColNum] = scala#GetLineAndColumnThatMatchesBracket(a:openBracket, a:closedBracket)
+ if matchedLNum == a:lnum
+ return -1
+ endif
+ let matchedLine = scala#GetLine(matchedLNum)
+ if ! scala#MatchesIncompleteDefValr(matchedLine)
+ let bracketLine = substitute(substitute(matchedLine, '\%' . matchedColNum . 'c.*$', '', ''), '[^{}()]', '', 'g')
+ if bracketLine =~ '}$'
+ return scala#Testhelper(matchedLNum, matchedLine, '{', '}', a:iteration + 1)
+ elseif bracketLine =~ ')$'
+ return scala#Testhelper(matchedLNum, matchedLine, '(', ')', a:iteration + 1)
+ else
+ let prevCodeLNum = scala#GetPrevCodeLine(matchedLNum)
+ if scala#MatchesIncompleteDefValr(scala#GetLine(prevCodeLNum))
+ return prevCodeLNum
+ else
+ return -1
+ endif
+ endif
+ else
+ " return indent value instead
+ return matchedLNum
+ endif
+ " There's an equal number of '{' and '}' on this line so it may be a single line function definition
+ elseif bracketCount == 0
+ if a:iteration == 0
+ let otherBracketType = scala#InvertBracketType(a:openBracket, a:closedBracket)
+ return scala#Testhelper(a:lnum, a:line, otherBracketType[0], otherBracketType[1], a:iteration + 1)
+ else
+ let prevCodeLNum = scala#GetPrevCodeLine(a:lnum)
+ let prevCodeLine = scala#GetLine(prevCodeLNum)
+ if scala#MatchesIncompleteDefValr(prevCodeLine) && prevCodeLine !~ '{\s*$'
+ return prevCodeLNum
+ else
+ let possibleIfElse = scala#LineCompletesIfElse(a:lnum, a:line)
+ if possibleIfElse != 0
+ let defValrLine = prevnonblank(possibleIfElse - 1)
+ let possibleDefValr = scala#GetLine(defValrLine)
+ if scala#MatchesIncompleteDefValr(possibleDefValr) && possibleDefValr =~ '^.*=\s*$'
+ return possibleDefValr
+ else
+ return -1
+ endif
+ else
+ return -1
+ endif
+ endif
+ endif
+ else
+ return -1
+ endif
+endfunction
+
+function! scala#Test(lnum, line, openBracket, closedBracket)
+ return scala#Testhelper(a:lnum, a:line, a:openBracket, a:closedBracket, 0)
+endfunction
+
+function! scala#LineCompletesDefValr(lnum, line)
+ let bracketCount = scala#CountBrackets(a:line, '{', '}')
+ if bracketCount < 0
+ let matchedBracket = scala#GetLineThatMatchesBracket('{', '}')
+ if ! scala#MatchesIncompleteDefValr(scala#GetLine(matchedBracket))
+ let possibleDefValr = scala#GetLine(prevnonblank(matchedBracket - 1))
+ if matchedBracket != -1 && scala#MatchesIncompleteDefValr(possibleDefValr)
+ return 1
+ else
+ return 0
+ endif
+ else
+ return 0
+ endif
+ elseif bracketCount == 0
+ let bracketCount = scala#CountBrackets(a:line, '(', ')')
+ if bracketCount < 0
+ let matchedBracket = scala#GetLineThatMatchesBracket('(', ')')
+ if ! scala#MatchesIncompleteDefValr(scala#GetLine(matchedBracket))
+ let possibleDefValr = scala#GetLine(prevnonblank(matchedBracket - 1))
+ if matchedBracket != -1 && scala#MatchesIncompleteDefValr(possibleDefValr)
+ return 1
+ else
+ return 0
+ endif
+ else
+ return 0
+ endif
+ elseif bracketCount == 0
+ let possibleDefValr = scala#GetLine(prevnonblank(a:lnum - 1))
+ if scala#MatchesIncompleteDefValr(possibleDefValr) && possibleDefValr =~ '^.*=\s*$'
+ return 1
+ else
+ let possibleIfElse = scala#LineCompletesIfElse(a:lnum, a:line)
+ if possibleIfElse != 0
+ let possibleDefValr = scala#GetLine(prevnonblank(possibleIfElse - 1))
+ if scala#MatchesIncompleteDefValr(possibleDefValr) && possibleDefValr =~ '^.*=\s*$'
+ return 2
+ else
+ return 0
+ endif
+ else
+ return 0
+ endif
+ endif
+ else
+ return 0
+ endif
+ endif
+endfunction
+
+function! scala#SpecificLineCompletesBrackets(lnum, openBracket, closedBracket)
+ let savedpos = getpos('.')
+ call setpos('.', [savedpos[0], a:lnum, 9999, savedpos[3]])
+ let retv = scala#LineCompletesBrackets(a:openBracket, a:closedBracket)
+ call setpos('.', savedpos)
+
+ return retv
+endfunction
+
+function! scala#LineCompletesBrackets(openBracket, closedBracket)
+ let savedpos = getpos('.')
+ let offline = 0
+ while offline == 0
+ let [lnum, colnum] = searchpos(a:closedBracket, 'Wb')
+ let [lnumA, colnumA] = searchpairpos(a:openBracket, '', a:closedBracket, 'Wbn')
+ if lnum != lnumA
+ let [lnumB, colnumB] = searchpairpos(a:openBracket, '', a:closedBracket, 'Wbnr')
+ let offline = 1
+ endif
+ endwhile
+ call setpos('.', savedpos)
+ if lnumA == lnumB && colnumA == colnumB
+ return lnumA
+ else
+ return -1
+ endif
+endfunction
+
+function! GetScalaIndent()
+ " Find a non-blank line above the current line.
+ let prevlnum = prevnonblank(v:lnum - 1)
+
+ " Hit the start of the file, use zero indent.
+ if prevlnum == 0
+ return 0
+ endif
+
+ let ind = indent(prevlnum)
+ let originalIndentValue = ind
+ let prevline = scala#GetLine(prevlnum)
+ let curlnum = v:lnum
+ let curline = scala#GetLine(curlnum)
+
+ if prevline =~ '^\s*/\*\*'
+ return ind + 1
+ endif
+
+ if curline =~ '^\s*\*'
+ return cindent(curlnum)
+ endif
+
+ " If this line starts with a { then make it indent the same as the previous line
+ if curline =~ '^\s*{'
+ call scala#ConditionalConfirm("1")
+ " Unless, of course, the previous one is a { as well
+ if prevline !~ '^\s*{'
+ call scala#ConditionalConfirm("2")
+ return indent(prevlnum)
+ endif
+ endif
+
+ " '.' continuations
+ if curline =~ '^\s*\.'
+ if prevline =~ '^\s*\.'
+ return ind
+ else
+ return ind + &shiftwidth
+ endif
+ endif
+
+ " Indent html literals
+ if prevline !~ '/>\s*$' && prevline =~ '^\s*<[a-zA-Z][^>]*>\s*$'
+ call scala#ConditionalConfirm("3")
+ return ind + &shiftwidth
+ endif
+
+ " assumes curly braces around try-block
+ if curline =~ '^\s*}\s*\<catch\>'
+ return ind - &shiftwidth
+ elseif curline =~ '^\s*\<catch\>'
+ return ind
+ 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*\<\%(\%(}\?\s*else\s\+\)\?if\|for\|while\)\>.*[)=]\s*$' && scala#NumberOfBraceGroups(prevline) <= 1)
+ \ || prevline =~ '^\s*' . s:defMatcher . '.*=\s*$'
+ \ || prevline =~ '^\s*\<va[lr]\>.*[=]\s*$'
+ \ || prevline =~ '^\s*\%(}\s*\)\?\<else\>\s*$'
+ \ || prevline =~ '=\s*$'
+ call scala#ConditionalConfirm("4")
+ let ind = ind + &shiftwidth
+ elseif prevline =~ '^\s*\<\%(}\?\s*else\s\+\)\?if\>' && curline =~ '^\s*}\?\s*\<else\>'
+ return ind
+ endif
+
+ let lineCompletedBrackets = 0
+ let bracketCount = scala#CountBrackets(prevline, '{', '}')
+ if bracketCount > 0 || prevline =~ '.*{\s*$'
+ call scala#ConditionalConfirm("5b")
+ let ind = ind + &shiftwidth
+ elseif bracketCount < 0
+ call scala#ConditionalConfirm("6b")
+ " if the closing brace actually completes the braces entirely, then we
+ " have to indent to line that started the whole thing
+ let completeLine = scala#LineCompletesBrackets('{', '}')
+ if completeLine != -1
+ call scala#ConditionalConfirm("8b")
+ let prevCompleteLine = scala#GetLine(prevnonblank(completeLine - 1))
+ " However, what actually started this part looks like it was a function
+ " definition, so we need to indent to that line instead. This is
+ " actually pretty weak at the moment.
+ if prevCompleteLine =~ '=\s*$'
+ call scala#ConditionalConfirm("9b")
+ let ind = indent(prevnonblank(completeLine - 1))
+ else
+ call scala#ConditionalConfirm("10b")
+ let ind = indent(completeLine)
+ endif
+ else
+ let lineCompletedBrackets = 1
+ endif
+ endif
+
+ if ind == originalIndentValue
+ let bracketCount = scala#CountBrackets(prevline, '(', ')')
+ if bracketCount > 0 || prevline =~ '.*(\s*$'
+ call scala#ConditionalConfirm("5a")
+ let ind = ind + &shiftwidth
+ elseif bracketCount < 0
+ call scala#ConditionalConfirm("6a")
+ " if the closing brace actually completes the braces entirely, then we
+ " have to indent to line that started the whole thing
+ let completeLine = scala#LineCompletesBrackets('(', ')')
+ if completeLine != -1 && prevline !~ '^.*{\s*$'
+ call scala#ConditionalConfirm("8a")
+ let prevCompleteLine = scala#GetLine(prevnonblank(completeLine - 1))
+ " However, what actually started this part looks like it was a function
+ " definition, so we need to indent to that line instead. This is
+ " actually pretty weak at the moment.
+ if prevCompleteLine =~ '=\s*$'
+ call scala#ConditionalConfirm("9a")
+ let ind = indent(prevnonblank(completeLine - 1))
+ else
+ call scala#ConditionalConfirm("10a")
+ let ind = indent(completeLine)
+ endif
+ else
+ " This is the only part that's different from from the '{', '}' one below
+ " Yup... some refactoring is necessary at some point.
+ let ind = ind + (bracketCount * &shiftwidth)
+ let lineCompletedBrackets = 1
+ endif
+ endif
+ endif
+
+ if curline =~ '^\s*}\?\s*\<else\>\%(\s\+\<if\>\s*(.*)\)\?\s*{\?\s*$' &&
+ \ ! scala#LineIsCompleteIf(prevline) &&
+ \ prevline !~ '^.*}\s*$'
+ let ind = ind - &shiftwidth
+ endif
+
+ " Subtract a 'shiftwidth' on '}' or html
+ let curCurlyCount = scala#CountCurlies(curline)
+ if curCurlyCount < 0
+ call scala#ConditionalConfirm("14a")
+ let matchline = scala#CurlyMatcher()
+ return indent(matchline)
+ elseif curline =~ '^\s*</[a-zA-Z][^>]*>'
+ call scala#ConditionalConfirm("14c")
+ return ind - &shiftwidth
+ endif
+
+ let prevParenCount = scala#CountParens(prevline)
+ if prevline =~ '^\s*\<for\>.*$' && prevParenCount > 0
+ call scala#ConditionalConfirm("15")
+ let ind = indent(prevlnum) + 5
+ endif
+
+ let prevCurlyCount = scala#CountCurlies(prevline)
+ if prevCurlyCount == 0 && prevline =~ '^.*=>\s*$' && prevline !~ '^\s*this\s*:.*=>\s*$' && curline !~ '^\s*\<case\>'
+ call scala#ConditionalConfirm("16")
+ let ind = ind + &shiftwidth
+ endif
+
+ if ind == originalIndentValue && curline =~ '^\s*\<case\>'
+ call scala#ConditionalConfirm("17")
+ let parentCase = scala#IsParentCase()
+ if parentCase != -1
+ call scala#ConditionalConfirm("17a")
+ return indent(parentCase)
+ endif
+ endif
+
+ if prevline =~ '^\s*\*/'
+ \ || prevline =~ '*/\s*$'
+ call scala#ConditionalConfirm("18")
+ let ind = ind - 1
+ endif
+
+ if scala#LineEndsInIncomplete(curline)
+ call scala#ConditionalConfirm("19")
+ return ind
+ endif
+
+ if scala#LineIsAClosingXML(prevline)
+ if scala#LineCompletesXML(prevlnum, prevline)
+ call scala#ConditionalConfirm("20a")
+ return ind - &shiftwidth
+ else
+ call scala#ConditionalConfirm("20b")
+ return ind
+ endif
+ endif
+
+ if ind == originalIndentValue
+ "let indentMultiplier = scala#LineCompletesDefValr(prevlnum, prevline)
+ "if indentMultiplier != 0
+ " call scala#ConditionalConfirm("19a")
+ " let ind = ind - (indentMultiplier * &shiftwidth)
+ let defValrLine = scala#Test(prevlnum, prevline, '{', '}')
+ if defValrLine != -1
+ call scala#ConditionalConfirm("21a")
+ let ind = indent(defValrLine)
+ elseif lineCompletedBrackets == 0
+ call scala#ConditionalConfirm("21b")
+ if scala#GetLine(prevnonblank(prevlnum - 1)) =~ '^.*\<else\>\s*\%(//.*\)\?$'
+ call scala#ConditionalConfirm("21c")
+ let ind = ind - &shiftwidth
+ elseif scala#LineCompletesIfElse(prevlnum, prevline)
+ call scala#ConditionalConfirm("21d")
+ let ind = ind - &shiftwidth
+ elseif scala#CountParens(curline) < 0 && curline =~ '^\s*)' && scala#GetLine(scala#GetLineThatMatchesBracket('(', ')')) =~ '.*(\s*$'
+ " Handles situations that look like this:
+ "
+ " val a = func(
+ " 10
+ " )
+ "
+ " or
+ "
+ " val a = func(
+ " 10
+ " ).somethingHere()
+ call scala#ConditionalConfirm("21e")
+ let ind = ind - &shiftwidth
+ endif
+ endif
+ endif
+
+ call scala#ConditionalConfirm("returning " . ind)
+
+ return ind
+endfunction
+" vim:set ts=2 sts=2 sw=2:
+" vim600:fdm=marker fdl=1 fdc=0:
diff --git a/syntax/sbt.vim b/syntax/sbt.vim
new file mode 100644
index 00000000..1af382e1
--- /dev/null
+++ b/syntax/sbt.vim
@@ -0,0 +1,31 @@
+" Vim syntax file
+" Language: sbt
+" Maintainer: Derek Wyatt <derek@{myfirstname}{mylastname}.org>
+" Last Change: 2012 Jan 19
+
+if exists("b:current_syntax")
+ finish
+endif
+
+runtime! syntax/scala.vim
+
+syn region sbtString start="\"[^"]" skip="\\\"" end="\"" contains=sbtStringEscape
+syn match sbtStringEscape "\\u[0-9a-fA-F]\{4}" contained
+syn match sbtStringEscape "\\[nrfvb\\\"]" contained
+
+syn match sbtIdentitifer "^\S\+\ze\s*\(:=\|++=\|+=\|<<=\|<+=\)"
+syn match sbtBeginningSeq "^[Ss]eq\>"
+
+syn match sbtSpecial "\(:=\|++=\|+=\|<<=\|<+=\)"
+
+syn match sbtLineComment "//.*"
+syn region sbtComment start="/\*" end="\*/"
+syn region sbtDocComment start="/\*\*" end="\*/" keepend
+
+hi link sbtString String
+hi link sbtIdentitifer Keyword
+hi link sbtBeginningSeq Keyword
+hi link sbtSpecial Special
+hi link sbtComment Comment
+hi link sbtLineComment Comment
+hi link sbtDocComment Comment
diff --git a/syntax/scala.vim b/syntax/scala.vim
new file mode 100644
index 00000000..a6191148
--- /dev/null
+++ b/syntax/scala.vim
@@ -0,0 +1,192 @@
+" Vim syntax file
+" Language : Scala (http://scala-lang.org/)
+" Maintainers: Stefan Matthias Aust, Julien Wetterwald
+" Last Change: 2007 June 13
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+syn case match
+syn sync minlines=50 maxlines=100
+
+" most Scala keywords
+syn keyword scalaKeyword case
+syn keyword scalaKeyword catch
+syn keyword scalaKeyword do
+syn keyword scalaKeyword else
+syn keyword scalaKeyword extends
+syn keyword scalaKeyword final
+syn keyword scalaKeyword finally
+syn keyword scalaKeyword for
+syn keyword scalaKeyword forSome
+syn keyword scalaKeyword if
+syn keyword scalaKeyword match
+syn keyword scalaKeyword new
+syn keyword scalaKeyword null
+syn keyword scalaKeyword require
+syn keyword scalaKeyword return
+syn keyword scalaKeyword super
+syn keyword scalaKeyword this
+syn keyword scalaKeyword throw
+syn keyword scalaKeyword try
+syn keyword scalaKeyword type
+syn keyword scalaKeyword while
+syn keyword scalaKeyword with
+syn keyword scalaKeyword yield
+syn keyword scalaKeywordModifier abstract
+syn keyword scalaKeywordModifier override
+syn keyword scalaKeywordModifier final
+syn keyword scalaKeywordModifier implicit
+syn keyword scalaKeywordModifier lazy
+syn keyword scalaKeywordModifier private
+syn keyword scalaKeywordModifier protected
+syn keyword scalaKeywordModifier sealed
+syn match scalaKeyword "=>"
+syn match scalaKeyword "<-"
+syn match scalaKeyword "\<_\>"
+
+syn match scalaOperator ":\{2,\}" "this is not a type
+
+" package and import statements
+syn keyword scalaPackage package nextgroup=scalaFqn skipwhite
+syn keyword scalaImport import nextgroup=scalaFqn skipwhite
+syn match scalaFqn "\<[._$a-zA-Z0-9,]*" contained nextgroup=scalaFqnSet
+syn region scalaFqnSet start="{" end="}" contained
+
+" boolean literals
+syn keyword scalaBoolean true false
+
+" definitions
+syn keyword scalaDef def nextgroup=scalaDefName skipwhite
+syn keyword scalaVal val nextgroup=scalaValName skipwhite
+syn keyword scalaVar var nextgroup=scalaVarName skipwhite
+syn keyword scalaClass class nextgroup=scalaClassName skipwhite
+syn keyword scalaObject object nextgroup=scalaClassName skipwhite
+syn keyword scalaTrait trait nextgroup=scalaClassName skipwhite
+syn match scalaDefName "[^ =:;([]\+" contained nextgroup=scalaDefSpecializer skipwhite
+syn match scalaValName "[^ =:;([]\+" contained
+syn match scalaVarName "[^ =:;([]\+" contained
+syn match scalaClassName "[^ =:;(\[]\+" contained nextgroup=scalaClassSpecializer skipwhite
+syn region scalaDefSpecializer start="\[" end="\]" contained contains=scalaDefSpecializer
+syn region scalaClassSpecializer start="\[" end="\]" contained contains=scalaClassSpecializer
+syn match scalaBackTick "`[^`]\+`"
+
+" type constructor (actually anything with an uppercase letter)
+syn match scalaConstructor "\<[A-Z][_$a-zA-Z0-9]*\>" nextgroup=scalaConstructorSpecializer
+syn region scalaConstructorSpecializer start="\[" end="\]" contained contains=scalaConstructorSpecializer
+
+" method call
+syn match scalaRoot "\<[a-zA-Z][_$a-zA-Z0-9]*\."me=e-1
+syn match scalaMethodCall "\.[a-z][_$a-zA-Z0-9]*"ms=s+1
+
+" type declarations in val/var/def
+syn match scalaType ":\s*\%(=>\s*\)\?\%([\._$a-zA-Z0-9]\+\|([^)]\{-1,})\)\%(\[[^\]]\{-1,}\]\+\%([^)]*)\]\+\)\?\)\?\%(\s*\%(<:\|>:\|#\|=>\|⇒\)\s*\%([\._$a-zA-Z0-9]\+\|([^)]\{-1,})\)\%(\[[^\]]\{-1,}\]\+\%([^)]*)\]\+\)\?\)*\)*"ms=s+1
+" type declarations in case statements
+syn match scalaCaseType "\(case\s\+[_a-zA-Z0-9]\+\)\@<=:\s*[\._$a-zA-Z0-9]\+\(\[[^:]\{-1,}\]\+\)\?"ms=s+1
+
+" comments
+syn match scalaTodo "[tT][oO][dD][oO]" contained
+syn match scalaLineComment "//.*" contains=scalaTodo
+syn region scalaComment start="/\*" end="\*/" contains=scalaTodo
+syn case ignore
+syn include @scalaHtml syntax/html.vim
+syn case match
+syn region scalaDocComment start="/\*\*" end="\*/" contains=scalaDocTags,scalaTodo,@scalaHtml keepend
+syn region scalaDocTags start="{@\(link\|linkplain\|inherit[Dd]oc\|doc[rR]oot\|value\)" end="}" contained
+syn match scalaDocTags "@[a-z]\+" contained
+
+" annotations
+syn match scalaAnnotation "@[a-zA-Z]\+"
+
+syn match scalaEmptyString "\"\""
+
+" multi-line string literals
+syn region scalaMultiLineString start="\"\"\"" end="\"\"\"\"\@!" contains=scalaUnicode
+syn match scalaUnicode "\\u[0-9a-fA-F]\{4}" contained
+
+" string literals with escapes
+syn region scalaString start="\"[^"]" skip="\\\"" end="\"" contains=scalaStringEscape " TODO end \n or not?
+syn match scalaStringEscape "\\u[0-9a-fA-F]\{4}" contained
+syn match scalaStringEscape "\\[nrfvb\\\"]" contained
+
+" symbol and character literals
+syn match scalaSymbol "'[_a-zA-Z0-9][_a-zA-Z0-9]*\>"
+syn match scalaChar "'[^'\\]'\|'\\.'\|'\\u[0-9a-fA-F]\{4}'"
+
+" number literals
+syn match scalaNumber "\<\(0[0-7]*\|0[xX]\x\+\|\d\+\)[lL]\=\>"
+syn match scalaNumber "\(\<\d\+\.\d*\|\.\d\+\)\([eE][-+]\=\d\+\)\=[fFdD]\="
+syn match scalaNumber "\<\d\+[eE][-+]\=\d\+[fFdD]\=\>"
+syn match scalaNumber "\<\d\+\([eE][-+]\=\d\+\)\=[fFdD]\>"
+
+" xml literals
+syn match scalaXmlTag "<[a-zA-Z]\_[^>]*/>" contains=scalaXmlQuote,scalaXmlEscape,scalaXmlString
+syn region scalaXmlString start="\"" end="\"" contained
+syn match scalaXmlStart "<[a-zA-Z]\_[^>]*>" contained contains=scalaXmlQuote,scalaXmlEscape,scalaXmlString
+syn region scalaXml start="<\([a-zA-Z]\_[^>]*\_[^/]\|[a-zA-Z]\)>" matchgroup=scalaXmlStart end="</\_[^>]\+>" contains=scalaXmlEscape,scalaXmlQuote,scalaXml,scalaXmlStart,scalaXmlComment
+syn region scalaXmlEscape matchgroup=scalaXmlEscapeSpecial start="{" matchgroup=scalaXmlEscapeSpecial end="}" contained contains=TOP
+syn match scalaXmlQuote "&[^;]\+;" contained
+syn match scalaXmlComment "<!--\_[^>]*-->" contained
+
+" REPL
+syn match scalaREPLCmdLine "\<scala>\>"
+
+" map Scala groups to standard groups
+hi link scalaKeyword Keyword
+hi link scalaKeywordModifier Function
+hi link scalaAnnotation Include
+hi link scalaPackage Include
+hi link scalaImport Include
+hi link scalaREPLCmdLine Include
+hi link scalaDocTags Include
+hi link scalaBackTick Include
+hi link scalaBoolean Boolean
+hi link scalaOperator Normal
+hi link scalaNumber Number
+hi link scalaEmptyString String
+hi link scalaString String
+hi link scalaChar String
+hi link scalaMultiLineString String
+hi link scalaStringEscape Special
+hi link scalaSymbol Special
+hi link scalaUnicode Special
+hi link scalaComment Comment
+hi link scalaLineComment Comment
+hi link scalaDocComment Comment
+hi link scalaTodo Todo
+hi link scalaType Type
+hi link scalaCaseType Type
+hi link scalaTypeSpecializer scalaType
+hi link scalaXml String
+hi link scalaXmlTag Include
+hi link scalaXmlString String
+hi link scalaXmlStart Include
+hi link scalaXmlEscape Normal
+hi link scalaXmlEscapeSpecial Special
+hi link scalaXmlQuote Special
+hi link scalaXmlComment Comment
+hi link scalaDef Keyword
+hi link scalaVar Keyword
+hi link scalaVal Keyword
+hi link scalaClass Keyword
+hi link scalaObject Keyword
+hi link scalaTrait Keyword
+hi link scalaDefName Function
+hi link scalaDefSpecializer Function
+hi link scalaClassName Special
+hi link scalaClassSpecializer Special
+hi link scalaConstructor Special
+hi link scalaConstructorSpecializer scalaConstructor
+
+let b:current_syntax = "scala"
+
+" you might like to put these lines in your .vimrc
+"
+" customize colors a little bit (should be a different file)
+" hi scalaNew gui=underline
+" hi scalaMethodCall gui=italic
+" hi scalaValName gui=underline
+" hi scalaVarName gui=underline