blob: 55d3f14dc2138f449baa3449683e5a960764bd97 [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>
Gregory Andersfc935942023-09-12 13:23:38 -05006" Last Change: 2023-09-11
Bram Moolenaar3c2881d2017-03-21 19:18:29 +01007" For bugs, patches and license go to https://github.com/rust-lang/rust.vim
8
9if version < 600
Gregory Andersfc935942023-09-12 13:23:38 -050010 syntax clear
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010011elseif exists("b:current_syntax")
Gregory Andersfc935942023-09-12 13:23:38 -050012 finish
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010013endif
14
15" Syntax definitions {{{1
16" Basic keywords {{{2
17syn keyword rustConditional match if else
Gregory Andersfc935942023-09-12 13:23:38 -050018syn keyword rustRepeat loop while
19" `:syn match` must be used to prioritize highlighting `for` keyword.
20syn match rustRepeat /\<for\>/
21" Highlight `for` keyword in `impl ... for ... {}` statement. This line must
22" be put after previous `syn match` line to overwrite it.
23syn match rustKeyword /\%(\<impl\>.\+\)\@<=\<for\>/
24syn keyword rustRepeat in
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010025syn keyword rustTypedef type nextgroup=rustIdentifier skipwhite skipempty
26syn keyword rustStructure struct enum nextgroup=rustIdentifier skipwhite skipempty
27syn keyword rustUnion union nextgroup=rustIdentifier skipwhite skipempty contained
28syn match rustUnionContextual /\<union\_s\+\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*/ transparent contains=rustUnion
29syn keyword rustOperator as
Gregory Andersfc935942023-09-12 13:23:38 -050030syn keyword rustExistential existential nextgroup=rustTypedef skipwhite skipempty contained
31syn match rustExistentialContextual /\<existential\_s\+type/ transparent contains=rustExistential,rustTypedef
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010032
33syn match rustAssert "\<assert\(\w\)*!" contained
34syn match rustPanic "\<panic\(\w\)*!" contained
Gregory Andersfc935942023-09-12 13:23:38 -050035syn match rustAsync "\<async\%(\s\|\n\)\@="
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010036syn keyword rustKeyword break
Gregory Andersfc935942023-09-12 13:23:38 -050037syn keyword rustKeyword box
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010038syn keyword rustKeyword continue
Gregory Andersfc935942023-09-12 13:23:38 -050039syn keyword rustKeyword crate
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010040syn keyword rustKeyword extern nextgroup=rustExternCrate,rustObsoleteExternMod skipwhite skipempty
41syn keyword rustKeyword fn nextgroup=rustFuncName skipwhite skipempty
Gregory Andersfc935942023-09-12 13:23:38 -050042syn keyword rustKeyword impl let
43syn keyword rustKeyword macro
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010044syn keyword rustKeyword pub nextgroup=rustPubScope skipwhite skipempty
45syn keyword rustKeyword return
Gregory Andersfc935942023-09-12 13:23:38 -050046syn keyword rustKeyword yield
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010047syn keyword rustSuper super
Gregory Andersfc935942023-09-12 13:23:38 -050048syn keyword rustKeyword where
49syn keyword rustUnsafeKeyword unsafe
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010050syn keyword rustKeyword use nextgroup=rustModPath skipwhite skipempty
51" FIXME: Scoped impl's name is also fallen in this category
52syn keyword rustKeyword mod trait nextgroup=rustIdentifier skipwhite skipempty
53syn keyword rustStorage move mut ref static const
Gregory Andersfc935942023-09-12 13:23:38 -050054syn match rustDefault /\<default\ze\_s\+\(impl\|fn\|type\|const\)\>/
55syn keyword rustAwait await
56syn match rustKeyword /\<try\>!\@!/ display
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010057
58syn keyword rustPubScopeCrate crate contained
59syn match rustPubScopeDelim /[()]/ contained
60syn match rustPubScope /([^()]*)/ contained contains=rustPubScopeDelim,rustPubScopeCrate,rustSuper,rustModPath,rustModPathSep,rustSelf transparent
61
62syn keyword rustExternCrate crate contained nextgroup=rustIdentifier,rustExternCrateString skipwhite skipempty
63" This is to get the `bar` part of `extern crate "foo" as bar;` highlighting.
64syn match rustExternCrateString /".*"\_s*as/ contained nextgroup=rustIdentifier skipwhite transparent skipempty contains=rustString,rustOperator
65syn keyword rustObsoleteExternMod mod contained nextgroup=rustIdentifier skipwhite skipempty
66
67syn match rustIdentifier contains=rustIdentifierPrime "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained
Gregory Andersfc935942023-09-12 13:23:38 -050068syn match rustFuncName "\%(r#\)\=\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010069
Gregory Andersfc935942023-09-12 13:23:38 -050070syn region rustMacroRepeat matchgroup=rustMacroRepeatDelimiters start="$(" end="),\=[*+]" contains=TOP
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010071syn match rustMacroVariable "$\w\+"
Gregory Andersfc935942023-09-12 13:23:38 -050072syn match rustRawIdent "\<r#\h\w*" contains=NONE
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010073
74" Reserved (but not yet used) keywords {{{2
Gregory Andersfc935942023-09-12 13:23:38 -050075syn keyword rustReservedKeyword become do priv typeof unsized abstract virtual final override
Bram Moolenaar3c2881d2017-03-21 19:18:29 +010076
77" Built-in types {{{2
78syn keyword rustType isize usize char bool u8 u16 u32 u64 u128 f32
79syn keyword rustType f64 i8 i16 i32 i64 i128 str Self
80
81" Things from the libstd v1 prelude (src/libstd/prelude/v1.rs) {{{2
82" This section is just straight transformation of the contents of the prelude,
83" to make it easy to update.
84
85" Reexported core operators {{{3
86syn keyword rustTrait Copy Send Sized Sync
87syn keyword rustTrait Drop Fn FnMut FnOnce
88
89" Reexported functions {{{3
90" Theres no point in highlighting these; when one writes drop( or drop::< it
91" gets the same highlighting anyway, and if someone writes `let drop = …;` we
92" dont really want *that* drop to be highlighted.
93"syn keyword rustFunction drop
94
95" Reexported types and traits {{{3
96syn keyword rustTrait Box
97syn keyword rustTrait ToOwned
98syn keyword rustTrait Clone
99syn keyword rustTrait PartialEq PartialOrd Eq Ord
100syn keyword rustTrait AsRef AsMut Into From
101syn keyword rustTrait Default
102syn keyword rustTrait Iterator Extend IntoIterator
103syn keyword rustTrait DoubleEndedIterator ExactSizeIterator
104syn keyword rustEnum Option
105syn keyword rustEnumVariant Some None
106syn keyword rustEnum Result
107syn keyword rustEnumVariant Ok Err
108syn keyword rustTrait SliceConcatExt
109syn keyword rustTrait String ToString
110syn keyword rustTrait Vec
111
112" Other syntax {{{2
113syn keyword rustSelf self
114syn keyword rustBoolean true false
115
116" If foo::bar changes to foo.bar, change this ("::" to "\.").
117" If foo::bar changes to Foo::bar, change this (first "\w" to "\u").
118syn match rustModPath "\w\(\w\)*::[^<]"he=e-3,me=e-3
119syn match rustModPathSep "::"
120
121syn match rustFuncCall "\w\(\w\)*("he=e-1,me=e-1
122syn match rustFuncCall "\w\(\w\)*::<"he=e-3,me=e-3 " foo::<T>();
123
124" This is merely a convention; note also the use of [A-Z], restricting it to
125" latin identifiers rather than the full Unicode uppercase. I have not used
126" [:upper:] as it depends upon 'noignorecase'
127"syn match rustCapsIdent display "[A-Z]\w\(\w\)*"
128
129syn match rustOperator display "\%(+\|-\|/\|*\|=\|\^\|&\||\|!\|>\|<\|%\)=\?"
130" This one isn't *quite* right, as we could have binary-& with a reference
131syn match rustSigil display /&\s\+[&~@*][^)= \t\r\n]/he=e-1,me=e-1
132syn match rustSigil display /[&~@*][^)= \t\r\n]/he=e-1,me=e-1
133" This isn't actually correct; a closure with no arguments can be `|| { }`.
134" Last, because the & in && isn't a sigil
135syn match rustOperator display "&&\|||"
136" This is rustArrowCharacter rather than rustArrow for the sake of matchparen,
137" so it skips the ->; see http://stackoverflow.com/a/30309949 for details.
138syn match rustArrowCharacter display "->"
139syn match rustQuestionMark display "?\([a-zA-Z]\+\)\@!"
140
141syn match rustMacro '\w\(\w\)*!' contains=rustAssert,rustPanic
142syn match rustMacro '#\w\(\w\)*' contains=rustAssert,rustPanic
143
144syn match rustEscapeError display contained /\\./
145syn match rustEscape display contained /\\\([nrt0\\'"]\|x\x\{2}\)/
Gregory Andersfc935942023-09-12 13:23:38 -0500146syn match rustEscapeUnicode display contained /\\u{\%(\x_*\)\{1,6}}/
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100147syn match rustStringContinuation display contained /\\\n\s*/
Gregory Andersfc935942023-09-12 13:23:38 -0500148syn region rustString matchgroup=rustStringDelimiter start=+b"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeError,rustStringContinuation
149syn region rustString matchgroup=rustStringDelimiter start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustStringContinuation,@Spell
150syn region rustString matchgroup=rustStringDelimiter start='b\?r\z(#*\)"' end='"\z1' contains=@Spell
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100151
Gregory Andersfc935942023-09-12 13:23:38 -0500152" Match attributes with either arbitrary syntax or special highlighting for
153" derives. We still highlight strings and comments inside of the attribute.
154syn region rustAttribute start="#!\?\[" end="\]" contains=@rustAttributeContents,rustAttributeParenthesizedParens,rustAttributeParenthesizedCurly,rustAttributeParenthesizedBrackets,rustDerive
155syn region rustAttributeParenthesizedParens matchgroup=rustAttribute start="\w\%(\w\)*("rs=e end=")"re=s transparent contained contains=rustAttributeBalancedParens,@rustAttributeContents
156syn region rustAttributeParenthesizedCurly matchgroup=rustAttribute start="\w\%(\w\)*{"rs=e end="}"re=s transparent contained contains=rustAttributeBalancedCurly,@rustAttributeContents
157syn region rustAttributeParenthesizedBrackets matchgroup=rustAttribute start="\w\%(\w\)*\["rs=e end="\]"re=s transparent contained contains=rustAttributeBalancedBrackets,@rustAttributeContents
158syn region rustAttributeBalancedParens matchgroup=rustAttribute start="("rs=e end=")"re=s transparent contained contains=rustAttributeBalancedParens,@rustAttributeContents
159syn region rustAttributeBalancedCurly matchgroup=rustAttribute start="{"rs=e end="}"re=s transparent contained contains=rustAttributeBalancedCurly,@rustAttributeContents
160syn region rustAttributeBalancedBrackets matchgroup=rustAttribute start="\["rs=e end="\]"re=s transparent contained contains=rustAttributeBalancedBrackets,@rustAttributeContents
161syn cluster rustAttributeContents contains=rustString,rustCommentLine,rustCommentBlock,rustCommentLineDocError,rustCommentBlockDocError
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100162syn region rustDerive start="derive(" end=")" contained contains=rustDeriveTrait
163" This list comes from src/libsyntax/ext/deriving/mod.rs
164" Some are deprecated (Encodable, Decodable) or to be removed after a new snapshot (Show).
165syn keyword rustDeriveTrait contained Clone Hash RustcEncodable RustcDecodable Encodable Decodable PartialEq Eq PartialOrd Ord Rand Show Debug Default FromPrimitive Send Sync Copy
166
Gregory Andersfc935942023-09-12 13:23:38 -0500167" dyn keyword: It's only a keyword when used inside a type expression, so
168" we make effort here to highlight it only when Rust identifiers follow it
169" (not minding the case of pre-2018 Rust where a path starting with :: can
170" follow).
171"
172" This is so that uses of dyn variable names such as in 'let &dyn = &2'
173" and 'let dyn = 2' will not get highlighted as a keyword.
174syn match rustKeyword "\<dyn\ze\_s\+\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)" contains=rustDynKeyword
175syn keyword rustDynKeyword dyn contained
176
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100177" Number literals
178syn match rustDecNumber display "\<[0-9][0-9_]*\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\="
179syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\="
180syn match rustOctNumber display "\<0o[0-7_]\+\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\="
181syn match rustBinNumber display "\<0b[01_]\+\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\="
182
183" Special case for numbers of the form "1." which are float literals, unless followed by
184" an identifier, which makes them integer literals with a method call or field access,
185" or by another ".", which makes them integer literals followed by the ".." token.
186" (This must go first so the others take precedence.)
187syn match rustFloat display "\<[0-9][0-9_]*\.\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\|\.\)\@!"
188" To mark a number as a normal float, it must have at least one of the three things integral values don't have:
189" a decimal point and more numbers; an exponent; and a type suffix.
190syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)\="
191syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\(f32\|f64\)\="
192syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)"
193
194" For the benefit of delimitMate
Gregory Andersfc935942023-09-12 13:23:38 -0500195syn region rustLifetimeCandidate display start=/&'\%(\([^'\\]\|\\\(['nrt0\\\"]\|x\x\{2}\|u{\%(\x_*\)\{1,6}}\)\)'\)\@!/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime
196syn region rustGenericRegion display start=/<\%('\|[^[:cntrl:][:space:][:punct:]]\)\@=')\S\@=/ end=/>/ contains=rustGenericLifetimeCandidate
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100197syn region rustGenericLifetimeCandidate display start=/\%(<\|,\s*\)\@<='/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime
198
199"rustLifetime must appear before rustCharacter, or chars will get the lifetime highlighting
200syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*"
201syn match rustLabel display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*:"
Gregory Andersfc935942023-09-12 13:23:38 -0500202syn match rustLabel display "\%(\<\%(break\|continue\)\s*\)\@<=\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*"
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100203syn match rustCharacterInvalid display contained /b\?'\zs[\n\r\t']\ze'/
204" The groups negated here add up to 0-255 but nothing else (they do not seem to go beyond ASCII).
205syn match rustCharacterInvalidUnicode display contained /b'\zs[^[:cntrl:][:graph:][:alnum:][:space:]]\ze'/
206syn match rustCharacter /b'\([^\\]\|\\\(.\|x\x\{2}\)\)'/ contains=rustEscape,rustEscapeError,rustCharacterInvalid,rustCharacterInvalidUnicode
Gregory Andersfc935942023-09-12 13:23:38 -0500207syn match rustCharacter /'\([^\\]\|\\\(.\|x\x\{2}\|u{\%(\x_*\)\{1,6}}\)\)'/ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustCharacterInvalid
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100208
209syn match rustShebang /\%^#![^[].*/
210syn region rustCommentLine start="//" end="$" contains=rustTodo,@Spell
211syn region rustCommentLineDoc start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell
212syn region rustCommentLineDocError start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell contained
213syn region rustCommentBlock matchgroup=rustCommentBlock start="/\*\%(!\|\*[*/]\@!\)\@!" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell
Gregory Andersfc935942023-09-12 13:23:38 -0500214syn region rustCommentBlockDoc matchgroup=rustCommentBlockDoc start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=rustTodo,rustCommentBlockDocNest,rustCommentBlockDocRustCode,@Spell
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100215syn region rustCommentBlockDocError matchgroup=rustCommentBlockDocError start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=rustTodo,rustCommentBlockDocNestError,@Spell contained
216syn region rustCommentBlockNest matchgroup=rustCommentBlock start="/\*" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell contained transparent
217syn region rustCommentBlockDocNest matchgroup=rustCommentBlockDoc start="/\*" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell contained transparent
218syn region rustCommentBlockDocNestError matchgroup=rustCommentBlockDocError start="/\*" end="\*/" contains=rustTodo,rustCommentBlockDocNestError,@Spell contained transparent
Gregory Andersfc935942023-09-12 13:23:38 -0500219
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100220" FIXME: this is a really ugly and not fully correct implementation. Most
221" importantly, a case like ``/* */*`` should have the final ``*`` not being in
222" a comment, but in practice at present it leaves comments open two levels
223" deep. But as long as you stay away from that particular case, I *believe*
224" the highlighting is correct. Due to the way Vim's syntax engine works
225" (greedy for start matches, unlike Rust's tokeniser which is searching for
226" the earliest-starting match, start or end), I believe this cannot be solved.
227" Oh you who would fix it, don't bother with things like duplicating the Block
228" rules and putting ``\*\@<!`` at the start of them; it makes it worse, as
229" then you must deal with cases like ``/*/**/*/``. And don't try making it
230" worse with ``\%(/\@<!\*\)\@<!``, either...
231
Gregory Andersfc935942023-09-12 13:23:38 -0500232syn keyword rustTodo contained TODO FIXME XXX NB NOTE SAFETY
233
234" asm! macro {{{2
235syn region rustAsmMacro matchgroup=rustMacro start="\<asm!\s*(" end=")" contains=rustAsmDirSpec,rustAsmSym,rustAsmConst,rustAsmOptionsGroup,rustComment.*,rustString.*
236
237" Clobbered registers
238syn keyword rustAsmDirSpec in out lateout inout inlateout contained nextgroup=rustAsmReg skipwhite skipempty
239syn region rustAsmReg start="(" end=")" contained contains=rustString
240
241" Symbol operands
242syn keyword rustAsmSym sym contained nextgroup=rustAsmSymPath skipwhite skipempty
243syn region rustAsmSymPath start="\S" end=",\|)"me=s-1 contained contains=rustComment.*,rustIdentifier
244
245" Const
246syn region rustAsmConstBalancedParens start="("ms=s+1 end=")" contained contains=@rustAsmConstExpr
247syn cluster rustAsmConstExpr contains=rustComment.*,rust.*Number,rustString,rustAsmConstBalancedParens
248syn region rustAsmConst start="const" end=",\|)"me=s-1 contained contains=rustStorage,@rustAsmConstExpr
249
250" Options
251syn region rustAsmOptionsGroup start="options\s*(" end=")" contained contains=rustAsmOptions,rustAsmOptionsKey
252syn keyword rustAsmOptionsKey options contained
253syn keyword rustAsmOptions pure nomem readonly preserves_flags noreturn nostack att_syntax contained
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100254
255" Folding rules {{{2
256" Trivial folding rules to begin with.
257" FIXME: use the AST to make really good folding
258syn region rustFoldBraces start="{" end="}" transparent fold
259
Gregory Andersfc935942023-09-12 13:23:38 -0500260if !exists("b:current_syntax_embed")
261 let b:current_syntax_embed = 1
262 syntax include @RustCodeInComment <sfile>:p:h/rust.vim
263 unlet b:current_syntax_embed
264
265 " Currently regions marked as ```<some-other-syntax> will not get
266 " highlighted at all. In the future, we can do as vim-markdown does and
267 " highlight with the other syntax. But for now, let's make sure we find
268 " the closing block marker, because the rules below won't catch it.
269 syn region rustCommentLinesDocNonRustCode matchgroup=rustCommentDocCodeFence start='^\z(\s*//[!/]\s*```\).\+$' end='^\z1$' keepend contains=rustCommentLineDoc
270
271 " We borrow the rules from rusts src/librustdoc/html/markdown.rs, so that
272 " we only highlight as Rust what it would perceive as Rust (almost; it’s
273 " possible to trick it if you try hard, and indented code blocks arent
274 " supported because Markdown is a menace to parse and only mad dogs and
275 " Englishmen would try to handle that case correctly in this syntax file).
276 syn region rustCommentLinesDocRustCode matchgroup=rustCommentDocCodeFence start='^\z(\s*//[!/]\s*```\)[^A-Za-z0-9_-]*\%(\%(should_panic\|no_run\|ignore\|allow_fail\|rust\|test_harness\|compile_fail\|E\d\{4}\|edition201[58]\)\%([^A-Za-z0-9_-]\+\|$\)\)*$' end='^\z1$' keepend contains=@RustCodeInComment,rustCommentLineDocLeader
277 syn region rustCommentBlockDocRustCode matchgroup=rustCommentDocCodeFence start='^\z(\%(\s*\*\)\?\s*```\)[^A-Za-z0-9_-]*\%(\%(should_panic\|no_run\|ignore\|allow_fail\|rust\|test_harness\|compile_fail\|E\d\{4}\|edition201[58]\)\%([^A-Za-z0-9_-]\+\|$\)\)*$' end='^\z1$' keepend contains=@RustCodeInComment,rustCommentBlockDocStar
278 " Strictly, this may or may not be correct; this code, for example, would
279 " mishighlight:
280 "
281 " /**
282 " ```rust
283 " println!("{}", 1
284 " * 1);
285 " ```
286 " */
287 "
288 " but I dont care. Balance of probability, and all that.
289 syn match rustCommentBlockDocStar /^\s*\*\s\?/ contained
290 syn match rustCommentLineDocLeader "^\s*//\%(//\@!\|!\)" contained
291endif
292
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100293" Default highlighting {{{1
294hi def link rustDecNumber rustNumber
295hi def link rustHexNumber rustNumber
296hi def link rustOctNumber rustNumber
297hi def link rustBinNumber rustNumber
298hi def link rustIdentifierPrime rustIdentifier
299hi def link rustTrait rustType
300hi def link rustDeriveTrait rustTrait
301
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100302hi def link rustMacroRepeatDelimiters Macro
303hi def link rustMacroVariable Define
304hi def link rustSigil StorageClass
305hi def link rustEscape Special
306hi def link rustEscapeUnicode rustEscape
307hi def link rustEscapeError Error
308hi def link rustStringContinuation Special
309hi def link rustString String
Gregory Andersfc935942023-09-12 13:23:38 -0500310hi def link rustStringDelimiter String
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100311hi def link rustCharacterInvalid Error
312hi def link rustCharacterInvalidUnicode rustCharacterInvalid
313hi def link rustCharacter Character
314hi def link rustNumber Number
315hi def link rustBoolean Boolean
316hi def link rustEnum rustType
317hi def link rustEnumVariant rustConstant
318hi def link rustConstant Constant
319hi def link rustSelf Constant
320hi def link rustFloat Float
321hi def link rustArrowCharacter rustOperator
322hi def link rustOperator Operator
323hi def link rustKeyword Keyword
Gregory Andersfc935942023-09-12 13:23:38 -0500324hi def link rustDynKeyword rustKeyword
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100325hi def link rustTypedef Keyword " More precise is Typedef, but it doesn't feel right for Rust
326hi def link rustStructure Keyword " More precise is Structure
327hi def link rustUnion rustStructure
Gregory Andersfc935942023-09-12 13:23:38 -0500328hi def link rustExistential rustKeyword
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100329hi def link rustPubScopeDelim Delimiter
330hi def link rustPubScopeCrate rustKeyword
331hi def link rustSuper rustKeyword
Gregory Andersfc935942023-09-12 13:23:38 -0500332hi def link rustUnsafeKeyword Exception
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100333hi def link rustReservedKeyword Error
334hi def link rustRepeat Conditional
335hi def link rustConditional Conditional
336hi def link rustIdentifier Identifier
337hi def link rustCapsIdent rustIdentifier
338hi def link rustModPath Include
339hi def link rustModPathSep Delimiter
340hi def link rustFunction Function
341hi def link rustFuncName Function
342hi def link rustFuncCall Function
343hi def link rustShebang Comment
344hi def link rustCommentLine Comment
345hi def link rustCommentLineDoc SpecialComment
Gregory Andersfc935942023-09-12 13:23:38 -0500346hi def link rustCommentLineDocLeader rustCommentLineDoc
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100347hi def link rustCommentLineDocError Error
348hi def link rustCommentBlock rustCommentLine
349hi def link rustCommentBlockDoc rustCommentLineDoc
Gregory Andersfc935942023-09-12 13:23:38 -0500350hi def link rustCommentBlockDocStar rustCommentBlockDoc
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100351hi def link rustCommentBlockDocError Error
Gregory Andersfc935942023-09-12 13:23:38 -0500352hi def link rustCommentDocCodeFence rustCommentLineDoc
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100353hi def link rustAssert PreCondit
354hi def link rustPanic PreCondit
355hi def link rustMacro Macro
356hi def link rustType Type
357hi def link rustTodo Todo
358hi def link rustAttribute PreProc
359hi def link rustDerive PreProc
360hi def link rustDefault StorageClass
361hi def link rustStorage StorageClass
362hi def link rustObsoleteStorage Error
363hi def link rustLifetime Special
364hi def link rustLabel Label
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100365hi def link rustExternCrate rustKeyword
366hi def link rustObsoleteExternMod Error
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100367hi def link rustQuestionMark Special
Gregory Andersfc935942023-09-12 13:23:38 -0500368hi def link rustAsync rustKeyword
369hi def link rustAwait rustKeyword
370hi def link rustAsmDirSpec rustKeyword
371hi def link rustAsmSym rustKeyword
372hi def link rustAsmOptions rustKeyword
373hi def link rustAsmOptionsKey rustAttribute
Bram Moolenaar3c2881d2017-03-21 19:18:29 +0100374
375" Other Suggestions:
376" hi rustAttribute ctermfg=cyan
377" hi rustDerive ctermfg=cyan
378" hi rustAssert ctermfg=yellow
379" hi rustPanic ctermfg=red
380" hi rustMacro ctermfg=magenta
381
382syn sync minlines=200
383syn sync maxlines=500
384
385let b:current_syntax = "rust"
Gregory Andersfc935942023-09-12 13:23:38 -0500386
387" vim: set et sw=4 sts=4 ts=8: