From bb6572dac91aee246b012bb7ce14c17a6f8c28bd Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Thu, 20 Mar 2025 22:08:22 +1000 Subject: [PATCH 01/28] Special case pattern strings --- Lua/Lua.sublime-syntax | 165 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 163 insertions(+), 2 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 72b0f6826b..4c28d440c0 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -465,7 +465,11 @@ contexts: push: expression-begin accessor: - - match: '[.:]' + - match: ':' + scope: punctuation.accessor.lua + push: property-method + + - match: '\.' scope: punctuation.accessor.lua push: property @@ -499,6 +503,18 @@ contexts: - include: reserved-word-pop - include: else-pop + property-method: + - match: '(?:find|gmatch|gsub|match){{identifier_break}}' + scope: meta.property.lua meta.function-call.lua variable.function.lua + set: + - match: (?={{function_args_begin}}) + pop: 1 + push: + - function-arguments-meta + - function-arguments-pattern-at1 + - include: else-pop + - include: property + function-arguments-meta: - meta_scope: meta.function-call.arguments.lua - include: immediately-pop @@ -757,6 +773,142 @@ contexts: - meta_scope: meta.function.lua - include: immediately-pop + function-arguments-pattern-at2: + - include: string + - include: table-constructor + + - match: \( + scope: punctuation.section.group.begin.lua + set: + - meta_scope: meta.group.lua + - match: \) + scope: punctuation.section.group.end.lua + pop: 1 + - include: reserved-word-expression-pop + - match: (?=\S) + push: + - expression-list-end-pattern-next + - expression-begin + + function-arguments-pattern-at1: + - include: pattern-string + - include: table-constructor + + - match: \( + scope: punctuation.section.group.begin.lua + set: + - meta_scope: meta.group.lua + - match: \) + scope: punctuation.section.group.end.lua + pop: 1 + - include: reserved-word-expression-pop + - match: (?=\S) + push: + - expression-list-end + - pattern-expression + + pattern-expression: + - include: pattern-string + - include: expression-begin + + expression-list-end-pattern-next: + - match: ',' + scope: punctuation.separator.comma.lua + set: + - expression-list-end + - pattern-expression + - include: expression-end + + pattern-nonnested: + - match: '\(' + scope: punctuation.section.group.begin.lua + - match: '\)' + scope: punctuation.section.group.end.lua + - match: '(\[)(\^)?\]?' + captures: + 1: punctuation.definition.set.begin.lua + 2: keyword.operator.logical.lua + - match: '\]' + scope: punctuation.definition.set.end.lua + - match: '\(\)' + scope: punctuation.section.brackets.lua + - match: '[+*?\-]' + scope: keyword.operator.quantifier.lua + - match: \. + scope: keyword.other.any.lua + + pattern-string: + - match: \[(=*)\[ + scope: punctuation.definition.string.begin.lua + set: + - pattern-multiline-string-body + - pattern-test-first-caret + - match: \' + scope: punctuation.definition.string.begin.lua + set: + - pattern-single-quoted-string-body + - pattern-test-first-caret + - match: \" + scope: punctuation.definition.string.begin.lua + set: + - pattern-double-quoted-string-body + - pattern-test-first-caret + + pattern-test-first-caret: + - match: '\^' + scope: keyword.control.anchor.lua + pop: 1 + - include: immediately-pop + + pattern-single-quoted-string-body: + - meta_include_prototype: false + - meta_scope: meta.string.lua string.quoted.single.lua + - include: single-quoted-string-body + - match: \$(?=\') + scope: keyword.control.anchor.lua + - match: '%' + scope: constant.character.escape.lua + push: + - match: (?=[\\\']) + pop: 1 + - match: . + scope: constant.character.escape.lua + pop: 1 + - include: pattern-nonnested + + pattern-double-quoted-string-body: + - meta_include_prototype: false + - meta_scope: meta.string.lua string.quoted.double.lua + - include: double-quoted-string-body + - match: \$(?=\") + scope: keyword.control.anchor.lua + - match: '%' + scope: constant.character.escape.lua + push: + - match: (?=[\\\"]) + pop: 1 + - match: . + scope: constant.character.escape.lua + pop: 1 + - include: pattern-nonnested + + pattern-multiline-string-body: + - meta_include_prototype: false + - meta_scope: meta.string.lua string.quoted.multiline.lua + - match: (?:(\$)|(%)|)(\]\1\]) + captures: + 1: keyword.control.anchor.lua + 2: constant.character.escape.lua + 3: punctuation.definition.string.end.lua + pop: 1 + - match: '%' + scope: constant.character.escape.lua + push: + - match: . + scope: constant.character.escape.lua + pop: 1 + - include: pattern-nonnested + builtin-modules: - match: coroutine{{identifier_break}} scope: support.constant.builtin.lua @@ -800,9 +952,18 @@ contexts: - match: \. scope: punctuation.accessor.lua set: + - match: (?:find|gmatch|gsub|match){{identifier_break}} + scope: meta.property.lua support.function.builtin.lua + set: + - match: (?={{function_args_begin}}) + pop: 1 + push: + - function-arguments-meta + - function-arguments-pattern-at2 + - include: else-pop - match: |- (?x: - byte|char|dump|find|format|gmatch|gsub|len|lower|match|pack + byte|char|dump|format|len|lower|pack |packsize|rep|reverse|sub|unpack|upper ){{identifier_break}} scope: meta.property.lua support.function.builtin.lua From 8ace4cf770d17973615520ce4d040a56082cb4b3 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Thu, 20 Mar 2025 22:09:18 +1000 Subject: [PATCH 02/28] Special case format strings --- Lua/Lua.sublime-syntax | 69 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 4c28d440c0..c14dbadc38 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -807,6 +807,23 @@ contexts: - expression-list-end - pattern-expression + function-arguments-fmtstr-at1: + - include: fmtstr-string + - include: table-constructor + + - match: \( + scope: punctuation.section.group.begin.lua + set: + - meta_scope: meta.group.lua + - match: \) + scope: punctuation.section.group.end.lua + pop: 1 + - include: reserved-word-expression-pop + - match: (?=\S) + push: + - expression-list-end + - fmtstr-expression + pattern-expression: - include: pattern-string - include: expression-begin @@ -909,6 +926,47 @@ contexts: pop: 1 - include: pattern-nonnested + fmtstr-expression: + - include: fmtstr-string + - include: expression-begin + + fmtstr-string: + - match: \[(=*)\[ + scope: punctuation.definition.string.begin.lua + set: multiline-string-body + with_prototype: + - include: fmtstr-embed + + - match: \' + scope: punctuation.definition.string.begin.lua + set: single-quoted-string-body + with_prototype: + - include: fmtstr-embed + + - match: \" + scope: punctuation.definition.string.begin.lua + set: double-quoted-string-body + with_prototype: + - include: fmtstr-embed + + fmtstr-embed: + - match: '%' + scope: constant.other.placeholder.lua + push: fmtstr-pattern + + fmtstr-pattern: + # these characters never appear in a format pattern so it can be simpler + - match: (?=[\\\"\'\]]) + pop: 1 + - match: '[-+#0-9. ]' + scope: constant.other.placeholder.lua + - match: '[cdiuoxXaAfeEgGpqs%]' + scope: constant.other.placeholder.lua + pop: 1 + - match: '.' + scope: invalid.illegal.invalid-format.lua + pop: 1 + builtin-modules: - match: coroutine{{identifier_break}} scope: support.constant.builtin.lua @@ -961,9 +1019,18 @@ contexts: - function-arguments-meta - function-arguments-pattern-at2 - include: else-pop + - match: (?:format){{identifier_break}} + scope: meta.property.lua support.function.builtin.stringy.lua + set: + - match: (?={{function_args_begin}}) + pop: 1 + push: + - function-arguments-meta + - function-arguments-fmtstr-at1 + - include: else-pop - match: |- (?x: - byte|char|dump|format|len|lower|pack + byte|char|dump|len|lower|pack |packsize|rep|reverse|sub|unpack|upper ){{identifier_break}} scope: meta.property.lua support.function.builtin.lua From b310c1a8a8c1847b0de67a320e78687c48316ace Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Thu, 20 Mar 2025 22:09:50 +1000 Subject: [PATCH 03/28] Special case pack strings --- Lua/Lua.sublime-syntax | 66 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index c14dbadc38..30a05ec49e 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -824,6 +824,23 @@ contexts: - expression-list-end - fmtstr-expression + function-arguments-packstr-at1: + - include: packstr-string + - include: table-constructor + + - match: \( + scope: punctuation.section.group.begin.lua + set: + - meta_scope: meta.group.lua + - match: \) + scope: punctuation.section.group.end.lua + pop: 1 + - include: reserved-word-expression-pop + - match: (?=\S) + push: + - expression-list-end + - packstr-expression + pattern-expression: - include: pattern-string - include: expression-begin @@ -967,6 +984,42 @@ contexts: scope: invalid.illegal.invalid-format.lua pop: 1 + packstr-expression: + - include: packstr-string + - include: expression-begin + + packstr-string: + - match: \[(=*)\[ + scope: punctuation.definition.string.begin.lua + set: multiline-string-body + with_prototype: + - include: packstr-pattern + + - match: \' + scope: punctuation.definition.string.begin.lua + set: single-quoted-string-body + with_prototype: + - include: packstr-pattern + + - match: \" + scope: punctuation.definition.string.begin.lua + set: double-quoted-string-body + with_prototype: + - include: packstr-pattern + + packstr-pattern: + - match: '[=<>]|![0-9]*' + scope: storage.modifier.lua + + - match: '[bBhHlLjJTfdnz]|[Iis][0-9]*|c[0-9]+' + scope: storage.type.lua + + - match: '[xX]' + scope: punctuation.separator.padding.lua + + - match: (?:[^\\\"\'\]\s]) + scope: invalid.illegal.invalid-storage.lua + builtin-modules: - match: coroutine{{identifier_break}} scope: support.constant.builtin.lua @@ -1028,10 +1081,19 @@ contexts: - function-arguments-meta - function-arguments-fmtstr-at1 - include: else-pop + - match: (?:pack|unpack|packsize){{identifier_break}} + scope: meta.property.lua support.function.builtin.stringy.lua + set: + - match: (?={{function_args_begin}}) + pop: 1 + push: + - function-arguments-meta + - function-arguments-packstr-at1 + - include: else-pop - match: |- (?x: - byte|char|dump|len|lower|pack - |packsize|rep|reverse|sub|unpack|upper + byte|char|dump|len|lower + |rep|reverse|sub|upper ){{identifier_break}} scope: meta.property.lua support.function.builtin.lua pop: 1 From c6974f0d090127f3f436d343a14e3ab5f44713e7 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Thu, 20 Mar 2025 22:10:25 +1000 Subject: [PATCH 04/28] Add test --- Lua/tests/syntax_test_lua.lua | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Lua/tests/syntax_test_lua.lua b/Lua/tests/syntax_test_lua.lua index 10d7dcb17c..452d1f5b5f 100644 --- a/Lua/tests/syntax_test_lua.lua +++ b/Lua/tests/syntax_test_lua.lua @@ -789,3 +789,17 @@ -- ^^^^^^^^^^^^ meta.string string.quoted.double.lua -- ^ punctuation.separator.comma.lua -- ^ punctuation.section.group.end.lua + +-- basic tests for patterns + local a = ('test'):match('^()t?$-e*s+()$') +-- ^ keyword.control.anchor +-- ^ punctuation.section.group.begin +-- ^ punctuation.section.group.end +-- ^ keyword.operator.quantifier +-- ^ keyword.operator.quantifier +-- ^ keyword.operator.quantifier +-- ^ keyword.operator.quantifier +-- ^ keyword.control.anchor + + local b = string.format('%0.9f', 15.4) +-- ^^^^^ constant.other.placeholder.lua From e3caf59dd35d5e962308503db8b85f65dcfb0d7a Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Fri, 21 Mar 2025 09:27:20 +1000 Subject: [PATCH 05/28] Further work on patterns --- Lua/Lua.sublime-syntax | 65 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 30a05ec49e..d5476c344c 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -696,6 +696,38 @@ contexts: - match: \\. scope: invalid.illegal.invalid-escape.lua + # pop the context once one escaped character has been matched + string-escape-pop: + - match: \\[abfnrtv\\'"\[\]\n] + scope: constant.character.escape.lua + pop: 1 + + - match: \\x\h\h + scope: constant.character.escape.hexadecimal.lua + pop: 1 + + - match: \\\d{1,3} + scope: constant.character.escape.decimal.lua + pop: 1 + + # unicode can make multiple, but that is a bit hard to handle + - match: \\u\{\h+\} + scope: constant.character.escape.unicode.lua + pop: 1 + + # \z turns into nothing, so we don't pop + - match: \\z + push: + - meta_scope: constant.character.escape.whitespace.lua + - include: else-pop + + - match: \n + scope: invalid.illegal.unclosed-string.lua + pop: 2 + - match: \\. + scope: invalid.illegal.invalid-escape.lua + pop: 1 + parenthesized-expression: - match: \( scope: punctuation.section.group.begin.lua @@ -880,6 +912,7 @@ contexts: - match: \' scope: punctuation.definition.string.begin.lua set: + # - single-quoted-meta - pattern-single-quoted-string-body - pattern-test-first-caret - match: \" @@ -889,10 +922,12 @@ contexts: - pattern-test-first-caret pattern-test-first-caret: + - meta_include_prototype: false - match: '\^' scope: keyword.control.anchor.lua pop: 1 - - include: immediately-pop + - match: '[^\n]' + pop: 1 pattern-single-quoted-string-body: - meta_include_prototype: false @@ -903,8 +938,9 @@ contexts: - match: '%' scope: constant.character.escape.lua push: - - match: (?=[\\\']) + - match: (?=\') pop: 1 + - include: string-escape-pop - match: . scope: constant.character.escape.lua pop: 1 @@ -919,8 +955,9 @@ contexts: - match: '%' scope: constant.character.escape.lua push: - - match: (?=[\\\"]) + - match: (?=\") pop: 1 + - include: string-escape-pop - match: . scope: constant.character.escape.lua pop: 1 @@ -929,12 +966,19 @@ contexts: pattern-multiline-string-body: - meta_include_prototype: false - meta_scope: meta.string.lua string.quoted.multiline.lua - - match: (?:(\$)|(%)|)(\]\1\]) - captures: - 1: keyword.control.anchor.lua - 2: constant.character.escape.lua - 3: punctuation.definition.string.end.lua - pop: 1 + - include: multiline-string-body + # - match: (?:(\$)|(%)|)(\]\1\]) + # captures: + # 1: keyword.control.anchor.lua + # 2: constant.character.escape.lua + # 3: punctuation.definition.string.end.lua + # pop: 1 + # This is added here so that we can escape the string properly + - match: (%)(?=\]\1\]) + scope: constant.character.escape.lua + - match: (\$)(?=\]\1\]) + scope: keyword.control.anchor.lua + - match: '%' scope: constant.character.escape.lua push: @@ -967,11 +1011,13 @@ contexts: - include: fmtstr-embed fmtstr-embed: + - meta_include_prototype: false - match: '%' scope: constant.other.placeholder.lua push: fmtstr-pattern fmtstr-pattern: + - meta_include_prototype: false # these characters never appear in a format pattern so it can be simpler - match: (?=[\\\"\'\]]) pop: 1 @@ -1008,6 +1054,7 @@ contexts: - include: packstr-pattern packstr-pattern: + - meta_include_prototype: false - match: '[=<>]|![0-9]*' scope: storage.modifier.lua From a875bb8e4c466b5d6b075447859f400101452fc9 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Fri, 21 Mar 2025 09:28:06 +1000 Subject: [PATCH 06/28] More work on patterns --- Lua/Lua.sublime-syntax | 213 ++++++++++++++++++++++++++++++----------- 1 file changed, 159 insertions(+), 54 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index d5476c344c..b734a5becd 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -62,6 +62,8 @@ variables: )\b) doc_comment_custom_tag: (?:@\w+\b) + string_char_escape: \\(?:[abfnrtv\\'"\[\]\n]|x\h\h|\d{1,3}|u\{\h+\}) + contexts: main: - meta_include_prototype: false @@ -885,34 +887,160 @@ contexts: - pattern-expression - include: expression-end - pattern-nonnested: + pattern-shared: + - meta_include_prototype: false + # start anchor is handled separately as ^ doesn't match the start of the string + - match: \$$ + scope: keyword.control.anchor.lua + - match: '\(\)' + scope: punctuation.section.brackets.lua + - match: '[+*?\-]' + scope: keyword.operator.quantifier.lua + push: pattern-shared-norepetition + - match: \. + scope: keyword.other.any.lua + + pattern-shared-norepetition: + - meta_include_prototype: false + - match: '[+*?\-]' + pop: 1 + - match: '' + pop: 1 + + # the pattern implementation is split into quoted and unquoted as escapes are only processed + # in quoted strings. + pattern-quoted: + - meta_include_prototype: false + - include: string-content + - include: pattern-shared - match: '\(' scope: punctuation.section.group.begin.lua + push: + - pattern-shared-norepetition + - pattern-quoted-nested + - match: '(\[)(\^)?\]?' + captures: + 1: punctuation.definition.set.begin.lua + 2: keyword.operator.logical.lua + push: pattern-quoted-set-body + - include: pattern-quoted-charclass + + pattern-quoted-charclass: + - match: \% + scope: constant.character.escape.lua + push: + - include: string-escape-pop + - match: . + scope: constant.character.escape.lua + pop: 1 + + pattern-quoted-nested: + - meta_include_prototype: false + - meta_scope: meta.group.lua meta.mode.basic.lua - match: '\)' scope: punctuation.section.group.end.lua + pop: 1 + - include: pattern-quoted + + pattern-quoted-set-body: + - meta_scope: meta.set.regexp + - match: '\]' + scope: punctuation.definition.set.end.lua + pop: 1 + - include: pattern-quoted-set-ranges + - include: pattern-quoted-charclass + + pattern-quoted-set-ranges: + - meta_include_prototype: false + # These only work with direct characters. Lua doesn't support percent escapes in sets + - match: (?=({{string_char_escape}}|[^%\]\-])-({{string_char_escape}}|[^\]])) + push: + - pattern-quoted-set-range-end + - pattern-quoted-set-range-begin + + pattern-quoted-set-range-begin: + - meta_include_prototype: false + - match: '-' + scope: punctuation.separator.sequence.regexp + pop: 1 + - include: string-content + + pattern-quoted-set-range-end: + - meta_include_prototype: false + - meta_scope: constant.other.range.regexp + - include: string-escape-pop + - match: . + pop: 1 + + pattern-unquoted: + - meta_include_prototype: false + - include: pattern-shared + - match: '\(' + scope: punctuation.section.group.begin.lua + push: + - pattern-shared-norepetition + - pattern-unquoted-nested - match: '(\[)(\^)?\]?' captures: 1: punctuation.definition.set.begin.lua 2: keyword.operator.logical.lua + push: pattern-unquoted-set-body + - include: pattern-unquoted-charclass + + pattern-unquoted-charclass: + - match: \% + scope: constant.character.escape.lua + push: + - match: . + scope: constant.character.escape.lua + pop: 1 + + pattern-unquoted-nested: + - meta_include_prototype: false + - meta_scope: meta.group.lua meta.mode.basic.lua + - match: '\)' + scope: punctuation.section.group.end.lua + pop: 1 + - include: pattern-unquoted + + pattern-unquoted-set-body: + - meta_scope: meta.set.regexp - match: '\]' scope: punctuation.definition.set.end.lua - - match: '\(\)' - scope: punctuation.section.brackets.lua - - match: '[+*?\-]' - scope: keyword.operator.quantifier.lua - - match: \. - scope: keyword.other.any.lua + pop: 1 + - include: pattern-unquoted-set-ranges + - include: pattern-unquoted-charclass + pattern-unquoted-set-ranges: + - meta_include_prototype: false + # These only work with direct characters. Lua doesn't support percent escapes in sets + - match: (?=[^%\]\-]-[^\]]) + push: + - pattern-unquoted-set-range-end + - pattern-unquoted-set-range-begin + + pattern-unquoted-set-range-begin: + - meta_include_prototype: false + - match: '-' + scope: punctuation.separator.sequence.regexp + pop: 1 + + pattern-unquoted-set-range-end: + - meta_include_prototype: false + - meta_scope: constant.other.range.regexp + - match: . + pop: 1 + + # this gets included in expressions that want to have a pattern string pattern-string: - match: \[(=*)\[ scope: punctuation.definition.string.begin.lua set: - pattern-multiline-string-body - - pattern-test-first-caret + - pattern-test-first-caret-multiline - match: \' scope: punctuation.definition.string.begin.lua set: - # - single-quoted-meta - pattern-single-quoted-string-body - pattern-test-first-caret - match: \" @@ -926,66 +1054,43 @@ contexts: - match: '\^' scope: keyword.control.anchor.lua pop: 1 - - match: '[^\n]' + # it seems to require this match rather than immediately-pop + # in order to work with the multiline below + - match: (?=[^\^]) pop: 1 + pattern-test-first-caret-multiline: + - meta_include_prototype: false + - match: $\n? + set: pattern-test-first-caret + - include: pattern-test-first-caret + pattern-single-quoted-string-body: - meta_include_prototype: false - meta_scope: meta.string.lua string.quoted.single.lua - include: single-quoted-string-body - - match: \$(?=\') - scope: keyword.control.anchor.lua - - match: '%' - scope: constant.character.escape.lua - push: - - match: (?=\') - pop: 1 - - include: string-escape-pop - - match: . - scope: constant.character.escape.lua - pop: 1 - - include: pattern-nonnested + - match: '' + embed: pattern-quoted + escape: (?=\') pattern-double-quoted-string-body: - meta_include_prototype: false - meta_scope: meta.string.lua string.quoted.double.lua - include: double-quoted-string-body - - match: \$(?=\") - scope: keyword.control.anchor.lua - - match: '%' - scope: constant.character.escape.lua - push: - - match: (?=\") - pop: 1 - - include: string-escape-pop - - match: . - scope: constant.character.escape.lua - pop: 1 - - include: pattern-nonnested + - match: '' + embed: pattern-quoted + escape: (?=\") pattern-multiline-string-body: - meta_include_prototype: false - - meta_scope: meta.string.lua string.quoted.multiline.lua + - meta_scope: meta.string.lua string.quoted.double.lua - include: multiline-string-body - # - match: (?:(\$)|(%)|)(\]\1\]) - # captures: - # 1: keyword.control.anchor.lua - # 2: constant.character.escape.lua - # 3: punctuation.definition.string.end.lua - # pop: 1 - # This is added here so that we can escape the string properly - - match: (%)(?=\]\1\]) - scope: constant.character.escape.lua - - match: (\$)(?=\]\1\]) - scope: keyword.control.anchor.lua - - - match: '%' - scope: constant.character.escape.lua - push: - - match: . - scope: constant.character.escape.lua - pop: 1 - - include: pattern-nonnested + - match: '' + embed: pattern-unquoted + # we don't seem to be able to use the capture to get the right one + # this means that patterns that contain something that matches this + # will lose their context half way through. + escape: (?=\]=*\]) fmtstr-expression: - include: fmtstr-string From 933aa6657c5e693a35cf7a79cae4d3e25456082e Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Fri, 21 Mar 2025 10:18:30 +1000 Subject: [PATCH 07/28] More work on Lua patterns --- Lua/Lua.sublime-syntax | 57 ++++++++-- Lua/tests/syntax_test_lua.lua | 3 +- Lua/tests/syntax_test_lua_patterns.lua | 143 +++++++++++++++++++++++++ 3 files changed, 193 insertions(+), 10 deletions(-) create mode 100644 Lua/tests/syntax_test_lua_patterns.lua diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index b734a5becd..0c91c0433e 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -887,6 +887,24 @@ contexts: - pattern-expression - include: expression-end + pattern-shared-charclass: + - meta_include_prototype: false + - match: \%[AaCcDdGgLlPpSsUuWwXxZz] + scope: keyword.control.character-class.lua + - match: \%f + scope: keyword.control.anchor.lua + + - match: (\%)(\d) + captures: + 1: keyword.other.backref-and-recursion.lua + 2: variable.other.backref-and-recursion.lua + push: pattern-shared-norepetition + + # other alphabetic characters are not defined + # this skips `f` and `b` as they are special patterns + - match: \%[EeHhIiJjKkMmNnOoQqRrTtVvYy] + scope: invalid.illegal.invalid-escape.lua + pattern-shared: - meta_include_prototype: false # start anchor is handled separately as ^ doesn't match the start of the string @@ -900,6 +918,7 @@ contexts: - match: \. scope: keyword.other.any.lua + pattern-shared-norepetition: - meta_include_prototype: false - match: '[+*?\-]' @@ -918,6 +937,7 @@ contexts: push: - pattern-shared-norepetition - pattern-quoted-nested + - pattern-shared-norepetition - match: '(\[)(\^)?\]?' captures: 1: punctuation.definition.set.begin.lua @@ -926,10 +946,16 @@ contexts: - include: pattern-quoted-charclass pattern-quoted-charclass: + - meta_include_prototype: false + - include: pattern-shared-charclass - match: \% scope: constant.character.escape.lua push: + - meta_include_prototype: false - include: string-escape-pop + - match: \d + scope: keyword.other.backref-and-recursion.lua + pop: 1 - match: . scope: constant.character.escape.lua pop: 1 @@ -943,12 +969,14 @@ contexts: - include: pattern-quoted pattern-quoted-set-body: - - meta_scope: meta.set.regexp + - meta_include_prototype: false + - meta_scope: meta.set.lua - match: '\]' scope: punctuation.definition.set.end.lua pop: 1 - include: pattern-quoted-set-ranges - include: pattern-quoted-charclass + - include: string-content pattern-quoted-set-ranges: - meta_include_prototype: false @@ -961,13 +989,13 @@ contexts: pattern-quoted-set-range-begin: - meta_include_prototype: false - match: '-' - scope: punctuation.separator.sequence.regexp + scope: punctuation.separator.sequence.lua pop: 1 - include: string-content pattern-quoted-set-range-end: - meta_include_prototype: false - - meta_scope: constant.other.range.regexp + - meta_scope: constant.other.range.lua - include: string-escape-pop - match: . pop: 1 @@ -980,6 +1008,7 @@ contexts: push: - pattern-shared-norepetition - pattern-unquoted-nested + - pattern-shared-norepetition - match: '(\[)(\^)?\]?' captures: 1: punctuation.definition.set.begin.lua @@ -988,9 +1017,15 @@ contexts: - include: pattern-unquoted-charclass pattern-unquoted-charclass: + - meta_include_prototype: false + - include: pattern-shared-charclass - match: \% scope: constant.character.escape.lua push: + - meta_include_prototype: false + - match: \d + scope: keyword.other.backref-and-recursion.lua + pop: 1 - match: . scope: constant.character.escape.lua pop: 1 @@ -1004,7 +1039,8 @@ contexts: - include: pattern-unquoted pattern-unquoted-set-body: - - meta_scope: meta.set.regexp + - meta_include_prototype: false + - meta_scope: meta.set.lua - match: '\]' scope: punctuation.definition.set.end.lua pop: 1 @@ -1022,12 +1058,12 @@ contexts: pattern-unquoted-set-range-begin: - meta_include_prototype: false - match: '-' - scope: punctuation.separator.sequence.regexp + scope: punctuation.separator.sequence.lua pop: 1 pattern-unquoted-set-range-end: - meta_include_prototype: false - - meta_scope: constant.other.range.regexp + - meta_scope: constant.other.range.lua - match: . pop: 1 @@ -1051,8 +1087,13 @@ contexts: pattern-test-first-caret: - meta_include_prototype: false - - match: '\^' - scope: keyword.control.anchor.lua + - match: (\^)[+*?\-]? + captures: + 1: keyword.control.anchor.lua + pop: 1 + + # eat these because they can't be a repetition at the start + - match: '[+*?\-]' pop: 1 # it seems to require this match rather than immediately-pop # in order to work with the multiline below diff --git a/Lua/tests/syntax_test_lua.lua b/Lua/tests/syntax_test_lua.lua index 452d1f5b5f..bfdae6be1b 100644 --- a/Lua/tests/syntax_test_lua.lua +++ b/Lua/tests/syntax_test_lua.lua @@ -793,8 +793,7 @@ -- basic tests for patterns local a = ('test'):match('^()t?$-e*s+()$') -- ^ keyword.control.anchor --- ^ punctuation.section.group.begin --- ^ punctuation.section.group.end +-- ^^ punctuation.section.brackets.lua -- ^ keyword.operator.quantifier -- ^ keyword.operator.quantifier -- ^ keyword.operator.quantifier diff --git a/Lua/tests/syntax_test_lua_patterns.lua b/Lua/tests/syntax_test_lua_patterns.lua new file mode 100644 index 0000000000..43617766fb --- /dev/null +++ b/Lua/tests/syntax_test_lua_patterns.lua @@ -0,0 +1,143 @@ +-- SYNTAX TEST "Packages/Lua/Lua.sublime-syntax" + +-------------------- +-- Anchors and escapes +-------------------- + +(''):match('^foo ^bbar$ %f[test] $') +-- ^ keyword.control.anchor.lua +-- ^ - keyword.control.anchor.lua +-- ^ - keyword.control.anchor.lua +-- ^^ keyword.control.anchor.lua +-- ^ keyword.control.anchor.lua + +(''):match[[^foo ^bbar$ %f[test] $]] +-- ^ keyword.control.anchor.lua +-- ^ - keyword.control.anchor.lua +-- ^ - keyword.control.anchor.lua +-- ^^ keyword.control.anchor.lua +-- ^ keyword.control.anchor.lua + + +(''):match('%^foo ^bbar$ %$') +-- ^ - keyword.control.anchor.lua +-- ^ - keyword.control.anchor.lua + +(''):match[[%^foo ^bbar$ %$]] +-- ^^ constant.character.escape.lua +-- ^ - keyword.control.anchor.lua +-- ^ - keyword.control.anchor.lua +-- ^^ constant.character.escape.lua + +(''):match('%1') +-- ^ keyword.other.backref-and-recursion +-- ^ variable.other.backref-and-recursion + +(''):match('%W') +-- ^^ keyword.control.character-class + + +-------------------- +-- Quantifiers +-------------------- + +(''):match('\x00**++--??') +-- ^^^^ constant.character.escape +-- ^ keyword.operator.quantifier.lua +-- ^ - keyword.operator.quantifier.lua +-- ^ keyword.operator.quantifier.lua +-- ^ - keyword.operator.quantifier.lua +-- ^ keyword.operator.quantifier.lua +-- ^ - keyword.operator.quantifier.lua +-- ^ keyword.operator.quantifier.lua +-- ^ - keyword.operator.quantifier.lua + +(''):match('(ab)+') +-- ^ - keyword.operator.quantifier.lua + +(''):match('?(?abc)') +-- ^ - keyword.operator.quantifier.lua +-- ^ - keyword.operator.quantifier.lua + +(''):match('hello**') +-- ^ keyword.operator.quantifier.lua +-- ^ - keyword.operator.quantifier.lua + +(''):match(')') +-- ^ - punctuation.section.group.end.lua + +-------------------- +-- Sets +-------------------- + +(''):match(' [b-c]') +-- ^^^^^ meta.set.lua +-- ^ punctuation.definition.set.begin.lua +-- ^ punctuation.definition.set.end.lua +-- ^^^ constant.other.range.lua +-- ^ punctuation.separator.sequence.lua + +(''):match('[\x00-\123]') +-- ^ meta.set.lua punctuation.definition.set.begin.lua +-- ^^^^^^^^^^^ meta.set.lua +-- ^^^^^^^^^ constant.other.range +-- ^^^^ constant.character.escape +-- ^ punctuation.separator.sequence - constant.character +-- ^^^^ constant.character.escape +-- ^ punctuation.definition.set.end.lua + +(''):match('[^][]') +-- ^ keyword.operator.logical.lua +-- ^ - punctuation.definition.set.end.lua +-- ^ - punctuation.definition.set.begin.lua + +(''):match('[^abc%w\w0-9]') +-- ^^^^^^^^^^^^ meta.set.lua +-- ^ punctuation.definition.set.begin.lua +-- ^ keyword.operator.logical.lua +-- ^^ keyword.control.character-class.lua +-- ^^ invalid.illegal.invalid-escape.lua +-- ^^^ constant.other.range.lua +-- ^ punctuation.separator.sequence.lua +-- ^ punctuation.definition.set.end.lua + +(''):match('[a-c-x]') +-- ^^^ constant.other.range +-- ^^ - constant.other.range + +(''):match('[]-]') +-- ^ punctuation.definition.set.begin.lua +-- ^ - punctuation +-- ^ - constant.other.range +-- ^ punctuation.definition.set.end.lua + +(''):match('[-a-n]') +-- ^ punctuation.definition.set.begin.lua +-- ^ - constant.other.range +-- ^^^ constant.other.range +-- ^ punctuation.definition.set.end.lua + +(''):match('[%-a]') +-- ^ punctuation.definition.set.begin.lua +-- ^^^ - constant.other.range +-- ^ punctuation.definition.set.end.lua + +(''):match('[a-z%-9]') +-- ^^^ - constant.other.range +-- ^ punctuation.definition.set.end.lua + +(''):match('[%--z]') +-- ^^ - comment +-- ^^ constant.character.escape.lua + +(''):match('[a-%z]') +-- ^ punctuation.definition.set.begin.lua +-- ^^^ constant.other.range +-- ^ - constant.other.range +-- ^ punctuation.definition.set.end.lua + +(''):match('[a-%-]') +-- ^ punctuation.definition.set.begin.lua +-- ^^^ constant.other.range +-- ^ - constant.other.range +-- ^ punctuation.definition.set.end.lua From 4659e1d9acdf56ce3f91909ba299c998d82a9f83 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Fri, 21 Mar 2025 10:29:37 +1000 Subject: [PATCH 08/28] Add test for string.format --- Lua/Lua.sublime-syntax | 5 ++++- Lua/tests/syntax_test_lua.lua | 37 ++++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 0c91c0433e..3ccf21cd6b 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -1158,6 +1158,9 @@ contexts: fmtstr-embed: - meta_include_prototype: false + - match: '%%' + scope: constant.character.escape.lua + - match: '%' scope: constant.other.placeholder.lua push: fmtstr-pattern @@ -1169,7 +1172,7 @@ contexts: pop: 1 - match: '[-+#0-9. ]' scope: constant.other.placeholder.lua - - match: '[cdiuoxXaAfeEgGpqs%]' + - match: '[cdiuoxXaAfeEgGpqs]' scope: constant.other.placeholder.lua pop: 1 - match: '.' diff --git a/Lua/tests/syntax_test_lua.lua b/Lua/tests/syntax_test_lua.lua index bfdae6be1b..51ec3bdfe3 100644 --- a/Lua/tests/syntax_test_lua.lua +++ b/Lua/tests/syntax_test_lua.lua @@ -791,14 +791,41 @@ -- ^ punctuation.section.group.end.lua -- basic tests for patterns - local a = ('test'):match('^()t?$-e*s+()$') + local a = ('test'):match('^()t?$-e*s+%+()$') -- ^ keyword.control.anchor -- ^^ punctuation.section.brackets.lua -- ^ keyword.operator.quantifier -- ^ keyword.operator.quantifier -- ^ keyword.operator.quantifier -- ^ keyword.operator.quantifier --- ^ keyword.control.anchor - - local b = string.format('%0.9f', 15.4) --- ^^^^^ constant.other.placeholder.lua +-- ^^ constant.character.escape.lua +-- ^ keyword.control.anchor + + local b = string.format('%#0.9f %-5q %% %# 5.3d %i %p', 15.4) +-- ^^^^^^ constant.other.placeholder.lua +-- ^^^^ constant.other.placeholder.lua +-- ^^ constant.character.escape.lua +-- ^^^^^^^ constant.other.placeholder.lua +-- ^^ constant.other.placeholder.lua +-- ^^ constant.other.placeholder.lua + + local c = string.pack('< = !3 i f s b c1 d f h i1 j l n s1 x z X') +-- ^ storage.modifier.lua +-- ^ storage.modifier.lua +-- ^^ storage.modifier.lua +-- ^ storage.type.lua +-- ^ storage.type.lua +-- ^ storage.type.lua +-- ^ storage.type.lua +-- ^^ storage.type.lua +-- ^ storage.type.lua +-- ^ storage.type.lua +-- ^ storage.type.lua +-- ^^ storage.type.lua +-- ^ storage.type.lua +-- ^ storage.type.lua +-- ^ storage.type.lua +-- ^^ storage.type.lua +-- ^ punctuation.separator.padding.lua +-- ^ storage.type.lua +-- ^ punctuation.separator.padding.lua From ed8a4000d24ed8aeb8ec6f336695cedb2ac464fa Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Fri, 21 Mar 2025 10:37:54 +1000 Subject: [PATCH 09/28] Remove unused match --- Lua/Lua.sublime-syntax | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 3ccf21cd6b..3300abd67d 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -953,9 +953,6 @@ contexts: push: - meta_include_prototype: false - include: string-escape-pop - - match: \d - scope: keyword.other.backref-and-recursion.lua - pop: 1 - match: . scope: constant.character.escape.lua pop: 1 @@ -1023,9 +1020,6 @@ contexts: scope: constant.character.escape.lua push: - meta_include_prototype: false - - match: \d - scope: keyword.other.backref-and-recursion.lua - pop: 1 - match: . scope: constant.character.escape.lua pop: 1 From 61c450fbd064a183a69a7936e36b277ffc32b565 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Fri, 21 Mar 2025 10:51:11 +1000 Subject: [PATCH 10/28] Fix escapes --- Lua/Lua.sublime-syntax | 18 ++++++++++++++---- Lua/tests/syntax_test_lua_patterns.lua | 19 +++++++++++++++++-- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 3300abd67d..5489e3bd5c 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -893,6 +893,8 @@ contexts: scope: keyword.control.character-class.lua - match: \%f scope: keyword.control.anchor.lua + - match: \%[\$\^] + scope: constant.character.escape.lua - match: (\%)(\d) captures: @@ -1104,17 +1106,25 @@ contexts: - meta_include_prototype: false - meta_scope: meta.string.lua string.quoted.single.lua - include: single-quoted-string-body + - match: \$(?=\') + scope: keyword.control.anchor.lua - match: '' - embed: pattern-quoted - escape: (?=\') + push: pattern-quoted + with_prototype: + - match: (?=\$?\') + pop: 1 pattern-double-quoted-string-body: - meta_include_prototype: false - meta_scope: meta.string.lua string.quoted.double.lua - include: double-quoted-string-body + - match: \$(?=\") + scope: keyword.control.anchor.lua - match: '' - embed: pattern-quoted - escape: (?=\") + push: pattern-quoted + with_prototype: + - match: (?=\$?\") + pop: 1 pattern-multiline-string-body: - meta_include_prototype: false diff --git a/Lua/tests/syntax_test_lua_patterns.lua b/Lua/tests/syntax_test_lua_patterns.lua index 43617766fb..b50cb095f3 100644 --- a/Lua/tests/syntax_test_lua_patterns.lua +++ b/Lua/tests/syntax_test_lua_patterns.lua @@ -4,6 +4,15 @@ -- Anchors and escapes -------------------- +(''):match('\'') +-- ^^ constant.character.escape.lua + +(''):match(' \'') +-- ^^ constant.character.escape.lua + +(''):match(" \"") +-- ^^ constant.character.escape.lua + (''):match('^foo ^bbar$ %f[test] $') -- ^ keyword.control.anchor.lua -- ^ - keyword.control.anchor.lua @@ -21,12 +30,12 @@ (''):match('%^foo ^bbar$ %$') -- ^ - keyword.control.anchor.lua --- ^ - keyword.control.anchor.lua +-- ^ - keyword.control.anchor.lua (''):match[[%^foo ^bbar$ %$]] -- ^^ constant.character.escape.lua -- ^ - keyword.control.anchor.lua --- ^ - keyword.control.anchor.lua +-- ^ - keyword.control.anchor.lua -- ^^ constant.character.escape.lua (''):match('%1') @@ -141,3 +150,9 @@ -- ^^^ constant.other.range -- ^ - constant.other.range -- ^ punctuation.definition.set.end.lua + +------------------ +-- Other various tests +------------------ +(''):match[[[]] +-- ^ punctuation.definition.set.begin.lua From 121561783b3dfa530e84686890f1d6f3472d5fee Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Fri, 21 Mar 2025 11:00:09 +1000 Subject: [PATCH 11/28] Change scope --- Lua/Lua.sublime-syntax | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 5489e3bd5c..ec06129781 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -1128,7 +1128,7 @@ contexts: pattern-multiline-string-body: - meta_include_prototype: false - - meta_scope: meta.string.lua string.quoted.double.lua + - meta_scope: meta.string.lua string.quoted.multiline.lua - include: multiline-string-body - match: '' embed: pattern-unquoted From 2bf42bb2abe0323efadadd755a637d04717a779b Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Fri, 21 Mar 2025 11:08:40 +1000 Subject: [PATCH 12/28] Add extra test --- Lua/tests/syntax_test_lua_patterns.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Lua/tests/syntax_test_lua_patterns.lua b/Lua/tests/syntax_test_lua_patterns.lua index b50cb095f3..402968d2f9 100644 --- a/Lua/tests/syntax_test_lua_patterns.lua +++ b/Lua/tests/syntax_test_lua_patterns.lua @@ -38,6 +38,11 @@ -- ^ - keyword.control.anchor.lua -- ^^ constant.character.escape.lua +(''):match[[ +^testing$]] +-- <- keyword.control.anchor.lua +-- ^ keyword.control.anchor.lua + (''):match('%1') -- ^ keyword.other.backref-and-recursion -- ^ variable.other.backref-and-recursion @@ -156,3 +161,4 @@ ------------------ (''):match[[[]] -- ^ punctuation.definition.set.begin.lua +-- ^^ punctuation.definition.string.end.lua From 175be6c7929fb3979d2da78c6fdf94d110a52307 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Mon, 24 Mar 2025 20:44:36 +1000 Subject: [PATCH 13/28] Update to address comments --- Lua/Lua.sublime-syntax | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index ec06129781..d81c5a5974 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -510,8 +510,7 @@ contexts: scope: meta.property.lua meta.function-call.lua variable.function.lua set: - match: (?={{function_args_begin}}) - pop: 1 - push: + set: - function-arguments-meta - function-arguments-pattern-at1 - include: else-pop @@ -889,7 +888,7 @@ contexts: pattern-shared-charclass: - meta_include_prototype: false - - match: \%[AaCcDdGgLlPpSsUuWwXxZz] + - match: \%(?i:[acdglpsuwxz]) scope: keyword.control.character-class.lua - match: \%f scope: keyword.control.anchor.lua @@ -904,7 +903,7 @@ contexts: # other alphabetic characters are not defined # this skips `f` and `b` as they are special patterns - - match: \%[EeHhIiJjKkMmNnOoQqRrTtVvYy] + - match: \%(?i:[ehijkmnoqrtvy]) scope: invalid.illegal.invalid-escape.lua pattern-shared: @@ -1267,8 +1266,7 @@ contexts: scope: meta.property.lua support.function.builtin.lua set: - match: (?={{function_args_begin}}) - pop: 1 - push: + set: - function-arguments-meta - function-arguments-pattern-at2 - include: else-pop @@ -1276,8 +1274,7 @@ contexts: scope: meta.property.lua support.function.builtin.stringy.lua set: - match: (?={{function_args_begin}}) - pop: 1 - push: + set: - function-arguments-meta - function-arguments-fmtstr-at1 - include: else-pop @@ -1285,8 +1282,7 @@ contexts: scope: meta.property.lua support.function.builtin.stringy.lua set: - match: (?={{function_args_begin}}) - pop: 1 - push: + set: - function-arguments-meta - function-arguments-packstr-at1 - include: else-pop From 82a270cfed052f699d6e5a42ae3f25b36847e129 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Mon, 24 Mar 2025 20:44:55 +1000 Subject: [PATCH 14/28] Add balanced pattersn --- Lua/Lua.sublime-syntax | 23 +++++++++++++++++++++++ Lua/tests/syntax_test_lua_patterns.lua | 16 ++++++++++++---- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index d81c5a5974..d698a2cdf3 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -949,6 +949,11 @@ contexts: pattern-quoted-charclass: - meta_include_prototype: false - include: pattern-shared-charclass + - match: \%b + scope: keyword.control.balanced.lua + push: + - pattern-quoted-balanced-char + - pattern-quoted-balanced-char - match: \% scope: constant.character.escape.lua push: @@ -958,6 +963,13 @@ contexts: scope: constant.character.escape.lua pop: 1 + pattern-quoted-balanced-char: + - meta_include_prototype: false + - include: string-escape-pop + - match: . + scope: keyword.control.balanced.lua + pop: 1 + pattern-quoted-nested: - meta_include_prototype: false - meta_scope: meta.group.lua meta.mode.basic.lua @@ -1017,6 +1029,11 @@ contexts: pattern-unquoted-charclass: - meta_include_prototype: false - include: pattern-shared-charclass + - match: \%b + scope: keyword.control.balanced.lua + push: + - pattern-unquoted-balanced-char + - pattern-unquoted-balanced-char - match: \% scope: constant.character.escape.lua push: @@ -1025,6 +1042,12 @@ contexts: scope: constant.character.escape.lua pop: 1 + pattern-unquoted-balanced-char: + - meta_include_prototype: false + - match: . + scope: keyword.control.balanced.lua + pop: 1 + pattern-unquoted-nested: - meta_include_prototype: false - meta_scope: meta.group.lua meta.mode.basic.lua diff --git a/Lua/tests/syntax_test_lua_patterns.lua b/Lua/tests/syntax_test_lua_patterns.lua index 402968d2f9..8646457fef 100644 --- a/Lua/tests/syntax_test_lua_patterns.lua +++ b/Lua/tests/syntax_test_lua_patterns.lua @@ -13,19 +13,27 @@ (''):match(" \"") -- ^^ constant.character.escape.lua -(''):match('^foo ^bbar$ %f[test] $') +(''):match('^foo ^bbar$ %f[test] %b() $') -- ^ keyword.control.anchor.lua -- ^ - keyword.control.anchor.lua -- ^ - keyword.control.anchor.lua -- ^^ keyword.control.anchor.lua --- ^ keyword.control.anchor.lua +-- ^ punctuation.definition.set.begin.lua +-- ^ punctuation.definition.set.end.lua +-- ^^^^^^ meta.set.lua +-- ^^^^ keyword.control.balanced.lua +-- ^ keyword.control.anchor.lua -(''):match[[^foo ^bbar$ %f[test] $]] +(''):match[[^foo ^bbar$ %f[test] %b() $]] -- ^ keyword.control.anchor.lua -- ^ - keyword.control.anchor.lua -- ^ - keyword.control.anchor.lua -- ^^ keyword.control.anchor.lua --- ^ keyword.control.anchor.lua +-- ^ punctuation.definition.set.begin.lua +-- ^ punctuation.definition.set.end.lua +-- ^^^^^^ meta.set.lua +-- ^^^^ keyword.control.balanced.lua +-- ^ keyword.control.anchor.lua (''):match('%^foo ^bbar$ %$') From fb23b367201f952bbd4629d77859a0979debe55d Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Mon, 24 Mar 2025 21:04:49 +1000 Subject: [PATCH 15/28] Add matches for immediate calls --- Lua/Lua.sublime-syntax | 8 ++++++++ Lua/tests/syntax_test_lua.lua | 14 +++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index d698a2cdf3..156b520f64 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -738,6 +738,14 @@ contexts: scope: punctuation.section.group.end.lua pop: 1 - include: reserved-word-expression-pop + - match: (?="(?:{{string_char_escape}}|[^\\"])*"\s*\)\s*:\s*format{{identifier_break}}) + push: fmtstr-expression + - match: (?='(?:{{string_char_escape}}|[^\\'])*'\s*\)\s*:\s*format{{identifier_break}}) + push: fmtstr-expression + - match: (?="(?:{{string_char_escape}}|[^\\"])*"\s*\)\s*:\s*(?:pack|unpack|packsize){{identifier_break}}) + push: packstr-expression + - match: (?='(?:{{string_char_escape}}|[^\\'])*'\s*\)\s*:\s*(?:pack|unpack|packsize){{identifier_break}}) + push: packstr-expression - match: (?=\S) push: expression diff --git a/Lua/tests/syntax_test_lua.lua b/Lua/tests/syntax_test_lua.lua index 51ec3bdfe3..b56b835b2c 100644 --- a/Lua/tests/syntax_test_lua.lua +++ b/Lua/tests/syntax_test_lua.lua @@ -809,7 +809,7 @@ -- ^^ constant.other.placeholder.lua -- ^^ constant.other.placeholder.lua - local c = string.pack('< = !3 i f s b c1 d f h i1 j l n s1 x z X') + local c = string.pack('< = !3 i f s b c1 d f h i1 j l n s1 x z X'); -- ^ storage.modifier.lua -- ^ storage.modifier.lua -- ^^ storage.modifier.lua @@ -829,3 +829,15 @@ -- ^ punctuation.separator.padding.lua -- ^ storage.type.lua -- ^ punctuation.separator.padding.lua + + ("%q %d"):format(test); +-- ^ punctuation.section.group.begin.lua +-- ^^ constant.other.placeholder.lua +-- ^^ constant.other.placeholder.lua +-- ^ punctuation.section.group.end.lua + + ("< = !5 f"):pack(test); +-- ^ storage.modifier.lua +-- ^ storage.modifier.lua +-- ^^ storage.modifier.lua +-- ^ storage.type.lua From 5d71f93a2ad6bcdadfee7a06b001fa588ddb50b7 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Tue, 1 Apr 2025 14:18:34 +1000 Subject: [PATCH 16/28] Match $ at the end of patterns better --- Lua/Lua.sublime-syntax | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 156b520f64..050a861c83 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -917,7 +917,8 @@ contexts: pattern-shared: - meta_include_prototype: false # start anchor is handled separately as ^ doesn't match the start of the string - - match: \$$ + # It needs to be the end of the string (which $ matches when it is an embedded pattern) + - match: \$$(?!\n) scope: keyword.control.anchor.lua - match: '\(\)' scope: punctuation.section.brackets.lua From d4fdf095664c3c93eb82c9a82b2fec401dad5626 Mon Sep 17 00:00:00 2001 From: Johannes Rappen Date: Wed, 23 Apr 2025 22:25:38 +0200 Subject: [PATCH 17/28] Update Lua.sublime-syntax - add named contexts - add `leading_wspace` var - add `first_line_language` var --- Lua/Lua.sublime-syntax | 736 +++++++++++++++++++++++------------------ 1 file changed, 412 insertions(+), 324 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 050a861c83..c689586cb6 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -9,81 +9,28 @@ file_extensions: first_line_match: |- (?xi: - ^ \#! .* \blua\b # shebang - | ^ \s* -- .*? -\*- .*? \blua\b .*? -\*- # editorconfig + ^ \#! .* {{first_line_language}} # shebang + | {{leading_wspace}} -- .*? -\*- .*? {{first_line_language}} .*? -\*- # editorconfig ) -variables: - reserved_word: |- - (?x:(?: - and|break|do|elseif|else|end|false|for|function|goto|if|in| - local|nil|not|or|repeat|return|then|true|until|while - ){{identifier_break}}) - reserved_word_statement: |- # excludes 'not', 'true', 'nil', 'false', 'function' - (?x:(?: - and|break|do|elseif|else|end|for|goto|if|in| - local|or|repeat|return|then|until|while - ){{identifier_break}}) - metamethod: |- # http://lua-users.org/wiki/MetatableEvents - (?x:__(?: - # special - index|newindex|call|tostring|len|i?pairs|gc|close - # math operators - |unm|add|sub|mul|i?div|mod|pow|concat - # bitwise operators - |band|bor|bxor|bnot|shl|shr - # comparison - |eq|lt|le - ){{identifier_break}}) - # __metatable and __mode don't use functions - metaproperty: (?:__(?:metatable|mode|name){{identifier_break}}) - - identifier_start: '[A-Za-z_]' - identifier_char: '[A-Za-z0-9_]' - identifier_break: (?!{{identifier_char}}) - identifier_raw: (?:{{identifier_start}}{{identifier_char}}*) - identifier: (?:(?!{{reserved_word}}){{identifier_raw}}) - - trailing_expression_char: '[,\]})]' - - function_args_begin: (?:\(|"|'|\[=*\[|\{) - function_call_ahead: (?=\s*{{function_args_begin}}) - function_assignment_ahead: (?=\s*=\s*function{{identifier_break}}) - - dec_exponent: (?:[Ee][-+]?\d*) - hex_exponent: (?:[Pp][-+]?\d*) - - doc_comment_tag: |- - (?x:@(?: - alias|async|author|class|classmod|copyright|deprecated|diagnostic|field - |fixme|function|generic|language|lfunction|license|local|module|nodiscard - |overload|param|raise|release|return|script|section|see|submodule|table - |todo|tparam|treturn|type|usage|vararg|version|warning|within - )\b) - doc_comment_custom_tag: (?:@\w+\b) - - string_char_escape: \\(?:[abfnrtv\\'"\[\]\n]|x\h\h|\d{1,3}|u\{\h+\}) +###[ CONTEXTS ]################################################################ contexts: + prototype: + - include: comments + main: - meta_include_prototype: false - match: '' push: [statements, shebang] - else-pop: - - match: (?=\S) - pop: 1 - - immediately-pop: - - match: '' - pop: 1 - - prototype: - - include: comments +###[ COMMENTS ]################################################################ comments: - - include: block-comments - include: line-comments + - include: block-comments + +###[ COMMENTS / BLOCK COMMENTS ]############################################### block-comments: - match: --\[\[-- @@ -99,7 +46,7 @@ contexts: - match: \]\] scope: punctuation.definition.comment.end.lua pop: 1 - - match: ^\s*(@section)\s+(.*?\S)\s*(?=\]\]|$) + - match: '{{leading_wspace}}(@section)\s+(.*?\S)\s*(?=\]\]|$)' captures: 1: entity.name.tag.documentation.lua 2: entity.name.section.lua @@ -107,10 +54,10 @@ contexts: captures: 1: entity.name.tag.documentation.lua 2: variable.parameter.lua - - match: ^\s*({{doc_comment_tag}}) + - match: '{{leading_wspace}}({{doc_comment_tag}})' captures: 1: entity.name.tag.documentation.lua - - match: ^\s*({{doc_comment_custom_tag}}) + - match: '{{leading_wspace}}({{doc_comment_custom_tag}})' captures: 1: entity.name.tag.documentation.custom.lua @@ -121,6 +68,8 @@ contexts: scope: punctuation.definition.comment.end.lua pop: 1 +###[ COMMENTS / LINE COMMENTS ]################################################ + line-comments: - match: -{3,} scope: comment.line.documentation.lua punctuation.definition.comment.lua @@ -154,7 +103,7 @@ contexts: set: maybe-line-doc-comment maybe-line-doc-comment: - - match: ^\s*(?=--(?!\[(=*)\[)) + - match: '{{leading_wspace}}(?=--(?!\[(=*)\[))' set: - match: -{2,} scope: punctuation.definition.comment.lua @@ -165,8 +114,9 @@ contexts: line-comment-body: - meta_include_prototype: false - meta_scope: comment.line.lua - - match: \n - pop: 1 + - include: eol-pop + +###[ COMMENTS / SHEBANG ]###################################################### shebang: - meta_include_prototype: false @@ -179,10 +129,11 @@ contexts: shebang-body: - meta_include_prototype: false - meta_scope: comment.line.shebang.lua - - match: \blua\b + - match: '{{first_line_language}}' scope: constant.language.shebang.lua - - match: \n - pop: 1 + - include: eol-pop + +###[ STATEMENTS ]############################################################## statements: - match: ; @@ -225,6 +176,8 @@ contexts: scope: keyword.control.end.lua pop: 1 +###[ FUNCTIONS ]############################################################### + function-parameter-list: - match: \( scope: punctuation.section.group.begin.lua @@ -274,6 +227,8 @@ contexts: pop: 1 - include: else-pop +###[ CONTROL STATEMENTS ]##################################################### + control-statements: - match: do{{identifier_break}} scope: keyword.control.lua @@ -363,6 +318,8 @@ contexts: set: if-block - include: statements +###[ EXPRESSIONS ]############################################################# + expression: - match: '' set: @@ -555,6 +512,8 @@ contexts: scope: invalid.unexpected-keyword.lua pop: 1 +###[ CONSTANTS ]############################################################### + builtin: - match: false{{identifier_break}} scope: constant.language.boolean.false.lua @@ -590,6 +549,8 @@ contexts: - include: builtin-modules +###[ VARIABLES ]############################################################### + variable: - match: '{{identifier}}{{function_assignment_ahead}}' scope: entity.name.function.lua @@ -603,6 +564,8 @@ contexts: scope: variable.other.lua pop: 1 +###[ LITERALS / NUMBERS ]###################################################### + number: - match: (0[Xx])(\h*(?:(\.)\h*{{hex_exponent}}?|{{hex_exponent}})) scope: meta.number.float.hexadecimal.lua @@ -630,6 +593,8 @@ contexts: scope: meta.number.integer.decimal.lua constant.numeric.value.lua pop: 1 +###[ LITERALS / STRINGS ]###################################################### + string: - include: single-quoted-string - include: double-quoted-string @@ -729,6 +694,8 @@ contexts: scope: invalid.illegal.invalid-escape.lua pop: 1 +###[ PARENTHESIZED EXPRESSIONS ]############################################### + parenthesized-expression: - match: \( scope: punctuation.section.group.begin.lua @@ -749,6 +716,8 @@ contexts: - match: (?=\S) push: expression +###[ MAPPINGS ]################################################################ + table-constructor: - match: \{ scope: punctuation.section.block.begin.lua @@ -761,46 +730,55 @@ contexts: - match: '[,;]' scope: punctuation.separator.field.lua - - match: \[(?!=*\[) - scope: punctuation.section.brackets.begin.lua - push: - - clear_scopes: 1 - - meta_scope: meta.mapping.key.lua meta.brackets.lua - - match: \] - scope: punctuation.section.brackets.end.lua - pop: 1 - - match: (?=\S) - push: expression - - - match: (?={{identifier}}\s*=(?!=)) - push: - - clear_scopes: 1 - - meta_scope: meta.mapping.key.lua - - match: (?:({{metamethod}})|{{identifier}})(?=\s*=\s*function\b) - scope: entity.name.function.lua - captures: - 1: support.function.metamethod.lua - pop: 1 - - match: '{{metamethod}}' - scope: entity.name.function.lua support.function.metamethod.lua - pop: 1 - - match: '{{metaproperty}}' - scope: string.unquoted.key.lua support.other.metaproperty.lua - pop: 1 - - match: '{{identifier}}' - scope: string.unquoted.key.lua - pop: 1 + - include: table-constructor-body-brackets + - include: table-constructor-body-mapping-key + - include: table-constructor-body-mapping-value - - match: =(?!=) - scope: meta.mapping.lua punctuation.separator.key-value.lua - push: - - - clear_scopes: 1 - - meta_content_scope: meta.mapping.value.lua - - include: immediately-pop - - expression + table-constructor-body-brackets: + - match: \[(?!=*\[) + scope: punctuation.section.brackets.begin.lua + push: + - clear_scopes: 1 + - meta_scope: meta.mapping.key.lua meta.brackets.lua + - match: \] + scope: punctuation.section.brackets.end.lua + pop: 1 - match: (?=\S) push: expression + table-constructor-body-mapping-key: + - match: (?={{identifier}}\s*=(?!=)) + push: + - clear_scopes: 1 + - meta_scope: meta.mapping.key.lua + - match: (?:({{metamethod}})|{{identifier}})(?=\s*=\s*function\b) + scope: entity.name.function.lua + captures: + 1: support.function.metamethod.lua + pop: 1 + - match: '{{metamethod}}' + scope: entity.name.function.lua support.function.metamethod.lua + pop: 1 + - match: '{{metaproperty}}' + scope: string.unquoted.key.lua support.other.metaproperty.lua + pop: 1 + - match: '{{identifier}}' + scope: string.unquoted.key.lua + pop: 1 + + table-constructor-body-mapping-value: + - match: =(?!=) + scope: meta.mapping.lua punctuation.separator.key-value.lua + push: + - - clear_scopes: 1 + - meta_content_scope: meta.mapping.value.lua + - include: immediately-pop + - expression + - match: (?=\S) + push: expression + +###[ FUNCTION DECLARATIONS ]################################################### + function-literal: - match: function{{identifier_break}} scope: keyword.declaration.function.lua @@ -820,16 +798,18 @@ contexts: - match: \( scope: punctuation.section.group.begin.lua - set: - - meta_scope: meta.group.lua - - match: \) - scope: punctuation.section.group.end.lua - pop: 1 - - include: reserved-word-expression-pop - - match: (?=\S) - push: - - expression-list-end-pattern-next - - expression-begin + set: function-arguments-pattern-at2-body + + function-arguments-pattern-at2-body: + - meta_scope: meta.group.lua + - match: \) + scope: punctuation.section.group.end.lua + pop: 1 + - include: reserved-word-expression-pop + - match: (?=\S) + push: + - expression-list-end-pattern-next + - expression-begin function-arguments-pattern-at1: - include: pattern-string @@ -837,16 +817,18 @@ contexts: - match: \( scope: punctuation.section.group.begin.lua - set: - - meta_scope: meta.group.lua - - match: \) - scope: punctuation.section.group.end.lua - pop: 1 - - include: reserved-word-expression-pop - - match: (?=\S) - push: - - expression-list-end - - pattern-expression + set: function-arguments-pattern-at1-body + + function-arguments-pattern-at1-body: + - meta_scope: meta.group.lua + - match: \) + scope: punctuation.section.group.end.lua + pop: 1 + - include: reserved-word-expression-pop + - match: (?=\S) + push: + - expression-list-end + - pattern-expression function-arguments-fmtstr-at1: - include: fmtstr-string @@ -854,16 +836,18 @@ contexts: - match: \( scope: punctuation.section.group.begin.lua - set: - - meta_scope: meta.group.lua - - match: \) - scope: punctuation.section.group.end.lua - pop: 1 - - include: reserved-word-expression-pop - - match: (?=\S) - push: - - expression-list-end - - fmtstr-expression + set: function-arguments-fmtstr-at1-body + + function-arguments-fmtstr-at1-body: + - meta_scope: meta.group.lua + - match: \) + scope: punctuation.section.group.end.lua + pop: 1 + - include: reserved-word-expression-pop + - match: (?=\S) + push: + - expression-list-end + - fmtstr-expression function-arguments-packstr-at1: - include: packstr-string @@ -871,16 +855,20 @@ contexts: - match: \( scope: punctuation.section.group.begin.lua - set: - - meta_scope: meta.group.lua - - match: \) - scope: punctuation.section.group.end.lua - pop: 1 - - include: reserved-word-expression-pop - - match: (?=\S) - push: - - expression-list-end - - packstr-expression + set: function-arguments-packstr-at1-body + + function-arguments-packstr-at1-body: + - meta_scope: meta.group.lua + - match: \) + scope: punctuation.section.group.end.lua + pop: 1 + - include: reserved-word-expression-pop + - match: (?=\S) + push: + - expression-list-end + - packstr-expression + +###[ PATTERNS ]################################################################ pattern-expression: - include: pattern-string @@ -933,8 +921,9 @@ contexts: - meta_include_prototype: false - match: '[+*?\-]' pop: 1 - - match: '' - pop: 1 + - include: immediately-pop + +###[ PATTERNS / QUOTED PATTERNS ]############################################## # the pattern implementation is split into quoted and unquoted as escapes are only processed # in quoted strings. @@ -1019,6 +1008,8 @@ contexts: - match: . pop: 1 +###[ PATTERNS / UNQUOTED PATTERNS ]############################################ + pattern-unquoted: - meta_include_prototype: false - include: pattern-shared @@ -1094,6 +1085,8 @@ contexts: - match: . pop: 1 +###[ PATTERNS / STRING PATTERNS ]############################################## + # this gets included in expressions that want to have a pattern string pattern-string: - match: \[(=*)\[ @@ -1168,6 +1161,8 @@ contexts: # will lose their context half way through. escape: (?=\]=*\]) +###[ PATTERNS / STRING PATTERNS / FMT STRING ]################################# + fmtstr-expression: - include: fmtstr-string - include: expression-begin @@ -1214,6 +1209,8 @@ contexts: scope: invalid.illegal.invalid-format.lua pop: 1 +###[ PATTERNS / STRING PATTERNS / PACK STR ]################################### + packstr-expression: - include: packstr-string - include: expression-begin @@ -1251,209 +1248,300 @@ contexts: - match: (?:[^\\\"\'\]\s]) scope: invalid.illegal.invalid-storage.lua +###[ MODULES ]################################################################# + builtin-modules: - match: coroutine{{identifier_break}} scope: support.constant.builtin.lua - set: - - match: \. - scope: punctuation.accessor.lua - set: - - match: |- - (?x: - create|isyieldable|resume|running|status|wrap|yield|close - ){{identifier_break}} - scope: meta.property.lua support.function.builtin.lua - pop: 1 - - include: property - - include: else-pop + set: builtin-module-coroutine-body - match: package{{identifier_break}} scope: support.constant.builtin.lua - set: - - match: \. - scope: punctuation.accessor.lua - set: - - match: |- - (?x: - config|cpath|loaded|path|preload|searchers|loaders - ){{identifier_break}} - scope: meta.property.lua support.constant.builtin.lua - pop: 1 - - match: |- - (?x: - loadlib|searchpath|seeall - ){{identifier_break}} - scope: meta.property.lua support.function.builtin.lua - pop: 1 - - include: property - - include: else-pop + set: builtin-module-package-body - match: string{{identifier_break}} scope: support.constant.builtin.lua - set: - - match: \. - scope: punctuation.accessor.lua - set: - - match: (?:find|gmatch|gsub|match){{identifier_break}} - scope: meta.property.lua support.function.builtin.lua - set: - - match: (?={{function_args_begin}}) - set: - - function-arguments-meta - - function-arguments-pattern-at2 - - include: else-pop - - match: (?:format){{identifier_break}} - scope: meta.property.lua support.function.builtin.stringy.lua - set: - - match: (?={{function_args_begin}}) - set: - - function-arguments-meta - - function-arguments-fmtstr-at1 - - include: else-pop - - match: (?:pack|unpack|packsize){{identifier_break}} - scope: meta.property.lua support.function.builtin.stringy.lua - set: - - match: (?={{function_args_begin}}) - set: - - function-arguments-meta - - function-arguments-packstr-at1 - - include: else-pop - - match: |- - (?x: - byte|char|dump|len|lower - |rep|reverse|sub|upper - ){{identifier_break}} - scope: meta.property.lua support.function.builtin.lua - pop: 1 - - include: property - - include: else-pop + set: builtin-module-string-body - match: utf8{{identifier_break}} scope: support.constant.builtin.lua - set: - - match: \. - scope: punctuation.accessor.lua - set: - - match: |- - (?x: - charpattern - ){{identifier_break}} - scope: meta.property.lua support.constant.builtin.lua - pop: 1 - - match: |- - (?x: - char|codes|codepoint|len|offset - ){{identifier_break}} - scope: meta.property.lua support.function.builtin.lua - pop: 1 - - include: property - - include: else-pop + set: builtin-module-utf8-body - match: table{{identifier_break}} scope: support.constant.builtin.lua - set: - - match: \. - scope: punctuation.accessor.lua - set: - - match: |- - (?x: - concat|insert|move|pack|remove|sort|unpack|maxn - ){{identifier_break}} - scope: meta.property.lua support.function.builtin.lua - pop: 1 - - include: property - - include: else-pop + set: builtin-module-table-body - match: math{{identifier_break}} scope: support.constant.builtin.lua - set: - - match: \. - scope: punctuation.accessor.lua - set: - - match: |- - (?x: - huge|maxinteger|mininteger|pi - ){{identifier_break}} - scope: meta.property.lua support.constant.builtin.lua - pop: 1 - - match: |- - (?x: - abs|acos|asin|atan|ceil|cos|deg|exp|floor|fmod|log|max|min - |modf|rad|random|randomseed|sin|sqrt|tan|tointeger|type|ult - |atan2|cosh|frexp|ldexp|log10|pow|sinh|tanh - ){{identifier_break}} - scope: meta.property.lua support.function.builtin.lua - pop: 1 - - include: property - - include: else-pop + set: builtin-module-math-body - match: io{{identifier_break}} scope: support.constant.builtin.lua - set: - - match: \. - scope: punctuation.accessor.lua - set: - - match: |- - (?x: - stderr|stdin|stdout - ){{identifier_break}} - scope: meta.property.lua support.constant.builtin.lua - pop: 1 - - match: |- - (?x: - close|flush|input|lines|open|output|popen|read|tmpfile|type|write - ){{identifier_break}} - scope: meta.property.lua support.function.builtin.lua - pop: 1 - - include: property - - include: else-pop + set: builtin-module-io-body - match: os{{identifier_break}} scope: support.constant.builtin.lua - set: - - match: \. - scope: punctuation.accessor.lua - set: - - match: |- - (?x: - clock|date|difftime|execute|exit|getenv|remove|rename - |setlocale|time|tmpname - ){{identifier_break}} - scope: meta.property.lua support.function.builtin.lua - pop: 1 - - include: property - - include: else-pop + set: builtin-module-os-body - match: debug{{identifier_break}} scope: support.constant.builtin.lua - set: - - match: \. - scope: punctuation.accessor.lua - set: - - match: |- - (?x: - debug|gethook|getinfo|getlocal|getmetatable|getregistry - |getupvalue|getuservalue|sethook|setlocal|setmetatable - |setupvalue|setuservalue|traceback|upvalueid|upvaluejoin - |getfenv|setfenv - ){{identifier_break}} - scope: meta.property.lua support.function.builtin.lua - pop: 1 - - include: property - - include: else-pop + set: builtin-module-debug-body - match: bit32{{identifier_break}} scope: support.constant.builtin.lua + set: builtin-module-bit32-body + + builtin-module-coroutine-body: + - match: \. + scope: punctuation.accessor.lua set: - - match: \. - scope: punctuation.accessor.lua + - match: |- + (?x: + create|isyieldable|resume|running|status|wrap|yield|close + ){{identifier_break}} + scope: meta.property.lua support.function.builtin.lua + pop: 1 + - include: property + - include: else-pop + + builtin-module-package-body: + - match: \. + scope: punctuation.accessor.lua + set: + - match: |- + (?x: + config|cpath|loaded|path|preload|searchers|loaders + ){{identifier_break}} + scope: meta.property.lua support.constant.builtin.lua + pop: 1 + - match: |- + (?x: + loadlib|searchpath|seeall + ){{identifier_break}} + scope: meta.property.lua support.function.builtin.lua + pop: 1 + - include: property + - include: else-pop + + builtin-module-string-body: + - match: \. + scope: punctuation.accessor.lua + set: + - match: (?:find|gmatch|gsub|match){{identifier_break}} + scope: meta.property.lua support.function.builtin.lua set: - - match: |- - (?x: - arshift|band|bnot|bor|btest|bxor|extract|lrotate|lshift - |replace|rrotate|rshift - ){{identifier_break}} - scope: meta.property.lua support.function.builtin.lua - pop: 1 - - include: property - - include: else-pop + - match: (?={{function_args_begin}}) + set: + - function-arguments-meta + - function-arguments-pattern-at2 + - include: else-pop + - match: (?:format){{identifier_break}} + scope: meta.property.lua support.function.builtin.stringy.lua + set: + - match: (?={{function_args_begin}}) + set: + - function-arguments-meta + - function-arguments-fmtstr-at1 + - include: else-pop + - match: (?:pack|unpack|packsize){{identifier_break}} + scope: meta.property.lua support.function.builtin.stringy.lua + set: + - match: (?={{function_args_begin}}) + set: + - function-arguments-meta + - function-arguments-packstr-at1 + - include: else-pop + - match: |- + (?x: + byte|char|dump|len|lower + |rep|reverse|sub|upper + ){{identifier_break}} + scope: meta.property.lua support.function.builtin.lua + pop: 1 + - include: property + - include: else-pop + + builtin-module-utf8-body: + - match: \. + scope: punctuation.accessor.lua + set: + - match: |- + (?x: + charpattern + ){{identifier_break}} + scope: meta.property.lua support.constant.builtin.lua + pop: 1 + - match: |- + (?x: + char|codes|codepoint|len|offset + ){{identifier_break}} + scope: meta.property.lua support.function.builtin.lua + pop: 1 + - include: property + - include: else-pop + + builtin-module-table-body: + - match: \. + scope: punctuation.accessor.lua + set: + - match: |- + (?x: + concat|insert|move|pack|remove|sort|unpack|maxn + ){{identifier_break}} + scope: meta.property.lua support.function.builtin.lua + pop: 1 + - include: property + - include: else-pop + + builtin-module-math-body: + - match: \. + scope: punctuation.accessor.lua + set: + - match: |- + (?x: + huge|maxinteger|mininteger|pi + ){{identifier_break}} + scope: meta.property.lua support.constant.builtin.lua + pop: 1 + - match: |- + (?x: + abs|acos|asin|atan|ceil|cos|deg|exp|floor|fmod|log|max|min + |modf|rad|random|randomseed|sin|sqrt|tan|tointeger|type|ult + |atan2|cosh|frexp|ldexp|log10|pow|sinh|tanh + ){{identifier_break}} + scope: meta.property.lua support.function.builtin.lua + pop: 1 + - include: property + - include: else-pop + + builtin-module-io-body: + - match: \. + scope: punctuation.accessor.lua + set: + - match: |- + (?x: + stderr|stdin|stdout + ){{identifier_break}} + scope: meta.property.lua support.constant.builtin.lua + pop: 1 + - match: |- + (?x: + close|flush|input|lines|open|output|popen|read|tmpfile|type|write + ){{identifier_break}} + scope: meta.property.lua support.function.builtin.lua + pop: 1 + - include: property + - include: else-pop + + builtin-module-os-body: + - match: \. + scope: punctuation.accessor.lua + set: + - match: |- + (?x: + clock|date|difftime|execute|exit|getenv|remove|rename + |setlocale|time|tmpname + ){{identifier_break}} + scope: meta.property.lua support.function.builtin.lua + pop: 1 + - include: property + - include: else-pop + + builtin-module-debug-body: + - match: \. + scope: punctuation.accessor.lua + set: + - match: |- + (?x: + debug|gethook|getinfo|getlocal|getmetatable|getregistry + |getupvalue|getuservalue|sethook|setlocal|setmetatable + |setupvalue|setuservalue|traceback|upvalueid|upvaluejoin + |getfenv|setfenv + ){{identifier_break}} + scope: meta.property.lua support.function.builtin.lua + pop: 1 + - include: property + - include: else-pop + + builtin-module-bit32-body: + - match: \. + scope: punctuation.accessor.lua + set: + - match: |- + (?x: + arshift|band|bnot|bor|btest|bxor|extract|lrotate|lshift + |replace|rrotate|rshift + ){{identifier_break}} + scope: meta.property.lua support.function.builtin.lua + pop: 1 + - include: property + - include: else-pop + +###[ PROTOTYPES ]############################################################## + + eol-pop: + - match: '$\n?' + pop: 1 + + else-pop: + - match: (?=\S) + pop: 1 + + immediately-pop: + - match: '' + pop: 1 + +###[ VARIABLES ]############################################################### + +variables: + first_line_language: (?:\blua\b) + leading_wspace: (?:^\s*) + reserved_word: |- + (?x:(?: + and|break|do|elseif|else|end|false|for|function|goto|if|in| + local|nil|not|or|repeat|return|then|true|until|while + ){{identifier_break}}) + reserved_word_statement: |- # excludes 'not', 'true', 'nil', 'false', 'function' + (?x:(?: + and|break|do|elseif|else|end|for|goto|if|in| + local|or|repeat|return|then|until|while + ){{identifier_break}}) + metamethod: |- # http://lua-users.org/wiki/MetatableEvents + (?x:__(?: + # special + index|newindex|call|tostring|len|i?pairs|gc|close + # math operators + |unm|add|sub|mul|i?div|mod|pow|concat + # bitwise operators + |band|bor|bxor|bnot|shl|shr + # comparison + |eq|lt|le + ){{identifier_break}}) + # __metatable and __mode don't use functions + metaproperty: (?:__(?:metatable|mode|name){{identifier_break}}) + + identifier_start: '[A-Za-z_]' + identifier_char: '[A-Za-z0-9_]' + identifier_break: (?!{{identifier_char}}) + identifier_raw: (?:{{identifier_start}}{{identifier_char}}*) + identifier: (?:(?!{{reserved_word}}){{identifier_raw}}) + + trailing_expression_char: '[,\]})]' + + function_args_begin: (?:\(|"|'|\[=*\[|\{) + function_call_ahead: (?=\s*{{function_args_begin}}) + function_assignment_ahead: (?=\s*=\s*function{{identifier_break}}) + + dec_exponent: (?:[Ee][-+]?\d*) + hex_exponent: (?:[Pp][-+]?\d*) + + doc_comment_tag: |- + (?x:@(?: + alias|async|author|class|classmod|copyright|deprecated|diagnostic|field + |fixme|function|generic|language|lfunction|license|local|module|nodiscard + |overload|param|raise|release|return|script|section|see|submodule|table + |todo|tparam|treturn|type|usage|vararg|version|warning|within + )\b) + doc_comment_custom_tag: (?:@\w+\b) + + string_char_escape: \\(?:[abfnrtv\\'"\[\]\n]|x\h\h|\d{1,3}|u\{\h+\}) From 15eedc12d33ca116243fee1ff6be6c8a7f5e8d99 Mon Sep 17 00:00:00 2001 From: Johannes Rappen Date: Wed, 23 Apr 2025 22:34:25 +0200 Subject: [PATCH 18/28] Update Lua.sublime-syntax --- Lua/Lua.sublime-syntax | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index e51e074ed5..9d1b36d440 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -27,8 +27,8 @@ contexts: ###[ COMMENTS ]################################################################ comments: - - include: line-comments - include: block-comments + - include: line-comments ###[ COMMENTS / BLOCK COMMENTS ]############################################### From ca6f34d2361273d2e0def26cbfff8fd5978b2a7d Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Tue, 6 May 2025 08:39:29 +1000 Subject: [PATCH 19/28] Change first_line_language to shebang_language --- Lua/Lua.sublime-syntax | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 9d1b36d440..af6f5f594a 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -9,8 +9,8 @@ file_extensions: first_line_match: |- (?xi: - ^ \#! .* {{first_line_language}} # shebang - | {{leading_wspace}} -- .*? -\*- .*? {{first_line_language}} .*? -\*- # editorconfig + ^ \#! .* {{shebang_language}} # shebang + | {{leading_wspace}} -- .*? -\*- .*? {{shebang_language}} .*? -\*- # editorconfig ) ###[ CONTEXTS ]################################################################ @@ -130,7 +130,7 @@ contexts: shebang-body: - meta_include_prototype: false - meta_scope: comment.line.shebang.lua - - match: '{{first_line_language}}' + - match: '{{shebang_language}}' scope: constant.language.shebang.lua - include: eol-pop @@ -1495,7 +1495,7 @@ contexts: ###[ VARIABLES ]############################################################### variables: - first_line_language: (?:\blua\b) + shebang_language: (?:\blua\b) leading_wspace: (?:^\s*) reserved_word: |- (?x:(?: From ccbc1ad5281e8c4d49b15eacbc5017eac07e556b Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Tue, 6 May 2025 08:40:04 +1000 Subject: [PATCH 20/28] Add more patterns to clarify --- Lua/tests/syntax_test_lua_patterns.lua | 48 ++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/Lua/tests/syntax_test_lua_patterns.lua b/Lua/tests/syntax_test_lua_patterns.lua index 8646457fef..11c7479fef 100644 --- a/Lua/tests/syntax_test_lua_patterns.lua +++ b/Lua/tests/syntax_test_lua_patterns.lua @@ -58,6 +58,54 @@ (''):match('%W') -- ^^ keyword.control.character-class +(''):match('%f[test]') +-- ^^ keyword.control.anchor + +(''):match('% ') +-- ^^ constant.character.escape.lua + +(''):match('%"') +-- ^^ constant.character.escape.lua + +(''):match("%'") +-- ^^ constant.character.escape.lua + +(''):match('%\x1b') +-- ^ constant.character.escape.lua +-- ^^^^ constant.character.escape.hexadecimal.lua + +(''):match('%\1234') +-- ^ constant.character.escape.lua +-- ^^^^ constant.character.escape.decimal.lua +-- ^ - constant.character.escape.decimal.lua + +(''):match('%\r %\n') +-- ^^^ constant.character.escape.lua +-- ^^^ constant.character.escape.lua + +(''):match("%\u{2d}") +-- ^ constant.character.escape.lua +-- ^^^^^^ constant.character.escape.unicode.lua + +-- note: this pattern only repeats the first byte of the UTF-8 character. +(''):match("%\u{2013}") +-- ^ constant.character.escape.lua +-- ^^^^^^^^ constant.character.escape.unicode.lua + +-- invalid patterns that we allow because of highlighting concerns + +(''):match('%') +-- ^ constant.character.escape.lua +-- ^ punctuation.definition.string.end.lua + +(''):match("%") +-- ^ constant.character.escape.lua +-- ^ punctuation.definition.string.end.lua + +(''):match[[%]] +-- ^ constant.character.escape.lua +-- ^^ punctuation.definition.string.end.lua + -------------------- -- Quantifiers From 93e1c979b338236e0fd747aecbd6ccf09bd44956 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Tue, 6 May 2025 09:28:24 +1000 Subject: [PATCH 21/28] Simplify patterns --- Lua/Lua.sublime-syntax | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index af6f5f594a..07ce2d9d9a 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -889,7 +889,7 @@ contexts: scope: keyword.control.character-class.lua - match: \%f scope: keyword.control.anchor.lua - - match: \%[\$\^] + - match: \%[\$\^()%.\[\]+\-?] scope: constant.character.escape.lua - match: (\%)(\d) @@ -953,14 +953,18 @@ contexts: push: - pattern-quoted-balanced-char - pattern-quoted-balanced-char + - match: \%[^'"\\] + scope: constant.character.escape.lua + + # this one is split so that it works with quoted strings - match: \% scope: constant.character.escape.lua push: - meta_include_prototype: false - - include: string-escape-pop - - match: . + - match: '[''"]' scope: constant.character.escape.lua pop: 1 + - include: else-pop pattern-quoted-balanced-char: - meta_include_prototype: false @@ -1030,24 +1034,10 @@ contexts: pattern-unquoted-charclass: - meta_include_prototype: false - include: pattern-shared-charclass - - match: \%b + - match: \%b.?.? scope: keyword.control.balanced.lua - push: - - pattern-unquoted-balanced-char - - pattern-unquoted-balanced-char - - match: \% + - match: \%.? scope: constant.character.escape.lua - push: - - meta_include_prototype: false - - match: . - scope: constant.character.escape.lua - pop: 1 - - pattern-unquoted-balanced-char: - - meta_include_prototype: false - - match: . - scope: keyword.control.balanced.lua - pop: 1 pattern-unquoted-nested: - meta_include_prototype: false From 06121671e209b9d48321ea7d6dff8afb9df82871 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Tue, 6 May 2025 09:30:34 +1000 Subject: [PATCH 22/28] Remove unused pattern --- Lua/Lua.sublime-syntax | 2 -- 1 file changed, 2 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 07ce2d9d9a..9fed54df48 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -889,8 +889,6 @@ contexts: scope: keyword.control.character-class.lua - match: \%f scope: keyword.control.anchor.lua - - match: \%[\$\^()%.\[\]+\-?] - scope: constant.character.escape.lua - match: (\%)(\d) captures: From 9a11575529645280a4c0b854bedf75952c999772 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Tue, 6 Jan 2026 09:27:22 +1000 Subject: [PATCH 23/28] Update string patterns --- Lua/Lua.sublime-syntax | 124 ++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 58 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 9fed54df48..fd4e825079 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -1079,10 +1079,13 @@ contexts: # this gets included in expressions that want to have a pattern string pattern-string: - match: \[(=*)\[ - scope: punctuation.definition.string.begin.lua - set: - - pattern-multiline-string-body - - pattern-test-first-caret-multiline + scope: meta.string.lua string.quoted.multiline.lua punctuation.definition.string.begin.lua + embed: pattern-multiline-string-body + embed_scope: meta.string.lua string.quoted.multiline.lua + escape: \]\1\] + escape_captures: + 0: meta.string.lua string.quoted.multiline.lua punctuation.definition.string.end.lua + pop: 1 - match: \' scope: punctuation.definition.string.begin.lua set: @@ -1109,12 +1112,6 @@ contexts: - match: (?=[^\^]) pop: 1 - pattern-test-first-caret-multiline: - - meta_include_prototype: false - - match: $\n? - set: pattern-test-first-caret - - include: pattern-test-first-caret - pattern-single-quoted-string-body: - meta_include_prototype: false - meta_scope: meta.string.lua string.quoted.single.lua @@ -1141,14 +1138,10 @@ contexts: pattern-multiline-string-body: - meta_include_prototype: false - - meta_scope: meta.string.lua string.quoted.multiline.lua - - include: multiline-string-body - - match: '' - embed: pattern-unquoted - # we don't seem to be able to use the capture to get the right one - # this means that patterns that contain something that matches this - # will lose their context half way through. - escape: (?=\]=*\]) + - match: \n? + push: + - pattern-unquoted + - pattern-test-first-caret ###[ PATTERNS / STRING PATTERNS / FMT STRING ]################################# @@ -1159,44 +1152,50 @@ contexts: fmtstr-string: - match: \[(=*)\[ scope: punctuation.definition.string.begin.lua - set: multiline-string-body - with_prototype: - - include: fmtstr-embed - + set: multiline-fmtstr-body - match: \' scope: punctuation.definition.string.begin.lua - set: single-quoted-string-body - with_prototype: - - include: fmtstr-embed - + set: single-quoted-fmtstr-body - match: \" scope: punctuation.definition.string.begin.lua - set: double-quoted-string-body - with_prototype: - - include: fmtstr-embed + set: double-quoted-fmtstr-body - fmtstr-embed: + single-quoted-fmtstr-body: - meta_include_prototype: false - - match: '%%' - scope: constant.character.escape.lua + - meta_scope: meta.string.lua string.quoted.single.lua + - include: single-quoted-string-body + - include: fmtstr-placeholder - - match: '%' - scope: constant.other.placeholder.lua - push: fmtstr-pattern + double-quoted-fmtstr-body: + - meta_include_prototype: false + - meta_scope: meta.string.lua string.quoted.double.lua + - include: double-quoted-string-body + - include: fmtstr-placeholder - fmtstr-pattern: + multiline-fmtstr-body: - meta_include_prototype: false - # these characters never appear in a format pattern so it can be simpler - - match: (?=[\\\"\'\]]) - pop: 1 - - match: '[-+#0-9. ]' - scope: constant.other.placeholder.lua - - match: '[cdiuoxXaAfeEgGpqs]' + - meta_scope: meta.string.lua string.quoted.multiline.lua + - include: multiline-string-body + - include: fmtstr-placeholder + + fmtstr-placeholder: + - meta_include_prototype: false + - match: '%%' + scope: constant.character.escape.lua + - match: |- + (?x) + % + \#? # alternate form + 0? # pad with zeros + \-? # left-adjust + \ ? # implicit sign + [+-]? # sign + \d* # width + (\.\d*)? # precision + [cdiuoxXaAfeEgGpqs%] scope: constant.other.placeholder.lua - pop: 1 - - match: '.' + - match: '%[^"''\\\]]' scope: invalid.illegal.invalid-format.lua - pop: 1 ###[ PATTERNS / STRING PATTERNS / PACK STR ]################################### @@ -1207,24 +1206,33 @@ contexts: packstr-string: - match: \[(=*)\[ scope: punctuation.definition.string.begin.lua - set: multiline-string-body - with_prototype: - - include: packstr-pattern - + set: multiline-packstr-body - match: \' scope: punctuation.definition.string.begin.lua - set: single-quoted-string-body - with_prototype: - - include: packstr-pattern - + set: single-quoted-packstr-body - match: \" scope: punctuation.definition.string.begin.lua - set: double-quoted-string-body - with_prototype: - - include: packstr-pattern + set: double-quoted-packstr-body + + single-quoted-packstr-body: + - meta_include_prototype: false + - meta_scope: meta.string.lua string.quoted.single.lua + - include: single-quoted-string-body + - include: packstr-patterns - packstr-pattern: + double-quoted-packstr-body: - meta_include_prototype: false + - meta_scope: meta.string.lua string.quoted.double.lua + - include: double-quoted-string-body + - include: packstr-patterns + + multiline-packstr-body: + - meta_include_prototype: false + - meta_scope: meta.string.lua string.quoted.multiline.lua + - include: multiline-string-body + - include: packstr-patterns + + packstr-patterns: - match: '[=<>]|![0-9]*' scope: storage.modifier.lua @@ -1234,7 +1242,7 @@ contexts: - match: '[xX]' scope: punctuation.separator.padding.lua - - match: (?:[^\\\"\'\]\s]) + - match: '[^"''\\\]\s]' scope: invalid.illegal.invalid-storage.lua ###[ MODULES ]################################################################# From f7f0bf8349661f445fd7c1ae4fa007eb8090d022 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Tue, 6 Jan 2026 09:32:23 +1000 Subject: [PATCH 24/28] Exclude prototypes for \z --- Lua/Lua.sublime-syntax | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index fd4e825079..1be06579ba 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -654,6 +654,7 @@ contexts: - match: \\z push: + - meta_include_prototype: false - meta_scope: constant.character.escape.whitespace.lua - include: else-pop @@ -685,6 +686,7 @@ contexts: # \z turns into nothing, so we don't pop - match: \\z push: + - meta_include_prototype: false - meta_scope: constant.character.escape.whitespace.lua - include: else-pop From 47bc7d3ada52332c9caec89707edbc5452c677d4 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Tue, 6 Jan 2026 09:55:24 +1000 Subject: [PATCH 25/28] [Lua] Update special string expression handling It now allows multiple strings to be highlighted. For example string.match("this", "%w".."hi".."%S") --- Lua/Lua.sublime-syntax | 114 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 111 insertions(+), 3 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index 1be06579ba..ee0b313ee8 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -831,7 +831,8 @@ contexts: - match: (?=\S) push: - expression-list-end - - pattern-expression + - pattern-expression-endpopc + - pattern-expression-begin function-arguments-fmtstr-at1: - include: fmtstr-string @@ -850,7 +851,8 @@ contexts: - match: (?=\S) push: - expression-list-end - - fmtstr-expression + - fmtstr-expression-endpopc + - fmtstr-expression-begin function-arguments-packstr-at1: - include: packstr-string @@ -869,14 +871,50 @@ contexts: - match: (?=\S) push: - expression-list-end - - packstr-expression + - packstr-expression-endpopc + - packstr-expression-begin ###[ PATTERNS ]################################################################ pattern-expression: + - match: '' + set: + - pattern-expression-end + - pattern-expression-begin + + pattern-expression-begin: - include: pattern-string - include: expression-begin + pattern-expression-endpopc: + - match: ',' + pop: 1 + - include: pattern-expression-end + + pattern-expression-end: + - match: (?:[=<>~]=) + scope: keyword.operator.comparison.lua + push: pattern-expression-begin + - match: (?://|[-+*/%^]) + scope: keyword.operator.arithmetic.lua + push: pattern-expression-begin + - match: (?:>>|<<|[&|~]) + scope: keyword.operator.bitwise.lua + push: pattern-expression-begin + - match: (?:[<>]) + scope: keyword.operator.comparison.lua + push: pattern-expression-begin + - match: \.\. + scope: keyword.operator.concatenation.lua + push: pattern-expression-begin + - match: = + scope: keyword.operator.assignment.lua + push: pattern-expression-begin + - match: (?:and|or){{identifier_break}} + scope: keyword.operator.logical.lua + push: pattern-expression-begin + - include: expression-end + expression-list-end-pattern-next: - match: ',' scope: punctuation.separator.comma.lua @@ -1148,9 +1186,44 @@ contexts: ###[ PATTERNS / STRING PATTERNS / FMT STRING ]################################# fmtstr-expression: + - match: '' + set: + - fmtstr-expression-end + - fmtstr-expression-begin + + fmtstr-expression-begin: - include: fmtstr-string - include: expression-begin + fmtstr-expression-endpopc: + - match: ',' + pop: 1 + - include: fmtstr-expression-end + + fmtstr-expression-end: + - match: (?:[=<>~]=) + scope: keyword.operator.comparison.lua + push: fmtstr-expression-begin + - match: (?://|[-+*/%^]) + scope: keyword.operator.arithmetic.lua + push: fmtstr-expression-begin + - match: (?:>>|<<|[&|~]) + scope: keyword.operator.bitwise.lua + push: fmtstr-expression-begin + - match: (?:[<>]) + scope: keyword.operator.comparison.lua + push: fmtstr-expression-begin + - match: \.\. + scope: keyword.operator.concatenation.lua + push: fmtstr-expression-begin + - match: = + scope: keyword.operator.assignment.lua + push: fmtstr-expression-begin + - match: (?:and|or){{identifier_break}} + scope: keyword.operator.logical.lua + push: fmtstr-expression-begin + - include: expression-end + fmtstr-string: - match: \[(=*)\[ scope: punctuation.definition.string.begin.lua @@ -1202,9 +1275,44 @@ contexts: ###[ PATTERNS / STRING PATTERNS / PACK STR ]################################### packstr-expression: + - match: '' + set: + - packstr-expression-end + - packstr-expression-begin + + packstr-expression-begin: - include: packstr-string - include: expression-begin + packstr-expression-endpopc: + - match: ',' + pop: 1 + - include: packstr-expression-end + + packstr-expression-end: + - match: (?:[=<>~]=) + scope: keyword.operator.comparison.lua + push: packstr-expression-begin + - match: (?://|[-+*/%^]) + scope: keyword.operator.arithmetic.lua + push: packstr-expression-begin + - match: (?:>>|<<|[&|~]) + scope: keyword.operator.bitwise.lua + push: packstr-expression-begin + - match: (?:[<>]) + scope: keyword.operator.comparison.lua + push: packstr-expression-begin + - match: \.\. + scope: keyword.operator.concatenation.lua + push: packstr-expression-begin + - match: = + scope: keyword.operator.assignment.lua + push: packstr-expression-begin + - match: (?:and|or){{identifier_break}} + scope: keyword.operator.logical.lua + push: packstr-expression-begin + - include: expression-end + packstr-string: - match: \[(=*)\[ scope: punctuation.definition.string.begin.lua From d7d66d3427f561d2f05c3efd89d9982cbc29a23e Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Tue, 6 Jan 2026 10:16:12 +1000 Subject: [PATCH 26/28] [Lua] Use branching to choose when to highlight expressions. --- Lua/Lua.sublime-syntax | 82 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 15 deletions(-) diff --git a/Lua/Lua.sublime-syntax b/Lua/Lua.sublime-syntax index ee0b313ee8..d06261a32e 100644 --- a/Lua/Lua.sublime-syntax +++ b/Lua/Lua.sublime-syntax @@ -702,22 +702,74 @@ contexts: parenthesized-expression: - match: \( scope: punctuation.section.group.begin.lua + branch_point: special-string-paren + branch: + - special-string-is-fmtstr + - special-string-is-packstr + - special-string-is-nothing + + special-string-is-fmtstr: + - match: '' set: - - meta_scope: meta.group.lua - - match: \) - scope: punctuation.section.group.end.lua - pop: 1 - - include: reserved-word-expression-pop - - match: (?="(?:{{string_char_escape}}|[^\\"])*"\s*\)\s*:\s*format{{identifier_break}}) - push: fmtstr-expression - - match: (?='(?:{{string_char_escape}}|[^\\'])*'\s*\)\s*:\s*format{{identifier_break}}) - push: fmtstr-expression - - match: (?="(?:{{string_char_escape}}|[^\\"])*"\s*\)\s*:\s*(?:pack|unpack|packsize){{identifier_break}}) - push: packstr-expression - - match: (?='(?:{{string_char_escape}}|[^\\'])*'\s*\)\s*:\s*(?:pack|unpack|packsize){{identifier_break}}) - push: packstr-expression - - match: (?=\S) - push: expression + - parenthesized-expression-end-fmtstr + - parenthesized-expression-inside-fmtstr + + special-string-is-packstr: + - match: '' + set: + - parenthesized-expression-end-packstr + - parenthesized-expression-inside-packstr + + special-string-is-nothing: + - match: '' + set: + - parenthesized-expression-end-normal + - parenthesized-expression-inside-normal + + # at this point the stack is: + # - expression-end # <- where we need to get to + # - expression-begin + # - parenthesized-expression-end-X + parenthesized-expression-end-normal: + - match: '' + pop: 2 # pop this as well as expression-begin + + parenthesized-expression-end-fmtstr: + - match: (?=:\s*format{{identifier_break}}) + pop: 2 # pop this as well as expression-begin + + - match: (?=\S) + fail: special-string-paren + + parenthesized-expression-end-packstr: + - match: (?=:\s*(pack|unpack|packsize){{identifier_break}}) + pop: 2 # pop this as well as expression-begin + + - match: (?=\S) + fail: special-string-paren + + + parenthesized-expression-inside-base: + - meta_scope: meta.group.lua + - match: \) + scope: punctuation.section.group.end.lua + pop: 1 + - include: reserved-word-expression-pop + + parenthesized-expression-inside-normal: + - include: parenthesized-expression-inside-base + - match: (?=\S) + push: expression + + parenthesized-expression-inside-fmtstr: + - include: parenthesized-expression-inside-base + - match: (?=\S) + push: fmtstr-expression + + parenthesized-expression-inside-packstr: + - include: parenthesized-expression-inside-base + - match: (?=\S) + push: packstr-expression ###[ MAPPINGS ]################################################################ From 1a13c1ec21aa577f41ca20690667bfef2b065c14 Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Tue, 6 Jan 2026 10:26:03 +1000 Subject: [PATCH 27/28] Add semis --- Lua/tests/syntax_test_lua_patterns.lua | 78 +++++++++++++------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/Lua/tests/syntax_test_lua_patterns.lua b/Lua/tests/syntax_test_lua_patterns.lua index 11c7479fef..6aefa123ec 100644 --- a/Lua/tests/syntax_test_lua_patterns.lua +++ b/Lua/tests/syntax_test_lua_patterns.lua @@ -4,16 +4,16 @@ -- Anchors and escapes -------------------- -(''):match('\'') +(''):match('\''); -- ^^ constant.character.escape.lua -(''):match(' \'') +(''):match(' \''); -- ^^ constant.character.escape.lua -(''):match(" \"") +(''):match(" \""); -- ^^ constant.character.escape.lua -(''):match('^foo ^bbar$ %f[test] %b() $') +(''):match('^foo ^bbar$ %f[test] %b() $'); -- ^ keyword.control.anchor.lua -- ^ - keyword.control.anchor.lua -- ^ - keyword.control.anchor.lua @@ -24,7 +24,7 @@ -- ^^^^ keyword.control.balanced.lua -- ^ keyword.control.anchor.lua -(''):match[[^foo ^bbar$ %f[test] %b() $]] +(''):match[[^foo ^bbar$ %f[test] %b() $]]; -- ^ keyword.control.anchor.lua -- ^ - keyword.control.anchor.lua -- ^ - keyword.control.anchor.lua @@ -36,11 +36,11 @@ -- ^ keyword.control.anchor.lua -(''):match('%^foo ^bbar$ %$') +(''):match('%^foo ^bbar$ %$'); -- ^ - keyword.control.anchor.lua -- ^ - keyword.control.anchor.lua -(''):match[[%^foo ^bbar$ %$]] +(''):match[[%^foo ^bbar$ %$]]; -- ^^ constant.character.escape.lua -- ^ - keyword.control.anchor.lua -- ^ - keyword.control.anchor.lua @@ -51,58 +51,58 @@ -- <- keyword.control.anchor.lua -- ^ keyword.control.anchor.lua -(''):match('%1') +(''):match('%1'); -- ^ keyword.other.backref-and-recursion -- ^ variable.other.backref-and-recursion -(''):match('%W') +(''):match('%W'); -- ^^ keyword.control.character-class -(''):match('%f[test]') +(''):match('%f[test]'); -- ^^ keyword.control.anchor -(''):match('% ') +(''):match('% '); -- ^^ constant.character.escape.lua -(''):match('%"') +(''):match('%"'); -- ^^ constant.character.escape.lua -(''):match("%'") +(''):match("%'"); -- ^^ constant.character.escape.lua -(''):match('%\x1b') +(''):match('%\x1b'); -- ^ constant.character.escape.lua -- ^^^^ constant.character.escape.hexadecimal.lua -(''):match('%\1234') +(''):match('%\1234'); -- ^ constant.character.escape.lua -- ^^^^ constant.character.escape.decimal.lua -- ^ - constant.character.escape.decimal.lua -(''):match('%\r %\n') +(''):match('%\r %\n'); -- ^^^ constant.character.escape.lua -- ^^^ constant.character.escape.lua -(''):match("%\u{2d}") +(''):match("%\u{2d}"); -- ^ constant.character.escape.lua -- ^^^^^^ constant.character.escape.unicode.lua -- note: this pattern only repeats the first byte of the UTF-8 character. -(''):match("%\u{2013}") +(''):match("%\u{2013}"); -- ^ constant.character.escape.lua -- ^^^^^^^^ constant.character.escape.unicode.lua -- invalid patterns that we allow because of highlighting concerns -(''):match('%') +(''):match('%'); -- ^ constant.character.escape.lua -- ^ punctuation.definition.string.end.lua -(''):match("%") +(''):match("%"); -- ^ constant.character.escape.lua -- ^ punctuation.definition.string.end.lua -(''):match[[%]] +(''):match[[%]]; -- ^ constant.character.escape.lua -- ^^ punctuation.definition.string.end.lua @@ -111,7 +111,7 @@ -- Quantifiers -------------------- -(''):match('\x00**++--??') +(''):match('\x00**++--??'); -- ^^^^ constant.character.escape -- ^ keyword.operator.quantifier.lua -- ^ - keyword.operator.quantifier.lua @@ -122,32 +122,32 @@ -- ^ keyword.operator.quantifier.lua -- ^ - keyword.operator.quantifier.lua -(''):match('(ab)+') +(''):match('(ab)+'); -- ^ - keyword.operator.quantifier.lua -(''):match('?(?abc)') +(''):match('?(?abc)'); -- ^ - keyword.operator.quantifier.lua -- ^ - keyword.operator.quantifier.lua -(''):match('hello**') +(''):match('hello**'); -- ^ keyword.operator.quantifier.lua -- ^ - keyword.operator.quantifier.lua -(''):match(')') +(''):match(')'); -- ^ - punctuation.section.group.end.lua -------------------- -- Sets -------------------- -(''):match(' [b-c]') +(''):match(' [b-c]'); -- ^^^^^ meta.set.lua -- ^ punctuation.definition.set.begin.lua -- ^ punctuation.definition.set.end.lua -- ^^^ constant.other.range.lua -- ^ punctuation.separator.sequence.lua -(''):match('[\x00-\123]') +(''):match('[\x00-\123]'); -- ^ meta.set.lua punctuation.definition.set.begin.lua -- ^^^^^^^^^^^ meta.set.lua -- ^^^^^^^^^ constant.other.range @@ -156,12 +156,12 @@ -- ^^^^ constant.character.escape -- ^ punctuation.definition.set.end.lua -(''):match('[^][]') +(''):match('[^][]'); -- ^ keyword.operator.logical.lua -- ^ - punctuation.definition.set.end.lua -- ^ - punctuation.definition.set.begin.lua -(''):match('[^abc%w\w0-9]') +(''):match('[^abc%w\w0-9]'); -- ^^^^^^^^^^^^ meta.set.lua -- ^ punctuation.definition.set.begin.lua -- ^ keyword.operator.logical.lua @@ -171,42 +171,42 @@ -- ^ punctuation.separator.sequence.lua -- ^ punctuation.definition.set.end.lua -(''):match('[a-c-x]') +(''):match('[a-c-x]'); -- ^^^ constant.other.range -- ^^ - constant.other.range -(''):match('[]-]') +(''):match('[]-]'); -- ^ punctuation.definition.set.begin.lua -- ^ - punctuation -- ^ - constant.other.range -- ^ punctuation.definition.set.end.lua -(''):match('[-a-n]') +(''):match('[-a-n]'); -- ^ punctuation.definition.set.begin.lua -- ^ - constant.other.range -- ^^^ constant.other.range -- ^ punctuation.definition.set.end.lua -(''):match('[%-a]') +(''):match('[%-a]'); -- ^ punctuation.definition.set.begin.lua -- ^^^ - constant.other.range -- ^ punctuation.definition.set.end.lua -(''):match('[a-z%-9]') +(''):match('[a-z%-9]'); -- ^^^ - constant.other.range -- ^ punctuation.definition.set.end.lua -(''):match('[%--z]') +(''):match('[%--z]'); -- ^^ - comment -- ^^ constant.character.escape.lua -(''):match('[a-%z]') +(''):match('[a-%z]'); -- ^ punctuation.definition.set.begin.lua -- ^^^ constant.other.range -- ^ - constant.other.range -- ^ punctuation.definition.set.end.lua -(''):match('[a-%-]') +(''):match('[a-%-]'); -- ^ punctuation.definition.set.begin.lua -- ^^^ constant.other.range -- ^ - constant.other.range @@ -215,6 +215,6 @@ ------------------ -- Other various tests ------------------ -(''):match[[[]] +(''):match[[[]]; -- ^ punctuation.definition.set.begin.lua -- ^^ punctuation.definition.string.end.lua From deb92f91f7b1c3f655aa86b7f62106c8d0190f3d Mon Sep 17 00:00:00 2001 From: mbartlett21 Date: Tue, 6 Jan 2026 10:26:21 +1000 Subject: [PATCH 28/28] Add tests for strings before functions --- Lua/tests/syntax_test_lua_patterns.lua | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Lua/tests/syntax_test_lua_patterns.lua b/Lua/tests/syntax_test_lua_patterns.lua index 6aefa123ec..395fb78c29 100644 --- a/Lua/tests/syntax_test_lua_patterns.lua +++ b/Lua/tests/syntax_test_lua_patterns.lua @@ -218,3 +218,34 @@ (''):match[[[]]; -- ^ punctuation.definition.set.begin.lua -- ^^ punctuation.definition.string.end.lua + +------------------ +-- testing concatted and other expressions +------------------ + +;("%s" .. "%%" .. "%02s"):format(that) +-- ^^ constant.other.placeholder.lua +-- ^^ keyword.operator.concatenation.lua +-- ^^ constant.character.escape.lua +-- ^^^^ constant.other.placeholder.lua + +;("szs" .. "I3"):pack(that) +-- ^^^ storage.type.lua +-- ^^ storage.type.lua + +;("%s"):this() +-- ^^ - constant.other.placeholder + +string.format("est" .. "%s that") +-- ^^ constant.other.placeholder.lua + +string.match("this", "test(%[ [^123] this) ()" .. "%+[^test](that)") +-- ^^ constant.character.escape.lua +-- ^^ constant.character.escape.lua + +string.match("this", "%w" .. "hi" .. "%S") +-- ^^ keyword.control.character-class.lua +-- ^^ keyword.control.character-class.lua + +string.format("%+10s") +-- ^^^^^ constant.other.placeholder.lua