diff --git a/Default.sublime-keymap b/Default.sublime-keymap index ee290b13..8fb58c30 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -37,14 +37,14 @@ { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.double - punctuation.definition.string.end", "match_all": true } ] }, - // r# will expand to r#""# + // r#" will expand to r#""# // Additional # characters will be duplicated on both sides. - { "keys": ["#"], "command": "insert_snippet", "args": {"contents": "#$1\"$0\"${1/[^#]/$1/}#"}, "context": + { "keys": ["\""], "command": "insert_snippet", "args": {"contents": "\"$0\"${TM_CURRENT_WORD/[^#]/$1/}"}, "context": [ { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|>|$)", "match_all": true }, - { "key": "preceding_text", "operator": "regex_contains", "operand": "r$", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "r#+$", "match_all": true }, { "key": "selector", "operator": "equal", "operand": "source.rust" }, { "key": "eol_selector", "operator": "not_equal", "operand": "string.quoted.double - punctuation.definition.string.end", "match_all": true } ] diff --git a/RustEnhanced.sublime-syntax b/RustEnhanced.sublime-syntax index bc82fcc0..dcdb19e3 100644 --- a/RustEnhanced.sublime-syntax +++ b/RustEnhanced.sublime-syntax @@ -6,9 +6,10 @@ file_extensions: - rs scope: source.rust variables: - identifier: '(?:[[:alpha:]][_[:alnum:]]*|_[_[:alnum:]]+)' + non_raw_ident: '[[:alpha:]][_[:alnum:]]*|_[_[:alnum:]]+' + identifier: '(?:(?:r\#)?{{non_raw_ident}})' camel_ident: '\b_*[A-Z][a-zA-Z0-9_]*[a-z][a-zA-Z0-9_]*\b' - lifetime: '''(?:_|{{identifier}})(?!\'')\b' + lifetime: '''(?:_|{{non_raw_ident}})(?!\'')\b' escaped_byte: '\\([nrt0\"''\\]|x\h{2})' escaped_char: '\\([nrt0\"''\\]|x[0-7]\h|u\{(?:\h_*){1,6}\})' int_suffixes: '[iu](?:8|16|32|64|128|size)' @@ -32,7 +33,7 @@ contexts: - match: ';' scope: punctuation.terminator.rust - - match: '(''{{identifier}})\s*(:)' + - match: '(''(?:{{non_raw_ident}}))\s*(:)' captures: 1: entity.name.label.rust 2: punctuation.separator.rust @@ -114,14 +115,14 @@ contexts: 2: storage.modifier.rust 3: entity.name.constant.rust - - match: '\b(break|continue)(?:\s+(''{{identifier}}))?' + - match: '\b(break|continue)(?:\s+(''{{non_raw_ident}}))?' captures: 1: keyword.control.rust 2: entity.name.label.rust - include: type - - match: '\b(macro_rules!)\s+([[:alpha:]_][[:alnum:]_]*)\b' + - match: '\b(macro_rules!)\s+({{identifier}})\b' captures: 1: support.function.rust 2: entity.name.macro.rust @@ -167,7 +168,7 @@ contexts: # is more performant as the below # - match: '\b((?:debug_)?assert_(?:eq|ne)!)\s*(\()' - - match: '\b[[:lower:]_][[:lower:][:digit:]_]*!(?=\s*(\(|\{|\[))' + - match: '\b{{identifier}}!(?=\s*(\(|\{|\[))' scope: support.macro.rust - include: support-type @@ -193,9 +194,12 @@ contexts: - include: return-type - include: symbols - include: keywords + - match: '\b[[:lower:]_][[:lower:][:digit:]_]*(?=\()' scope: support.function.rust + - match: '{{identifier}}' + visibility: - match: '\b(pub)\s*(\()' captures: @@ -472,6 +476,7 @@ contexts: scope: keyword.operator.rust - match: '!' scope: keyword.operator.rust + - match: '{{identifier}}' raw-pointer: - match: '\*\s*(?:const|mut)\b' @@ -1229,11 +1234,11 @@ contexts: scope: storage.modifier.lifetime.rust basic-identifiers: - - match: '\b([[:upper:]_][[:upper:][:digit:]_]+)\b' + - match: '\b(?:(?:r#)?[[:upper:]_][[:upper:][:digit:]_]+)\b' scope: constant.other.rust - match: '\b(c_[[:lower:][:digit:]_]+|[[:lower:]_][[:lower:][:digit:]_]*_t)\b' scope: storage.type.rust - - match: '\b_*[A-Z][a-zA-Z0-9_]*[a-z][a-zA-Z0-9_]*\b' + - match: '\b(?:r#)?_*[A-Z][a-zA-Z0-9_]*[a-z][a-zA-Z0-9_]*\b' scope: storage.type.source.rust - match: '(?={{identifier}}::)' push: @@ -1241,9 +1246,6 @@ contexts: - include: no-path-identifiers - match: '::' set: no-type-names - - match: '{{identifier}}::' - scope: meta.path.rust - push: no-type-names - match: '::(?={{identifier}})' scope: meta.path.rust push: no-type-names diff --git a/tests/syntax-rust/syntax_test_raw.rs b/tests/syntax-rust/syntax_test_raw.rs new file mode 100644 index 00000000..894f9232 --- /dev/null +++ b/tests/syntax-rust/syntax_test_raw.rs @@ -0,0 +1,106 @@ +// SYNTAX TEST "Packages/Rust Enhanced/RustEnhanced.sublime-syntax" +// Raw identifiers in various positions. + +use r#foo::bar as r#alias_foo; +// ^^^^^^^ meta.path +// ^^^^^^^^^^^ source -keyword + +fn main() { + #[r#attr] +// ^^^^^^^^^ meta.annotation -keyword + r#foo::r#bar(); +// ^^^^^^^ meta.path -keyword +// ^^^^^ -keyword + + let r#local = r#Struct { r#struct: () }; +// ^^^^^^^^ -keyword +// ^^^^^^^^ storage.type.source -keyword +// ^^^^^^^^ -keyword + let r#async = r#foo(r#local); +// ^^^^^^^^ -keyword +// ^^^^^ -keyword +// ^^^^^^^ -keyword + r#macro!(); +// ^^^^^^^^ support.macro -keyword -invalid + somecall(r#foo); +// ^^^^^ meta.function meta.block meta.group + + if let r#sub_pat @ Foo(_) = r#Foo(3) {} +// ^^^^^^^^^^ -keyword +// ^^^^^ storage.type.source + + match r#async { +// ^^^^^^^^ -keyword + r#Foo | r#Bar => r#foo(), +// ^^^^^ storage.type.source -keyword +// ^^^^^ storage.type.source -keyword +// ^^^^^ -keyword + } +} + +fn r#bar<'a, r#T>(r#x: &'a r#T) {} +// ^^^^^ meta.function entity.name.function -keyword +// ^^^ meta.generic -keyword +// ^^^ meta.function meta.function.parameters variable.parameter -keyword +// ^^^ meta.function meta.function.parameters -keyword + +struct Generic(T); +// ^^^ meta.struct meta.generic meta.generic -keyword + +mod r#foo { +// ^^^^^ meta.module entity.name.module -keyword + pub fn r#bar() {} +// ^^^^^ meta.module meta.block meta.function entity.name.function -keyword +} + +enum r#Foo { +// ^^^^^ meta.enum meta.enum entity.name.enum + r#Bar {}, +// ^^^^^^ meta.enum -keyword +} + +struct r#Struct { +// ^^^^^^^^ meta.struct entity.name.struct -keyword + r#field: r#FieldType, +// ^^^^^^^ meta.struct meta.block variable.other.member -keyword +// ^^^^^^^^^^^^^ meta.struct meta.block -keyword +} + +trait r#Trait { +// ^^^^^^^ meta.trait entity.name.trait -keyword + type r#Type; +// ^^^^^^ meta.trait meta.block entity.name.type -keyword +} + +impl r#Trait for r#Impl { +// ^^^^^^^^ meta.impl -keyword +// ^^^^^^ meta.impl entity.name.impl -keyword + type r#Type = r#u32; +// ^^^^^^ meta.impl meta.block entity.name.type +// ^^^^^ meta.impl meta.block -keyword -storage + fn r#xxx(r#fjio: r#u32) {} +// ^^^^^ meta.impl meta.block meta.function entity.name.function -keyword +// ^^^^^^ meta.impl meta.block meta.function meta.function.parameters variable.parameter -keyword +// ^^^^^ meta.impl meta.block meta.function meta.function.parameters -keyword -storage +} + +extern "C" { + type r#ccc; +// ^^^^^ meta.block entity.name.type -keyword + static r#static_val: u32; +// ^^^^^^^^^^^^ meta.block -keyword +} + +macro_rules! r#macro { +// ^^^^^^^ meta.macro entity.name.macro -keyword -invalid + () => {}; +} + +macro_rules! foo { + ($x:expr) => { + let r#catch = $x + 1; +// ^^^^^^^^ meta.macro meta.macro.transcribers -keyword + r#println!("{}", r#catch); +// ^^^^^^^ meta.macro meta.macro.transcribers meta.group -keyword + }; +}