From e00f615e080935af89f926bea9bb758fcceafd92 Mon Sep 17 00:00:00 2001 From: Enigma Date: Wed, 7 Sep 2016 20:14:10 -0400 Subject: [PATCH] Add format macro syntax highlighting (closes #60) --- grammars/rust.cson | 71 +++++++++++++++++++++++++++++++++++++++++++--- test.rs | 44 ++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 4 deletions(-) diff --git a/grammars/rust.cson b/grammars/rust.cson index 926dac0..2c4ee1d 100644 --- a/grammars/rust.cson +++ b/grammars/rust.cson @@ -56,6 +56,46 @@ 'begin': 'b?r(#*)"' 'end': '"\\1' } + 'format_string_literal': { + 'comment': 'Format string literal' + 'name': 'string.quoted.double.format.rust' + 'begin': '"' + 'end': '"' + 'patterns': [ + { 'include': '#escaped_character' } + { + 'name': 'constant.character.escape.rust' + 'match': '{{|}}' + } + { + 'comment': 'Format string thing' + 'name': 'punctuation.section.embedded.format.rust' + 'begin': "{" + 'end': "}" + 'patterns': [ + { + # I hope you like regular expressions + 'match': '(?:([0-9]+)|(\\p{Alpha}\\w*|_\\w+))?(?:(\\:)(.?[<>\\^])?([\\+\\-])?(#)?0?(?:((?:([0-9]+)|\\p{Alpha}\\w*|_\\w+)\\$)|([0-9]+))?(?:\\.(?:(?:((?:([0-9]+)|\\p{Alpha}\\w*|_\\w+)\\$)|([0-9]+))|\\*))?(\\?|\\p{Alpha}\\w*|_\\w+)?)?' + 'captures': { + '1': { 'name': 'constant.numeric.integer.format.argument.rust' } + '2': { 'name': 'constant.variable.format.argument.rust' } + '3': { 'name': 'meta.separator.format.rust' } + '4': { 'name': 'punctuation.parameters.format.fill.rust' } + '5': { 'name': 'punctuation.separator.format.sign.rust' } + '6': { 'name': 'punctuation.separator.format.alt.rust' } + '7': { 'name': 'constant.variable.format.width.argument.rust' } + '8': { 'name': 'constant.numeric.integer.format.width.argument.rust' } + '9': { 'name': 'constant.numeric.integer.format.width.rust' } + '10': { 'name': 'constant.variable.format.precision.argument.rust' } + '11': { 'name': 'constant.numeric.integer.format.precision.argument.rust' } + '12': { 'name': 'constant.numeric.integer.format.precision.rust' } + '13': { 'name': 'support.type.format.type.rust' } + } + } + ] + } + ] + } 'sigils': { 'comment': 'Sigil' 'name': 'keyword.operator.sigil.rust' @@ -285,22 +325,45 @@ { 'comment': 'Built-in macro' 'name': 'support.function.builtin.rust' - 'match': '\\b(macro_rules|format_args|env|option_env|concat_idents|concat|log_syntax|line|column|file|stringify|include|include_str|include_bytes|module_path|asm|cfg|trace_macros)!' + 'match': '\\b(macro_rules|env|option_env|concat_idents|concat|log_syntax|line|column|file|stringify|include|include_str|include_bytes|module_path|asm|cfg|trace_macros)!' } { 'comment': 'Core macro' 'name': 'support.function.core.rust' - 'match': '\\b(panic|assert|assert_eq|debug_assert|debug_assert_eq|try|write|writeln|unreachable|unimplemented)!' + 'match': '\\b(panic|assert|assert_eq|debug_assert|debug_assert_eq|try|unreachable|unimplemented)!' } { 'comment': 'Standard library macro' 'name': 'support.function.std.rust' - 'match': '\\b(format|print|println|select|vec)!' + 'match': '\\b(select|vec)!' + } + { + 'comment': 'Format macro' + 'begin': '\\b(?:((?:write|writeln)!)|((?:format|format_args|print|println)!))' + 'end': '[,\\)\\]\\}]' + 'beginCaptures': { + '1': { 'name': 'support.function.core.rust' } + '2': { 'name': 'support.function.std.rust' } + } + 'patterns': [ + { 'include': '#format_string_literal' } + ] } { 'comment': 'Logging macro' 'name': 'support.function.log.rust' - 'match': '\\b(log|error|warn|info|debug|trace|log_enabled)!' + 'match': '\\b(log_enabled)!' + } + { + 'comment': 'Logging format macro' + 'begin': '\\b((?:log|error|warn|info|debug|trace)!)' + 'end': '[,\\)\\]\\}]' + 'beginCaptures': { + '1': { 'name': 'support.function.log.rust' } + } + 'patterns': [ + { 'include': '#format_string_literal' } + ] } # Function and macro calls { diff --git a/test.rs b/test.rs index a597979..46111ce 100644 --- a/test.rs +++ b/test.rs @@ -215,3 +215,47 @@ fn foo(bar: *const i32) { // Keywords and known types in wrapper structs (#56) pub struct Foobar(pub Option); + +// Format macros +format!("text"); +format!("text{}text", 1); +format!("text{0}text", 1); +format!("text{named}text", named=1); +format!("text{:?}text", to_debug); +format!("text{0:?}text", to_debug); +format!("text{named:?}text", named=to_debug); +format!("text{:<}text", 1); +format!("text{:.>}text", 1); +format!("text{:+}text", pos_or_neg); +format!("text{:+0}text", pos_or_neg); +format!("text{:+04}text", pos_or_neg); +format!("text{:6}", "text"); +format!("text{:1$}", "text", 6); +format!("text{1:6$}", 6, "text"); +format!("text{:w$}", "text", w=6); +format!("text{:8b}text", byte); +format!("text{:08b}text", byte); +format!("text{:#010b}text", byte); +format!("text{:2x}text", byte); +format!("text{:#4x}text", byte); +format!("text{:.2}text", 0.5); +format!("text{:0.2}text", 0.5); +format!("text{:06.2}text", 0.5); +format!("text{named:.prec$}text", prec=0.5, named=2.0); +format!("text{}text{2:.*}text", "text", 6, 0.5); +format!("text{named:-^+#06.2e}text", named=0.5); +format!("text{named:-^+#0width$.prec$e}text", named=0.5, width=6, prec=2); +format!("text{{escaped}}text\n{0}text", "only {text} first {{text}}"); + +not_format!("text{}text"); +format_args!("{}", "text"); +write!("{}", "text"); +writeln!("{}", "text"); +print!("{}", "text"); +println!("{}", "text"); +log!("{}", "text"); +error!("{}", "text"); +warn!("{}", "text"); +info!("{}", "text"); +debug!("{}", "text"); +trace!("{}", "text");