From b58ab9da035134319b00c3fb0d6c6072bf0b658a Mon Sep 17 00:00:00 2001 From: deathaxe Date: Mon, 11 Sep 2023 18:30:35 +0200 Subject: [PATCH] [ShellScript] Improve test expression and pattern matching highlighting (#3827) * [ShellScript] Fix regexp group highlighting Fixes #3825 * [ShellScript] Improve shell patterns and POSIX ERE This commit... 1. separates implementation of basic Bash pattern matching an posix extended regular expressions to more accurately scope them. 2. adjusts [[ ... ]] implementation to make use of both pattern types: a) after `==` or `!=` => basic pattern matching b) after `=~` => posix extended regular expressions 3. implements various variants of pattern contexts to correctly handle bailouts depending on where patterns occur. (e.g.: test expressions, parameter expansions, case patterns, ...) 4. fine tunes rules to follow language specifications more closely. POSIX Extended Regular Expressions are based on `RegExp (Basic)` but have been simplified by removing all the modifiers and (?x) regexp matching as it is not supported. Related context are included directly into Bash.sublime-syntax as they share various contexts with basic pattern matching and it may reduce friction in case Bash is inherited by a 3rd-party syntax (e.g.: Makefile). * [ShellScript] Drop unsupported parens in test args This commit removes support for parentheses within test command arguments, as those are not supported by Bash or Zsh. * [ShellScript] Separate contexts for [ ... ] and [[ ... ]] This commit distinguishes builtin test expressions `[ ... ]` and compound test expressions `[[ ... ]]` to respect the different features supported. Builtin test expressions support same limited test arguments as `test` command, only. * [ShellScript] Fix comparison operator scope in test expressions This commit... 1. scopes single `=` as comparison operator as it is equal to `==`. 2. scopes -ot, -ne, ... as comparison operators * [ShellScript] Tweak compound test context names This commit renames some contexts to make it more obvious where they belong to. --- ShellScript/Bash.sublime-syntax | 670 +++++++++----- ShellScript/test/syntax_test_bash.sh | 1244 +++++++++++++++++++++----- 2 files changed, 1478 insertions(+), 436 deletions(-) diff --git a/ShellScript/Bash.sublime-syntax b/ShellScript/Bash.sublime-syntax index 7c3d582324..a5c8d5e9d8 100644 --- a/ShellScript/Bash.sublime-syntax +++ b/ShellScript/Bash.sublime-syntax @@ -80,6 +80,15 @@ variables: variable_begin: (?={{variable_first_char}}|\$) variable_first_char: '{{identifier_first_char}}' + # posix regexp quantifiers + character_quantifier: '[?*+]' + lazy_or_possessive: '[?+]?' + ranged_quantifier: \{\d+(?:,\d*)?\} + + posix_classes: |- + (?x: ascii | alnum | alpha | blank | cntrl | digit | graph + | lower | print | punct | space | upper | word | xdigit ) + # A character that, when unquoted, separates words. A metacharacter is a # space, tab, newline, or one of the following characters: ‘|’, ‘&’, ‘;’, # ‘(’, ‘)’, ‘<’, or ‘>’. @@ -691,22 +700,10 @@ contexts: cmd-test: - match: \[\[(?=\s) scope: support.function.test.begin.shell - push: - - meta_scope: meta.conditional.shell - - match: '{{wspace}}(\]\])' - captures: - 1: support.function.test.end.shell - pop: 1 - - include: test-expression-body + push: compound-test-body - match: \[(?=\s) scope: support.function.test.begin.shell - push: - - meta_scope: meta.conditional.shell - - match: '{{wspace}}(\])' - captures: - 1: support.function.test.end.shell - pop: 1 - - include: test-expression-body + push: builtin-test-body - match: test{{cmd_break}} scope: meta.function-call.identifier.shell @@ -715,117 +712,111 @@ contexts: cmd-test-args: - meta_content_scope: meta.function-call.arguments.shell + - match: =~ + scope: invalid.illegal.operator.shell + - match: '!=|==?' + scope: keyword.operator.comparison.shell - include: redirections - - include: cmd-test-args-common + - include: test-expression-common - include: eoc-pop - cmd-test-args-common: - - match: \( - scope: punctuation.section.group.begin.shell - push: cmd-test-args-group-body - - match: '[=!]=' - scope: keyword.operator.comparison.shell + builtin-test-body: + - meta_scope: meta.conditional.shell + - match: '{{wspace}}(\])' + captures: + 1: support.function.test.end.shell + pop: 1 - match: =~ scope: invalid.illegal.operator.shell + - match: '!=|==?' + scope: keyword.operator.comparison.shell - include: test-expression-common - cmd-test-args-group-body: - - meta_scope: meta.group.shell - - match: \) - scope: punctuation.section.group.end.shell + compound-test-body: + - meta_scope: meta.conditional.shell + - match: '{{wspace}}(\]\])' + captures: + 1: support.function.test.end.shell pop: 1 - - include: cmd-test-args-common - - include: eoc-pop - - test-expression-body: - match: \( scope: punctuation.section.group.begin.shell - push: test-expression-group-body - - match: ([=!]=|=~)\s* + push: compound-test-group-body + - match: (=~)\s* captures: 1: keyword.operator.comparison.shell - push: test-expression-pattern + push: + - compound-test-eregexp + - eregexp-unexpected-quantifier + - match: (!=|==?)\s* + captures: + 1: keyword.operator.comparison.shell + push: compound-test-pattern - include: test-expression-common - test-expression-group-body: - - meta_scope: meta.group.shell - - match: \) - scope: punctuation.section.group.end.shell + compound-test-eregexp: + - meta_content_scope: meta.string.regexp.shell + - match: (?=\s) pop: 1 - - include: test-expression-body + - include: eregexp-main-content - test-expression-pattern: - - meta_content_scope: meta.pattern.regexp.shell - - include: test-pattern-common - - match: (?=\)) + compound-test-pattern: + - meta_content_scope: meta.string.regexp.shell + - match: (?=\s) pop: 1 + - include: pattern-main-content - test-pattern-common: - - match: (?=\s) + compound-test-group-body: + - meta_scope: meta.group.shell + - match: \) + scope: punctuation.section.group.end.shell pop: 1 - - match: ([?*+@!])?(\() + - match: (=~)\s* captures: - 1: keyword.operator.quantifier.regexp.shell - 2: meta.group.regexp.shell - punctuation.definition.group.begin.regexp.shell - push: expansions-pattern-group-body - - match: (?=\[) - branch_point: test-pattern-set - branch: - - test-pattern-set - - test-pattern-set-fallback - - include: boolean - - include: strings - - include: expansions-job - - include: expansions-variables - - include: expansions-pattern-quantifiers - - test-pattern-set: - - meta_include_prototype: false - # Inherited from `expansions-pattern-set` to fail in case of premature - # termination by test expression end ` ]]`. - - match: (\[)(?:([!^])|-)? + 1: keyword.operator.comparison.shell + push: + - compound-test-group-eregexp + - eregexp-unexpected-quantifier + - match: (!=|==?)\s* captures: - 1: punctuation.definition.set.begin.regexp.shell - 2: keyword.operator.logical.regexp.shell - set: test-pattern-set-body + 1: keyword.operator.comparison.shell + push: compound-test-group-pattern + - include: test-expression-common - test-pattern-set-body: - - meta_scope: meta.set.regexp.shell - - match: $|(?=\s\]\]) - fail: test-pattern-set - - include: expansions-pattern-set-end - - include: expansions-pattern-set-common - - match: (\[)([!^])?(?=[\.=:]) - captures: - 1: punctuation.definition.set.begin.regexp.shell - 2: keyword.operator.logical.regexp.shell - push: test-pattern-set-body + compound-test-group-eregexp: + - meta_content_scope: meta.string.regexp.shell + - include: compound-test-group-pattern-end + - include: eregexp-group-content - test-pattern-set-fallback: - - meta_include_prototype: false - - match: \[ - pop: 1 + compound-test-group-pattern: + - meta_content_scope: meta.string.regexp.shell + - include: compound-test-group-pattern-end + - include: pattern-main-content - test-expression-common: - - match: ([-+])[aobcdefghknoprstuvwxzGLNORS]{{opt_break}}(?!\s*([=!]=|=~)) - scope: - meta.parameter.option.shell - variable.parameter.option.shell + compound-test-group-pattern-end: + - match: \) + scope: punctuation.section.group.end.shell + pop: 2 + - match: '{{wspace}}(\]\])' captures: - 1: punctuation.definition.parameter.shell - - match: ([-+])(?:ef|nt|ot|eq|ne|lt|le|gt|ge){{opt_break}}(?!\s*([=!]=|=~)) + 1: invalid.illegal.unexpected-token.shell + pop: 3 + - match: $\n? + scope: invalid.illegal.unexpected-token.shell + pop: 3 + + test-expression-common: + - match: ([-+])[aobcdefghknoprstuvwxzGLNORS]{{opt_break}}(?!\s*(=~|!=|==?)) scope: meta.parameter.option.shell variable.parameter.option.shell captures: 1: punctuation.definition.parameter.shell - - match: '<=?|>=?' + - match: ([-+])(?:ef|nt|ot|eq|ne|lt|le|gt|ge){{opt_break}}(?!\s*(=~|!=|==?)) + scope: keyword.operator.comparison.shell + - match: '[<>]=?' scope: keyword.operator.comparison.shell - match: '&&|\|\||!' scope: keyword.operator.logical.shell - - match: '=' - scope: keyword.operator.assignment.shell - include: comments - include: booleans - include: numbers @@ -1119,29 +1110,28 @@ contexts: - clear_scopes: 1 # remove meta.conditional.case.shell - meta_scope: meta.conditional.case.clause.patterns.shell - meta.pattern.regexp.shell + meta.string.regexp.shell - match: \) scope: keyword.control.conditional.patterns.end.shell pop: 1 # emergency bail outs if ')' is missing - match: (?=;;&?|;&) pop: 1 - - include: case-clause-patterns-body + - include: case-clause-pattern-content - case-clause-patterns-body: + case-clause-pattern-content: # [Bash] 3.2.4.2: Each pattern undergoes tilde expansion, parameter # expansion, command substitution, and arithmetic expansion. - - match: \( - scope: punctuation.definition.group.begin.regexp.shell - push: - - meta_scope: meta.group.regexp.shell - - match: \) - scope: punctuation.definition.group.end.regexp.shell - pop: 1 - - include: case-clause-patterns-body + - match: \( # Note: exists to support ZSH + scope: meta.group.regexp.shell punctuation.definition.group.begin.regexp.shell + push: case-clause-pattern-group-body - include: case-end-ahead - - include: expansions-pattern - - include: expansions-pattern-group-common + - include: pattern-group-content + + case-clause-pattern-group-body: + - meta_content_scope: meta.group.regexp.shell + - include: pattern-group-end + - include: case-clause-pattern-content case-clause-commands: - clear_scopes: 1 # remove meta.conditional.case.shell @@ -1690,7 +1680,7 @@ contexts: - include: expansions expansions: - - include: expansions-pattern + - include: expansions-patterns - include: expansions-brace - include: expansions-variables - include: expansions-job @@ -1839,18 +1829,15 @@ contexts: set: - match: ":" scope: keyword.operator.substring.end.shell - set: - - include: expressions - - include: expansions-parameter-common - - include: expressions - - include: expansions-parameter-common + set: expansions-parameter-expression + - include: expansions-parameter-expression - match: \#(?=}) - match: ([@*])?(\#\#?|%%?|\^\^?|,,?) captures: 1: variable.language.shell 2: keyword.operator.expansion.shell - set: expansions-parameter-regexp - - match: ([@*]?)(@)([QEPAa])(?=}) + set: expansions-parameter-pattern + - match: ([@*])?(@)([QEPAa])(?=}) captures: 1: variable.language.shell 2: keyword.operator.expansion.shell @@ -1867,49 +1854,91 @@ contexts: - include: line-continuations - include: strings - expansions-parameter-regexp: + expansions-parameter-expression: + - include: expressions + - include: expansions-parameter-common + + expansions-parameter-pattern: + # [3.5.8.1] Pattern Matching in parameter expansions + - meta_content_scope: meta.string.regexp.shell - include: expansions-parameter-common - - include: expansions-parameter-pattern - include: expansions-variables + - include: expansions-parameter-pattern-charsets + - include: expansions-parameter-pattern-groups + - include: pattern-wildcards - expansions-parameter-pattern: - # [3.5.8.1] Pattern Matching + expansions-parameter-pattern-charsets: + - match: (?=\[) + branch_point: expansions-parameter-pattern-charset + branch: + - expansions-parameter-pattern-charset + - pattern-charset-fallback + + expansions-parameter-pattern-charset: + - match: (\[)([!^]?) + captures: + 1: punctuation.definition.set.begin.regexp.shell + 2: keyword.operator.logical.regexp.shell + set: + - expansions-parameter-pattern-charset-body + - pattern-charset-begin + + expansions-parameter-pattern-charset-body: + - meta_scope: meta.set.regexp.shell + - match: $|(?=\}) # bailout at end parameter + fail: expansions-parameter-pattern-charset + - include: pattern-charset-end + - include: pattern-charset-content + + expansions-parameter-pattern-groups: - match: ([?*+@!])(\() captures: 1: keyword.operator.quantifier.regexp.shell - 2: meta.group.regexp.shell - punctuation.definition.group.begin.regexp.shell + 2: meta.group.regexp.shell punctuation.definition.group.begin.regexp.shell push: expansions-parameter-pattern-group-body - - match: (\[)(?:([!^])|-)?(?=.*]) - captures: - 1: punctuation.definition.set.begin.regexp.shell - 2: keyword.operator.logical.regexp.shell - push: expansions-parameter-pattern-set-body - - include: expansions-pattern-quantifiers expansions-parameter-pattern-group-body: - meta_content_scope: meta.group.regexp.shell - - include: expansions-pattern-group-end - - include: expansions-parameter-pattern - - include: expansions-pattern-group-common + - include: pattern-group-end + - include: line-continuations + - include: strings + - include: expansions-variables + - include: expansions-parameter-pattern-groups + - include: expansions-parameter-pattern-group-charsets + - include: pattern-wildcards + - include: pattern-operators - include: brace-pop - expansions-parameter-pattern-set-body: - - meta_scope: meta.set.regexp.shell - - include: expansions-pattern-set-end - - include: expansions-pattern-set-common - - match: (\[)([!^])?(?=[\.=:]) + expansions-parameter-pattern-group-charsets: + - match: (?=\[) + branch_point: expansions-parameter-pattern-group-charset + branch: + - expansions-parameter-pattern-group-charset + - pattern-charset-fallback + + expansions-parameter-pattern-group-charset: + - match: (\[)([!^]?) captures: 1: punctuation.definition.set.begin.regexp.shell 2: keyword.operator.logical.regexp.shell - push: expansions-parameter-pattern-set-body - - include: brace-pop + set: + - expansions-parameter-pattern-group-charset-body + - pattern-charset-begin + + expansions-parameter-pattern-group-charset-body: + - meta_scope: meta.set.regexp.shell + - match: $|(?=[)}]) # bailout at end of group or parameter + fail: expansions-parameter-pattern-group-charset + - include: pattern-charset-end + - include: pattern-charset-content expansions-parameter-substitution: + # [3.5.8.1] Pattern Matching in parameter expansions' substitutions + - meta_content_scope: meta.string.regexp.shell - match: / scope: keyword.operator.substitution.shell set: expressions-parameter-variable - - include: expansions-parameter-regexp + - include: expansions-parameter-pattern expansions-parameter-switch: - match: '[/#%]' @@ -1922,97 +1951,336 @@ contexts: - include: expansions-parameter-common - include: expansions-variables - expansions-pattern: - # [3.5.8.1] Pattern Matching - - match: ([?*+@!])(\() - captures: - 1: keyword.operator.quantifier.regexp.shell - 2: meta.group.regexp.shell - punctuation.definition.group.begin.regexp.shell - push: expansions-pattern-group-body - - match: (\[)(?:([!^])|-)?(?=.*]) + expansions-patterns: + - include: pattern-groups + - include: pattern-charsets + - include: pattern-wildcards + + expansions-tilde: + - match: '~' + scope: meta.interpolation.tilde.shell variable.language.tilde.shell + +###[ SHELL PATTERN MATCHING ]################################################## + + pattern-main-content: + # [3.5.8.1] Pattern Matching in arbitrary expressions + - include: line-continuations + - include: any-escapes + - include: pattern-literals + - include: expansions-variables + - include: expansions-patterns + + pattern-charsets: + - match: (?=\[) + branch_point: pattern-charset + branch: + - pattern-charset + - pattern-charset-fallback + + pattern-charset: + - match: (\[)([!^]?) captures: 1: punctuation.definition.set.begin.regexp.shell 2: keyword.operator.logical.regexp.shell - push: expansions-pattern-set-body - - include: expansions-pattern-quantifiers + set: + - pattern-charset-body + - pattern-charset-begin - expansions-pattern-quantifiers: - - match: '[*?]' - scope: keyword.operator.quantifier.regexp.shell + pattern-charset-body: + - meta_scope: meta.set.regexp.shell + - match: (?!\S) # also fail at eof + fail: pattern-charset + - include: pattern-charset-end + - include: pattern-charset-content - expansions-pattern-group-body: - - meta_content_scope: meta.group.regexp.shell - - include: expansions-pattern-group-end - - include: expansions-pattern - - include: expansions-pattern-group-common + pattern-charset-begin: + - meta_include_prototype: false + # a range may start with `]` at the beginning of a set + - match: (?:(\\.)|.)(-)(?:(\\.)|[^\]$]|(?!\])) + scope: constant.other.range.regexp.shell + captures: + 1: constant.character.escape.regexp.shell + 2: punctuation.separator.sequence.regexp.shell + 3: constant.character.escape.regexp.shell + pop: 1 + # the following are treated literal at the beginning of a set + - match: '[]-]' + pop: 1 + - include: immediately-pop - expansions-pattern-group-end: - - match: \) - scope: - meta.group.regexp.shell - punctuation.definition.group.end.regexp.shell + pattern-charset-end: + - match: \] + scope: punctuation.definition.set.end.regexp.shell pop: 1 - expansions-pattern-group-common: - - match: \| - scope: keyword.operator.logical.regexp.shell - - include: strings + pattern-charset-fallback: + - meta_include_prototype: false + - match: \[ + pop: 1 + + pattern-charset-content: + - match: (\[)(\.)(?=\S*\.\]) + captures: + 1: punctuation.definition.set.begin.regexp.shell + 2: constant.character.collate.regexp.shell punctuation.definition.collate.begin.regexp.shell + push: pattern-charset-collate-body + - match: (\[)(=)(?=\S*=\]) + captures: + 1: punctuation.definition.set.begin.regexp.shell + 2: constant.character.equivalence-class.regexp.shell punctuation.definition.class.begin.regexp.shell + push: pattern-charset-equivalence-body + - match: (\[)(:)(?=(?:{{posix_classes}}|\$+(?:\{.*?\}|\w+)):\]) + captures: + 1: punctuation.definition.set.begin.regexp.shell + 2: constant.other.posix-class.regexp.shell punctuation.definition.class.begin.regexp.shell + push: pattern-charset-posix-body + - match: (?:(\\.)|[^\]])?(-)(?:(\\.)|[^\]$]|(?!\])) + scope: constant.other.range.regexp.shell + captures: + 1: constant.character.escape.regexp.shell + 2: punctuation.separator.sequence.regexp.shell + 3: constant.character.escape.regexp.shell + - include: any-escapes - include: expansions-variables - include: eol-pop - expansions-pattern-set-body: + pattern-charset-collate-body: - meta_scope: meta.set.regexp.shell - - include: expansions-pattern-set-end - - include: expansions-pattern-set-common - - match: (\[)([!^])?(?=[\.=:]) + - meta_content_scope: constant.character.collate.regexp.shell + - match: (\.)(\]) captures: - 1: punctuation.definition.set.begin.regexp.shell - 2: keyword.operator.logical.regexp.shell - push: expansions-pattern-set-body + 1: constant.character.collate.regexp.shell punctuation.definition.collate.end.regexp.shell + 2: punctuation.definition.set.end.regexp.shell + pop: 1 + - include: any-escapes + - include: expansions-variables - expansions-pattern-set-end: - - match: -?(\])([*?+]*) + pattern-charset-equivalence-body: + - meta_scope: meta.set.regexp.shell + - meta_content_scope: constant.character.equivalence-class.regexp.shell + - match: (=)(\]) captures: - 1: punctuation.definition.set.end.regexp.shell - 2: keyword.operator.quantifier.regexp.shell + 1: constant.character.equivalence-class.regexp.shell punctuation.definition.class.end.regexp.shell + 2: punctuation.definition.set.end.regexp.shell pop: 1 + - include: any-escapes + - include: expansions-variables - expansions-pattern-set-common: - - match: ((\.)[[:word:]](\.))(\]) + pattern-charset-posix-body: + - meta_scope: meta.set.regexp.shell + - meta_content_scope: constant.other.posix-class.regexp.shell + - match: ({{posix_classes}}?(:))(\]) captures: - 1: constant.character.collate.regexp.shell - 2: punctuation.definition.collate.begin.regexp.shell - 3: punctuation.definition.collate.end.regexp.shell - 4: punctuation.definition.set.end.regexp.shell + 1: constant.other.posix-class.regexp.shell + 2: punctuation.definition.class.end.regexp.shell + 3: punctuation.definition.set.end.regexp.shell pop: 1 - - match: ((=)[[:word:]](=))(\]) + - include: any-escapes + - include: expansions-variables + + pattern-groups: + - match: ([?*+@!])(\() captures: - 1: constant.character.equivalence-class.regexp.shell - 2: punctuation.definition.class.begin.regexp.shell - 3: punctuation.definition.class.end.regexp.shell - 4: punctuation.definition.set.end.regexp.shell + 1: keyword.operator.quantifier.regexp.shell + 2: meta.group.regexp.shell punctuation.definition.group.begin.regexp.shell + push: pattern-group-body + + pattern-group-body: + - meta_content_scope: meta.group.regexp.shell + - include: pattern-group-end + - include: pattern-group-content + + pattern-group-content: + - include: line-continuations + - include: any-escapes + - include: pattern-literals + - include: expansions-variables + - include: pattern-groups + - include: pattern-group-charsets + - include: pattern-wildcards + - include: pattern-operators + + pattern-group-end: + - match: \) + scope: meta.group.regexp.shell punctuation.definition.group.end.regexp.shell pop: 1 - - match: |- - ((:)(?x:alnum|alpha|ascii|blank|cntrl|digit|graph|lower|print| - punct|space|upper|word|xdigit)(:))(\]) + + pattern-group-charsets: + - match: (?=\[) + branch_point: pattern-group-charset + branch: + - pattern-group-charset + - pattern-charset-fallback + + pattern-group-charset: + - match: (\[)([!^]?) captures: - 1: constant.other.posix-class.regexp.shell - 2: punctuation.definition.class.begin.regexp.shell - 3: punctuation.definition.class.end.regexp.shell - 4: punctuation.definition.set.end.regexp.shell + 1: punctuation.definition.set.begin.regexp.shell + 2: keyword.operator.logical.regexp.shell + set: + - pattern-group-charset-body + - pattern-charset-begin + + pattern-group-charset-body: + - meta_scope: meta.set.regexp.shell + - match: (?=\)) + fail: pattern-group-charset + - include: pattern-charset-end + - include: pattern-charset-content + + pattern-literals: + - match: \" + scope: punctuation.definition.literal.begin.shell + push: pattern-double-quoted-literal-body + - match: \' + scope: punctuation.definition.literal.begin.shell + push: pattern-single-quoted-literal-body + + pattern-double-quoted-literal-body: + - meta_include_prototype: false + - match: \" + scope: punctuation.definition.literal.end.shell pop: 1 - - match: \- - scope: punctuation.separator.range.regexp.shell - # [Bash] 3.2.4.2: Each pattern undergoes tilde expansion, parameter - # expansion, command substitution, and arithmetic expansion. + - include: string-prototype + - include: string-escapes + - include: line-continuations + - include: expansions-variables + + pattern-single-quoted-literal-body: + - meta_include_prototype: false + - match: \' + scope: punctuation.definition.literal.end.shell + pop: 1 + - include: string-prototype + + pattern-operators: + - match: \| + scope: keyword.operator.logical.regexp.shell + + pattern-wildcards: + - match: \* + scope: constant.other.wildcard.asterisk.shell + - match: \? + scope: constant.other.wildcard.questionmark.shell + +###[ POSIX EXTENDED REGULAR EXPRESSIONS ]###################################### + + eregexp-main-content: + - include: line-continuations - include: any-escapes + - include: pattern-literals - include: expansions-variables - - include: eol-pop + - include: eregexp-charsets + - include: eregexp-groups + - include: eregexp-anchors + - include: eregexp-operators + - include: eregexp-quantifiers + - include: eregexp-literals + + eregexp-groups: + - match: \( + scope: punctuation.section.group.begin.regexp.shell + push: [eregexp-group-body, eregexp-unexpected-quantifier] - expansions-tilde: - - match: '~' - scope: meta.interpolation.tilde.shell variable.language.tilde.shell + eregexp-group-body: + - meta_scope: meta.group.regexp.shell + - match: \) + scope: punctuation.section.group.end.regexp.shell + pop: 1 + - include: eregexp-group-content + + eregexp-group-content: + - include: line-continuations + - include: any-escapes + - include: pattern-literals + - include: expansions-variables + - include: eregexp-group-charsets + - include: eregexp-groups + - include: eregexp-anchors + - include: eregexp-operators + - include: eregexp-quantifiers + - include: eregexp-literals + + eregexp-charsets: + - match: (?=\[) + branch_point: eregexp-charset + branch: + - eregexp-charset + - pattern-charset-fallback + + eregexp-charset: + - meta_include_prototype: false + - match: (\[)(\^?) + captures: + 1: punctuation.definition.set.begin.regexp.shell + 2: keyword.operator.logical.regexp.shell + set: + - eregexp-charset-body + - pattern-charset-begin + + eregexp-charset-body: + - meta_include_prototype: false + - meta_scope: meta.set.regexp.shell + - match: (?!\S) # also fail at eof + fail: eregexp-charset + - include: pattern-charset-end + - include: pattern-charset-content + + eregexp-group-charsets: + - match: (?=\[) + branch_point: eregexp-group-charset + branch: + - eregexp-group-charset + - pattern-charset-fallback + + eregexp-group-charset: + - match: (\[)(\^?) + captures: + 1: punctuation.definition.set.begin.regexp.shell + 2: keyword.operator.logical.regexp.shell + set: + - eregexp-group-charset-body + - pattern-charset-begin + + eregexp-group-charset-body: + - meta_include_prototype: false + - meta_scope: meta.set.regexp.shell + - match: (?=\)) + fail: eregexp-group-charset + - include: pattern-charset-end + - include: pattern-charset-content + + eregexp-anchors: + - match: '[$^]' + scope: keyword.control.anchor.regexp.shell + push: eregexp-unexpected-quantifier + + eregexp-operators: + - match: \| + scope: keyword.operator.alternation.regexp.shell + push: eregexp-unexpected-quantifier + + eregexp-quantifiers: + - match: '{{ranged_quantifier}}{{lazy_or_possessive}}' + scope: keyword.operator.quantifier.regexp.shell + push: eregexp-unexpected-quantifier + - match: '{{character_quantifier}}{{lazy_or_possessive}}' + scope: keyword.operator.quantifier.regexp.shell + push: eregexp-unexpected-quantifier + + eregexp-unexpected-quantifier: + - meta_include_prototype: false + - match: '{{ranged_quantifier}}{{lazy_or_possessive}}' + scope: invalid.illegal.unexpected-quantifier.regexp.shell + - match: '{{character_quantifier}}{{lazy_or_possessive}}' + scope: invalid.illegal.unexpected-quantifier.regexp.shell + - include: immediately-pop + + eregexp-literals: + - match: \. + scope: keyword.other.any.regexp.shell + - match: \) + scope: invalid.illegal.stray.regexp.shell ###[ STRINGS ]################################################################# diff --git a/ShellScript/test/syntax_test_bash.sh b/ShellScript/test/syntax_test_bash.sh index 5031caf07b..12798eb560 100755 --- a/ShellScript/test/syntax_test_bash.sh +++ b/ShellScript/test/syntax_test_bash.sh @@ -2064,8 +2064,7 @@ test+= test $var != 0 #<- meta.function-call.identifier.shell support.function.test.shell #^^^ meta.function-call.identifier.shell support.function.test.shell -# ^^^^^^^^^ meta.function-call.arguments.shell - meta.pattern -# ^ meta.function-call.arguments.shell +# ^^^^^^^^^^ meta.function-call.arguments.shell - meta.string.regexp # ^ - meta.function-call # ^^ keyword.operator.comparison.shell # ^ constant.numeric.value.shell @@ -2073,7 +2072,7 @@ test $var != 0 test $var == true #<- meta.function-call.identifier.shell support.function.test.shell #^^^ meta.function-call.identifier.shell support.function.test.shell -# ^^^^^^^^^^^^^ meta.function-call.arguments.shell - meta.pattern +# ^^^^^^^^^^^^^ meta.function-call.arguments.shell - meta.string.regexp # ^^ keyword.operator.comparison.shell # ^^^^ constant.language.boolean.shell @@ -2091,7 +2090,7 @@ test var[0] != var[^0-9]*$ # ^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.arguments.shell # ^^^^^^ meta.string.shell string.unquoted.shell # ^^ keyword.operator.comparison.shell -# ^^^^^^^^^^^ meta.string.shell string.unquoted.shell - meta.pattern +# ^^^^^^^^^^^ meta.string.shell string.unquoted.shell - meta.string.regexp test ${var[0]} != var[^0-9]*$ #<- meta.function-call.identifier.shell support.function.test.shell @@ -2101,7 +2100,7 @@ test ${var[0]} != var[^0-9]*$ # ^^^ variable.other.readwrite.shell # ^^^ meta.item-access.shell # ^^ keyword.operator.comparison.shell -# ^^^^^^^^^^^ meta.string.shell string.unquoted.shell - meta.pattern +# ^^^^^^^^^^^ meta.string.shell string.unquoted.shell - meta.string.regexp test expr -a expr -o expr -- | cmd |& cmd # <- meta.function-call.identifier.shell support.function.test.shell @@ -2115,34 +2114,28 @@ test expr -a expr -o expr -- | cmd |& cmd # ^^^ meta.function-call.identifier.shell variable.function.shell # ^^ keyword.operator.assignment.pipe.shell -test ! ($line =~ ^[0-9]+$) +test ! $line == ^[0-9]+$ # <- meta.function-call.identifier.shell support.function.test.shell #^^^ meta.function-call.identifier.shell - meta.function-call.arguments -# ^^^ meta.function-call.arguments.shell - meta.function-call.identifier - meta.group -# ^^^^^^^^^^^^^^^^^^^ meta.function-call.arguments.shell meta.group.shell -# ^ - meta.function-call - meta.group +# ^^^^^^^^^^^^^^^^^^^^ meta.function-call.arguments.shell - meta.function-call.identifier +# ^ - meta.function-call #^^^ support.function.test.shell # ^ keyword.operator.logical.shell -# ^ punctuation.section.group.begin.shell -# ^^^^^ variable.other.readwrite.shell -# ^^ invalid.illegal.operator.shell -# ^^^^^^^^ meta.string.shell string.unquoted.shell +# ^^^^^ variable.other.readwrite.shell +# ^^ keyword.operator.comparison.shell +# ^^^^^^^^ meta.string.shell string.unquoted.shell -test ! ($line =~ ^[0-9]+$) >> /file +test ! $line =~ ^[0-9]+$ >> /file # <- meta.function-call.identifier.shell support.function.test.shell #^^^ meta.function-call.identifier.shell - meta.function-call.arguments -# ^^^ meta.function-call.arguments.shell - meta.function-call.identifier - meta.group -# ^^^^^^^^^^^^^^^^^^^ meta.function-call.arguments.shell meta.group.shell -# ^^^^^^^^^ meta.function-call.arguments.shell - meta.group -# ^ - meta.function-call - meta.group +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.arguments.shell - meta.function-call.identifier - meta.group +# ^ - meta.function-call #^^^ support.function.test.shell # ^ keyword.operator.logical.shell -# ^ punctuation.section.group.begin.shell -# ^^^^^ variable.other.readwrite.shell -# ^^ invalid.illegal.operator.shell -# ^^^^^^^^ meta.string.shell string.unquoted.shell -# ^ punctuation.section.group.end.shell -# ^^ keyword.operator.assignment.redirection.shell +# ^^^^^ variable.other.readwrite.shell +# ^^ invalid.illegal.operator.shell +# ^^^^^^^^ meta.string.shell string.unquoted.shell +# ^^ keyword.operator.assignment.redirection.shell if test expr -a expr ; then echo "success"; fi # ^ - meta.function-call @@ -3305,6 +3298,7 @@ ${foo:=bar} : ${foo//:/[}] # ^^^^^^^^^^^ meta.interpolation.parameter.shell +# ^^^ - meta.string.regexp - meta.set # ^ - meta.interpolation # ^ punctuation.definition.variable.shell # ^ punctuation.section.interpolation.begin.shell @@ -3316,15 +3310,64 @@ ${foo:=bar} : ${foo//:/[\}]} # ^^^^^^^^^^^^^^ meta.interpolation.parameter.shell +# ^ - meta.interpolation # ^ punctuation.definition.variable.shell # ^ punctuation.section.interpolation.begin.shell # ^^^ variable.other.readwrite.shell # ^ keyword.operator.substitution.shell # ^ variable.parameter.switch.shell # ^ keyword.operator.substitution.shell +# ^^^^ - meta.string.regexp - meta.set - punctuation # ^^ constant.character.escape.shell # ^ punctuation.section.interpolation.end.shell +: ${foo//[a-/\}} # incomplete charset +# ^^^^^^^^^^^^^^ meta.interpolation.parameter.shell +# ^ - meta.interpolation +# ^ punctuation.definition.variable.shell +# ^ punctuation.section.interpolation.begin.shell +# ^^^ variable.other.readwrite.shell +# ^ keyword.operator.substitution.shell +# ^ variable.parameter.switch.shell +# ^^^ - meta.set - punctuation +# ^ keyword.operator.substitution.shell +# ^^ constant.character.escape.shell +# ^ punctuation.section.interpolation.end.shell + +: ${foo//+([a-:/\}} # incomplete charset in incomplete group +# ^^^^^^^^ meta.interpolation.parameter.shell - meta.group +# ^^^^^^^^ meta.interpolation.parameter.shell meta.group.regexp.shell +# ^ meta.interpolation.parameter.shell - meta.group +# ^ - meta.interpolation +# ^ punctuation.definition.variable.shell +# ^ punctuation.section.interpolation.begin.shell +# ^^^ variable.other.readwrite.shell +# ^ keyword.operator.substitution.shell +# ^ variable.parameter.switch.shell +# ^ keyword.operator.quantifier.regexp.shell +# ^ punctuation.definition.group.begin.regexp.shell +# ^^^^^ - constant - punctuation +# ^^ constant.character.escape.shell +# ^ punctuation.section.interpolation.end.shell + +: ${foo//+([a-:)/\}} # incomplete charset in group +# ^^^^^^^^ meta.interpolation.parameter.shell - meta.group +# ^^^^^^ meta.interpolation.parameter.shell meta.group.regexp.shell +# ^^^^ meta.interpolation.parameter.shell - meta.group +# ^ - meta.interpolation +# ^ punctuation.definition.variable.shell +# ^ punctuation.section.interpolation.begin.shell +# ^^^ variable.other.readwrite.shell +# ^ keyword.operator.substitution.shell +# ^ variable.parameter.switch.shell +# ^ keyword.operator.quantifier.regexp.shell +# ^ punctuation.definition.group.begin.regexp.shell +# ^^^^ - constant - punctuation +# ^ punctuation.definition.group.end.regexp.shell +# ^ keyword.operator.substitution.shell +# ^^ constant.character.escape.shell +# ^ punctuation.section.interpolation.end.shell + : ${^foo//:/[}] # ^^^^^^^^^^^^ meta.interpolation.parameter.shell # ^ - meta.interpolation @@ -3332,6 +3375,7 @@ ${foo:=bar} # ^ punctuation.section.interpolation.begin.shell # ^ keyword.operator.expansion.shell # ^^^ variable.other.readwrite.shell +# ^ - punctuation # ^ punctuation.section.interpolation.end.shell : ${^foo//:/[\}]} @@ -3739,11 +3783,11 @@ status="${status#"${status%%[![:space:]]*}"}" # ^ punctuation.definition.set.begin.regexp.shell # ^ keyword.operator.logical.regexp.shell # ^ punctuation.definition.set.begin.regexp.shell -# ^ punctuation.definition.class.begin.regexp -# ^^^^^^ constant.other.posix-class.regexp -# ^ punctuation.definition.set.end.regexp +# ^ punctuation.definition.class.begin.regexp.shell +# ^^^^^^ constant.other.posix-class.regexp.shell +# ^ punctuation.definition.set.end.regexp.shell # ^^ punctuation.definition.set.end.regexp.shell -# ^ keyword.operator.quantifier.regexp.shell +# ^ constant.other.wildcard.asterisk.shell status="${status#${status%%[![:space:]]*}}" # ^ meta.string.shell string.quoted.double.shell - meta.interpolation # ^^^^^^^^^ meta.string.shell meta.interpolation.parameter.shell - meta.interpolation meta.interpolation @@ -3758,18 +3802,20 @@ status="${status#${status%%[![:space:]]*}}" # ^ keyword.operator.logical.regexp.shell # ^ punctuation.definition.set.begin.regexp.shell # ^^ punctuation.definition.set.end.regexp.shell -# ^ keyword.operator.quantifier.regexp.shell +# ^ constant.other.wildcard.asterisk.shell CURPOS=${CURPOS#*[} -# ^ - keyword.control.regexp +# ^ constant.other.wildcard.asterisk.shell +# ^ - keyword.control.regexp.shell echo "${ROW#*[}" -# ^ - keyword.control.regexp +# ^ constant.other.wildcard.asterisk.shell +# ^ - keyword.control.regexp.shell echo * -# keyword.operator.quantifier.regexp.shell +# ^ constant.other.wildcard.asterisk.shell echo {a,g*} # ^^^^^^ meta.function-call.arguments.shell meta.interpolation.brace.shell # ^ punctuation.section.interpolation.begin.shell # ^ punctuation.separator.sequence.shell -# ^ keyword.operator.quantifier.regexp.shell +# ^ constant.other.wildcard.asterisk.shell # ^ punctuation.section.interpolation.end.shell echo ca{${x/z/t}" "{legs,f${o//a/o}d,f${o:0:1}t},r" "{tires,wh${o//a/e}ls}} # ^ punctuation.section.interpolation.begin.shell @@ -3811,9 +3857,80 @@ echo ca{${x/z/t}" "{legs,f${o//a/o}d,f${o:0:1}t},r" "{tires,wh${o//a/e}ls}} # ^ punctuation.definition.set.begin.regexp.shell # ^ keyword.operator.logical.regexp.shell # ^ punctuation.definition.set.end.regexp.shell -# ^ keyword.operator.quantifier.regexp.shell +# ^ constant.other.wildcard.asterisk.shell # ^ punctuation.definition.group.end.regexp.shell +: @([[] []] [![] [!]] [^[] [^]]) +# ^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell + +: @([-[] [-]] [[-)] []-)] [!-[] [!-]] [^-[] [^-]]) +# ^^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^ - punctuation +# ^^^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^ constant.other.range.regexp.shell +# ^ punctuation.definition.set.end.regexp.shell +# ^^^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^ constant.other.range.regexp.shell +# ^ punctuation.definition.set.end.regexp.shell +# ^^^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^ - punctuation +# ^^^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^^^^ meta.group.regexp.shell meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^ - punctuation + : @([.c.] [.c. ] [[.c.]] [^[.c.]] [[^.c.]]) # ^^^^^ meta.set.regexp.shell # ^ - meta.set @@ -3827,14 +3944,10 @@ echo ca{${x/z/t}" "{legs,f${o//a/o}d,f${o:0:1}t},r" "{tires,wh${o//a/e}ls}} # ^^^^^ meta.set.regexp.shell meta.set.regexp.shell # ^ meta.set.regexp.shell - meta.set meta.set # ^ - meta.set -# ^ meta.set.regexp.shell - meta.set meta.set -# ^^^^^^ meta.set.regexp.shell meta.set.regexp.shell -# ^ meta.set.regexp.shell - meta.set meta.set -# ^ - meta.set +# ^^^^^^^ meta.set.regexp.shell - meta.set meta.set +# ^^ - meta.set # ^ punctuation.definition.set.begin.regexp.shell -# ^ constant.character.collate.regexp.shell punctuation.definition.collate.begin.regexp.shell -# ^ constant.character.collate.regexp.shell - punctuation -# ^ constant.character.collate.regexp.shell punctuation.definition.collate.end.regexp.shell +# ^^^ - constant.character # ^ punctuation.definition.set.end.regexp.shell # ^ punctuation.definition.set.begin.regexp.shell # ^^^^ - constant.character.collate @@ -3847,29 +3960,27 @@ echo ca{${x/z/t}" "{legs,f${o//a/o}d,f${o:0:1}t},r" "{tires,wh${o//a/e}ls}} # ^ punctuation.definition.set.begin.regexp.shell # ^^^ constant.character.collate.regexp.shell # ^^ punctuation.definition.set.end.regexp.shell -# ^^ punctuation.definition.set.begin.regexp.shell -# ^ keyword.operator.logical.regexp.shell -# ^^^ constant.character.collate.regexp.shell -# ^^ punctuation.definition.set.end.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^^^ - keyword - punctuation - constant +# ^ punctuation.definition.set.end.regexp.shell +# ^ - punctuation -: @([=c=] [=c=illegal]) -# ^ punctuation.definition.set.begin.regexp.shell -# ^ constant.character.equivalence-class.regexp.shell punctuation.definition.class.begin.regexp.shell -# ^ constant.character.equivalence-class.regexp.shell - punctuation -# ^ constant.character.equivalence-class.regexp.shell punctuation.definition.class.end.regexp.shell -# ^ punctuation.definition.set.end.regexp.shell -# ^ punctuation.definition.set.begin.regexp.shell -# ^^^^^^^^^^ - constant.character.equivalence-class -# ^ punctuation.definition.set.end.regexp.shell - -: @([:alnum:] [:alnum] [alnum:] [alnum] [:alnum:other]) -# ^ constant.other.posix-class.regexp.shell punctuation.definition.class.begin.regexp.shell -# ^^^^^ constant.other.posix-class.regexp.shell - punctuation -# ^ constant.other.posix-class.regexp.shell punctuation.definition.class.end.regexp.shell -# ^^^^^^ - constant.other.posix-class -# ^^^^^^ - constant.other.posix-class -# ^^^^^ - constant.other.posix-class -# ^^^^^^^^^^^^ - constant.other.posix-class +: @([[=c=]] [[=c=illegal]]) +# ^^ punctuation.definition.set.begin.regexp.shell +# ^ constant.character.equivalence-class.regexp.shell punctuation.definition.class.begin.regexp.shell +# ^ constant.character.equivalence-class.regexp.shell - punctuation +# ^ constant.character.equivalence-class.regexp.shell punctuation.definition.class.end.regexp.shell +# ^^ punctuation.definition.set.end.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^^^^^^^^^ - constant.character.equivalence-class +# ^ punctuation.definition.set.end.regexp.shell +# ^ - punctuation + +: @([[:alnum:]] [[:alnum]] [[alnum:]] [[alnum]] [[:alnum:other]]) +# ^ constant.other.posix-class.regexp.shell punctuation.definition.class.begin.regexp.shell +# ^^^^^ constant.other.posix-class.regexp.shell - punctuation +# ^ constant.other.posix-class.regexp.shell punctuation.definition.class.end.regexp.shell +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant.other.posix-class : *(g[[:${charclass/\}/l}:]]*) #^^ meta.function-call.arguments.shell - meta.group @@ -3878,6 +3989,7 @@ echo ca{${x/z/t}" "{legs,f${o//a/o}d,f${o:0:1}t},r" "{tires,wh${o//a/e}ls}} # ^ keyword.operator.quantifier.regexp.shell # ^ punctuation.definition.group.begin.regexp.shell # ^^ punctuation.definition.set.begin.regexp.shell +# ^^^^^^^^^^^^^^^^^^^ constant.other.posix-class.regexp.shell # ^ punctuation.definition.variable.shell # ^ punctuation.section.interpolation.begin.shell # ^^^^^^^^^ variable.other.readwrite.shell @@ -3886,7 +3998,7 @@ echo ca{${x/z/t}" "{legs,f${o//a/o}d,f${o:0:1}t},r" "{tires,wh${o//a/e}ls}} # ^ keyword.operator.substitution.shell # ^ punctuation.section.interpolation.end.shell # ^^ punctuation.definition.set.end.regexp.shell -# ^ keyword.operator.quantifier.regexp.shell +# ^ constant.other.wildcard.asterisk.shell # ^ punctuation.definition.group.end.regexp.shell : ?([[:alpha:]]|[[:digit:]]|[[:unknwn:]])* @@ -3908,11 +4020,12 @@ echo ca{${x/z/t}" "{legs,f${o//a/o}d,f${o:0:1}t},r" "{tires,wh${o//a/e}ls}} # ^ constant.other.posix-class.regexp.shell punctuation.definition.class.end.regexp.shell # ^^ punctuation.definition.set.end.regexp.shell # ^ keyword.operator.logical.regexp.shell -# ^^ punctuation.definition.set.begin.regexp.shell -# ^^^^^^^^ - constant.other.posix-class -# ^^ punctuation.definition.set.end.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^^^^^^^ - constant.other.posix-class +# ^ punctuation.definition.set.end.regexp.shell +# ^ - punctuation # ^ punctuation.definition.group.end.regexp.shell -# ^ keyword.operator.quantifier.regexp.shell +# ^ constant.other.wildcard.asterisk.shell : @(foo*)* #^^ meta.function-call.arguments.shell - meta.group @@ -3921,9 +4034,9 @@ echo ca{${x/z/t}" "{legs,f${o//a/o}d,f${o:0:1}t},r" "{tires,wh${o//a/e}ls}} # ^ - meta.function-call - meta.group # ^ keyword.operator.quantifier.regexp.shell # ^ punctuation.definition.group.begin.regexp.shell -# ^ keyword.operator.quantifier.regexp.shell +# ^ constant.other.wildcard.asterisk.shell # ^ punctuation.definition.group.end.regexp.shell -# ^ keyword.operator.quantifier.regexp.shell +# ^ constant.other.wildcard.asterisk.shell : +(bar|qux) | wc #^^ meta.function-call.arguments.shell - meta.group @@ -3939,243 +4052,883 @@ echo ca{${x/z/t}" "{legs,f${o//a/o}d,f${o:0:1}t},r" "{tires,wh${o//a/e}ls}} # ^ - keyword.control # ^ punctuation.section.interpolation.end.shell -[[ a == [ ]] +#################################################################### +# Bash pattern matching in test expressions # +#################################################################### + +[[ abc == ?[a-z]? ]] # evaluates to true +# ^ meta.string.regexp.shell - meta.set +# ^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^ meta.string.regexp.shell - meta.set +# ^ - meta.string.regexp +# ^ constant.other.wildcard.questionmark.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^ constant.other.range.regexp.shell +# ^ punctuation.definition.set.end.regexp.shell +# ^ constant.other.wildcard.questionmark.shell + +[[ abc == ??[a-z] ]] # evaluates to true +# ^^ meta.string.regexp.shell - meta.set +# ^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^ - meta.string.regexp +# ^^ constant.other.wildcard.questionmark.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^ constant.other.range.regexp.shell +# ^ punctuation.definition.set.end.regexp.shell + +[[ abc == [a-z]?? ]] # evaluates to true +# ^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^ meta.string.regexp.shell - meta.set +# ^ - meta.string.regexp +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^ constant.other.range.regexp.shell +# ^ punctuation.definition.set.end.regexp.shell +# ^^ constant.other.wildcard.questionmark.shell + +[[ abc == *[a-z] ]] # evaluates to true +# ^ meta.string.regexp.shell - meta.set +# ^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^ - meta.string.regexp +# ^ constant.other.wildcard.asterisk.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^ constant.other.range.regexp.shell +# ^ punctuation.definition.set.end.regexp.shell + +[[ abc == ?(?[a-z]?) ]] # evaluates to true +# ^ meta.string.regexp.shell - meta.group +# ^^ meta.string.regexp.shell meta.group.regexp.shell - meta.set +# ^^^^^ meta.string.regexp.shell meta.group.regexp.shell meta.set.regexp.shell +# ^^ meta.string.regexp.shell meta.group.regexp.shell - meta.set +# ^ - meta.string.regexp +# ^ keyword.operator.quantifier.regexp.shell +# ^ punctuation.definition.group.begin.regexp.shell +# ^ constant.other.wildcard.questionmark.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^ constant.other.range.regexp.shell +# ^ punctuation.definition.set.end.regexp.shell +# ^ constant.other.wildcard.questionmark.shell + +[[ abc == ^abc|bca$ ]] +#^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^^^^^^ meta.string.regexp.shell - keyword +# ^^ support.function.test.end.shell + +[[ a\$b*c == a'$b*'? ]] +#^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^^^^ meta.string.regexp.shell +# ^ punctuation.definition.literal.begin.shell +# ^^^ - constant - keyword - variable +# ^ punctuation.definition.literal.end.shell +# ^ constant.other.wildcard.questionmark.shell + +[[ a"$bc*"c == *"$bc*"c ]] +#^^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^^^^^ meta.string.regexp.shell +# ^ constant.other.wildcard.asterisk.shell +# ^ punctuation.definition.literal.begin.shell +# ^^^ variable.other.readwrite.shell +# ^ - constant - keyword +# ^ punctuation.definition.literal.end.shell + +[[ $foo == !(foo|bar|???|*|'?'|'*') ]] +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^ meta.string.regexp.shell +# ^^^^^^^^^^^^^^^^^^^^^^^ meta.string.regexp.shell meta.group.regexp.shell +# ^ keyword.operator.quantifier.regexp.shell +# ^ punctuation.definition.group.begin.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^^^ constant.other.wildcard.questionmark.shell +# ^ keyword.operator.logical.regexp.shell +# ^ constant.other.wildcard.asterisk.shell +# ^ keyword.operator.logical.regexp.shell +# ^ punctuation.definition.literal.begin.shell +# ^ punctuation.definition.literal.end.shell +# ^ keyword.operator.logical.regexp.shell +# ^ punctuation.definition.literal.begin.shell +# ^ punctuation.definition.literal.end.shell +# ^ punctuation.definition.group.end.regexp.shell +# ^^ support.function.test.end.shell + +[[ ( $foo == * +#^^ meta.conditional.shell - meta.group +# ^^^^^^^^^^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^ meta.conditional.shell meta.group.shell meta.string.regexp.shell +# ^ meta.conditional.shell meta.group.shell - meta.string.regexp invalid.illegal.unexpected-token.shell + +[[ ( $foo == *\ + [^0-9]? ) ]] # note: line continuation is only valid without leading whitespace, but we ignore it +# <- meta.conditional.shell meta.group.shell meta.string.regexp.shell +#^^ meta.conditional.shell meta.group.shell meta.string.regexp.shell - meta.set +# ^^^^^^ meta.conditional.shell meta.group.shell meta.string.regexp.shell meta.set.regexp.shell +# ^^ meta.conditional.shell meta.group.shell meta.string.regexp.shell - meta.set +# ^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^^ meta.conditional.shell - meta.group +# ^^ support.function.test.end.shell + +[[ ( $foo == ? ]] +#^^ meta.conditional.shell - meta.group +# ^^^^^^^^^^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^ meta.conditional.shell meta.group.shell meta.string.regexp.shell +# ^^^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^ invalid.illegal.unexpected-token.shell + +[[ ( $foo == ? ]] + [^0-9]+ ) ]] +# <- - meta.conditional +#^^^^^^^^^^^^^^ - meta.conditional + +[[ $foo == +( ]] +#^^^^^^^^^^ meta.conditional.shell - meta.string.regexp - meta.group +# ^ meta.conditional.shell meta.string.regexp.shell - meta.group +# ^^^^^ meta.conditional.shell meta.string.regexp.shell meta.group.regexp.shell +# ^ keyword.operator.quantifier.regexp.shell +# ^ punctuation.definition.group.begin.regexp.shell +# ^^ - punctuation + [!0-9]+ ) ]] +# <- meta.conditional.shell meta.string.regexp.shell meta.group.regexp.shell +#^^ meta.conditional.shell meta.string.regexp.shell meta.group.regexp.shell - meta.set +# ^^^^^^ meta.conditional.shell meta.string.regexp.shell meta.group.regexp.shell meta.set.regexp.shell +# ^^^ meta.conditional.shell meta.string.regexp.shell meta.group.regexp.shell - meta.set +# ^^^ - meta.string.regexp +# ^ punctuation.definition.set.begin.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^^^ constant.other.range.regexp.shell +# ^ punctuation.definition.set.end.regexp.shell +# ^ - constant - keyword +# ^ punctuation.definition.group.end.regexp.shell +# ^^ support.function.test.end.shell + +#################################################################### +# POSIX extended regular expression pattern matching # +#################################################################### + +[[ a =~ [ ]] #^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^ meta.pattern.regexp.shell - meta.set.regexp -# ^^^ - meta.pattern.regexp +#^^^^^^^ - meta.string.regexp.shell +# ^ meta.string.regexp.shell - meta.set +# ^^^ - meta.string.regexp.shell # ^^ support.function.test.end.shell -[[ a == ] ]] +[[ a =~ ] ]] #^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^ meta.pattern.regexp.shell - meta.set.regexp -# ^^^ - meta.pattern.regexp +#^^^^^^^ - meta.string.regexp.shell +# ^ meta.string.regexp.shell - meta.set +# ^^^ - meta.string.regexp.shell # ^^ support.function.test.end.shell -[[ a == [\]] ]] -#^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^^^^ meta.pattern.regexp.shell meta.set.regexp.shell -# ^^^ - meta.pattern.regexp +[[ a =~ [[] ]] +#^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [^[] ]] +#^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^ - punctuation +# ^ punctuation.definition.set.end.regexp.shell # ^^ support.function.test.end.shell -[[ a == [^\]] ]] -#^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^^^^^ meta.pattern.regexp.shell meta.set.regexp.shell -# ^^^ - meta.pattern.regexp +[[ a =~ [![] ]] # ! is not an operator in ERE +#^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^ - keyword - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [\[] ]] +#^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [^\[] ]] +#^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell # ^^ support.function.test.end.shell -[[ a == [\\\]] ]] -#^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^^^^^^ meta.pattern.regexp.shell meta.set.regexp.shell -# ^^^ - meta.pattern.regexp +[[ a =~ []] ]] +#^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ []-[] ]] +#^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^ constant.other.range.regexp.shell +# ^ punctuation.definition.set.end.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [^]] ]] +#^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [!]] ]] # ! is not an operator in ERE +#^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^ meta.string.regexp.shell - meta.set +# ^^^ - meta.string.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ - keyword - punctuation +# ^ punctuation.definition.set.end.regexp.shell +# ^ - punctuation +# ^^ support.function.test.end.shell + +[[ a =~ [\]] ]] +#^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [^\]] ]] +#^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [\\\]] ]] +#^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell # ^^ support.function.test.end.shell -[[ a == [\\\] ]] -#^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^^^^^ meta.pattern.regexp.shell - meta.set.regexp -# ^^^ - meta.pattern.regexp +[[ a =~ [\\\] ]] +#^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^ meta.string.regexp.shell - meta.set +# ^^^ - meta.string.regexp.shell # ^^ support.function.test.end.shell -[[ a == [[:alpha:] ]] -#^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^ meta.pattern.regexp.shell - meta.set.regexp -# ^^^^^^^^^ meta.pattern.regexp.shell meta.set.regexp.shell -# ^^^ - meta.pattern.regexp +[[ a =~ [[:alpha: ]] +#^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^^ meta.string.regexp.shell - meta.set +# ^^^ - meta.string.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [[:alpha:] ]] +#^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^ meta.string.regexp.shell - meta.set +# ^^^^^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell # ^^ support.function.test.end.shell -[[ a == [[:alpha:]] ]] -#^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^^^^^^^^^^^ meta.pattern.regexp.shell meta.set.regexp.shell -# ^^^ - meta.pattern.regexp +[[ a =~ [[:alpha:]][^[:alpha:]][[^:alpha:]] ]] +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^ meta.string.regexp.shell - meta.set +# ^^^ - meta.string.regexp.shell +# ^^ punctuation.definition.set.begin.regexp.shell +# ^ punctuation.definition.class.begin.regexp.shell +# ^^^^^^^ constant.other.posix-class.regexp.shell +# ^ punctuation.definition.class.end.regexp.shell +# ^^ punctuation.definition.set.end.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ keyword.operator.logical.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^^^^^ constant.other.posix-class.regexp.shell +# ^^ punctuation.definition.set.end.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^^^^^^^^^ - constant.other.posix-class +# ^ punctuation.definition.set.end.regexp.shell +# ^ - punctuation +# ^^ support.function.test.end.shell + +[[ a =~ [[:${posix}:]][[:$foo:]] ]] +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^ meta.string.regexp.shell meta.set.regexp.shell - meta.interpolation +# ^^^^^^^^ meta.string.regexp.shell meta.set.regexp.shell meta.set.regexp.shell meta.interpolation.parameter.shell +# ^^^^^^ meta.string.regexp.shell meta.set.regexp.shell - meta.interpolation +# ^^^^ meta.string.regexp.shell meta.set.regexp.shell meta.set.regexp.shell meta.interpolation.parameter.shell +# ^^^ meta.string.regexp.shell meta.set.regexp.shell - meta.interpolation +# ^^^ - meta.string.regexp.shell +# ^^ support.function.test.end.shell +# ^^ punctuation.definition.set.begin.regexp.shell +# ^^^^^^^^^^ meta.string.regexp.shell meta.set.regexp.shell meta.set.regexp.shell constant.other.posix-class.regexp.shell +# ^ punctuation.definition.class.begin.regexp.shell +# ^ punctuation.definition.variable.shell +# ^ punctuation.section.interpolation.begin.shell +# ^^^^^ variable.other.readwrite.shell +# ^ punctuation.section.interpolation.end.shell +# ^ meta.set.regexp.shell constant.other.posix-class.regexp.shell punctuation.definition.class.end.regexp.shell +# ^^ punctuation.definition.set.end.regexp.shell +# ^^ punctuation.definition.set.begin.regexp.shell +# ^ punctuation.definition.class.begin.regexp.shell +# ^^^^ variable.other.readwrite.shell +# ^ punctuation.definition.class.end.regexp.shell +# ^^ punctuation.definition.set.end.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [[=a=]] ]] +#^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^^ punctuation.definition.set.begin.regexp.shell +# ^ punctuation.definition.class.begin.regexp.shell +# ^^^ constant.character.equivalence-class.regexp.shell +# ^ punctuation.definition.class.end.regexp.shell +# ^^ punctuation.definition.set.end.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [[=$a=]] ]] +#^^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^^ punctuation.definition.set.begin.regexp.shell +# ^ punctuation.definition.class.begin.regexp.shell +# ^^^^ constant.character.equivalence-class.regexp.shell +# ^^ meta.interpolation.parameter.shell variable.other.readwrite.shell +# ^ punctuation.definition.class.end.regexp.shell +# ^^ punctuation.definition.set.end.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [[.ch.]] ]] +#^^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^^ punctuation.definition.set.begin.regexp.shell +# ^ punctuation.definition.collate.begin.regexp.shell +# ^^^^ constant.character.collate.regexp.shell +# ^ punctuation.definition.collate.end.regexp.shell +# ^^ punctuation.definition.set.end.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [[.dollar-sign.]] ]] +#^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^^^^^^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^^ punctuation.definition.set.begin.regexp.shell +# ^ punctuation.definition.collate.begin.regexp.shell +# ^^^^^^^^^^^^^ constant.character.collate.regexp.shell +# ^ punctuation.definition.collate.end.regexp.shell +# ^^ punctuation.definition.set.end.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [[.${equiv}.]] ]] +#^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^^^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^^ punctuation.definition.set.begin.regexp.shell +# ^ punctuation.definition.collate.begin.regexp.shell +# ^^^^^^^^^^ constant.character.collate.regexp.shell +# ^^^^^^^^ meta.interpolation.parameter.shell +# ^ punctuation.definition.collate.end.regexp.shell +# ^^ punctuation.definition.set.end.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [[.alpha=]] ]] +#^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^^^ meta.string.regexp.shell meta.set.regexp.shell - constant +# ^ meta.string.regexp.shell - meta.set +# ^^^ - meta.string.regexp.shell # ^^ support.function.test.end.shell -[[ a == [[:alpha: ]] -#^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^^^^^^^^^ meta.pattern.regexp.shell - meta.set.regexp -# ^^^ - meta.pattern.regexp -# ^^ support.function.test.end.shell +[[ a =~ [-9][0-][$0-9][0-$9] ]] +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^^^^^^^^^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^ - constant - operator +# ^^ meta.interpolation.parameter.shell variable.other.readwrite.shell +# ^^ constant.other.range.regexp.shell +# ^^ constant.other.range.regexp.shell +# ^^ meta.interpolation.parameter.shell variable.other.readwrite.shell +# ^^^ - meta.string.regexp.shell +# ^^ support.function.test.end.shell + +[[ a =~ [${ bar }] ]] +#^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^^^^^^ meta.interpolation.parameter.shell +# ^^^ - meta.string.regexp.shell +# ^^ support.function.test.end.shell -[[ a == { ]] +[[ a =~ { ]] #^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^ meta.pattern.regexp.shell - meta.interpolation -# ^^^ - meta.pattern.regexp +#^^^^^^^ - meta.string.regexp.shell +# ^ meta.string.regexp.shell - meta.interpolation +# ^^^ - meta.string.regexp.shell # ^^ support.function.test.end.shell -[[ a == } ]] +[[ a =~ } ]] #^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^ meta.pattern.regexp.shell - meta.interpolation -# ^^^ - meta.pattern.regexp +#^^^^^^^ - meta.string.regexp.shell +# ^ meta.string.regexp.shell - meta.interpolation +# ^^^ - meta.string.regexp.shell # ^^ support.function.test.end.shell -[[ a == \${* ]] +[[ a =~ \${* ]] #^^^^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^^^^ meta.pattern.regexp.shell - meta.interpolation -# ^^^ - meta.pattern.regexp -# ^^ constant.character.escape.shell +#^^^^^^^ - meta.string.regexp.shell +# ^^^^ meta.string.regexp.shell - meta.interpolation +# ^^^ - meta.string.regexp.shell +# ^^ constant.character.escape # ^ keyword.operator.quantifier.regexp.shell -[[ a == ${* ]]} ]] +[[ a =~ ${* ]]} ]] #^^^^^^^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^^^^^^^ meta.pattern.regexp.shell meta.interpolation.parameter.shell -# ^^^ - meta.pattern.regexp +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^ meta.string.regexp.shell meta.interpolation.parameter.shell +# ^^^ - meta.string.regexp.shell # ^ punctuation.definition.variable.shell # ^ punctuation.section.interpolation.begin.shell # ^^ - support.function # ^ punctuation.section.interpolation.end.shell # ^^ support.function.test.end.shell -[[ a == %1* ]] +[[ a =~ %1* ]] #^^^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^^ meta.pattern.regexp.shell meta.interpolation.job.shell variable.language.job.shell -# ^ meta.pattern.regexp.shell keyword.operator.quantifier.regexp.shell -# ^^^ - meta.pattern.regexp +#^^^^^^^ - meta.string.regexp.shell +# ^^^ meta.string.regexp.shell - meta.interpolation +# ^ keyword.operator.quantifier.regexp.shell +# ^^^ - meta.string.regexp.shell -[[ a == [abc[]* ]] +[[ a =~ [abc[]* ]] #^^^^^^^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^ - meta.pattern.regexp -# ^^^^^^^ meta.pattern.regexp.shell - meta.interpolation -# ^^^ - meta.pattern.regexp +#^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^ meta.string.regexp.shell - meta.interpolation +# ^^^ - meta.string.regexp.shell # ^ punctuation.definition.set.begin.regexp.shell # ^ - keyword.control # ^ punctuation.definition.set.end.regexp.shell # ^ keyword.operator.quantifier.regexp.shell -[[ "${foo}" == bar*baz ]] +[[ "${foo}" =~ bar*baz ]] #^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^^^^^^^^ - meta.pattern.regexp -# ^^^^^^^ meta.pattern.regexp.shell - meta.interpolation -# ^^^ - meta.pattern.regexp +#^^^^^^^^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^ meta.string.regexp.shell - meta.interpolation +# ^^^ - meta.string.regexp.shell # ^^ keyword.operator.comparison.shell # ^ keyword.operator.quantifier.regexp.shell -[[ $str != ^$'\t' ]] +[[ "${foo}" =~ bar|baz ]] +#^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +#^^^^^^^^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^ meta.string.regexp.shell - meta.interpolation +# ^^^ - meta.string.regexp.shell +# ^^ keyword.operator.comparison.shell +# ^ keyword.operator.alternation.regexp.shell + +[[ $foo =~ ^$'\t' ]] #^^^^^^^^^^^^^^^^^^^ meta.conditional.shell # ^ - meta.conditional -#^^^^^^^^^^ - meta.pattern.regexp -# ^^^^^^ meta.pattern.regexp.shell - meta.interpolation -# ^^^ - meta.pattern.regexp +#^^^^^^^^^^ - meta.string.regexp.shell +# ^^^^^^ meta.string.regexp.shell - meta.interpolation +# ^^^ - meta.string.regexp.shell # ^^^^ meta.interpolation.parameter.shell variable.other.readwrite.shell # ^^ keyword.operator.comparison.shell -[[ $str =~ ^abc$var$ ]] +[[ $foo =~ ^abc$var$ ]] #^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell # ^ - meta.conditional -#^^^^^^^^^^ - meta.pattern.regexp +#^^^^^^^^^^ - meta.string.regexp.shell # ^^^^ meta.interpolation.parameter.shell variable.other.readwrite.shell # ^^ keyword.operator.comparison.shell -# ^^^^ meta.pattern.regexp.shell - meta.interpolation -# ^^^^ meta.pattern.regexp.shell meta.interpolation.parameter.shell -# ^ meta.pattern.regexp.shell - meta.interpolation -# ^^^ - meta.pattern.regexp - -[[ $line =~ [[:space:]]*?(a)b ]] -#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell -# ^ - meta.conditional -#^^^^^^^^^^^ - meta.pattern.regexp.shell -# ^^^^^^^^^^^^^^^^^ meta.pattern.regexp.shell -# ^^^^^^^^^^^ meta.set.regexp.shell -# ^^^ meta.group.regexp.shell -# ^^^ - meta.pattern.regexp.shell -# ^^^^^ meta.interpolation.parameter.shell variable.other.readwrite.shell -# ^^ keyword.operator.comparison.shell -# ^^ punctuation.definition.set.begin.regexp.shell -# ^^^^^^^ constant.other.posix-class.regexp.shell -# ^^ punctuation.definition.set.end.regexp.shell -# ^^ keyword.operator.quantifier.regexp.shell -# ^ punctuation.definition.group.begin.regexp.shell -# ^ punctuation.definition.group.end.regexp.shell - -[[ $line =~ ^0[1-9]$ ]] -#^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell -# ^ - meta.conditional -#^^^^^^^^^^^ - meta.pattern.regexp.shell -# ^^^^^^^^ meta.pattern.regexp.shell -# ^^^ - meta.pattern.regexp.shell - -[[ ! ($line =~ ^0[1-9]$) ]] +# ^^^^ meta.string.regexp.shell - meta.interpolation +# ^^^^ meta.string.regexp.shell meta.interpolation.parameter.shell +# ^ meta.string.regexp.shell - meta.interpolation +# ^^^ - meta.string.regexp.shell + +[[ $foo =~ [[:space:]]*?(a)b ]] +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^ - meta.conditional +#^^^^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^^^^^^^^^^ meta.string.regexp.shell +# ^^^^^^^^^^^ meta.set.regexp.shell +# ^^^ meta.group.regexp.shell +# ^^^ - meta.string.regexp.shell +# ^^^^ meta.interpolation.parameter.shell variable.other.readwrite.shell +# ^^ keyword.operator.comparison.shell +# ^^ punctuation.definition.set.begin.regexp.shell +# ^^^^^^^ constant.other.posix-class.regexp.shell +# ^^ punctuation.definition.set.end.regexp.shell +# ^^ keyword.operator.quantifier.regexp.shell +# ^ punctuation.section.group.begin.regexp.shell +# ^ punctuation.section.group.end.regexp.shell + +[[ $foo =~ ^0[1-9]$ ]] +#^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^ - meta.conditional +#^^^^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^ meta.string.regexp.shell +# ^ keyword.control.anchor.regexp.shell +# ^ keyword.control.anchor.regexp.shell +# ^^^ - meta.string.regexp.shell + +[[ $foo =~ ^0[1-9]{2,3}$ ]] +#^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^ - meta.conditional +#^^^^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^^^^^^ meta.string.regexp.shell +# ^ keyword.control.anchor.regexp.shell +# ^^^^^ keyword.operator.quantifier.regexp.shell +# ^ keyword.control.anchor.regexp.shell +# ^^^ - meta.string.regexp.shell + +[[ ! ($foo =~ ^0[1-9]$) ]] # <- meta.conditional.shell - meta.group #^^^^ meta.conditional.shell - meta.group -# ^^^^^^^^^^ meta.conditional.shell meta.group.shell - meta.pattern -# ^^^^^^^^ meta.conditional.shell meta.group.shell meta.pattern.regexp.shell -# ^ meta.conditional.shell meta.group.shell - meta.pattern -# ^^^ meta.conditional.shell - meta.group -# ^ - meta.conditional - meta.group +# ^^^^^^^^^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^^^^^^^ meta.conditional.shell meta.group.shell meta.string.regexp.shell +# ^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^^ meta.conditional.shell - meta.group +# ^ - meta.conditional - meta.group -[[ ! ($line =~ ^(\([0-9]+)$) ]] +[[ ! ($foo =~ ^(\([0-9]+)$) ]] # <- meta.conditional.shell - meta.group #^^^^ meta.conditional.shell - meta.group -# ^^^^^^^^^^ meta.conditional.shell meta.group.shell - meta.pattern -# ^^^^^^^^^^^^ meta.conditional.shell meta.group.shell meta.pattern.regexp.shell -# ^ meta.conditional.shell meta.group.shell - meta.pattern -# ^^^ meta.conditional.shell - meta.group -# ^ - meta.conditional - meta.group +# ^^^^^^^^^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^^^^^^^^^^^ meta.conditional.shell meta.group.shell meta.string.regexp.shell +# ^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^^ meta.conditional.shell - meta.group +# ^ - meta.conditional - meta.group # <- support.function.test.begin.shell #^ support.function.test.begin.shell # ^ keyword.operator.logical.shell # ^ punctuation.section.group.begin.shell -# ^^^^^ variable.other.readwrite.shell -# ^^ keyword.operator.comparison.shell -# ^^^^^^^^ meta.group.regexp.shell -# ^ punctuation.definition.group.begin.regexp.shell -# ^^ constant.character.escape.shell -# ^^^^^ meta.set.regexp.shell -# ^ punctuation.definition.set.begin.regexp.shell +# ^^^^ variable.other.readwrite.shell +# ^^ keyword.operator.comparison.shell +# ^^^^^^^^ meta.group.regexp.shell +# ^ punctuation.section.group.begin.regexp.shell +# ^^ constant.character.escape +# ^^^^^ meta.set.regexp.shell +# ^ punctuation.definition.set.begin.regexp. +# ^ punctuation.definition.set.end.regexp.shell +# ^ keyword.operator.quantifier.regexp.shell +# ^ punctuation.section.group.end.regexp.shell +# ^ punctuation.section.group.end.shell +# ^^ support.function.test.end.shell + +[[ ( $foo =~ ^ +#^^ meta.conditional.shell - meta.group +# ^^^^^^^^^^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^ meta.conditional.shell meta.group.shell meta.string.regexp.shell +# ^ meta.conditional.shell meta.group.shell - meta.string.regexp invalid.illegal.unexpected-token.shell + +[[ ( $foo =~ ^\ + [^0-9]+ ) ]] +# <- meta.conditional.shell meta.group.shell meta.string.regexp.shell +#^^^^^^^^^^ meta.conditional.shell meta.group.shell meta.string.regexp.shell +# ^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^^ meta.conditional.shell - meta.group +# ^^ support.function.test.end.shell + +[[ ( $foo =~ ^ ]] +#^^ meta.conditional.shell - meta.group +# ^^^^^^^^^^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^ meta.conditional.shell meta.group.shell meta.string.regexp.shell +# ^^^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^ invalid.illegal.unexpected-token.shell + +[[ ( $foo =~ ^ ]] + [^0-9]+ ) ]] +# <- - meta.conditional +#^^^^^^^^^^^^^^ - meta.conditional + +[[ $foo =~ ( ]] +#^^^^^^^^^^ meta.conditional.shell - meta.string.regexp - meta.group +# ^^^^^ meta.conditional.shell meta.string.regexp.shell meta.group.regexp.shell +# ^ punctuation.section.group.begin.regexp.shell +# ^^ - punctuation + [^0-9]+ ) ]] +# <- meta.conditional.shell meta.string.regexp.shell meta.group.regexp.shell +#^^^^^^^^^^^ meta.conditional.shell meta.string.regexp.shell meta.group.regexp.shell +# ^^^ - meta.string.regexp +# ^^ support.function.test.end.shell + +[[ $foo =~ ) ]] +#^^^^^^^^^^^^^^ meta.conditional.shell +# ^ meta.string.regexp.shell invalid.illegal.stray.regexp.shell + +[[ $foo =~ ( ) ]] +#^^^^^^^^^^ meta.conditional.shell - meta.string.regexp - meta.group +# ^^^ meta.conditional.shell meta.string.regexp.shell meta.group.regexp.shell +# ^^^ meta.conditional.shell - meta.string.regexp - meta.group +# ^ - meta.conditional + +[[ $foo =~ ( [ ) ]] +#^^^^^^^^^^ meta.conditional.shell - meta.string.regexp - meta.group +# ^^^^^ meta.conditional.shell meta.string.regexp.shell meta.group.regexp.shell +# ^^^ meta.conditional.shell - meta.string.regexp - meta.group +# ^ - meta.conditional + +[[ $foo =~ ( ] ) ]] +#^^^^^^^^^^ meta.conditional.shell - meta.string.regexp - meta.group +# ^^^^^ meta.conditional.shell meta.string.regexp.shell meta.group.regexp.shell +# ^^^ meta.conditional.shell - meta.string.regexp - meta.group +# ^ - meta.conditional + +[[ $foo =~ ( [\\\] ) ]] +#^^^^^^^^^^ meta.conditional.shell - meta.string.regexp - meta.group +# ^^^^^^^^^ meta.conditional.shell meta.string.regexp.shell meta.group.regexp.shell +# ^^^ meta.conditional.shell - meta.string.regexp - meta.group +# ^ - meta.conditional + +[[ ( $foo =~ [\\\] ) ]] +#^^ meta.conditional.shell - meta.group +# ^^^^^^^^^^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^^^^^ meta.conditional.shell meta.group.shell meta.string.regexp.shell +# ^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^^ meta.conditional.shell - meta.group - meta.string.regexp +# ^ - meta.conditional + +[[ ( $foo =~ ([\\\])) ]] +#^^ meta.conditional.shell - meta.group +# ^^^^^^^^^^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^^^^^^ meta.conditional.shell meta.group.shell meta.string.regexp.shell meta.group.regexp.shell +# ^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^^ meta.conditional.shell - meta.group - meta.string.regexp +# ^ - meta.conditional + +[[ $foo =~ (?x) ]] +#^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^ meta.string.regexp.shell meta.group.regexp.shell +# ^ punctuation.section.group.begin.regexp.shell +# ^ invalid.illegal.unexpected-quantifier.regexp.shell +# ^ punctuation.section.group.end.regexp.shell + +[[ $foo =~ (?:bar) ]] +#^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^^^^ meta.string.regexp.shell meta.group.regexp.shell +# ^ punctuation.section.group.begin.regexp.shell +# ^ invalid.illegal.unexpected-quantifier.regexp.shell +# ^ punctuation.section.group.end.regexp.shell + +[[ $foo =~ (?i:bar) ]] +#^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^^^^^ meta.string.regexp.shell meta.group.regexp.shell +# ^ punctuation.section.group.begin.regexp.shell +# ^ invalid.illegal.unexpected-quantifier.regexp.shell +# ^ punctuation.section.group.end.regexp.shell + +[[ ' foo ' =~ ( foo ) ]] # evaluates to true +#^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^^^^ meta.string.shell string.quoted.single.shell +# ^^ keyword.operator.comparison.shell +# ^^^^^^^ meta.string.regexp.shell meta.group.regexp.shell +# ^ punctuation.section.group.begin.regexp.shell +# ^ punctuation.section.group.end.regexp.shell +# ^^ support.function.test.end.shell + +[[ ' foo ' =~ ([ ]foo[ ]) ]] # evaluates to true +#^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^^^^ meta.string.shell string.quoted.single.shell +# ^ meta.string.regexp.shell meta.group.regexp.shell - meta.set +# ^^^ meta.string.regexp.shell meta.group.regexp.shell meta.set.regexp.shell +# ^^^ meta.string.regexp.shell meta.group.regexp.shell - meta.set +# ^^^ meta.string.regexp.shell meta.group.regexp.shell meta.set.regexp.shell +# ^ meta.string.regexp.shell meta.group.regexp.shell - meta.set +# ^^ keyword.operator.comparison.shell +# ^ punctuation.section.group.begin.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell +# ^ punctuation.definition.set.end.regexp.shell +# ^ punctuation.definition.set.begin.regexp.shell # ^ punctuation.definition.set.end.regexp.shell -# ^ keyword.operator.quantifier.regexp.shell -# ^ punctuation.definition.group.end.regexp.shell -# ^ punctuation.section.group.end.shell -# ^^ support.function.test.end.shell +# ^ punctuation.section.group.end.regexp.shell +# ^^ support.function.test.end.shell [[ foo =~ ^foo//:/[}] ]] #^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell -#^^^^^^^^^ - meta.pattern.regexp.shell -# ^^^^^^^^ meta.pattern.regexp.shell - meta.set -# ^^^ meta.pattern.regexp.shell meta.set.regexp.shell -# ^^^ - meta.pattern.regexp.shell +#^^^^^^^^^ - meta.string.regexp.shell +# ^^^^^^^^ meta.string.regexp.shell - meta.set +# ^^^ meta.string.regexp.shell meta.set.regexp.shell +# ^^^ - meta.string.regexp.shell # ^^ keyword.operator.comparison.shell # ^ punctuation.definition.set.begin.regexp.shell # ^ punctuation.definition.set.end.regexp.shell # ^^ support.function.test.end.shell -[[ ' foobar' == [\ ]foo* ]] +[[ foo =~ ^[0-9]+\.[0-9]+(([ab]|rc)[0-9]+)?$ ]] +# ^ meta.group.regexp.shell - meta.group meta.group +# ^^^^^^^^^ meta.group.regexp.shell meta.group.regexp.shell +# ^^^^^^^ meta.group.regexp.shell - meta.group meta.group +# ^^ punctuation.section.group.begin.regexp.shell +# ^ punctuation.section.group.end.regexp.shell +# ^ punctuation.section.group.end.regexp.shell + +[[ ' foobar' =~ [\ ]foo* ]] #^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell # ^ - meta.conditional -#^^^^^^^^^^^^^^^ - meta.pattern.regexp.shell +#^^^^^^^^^^^^^^^ - meta.string.regexp.shell # ^^^^ meta.set.regexp.shell -# ^^^^^^^^ meta.pattern.regexp.shell -# ^^^ - meta.pattern.regexp.shell +# ^^^^^^^^ meta.string.regexp.shell +# ^^^ - meta.string.regexp.shell # ^ punctuation.definition.set.begin.regexp.shell -# ^^ constant.character.escape.shell +# ^^ constant.character.escape # ^ punctuation.definition.set.end.regexp.shell # ^ keyword.operator.quantifier.regexp.shell +[[ a\$bc =~ ^a'$b'c$ ]] +#^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^^^^^ meta.string.regexp.shell - variable +# ^ keyword.control.anchor.regexp.shell +# ^ punctuation.definition.literal.begin.shell +# ^ punctuation.definition.literal.end.shell +# ^ keyword.control.anchor.regexp.shell + +[[ a"$bc"c =~ ^a"$bc"c$ ]] +#^^^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^^^^^^ meta.string.regexp.shell +# ^ keyword.control.anchor.regexp.shell +# ^ punctuation.definition.literal.begin.shell +# ^^^ variable.other.readwrite.shell +# ^ punctuation.definition.literal.end.shell +# ^ keyword.control.anchor.regexp.shell + [[ '-e' == -e ]] # -e undergoes pattern matching on the right # ^^^^ meta.string.shell string.quoted.single.shell # ^^ keyword.operator.comparison.shell -# ^^ meta.pattern.regexp.shell - variable.parameter +# ^^ meta.conditional.shell meta.string.regexp.shell - variable [[ -e == -e ]] # a syntax error in bash but allowed in zsh # ^^ - variable.parameter.option # ^^ keyword.operator.comparison.shell -# ^^ meta.pattern.regexp.shell - variable.parameter +# ^^ meta.conditional.shell meta.string.regexp.shell - variable echo '([^.[:space:]]+) Class::method()' # colon not scoped as path separator # ^^^^^^^^^^^^^^^^^^^^^ string.quoted.single - punctuation.separator.sequence +#################################################################### +# 6.4 Bash Conditional Expressions # +#################################################################### + +[ ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^ meta.conditional.shell +# ^ support.function.test.end.shell + +[ -a file ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^ meta.conditional.shell + +[ -v varname ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^^^^ meta.conditional.shell + +[ file1 -ef file2 ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^^ meta.string.shell string.unquoted.shell +# ^^^ keyword.operator.comparison.shell +# ^^^^^ meta.string.shell string.unquoted.shell +# ^ support.function.test.end.shell + +[ file1 -nt file2 ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^^ meta.string.shell string.unquoted.shell +# ^^^ keyword.operator.comparison.shell +# ^^^^^ meta.string.shell string.unquoted.shell +# ^ support.function.test.end.shell + +[ file1 -ot file2 ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^^ meta.string.shell string.unquoted.shell +# ^^^ keyword.operator.comparison.shell +# ^^^^^ meta.string.shell string.unquoted.shell +# ^ support.function.test.end.shell + +[ ! str != str ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^^^^^^ meta.conditional.shell +# ^ keyword.operator.logical.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^^ keyword.operator.comparison.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^ support.function.test.end.shell + +[ str != str ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^^^^ meta.conditional.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^^ keyword.operator.comparison.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^ support.function.test.end.shell + +[ str == str ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^^^^ meta.conditional.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^^ keyword.operator.comparison.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^ support.function.test.end.shell + +[ str =~ str ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^^^^ meta.conditional.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^^ invalid.illegal.operator.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^ support.function.test.end.shell + +[ str = str ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^^^ meta.conditional.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^ keyword.operator.comparison.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^ support.function.test.end.shell + + +[ str < str ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^^^ meta.conditional.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^ keyword.operator.comparison.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^ support.function.test.end.shell + +[ str > str ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^^^ meta.conditional.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^ keyword.operator.comparison.shell +# ^^^ meta.string.shell string.unquoted.shell +# ^ support.function.test.end.shell + +[ $arg -lt 2 ] +# <- meta.conditional.shell support.function.test.begin.shell +#^^^^^^^^^^^^^ meta.conditional.shell +# ^^^^ variable.other.readwrite.shell +# ^^^ keyword.operator.comparison.shell +# ^ meta.number.integer.decimal.shell constant.numeric.value.shell +# ^ support.function.test.end.shell + #################################################################### # Bash Numeric Constants # #################################################################### @@ -4764,19 +5517,37 @@ if [[ expr && ( expr || expr ) ]] ; then cmd ; fi # ^^ support.function.test.end.shell # ^ punctuation.terminator.statement.shell -if [[ $- != *i* ]] ; then echo shell is not interactive; fi +[[ ! ($line == ^0[1-9]$) ]] +# <- meta.conditional.shell - meta.group +#^^^^ meta.conditional.shell - meta.group +# ^^^^^^^^^^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^^^^^^^ meta.conditional.shell meta.group.shell meta.string.regexp.shell +# ^ meta.conditional.shell meta.group.shell - meta.string +# ^^^ meta.conditional.shell - meta.group +# + +[[ ! ($line != \() ]] +# <- meta.conditional.shell - meta.group +#^^^^ meta.conditional.shell - meta.group +# ^^^^^^^^^^ meta.conditional.shell meta.group.shell - meta.string.regexp +# ^^ meta.conditional.shell meta.group.shell meta.string.regexp.shell constant.character.escape.shell +# ^ meta.conditional.shell meta.group.shell - meta.string +# ^^^ meta.conditional.shell - meta.group +# + +if [[ $- =~ *i* ]] ; then echo shell is not interactive; fi #^ keyword.control.conditional.if.shell # ^^^^^^^^^^^^^^^ meta.conditional.shell -# ^^^^^^^^^ - meta.pattern -# ^^^ meta.pattern.regexp.shell -# ^^^ - meta.pattern +# ^^^^^^^^^ - meta.string.regexp +# ^^^ meta.string.regexp.shell +# ^^^ - meta.string.regexp # ^^^^ meta.function-call.identifier.shell # ^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call.arguments.shell # ^^ support.function.test.begin.shell # ^^ meta.interpolation.parameter.shell variable.language.shell # ^ punctuation.definition.variable.shell # ^^ keyword.operator.comparison.shell -# ^ keyword.operator.quantifier.regexp.shell +# ^ invalid.illegal.unexpected-quantifier.regexp.shell # ^ keyword.operator.quantifier.regexp.shell # ^^ support.function.test.end.shell # ^ punctuation.terminator.statement.shell @@ -4788,9 +5559,9 @@ if [[ $- != *i* ]] ; then echo shell is not interactive; fi if [[ "$ERL_TOP" != ";"; ]];then;fi #^ keyword.control.conditional.if.shell # ^^^^^^^^^^^^^^^^^^^^^^^ meta.conditional.shell -# ^^^^^^^^^^^^^^^^^ - meta.pattern -# ^^^^ meta.pattern.regexp.shell -# ^^^ - meta.pattern +# ^^^^^^^^^^^^^^^^^ - meta.string.regexp +# ^^^^ meta.string.regexp.shell +# ^^^ - meta.string.regexp # ^ punctuation.terminator.statement.shell # ^^^^ keyword.control.conditional.then.shell # ^ punctuation.terminator.statement.shell @@ -5055,7 +5826,7 @@ echo Deploying... # <- punctuation.terminator.case.clause.shell #^ punctuation.terminator.case.clause.shell * ) -# <- keyword.operator.quantifier.regexp.shell +# <- constant.other.wildcard.asterisk.shell # ^ keyword.control.conditional.patterns.end.shell cat <<'ENDCAT' # <- meta.function-call.identifier.shell variable.function.shell @@ -5125,7 +5896,7 @@ case $TERM in # ^ meta.function punctuation.section.compound.end.shell # ^^ punctuation.terminator.case.clause.shell *xterm*|rxvt|(dt|k|E)term) - # ^ keyword.operator.quantifier.regexp.shell + # ^ constant.other.wildcard.asterisk.shell # ^ keyword.operator.logical.regexp.shell # ^ keyword.operator.logical.regexp.shell # ^ punctuation.definition.group.begin.regexp.shell @@ -5137,7 +5908,7 @@ case $TERM in # ^ meta.function punctuation.section.compound.end.shell # ^^ punctuation.terminator.case.clause.shell *) - # <- keyword.operator.quantifier.regexp.shell + # <- constant.other.wildcard.asterisk.shell #^ keyword.control.conditional.patterns.end.shell update_terminal_cwd() {};; # ^ meta.function punctuation.section.compound.end.shell @@ -5148,13 +5919,14 @@ esac case $SERVER in # <- keyword.control.conditional.case.shell ws-+([0-9]).host.com) echo "Web Server" -#^^^ meta.conditional.case.clause.patterns.shell meta.pattern.regexp.shell - meta.group -# ^^^^^^^ meta.conditional.case.clause.patterns.shell meta.pattern.regexp.shell meta.group.regexp.shell -# ^^^^^^^^^^ meta.conditional.case.clause.patterns.shell meta.pattern.regexp.shell - meta.group +#^^^ meta.conditional.case.clause.patterns.shell meta.string.regexp.shell - meta.group +# ^^^^^^^ meta.conditional.case.clause.patterns.shell meta.string.regexp.shell meta.group.regexp.shell +# ^^^^^^^^^^ meta.conditional.case.clause.patterns.shell meta.string.regexp.shell - meta.group # ^ keyword.operator.quantifier.regexp.shell # ^ punctuation.definition.group.begin.regexp.shell # ^ punctuation.definition.set.begin.regexp.shell -# ^ punctuation.separator.range.regexp.shell +# ^^^ constant.other.range.regexp.shell +# ^ punctuation.separator.sequence.regexp.shell # ^ punctuation.definition.set.end.regexp.shell # ^ punctuation.definition.group.end.regexp.shell # ^ keyword.control.conditional.patterns.end.shell @@ -5162,13 +5934,14 @@ ws-+([0-9]).host.com) echo "Web Server" # <- punctuation.terminator.case.clause.shell #^ punctuation.terminator.case.clause.shell db-+([0-9])\.host\.com) echo "DB server" -#^^^ meta.conditional.case.clause.patterns.shell meta.pattern.regexp.shell - meta.group -# ^^^^^^^ meta.conditional.case.clause.patterns.shell meta.pattern.regexp.shell meta.group.regexp.shell -# ^^^^^^^^^^^ meta.conditional.case.clause.patterns.shell meta.pattern.regexp.shell - meta.group +#^^^ meta.conditional.case.clause.patterns.shell meta.string.regexp.shell - meta.group +# ^^^^^^^ meta.conditional.case.clause.patterns.shell meta.string.regexp.shell meta.group.regexp.shell +# ^^^^^^^^^^^ meta.conditional.case.clause.patterns.shell meta.string.regexp.shell - meta.group # ^ keyword.operator.quantifier.regexp.shell # ^ punctuation.definition.group.begin.regexp.shell # ^ punctuation.definition.set.begin.regexp.shell -# ^ punctuation.separator.range.regexp.shell +# ^^^ constant.other.range.regexp.shell +# ^ punctuation.separator.sequence.regexp.shell # ^ punctuation.definition.set.end.regexp.shell # ^ punctuation.definition.group.end.regexp.shell # ^ keyword.control.conditional.patterns.end.shell @@ -5179,7 +5952,8 @@ bk-+([0-9])\.host\.com) echo "Backup server" # ^ keyword.operator.quantifier.regexp.shell # ^ punctuation.definition.group.begin.regexp.shell # ^ punctuation.definition.set.begin.regexp.shell -# ^ punctuation.separator.range.regexp.shell +# ^^^ constant.other.range.regexp.shell +# ^ punctuation.separator.sequence.regexp.shell # ^ punctuation.definition.set.end.regexp.shell # ^ punctuation.definition.group.end.regexp.shell # ^ keyword.control.conditional.patterns.end.shell @@ -5188,7 +5962,7 @@ bk-+([0-9])\.host\.com) echo "Backup server" # <- punctuation.terminator.case.clause.shell #^ punctuation.terminator.case.clause.shell *)echo "Unknown server" -# <- keyword.operator.quantifier.regexp.shell +# <- constant.other.wildcard.asterisk.shell #^ keyword.control.conditional.patterns.end.shell # ^^^^ support.function.echo.shell ;;