xref: /vim-8.2.3635/runtime/syntax/rust.vim (revision 3c2881dc)
1" Vim syntax file
2" Language:     Rust
3" Maintainer:   Patrick Walton <[email protected]>
4" Maintainer:   Ben Blum <[email protected]>
5" Maintainer:   Chris Morgan <[email protected]>
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"
296