diff options
| -rw-r--r-- | after/syntax/help.vim | 8 | ||||
| -rwxr-xr-x | build.sh | 2 | ||||
| -rw-r--r-- | ftdetect/sbt.vim | 6 | ||||
| -rw-r--r-- | ftdetect/scala.vim | 8 | ||||
| -rw-r--r-- | ftplugin/scala.vim | 166 | ||||
| -rw-r--r-- | ftplugin/scala.xpt.vim | 29 | ||||
| -rw-r--r-- | indent/scala.vim | 593 | ||||
| -rw-r--r-- | syntax/sbt.vim | 31 | ||||
| -rw-r--r-- | syntax/scala.vim | 192 | 
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 @@ -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 | 
