2020-05-19 18:20:18 +02:00
|
|
|
|
%YAML 1.2
|
|
|
|
|
# [Sublime]: https://www.sublimetext.com/docs/3/syntax.html
|
|
|
|
|
# [Bash]: https://www.gnu.org/software/bash/manual/bash.html
|
|
|
|
|
--- #---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
name: console
|
|
|
|
|
|
|
|
|
|
scope: source.shell.console
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
variables:
|
|
|
|
|
call_token: \./
|
|
|
|
|
cmd_boundary: (?=\s|;|$|>|<)
|
|
|
|
|
extension: \.sh
|
|
|
|
|
identifier: '[[:alpha:]_][[:alnum:]_]*'
|
|
|
|
|
identifier_non_posix: '[^{{metachar}}\d][^{{metachar}}=]*'
|
|
|
|
|
is_command: (?=\S)
|
|
|
|
|
is_end_of_interpolation: \)
|
|
|
|
|
is_end_of_option: '[^\w$-]|$'
|
|
|
|
|
is_function: \s*\b(function)\s+|(?=\s*{{identifier_non_posix}}\s*\(\s*\))
|
|
|
|
|
is_path_component: (?=[^\s/]*/)
|
|
|
|
|
is_start_of_arguments: '[`=|&;()<>\s]'
|
|
|
|
|
is_variable: (?=\s*{{nbc}}(?:[({]{{nbc}}[)}])?{{nbc}}=)
|
|
|
|
|
keyword_break: (?![-=\w])
|
|
|
|
|
|
|
|
|
|
# A character that, when unquoted, separates words. A metacharacter is a
|
|
|
|
|
# space, tab, newline, or one of the following characters: ‘|’, ‘&’, ‘;’,
|
|
|
|
|
# ‘(’, ‘)’, ‘<’, or ‘>’.
|
|
|
|
|
metachar: '[\s\t\n|&;()<>]'
|
|
|
|
|
|
|
|
|
|
nbc: '[^{}()=\s]*' # non bracket characters (and also non-whitespace, parens)
|
|
|
|
|
start_of_option: (?:\s+|^)--?(?=[\w$])
|
|
|
|
|
varassign: '[+\-?]?='
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
contexts:
|
|
|
|
|
|
|
|
|
|
comment:
|
|
|
|
|
- match: (?:^\s*|\s+)(\#)
|
|
|
|
|
captures:
|
|
|
|
|
1:
|
|
|
|
|
comment.line.number-sign.shell
|
|
|
|
|
punctuation.definition.comment.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_content_scope: comment.line.number-sign.shell
|
|
|
|
|
# NOTE: The reason for consuming the newline character is as follows.
|
|
|
|
|
# When triggering a snippet, its scope is tested to the *right* of the
|
|
|
|
|
# cursor. So, if you don't want your snippet to trigger in a comment,
|
|
|
|
|
# you have to use something like <scope>source.shell - comment</scope>.
|
|
|
|
|
# If the newline character is not scoped as a comment too, then that
|
|
|
|
|
# scope will never work, because the scope to the right of the cursor
|
|
|
|
|
# will never be a comment scope. That is, unless we consume the newline
|
|
|
|
|
# character (or we are editing something in the middle of an existing
|
|
|
|
|
# comment).
|
|
|
|
|
- match: '(?=\n)'
|
|
|
|
|
scope: comment.line.number-sign.shell
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
line-continuation-or-pop-at-end:
|
|
|
|
|
- include: pop-at-end
|
|
|
|
|
- include: line-continuation
|
|
|
|
|
|
|
|
|
|
pop-at-end:
|
|
|
|
|
- match: $
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
any-escape:
|
|
|
|
|
- match: \\.
|
|
|
|
|
scope: constant.character.escape.shell
|
|
|
|
|
|
|
|
|
|
line-continuation:
|
|
|
|
|
- match: \\\n
|
|
|
|
|
scope: punctuation.separator.continuation.line.shell
|
|
|
|
|
push:
|
|
|
|
|
- match: ^
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \\(\s+)\n
|
|
|
|
|
captures:
|
|
|
|
|
1: invalid.illegal.extraneous-spaces-after-line-continuation.shell
|
|
|
|
|
|
|
|
|
|
prototype:
|
|
|
|
|
- include: comment
|
|
|
|
|
- include: line-continuation
|
|
|
|
|
- include: any-escape
|
|
|
|
|
|
|
|
|
|
main:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- match: ^(\$|\#|❯)(?:\s)
|
|
|
|
|
captures:
|
|
|
|
|
1: keyword.operator.assignment.redirection.process.shell
|
|
|
|
|
push: console-line
|
|
|
|
|
|
|
|
|
|
console-line:
|
2020-05-19 20:38:33 +02:00
|
|
|
|
- match: $
|
|
|
|
|
pop: true
|
2020-05-19 18:20:18 +02:00
|
|
|
|
- include: prototype
|
|
|
|
|
- include: funcdef
|
|
|
|
|
- include: vardef
|
|
|
|
|
- include: redirection
|
|
|
|
|
- include: operator-exclamation
|
|
|
|
|
- match: '{{is_command}}'
|
|
|
|
|
push: cmd
|
|
|
|
|
|
|
|
|
|
# NOTE: Contexts with a "-bt" suffix are the "backtick" contexts. They mirror
|
|
|
|
|
# the ordinary contexts, except that when a backtick is encountered while in
|
|
|
|
|
# a "-bt" context, we pop.
|
|
|
|
|
# Normally, we are in a non-bt context. When we encounter a backtick character
|
|
|
|
|
# (the ` character), we enter the main-bt context. Popping when encountering
|
|
|
|
|
# another ` character then ensures that we don't enter yet another backtick
|
|
|
|
|
# context.
|
|
|
|
|
# The "expansion" context is the **only** place where this main-bt context is
|
|
|
|
|
# used. If you, the reader, knows of a more elegant way to handle backticks,
|
|
|
|
|
# don't hesitate to change it.
|
|
|
|
|
main-bt:
|
|
|
|
|
- include: funcdef-bt
|
|
|
|
|
- include: vardef
|
|
|
|
|
- include: redirection
|
|
|
|
|
- match: '{{is_command}}'
|
|
|
|
|
push: cmd-bt
|
|
|
|
|
|
|
|
|
|
control:
|
|
|
|
|
- match: \bif{{keyword_break}}
|
|
|
|
|
scope: keyword.control.conditional.if.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \bthen{{keyword_break}}
|
|
|
|
|
scope: keyword.control.conditional.then.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \belif{{keyword_break}}
|
|
|
|
|
scope: keyword.control.conditional.elseif.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \bfi{{keyword_break}}
|
|
|
|
|
scope: keyword.control.conditional.end.shell
|
|
|
|
|
set: [cmd-post, cmd-args]
|
|
|
|
|
- match: \belse{{keyword_break}}
|
|
|
|
|
scope: keyword.control.conditional.else.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \bfor{{keyword_break}}
|
|
|
|
|
scope: keyword.control.loop.for.shell
|
|
|
|
|
set: [cmd-post, for-args]
|
|
|
|
|
- match: \bdo{{keyword_break}}
|
|
|
|
|
scope: keyword.control.loop.do.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \bdone{{keyword_break}}
|
|
|
|
|
scope: keyword.control.loop.end.shell
|
|
|
|
|
set: [cmd-post, cmd-args]
|
|
|
|
|
- match: \bwhile{{keyword_break}}
|
|
|
|
|
scope: keyword.control.loop.while.shell
|
|
|
|
|
- match: \buntil{{keyword_break}}
|
|
|
|
|
scope: keyword.control.loop.until.shell
|
|
|
|
|
- match: \bcase{{keyword_break}}
|
|
|
|
|
scope: keyword.control.conditional.case.shell
|
|
|
|
|
set: [case-body, case-word]
|
|
|
|
|
- match: \bcontinue{{keyword_break}}
|
|
|
|
|
scope: keyword.control.flow.continue.shell
|
|
|
|
|
- match: \bbreak{{keyword_break}}
|
|
|
|
|
scope: keyword.control.flow.break.shell
|
|
|
|
|
set: [cmd-post, cmd-args]
|
|
|
|
|
- match: \besac{{keyword_break}}
|
|
|
|
|
scope: keyword.control.conditional.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
case-word:
|
|
|
|
|
- match: \bin{{keyword_break}}
|
|
|
|
|
scope: keyword.control.in.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: case-end-ahead
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
|
|
|
|
|
case-body:
|
|
|
|
|
- meta_scope: meta.conditional.case.shell
|
|
|
|
|
- match: \besac{{keyword_break}}
|
|
|
|
|
scope: keyword.control.conditional.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: (?=\()
|
|
|
|
|
push:
|
|
|
|
|
- clear_scopes: 1 # remove meta.conditional.case.shell
|
|
|
|
|
- match: \(
|
|
|
|
|
scope: keyword.control.conditional.patterns.begin.shell
|
|
|
|
|
set: case-clause-patterns
|
|
|
|
|
- match: (?=\S)
|
|
|
|
|
push: case-clause-patterns
|
|
|
|
|
|
|
|
|
|
case-clause-patterns:
|
|
|
|
|
- clear_scopes: 1 # remove meta.conditional.case.shell
|
|
|
|
|
- meta_scope: meta.conditional.case.clause.patterns.shell
|
|
|
|
|
- match: \)
|
|
|
|
|
scope: keyword.control.conditional.patterns.end.shell
|
|
|
|
|
set: case-clause-commands
|
|
|
|
|
# emergency bail outs if ')' is missing
|
|
|
|
|
- match: (?=;;&?|;&)
|
|
|
|
|
set: case-clause-commands
|
|
|
|
|
- include: case-end-ahead
|
|
|
|
|
- include: case-clause-patterns-body
|
|
|
|
|
|
|
|
|
|
case-clause-patterns-body:
|
|
|
|
|
# [Bash] 3.2.4.2: Each pattern undergoes tilde expansion, parameter
|
|
|
|
|
# expansion, command substitution, and arithmetic expansion.
|
|
|
|
|
- include: expansion-pattern
|
|
|
|
|
- include: expansion-tilde
|
|
|
|
|
- include: expansion-parameter
|
|
|
|
|
- include: expansion-command
|
|
|
|
|
- include: expansion-arithmetic
|
|
|
|
|
- include: string
|
|
|
|
|
- match: \|
|
|
|
|
|
scope: keyword.operator.logical.shell
|
|
|
|
|
- match: \(
|
|
|
|
|
scope: punctuation.section.parens.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- match: \)
|
|
|
|
|
scope: punctuation.section.parens.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: case-clause-patterns-body
|
|
|
|
|
|
|
|
|
|
case-clause-commands:
|
|
|
|
|
- clear_scopes: 1 # remove meta.conditional.case.shell
|
|
|
|
|
- meta_content_scope: meta.conditional.case.clause.commands.shell
|
|
|
|
|
- match: ;;&?|;&
|
|
|
|
|
scope:
|
|
|
|
|
meta.conditional.case.clause.commands.shell
|
|
|
|
|
punctuation.terminator.case.clause.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: case-end-ahead
|
|
|
|
|
- include: main
|
|
|
|
|
|
|
|
|
|
case-end-ahead:
|
|
|
|
|
- match: (?=\besac{{keyword_break}})
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
# I don't think anybody will write a for-loop inside backticks. Hence no
|
|
|
|
|
# for-args-bt context.
|
|
|
|
|
for-args:
|
|
|
|
|
- match: ""
|
|
|
|
|
set:
|
|
|
|
|
- meta_scope: meta.group.for.shell
|
|
|
|
|
- include: cmd-args-boilerplate
|
|
|
|
|
- include: arithmetic
|
|
|
|
|
- match: \bin{{keyword_break}}
|
|
|
|
|
scope: keyword.control.in.shell
|
|
|
|
|
|
|
|
|
|
expansion-and-string:
|
|
|
|
|
- include: string
|
|
|
|
|
- include: expansion
|
|
|
|
|
|
|
|
|
|
funcdef:
|
|
|
|
|
- match: '{{is_function}}'
|
|
|
|
|
captures:
|
|
|
|
|
1: storage.type.function.shell
|
|
|
|
|
push: [funcdef-body, funcdef-parens, funcdef-name]
|
|
|
|
|
- match: \bcoproc{{keyword_break}}
|
|
|
|
|
scope: keyword.other.coproc.shell
|
|
|
|
|
push: [cmd-post, cmd-args, coproc-body]
|
|
|
|
|
|
|
|
|
|
funcdef-bt:
|
|
|
|
|
- match: '{{is_function}}'
|
|
|
|
|
captures:
|
|
|
|
|
1: storage.type.function.shell
|
|
|
|
|
push: [funcdef-body-bt, funcdef-parens, funcdef-name]
|
|
|
|
|
- match: \bcoproc{{keyword_break}}
|
|
|
|
|
scope: keyword.other.coproc.shell
|
|
|
|
|
push: [cmd-post, cmd-args-bt, coproc-body]
|
|
|
|
|
|
|
|
|
|
coproc-body:
|
|
|
|
|
- match: \s*(?=\S+\s*\{)
|
|
|
|
|
set:
|
|
|
|
|
- meta_content_scope: entity.name.function.coproc.shell
|
|
|
|
|
- match: (?=\s*\{)
|
|
|
|
|
set:
|
|
|
|
|
- match: \{
|
|
|
|
|
scope: punctuation.section.braces.begin.shell
|
|
|
|
|
set:
|
|
|
|
|
- meta_scope: meta.function.coproc.shell
|
|
|
|
|
- match: \}
|
|
|
|
|
scope: punctuation.section.braces.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: main
|
|
|
|
|
- match: ""
|
|
|
|
|
set: main-with-pop-at-end
|
|
|
|
|
|
|
|
|
|
funcdef-name:
|
|
|
|
|
- match: \s*
|
|
|
|
|
set:
|
|
|
|
|
- meta_content_scope: entity.name.function.shell
|
|
|
|
|
- match: (?=\s*[({]|$)
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
funcdef-parens:
|
|
|
|
|
- match: (\()\s*(\))
|
|
|
|
|
captures:
|
|
|
|
|
1: punctuation.section.parens.begin.shell
|
|
|
|
|
2: punctuation.section.parens.end.shell
|
|
|
|
|
- match: \{
|
|
|
|
|
scope: punctuation.section.braces.begin.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \(
|
|
|
|
|
scope: punctuation.definition.compound.begin.shell
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
funcdef-body:
|
|
|
|
|
- meta_scope: meta.function.shell
|
|
|
|
|
- match: \}
|
|
|
|
|
scope: punctuation.section.braces.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \)
|
|
|
|
|
scope: punctuation.definition.compound.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: main
|
|
|
|
|
|
|
|
|
|
funcdef-body-bt:
|
|
|
|
|
- meta_scope: meta.function.shell
|
|
|
|
|
- match: \}
|
|
|
|
|
scope: punctuation.section.braces.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \)
|
|
|
|
|
scope: punctuation.definition.compound.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: main-bt
|
|
|
|
|
|
|
|
|
|
vardef:
|
|
|
|
|
- match: \s*\b(alias){{keyword_break}}
|
|
|
|
|
captures:
|
|
|
|
|
1: support.function.alias.shell
|
|
|
|
|
push:
|
|
|
|
|
- vardef-ensure-function-call-scope
|
|
|
|
|
- vardef-maybe-more
|
|
|
|
|
- vardef-value
|
|
|
|
|
- vardef-assign
|
|
|
|
|
- vardef-alias-name
|
|
|
|
|
- vardef-alias-options
|
|
|
|
|
- match: \s*\b(typeset|declare|local){{keyword_break}}
|
|
|
|
|
captures:
|
|
|
|
|
1: storage.modifier.shell
|
|
|
|
|
push:
|
|
|
|
|
- vardef-ensure-function-call-scope
|
|
|
|
|
- vardef-maybe-more
|
|
|
|
|
- vardef-value
|
|
|
|
|
- vardef-assign
|
|
|
|
|
- vardef-name
|
|
|
|
|
- vardef-declare-options
|
|
|
|
|
- match: \s*\b(export){{keyword_break}}
|
|
|
|
|
captures:
|
|
|
|
|
1: storage.modifier.shell
|
|
|
|
|
push:
|
|
|
|
|
- vardef-ensure-function-call-scope
|
|
|
|
|
- vardef-maybe-more
|
|
|
|
|
- vardef-value
|
|
|
|
|
- vardef-assign
|
|
|
|
|
- vardef-name
|
|
|
|
|
- vardef-export-options
|
|
|
|
|
- match: \s*\b(readonly){{keyword_break}}
|
|
|
|
|
captures:
|
|
|
|
|
1: storage.modifier.shell
|
|
|
|
|
push:
|
|
|
|
|
- vardef-ensure-function-call-scope
|
|
|
|
|
- vardef-maybe-more
|
|
|
|
|
- vardef-value
|
|
|
|
|
- vardef-assign
|
|
|
|
|
- vardef-name
|
|
|
|
|
- vardef-readonly-options
|
|
|
|
|
- match: '{{is_variable}}'
|
|
|
|
|
push:
|
|
|
|
|
- vardef-value
|
|
|
|
|
- vardef-assign
|
|
|
|
|
- vardef-name
|
|
|
|
|
|
|
|
|
|
vardef-readonly-options:
|
|
|
|
|
- match: \s*((-)(?:[aAf]+|p))
|
|
|
|
|
captures:
|
|
|
|
|
2: punctuation.definition.parameter.shell
|
|
|
|
|
1: variable.parameter.option.shell
|
|
|
|
|
- match: \s*
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
vardef-export-options:
|
|
|
|
|
- match: \s*((-)(?:[fn]+|p))
|
|
|
|
|
captures:
|
|
|
|
|
2: punctuation.definition.parameter.shell
|
|
|
|
|
1: variable.parameter.option.shell
|
|
|
|
|
- match: \s*
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
vardef-ensure-function-call-scope:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_scope: meta.function-call.shell
|
|
|
|
|
- match: ""
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
vardef-maybe-more:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- match: (?=`)
|
|
|
|
|
pop: true
|
|
|
|
|
- match: (?=\s*#)
|
|
|
|
|
pop: true
|
|
|
|
|
- include: cmd-args-boilerplate
|
|
|
|
|
- match: (?=\S)
|
|
|
|
|
push: [vardef-value, vardef-assign, vardef-name]
|
|
|
|
|
|
|
|
|
|
vardef-alias-options:
|
|
|
|
|
- match: \s*((-)p)
|
|
|
|
|
captures:
|
|
|
|
|
2: punctuation.definition.parameter.shell
|
|
|
|
|
1: variable.parameter.option.shell
|
|
|
|
|
- match: \s*
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
vardef-alias-name:
|
|
|
|
|
- match: \s*
|
|
|
|
|
set:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_content_scope: entity.name.function.alias.shell
|
|
|
|
|
- include: line-continuation-or-pop-at-end
|
|
|
|
|
- include: any-escape
|
|
|
|
|
- match: (?={{varassign}}|\s)|$
|
|
|
|
|
pop: true
|
|
|
|
|
- include: array
|
|
|
|
|
- match: \s*$
|
|
|
|
|
pop: true
|
|
|
|
|
- include: string
|
|
|
|
|
|
|
|
|
|
vardef-declare-options:
|
|
|
|
|
- match: \s*((-)(?:[aAfFgilnrtux]+|p))
|
|
|
|
|
captures:
|
|
|
|
|
2: punctuation.definition.parameter.shell
|
|
|
|
|
1: variable.parameter.option.shell
|
|
|
|
|
- match: \s*
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
vardef-name:
|
|
|
|
|
- match: \s*
|
|
|
|
|
set:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_content_scope: variable.other.readwrite.assignment.shell
|
|
|
|
|
- include: line-continuation-or-pop-at-end
|
|
|
|
|
- include: any-escape
|
|
|
|
|
- match: (?={{varassign}}|\s)|$|(?=[;&`]|{{metachar}})
|
|
|
|
|
pop: true
|
|
|
|
|
- include: array
|
|
|
|
|
- match: \s*$
|
|
|
|
|
pop: true
|
|
|
|
|
- include: string
|
|
|
|
|
|
|
|
|
|
vardef-assign:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- include: line-continuation-or-pop-at-end
|
|
|
|
|
- include: any-escape
|
|
|
|
|
- match: '{{varassign}}'
|
|
|
|
|
scope: keyword.operator.assignment.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: ""
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
vardef-value:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- match: \(
|
|
|
|
|
scope: punctuation.section.parens.begin.shell
|
|
|
|
|
set:
|
|
|
|
|
- match: \)
|
|
|
|
|
scope: punctuation.section.parens.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \[
|
|
|
|
|
scope: punctuation.section.brackets.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- match: \]
|
|
|
|
|
scope: punctuation.section.brackets.end.shell
|
|
|
|
|
set:
|
|
|
|
|
- match: =
|
|
|
|
|
scope: keyword.operator.assignment.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: ""
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
- match: (?=[&`])
|
|
|
|
|
pop: true
|
|
|
|
|
- match: ""
|
|
|
|
|
set:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_scope: string.unquoted.shell
|
|
|
|
|
- match: (?=`)
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
- include: line-continuation-or-pop-at-end
|
|
|
|
|
- include: any-escape
|
|
|
|
|
- match: (?={{metachar}})
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
redirection:
|
|
|
|
|
- include: redirection-here-string
|
|
|
|
|
- include: redirection-here-document
|
|
|
|
|
- include: redirection-process
|
|
|
|
|
- include: redirection-input
|
|
|
|
|
- include: redirection-output
|
|
|
|
|
- include: redirection-inout
|
|
|
|
|
|
|
|
|
|
redirection-process:
|
|
|
|
|
- match: (\d*)([<>])(\()
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.assignment.redirection.process.shell
|
|
|
|
|
3: punctuation.section.parens.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- match: \)
|
|
|
|
|
scope: punctuation.section.parens.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: main
|
|
|
|
|
|
|
|
|
|
redirection-output:
|
|
|
|
|
- match: (\d*)(>>!?|>&?|&>|&?>(?:\||>))
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.assignment.redirection.shell
|
|
|
|
|
push: redirection-post
|
|
|
|
|
|
|
|
|
|
redirection-input:
|
|
|
|
|
- match: (\d*)(<&?)
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.assignment.redirection.shell
|
|
|
|
|
push: redirection-post
|
|
|
|
|
|
|
|
|
|
redirection-post:
|
|
|
|
|
- match: \s*(?:(\d+)|(-))
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: punctuation.terminator.file-descriptor.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \s*(?=\S)
|
|
|
|
|
set:
|
|
|
|
|
- match: (?={{metachar}}|`)
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
- match: \s*
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
redirection-inout:
|
|
|
|
|
- match: (\d*)(<>)
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.assignment.redirection.shell
|
|
|
|
|
|
|
|
|
|
redirection-here-string:
|
|
|
|
|
- match: (\d*)(<<<)\s
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.herestring.shell
|
|
|
|
|
|
|
|
|
|
redirection-here-document:
|
|
|
|
|
# These are the variants that allow tabs before the end token
|
|
|
|
|
- match: (\d*)(<<-)\s*(')({{identifier}})(')
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.assignment.redirection.shell
|
|
|
|
|
3: punctuation.definition.string.begin.shell
|
|
|
|
|
4: keyword.control.heredoc-token.shell
|
|
|
|
|
5: punctuation.definition.string.end.shell
|
|
|
|
|
push: [heredocs-body-allow-tabs-no-expansion, heredocs-preamble]
|
|
|
|
|
- match: (\d*)(<<-)\s*(")({{identifier}})(")
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.assignment.redirection.shell
|
|
|
|
|
3: punctuation.definition.string.begin.shell
|
|
|
|
|
4: keyword.control.heredoc-token.shell
|
|
|
|
|
5: punctuation.definition.string.end.shell
|
|
|
|
|
push: [heredocs-body-allow-tabs-no-expansion, heredocs-preamble]
|
|
|
|
|
- match: (\d*)(<<-)\s*(\\)({{identifier}})
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.assignment.redirection.shell
|
|
|
|
|
3: punctuation.definition.string.shell
|
|
|
|
|
4: keyword.control.heredoc-token.shell
|
|
|
|
|
push: [heredocs-body-allow-tabs-no-expansion, heredocs-preamble]
|
|
|
|
|
- match: (\d*)(<<-)\s*({{identifier}})
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.assignment.redirection.shell
|
|
|
|
|
3: keyword.control.heredoc-token.shell
|
|
|
|
|
push: [heredocs-body-allow-tabs, heredocs-preamble]
|
|
|
|
|
# These are the variants that DON'T allow tabs before the end token
|
|
|
|
|
- match: (\d*)(<<)\s*(')({{identifier}})(')
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.assignment.redirection.shell
|
|
|
|
|
3: punctuation.definition.string.begin.shell
|
|
|
|
|
4: keyword.control.heredoc-token.shell
|
|
|
|
|
5: punctuation.definition.string.end.shell
|
|
|
|
|
push: [heredocs-body-no-expansion, heredocs-preamble]
|
|
|
|
|
- match: (\d*)(<<)\s*(")({{identifier}})(")
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.assignment.redirection.shell
|
|
|
|
|
3: punctuation.definition.string.begin.shell
|
|
|
|
|
4: keyword.control.heredoc-token.shell
|
|
|
|
|
5: punctuation.definition.string.end.shell
|
|
|
|
|
push: [heredocs-body-no-expansion, heredocs-preamble]
|
|
|
|
|
- match: (\d*)(<<)\s*(\\)({{identifier}})
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.assignment.redirection.shell
|
|
|
|
|
3: punctuation.definition.string.shell
|
|
|
|
|
4: keyword.control.heredoc-token.shell
|
|
|
|
|
push: [heredocs-body-no-expansion, heredocs-preamble]
|
|
|
|
|
- match: (\d*)(<<)\s*({{identifier}})
|
|
|
|
|
captures:
|
|
|
|
|
1: constant.numeric.integer.decimal.file-descriptor.shell
|
|
|
|
|
2: keyword.operator.assignment.redirection.shell
|
|
|
|
|
3: keyword.control.heredoc-token.shell
|
|
|
|
|
push: [heredocs-body, heredocs-preamble]
|
|
|
|
|
|
|
|
|
|
heredocs-body:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_scope: string.unquoted.heredoc.shell
|
|
|
|
|
- include: heredocs-body-common-with-expansion
|
|
|
|
|
- match: ^\3(\s+)\n # the third capture from redirection-here-document
|
|
|
|
|
captures:
|
|
|
|
|
1: invalid.illegal.no-spaces-allowed-after-heredoc-token.shell
|
|
|
|
|
# rather not pop, but sublime throws an error otherwise.
|
|
|
|
|
pop: true
|
|
|
|
|
- match: ^\3$ # the third capture from redirection-here-document
|
|
|
|
|
scope: keyword.control.heredoc-token.shell
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
heredocs-body-allow-tabs:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_scope: string.unquoted.heredoc.shell
|
|
|
|
|
- include: heredocs-body-common-with-expansion
|
|
|
|
|
- match: ^\s*\3(\s+)\n # the third capture from redirection-here-document
|
|
|
|
|
captures:
|
|
|
|
|
1: invalid.illegal.no-spaces-allowed-after-heredoc-token.shell
|
|
|
|
|
# rather not pop, but sublime throws an error otherwise.
|
|
|
|
|
pop: true
|
|
|
|
|
- match: ^\s*(\3)$ # the third capture from redirection-here-document
|
|
|
|
|
captures:
|
|
|
|
|
1: keyword.control.heredoc-token.shell
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
heredocs-body-common-with-expansion:
|
|
|
|
|
# [Bash] 3.6.6: all lines of the here-document are subjected to parameter
|
|
|
|
|
# expansion, command substitution, and arithmetic expansion, the character
|
|
|
|
|
# sequence \newline is ignored, and ‘\’ must be used to quote the
|
|
|
|
|
# characters ‘\’, ‘$’, and ‘`’.
|
|
|
|
|
- match: \\[`$"\\]
|
|
|
|
|
scope: constant.character.escape.backtick.shell
|
|
|
|
|
- include: expansion-parameter
|
|
|
|
|
- include: expansion-arithmetic
|
|
|
|
|
- include: expansion-command
|
|
|
|
|
|
|
|
|
|
heredocs-body-no-expansion:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_scope: string.unquoted.heredoc.shell
|
|
|
|
|
- match: ^\4(\s+)\n # the fourth capture from redirection-here-document
|
|
|
|
|
captures:
|
|
|
|
|
1: invalid.illegal.no-spaces-allowed-after-heredoc-token.shell
|
|
|
|
|
# rather not pop, but sublime throws an error otherwise.
|
|
|
|
|
pop: true
|
|
|
|
|
- match: ^\4$ # the fourth capture from redirection-here-document
|
|
|
|
|
scope: keyword.control.heredoc-token.shell
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
heredocs-body-allow-tabs-no-expansion:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_scope: string.unquoted.heredoc.shell
|
|
|
|
|
- match: ^\s*\4(\s+)\n # the fourth capture from redirection-here-document
|
|
|
|
|
captures:
|
|
|
|
|
1: invalid.illegal.no-spaces-allowed-after-heredoc-token.shell
|
|
|
|
|
# rather not pop, but sublime throws an error otherwise.
|
|
|
|
|
pop: true
|
|
|
|
|
- match: ^\s*(\4)$ # the fourth capture from redirection-here-document
|
|
|
|
|
captures:
|
|
|
|
|
1: keyword.control.heredoc-token.shell
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
heredocs-preamble:
|
|
|
|
|
- match: ""
|
|
|
|
|
set:
|
|
|
|
|
# This enables us to keep parsing on the line where the start token of
|
|
|
|
|
# the heredoc is. Once the first line has ended, we enter the body of
|
|
|
|
|
# the heredoc, where everything is just an unquoted string.
|
|
|
|
|
# One clear_scope for the string.unquoted.
|
|
|
|
|
# The problem with this is that when we also end a function definition
|
|
|
|
|
# on the same line (with the "}" token), we cannot do that.
|
|
|
|
|
- clear_scopes: 1
|
|
|
|
|
- match: $
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \s*(?=\S)
|
|
|
|
|
push: [main-with-pop-at-end, cmd-post, cmd-args]
|
|
|
|
|
|
|
|
|
|
main-with-pop-at-end:
|
|
|
|
|
- include: line-continuation-or-pop-at-end
|
|
|
|
|
- include: main
|
|
|
|
|
|
|
|
|
|
cmd-name-common:
|
|
|
|
|
- match: (?=}|\s+#|\s*(?:[|;]|&(?!>)))
|
|
|
|
|
pop: true
|
|
|
|
|
- include: string
|
|
|
|
|
- include: expansion-parameter
|
|
|
|
|
- include: expansion-arithmetic
|
|
|
|
|
- include: expansion-command
|
|
|
|
|
- include: expansion-tilde
|
|
|
|
|
- include: expansion-job
|
|
|
|
|
- include: line-continuation-or-pop-at-end
|
|
|
|
|
|
|
|
|
|
cmd-args-common:
|
|
|
|
|
- match: (?=}|\s+#)
|
|
|
|
|
pop: true
|
|
|
|
|
- include: redirection
|
|
|
|
|
- match: (?=\s*([|;]|&(?!>)))
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
- include: line-continuation-or-pop-at-end
|
|
|
|
|
|
|
|
|
|
cmd-post: # looks like [main, cmd-post] at this point
|
|
|
|
|
- match: ;(?![;&])
|
|
|
|
|
scope: keyword.operator.logical.continue.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \|\|
|
|
|
|
|
scope: keyword.operator.logical.or.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \|
|
|
|
|
|
scope: keyword.operator.logical.pipe.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \&\&
|
|
|
|
|
scope: keyword.operator.logical.and.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \&
|
|
|
|
|
scope: keyword.operator.logical.job.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: $|(?=\S)
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
cmd-args-boilerplate:
|
|
|
|
|
- match: (?={{is_end_of_interpolation}})
|
|
|
|
|
pop: true
|
|
|
|
|
- include: cmd-args-common
|
|
|
|
|
- match: (?:\s+|^)--(?=\s|$)
|
|
|
|
|
scope: keyword.operator.end-of-options.shell
|
|
|
|
|
set:
|
|
|
|
|
- meta_content_scope: meta.function-call.arguments.shell
|
|
|
|
|
- include: end-of-options-common
|
|
|
|
|
|
|
|
|
|
cmd-args-boilerplate-bt:
|
|
|
|
|
- match: (?={{is_end_of_interpolation}}|`) # <-------------- extra backtick
|
|
|
|
|
pop: true
|
|
|
|
|
- include: cmd-args-common
|
|
|
|
|
- match: (?:\s+|^)--(?=\s|$)
|
|
|
|
|
scope: keyword.operator.end-of-options.shell
|
|
|
|
|
set:
|
|
|
|
|
- meta_content_scope: meta.function-call.arguments.shell
|
|
|
|
|
- match: (?=`) # <-------------------------------------- extra backtick
|
|
|
|
|
pop: true
|
|
|
|
|
- include: end-of-options-common
|
|
|
|
|
|
|
|
|
|
end-of-options-common:
|
|
|
|
|
- include: redirection
|
|
|
|
|
- match: (?=[)};&|])
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
- include: line-continuation-or-pop-at-end
|
|
|
|
|
|
|
|
|
|
cmd-args:
|
|
|
|
|
- match: ""
|
|
|
|
|
set:
|
|
|
|
|
- meta_scope: meta.function-call.arguments.shell
|
|
|
|
|
- include: cmd-args-boilerplate
|
|
|
|
|
- match: '{{start_of_option}}'
|
|
|
|
|
scope: punctuation.definition.parameter.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_scope: variable.parameter.option.shell
|
|
|
|
|
- match: (?==)
|
|
|
|
|
set:
|
|
|
|
|
- match: =
|
|
|
|
|
scope: keyword.operator.assignment.option.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: (?={{is_end_of_option}})
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
|
|
|
|
|
cmd-args-bt:
|
|
|
|
|
- match: ""
|
|
|
|
|
set:
|
|
|
|
|
- meta_scope: meta.function-call.arguments.shell
|
|
|
|
|
- include: cmd-args-boilerplate-bt
|
|
|
|
|
- match: '{{start_of_option}}'
|
|
|
|
|
scope: punctuation.definition.parameter.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_scope: variable.parameter.option.shell
|
|
|
|
|
- match: (?==)
|
|
|
|
|
set:
|
|
|
|
|
- match: =
|
|
|
|
|
scope: keyword.operator.assignment.option.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: (?={{is_end_of_option}}|`) # <------------- extra backtick
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
|
|
|
|
|
cmd:
|
|
|
|
|
- include: cmd-common
|
|
|
|
|
- match: \(
|
|
|
|
|
scope: punctuation.definition.compound.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- match: \)
|
|
|
|
|
scope: punctuation.definition.compound.end.shell
|
|
|
|
|
set: [cmd-post, cmd-args]
|
|
|
|
|
- include: main
|
|
|
|
|
- include: scope:commands.builtin.shell.bash#main
|
|
|
|
|
- match: \blet\b
|
|
|
|
|
scope: support.function.let.bash
|
|
|
|
|
push:
|
|
|
|
|
- meta_scope: meta.function-call.shell
|
|
|
|
|
- match: $
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expression
|
|
|
|
|
- match: (\[\[)(?=\s)
|
|
|
|
|
captures:
|
|
|
|
|
1: support.function.double-brace.begin.shell
|
|
|
|
|
set: [cmd-post, cmd-test-double-brace-args]
|
|
|
|
|
- match: (\[)(?=\s)
|
|
|
|
|
captures:
|
|
|
|
|
1: support.function.test.begin.shell
|
|
|
|
|
set: [cmd-post, cmd-test-brace-args]
|
|
|
|
|
- match: (\{)(?=\s)
|
|
|
|
|
captures:
|
|
|
|
|
1: punctuation.definition.compound.braces.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- match: \}
|
|
|
|
|
scope: punctuation.definition.compound.braces.end.shell
|
|
|
|
|
set: [cmd-post, cmd-args]
|
|
|
|
|
- include: main
|
|
|
|
|
- match: (?=\S)
|
|
|
|
|
set: [cmd-post, cmd-args, cmd-name]
|
|
|
|
|
|
|
|
|
|
cmd-bt:
|
|
|
|
|
- include: cmd-common
|
|
|
|
|
- match: \(
|
|
|
|
|
scope: punctuation.definition.compound.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- match: \)
|
|
|
|
|
scope: punctuation.definition.compound.end.shell
|
|
|
|
|
set: [cmd-post, cmd-args-bt]
|
|
|
|
|
- include: main
|
|
|
|
|
- include: scope:commands.builtin.shell.bash#main-bt
|
|
|
|
|
- match: \blet\b
|
|
|
|
|
scope: support.function.let.bash
|
|
|
|
|
push:
|
|
|
|
|
- meta_scope: meta.function-call.shell
|
|
|
|
|
- match: $|(?=\`)
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expression
|
|
|
|
|
- match: (\[\[)(?=\s)
|
|
|
|
|
captures:
|
|
|
|
|
1: support.function.double-brace.begin.shell
|
|
|
|
|
set: [cmd-post, cmd-test-double-brace-args-bt]
|
|
|
|
|
- match: (\[)(?=\s)
|
|
|
|
|
captures:
|
|
|
|
|
1: support.function.test.begin.shell
|
|
|
|
|
set: [cmd-post, cmd-test-brace-args-bt]
|
|
|
|
|
- match: (\{)(?=\s)
|
|
|
|
|
captures:
|
|
|
|
|
1: punctuation.definition.compound.braces.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- match: \}
|
|
|
|
|
scope: punctuation.definition.compound.braces.end.shell
|
|
|
|
|
set: [cmd-post, cmd-args-bt]
|
|
|
|
|
- include: main-bt
|
|
|
|
|
- match: (?=\S)
|
|
|
|
|
set: [cmd-post, cmd-args-bt, cmd-name-bt]
|
|
|
|
|
|
|
|
|
|
cmd-test-brace-args:
|
|
|
|
|
- match: ""
|
|
|
|
|
set:
|
|
|
|
|
- meta_scope: meta.function-call.arguments.shell
|
|
|
|
|
- include: cmd-args-boilerplate
|
|
|
|
|
- match: \s+(\])
|
|
|
|
|
captures:
|
|
|
|
|
1: support.function.test.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expression-test
|
|
|
|
|
|
|
|
|
|
cmd-test-brace-args-bt:
|
|
|
|
|
- match: ""
|
|
|
|
|
set:
|
|
|
|
|
- meta_scope: meta.function-call.arguments.shell
|
|
|
|
|
- include: cmd-args-boilerplate-bt
|
|
|
|
|
- match: \s+(\])
|
|
|
|
|
captures:
|
|
|
|
|
1: support.function.test.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expression-test
|
|
|
|
|
|
|
|
|
|
cmd-test-double-brace-args:
|
|
|
|
|
- meta_scope: meta.function-call.arguments.shell
|
|
|
|
|
- match: \s+(\]\])
|
|
|
|
|
captures:
|
|
|
|
|
1: support.function.double-brace.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expression-test
|
|
|
|
|
# - include: cmd-args-boilerplate
|
|
|
|
|
|
|
|
|
|
cmd-test-double-brace-args-bt:
|
|
|
|
|
- meta_scope: meta.function-call.arguments.shell
|
|
|
|
|
- match: \s+(\]\])
|
|
|
|
|
captures:
|
|
|
|
|
1: support.function.double-brace.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expression-test
|
|
|
|
|
# - include: cmd-args-boilerplate-bt
|
|
|
|
|
|
|
|
|
|
cmd-name:
|
|
|
|
|
- match: ""
|
|
|
|
|
set:
|
|
|
|
|
- meta_scope: meta.function-call.shell variable.function.shell
|
|
|
|
|
- match: (?={{is_start_of_arguments}}|{{is_end_of_interpolation}})
|
|
|
|
|
pop: true
|
|
|
|
|
- include: cmd-name-common
|
|
|
|
|
|
|
|
|
|
cmd-name-bt:
|
|
|
|
|
- match: ""
|
|
|
|
|
set:
|
|
|
|
|
- meta_scope: meta.function-call.shell variable.function.shell
|
|
|
|
|
# extra backtick
|
|
|
|
|
- match: (?={{is_start_of_arguments}}|{{is_end_of_interpolation}}|`)
|
|
|
|
|
pop: true
|
|
|
|
|
- include: cmd-name-common
|
|
|
|
|
|
|
|
|
|
cmd-common:
|
|
|
|
|
- include: control
|
|
|
|
|
- include: arithmetic
|
|
|
|
|
- match: (?=\)|})
|
|
|
|
|
pop: true
|
|
|
|
|
- include: line-continuation-or-pop-at-end
|
|
|
|
|
|
|
|
|
|
arithmetic:
|
|
|
|
|
- match: \(\((?=.+\)\))
|
|
|
|
|
scope: punctuation.section.arithmetic.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_scope: meta.group.arithmetic.shell
|
|
|
|
|
- match: \)\)
|
|
|
|
|
scope: punctuation.section.arithmetic.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expression
|
|
|
|
|
|
|
|
|
|
expansion-tilde:
|
|
|
|
|
- match: '~'
|
|
|
|
|
scope: meta.group.expansion.tilde variable.language.tilde.shell
|
|
|
|
|
|
|
|
|
|
expansion-brace:
|
|
|
|
|
- match: \{
|
|
|
|
|
scope: punctuation.section.expansion.brace.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_scope: meta.group.expansion.brace.shell
|
|
|
|
|
- match: \}
|
|
|
|
|
scope: punctuation.section.expansion.brace.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \,
|
|
|
|
|
scope: punctuation.separator.shell
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
|
|
|
|
|
expansion-parameter:
|
|
|
|
|
- match: (\$)(\{)
|
|
|
|
|
captures:
|
|
|
|
|
0: meta.group.expansion.parameter.shell
|
|
|
|
|
1: punctuation.definition.variable.shell
|
|
|
|
|
2: punctuation.section.expansion.parameter.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_content_scope: meta.group.expansion.parameter.shell
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- match: \!
|
|
|
|
|
scope: keyword.operator.indirection.shell
|
|
|
|
|
set: expansion-parameter-post-first-character
|
|
|
|
|
- match: \#
|
|
|
|
|
scope: keyword.operator.arithmetic.shell
|
|
|
|
|
set: expansion-parameter-post-first-character
|
|
|
|
|
- match: ""
|
|
|
|
|
set: expansion-parameter-post-first-character
|
|
|
|
|
- match: (\$)(\d)
|
|
|
|
|
captures:
|
|
|
|
|
0: meta.group.expansion.parameter.shell
|
|
|
|
|
1: punctuation.definition.variable.shell
|
|
|
|
|
2: variable.other.readwrite.shell
|
|
|
|
|
- match: (\$)([$#@!~*?_-])(?!\w)
|
|
|
|
|
captures:
|
|
|
|
|
0: meta.group.expansion.parameter.shell
|
|
|
|
|
1: punctuation.definition.variable.shell
|
|
|
|
|
2: variable.language.shell
|
|
|
|
|
- match: (\$)({{identifier}})
|
|
|
|
|
captures:
|
|
|
|
|
0: meta.group.expansion.parameter.shell
|
|
|
|
|
1: punctuation.definition.variable.shell
|
|
|
|
|
2: variable.other.readwrite.shell
|
|
|
|
|
|
|
|
|
|
expansion-pattern:
|
|
|
|
|
- match: ([?*+@!])(\()
|
|
|
|
|
captures:
|
|
|
|
|
1: keyword.operator.regexp.quantifier.shell
|
|
|
|
|
2: punctuation.section.parens.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- match: \)
|
|
|
|
|
scope: punctuation.section.parens.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \|
|
|
|
|
|
scope: keyword.operator.logical.or.shell
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
- match: '[*?]'
|
|
|
|
|
scope: keyword.operator.regexp.quantifier.shell
|
|
|
|
|
- match: \[(?=.*])
|
|
|
|
|
scope: keyword.control.regexp.set.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- match: (?=])
|
|
|
|
|
set: expansion-pattern-post-first-char
|
|
|
|
|
- match: '[!^]'
|
|
|
|
|
scope: keyword.operator.logical.not.shell
|
|
|
|
|
set: expansion-pattern-post-first-char
|
|
|
|
|
- match: \-
|
|
|
|
|
set: expansion-pattern-post-first-char
|
|
|
|
|
- match: ""
|
|
|
|
|
set: expansion-pattern-post-first-char
|
|
|
|
|
|
|
|
|
|
expansion-pattern-post-first-char:
|
|
|
|
|
- match: (?:-)?(\])
|
|
|
|
|
captures:
|
|
|
|
|
1: keyword.control.regexp.set.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: \-
|
|
|
|
|
scope: keyword.operator.word.shell
|
|
|
|
|
- match: (\.)[[:word:]](\.)
|
|
|
|
|
captures:
|
|
|
|
|
1: punctuation.separator.collate.begin.shell
|
|
|
|
|
2: punctuation.separator.collate.end.shell
|
|
|
|
|
- match: (=)[[:word:]](=)
|
|
|
|
|
captures:
|
|
|
|
|
1: punctuation.separator.equivalence-class.begin.shell
|
|
|
|
|
2: punctuation.separator.equivalence-class.end.shell
|
|
|
|
|
- match: (:)[[:lower:]]+(:)
|
|
|
|
|
captures:
|
|
|
|
|
1: punctuation.separator.character-class.begin.shell
|
|
|
|
|
2: punctuation.separator.character-class.end.shell
|
|
|
|
|
# You cannot have a regex set inside a regex set, so just consume this
|
|
|
|
|
# character in order to not push into another regex set.
|
|
|
|
|
# Except when writing a character class like [:lower:], so negative look
|
|
|
|
|
# ahead for that possibility.
|
|
|
|
|
- match: \[(?![\.=:])
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
|
|
|
|
|
expansion-arithmetic:
|
|
|
|
|
- match: (\$)(\(\()(?=.+\)\))
|
|
|
|
|
captures:
|
|
|
|
|
1: punctuation.definition.variable.shell
|
|
|
|
|
2: punctuation.section.parens.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_scope: meta.group.expansion.arithmetic.shell
|
|
|
|
|
- match: \)\)
|
|
|
|
|
scope: punctuation.section.parens.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expression
|
|
|
|
|
|
|
|
|
|
expansion-command:
|
|
|
|
|
- match: (\$)(\()
|
|
|
|
|
captures:
|
|
|
|
|
1: punctuation.definition.variable.shell
|
|
|
|
|
2: punctuation.section.parens.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_scope: meta.group.expansion.command.parens.shell
|
|
|
|
|
- match: \s*(\))
|
|
|
|
|
captures:
|
|
|
|
|
1: punctuation.section.parens.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: main
|
|
|
|
|
- match: \`
|
|
|
|
|
scope: punctuation.section.group.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_scope: meta.group.expansion.command.backticks.shell
|
|
|
|
|
- match: \`
|
|
|
|
|
scope: punctuation.section.group.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: main-bt # all those *-bt contexts just for this!!!!
|
|
|
|
|
|
|
|
|
|
expansion:
|
|
|
|
|
- include: expansion-pattern
|
|
|
|
|
- include: expansion-parameter
|
|
|
|
|
- include: expansion-brace
|
|
|
|
|
- include: expansion-arithmetic
|
|
|
|
|
- include: expansion-command
|
|
|
|
|
- include: expansion-tilde
|
|
|
|
|
- include: expansion-job
|
|
|
|
|
|
|
|
|
|
expansion-parameter-common:
|
|
|
|
|
- meta_content_scope: meta.group.expansion.parameter.shell
|
|
|
|
|
- match: \}
|
|
|
|
|
scope:
|
|
|
|
|
meta.group.expansion.parameter.shell
|
|
|
|
|
punctuation.section.expansion.parameter.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: string
|
|
|
|
|
- include: expansion-parameter
|
|
|
|
|
# no brace expansion
|
|
|
|
|
- include: expansion-arithmetic
|
|
|
|
|
- include: expansion-command
|
|
|
|
|
- include: expansion-tilde
|
|
|
|
|
# no pattern expansion
|
|
|
|
|
- include: any-escape
|
|
|
|
|
|
|
|
|
|
array:
|
|
|
|
|
- match: \[
|
|
|
|
|
scope: punctuation.section.braces.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- match: \]
|
|
|
|
|
scope: punctuation.section.braces.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: '[*@]'
|
|
|
|
|
scope: variable.language.array.shell
|
|
|
|
|
- include: expression
|
|
|
|
|
|
|
|
|
|
expansion-parameter-post-first-character:
|
|
|
|
|
- meta_content_scope:
|
|
|
|
|
meta.group.expansion.parameter.shell
|
|
|
|
|
variable.other.readwrite.shell
|
|
|
|
|
- include: expansion-parameter-common
|
|
|
|
|
- match: (?=[@*]?/)
|
|
|
|
|
set:
|
|
|
|
|
- meta_content_scope: meta.group.expansion.parameter.shell
|
|
|
|
|
- match: ([@*])?(/)
|
|
|
|
|
captures:
|
|
|
|
|
1: variable.language.shell
|
|
|
|
|
2: keyword.operator.substitution.shell
|
|
|
|
|
set:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_content_scope: meta.group.expansion.parameter.shell
|
|
|
|
|
- match: '[/#%]'
|
|
|
|
|
scope: variable.parameter.switch.shell
|
|
|
|
|
set: expansion-parameter-pattern
|
|
|
|
|
- match: ""
|
|
|
|
|
set: expansion-parameter-pattern
|
|
|
|
|
- match: (?=\:?[-+=?])
|
|
|
|
|
set:
|
|
|
|
|
- meta_content_scope: meta.group.expansion.parameter.shell
|
|
|
|
|
- match: \:?[-+=?]
|
|
|
|
|
scope: keyword.operator.assignment.shell
|
|
|
|
|
set: expansion-parameter-common
|
|
|
|
|
- match: (?=@?:)
|
|
|
|
|
set:
|
|
|
|
|
- meta_content_scope: meta.group.expansion.parameter.shell
|
|
|
|
|
- match: '(@)?(:)'
|
|
|
|
|
captures:
|
|
|
|
|
1: variable.language.shell
|
|
|
|
|
2: keyword.operator.substring.begin.shell
|
|
|
|
|
set:
|
|
|
|
|
- meta_content_scope: meta.group.expansion.parameter.shell
|
|
|
|
|
- match: (?=:)
|
|
|
|
|
set:
|
|
|
|
|
- meta_content_scope: meta.group.expansion.parameter.shell
|
|
|
|
|
- match: ":"
|
|
|
|
|
scope: keyword.operator.substring.end.shell
|
|
|
|
|
set:
|
|
|
|
|
- meta_content_scope: meta.group.expansion.parameter.shell
|
|
|
|
|
- include: expression
|
|
|
|
|
- include: expansion-parameter-common
|
|
|
|
|
- include: expression
|
|
|
|
|
- include: expansion-parameter-common
|
|
|
|
|
- match: \#(?=})
|
|
|
|
|
- match: ([@*])?(\#\#?|%%?|\^\^?|,,?)
|
|
|
|
|
captures:
|
|
|
|
|
1: variable.language.shell
|
|
|
|
|
2: keyword.operator.expansion.shell
|
|
|
|
|
set:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_content_scope: meta.group.expansion.parameter.shell
|
|
|
|
|
- include: expansion-parameter-common
|
|
|
|
|
- include: expansion-pattern
|
|
|
|
|
- match: ([@*]?)(@)([QEPAa])(?=})
|
|
|
|
|
captures:
|
|
|
|
|
1: variable.language.shell
|
|
|
|
|
2: keyword.operator.expansion.shell
|
|
|
|
|
3: variable.parameter.switch.shell
|
|
|
|
|
- include: array
|
|
|
|
|
- match: '[*@](?=})'
|
|
|
|
|
scope: variable.language.shell
|
|
|
|
|
|
|
|
|
|
expansion-parameter-pattern:
|
|
|
|
|
- meta_content_scope: meta.group.expansion.parameter.shell
|
|
|
|
|
- match: /
|
|
|
|
|
scope: keyword.operator.substitution.shell
|
|
|
|
|
set: expansion-parameter-common
|
|
|
|
|
- include: expansion-parameter-common
|
|
|
|
|
- include: expansion-pattern
|
|
|
|
|
|
|
|
|
|
expansion-job:
|
|
|
|
|
# There are a number of ways to refer to a job in the shell.
|
|
|
|
|
# The symbols ‘%%’ and ‘%+’ refer to the shell’s notion of the current job,
|
|
|
|
|
# which is the last job stopped while it was in the foreground or started in
|
|
|
|
|
# the background. The previous job may be referenced using ‘%-’.
|
|
|
|
|
- match: (%)([%+-])
|
|
|
|
|
captures:
|
|
|
|
|
0: meta.group.expansion.job.shell
|
|
|
|
|
1: punctuation.definition.variable.job.shell
|
|
|
|
|
2: variable.language.job.shell
|
|
|
|
|
# The character ‘%’ introduces a job specification (jobspec). Job number n
|
|
|
|
|
# may be referred to as ‘%n’.
|
|
|
|
|
- match: (%)(\d+)
|
|
|
|
|
captures:
|
|
|
|
|
0: meta.group.expansion.job.shell
|
|
|
|
|
1: punctuation.definition.variable.job.shell
|
|
|
|
|
2: constant.numeric.integer.decimal.job.shell
|
|
|
|
|
# A job may also be referred to using a prefix of the name used to start it,
|
|
|
|
|
# or using a substring that appears in its command line. For example, ‘%ce’
|
|
|
|
|
# refers to a stopped ce job. Using ‘%?ce’, on the other hand, refers to any
|
|
|
|
|
# job containing the string ‘ce’ in its command line. If the prefix or
|
|
|
|
|
# substring matches more than one job, Bash reports an error.
|
|
|
|
|
- match: (%)(\??)(\w+)
|
|
|
|
|
captures:
|
|
|
|
|
0: meta.group.expansion.job.shell
|
|
|
|
|
1: punctuation.definition.variable.job.shell
|
|
|
|
|
2: keyword.operator.regexp.quantifier.shell
|
|
|
|
|
3: variable.other.readwrite.shell
|
|
|
|
|
# A single ‘%’ (with no accompanying job specification) also refers to the
|
|
|
|
|
# current job.
|
|
|
|
|
- match: '%'
|
|
|
|
|
scope:
|
|
|
|
|
meta.group.expansion.job.shell
|
|
|
|
|
punctuation.definition.variable.job.shell
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
expression:
|
|
|
|
|
# A leading ‘0x’ or ‘0X’ denotes hexadecimal.
|
|
|
|
|
- match: \b0[xX]
|
|
|
|
|
scope: punctuation.definition.numeric.base.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_scope: constant.numeric.integer.hexadecimal.shell
|
|
|
|
|
- match: '[g-zG-Z]'
|
|
|
|
|
scope: invalid.illegal.not-a-hex-character.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: (?=\H)
|
|
|
|
|
pop: true
|
|
|
|
|
# Constants with a leading 0 are interpreted as octal numbers.
|
|
|
|
|
- match: \b0(?=[0-7])
|
|
|
|
|
scope: punctuation.definition.numeric.base.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_scope: constant.numeric.integer.octal.shell
|
|
|
|
|
- match: '[89]'
|
|
|
|
|
scope: invalid.illegal.not-an-octal-character.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- match: (?=[^0-7])
|
|
|
|
|
pop: true
|
|
|
|
|
# Otherwise, numbers take the form [base#]n, where the optional base is a
|
|
|
|
|
# decimal number between 2 and 64 representing the arithmetic base, and n is
|
|
|
|
|
# a number in that base. When specifying n, the digits greater than 9 are
|
|
|
|
|
# represented by the lowercase letters, the uppercase letters, ‘@’, and ‘_’,
|
|
|
|
|
# in that order.
|
|
|
|
|
- match: \b(\d+#)[a-zA-Z0-9@_]+
|
|
|
|
|
scope: constant.numeric.integer.other.shell
|
|
|
|
|
captures:
|
|
|
|
|
1: punctuation.definition.numeric.base.shell
|
|
|
|
|
# If base# is omitted, then base 10 is used.
|
|
|
|
|
- match: \b\d+
|
|
|
|
|
scope: constant.numeric.integer.decimal.shell
|
|
|
|
|
- match: '[*/%+\-&^|]?=|<<=|>>='
|
|
|
|
|
scope: keyword.operator.assignment.shell
|
|
|
|
|
- match: \+\+?|\-\-?|\*\*?|%|/
|
|
|
|
|
scope: keyword.operator.arithmetic.shell
|
|
|
|
|
- match: <[=<]?|>[=>]?|[=!]=|&&|\:|\|\||!
|
|
|
|
|
scope: keyword.operator.logical.shell
|
|
|
|
|
- match: '[&|^~]'
|
|
|
|
|
scope: keyword.operator.bitwise.shell
|
|
|
|
|
- match: '[,;]'
|
|
|
|
|
scope: punctuation.separator.shell
|
|
|
|
|
- match: \?
|
|
|
|
|
scope: keyword.operator.ternary.shell
|
|
|
|
|
- match: \(
|
|
|
|
|
scope: punctuation.section.parens.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_scope: meta.group.parens.shell
|
|
|
|
|
- match: \)
|
|
|
|
|
scope: punctuation.section.parens.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expression
|
|
|
|
|
# Shell variables are allowed as operands; parameter expansion is performed
|
|
|
|
|
# before the expression is evaluated. Within an expression, shell variables
|
|
|
|
|
# may also be referenced by name without using the parameter expansion
|
|
|
|
|
# syntax.
|
|
|
|
|
- include: string
|
|
|
|
|
- include: expansion-parameter
|
|
|
|
|
- include: expansion-arithmetic
|
|
|
|
|
- include: expansion-command
|
|
|
|
|
|
|
|
|
|
expression-test:
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
- match: ((-)[aobcdefghknoprstuvwxzGLNORS])(?=\s)
|
|
|
|
|
captures:
|
|
|
|
|
2: punctuation.definition.parameter.shell
|
|
|
|
|
1: variable.parameter.option.shell
|
|
|
|
|
- match: ((-)(?:ef|nt|ot|eq|ne|lt|le|gt|ge))(?=\s)
|
|
|
|
|
captures:
|
|
|
|
|
2: punctuation.definition.parameter.shell
|
|
|
|
|
1: variable.parameter.option.shell
|
|
|
|
|
- match: (=~)\s*
|
|
|
|
|
captures:
|
|
|
|
|
1: keyword.operator.logical.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_content_scope: meta.regexp.shell
|
|
|
|
|
- match: (?=\s)
|
|
|
|
|
pop: true
|
|
|
|
|
- include: expansion-and-string
|
|
|
|
|
- match: ==?|!=?|<|>|\|\||&&
|
|
|
|
|
scope: keyword.operator.logical.shell
|
|
|
|
|
|
|
|
|
|
operator-exclamation:
|
|
|
|
|
- match: \!(?!\S)
|
|
|
|
|
scope: keyword.operator.logical.shell
|
|
|
|
|
- match: (\!)(-?\d+|!)
|
|
|
|
|
scope: variable.language.history.shell
|
|
|
|
|
captures:
|
|
|
|
|
1: punctuation.definition.history.shell
|
|
|
|
|
- match: \!
|
|
|
|
|
scope: punctuation.definition.history.shell
|
|
|
|
|
|
|
|
|
|
string:
|
|
|
|
|
- include: string-quoted-double
|
|
|
|
|
- include: string-quoted-single
|
|
|
|
|
- include: string-ansi-c
|
|
|
|
|
- include: string-locale
|
|
|
|
|
|
|
|
|
|
# nothing is escaped in a singly-quoted string!
|
|
|
|
|
string-quoted-single:
|
|
|
|
|
- match: \'
|
|
|
|
|
scope: punctuation.definition.string.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_scope: string.quoted.single.shell
|
|
|
|
|
- match: \'
|
|
|
|
|
scope: punctuation.definition.string.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
string-quoted-double:
|
|
|
|
|
- match: \"
|
|
|
|
|
scope: punctuation.definition.string.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_scope: string.quoted.double.shell
|
|
|
|
|
- include: string-quoted-double-common
|
|
|
|
|
|
|
|
|
|
string-quoted-double-escape-character:
|
|
|
|
|
- match: \\[$`"\\]
|
|
|
|
|
scope: constant.character.escape.shell
|
|
|
|
|
- match: \\\n
|
|
|
|
|
scope: constant.character.escape.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- match: (?=\S)
|
|
|
|
|
pop: true
|
|
|
|
|
|
|
|
|
|
# [Bash] 3.1.2.4
|
|
|
|
|
string-ansi-c:
|
|
|
|
|
- match: \$'
|
|
|
|
|
scope: punctuation.definition.string.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_scope: string.quoted.single.ansi-c.shell
|
|
|
|
|
- match: "'"
|
|
|
|
|
scope: punctuation.definition.string.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: string-quoted-double-escape-character
|
|
|
|
|
- match: \\([abfnrtv'"?]|[0-8]{1,3}|x\h{1,8}|c[a-z])
|
|
|
|
|
scope: constant.character.escape.shell
|
|
|
|
|
|
|
|
|
|
# [Bash] 3.1.2.5
|
|
|
|
|
# If the string is translated and replaced, the replacement is double-quoted.
|
|
|
|
|
string-locale:
|
|
|
|
|
- match: \$"
|
|
|
|
|
scope: punctuation.definition.string.begin.shell
|
|
|
|
|
push:
|
|
|
|
|
- meta_include_prototype: false
|
|
|
|
|
- meta_scope: string.quoted.double.locale.shell
|
|
|
|
|
- include: string-quoted-double-common
|
|
|
|
|
|
|
|
|
|
string-quoted-double-common:
|
|
|
|
|
- match: \"
|
|
|
|
|
scope: punctuation.definition.string.end.shell
|
|
|
|
|
pop: true
|
|
|
|
|
- include: string-quoted-double-escape-character
|
|
|
|
|
- include: expansion-parameter
|
|
|
|
|
- include: expansion-arithmetic
|
|
|
|
|
- include: expansion-command
|
|
|
|
|
|