3 " Maintainer: Patrick Walton <pcwalton@mozilla.com>
4 " Maintainer: Ben Blum <bblum@cs.cmu.edu>
5 " Maintainer: Chris Morgan <me@chrismorgan.info>
6 " Last Change: January 5, 2015
10 elseif exists("b:current_syntax")
14 " Syntax definitions {{{1
16 syn keyword rustConditional match if else
17 syn keyword rustOperator as
19 syn match rustAssert "\<assert\(\w\)*!" contained
20 syn match rustPanic "\<panic\(\w\)*!" contained
21 syn keyword rustKeyword break
22 syn keyword rustKeyword box nextgroup=rustBoxPlacement skipwhite skipempty
23 syn keyword rustKeyword continue
24 syn keyword rustKeyword extern nextgroup=rustExternCrate,rustObsoleteExternMod skipwhite skipempty
25 syn keyword rustKeyword fn nextgroup=rustFuncName skipwhite skipempty
26 syn keyword rustKeyword for in if impl let
27 syn keyword rustKeyword loop once pub
28 syn keyword rustKeyword return super
29 syn keyword rustKeyword unsafe virtual where while
30 syn keyword rustKeyword use nextgroup=rustModPath skipwhite skipempty
31 " FIXME: Scoped impl's name is also fallen in this category
32 syn keyword rustKeyword mod trait struct enum type nextgroup=rustIdentifier skipwhite skipempty
33 syn keyword rustStorage move mut ref static const
35 syn keyword rustInvalidBareKeyword crate
37 syn keyword rustExternCrate crate contained nextgroup=rustIdentifier,rustExternCrateString skipwhite skipempty
38 " This is to get the `bar` part of `extern crate "foo" as bar;` highlighting.
39 syn match rustExternCrateString /".*"\_s*as/ contained nextgroup=rustIdentifier skipwhite transparent skipempty contains=rustString,rustOperator
40 syn keyword rustObsoleteExternMod mod contained nextgroup=rustIdentifier skipwhite skipempty
42 syn match rustIdentifier contains=rustIdentifierPrime "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained
43 syn match rustFuncName "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained
45 syn region rustBoxPlacement matchgroup=rustBoxPlacementParens start="(" end=")" contains=TOP contained
46 syn keyword rustBoxPlacementExpr GC containedin=rustBoxPlacement
47 " Ideally we'd have syntax rules set up to match arbitrary expressions. Since
48 " we don't, we'll just define temporary contained rules to handle balancing
50 syn region rustBoxPlacementBalance start="(" end=")" containedin=rustBoxPlacement transparent
51 syn region rustBoxPlacementBalance start="\[" end="\]" containedin=rustBoxPlacement transparent
52 " {} are handled by rustFoldBraces
54 syn region rustMacroRepeat matchgroup=rustMacroRepeatDelimiters start="$(" end=")" contains=TOP nextgroup=rustMacroRepeatCount
55 syn match rustMacroRepeatCount ".\?[*+]" contained
56 syn match rustMacroVariable "$\w\+"
58 " Reserved (but not yet used) keywords {{{2
59 syn keyword rustReservedKeyword alignof be do offsetof priv pure sizeof typeof unsized yield abstract final override
62 syn keyword rustType int uint float char bool u8 u16 u32 u64 f32
63 syn keyword rustType f64 i8 i16 i32 i64 str Self
65 " Things from the prelude (src/libstd/prelude.rs) {{{2
66 " This section is just straight transformation of the contents of the prelude,
67 " to make it easy to update.
69 " Reexported core operators {{{3
70 syn keyword rustTrait Copy Send Sized Sync
71 syn keyword rustTrait Drop Fn FnMut FnOnce
73 " Reexported functions {{{3
74 syn keyword rustFunction drop
76 " Reexported types and traits {{{3
77 syn keyword rustTrait Box
78 syn keyword rustTrait CharExt
79 syn keyword rustTrait Clone
80 syn keyword rustTrait PartialEq PartialOrd Eq Ord
81 syn keyword rustTrait DoubleEndedIterator
82 syn keyword rustTrait ExactSizeIterator
83 syn keyword rustTrait Iterator IteratorExt Extend
84 syn keyword rustEnum Option
85 syn keyword rustEnumVariant Some None
86 syn keyword rustTrait PtrExt MutPtrExt
87 syn keyword rustEnum Result
88 syn keyword rustEnumVariant Ok Err
89 syn keyword rustTrait AsSlice
90 syn keyword rustTrait SliceExt SliceConcatExt
91 syn keyword rustTrait Str StrExt
92 syn keyword rustTrait String ToString
93 syn keyword rustTrait Vec
94 " FIXME: remove when path reform lands
95 syn keyword rustTrait Path GenericPath
96 " FIXME: remove when I/O reform lands
97 syn keyword rustTrait Buffer Writer Reader Seek BufferPrelude
98 " FIXME: remove when range syntax lands
99 syn keyword rustFunction range
102 syn keyword rustSelf self
103 syn keyword rustBoolean true false
105 " If foo::bar changes to foo.bar, change this ("::" to "\.").
106 " If foo::bar changes to Foo::bar, change this (first "\w" to "\u").
107 syn match rustModPath "\w\(\w\)*::[^<]"he=e-3,me=e-3
108 syn match rustModPathSep "::"
110 syn match rustFuncCall "\w\(\w\)*("he=e-1,me=e-1
111 syn match rustFuncCall "\w\(\w\)*::<"he=e-3,me=e-3 " foo::<T>();
113 " This is merely a convention; note also the use of [A-Z], restricting it to
114 " latin identifiers rather than the full Unicode uppercase. I have not used
115 " [:upper:] as it depends upon 'noignorecase'
116 "syn match rustCapsIdent display "[A-Z]\w\(\w\)*"
118 syn match rustOperator display "\%(+\|-\|/\|*\|=\|\^\|&\||\|!\|>\|<\|%\)=\?"
119 " This one isn't *quite* right, as we could have binary-& with a reference
120 syn match rustSigil display /&\s\+[&~@*][^)= \t\r\n]/he=e-1,me=e-1
121 syn match rustSigil display /[&~@*][^)= \t\r\n]/he=e-1,me=e-1
122 " This isn't actually correct; a closure with no arguments can be `|| { }`.
123 " Last, because the & in && isn't a sigil
124 syn match rustOperator display "&&\|||"
126 syn match rustMacro '\w\(\w\)*!' contains=rustAssert,rustPanic
127 syn match rustMacro '#\w\(\w\)*' contains=rustAssert,rustPanic
129 syn match rustEscapeError display contained /\\./
130 syn match rustEscape display contained /\\\([nrt0\\'"]\|x\x\{2}\)/
131 syn match rustEscapeUnicode display contained /\\\(u\x\{4}\|U\x\{8}\)/
132 syn match rustEscapeUnicode display contained /\\u{\x\{1,6}}/
133 syn match rustStringContinuation display contained /\\\n\s*/
134 syn region rustString start=+b"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeError,rustStringContinuation
135 syn region rustString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustStringContinuation,@Spell
136 syn region rustString start='b\?r\z(#*\)"' end='"\z1' contains=@Spell
138 syn region rustAttribute start="#!\?\[" end="\]" contains=rustString,rustDerive
139 syn region rustDerive start="derive(" end=")" contained contains=rustTrait
142 syn match rustDecNumber display "\<[0-9][0-9_]*\%([iu]\%(8\|16\|32\|64\)\=\)\="
143 syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\%([iu]\%(8\|16\|32\|64\)\=\)\="
144 syn match rustOctNumber display "\<0o[0-7_]\+\%([iu]\%(8\|16\|32\|64\)\=\)\="
145 syn match rustBinNumber display "\<0b[01_]\+\%([iu]\%(8\|16\|32\|64\)\=\)\="
147 " Special case for numbers of the form "1." which are float literals, unless followed by
148 " an identifier, which makes them integer literals with a method call or field access,
149 " or by another ".", which makes them integer literals followed by the ".." token.
150 " (This must go first so the others take precedence.)
151 syn match rustFloat display "\<[0-9][0-9_]*\.\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\|\.\)\@!"
152 " To mark a number as a normal float, it must have at least one of the three things integral values don't have:
153 " a decimal point and more numbers; an exponent; and a type suffix.
154 syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)\="
155 syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\(f32\|f64\)\="
156 syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)"
158 " For the benefit of delimitMate
159 syn region rustLifetimeCandidate display start=/&'\%(\([^'\\]\|\\\(['nrt0\\\"]\|x\x\{2}\|u\x\{4}\|U\x\{8}\)\)'\)\@!/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime
160 syn region rustGenericRegion display start=/<\%('\|[^[cntrl:][:space:][:punct:]]\)\@=')\S\@=/ end=/>/ contains=rustGenericLifetimeCandidate
161 syn region rustGenericLifetimeCandidate display start=/\%(<\|,\s*\)\@<='/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime
163 "rustLifetime must appear before rustCharacter, or chars will get the lifetime highlighting
164 syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*"
165 syn match rustCharacterInvalid display contained /b\?'\zs[\n\r\t']\ze'/
166 " The groups negated here add up to 0-255 but nothing else (they do not seem to go beyond ASCII).
167 syn match rustCharacterInvalidUnicode display contained /b'\zs[^[:cntrl:][:graph:][:alnum:][:space:]]\ze'/
168 syn match rustCharacter /b'\([^\\]\|\\\(.\|x\x\{2}\)\)'/ contains=rustEscape,rustEscapeError,rustCharacterInvalid,rustCharacterInvalidUnicode
169 syn match rustCharacter /'\([^\\]\|\\\(.\|x\x\{2}\|u\x\{4}\|U\x\{8}\|u{\x\{1,6}}\)\)'/ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustCharacterInvalid
171 syn region rustCommentLine start="//" end="$" contains=rustTodo,@Spell
172 syn region rustCommentLineDoc start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell
173 syn region rustCommentBlock matchgroup=rustCommentBlock start="/\*\%(!\|\*[*/]\@!\)\@!" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell
174 syn region rustCommentBlockDoc matchgroup=rustCommentBlockDoc start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell
175 syn region rustCommentBlockNest matchgroup=rustCommentBlock start="/\*" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell contained transparent
176 syn region rustCommentBlockDocNest matchgroup=rustCommentBlockDoc start="/\*" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell contained transparent
177 " FIXME: this is a really ugly and not fully correct implementation. Most
178 " importantly, a case like ``/* */*`` should have the final ``*`` not being in
179 " a comment, but in practice at present it leaves comments open two levels
180 " deep. But as long as you stay away from that particular case, I *believe*
181 " the highlighting is correct. Due to the way Vim's syntax engine works
182 " (greedy for start matches, unlike Rust's tokeniser which is searching for
183 " the earliest-starting match, start or end), I believe this cannot be solved.
184 " Oh you who would fix it, don't bother with things like duplicating the Block
185 " rules and putting ``\*\@<!`` at the start of them; it makes it worse, as
186 " then you must deal with cases like ``/*/**/*/``. And don't try making it
187 " worse with ``\%(/\@<!\*\)\@<!``, either...
189 syn keyword rustTodo contained TODO FIXME XXX NB NOTE
192 " Trivial folding rules to begin with.
193 " FIXME: use the AST to make really good folding
194 syn region rustFoldBraces start="{" end="}" transparent fold
196 " Default highlighting {{{1
197 hi def link rustDecNumber rustNumber
198 hi def link rustHexNumber rustNumber
199 hi def link rustOctNumber rustNumber
200 hi def link rustBinNumber rustNumber
201 hi def link rustIdentifierPrime rustIdentifier
202 hi def link rustTrait rustType
204 hi def link rustMacroRepeatCount rustMacroRepeatDelimiters
205 hi def link rustMacroRepeatDelimiters Macro
206 hi def link rustMacroVariable Define
207 hi def link rustSigil StorageClass
208 hi def link rustEscape Special
209 hi def link rustEscapeUnicode rustEscape
210 hi def link rustEscapeError Error
211 hi def link rustStringContinuation Special
212 hi def link rustString String
213 hi def link rustCharacterInvalid Error
214 hi def link rustCharacterInvalidUnicode rustCharacterInvalid
215 hi def link rustCharacter Character
216 hi def link rustNumber Number
217 hi def link rustBoolean Boolean
218 hi def link rustEnum rustType
219 hi def link rustEnumVariant rustConstant
220 hi def link rustConstant Constant
221 hi def link rustSelf Constant
222 hi def link rustFloat Float
223 hi def link rustOperator Operator
224 hi def link rustKeyword Keyword
225 hi def link rustReservedKeyword Error
226 hi def link rustConditional Conditional
227 hi def link rustIdentifier Identifier
228 hi def link rustCapsIdent rustIdentifier
229 hi def link rustModPath Include
230 hi def link rustModPathSep Delimiter
231 hi def link rustFunction Function
232 hi def link rustFuncName Function
233 hi def link rustFuncCall Function
234 hi def link rustCommentLine Comment
235 hi def link rustCommentLineDoc SpecialComment
236 hi def link rustCommentBlock rustCommentLine
237 hi def link rustCommentBlockDoc rustCommentLineDoc
238 hi def link rustAssert PreCondit
239 hi def link rustPanic PreCondit
240 hi def link rustMacro Macro
241 hi def link rustType Type
242 hi def link rustTodo Todo
243 hi def link rustAttribute PreProc
244 hi def link rustDerive PreProc
245 hi def link rustStorage StorageClass
246 hi def link rustObsoleteStorage Error
247 hi def link rustLifetime Special
248 hi def link rustInvalidBareKeyword Error
249 hi def link rustExternCrate rustKeyword
250 hi def link rustObsoleteExternMod Error
251 hi def link rustBoxPlacementParens Delimiter
252 hi def link rustBoxPlacementExpr rustKeyword
255 " hi rustAttribute ctermfg=cyan
256 " hi rustDerive ctermfg=cyan
257 " hi rustAssert ctermfg=yellow
258 " hi rustPanic ctermfg=red
259 " hi rustMacro ctermfg=magenta
261 syn sync minlines=200
262 syn sync maxlines=500
264 let b:current_syntax = "rust"