diff --git a/build.sh b/build.sh index 34594a8..dd06af0 100755 --- a/build.sh +++ b/build.sh @@ -65,6 +65,7 @@ syntax 'beyondwords/vim-twig' & syntax 'sudar/vim-arduino-syntax' & syntax 'guns/vim-clojure-static' & syntax 'chrisbra/csv.vim' & +syntax 'elixir-lang/vim-elixir' & wait diff --git a/compiler/exunit.vim b/compiler/exunit.vim new file mode 100644 index 0000000..2c9fb29 --- /dev/null +++ b/compiler/exunit.vim @@ -0,0 +1,24 @@ +" Vim compiler file +" Language: ExUnit +" Maintainer: Rein Henrichs +" URL: https://github.com/elixir-lang/vim-elixir + +if exists("current_compiler") + finish +endif +let current_compiler = "exunit" + +if exists(":CompilerSet") != 2 " older Vim always used :setlocal + command -nargs=* CompilerSet setlocal +endif + +let s:cpo_save = &cpo +set cpo-=C + +CompilerSet makeprg=mix\ test +CompilerSet errorformat=%A\ \ %.)\ %m(%.%#),%C\ \ \ \ \ **%m,%C\ \ \ \ \ \ \ %m,%Z\ \ \ \ \ at\ %f:%l,%-G%.%# + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: nowrap sw=2 sts=2 ts=8: diff --git a/ftdetect/elixir.vim b/ftdetect/elixir.vim new file mode 100644 index 0000000..df413e1 --- /dev/null +++ b/ftdetect/elixir.vim @@ -0,0 +1,2 @@ +au BufRead,BufNewFile *.ex,*.exs set filetype=elixir +au FileType elixir setl sw=2 sts=2 et iskeyword+=!,? diff --git a/ftplugin/elixir.vim b/ftplugin/elixir.vim new file mode 100644 index 0000000..5571fcf --- /dev/null +++ b/ftplugin/elixir.vim @@ -0,0 +1,25 @@ +" Vim filetype plugin +" Language: Elixir +" Maintainer: Carlos Galdino +" URL: https://github.com/elixir-lang/vim-elixir + +if (exists("b:did_ftplugin")) + finish +endif +let b:did_ftplugin = 1 + + +" Matchit support +if exists("loaded_matchit") && !exists("b:match_words") + let b:match_ignorecase = 0 + + let b:match_words = '\<\%(do\|fn\)\:\@!\>' . + \ ':' . + \ '\<\%(else\|elsif\|catch\|after\|rescue\)\:\@!\>' . + \ ':' . + \ '\:\@' . + \ ',{:},\[:\],(:)' +endif + +setlocal comments=:# +setlocal commentstring=#\ %s diff --git a/indent/elixir.vim b/indent/elixir.vim new file mode 100644 index 0000000..54bc828 --- /dev/null +++ b/indent/elixir.vim @@ -0,0 +1,61 @@ +" Vim indent file +" Language: Elixir +" Maintainer: Carlos Galdino +" Last Change: 2013 Apr 24 + +if exists("b:did_indent") + finish +endif +let b:did_indent = 1 + +setlocal nosmartindent + +setlocal indentexpr=GetElixirIndent(v:lnum) +setlocal indentkeys+==end,=else:,=match:,=elsif:,=catch:,=after:,=rescue: + +if exists("*GetElixirIndent") + finish +endif + +let s:cpo_save = &cpo +set cpo&vim + +let s:skip_syntax = '\%(Comment\|String\)$' +let s:block_skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" . s:skip_syntax . "'" +let s:block_start = 'do\|fn' +let s:block_middle = 'else\|match\|elsif\|catch\|after\|rescue' +let s:block_end = 'end' + +let s:indent_keywords = '\<\%(' . s:block_start . '\|' . s:block_middle . '\)$' +let s:deindent_keywords = '^\s*\<\%(' . s:block_end . '\|' . s:block_middle . '\)\>' + +function! GetElixirIndent(...) + let lnum = prevnonblank(v:lnum - 1) + let ind = indent(lnum) + + " At the start of the file use zero indent. + if lnum == 0 + return 0 + endif + + if synIDattr(synID(v:lnum, 1, 1), "name") !~ '\(Comment\|String\)$' + if getline(lnum) =~ s:indent_keywords . + \ '\|^\s*\%(^.*[\[{(].*[,:]\|.*->\)$' + let ind += &sw + endif + + if getline(v:lnum) =~ s:deindent_keywords + let bslnum = searchpair( '\<\%(' . s:block_start . '\):\@!\>', + \ '\<\%(' . s:block_middle . '\):\@!\>\zs', + \ '\<:\@\zs', + \ 'nbW', + \ s:block_skip ) + let ind = indent(bslnum) + endif + endif + + return ind +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/syntax/elixir.vim b/syntax/elixir.vim new file mode 100644 index 0000000..7dc428e --- /dev/null +++ b/syntax/elixir.vim @@ -0,0 +1,162 @@ +" Vim syntax file +" Language: Elixir +" Maintainer: Carlos Galdino +" Last Change: 2013 Apr 24 + +if exists("b:current_syntax") + finish +endif + +" syncing starts 2000 lines before top line so docstrings don't screw things up +syn sync minlines=2000 + +syn cluster elixirNotTop contains=@elixirRegexSpecial,@elixirStringContained,@elixirDeclaration,elixirTodo,elixirArguments + +syn match elixirComment '#.*' contains=elixirTodo +syn keyword elixirTodo FIXME NOTE TODO OPTIMIZE XXX HACK contained + +syn keyword elixirKeyword is_atom is_binary is_bitstring is_boolean is_float is_function is_integer is_list is_number is_pid is_port is_record is_reference is_tuple is_exception +syn keyword elixirKeyword case cond bc lc inlist inbits if unless try receive function +syn keyword elixirKeyword exit raise throw after rescue catch else +syn keyword elixirKeyword use quote unquote super alias +syn match elixirKeyword '\<\%(->\)\>\s*' + +syn keyword elixirInclude import require + +syn keyword elixirOperator and not or when xor in +syn match elixirOperator '%=\|\*=\|\*\*=\|+=\|-=\|\^=\|||=' +syn match elixirOperator "\%(<=>\|<\%(<\|=\)\@!\|>\%(<\|=\|>\)\@!\|<=\|>=\|===\|==\|=\~\|!=\|!\~\|\s?[ \t]\@=\)" +syn match elixirOperator "!+[ \t]\@=\|&&\|||\|\^\|\*\|+\|-\|/" +syn match elixirOperator "|\|++\|--\|\*\*\|\/\/\|<-\|<>\|<<\|>>\|=\|\.\|::" + +syn match elixirSymbol '\(:\)\@=]\@!\)\?\|<>\|===\?\|>=\?\|<=\?\)' +syn match elixirSymbol '\(:\)\@\|&&\?\|%\(()\|\[\]\|{}\)\|++\?\|--\?\|||\?\|!\|//\|[%&`/|]\)' +syn match elixirSymbol "\%([a-zA-Z_]\w*\([?!]\)\?\):\(:\)\@!" + +syn keyword elixirName nil +syn match elixirName '\<[A-Z]\w*\>' + +syn match elixirUnusedVariable '\<_\w*\>' + +syn keyword elixirBoolean true false + +syn match elixirVariable '@[a-zA-Z_]\w*\|&\d' + +syn keyword elixirPseudoVariable __FILE__ __DIR__ __MODULE__ __ENV__ __CALLER__ + +syn match elixirNumber '\<\d\(_\?\d\)*\(\.[^[:space:][:digit:]]\@!\(_\?\d\)*\)\?\([eE][-+]\?\d\(_\?\d\)*\)\?\>' +syn match elixirNumber '\<0[xX][0-9A-Fa-f]\+\>' +syn match elixirNumber '\<0[bB][01]\+\>' + +syn match elixirRegexEscape "\\\\\|\\[aAbBcdDefGhHnrsStvVwW]\|\\\d\{3}\|\\x[0-9a-fA-F]\{2}" contained +syn match elixirRegexEscapePunctuation "?\|\\.\|*\|\\\[\|\\\]\|+\|\\^\|\\\$\|\\|\|\\(\|\\)\|\\{\|\\}" contained +syn match elixirRegexQuantifier "[*?+][?+]\=" contained display +syn match elixirRegexQuantifier "{\d\+\%(,\d*\)\=}?\=" contained display +syn match elixirRegexCharClass "\[:\(alnum\|alpha\|ascii\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|word\|xdigit\):\]" contained display + +syn region elixirRegex matchgroup=elixirDelimiter start="%r/" end="/[uiomxfr]*" skip="\\\\" contains=@elixirRegexSpecial + +syn cluster elixirRegexSpecial contains=elixirRegexEscape,elixirRegexCharClass,elixirRegexQuantifier,elixirRegexEscapePunctuation +syn cluster elixirStringContained contains=elixirInterpolation,elixirRegexEscape,elixirRegexCharClass + +syn region elixirString matchgroup=elixirDelimiter start="'" end="'" skip="\\'" +syn region elixirString matchgroup=elixirDelimiter start='"' end='"' skip='\\"' contains=@elixirStringContained +syn region elixirInterpolation matchgroup=elixirDelimiter start="#{" end="}" contained contains=ALLBUT,elixirComment,@elixirNotTop + +syn region elixirDocStringStart matchgroup=elixirDocString start=+"""+ end=+$+ oneline contains=ALLBUT,@elixirNotTop +syn region elixirDocStringStart matchgroup=elixirDocString start=+'''+ end=+$+ oneline contains=ALLBUT,@elixirNotTop +syn region elixirDocString start=+\z("""\)+ end=+^\s*\zs\z1+ contains=elixirDocStringStart,elixirTodo fold keepend +syn region elixirDocString start=+\z('''\)+ end=+^\s*\zs\z1+ contains=elixirDocStringStart,elixirTodo fold keepend + +syn match elixirSymbolInterpolated ':\("\)\@=' contains=elixirString +syn match elixirString "\(\w\)\@\|0[0-7]{0,2}[0-7]\@!\>\|[^x0MC]\)\|(\\[MC]-)+\w\|[^\s\\]\)" + +syn region elixirBlock matchgroup=elixirKeyword start="\\(:\)\@!" end="\" contains=ALLBUT,@elixirNotTop fold +syn region elixirAnonymousFunction matchgroup=elixirKeyword start="\" end="\" contains=ALLBUT,@elixirNotTop fold + +syn region elixirArguments start="(" end=")" contained contains=elixirOperator,elixirSymbol,elixirPseudoVariable,elixirName,elixirBoolean,elixirVariable,elixirUnusedVariable,elixirNumber,elixirDocString,elixirSymbolInterpolated,elixirRegex,elixirRegexEscape,elixirRegexEscapePunctuation,elixirRegexCharClass,elixirRegexQuantifier,elixirSpecial,elixirString,elixirDelimiter + +syn match elixirDelimEscape "\\[(<{\[)>}\]]" transparent display contained contains=NONE + +syn region elixirSigil matchgroup=elixirDelimiter start="%\z([~`!@#$%^&*_\-+|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" fold +syn region elixirSigil matchgroup=elixirDelimiter start="%[BCRW]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" fold +syn region elixirSigil matchgroup=elixirDelimiter start="%[BCRW]\={" end="}" skip="\\\\\|\\}" contains=elixirDelimEscape fold +syn region elixirSigil matchgroup=elixirDelimiter start="%[BCRW]\=<" end=">" skip="\\\\\|\\>" contains=elixirDelimEscape fold +syn region elixirSigil matchgroup=elixirDelimiter start="%[BCRW]\=\[" end="\]" skip="\\\\\|\\\]" contains=elixirDelimEscape fold +syn region elixirSigil matchgroup=elixirDelimiter start="%[BCRW]\=(" end=")" skip="\\\\\|\\)" contains=elixirDelimEscape fold + +syn region elixirSigil matchgroup=elixirDelimiter start="%[bcrw]\z([~`!@#$%^&*_\-+=|\:;"',.?/]\)" end="\z1" skip="\\\\\|\\\z1" fold +syn region elixirSigil matchgroup=elixirDelimiter start="%[bcrw]{" end="}" skip="\\\\\|\\}" fold contains=@elixirStringContained,elixirRegexEscapePunctuation +syn region elixirSigil matchgroup=elixirDelimiter start="%[bcrw]<" end=">" skip="\\\\\|\\>" fold contains=@elixirStringContained,elixirRegexEscapePunctuation +syn region elixirSigil matchgroup=elixirDelimiter start="%[bcrw]\[" end="\]" skip="\\\\\|\\\]" fold contains=@elixirStringContained,elixirRegexEscapePunctuation +syn region elixirSigil matchgroup=elixirDelimiter start="%[bcrw](" end=")" skip="\\\\\|\\)" fold contains=@elixirStringContained,elixirRegexEscapePunctuation + +" Defines +syn keyword elixirDefine def nextgroup=elixirFunctionDeclaration skipwhite skipnl +syn keyword elixirDefine def nextgroup=elixirFunctionDeclaration skipwhite skipnl +syn keyword elixirPrivateDefine defp nextgroup=elixirFunctionDeclaration skipwhite skipnl +syn keyword elixirModuleDefine defmodule nextgroup=elixirModuleDeclaration skipwhite skipnl +syn keyword elixirProtocolDefine defprotocol nextgroup=elixirProtocolDeclaration skipwhite skipnl +syn keyword elixirImplDefine defimpl nextgroup=elixirImplDeclaration skipwhite skipnl +syn keyword elixirRecordDefine defrecord nextgroup=elixirRecordDeclaration skipwhite skipnl +syn keyword elixirPrivateRecordDefine defrecordp nextgroup=elixirRecordDeclaration skipwhite skipnl +syn keyword elixirMacroDefine defmacro nextgroup=elixirMacroDeclaration skipwhite skipnl +syn keyword elixirPrivateMacroDefine defmacrop nextgroup=elixirMacroDeclaration skipwhite skipnl +syn keyword elixirDelegateDefine defdelegate nextgroup=elixirDelegateDeclaration skipwhite skipnl +syn keyword elixirOverridableDefine defoverridable nextgroup=elixirOverridableDeclaration skipwhite skipnl +syn keyword elixirExceptionDefine defexception nextgroup=elixirExceptionDeclaration skipwhite skipnl +syn keyword elixirCallbackDefine defcallback nextgroup=elixirCallbackDeclaration skipwhite skipnl + +" Declarations +syn match elixirModuleDeclaration "[^[:space:];#<]\+" contained contains=elixirName nextgroup=elixirBlock skipwhite skipnl +syn match elixirFunctionDeclaration "[^[:space:];#<,()\[\]]\+" contained nextgroup=elixirArguments skipwhite skipnl +syn match elixirProtocolDeclaration "[^[:space:];#<]\+" contained contains=elixirName skipwhite skipnl +syn match elixirImplDeclaration "[^[:space:];#<]\+" contained contains=elixirName skipwhite skipnl +syn match elixirRecordDeclaration "[^[:space:];#<]\+" contained contains=elixirName,elixirSymbol skipwhite skipnl +syn match elixirMacroDeclaration "[^[:space:];#<,()\[\]]\+" contained nextgroup=elixirArguments skipwhite skipnl +syn match elixirDelegateDeclaration "[^[:space:];#<,()\[\]]\+" contained contains=elixirFunctionDeclaration skipwhite skipnl +syn region elixirDelegateDeclaration start='\[' end='\]' contained contains=elixirFunctionDeclaration skipwhite skipnl +syn match elixirOverridableDeclaration "[^[:space:];#<]\+" contained contains=elixirName skipwhite skipnl +syn match elixirExceptionDeclaration "[^[:space:];#<]\+" contained contains=elixirName skipwhite skipnl +syn match elixirCallbackDeclaration "[^[:space:];#<,()\[\]]\+" contained contains=elixirFunctionDeclaration skipwhite skipnl + +syn cluster elixirDeclaration contains=elixirFunctionDeclaration,elixirModuleDeclaration,elixirProtocolDeclaration,elixirImplDeclaration,elixirRecordDeclaration,elixirMacroDeclaration,elixirDelegateDeclaration,elixirOverridableDeclaration,elixirExceptionDeclaration,elixirCallbackDeclaration + +hi def link elixirDefine Define +hi def link elixirPrivateDefine Define +hi def link elixirModuleDefine Define +hi def link elixirProtocolDefine Define +hi def link elixirImplDefine Define +hi def link elixirRecordDefine Define +hi def link elixirPrivateRecordDefine Define +hi def link elixirMacroDefine Define +hi def link elixirPrivateMacroDefine Define +hi def link elixirDelegateDefine Define +hi def link elixirOverridableDefine Define +hi def link elixirExceptionDefine Define +hi def link elixirCallbackDefine Define +hi def link elixirFunctionDeclaration Function +hi def link elixirMacroDeclaration Macro +hi def link elixirInclude Include +hi def link elixirComment Comment +hi def link elixirTodo Todo +hi def link elixirKeyword Keyword +hi def link elixirOperator Operator +hi def link elixirSymbol Constant +hi def link elixirPseudoVariable Constant +hi def link elixirName Type +hi def link elixirBoolean Boolean +hi def link elixirVariable Identifier +hi def link elixirUnusedVariable Comment +hi def link elixirNumber Number +hi def link elixirDocString Comment +hi def link elixirSymbolInterpolated elixirSymbol +hi def link elixirRegex elixirString +hi def link elixirRegexEscape elixirSpecial +hi def link elixirRegexEscapePunctuation elixirSpecial +hi def link elixirRegexCharClass elixirSpecial +hi def link elixirRegexQuantifier elixirSpecial +hi def link elixirSpecial Special +hi def link elixirString String +hi def link elixirSigil String +hi def link elixirDelimiter Delimiter