blob: 57343301e07dbe2133e5fb89706279472ef6d400 [file] [log] [blame]
Bram Moolenaar3c2881d2017-03-21 19:18:29 +01001" Vim syntax file
2" Language: Rust
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: Feb 24, 2016
7" For bugs, patches and license go to https://github.com/rust-lang/rust.vim
8
9if version < 600
10 syntax clear
11elseif exists("b:current_syntax")
12 finish
13endif
14
15" Syntax definitions {{{1
16" Basic keywords {{{2
17syn keyword rustConditional match if else
18syn keyword rustRepeat for loop while
19syn keyword rustTypedef type nextgroup=rustIdentifier skipwhite skipempty
20syn keyword rustStructure struct enum nextgroup=rustIdentifier skipwhite skipempty
21syn keyword rustUnion union nextgroup=rustIdentifier skipwhite skipempty contained
22syn match rustUnionContextual /\<union\_s\+\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*/ transparent contains=rustUnion
23syn keyword rustOperator as
24
25syn match rustAssert "\<assert\(\w\)*!" contained
26syn match rustPanic "\<panic\(\w\)*!" contained
27syn keyword rustKeyword break
28syn keyword rustKeyword box nextgroup=rustBoxPlacement skipwhite skipempty
29syn keyword rustKeyword continue
30syn keyword rustKeyword extern nextgroup=rustExternCrate,rustObsoleteExternMod skipwhite skipempty
31syn keyword rustKeyword fn nextgroup=rustFuncName skipwhite skipempty
32syn keyword rustKeyword in impl let
33syn keyword rustKeyword pub nextgroup=rustPubScope skipwhite skipempty
34syn keyword rustKeyword return
35syn keyword rustSuper super
36syn keyword rustKeyword unsafe where
37syn keyword rustKeyword use nextgroup=rustModPath skipwhite skipempty
38" FIXME: Scoped impl's name is also fallen in this category
39syn keyword rustKeyword mod trait nextgroup=rustIdentifier skipwhite skipempty
40syn keyword rustStorage move mut ref static const
41syn match rustDefault /\<default\ze\_s\+\(impl\|fn\|type\|const\)\>/
42
43syn keyword rustInvalidBareKeyword crate
44
45syn keyword rustPubScopeCrate crate contained
46syn match rustPubScopeDelim /[()]/ contained
47syn match rustPubScope /([^()]*)/ contained contains=rustPubScopeDelim,rustPubScopeCrate,rustSuper,rustModPath,rustModPathSep,rustSelf transparent
48
49syn keyword rustExternCrate crate contained nextgroup=rustIdentifier,rustExternCrateString skipwhite skipempty
50" This is to get the `bar` part of `extern crate "foo" as bar;` highlighting.
51syn match rustExternCrateString /".*"\_s*as/ contained nextgroup=rustIdentifier skipwhite transparent skipempty contains=rustString,rustOperator
52syn keyword rustObsoleteExternMod mod contained nextgroup=rustIdentifier skipwhite skipempty
53
54syn match rustIdentifier contains=rustIdentifierPrime "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained
55syn match rustFuncName "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained
56
57syn region rustBoxPlacement matchgroup=rustBoxPlacementParens start="(" end=")" contains=TOP contained
58" Ideally we'd have syntax rules set up to match arbitrary expressions. Since
59" we don't, we'll just define temporary contained rules to handle balancing
60" delimiters.
61syn region rustBoxPlacementBalance start="(" end=")" containedin=rustBoxPlacement transparent
62syn region rustBoxPlacementBalance start="\[" end="\]" containedin=rustBoxPlacement transparent
63" {} are handled by rustFoldBraces
64
65syn region rustMacroRepeat matchgroup=rustMacroRepeatDelimiters start="$(" end=")" contains=TOP nextgroup=rustMacroRepeatCount
66syn match rustMacroRepeatCount ".\?[*+]" contained
67syn match rustMacroVariable "$\w\+"
68
69" Reserved (but not yet used) keywords {{{2
70syn keyword rustReservedKeyword alignof become do offsetof priv pure sizeof typeof unsized yield abstract virtual final override macro
71
72" Built-in types {{{2
73syn keyword rustType isize usize char bool u8 u16 u32 u64 u128 f32
74syn keyword rustType f64 i8 i16 i32 i64 i128 str Self
75
76" Things from the libstd v1 prelude (src/libstd/prelude/v1.rs) {{{2
77" This section is just straight transformation of the contents of the prelude,
78" to make it easy to update.
79
80" Reexported core operators {{{3
81syn keyword rustTrait Copy Send Sized Sync
82syn keyword rustTrait Drop Fn FnMut FnOnce
83
84" Reexported functions {{{3
85" There’s no point in highlighting these; when one writes drop( or drop::< it
86" gets the same highlighting anyway, and if someone writes `let drop = …;` we
87" don’t really want *that* drop to be highlighted.
88"syn keyword rustFunction drop
89
90" Reexported types and traits {{{3
91syn keyword rustTrait Box
92syn keyword rustTrait ToOwned
93syn keyword rustTrait Clone
94syn keyword rustTrait PartialEq PartialOrd Eq Ord
95syn keyword rustTrait AsRef AsMut Into From
96syn keyword rustTrait Default
97syn keyword rustTrait Iterator Extend IntoIterator
98syn keyword rustTrait DoubleEndedIterator ExactSizeIterator
99syn keyword rustEnum Option
100syn keyword rustEnumVariant Some None
101syn keyword rustEnum Result
102syn keyword rustEnumVariant Ok Err
103syn keyword rustTrait SliceConcatExt
104syn keyword rustTrait String ToString
105syn keyword rustTrait Vec
106
107" Other syntax {{{2
108syn keyword rustSelf self
109syn keyword rustBoolean true false
110
111" If foo::bar changes to foo.bar, change this ("::" to "\.").
112" If foo::bar changes to Foo::bar, change this (first "\w" to "\u").
113syn match rustModPath "\w\(\w\)*::[^<]"he=e-3,me=e-3
114syn match rustModPathSep "::"
115
116syn match rustFuncCall "\w\(\w\)*("he=e-1,me=e-1
117syn match rustFuncCall "\w\(\w\)*::<"he=e-3,me=e-3 " foo::<T>();
118
119" This is merely a convention; note also the use of [A-Z], restricting it to
120" latin identifiers rather than the full Unicode uppercase. I have not used
121" [:upper:] as it depends upon 'noignorecase'
122"syn match rustCapsIdent display "[A-Z]\w\(\w\)*"
123
124syn match rustOperator display "\%(+\|-\|/\|*\|=\|\^\|&\||\|!\|>\|<\|%\)=\?"
125" This one isn't *quite* right, as we could have binary-& with a reference
126syn match rustSigil display /&\s\+[&~@*][^)= \t\r\n]/he=e-1,me=e-1
127syn match rustSigil display /[&~@*][^)= \t\r\n]/he=e-1,me=e-1
128" This isn't actually correct; a closure with no arguments can be `|| { }`.
129" Last, because the & in && isn't a sigil
130syn match rustOperator display "&&\|||"
131" This is rustArrowCharacter rather than rustArrow for the sake of matchparen,
132" so it skips the ->; see http://stackoverflow.com/a/30309949 for details.
133syn match rustArrowCharacter display "->"
134syn match rustQuestionMark display "?\([a-zA-Z]\+\)\@!"
135
136syn match rustMacro '\w\(\w\)*!' contains=rustAssert,rustPanic
137syn match rustMacro '#\w\(\w\)*' contains=rustAssert,rustPanic
138
139syn match rustEscapeError display contained /\\./
140syn match rustEscape display contained /\\\([nrt0\\'"]\|x\x\{2}\)/
141syn match rustEscapeUnicode display contained /\\u{\x\{1,6}}/
142syn match rustStringContinuation display contained /\\\n\s*/
143syn region rustString start=+b"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeError,rustStringContinuation
144syn region rustString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustStringContinuation,@Spell
145syn region rustString start='b\?r\z(#*\)"' end='"\z1' contains=@Spell
146
147syn region rustAttribute start="#!\?\[" end="\]" contains=rustString,rustDerive,rustCommentLine,rustCommentBlock,rustCommentLineDocError,rustCommentBlockDocError
148syn region rustDerive start="derive(" end=")" contained contains=rustDeriveTrait
149" This list comes from src/libsyntax/ext/deriving/mod.rs
150" Some are deprecated (Encodable, Decodable) or to be removed after a new snapshot (Show).
151syn keyword rustDeriveTrait contained Clone Hash RustcEncodable RustcDecodable Encodable Decodable PartialEq Eq PartialOrd Ord Rand Show Debug Default FromPrimitive Send Sync Copy
152
153" Number literals
154syn match rustDecNumber display "\<[0-9][0-9_]*\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\="
155syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\="
156syn match rustOctNumber display "\<0o[0-7_]\+\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\="
157syn match rustBinNumber display "\<0b[01_]\+\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\="
158
159" Special case for numbers of the form "1." which are float literals, unless followed by
160" an identifier, which makes them integer literals with a method call or field access,
161" or by another ".", which makes them integer literals followed by the ".." token.
162" (This must go first so the others take precedence.)
163syn match rustFloat display "\<[0-9][0-9_]*\.\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\|\.\)\@!"
164" To mark a number as a normal float, it must have at least one of the three things integral values don't have:
165" a decimal point and more numbers; an exponent; and a type suffix.
166syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)\="
167syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\(f32\|f64\)\="
168syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)"
169
170" For the benefit of delimitMate
171syn region rustLifetimeCandidate display start=/&'\%(\([^'\\]\|\\\(['nrt0\\\"]\|x\x\{2}\|u{\x\{1,6}}\)\)'\)\@!/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime
172syn region rustGenericRegion display start=/<\%('\|[^[cntrl:][:space:][:punct:]]\)\@=')\S\@=/ end=/>/ contains=rustGenericLifetimeCandidate
173syn region rustGenericLifetimeCandidate display start=/\%(<\|,\s*\)\@<='/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime
174
175"rustLifetime must appear before rustCharacter, or chars will get the lifetime highlighting
176syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*"
177syn match rustLabel display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*:"
178syn match rustCharacterInvalid display contained /b\?'\zs[\n\r\t']\ze'/
179" The groups negated here add up to 0-255 but nothing else (they do not seem to go beyond ASCII).
180syn match rustCharacterInvalidUnicode display contained /b'\zs[^[:cntrl:][:graph:][:alnum:][:space:]]\ze'/
181syn match rustCharacter /b'\([^\\]\|\\\(.\|x\x\{2}\)\)'/ contains=rustEscape,rustEscapeError,rustCharacterInvalid,rustCharacterInvalidUnicode
182syn match rustCharacter /'\([^\\]\|\\\(.\|x\x\{2}\|u{\x\{1,6}}\)\)'/ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustCharacterInvalid
183
184syn match rustShebang /\%^#![^[].*/
185syn region rustCommentLine start="//" end="$" contains=rustTodo,@Spell
186syn region rustCommentLineDoc start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell
187syn region rustCommentLineDocError start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell contained
188syn region rustCommentBlock matchgroup=rustCommentBlock start="/\*\%(!\|\*[*/]\@!\)\@!" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell
189syn region rustCommentBlockDoc matchgroup=rustCommentBlockDoc start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell
190syn region rustCommentBlockDocError matchgroup=rustCommentBlockDocError start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=rustTodo,rustCommentBlockDocNestError,@Spell contained
191syn region rustCommentBlockNest matchgroup=rustCommentBlock start="/\*" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell contained transparent
192syn region rustCommentBlockDocNest matchgroup=rustCommentBlockDoc start="/\*" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell contained transparent
193syn region rustCommentBlockDocNestError matchgroup=rustCommentBlockDocError start="/\*" end="\*/" contains=rustTodo,rustCommentBlockDocNestError,@Spell contained transparent
194" FIXME: this is a really ugly and not fully correct implementation. Most
195" importantly, a case like ``/* */*`` should have the final ``*`` not being in
196" a comment, but in practice at present it leaves comments open two levels
197" deep. But as long as you stay away from that particular case, I *believe*
198" the highlighting is correct. Due to the way Vim's syntax engine works
199" (greedy for start matches, unlike Rust's tokeniser which is searching for
200" the earliest-starting match, start or end), I believe this cannot be solved.
201" Oh you who would fix it, don't bother with things like duplicating the Block
202" rules and putting ``\*\@<!`` at the start of them; it makes it worse, as
203" then you must deal with cases like ``/*/**/*/``. And don't try making it
204" worse with ``\%(/\@<!\*\)\@<!``, either...
205
206syn keyword rustTodo contained TODO FIXME XXX NB NOTE
207
208" Folding rules {{{2
209" Trivial folding rules to begin with.
210" FIXME: use the AST to make really good folding
211syn region rustFoldBraces start="{" end="}" transparent fold
212
213" Default highlighting {{{1
214hi def link rustDecNumber rustNumber
215hi def link rustHexNumber rustNumber
216hi def link rustOctNumber rustNumber
217hi def link rustBinNumber rustNumber
218hi def link rustIdentifierPrime rustIdentifier
219hi def link rustTrait rustType
220hi def link rustDeriveTrait rustTrait
221
222hi def link rustMacroRepeatCount rustMacroRepeatDelimiters
223hi def link rustMacroRepeatDelimiters Macro
224hi def link rustMacroVariable Define
225hi def link rustSigil StorageClass
226hi def link rustEscape Special
227hi def link rustEscapeUnicode rustEscape
228hi def link rustEscapeError Error
229hi def link rustStringContinuation Special
230hi def link rustString String
231hi def link rustCharacterInvalid Error
232hi def link rustCharacterInvalidUnicode rustCharacterInvalid
233hi def link rustCharacter Character
234hi def link rustNumber Number
235hi def link rustBoolean Boolean
236hi def link rustEnum rustType
237hi def link rustEnumVariant rustConstant
238hi def link rustConstant Constant
239hi def link rustSelf Constant
240hi def link rustFloat Float
241hi def link rustArrowCharacter rustOperator
242hi def link rustOperator Operator
243hi def link rustKeyword Keyword
244hi def link rustTypedef Keyword " More precise is Typedef, but it doesn't feel right for Rust
245hi def link rustStructure Keyword " More precise is Structure
246hi def link rustUnion rustStructure
247hi def link rustPubScopeDelim Delimiter
248hi def link rustPubScopeCrate rustKeyword
249hi def link rustSuper rustKeyword
250hi def link rustReservedKeyword Error
251hi def link rustRepeat Conditional
252hi def link rustConditional Conditional
253hi def link rustIdentifier Identifier
254hi def link rustCapsIdent rustIdentifier
255hi def link rustModPath Include
256hi def link rustModPathSep Delimiter
257hi def link rustFunction Function
258hi def link rustFuncName Function
259hi def link rustFuncCall Function
260hi def link rustShebang Comment
261hi def link rustCommentLine Comment
262hi def link rustCommentLineDoc SpecialComment
263hi def link rustCommentLineDocError Error
264hi def link rustCommentBlock rustCommentLine
265hi def link rustCommentBlockDoc rustCommentLineDoc
266hi def link rustCommentBlockDocError Error
267hi def link rustAssert PreCondit
268hi def link rustPanic PreCondit
269hi def link rustMacro Macro
270hi def link rustType Type
271hi def link rustTodo Todo
272hi def link rustAttribute PreProc
273hi def link rustDerive PreProc
274hi def link rustDefault StorageClass
275hi def link rustStorage StorageClass
276hi def link rustObsoleteStorage Error
277hi def link rustLifetime Special
278hi def link rustLabel Label
279hi def link rustInvalidBareKeyword Error
280hi def link rustExternCrate rustKeyword
281hi def link rustObsoleteExternMod Error
282hi def link rustBoxPlacementParens Delimiter
283hi def link rustQuestionMark Special
284
285" Other Suggestions:
286" hi rustAttribute ctermfg=cyan
287" hi rustDerive ctermfg=cyan
288" hi rustAssert ctermfg=yellow
289" hi rustPanic ctermfg=red
290" hi rustMacro ctermfg=magenta
291
292syn sync minlines=200
293syn sync maxlines=500
294
295let b:current_syntax = "rust"