Bram Moolenaar | 3c2881d | 2017-03-21 19:18:29 +0100 | [diff] [blame] | 1 | " 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 | |
| 9 | if version < 600 |
| 10 | syntax clear |
| 11 | elseif exists("b:current_syntax") |
| 12 | finish |
| 13 | endif |
| 14 | |
| 15 | " Syntax definitions {{{1 |
| 16 | " Basic keywords {{{2 |
| 17 | syn keyword rustConditional match if else |
| 18 | syn keyword rustRepeat for loop while |
| 19 | syn keyword rustTypedef type nextgroup=rustIdentifier skipwhite skipempty |
| 20 | syn keyword rustStructure struct enum nextgroup=rustIdentifier skipwhite skipempty |
| 21 | syn keyword rustUnion union nextgroup=rustIdentifier skipwhite skipempty contained |
| 22 | syn match rustUnionContextual /\<union\_s\+\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*/ transparent contains=rustUnion |
| 23 | syn keyword rustOperator as |
| 24 | |
| 25 | syn match rustAssert "\<assert\(\w\)*!" contained |
| 26 | syn match rustPanic "\<panic\(\w\)*!" contained |
| 27 | syn keyword rustKeyword break |
| 28 | syn keyword rustKeyword box nextgroup=rustBoxPlacement skipwhite skipempty |
| 29 | syn keyword rustKeyword continue |
| 30 | syn keyword rustKeyword extern nextgroup=rustExternCrate,rustObsoleteExternMod skipwhite skipempty |
| 31 | syn keyword rustKeyword fn nextgroup=rustFuncName skipwhite skipempty |
| 32 | syn keyword rustKeyword in impl let |
| 33 | syn keyword rustKeyword pub nextgroup=rustPubScope skipwhite skipempty |
| 34 | syn keyword rustKeyword return |
| 35 | syn keyword rustSuper super |
| 36 | syn keyword rustKeyword unsafe where |
| 37 | syn keyword rustKeyword use nextgroup=rustModPath skipwhite skipempty |
| 38 | " FIXME: Scoped impl's name is also fallen in this category |
| 39 | syn keyword rustKeyword mod trait nextgroup=rustIdentifier skipwhite skipempty |
| 40 | syn keyword rustStorage move mut ref static const |
| 41 | syn match rustDefault /\<default\ze\_s\+\(impl\|fn\|type\|const\)\>/ |
| 42 | |
| 43 | syn keyword rustInvalidBareKeyword crate |
| 44 | |
| 45 | syn keyword rustPubScopeCrate crate contained |
| 46 | syn match rustPubScopeDelim /[()]/ contained |
| 47 | syn match rustPubScope /([^()]*)/ contained contains=rustPubScopeDelim,rustPubScopeCrate,rustSuper,rustModPath,rustModPathSep,rustSelf transparent |
| 48 | |
| 49 | syn keyword rustExternCrate crate contained nextgroup=rustIdentifier,rustExternCrateString skipwhite skipempty |
| 50 | " This is to get the `bar` part of `extern crate "foo" as bar;` highlighting. |
| 51 | syn match rustExternCrateString /".*"\_s*as/ contained nextgroup=rustIdentifier skipwhite transparent skipempty contains=rustString,rustOperator |
| 52 | syn keyword rustObsoleteExternMod mod contained nextgroup=rustIdentifier skipwhite skipempty |
| 53 | |
| 54 | syn match rustIdentifier contains=rustIdentifierPrime "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained |
| 55 | syn match rustFuncName "\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" display contained |
| 56 | |
| 57 | syn 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. |
| 61 | syn region rustBoxPlacementBalance start="(" end=")" containedin=rustBoxPlacement transparent |
| 62 | syn region rustBoxPlacementBalance start="\[" end="\]" containedin=rustBoxPlacement transparent |
| 63 | " {} are handled by rustFoldBraces |
| 64 | |
| 65 | syn region rustMacroRepeat matchgroup=rustMacroRepeatDelimiters start="$(" end=")" contains=TOP nextgroup=rustMacroRepeatCount |
| 66 | syn match rustMacroRepeatCount ".\?[*+]" contained |
| 67 | syn match rustMacroVariable "$\w\+" |
| 68 | |
| 69 | " Reserved (but not yet used) keywords {{{2 |
| 70 | syn keyword rustReservedKeyword alignof become do offsetof priv pure sizeof typeof unsized yield abstract virtual final override macro |
| 71 | |
| 72 | " Built-in types {{{2 |
| 73 | syn keyword rustType isize usize char bool u8 u16 u32 u64 u128 f32 |
| 74 | syn 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 |
| 81 | syn keyword rustTrait Copy Send Sized Sync |
| 82 | syn 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 |
| 91 | syn keyword rustTrait Box |
| 92 | syn keyword rustTrait ToOwned |
| 93 | syn keyword rustTrait Clone |
| 94 | syn keyword rustTrait PartialEq PartialOrd Eq Ord |
| 95 | syn keyword rustTrait AsRef AsMut Into From |
| 96 | syn keyword rustTrait Default |
| 97 | syn keyword rustTrait Iterator Extend IntoIterator |
| 98 | syn keyword rustTrait DoubleEndedIterator ExactSizeIterator |
| 99 | syn keyword rustEnum Option |
| 100 | syn keyword rustEnumVariant Some None |
| 101 | syn keyword rustEnum Result |
| 102 | syn keyword rustEnumVariant Ok Err |
| 103 | syn keyword rustTrait SliceConcatExt |
| 104 | syn keyword rustTrait String ToString |
| 105 | syn keyword rustTrait Vec |
| 106 | |
| 107 | " Other syntax {{{2 |
| 108 | syn keyword rustSelf self |
| 109 | syn 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"). |
| 113 | syn match rustModPath "\w\(\w\)*::[^<]"he=e-3,me=e-3 |
| 114 | syn match rustModPathSep "::" |
| 115 | |
| 116 | syn match rustFuncCall "\w\(\w\)*("he=e-1,me=e-1 |
| 117 | syn 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 | |
| 124 | syn match rustOperator display "\%(+\|-\|/\|*\|=\|\^\|&\||\|!\|>\|<\|%\)=\?" |
| 125 | " This one isn't *quite* right, as we could have binary-& with a reference |
| 126 | syn match rustSigil display /&\s\+[&~@*][^)= \t\r\n]/he=e-1,me=e-1 |
| 127 | syn 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 |
| 130 | syn 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. |
| 133 | syn match rustArrowCharacter display "->" |
| 134 | syn match rustQuestionMark display "?\([a-zA-Z]\+\)\@!" |
| 135 | |
| 136 | syn match rustMacro '\w\(\w\)*!' contains=rustAssert,rustPanic |
| 137 | syn match rustMacro '#\w\(\w\)*' contains=rustAssert,rustPanic |
| 138 | |
| 139 | syn match rustEscapeError display contained /\\./ |
| 140 | syn match rustEscape display contained /\\\([nrt0\\'"]\|x\x\{2}\)/ |
| 141 | syn match rustEscapeUnicode display contained /\\u{\x\{1,6}}/ |
| 142 | syn match rustStringContinuation display contained /\\\n\s*/ |
| 143 | syn region rustString start=+b"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeError,rustStringContinuation |
| 144 | syn region rustString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustStringContinuation,@Spell |
| 145 | syn region rustString start='b\?r\z(#*\)"' end='"\z1' contains=@Spell |
| 146 | |
| 147 | syn region rustAttribute start="#!\?\[" end="\]" contains=rustString,rustDerive,rustCommentLine,rustCommentBlock,rustCommentLineDocError,rustCommentBlockDocError |
| 148 | syn 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). |
| 151 | syn 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 |
| 154 | syn match rustDecNumber display "\<[0-9][0-9_]*\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\=" |
| 155 | syn match rustHexNumber display "\<0x[a-fA-F0-9_]\+\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\=" |
| 156 | syn match rustOctNumber display "\<0o[0-7_]\+\%([iu]\%(size\|8\|16\|32\|64\|128\)\)\=" |
| 157 | syn 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.) |
| 163 | syn 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. |
| 166 | syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)\=" |
| 167 | syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\(f32\|f64\)\=" |
| 168 | syn match rustFloat display "\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\=\%([eE][+-]\=[0-9_]\+\)\=\(f32\|f64\)" |
| 169 | |
| 170 | " For the benefit of delimitMate |
| 171 | syn region rustLifetimeCandidate display start=/&'\%(\([^'\\]\|\\\(['nrt0\\\"]\|x\x\{2}\|u{\x\{1,6}}\)\)'\)\@!/ end=/[[:cntrl:][:space:][:punct:]]\@=\|$/ contains=rustSigil,rustLifetime |
| 172 | syn region rustGenericRegion display start=/<\%('\|[^[cntrl:][:space:][:punct:]]\)\@=')\S\@=/ end=/>/ contains=rustGenericLifetimeCandidate |
| 173 | syn 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 |
| 176 | syn match rustLifetime display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*" |
| 177 | syn match rustLabel display "\'\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*:" |
| 178 | syn 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). |
| 180 | syn match rustCharacterInvalidUnicode display contained /b'\zs[^[:cntrl:][:graph:][:alnum:][:space:]]\ze'/ |
| 181 | syn match rustCharacter /b'\([^\\]\|\\\(.\|x\x\{2}\)\)'/ contains=rustEscape,rustEscapeError,rustCharacterInvalid,rustCharacterInvalidUnicode |
| 182 | syn match rustCharacter /'\([^\\]\|\\\(.\|x\x\{2}\|u{\x\{1,6}}\)\)'/ contains=rustEscape,rustEscapeUnicode,rustEscapeError,rustCharacterInvalid |
| 183 | |
| 184 | syn match rustShebang /\%^#![^[].*/ |
| 185 | syn region rustCommentLine start="//" end="$" contains=rustTodo,@Spell |
| 186 | syn region rustCommentLineDoc start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell |
| 187 | syn region rustCommentLineDocError start="//\%(//\@!\|!\)" end="$" contains=rustTodo,@Spell contained |
| 188 | syn region rustCommentBlock matchgroup=rustCommentBlock start="/\*\%(!\|\*[*/]\@!\)\@!" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell |
| 189 | syn region rustCommentBlockDoc matchgroup=rustCommentBlockDoc start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell |
| 190 | syn region rustCommentBlockDocError matchgroup=rustCommentBlockDocError start="/\*\%(!\|\*[*/]\@!\)" end="\*/" contains=rustTodo,rustCommentBlockDocNestError,@Spell contained |
| 191 | syn region rustCommentBlockNest matchgroup=rustCommentBlock start="/\*" end="\*/" contains=rustTodo,rustCommentBlockNest,@Spell contained transparent |
| 192 | syn region rustCommentBlockDocNest matchgroup=rustCommentBlockDoc start="/\*" end="\*/" contains=rustTodo,rustCommentBlockDocNest,@Spell contained transparent |
| 193 | syn 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 | |
| 206 | syn 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 |
| 211 | syn region rustFoldBraces start="{" end="}" transparent fold |
| 212 | |
| 213 | " Default highlighting {{{1 |
| 214 | hi def link rustDecNumber rustNumber |
| 215 | hi def link rustHexNumber rustNumber |
| 216 | hi def link rustOctNumber rustNumber |
| 217 | hi def link rustBinNumber rustNumber |
| 218 | hi def link rustIdentifierPrime rustIdentifier |
| 219 | hi def link rustTrait rustType |
| 220 | hi def link rustDeriveTrait rustTrait |
| 221 | |
| 222 | hi def link rustMacroRepeatCount rustMacroRepeatDelimiters |
| 223 | hi def link rustMacroRepeatDelimiters Macro |
| 224 | hi def link rustMacroVariable Define |
| 225 | hi def link rustSigil StorageClass |
| 226 | hi def link rustEscape Special |
| 227 | hi def link rustEscapeUnicode rustEscape |
| 228 | hi def link rustEscapeError Error |
| 229 | hi def link rustStringContinuation Special |
| 230 | hi def link rustString String |
| 231 | hi def link rustCharacterInvalid Error |
| 232 | hi def link rustCharacterInvalidUnicode rustCharacterInvalid |
| 233 | hi def link rustCharacter Character |
| 234 | hi def link rustNumber Number |
| 235 | hi def link rustBoolean Boolean |
| 236 | hi def link rustEnum rustType |
| 237 | hi def link rustEnumVariant rustConstant |
| 238 | hi def link rustConstant Constant |
| 239 | hi def link rustSelf Constant |
| 240 | hi def link rustFloat Float |
| 241 | hi def link rustArrowCharacter rustOperator |
| 242 | hi def link rustOperator Operator |
| 243 | hi def link rustKeyword Keyword |
| 244 | hi def link rustTypedef Keyword " More precise is Typedef, but it doesn't feel right for Rust |
| 245 | hi def link rustStructure Keyword " More precise is Structure |
| 246 | hi def link rustUnion rustStructure |
| 247 | hi def link rustPubScopeDelim Delimiter |
| 248 | hi def link rustPubScopeCrate rustKeyword |
| 249 | hi def link rustSuper rustKeyword |
| 250 | hi def link rustReservedKeyword Error |
| 251 | hi def link rustRepeat Conditional |
| 252 | hi def link rustConditional Conditional |
| 253 | hi def link rustIdentifier Identifier |
| 254 | hi def link rustCapsIdent rustIdentifier |
| 255 | hi def link rustModPath Include |
| 256 | hi def link rustModPathSep Delimiter |
| 257 | hi def link rustFunction Function |
| 258 | hi def link rustFuncName Function |
| 259 | hi def link rustFuncCall Function |
| 260 | hi def link rustShebang Comment |
| 261 | hi def link rustCommentLine Comment |
| 262 | hi def link rustCommentLineDoc SpecialComment |
| 263 | hi def link rustCommentLineDocError Error |
| 264 | hi def link rustCommentBlock rustCommentLine |
| 265 | hi def link rustCommentBlockDoc rustCommentLineDoc |
| 266 | hi def link rustCommentBlockDocError Error |
| 267 | hi def link rustAssert PreCondit |
| 268 | hi def link rustPanic PreCondit |
| 269 | hi def link rustMacro Macro |
| 270 | hi def link rustType Type |
| 271 | hi def link rustTodo Todo |
| 272 | hi def link rustAttribute PreProc |
| 273 | hi def link rustDerive PreProc |
| 274 | hi def link rustDefault StorageClass |
| 275 | hi def link rustStorage StorageClass |
| 276 | hi def link rustObsoleteStorage Error |
| 277 | hi def link rustLifetime Special |
| 278 | hi def link rustLabel Label |
| 279 | hi def link rustInvalidBareKeyword Error |
| 280 | hi def link rustExternCrate rustKeyword |
| 281 | hi def link rustObsoleteExternMod Error |
| 282 | hi def link rustBoxPlacementParens Delimiter |
| 283 | hi 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 | |
| 292 | syn sync minlines=200 |
| 293 | syn sync maxlines=500 |
| 294 | |
| 295 | let b:current_syntax = "rust" |