Add Rust lang support

This commit is contained in:
Adam Stankiewicz 2013-09-26 12:44:31 +02:00
parent d6710f1b57
commit 90d87abd30
7 changed files with 511 additions and 0 deletions

33
after/syntax/rust.vim Normal file
View File

@ -0,0 +1,33 @@
if !exists('g:rust_conceal') || !has('conceal') || &enc != 'utf-8'
finish
endif
" For those who don't want to see `::`...
if exists('g:rust_conceal_mod_path')
syn match rustNiceOperator "::" conceal cchar=
endif
syn match rustRightArrowHead contained ">" conceal cchar= 
syn match rustRightArrowTail contained "-" conceal cchar=
syn match rustNiceOperator "->" contains=rustRightArrowHead,rustRightArrowTail
syn match rustFatRightArrowHead contained ">" conceal cchar= 
syn match rustFatRightArrowTail contained "=" conceal cchar=
syn match rustNiceOperator "=>" contains=rustFatRightArrowHead,rustFatRightArrowTail
syn match rustNiceOperator /\<\@!_\(_*\>\)\@=/ conceal cchar=
" For those who don't want to see `pub`...
if exists('g:rust_conceal_pub')
syn match rustPublicSigil contained "pu" conceal cchar=
syn match rustPublicRest contained "b" conceal cchar= 
syn match rustNiceOperator "pub " contains=rustPublicSigil,rustPublicRest
endif
hi link rustNiceOperator Operator
if !exists('g:rust_conceal_mod_path')
hi! link Conceal Operator
endif
setlocal conceallevel=2

1
build
View File

@ -98,6 +98,7 @@ PACKS="
python:vim-scripts/python.vim--Vasiliev
rspec:sheerun/rspec.vim
ruby:vim-ruby/vim-ruby
rust:wting/rust.vim
sbt:derekwyatt/vim-sbt
scala:derekwyatt/vim-scala
slim:slim-template/vim-slim

33
compiler/rustc.vim Normal file
View File

@ -0,0 +1,33 @@
" Vim compiler file
" Compiler: Rust Compiler
" Maintainer: Chris Morgan <me@chrismorgan.info>
" Latest Revision: 2013 Jul 12
if exists("current_compiler")
finish
endif
let current_compiler = "rustc"
let s:cpo_save = &cpo
set cpo&vim
if exists(":CompilerSet") != 2
command -nargs=* CompilerSet setlocal <args>
endif
if exists("g:rustc_makeprg_no_percent") && g:rustc_makeprg_no_percent == 1
CompilerSet makeprg=rustc
else
CompilerSet makeprg=rustc\ \%
endif
CompilerSet errorformat=
\%f:%l:%c:\ %t%*[^:]:\ %m,
\%f:%l:%c:\ %*\\d:%*\\d\ %t%*[^:]:\ %m,
\%-G%f:%l\ %s,
\%-G%*[\ ]^,
\%-G%*[\ ]^%*[~],
\%-G%*[\ ]...
let &cpo = s:cpo_save
unlet s:cpo_save

View File

@ -104,6 +104,7 @@ au BufNewFile,BufRead *.jbuilder set filetype=ruby
au BufNewFile,BufRead Puppetfile set filetype=ruby
au BufNewFile,BufRead [Bb]uildfile set filetype=ruby
au BufNewFile,BufRead Appraisals set filetype=ruby
au BufRead,BufNewFile *.rs,*.rc set filetype=rust
au BufRead,BufNewFile *.sbt set filetype=sbt
fun! s:DetectScala()
if getline(1) == '#!/usr/bin/env scala'

45
ftplugin/rust.vim Normal file
View File

@ -0,0 +1,45 @@
" Vim syntax file
" Language: Rust
" Maintainer: Chris Morgan <me@chrismorgan.info>
" Last Change: 2013 Jul 10
if exists("b:did_ftplugin")
finish
endif
let b:did_ftplugin = 1
" The rust source code at present seems to typically omit a leader on /*!
" comments, so we'll use that as our default, but make it easy to switch.
" This does not affect indentation at all (I tested it with and without
" leader), merely whether a leader is inserted by default or not.
if exists("g:rust_bang_comment_leader") && g:rust_bang_comment_leader == 1
" Why is the `,s0:/*,mb:\ ,ex:*/` there, you ask? I don't understand why,
" but without it, */ gets indented one space even if there were no
" leaders. I'm fairly sure that's a Vim bug.
setlocal comments=s1:/*,mb:*,ex:*/,s0:/*,mb:\ ,ex:*/,:///,://!,://
else
setlocal comments=s0:/*!,m:\ ,ex:*/,s1:/*,mb:*,ex:*/,:///,://!,://
endif
setlocal commentstring=//%s
setlocal formatoptions-=t formatoptions+=croqnl
" j was only added in 7.3.541, so stop complaints about its nonexistence
silent! setlocal formatoptions+=j
" This includeexpr isn't perfect, but it's a good start
setlocal includeexpr=substitute(v:fname,'::','/','g')
" NOT adding .rc as it's being phased out (0.7)
setlocal suffixesadd=.rs
if exists("g:ftplugin_rust_source_path")
let &l:path=g:ftplugin_rust_source_path . ',' . &l:path
endif
if exists("g:loaded_delimitMate")
if exists("b:delimitMate_excluded_regions")
let b:rust_original_delimitMate_excluded_regions = b:delimitMate_excluded_regions
endif
let b:delimitMate_excluded_regions = delimitMate#Get("excluded_regions") . ',rustLifetimeCandidate,rustGenericLifetimeCandidate'
endif
let b:undo_ftplugin = "setlocal formatoptions< comments< commentstring< includeexpr< suffixesadd< | if exists('b:rust_original_delimitMate_excluded_regions') | let b:delimitMate_excluded_regions = b:rust_original_delimitMate_excluded_regions | unlet b:rust_original_delimitMate_excluded_regions | elseif exists('b:delimitMate_excluded_regions') | unlet b:delimitMate_excluded_regions | endif"

147
indent/rust.vim Normal file
View File

