2023-02-26 02:47:54 +08:00
; -------
2025-02-03 08:17:10 +08:00
; Basic identifiers
2023-02-26 02:47:54 +08:00
; -------
2025-02-03 08:17:10 +08:00
; We do not style ? as an operator on purpose as it allows styling ? differently, as many highlighters do. @operator.special might have been a better scope, but @special is already documented so the change would break themes (including the intent of the default theme)
"?" @special
( type_identifier ) @type
( identifier ) @variable
( field_identifier ) @variable . other . member
2023-02-26 02:47:54 +08:00
; -------
2025-02-03 08:17:10 +08:00
; Operators
2023-02-26 02:47:54 +08:00
; -------
2025-02-03 08:17:10 +08:00
[
"*"
"'"
"->"
"=>"
"<="
"="
"=="
"!"
"!="
"%"
"%="
"&"
"&="
"&&"
"|"
"|="
"||"
"^"
"^="
"*"
"*="
"-"
"-="
"+"
"+="
"/"
"/="
">"
"<"
">="
">>"
"<<"
">>="
"<<="
"@"
".."
"..="
"'"
] @operator
; -------
; Paths
; -------
( use_declaration
argument: ( identifier ) @namespace )
( use_wildcard
( identifier ) @namespace )
( dep_item
name: ( identifier ) @namespace )
( scoped_use_list
path: ( identifier ) ? @namespace )
( use_list
( identifier ) @namespace )
( use_as_clause
path: ( identifier ) ? @namespace
alias: ( identifier ) @namespace )
; ---
; Remaining Paths
; ---
( scoped_identifier
path: ( identifier ) ? @namespace
name: ( identifier ) @namespace )
( scoped_type_identifier
path: ( identifier ) @namespace )
2023-02-26 02:47:54 +08:00
; ---
; Primitives
; ---
( escape_sequence ) @constant . character . escape
( primitive_type ) @type . builtin
( boolean_literal ) @constant . builtin . boolean
( integer_literal ) @constant . numeric . integer
( float_literal ) @constant . numeric . float
( char_literal ) @constant . character
[
( string_literal )
( raw_string_literal )
] @string
[
( line_comment )
( block_comment )
] @comment
; ---
; Extraneous
; ---
( self ) @variable . builtin
( enum_variant ( identifier ) @type . enum . variant )
( field_initializer
( field_identifier ) @variable . other . member )
( shorthand_field_initializer
( identifier ) @variable . other . member )
( shorthand_field_identifier ) @variable . other . member
( loop_label
"'" @label
( identifier ) @label )
; ---
; Punctuation
; ---
[
"::"
"."
";"
","
] @punctuation . delimiter
[
"("
")"
"["
"]"
"{"
"}"
"#"
] @punctuation . bracket
( type_arguments
[
"<"
">"
] @punctuation . bracket )
( type_parameters
[
"<"
">"
] @punctuation . bracket )
( closure_parameters
"|" @punctuation . bracket )
; ---
; Variables
; ---
( let_declaration
pattern: [
( ( identifier ) @variable )
( ( tuple_pattern
( identifier ) @variable ) )
] )
; It needs to be anonymous to not conflict with `call_expression` further below.
( _
value: ( field_expression
value: ( identifier ) ? @variable
field: ( field_identifier ) @variable . other . member ) )
( parameter
pattern: ( identifier ) @variable . parameter )
( closure_parameters
( identifier ) @variable . parameter )
; -------
; Keywords
; -------
( for_expression
"for" @keyword . control . repeat )
( ( identifier ) @keyword . control
( # match? @keyword . control "^yield$" ) )
"in" @keyword . control
[
"match"
"if"
"else"
] @keyword . control . conditional
[
"while"
] @keyword . control . repeat
[
"break"
"continue"
"return"
] @keyword . control . return
[
"contract"
"script"
"predicate"
] @keyword . other
"use" @keyword . control . import
( dep_item "dep" @keyword . control . import !body )
( use_as_clause "as" @keyword . control . import )
( type_cast_expression "as" @keyword . operator )
[
"as"
"pub"
"dep"
"abi"
"impl"
"where"
"trait"
"for"
] @keyword
[
"struct"
"enum"
"storage"
"configurable"
] @keyword . storage . type
"let" @keyword . storage
"fn" @keyword . function
"abi" @keyword . function
( mutable_specifier ) @keyword . storage . modifier . mut
( reference_type "&" @keyword . storage . modifier . ref )
( self_parameter "&" @keyword . storage . modifier . ref )
[
"const"
"ref"
"deref"
"move"
] @keyword . storage . modifier
; TODO: variable.mut to highlight mutable identifiers via locals.scm
; -------
; Guess Other Types
; -------
2025-02-03 08:17:10 +08:00
; Other PascalCase identifiers are assumed to be structs.
( ( identifier ) @type
( # match? @type "^[A-Z]" ) )
2023-02-26 02:47:54 +08:00
( ( identifier ) @constant
( # match? @constant "^[A-Z][A-Z\\d_]*$" ) )
; ---
; PascalCase identifiers in call_expressions (e.g. `Ok()`)
; are assumed to be enum constructors.
; ---
( call_expression
function: [
2025-02-03 08:17:10 +08:00
( ( identifier ) @constructor
( # match? @constructor "^[A-Z]" ) )
2023-02-26 02:47:54 +08:00
( scoped_identifier
2025-02-03 08:17:10 +08:00
name: ( ( identifier ) @constructor
( # match? @constructor "^[A-Z]" ) ) )
2023-02-26 02:47:54 +08:00
] )
; ---
2025-02-03 08:17:10 +08:00
; PascalCase identifiers under a path which is also PascalCase
; are assumed to be constructors if they have methods or fields.
2023-02-26 02:47:54 +08:00
; ---
2025-02-03 08:17:10 +08:00
( field_expression
value: ( scoped_identifier
path: [
( identifier ) @type
( scoped_identifier
name: ( identifier ) @type )
]
name: ( identifier ) @constructor
( # match? @type "^[A-Z]" )
( # match? @constructor "^[A-Z]" ) ) )
2023-02-26 02:47:54 +08:00
; -------
; Functions
; -------
( call_expression
function: [
( ( identifier ) @function )
( scoped_identifier
name: ( identifier ) @function )
( field_expression
field: ( field_identifier ) @function )
] )
( generic_function
function: [
( ( identifier ) @function )
( scoped_identifier
name: ( identifier ) @function )
( field_expression
field: ( field_identifier ) @function . method )
] )
( function_item
name: ( identifier ) @function )
( function_signature_item
name: ( identifier ) @function )