--- /dev/null
+" Vim indent file
+" Language: Rust
+" Author: Chris Morgan <me@chrismorgan.info>
+" Last Change: 2014 Sep 13
+" from https://github.com/wting/rust.vim/blob/master/indent/rust.vim
+
+" 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,J1,j1
+setlocal cinkeys=0{,0},!^F,o,O,0[,0]
+" Don't think cinwords will actually do anything at all... never mind
+setlocal cinwords=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! s:is_string_comment(lnum, col)
+ if has('syntax_items')
+ for id in synstack(a:lnum, a:col)
+ let synname = synIDattr(id, "name")
+ if synname == "rustString" || synname =~ "^rustComment"
+ return 1
+ endif
+ endfor
+ else
+ " without syntax, let's not even try
+ return 0
+ 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 prevlinenum = prevnonblank(a:lnum - 1)
+ let prevline = s:get_line_trimmed(prevlinenum)
+ while prevlinenum > 1 && prevline !~ '[^[:blank:]]'
+ let prevlinenum = prevnonblank(prevlinenum - 1)
+ let prevline = s:get_line_trimmed(prevlinenum)
+ endwhile
+ if prevline[len(prevline) - 1] == ","
+ \ && s:get_line_trimmed(a:lnum) !~ '^\s*[\[\]{}]'
+ \ && prevline !~ '^\s*fn\s'
+ \ && prevline !~ '([^()]\+,$'
+ " Oh ho! The previous line ended in a comma! I bet cindent will try to
+ " take this too far... For now, let's normally use the previous line's
+ " indent.
+
+ " One case where this doesn't work out is where *this* line contains
+ " square or curly brackets; then we normally *do* want to be indenting
+ " further.
+ "
+ " Another case where we don't want to is one like a function
+ " definition with arguments spread over multiple lines:
+ "
+ " fn foo(baz: Baz,
+ " baz: Baz) // <-- cindent gets this right by itself
+ "
+ " Another case is similar to the previous, except calling a function
+ " instead of defining it, or any conditional expression that leaves
+ " an open paren:
+ "
+ " foo(baz,
+ " baz);
+ "
+ " if baz && (foo ||
+ " bar) {
+ "
+ " There are probably other cases where we don't want to do this as
+ " well. Add them as needed.
+ return indent(prevlinenum)
+ endif
+
+ if !has("patch-7.4.355")
+ " cindent before 7.4.355 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',
+ \ 's:is_string_comment(line("."), col("."))') == 0
+ if searchpair('\[', '', '\]', 'nbW',
+ \ 's:is_string_comment(line("."), col("."))') == 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
+ endif
+
+ " Fall back on cindent, which does it mostly right
+ return cindent(a:lnum)
+endfunction
--- /dev/null
+" 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: January 5, 2015
+" from https://github.com/wting/rust.vim/blob/master/syntax/rust.vim
+
+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 rustPanic "\<panic\(\w\)*!" contained
+syn keyword rustKeyword break
+syn keyword rustKeyword box nextgroup=rustBoxPlacement skipwhite skipempty
+syn keyword rustKeyword continue
+syn keyword rustKeyword extern nextgroup=rustExternCrate,rustObsoleteExternMod skipwhite skipempty
+syn keyword rustKeyword fn nextgroup=rustFuncName skipwhite skipempty
+syn keyword rustKeyword for in if impl let
+syn keyword rustKeyword loop once pub
+syn keyword rustKeyword return super
+syn keyword rustKeyword unsafe virtual where while
+syn keyword rustKeyword use nextgroup=rustModPath skipwhite skipempty
+" FIXME: Scoped impl's name is also fallen in this category
+syn keyword rustKeyword mod trait struct enum type nextgroup=rustIdentifier skipwhite skipempty
+syn keyword rustStorage move mut ref static const
+
+syn keyword rustInvalidBareKeyword crate
+
+syn keyword rustExternCrate crate contained nextgroup=rustIdentifier,rustExternCrateString skipwhite skipempty
+" This is to get the `bar` part of `extern crate "foo" as bar;` highlighting.
+syn match rustExternCrateString /".*"\_s*as/ contained nextgroup=rustIdentifier skipwhite transparent skipempty contains=rustString,rustOperator
+syn keyword rustObsoleteExternMod mod contained nextgroup=rustIdentifier skipwhite skipempty
+
+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
+
+syn region rustBoxPlacement matchgroup=rustBoxPlacementParens start="(" end=")" contains=TOP contained
+syn keyword rustBoxPlacementExpr GC containedin=rustBoxPlacement
+" Ideally we'd have syntax rules set up to match arbitrary expressions. Since
+" we don't, we'll just define temporary contained rules to handle balancing
+" delimiters.
+syn region rustBoxPlacementBalance start="(" end=")" containedin=rustBoxPlacement transparent
+syn region rustBoxPlacementBalance start="\[" end="\]" containedin=rustBoxPlacement transparent
+" {} are handled by rustFoldBraces
+
+syn region rustMacroRepeat matchgroup=rustMacroRepeatDelimiters start="$(" end=")" contains=TOP nextgroup=rustMacroRepeatCount
+syn match rustMacroRepeatCount ".\?[*+]" contained
+syn match rustMacroVariable "$\w\+"
+
+" Reserved (but not yet used) keywords {{{2
+syn keyword rustReservedKeyword alignof be do offsetof priv pure sizeof typeof unsized yield abstract final override macro
+
+" Built-in types {{{2
+syn keyword rustType isize usize 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.
+
+" Reexported core operators {{{3
+syn keyword rustTrait Copy Send Sized Sync
+syn keyword rustTrait Drop Fn FnMut FnOnce
+
+" Reexported functions {{{3
+syn keyword rustFunction drop
+
+" Reexported types and traits {{{3
+syn keyword rustTrait Box
+syn keyword rustTrait CharExt
+syn keyword rustTrait Clone
+syn keyword rustTrait PartialEq PartialOrd Eq Ord
+syn keyword rustTrait DoubleEndedIterator
+syn keyword rustTrait ExactSizeIterator
+syn keyword rustTrait Iterator IteratorExt Extend
+syn keyword rustEnum Option
+syn keyword rustEnumVariant Some None
+syn keyword rustTrait PtrExt MutPtrExt
+syn keyword rustEnum Result
+syn keyword rustEnumVariant Ok Err
+syn keyword rustTrait AsSlice
+syn keyword rustTrait SliceExt SliceConcatExt
+syn keyword rustTrait Str StrExt
+syn keyword rustTrait String ToString
+syn keyword rustTrait Vec
+" FIXME: remove when path reform lands
+syn keyword rustTrait Path GenericPath
+" FIXME: remove when I/O reform lands
+syn keyword rustTrait Buffer Writer Reader Seek BufferPrelude
+
+" Other syntax {{{2
+syn keyword rustSelf self
+syn keyword rustBoolean true false
+
+" 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 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,rustPanic
+syn match rustMacro '#\w\(\w\)*' contains=rustAssert,rustPanic
+
+syn match rustEscapeError display contained /\\./
+syn match rustEscape display contained /\\\([nrt0\\'"]\|x\x\{2}\)/
+syn match rustEscapeUnicode display contained /\\\(u\x\{4}\|U\x\{8}\)/
+syn match rustEscapeUnicode display contained /\\u{\x\{1,6}}/
+syn match rustStringContinuation display contained /\\\n\s*/
+syn region rustString start=+b"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeError,rustStringContinuation
+syn region rustString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustStringContinuation,@Spell
+syn region rustString start='b\?r\z(#*\)"' end='"\z1' contains=@Spell
+
+syn region rustAttribute start="#!\?\[" end="\]" contains=rustString,rustDerive
+syn region rustDerive start="derive(" end=")" contained contains=rustTrait
+
+" Number literals
+syn match rustDecNumber display "\<[0-9][0-9_]*\%([iu]\%(s\|8\|16\|32\|64\)\)\="
+syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\%([iu]\%(s\|8\|16\|32\|64\)\)\="
+syn match rustOctNumber display "\<0o[0-7_]\+\%([iu]\%(s\|8\|16\|32\|64\)\)\="
+syn match rustBinNumber display "\<0b[01_]\+\%([iu]\%(s\|8\|16\|32\|64\)\)\="
+
+" Special case for numbers of the form "1." which are float literals, unless followed by
+" an identifier, which makes them integer literals with a method call or field access,
+" or by another ".", which makes them integer literals followed by the ".." token.
+" (This must go first so the others take precedence.)
+syn match rustFloat display "\<[0-9][0-9_]*\.\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\|\.\)\@!"
+" To mark a number as a normal float, it must have at least one of the three things integral values don't have:
+" a decimal point and more numbers; an exponent; and a type suffix.
+syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)\="
+syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\(f32\|f64\)\="
+syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)"
+
+" For the benefit of delimitMate
+syn region rustLifetimeCandidate display start=/&'\%(\([^'\\]\|\\\(['nrt0\\\"]\|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 rustCharacterInvalid display contained /b\?'\zs[\n\r\t']\ze'/
+" The groups negated here add up to 0-255 but nothing else (they do not seem to go beyond ASCII).
+syn match rustCharacterInvalidUnicode display contained /b'\zs[^[:cntrl:][:graph:][:alnum:][:space:]]\ze'/
+syn match rustCharacter /b'\([^\\]\|\\\(.\|x\x\{2}\)\)'/ contains=rustEscape,rustEscapeError,rustCharacterInvalid,rustCharacterInvalidUnicode
+syn match rustCharacter /'\([^\\]\|\\\(.\|x\x\{2}\|u\x\{4}\|U\x\{8}\|u{\x\{1,6}}\)\)'/ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustCharacterInvalid
+
+syn region rustCommentLine start="//" end="$" contains=rustTodo,@Spell
+syn region rustCommentLineDoc start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell
+syn region rustCommentBlock matchgroup=rustCommentBlock start="/\*\%(!\|\*[*/]\@!\)\@!" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell
+syn region rustCommentBlockDoc matchgroup=rustCommentBlockDoc start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell
+syn region rustCommentBlockNest matchgroup=rustCommentBlock start="/\*" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell contained transparent
+syn region rustCommentBlockDocNest matchgroup=rustCommentBlockDoc start="/\*" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell contained transparent
+" FIXME: this is a really ugly and not fully correct implementation. Most
+" importantly, a case like ``/* */*`` should have the final ``*`` not being in
+" a comment, but in practice at present it leaves comments open two levels
+" deep. But as long as you stay away from that particular case, I *believe*
+" the highlighting is correct. Due to the way Vim's syntax engine works
+" (greedy for start matches, unlike Rust's tokeniser which is searching for
+" the earliest-starting match, start or end), I believe this cannot be solved.
+" Oh you who would fix it, don't bother with things like duplicating the Block
+" rules and putting ``\*\@<!`` at the start of them; it makes it worse, as
+" then you must deal with cases like ``/*/**/*/``. And don't try making it
+" worse with ``\%(/\@<!\*\)\@<!``, either...
+
+syn keyword rustTodo contained TODO FIXME XXX NB NOTE
+
+" Folding rules {{{2
+" Trivial folding rules to begin with.
+" FIXME: use the AST to make really good folding
+syn region rustFoldBraces start="{" end="}" transparent fold
+
+" Default highlighting {{{1
+hi def link rustDecNumber rustNumber
+hi def link rustHexNumber rustNumber
+hi def link rustOctNumber rustNumber
+hi def link rustBinNumber rustNumber
+hi def link rustIdentifierPrime rustIdentifier
+hi def link rustTrait rustType
+
+hi def link rustMacroRepeatCount rustMacroRepeatDelimiters
+hi def link rustMacroRepeatDelimiters Macro
+hi def link rustMacroVariable Define
+hi def link rustSigil StorageClass
+hi def link rustEscape Special
+hi def link rustEscapeUnicode rustEscape
+hi def link rustEscapeError Error
+hi def link rustStringContinuation Special
+hi def link rustString String
+hi def link rustCharacterInvalid Error
+hi def link rustCharacterInvalidUnicode rustCharacterInvalid
+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 rustReservedKeyword Error
+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 rustCommentLine Comment
+hi def link rustCommentLineDoc SpecialComment
+hi def link rustCommentBlock rustCommentLine
+hi def link rustCommentBlockDoc rustCommentLineDoc
+hi def link rustAssert PreCondit
+hi def link rustPanic PreCondit
+hi def link rustMacro Macro
+hi def link rustType Type
+hi def link rustTodo Todo
+hi def link rustAttribute PreProc
+hi def link rustDerive PreProc
+hi def link rustStorage StorageClass
+hi def link rustObsoleteStorage Error
+hi def link rustLifetime Special
+hi def link rustInvalidBareKeyword Error
+hi def link rustExternCrate rustKeyword
+hi def link rustObsoleteExternMod Error
+hi def link rustBoxPlacementParens Delimiter
+hi def link rustBoxPlacementExpr rustKeyword
+
+" Other Suggestions:
+" hi rustAttribute ctermfg=cyan
+" hi rustDerive ctermfg=cyan
+" hi rustAssert ctermfg=yellow
+" hi rustPanic ctermfg=red
+" hi rustMacro ctermfg=magenta
+
+syn sync minlines=200
+syn sync maxlines=500
+
+let b:current_syntax = "rust"