@ -0,0 +1,147 @@
" Vim indent file
" Language: Rust
" Author: Chris Morgan <me@chrismorgan.info>
" Last Change: 2013 Jul 10
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
finish
endif
let b:did_indent = 1
setlocal cindent
setlocal cinoptions=L0,(0,Ws,JN,j1
setlocal cinkeys=0{,0},!^F,o,O,0[,0]
" Don't think cinwords will actually do anything at all... never mind
setlocal cinwords=do,for,if,else,while,loop,impl,mod,unsafe,trait,struct,enum,fn,extern
" Some preliminary settings
setlocal nolisp " Make sure lisp indenting doesn't supersede us
setlocal autoindent " indentexpr isn't much help otherwise
" Also do indentkeys, otherwise # gets shoved to column 0 :-/
setlocal indentkeys=0{,0},!^F,o,O,0[,0]
setlocal indentexpr=GetRustIndent(v:lnum)
" Only define the function once.
if exists("*GetRustIndent")
finish
endif
" Come here when loading the script the first time.
function s:get_line_trimmed(lnum)
" Get the line and remove a trailing comment.
" Use syntax highlighting attributes when possible.
" NOTE: this is not accurate; /* */ or a line continuation could trick it
let line = getline(a:lnum)
let line_len = strlen(line)
if has('syntax_items')
" If the last character in the line is a comment, do a binary search for
" the start of the comment. synID() is slow, a linear search would take
" too long on a long line.
if synIDattr(synID(a:lnum, line_len, 1), "name") =~ "Comment\|Todo"
let min = 1
let max = line_len
while min < max
let col = (min + max) / 2
if synIDattr(synID(a:lnum, col, 1), "name") =~ "Comment\|Todo"
let max = col
else
let min = col + 1
endif
endwhile
let line = strpart(line, 0, min - 1)
endif
return substitute(line, "\s*$", "", "")
else
" Sorry, this is not complete, nor fully correct (e.g. string "//").
" Such is life.
return substitute(line, "\s*//.*$", "", "")
endif
endfunction
function GetRustIndent(lnum)
" Starting assumption: cindent (called at the end) will do it right
" normally. We just want to fix up a few cases.
let line = getline(a:lnum)
if has('syntax_items')
let synname = synIDattr(synID(a:lnum, 1, 1), "name")
if synname == "rustString"
" If the start of the line is in a string, don't change the indent
return -1
elseif synname =~ "\\(Comment\\|Todo\\)"
\ && line !~ "^\\s*/\\*" " not /* opening line
if synname =~ "CommentML" " multi-line
if line !~ "^\\s*\\*" && getline(a:lnum - 1) =~ "^\\s*/\\*"
" This is (hopefully) the line after a /*, and it has no
" leader, so the correct indentation is that of the
" previous line.
return GetRustIndent(a:lnum - 1)
endif
endif
" If it's in a comment, let cindent take care of it now. This is
" for cases like "/*" where the next line should start " * ", not
" "* " as the code below would otherwise cause for module scope
" Fun fact: " /*\n*\n*/" takes two calls to get right!
return cindent(a:lnum)
endif
endif
" cindent gets second and subsequent match patterns/struct members wrong,
" as it treats the comma as indicating an unfinished statement::
"
" match a {
" b => c,
" d => e,
" f => g,
" };
" Search backwards for the previous non-empty line.
let prevline = s:get_line_trimmed(prevnonblank(a:lnum - 1))
if prevline[len(prevline) - 1] == ","
\ && s:get_line_trimmed(a:lnum) !~ "^\\s*[\\[\\]{}]"
" Oh ho! The previous line ended in a comma! I bet cindent will try to
" take this too far... For now, let's use the previous line's indent
return GetRustIndent(a:lnum - 1)
endif
" cindent doesn't do the module scope well at all; e.g.::
"
" static FOO : &'static [bool] = [
" true,
" false,
" false,
" true,
" ];
"
" uh oh, next statement is indented further!
" Note that this does *not* apply the line continuation pattern properly;
" that's too hard to do correctly for my liking at present, so I'll just
" start with these two main cases (square brackets and not returning to
" column zero)
call cursor(a:lnum, 1)
if searchpair('{\|(', '', '}\|)', 'nbW') == 0
if searchpair('\[', '', '\]', 'nbW') == 0
" Global scope, should be zero
return 0
else
" At the module scope, inside square brackets only
"if getline(a:lnum)[0] == ']' || search('\[', '', '\]', 'nW') == a:lnum
if line =~ "^\\s*]"
" It's the closing line, dedent it
return 0
else
return &shiftwidth
endif
endif
endif
" Fall back on cindent, which does it mostly right
return cindent(a:lnum)
endfunction

251
syntax/rust.vim Normal file
View File

@ -0,0 +1,251 @@
" Vim syntax file
" Language: Rust
" Maintainer: Patrick Walton <pcwalton@mozilla.com>
" Maintainer: Ben Blum <bblum@cs.cmu.edu>
" Maintainer: Chris Morgan <me@chrismorgan.info>
" Last Change: 2013 Sep 4
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
" Syntax definitions {{{1
" Basic keywords {{{2
syn keyword rustConditional match if else
syn keyword rustOperator as
syn match rustAssert "\<assert\(\w\)*!" contained
syn match rustFail "\<fail\(\w\)*!" contained
syn keyword rustKeyword break do extern
syn keyword rustKeyword in if impl let log
syn keyword rustKeyword for impl let log
syn keyword rustKeyword loop mod once priv pub
syn keyword rustKeyword return
syn keyword rustKeyword unsafe while
syn keyword rustKeyword use nextgroup=rustModPath skipwhite
" FIXME: Scoped impl's name is also fallen in this category
syn keyword rustKeyword mod trait struct enum type nextgroup=rustIdentifier skipwhite
syn keyword rustKeyword fn nextgroup=rustFuncName skipwhite
syn keyword rustStorage const mut ref static
syn match rustIdentifier contains=rustIdentifierPrime "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained
syn match rustFuncName "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained
" Reserved (but not yet used) keywords {{{2
syn keyword rustKeyword alignof be offsetof pure sizeof typeof yield
" Built-in types {{{2
syn keyword rustType int uint float char bool u8 u16 u32 u64 f32
syn keyword rustType f64 i8 i16 i32 i64 str Self
" Things from the prelude (src/libstd/prelude.rs) {{{2
" This section is just straight transformation of the contents of the prelude,
" to make it easy to update.
" Core operators {{{3
syn keyword rustEnum Either
syn keyword rustEnumVariant Left Right
syn keyword rustTrait Sized
syn keyword rustTrait Freeze Send
syn keyword rustTrait Add Sub Mul Div Rem Neg Not
syn keyword rustTrait BitAnd BitOr BitXor
syn keyword rustTrait Drop
syn keyword rustTrait Shl Shr Index
syn keyword rustEnum Option
syn keyword rustEnumVariant Some None
syn keyword rustEnum Result
syn keyword rustEnumVariant Ok Err
" Functions {{{3
"syn keyword rustFunction print println
"syn keyword rustFunction range
" Types and traits {{{3
syn keyword rustTrait ToCStr
syn keyword rustTrait Clone DeepClone
syn keyword rustTrait Eq ApproxEq Ord TotalEq TotalOrd Ordering Equiv
syn keyword rustEnumVariant Less Equal Greater
syn keyword rustTrait Char
syn keyword rustTrait Container Mutable Map MutableMap Set MutableSet
syn keyword rustTrait Hash
syn keyword rustTrait Times
syn keyword rustTrait FromIterator Extendable
syn keyword rustTrait Iterator DoubleEndedIterator RandomAccessIterator ClonableIterator
syn keyword rustTrait OrdIterator MutableDoubleEndedIterator ExactSize
syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul
syn keyword rustTrait Orderable Signed Unsigned Round
syn keyword rustTrait Algebraic Trigonometric Exponential Hyperbolic
syn keyword rustTrait Integer Fractional Real RealExt
syn keyword rustTrait Bitwise BitCount Bounded
syn keyword rustTrait Primitive Int Float ToStrRadix
syn keyword rustTrait GenericPath
syn keyword rustTrait Path
syn keyword rustTrait PosixPath
syn keyword rustTrait WindowsPath
syn keyword rustTrait RawPtr
syn keyword rustTrait Ascii AsciiCast OwnedAsciiCast AsciiStr ToBytesConsume
syn keyword rustTrait Str StrVector StrSlice OwnedStr
syn keyword rustTrait FromStr
syn keyword rustTrait IterBytes
syn keyword rustTrait ToStr ToStrConsume
syn keyword rustTrait CopyableTuple ImmutableTuple
syn keyword rustTrait CloneableTuple1 ImmutableTuple1
syn keyword rustTrait CloneableTuple2 CloneableTuple3 CloneableTuple4 CloneableTuple5
syn keyword rustTrait CloneableTuple6 CloneableTuple7 CloneableTuple8 CloneableTuple9
syn keyword rustTrait CloneableTuple10 CloneableTuple11 CloneableTuple12
syn keyword rustTrait ImmutableTuple2 ImmutableTuple3 ImmutableTuple4 ImmutableTuple5
syn keyword rustTrait ImmutableTuple6 ImmutableTuple7 ImmutableTuple8 ImmutableTuple9
syn keyword rustTrait ImmutableTuple10 ImmutableTuple11 ImmutableTuple12
syn keyword rustTrait Vector VectorVector CopyableVector ImmutableVector
syn keyword rustTrait ImmutableEqVector ImmutableTotalOrdVector ImmutableCopyableVector
syn keyword rustTrait OwnedVector OwnedCopyableVector OwnedEqVector MutableVector
syn keyword rustTrait Reader ReaderUtil Writer WriterUtil
syn keyword rustTrait Default
"syn keyword rustFunction stream
syn keyword rustTrait Port Chan GenericChan GenericSmartChan GenericPort Peekable
"syn keyword rustFunction spawn
syn keyword rustSelf self
syn keyword rustBoolean true false
syn keyword rustConstant Some None " option
syn keyword rustConstant Left Right " either
syn keyword rustConstant Ok Err " result
syn keyword rustConstant Less Equal Greater " Ordering
" Other syntax {{{2
" If foo::bar changes to foo.bar, change this ("::" to "\.").
" If foo::bar changes to Foo::bar, change this (first "\w" to "\u").
syn match rustModPath "\w\(\w\)*::[^<]"he=e-3,me=e-3
syn match rustModPath "\w\(\w\)*" contained " only for 'use path;'
syn match rustModPathSep "::"
syn match rustFuncCall "\w\(\w\)*("he=e-1,me=e-1
syn match rustFuncCall "\w\(\w\)*::<"he=e-3,me=e-3 " foo::<T>();
" This is merely a convention; note also the use of [A-Z], restricting it to
" latin identifiers rather than the full Unicode uppercase. I have not used
" [:upper:] as it depends upon 'noignorecase'
"syn match rustCapsIdent display "[A-Z]\w\(\w\)*"
syn match rustOperator display "\%(+\|-\|/\|*\|=\|\^\|&\||\|!\|>\|<\|%\)=\?"
" This one isn't *quite* right, as we could have binary-& with a reference
syn match rustSigil display /&\s\+[&~@*][^)= \t\r\n]/he=e-1,me=e-1
syn match rustSigil display /[&~@*][^)= \t\r\n]/he=e-1,me=e-1
" This isn't actually correct; a closure with no arguments can be `|| { }`.
" Last, because the & in && isn't a sigil
syn match rustOperator display "&&\|||"
syn match rustMacro '\w\(\w\)*!' contains=rustAssert,rustFail
syn match rustMacro '#\w\(\w\)*' contains=rustAssert,rustFail
syn match rustFormat display "%\(\d\+\$\)\=[-+' #0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlLjzt]\|ll\|hh\)\=\([aAbdiuoxXDOUfFeEgGcCsSpn?]\|\[\^\=.[^]]*\]\)" contained
syn match rustFormat display "%%" contained
syn match rustSpecial display contained /\\\([nrt\\'"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)/
syn match rustStringContinuation display contained /\\\n\s*/
syn region rustString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=rustTodo,rustFormat,rustSpecial,rustStringContinuation
syn region rustAttribute start="#\[" end="\]" contains=rustString,rustDeriving
syn region rustDeriving start="deriving(" end=")" contained contains=rustTrait
" Number literals
syn match rustNumber display "\<[0-9][0-9_]*\>"
syn match rustNumber display "\<[0-9][0-9_]*\(u\|u8\|u16\|u32\|u64\)\>"
syn match rustNumber display "\<[0-9][0-9_]*\(i\|i8\|i16\|i32\|i64\)\>"
syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\>"
syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\(u\|u8\|u16\|u32\|u64\)\>"
syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\(i8\|i16\|i32\|i64\)\>"
syn match rustBinNumber display "\<0b[01_]\+\>"
syn match rustBinNumber display "\<0b[01_]\+\(u\|u8\|u16\|u32\|u64\)\>"
syn match rustBinNumber display "\<0b[01_]\+\(i8\|i16\|i32\|i64\)\>"
syn match rustFloat display "\<[0-9][0-9_]*\(f\|f32\|f64\)\>"
syn match rustFloat display "\<[0-9][0-9_]*\([eE][+-]\=[0-9_]\+\)\>"
syn match rustFloat display "\<[0-9][0-9_]*\([eE][+-]\=[0-9_]\+\)\(f\|f32\|f64\)\>"
syn match rustFloat display "\<[0-9][0-9_]*\.[0-9_]\+\>"
syn match rustFloat display "\<[0-9][0-9_]*\.[0-9_]\+\(f\|f32\|f64\)\>"
syn match rustFloat display "\<[0-9][0-9_]*\.[0-9_]\+\%([eE][+-]\=[0-9_]\+\)\>"
syn match rustFloat display "\<[0-9][0-9_]*\.[0-9_]\+\%([eE][+-]\=[0-9_]\+\)\(f\|f32\|f64\)\>"
" For the benefit of delimitMate
syn region rustLifetimeCandidate display start=/&'\%(\([^'\\]\|\\\(['nrt\\\"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'\)\@!/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime
syn region rustGenericRegion display start=/<\%('\|[^[cntrl:][:space:][:punct:]]\)\@=')\S\@=/ end=/>/ contains=rustGenericLifetimeCandidate
syn region rustGenericLifetimeCandidate display start=/\%(<\|,\s*\)\@<='/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime
"rustLifetime must appear before rustCharacter, or chars will get the lifetime highlighting
syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*"
syn match rustCharacter /'\([^'\\]\|\\\([nrt\\'"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'/ contains=rustSpecial
syn region rustCommentML start="/\*" end="\*/" contains=rustTodo
syn region rustComment start="//" end="$" contains=rustTodo keepend
syn region rustCommentMLDoc start="/\*\%(!\|\*/\@!\)" end="\*/" contains=rustTodo
syn region rustCommentDoc start="//[/!]" end="$" contains=rustTodo keepend
syn keyword rustTodo contained TODO FIXME XXX NB NOTE
" Folding rules {{{2
" Trivial folding rules to begin with.
" TODO: use the AST to make really good folding
syn region rustFoldBraces start="{" end="}" transparent fold
" If you wish to enable this, setlocal foldmethod=syntax
" It's not enabled by default as it would drive some people mad.
" Default highlighting {{{1
hi def link rustHexNumber rustNumber
hi def link rustBinNumber rustNumber
hi def link rustIdentifierPrime rustIdentifier
hi def link rustTrait rustType
hi def link rustSigil StorageClass
hi def link rustFormat Special
hi def link rustSpecial Special
hi def link rustStringContinuation Special
hi def link rustString String
hi def link rustCharacter Character
hi def link rustNumber Number
hi def link rustBoolean Boolean
hi def link rustEnum rustType
hi def link rustEnumVariant rustConstant
hi def link rustConstant Constant
hi def link rustSelf Constant
hi def link rustFloat Float
hi def link rustOperator Operator
hi def link rustKeyword Keyword
hi def link rustConditional Conditional
hi def link rustIdentifier Identifier
hi def link rustCapsIdent rustIdentifier
hi def link rustModPath Include
hi def link rustModPathSep Delimiter
hi def link rustFunction Function
hi def link rustFuncName Function
hi def link rustFuncCall Function
hi def link rustCommentMLDoc rustCommentDoc
hi def link rustCommentDoc SpecialComment
hi def link rustCommentML rustComment
hi def link rustComment Comment
hi def link rustAssert PreCondit
hi def link rustFail PreCondit
hi def link rustMacro Macro
hi def link rustType Type
hi def link rustTodo Todo
hi def link rustAttribute PreProc
hi def link rustDeriving PreProc
hi def link rustStorage StorageClass
hi def link rustLifetime Special
" Other Suggestions:
" hi rustAttribute ctermfg=cyan
" hi rustDeriving ctermfg=cyan
" hi rustAssert ctermfg=yellow
" hi rustFail ctermfg=red
" hi rustMacro ctermfg=magenta
syn sync minlines=200
syn sync maxlines=500
let b:current_syntax = "rust"