shellscriptLanguage top-level constant
Language
const shellscriptLanguage
Shell (source.shell).
Implementation
const shellscriptLanguage = Language(
name: 'shellscript',
scopeName: 'source.shell',
displayName: 'Shell',
aliases: ['bash', 'sh', 'shell', 'zsh'],
grammar: <String, Object?>{
'displayName': 'Shell',
'name': 'shellscript',
'patterns': [
{'include': '#initial_context'},
],
'repository': {
'alias_statement': {
'begin':
'[\\t ]*+(alias)[\\t ]*+((?:((?<!\\w)-\\w+)\\b[\\t ]*+)*)[\\t ]*+((?<!\\w)[-0-9A-Z_a-z]+(?!\\w))(?:(\\[)((?:(?:\\\$?(?<!\\w)[-0-9A-Z_a-z]+(?!\\w)|@)|\\*)|(-?\\d+))(]))?(?:(?:(=)|(\\+=))|(-=))',
'beginCaptures': {
'1': {'name': 'storage.type.alias.shell'},
'2': {
'patterns': [
{
'match': '(?<!\\w)-\\w+\\b',
'name':
'string.unquoted.argument.shell constant.other.option.shell',
},
],
},
'3': {
'name':
'string.unquoted.argument.shell constant.other.option.shell',
},
'4': {'name': 'variable.other.assignment.shell'},
'5': {'name': 'punctuation.definition.array.access.shell'},
'6': {'name': 'variable.other.assignment.shell'},
'7': {
'name': 'constant.numeric.shell constant.numeric.integer.shell',
},
'8': {'name': 'punctuation.definition.array.access.shell'},
'9': {'name': 'keyword.operator.assignment.shell'},
'10': {'name': 'keyword.operator.assignment.compound.shell'},
'11': {'name': 'keyword.operator.assignment.compound.shell'},
},
'end': '(?=[\\t ]|\$)|(?:(?:(?:(;)|(&&))|(\\|\\|))|(&))',
'endCaptures': {
'1': {'name': 'punctuation.terminator.statement.semicolon.shell'},
'2': {'name': 'punctuation.separator.statement.and.shell'},
'3': {'name': 'punctuation.separator.statement.or.shell'},
'4': {'name': 'punctuation.separator.statement.background.shell'},
},
'name': 'meta.expression.assignment.alias.shell',
'patterns': [
{'include': '#normal_context'},
],
},
'argument': {
'begin': '[\\t ]++(?![\\n#\\&(\\[|]|\$|;)',
'beginCaptures': {},
'end': '(?=[\\t \\&;|]|\$|[\\n)`])',
'endCaptures': {},
'name': 'meta.argument.shell',
'patterns': [
{'include': '#argument_context'},
{'include': '#line_continuation'},
],
},
'argument_context': {
'patterns': [
{
'captures': {
'1': {
'name': 'string.unquoted.argument.shell',
'patterns': [
{
'match': '\\*',
'name': 'variable.language.special.wildcard.shell',
},
{'include': '#variable'},
{'include': '#numeric_literal'},
{
'captures': {
'1': {'name': 'constant.language.\$1.shell'},
},
'match': '(?<!\\w)\\b(true|false)\\b(?!\\w)',
},
],
},
},
'match': '[\\t ]*+([^\\t\\n "\$\\&-);<>\\\\`|]+(?!>))',
},
{'include': '#normal_context'},
],
},
'arithmetic_double': {
'patterns': [
{
'begin': '\\(\\(',
'beginCaptures': {
'0': {'name': 'punctuation.section.arithmetic.double.shell'},
},
'end': '\\)\\s*\\)',
'endCaptures': {
'0': {'name': 'punctuation.section.arithmetic.double.shell'},
},
'name': 'meta.arithmetic.shell',
'patterns': [
{'include': '#math'},
{'include': '#string'},
],
},
],
},
'arithmetic_no_dollar': {
'patterns': [
{
'begin': '\\(',
'beginCaptures': {
'0': {'name': 'punctuation.section.arithmetic.single.shell'},
},
'end': '\\)',
'endCaptures': {
'0': {'name': 'punctuation.section.arithmetic.single.shell'},
},
'name': 'meta.arithmetic.shell',
'patterns': [
{'include': '#math'},
{'include': '#string'},
],
},
],
},
'array_access_inline': {
'captures': {
'1': {'name': 'punctuation.section.array.shell'},
'2': {
'patterns': [
{'include': '#special_expansion'},
{'include': '#string'},
{'include': '#variable'},
],
},
'3': {'name': 'punctuation.section.array.shell'},
},
'match': '(\\[)([^]\\[]+)(])',
},
'array_value': {
'begin':
'[\\t ]*+((?<!\\w)[-0-9A-Z_a-z]+(?!\\w))(?:(\\[)((?:(?:\\\$?(?<!\\w)[-0-9A-Z_a-z]+(?!\\w)|@)|\\*)|(-?\\d+))(]))?(?:(?:(=)|(\\+=))|(-=))[\\t ]*+(\\()',
'beginCaptures': {
'1': {'name': 'variable.other.assignment.shell'},
'2': {'name': 'punctuation.definition.array.access.shell'},
'3': {'name': 'variable.other.assignment.shell'},
'4': {
'name': 'constant.numeric.shell constant.numeric.integer.shell',
},
'5': {'name': 'punctuation.definition.array.access.shell'},
'6': {'name': 'keyword.operator.assignment.shell'},
'7': {'name': 'keyword.operator.assignment.compound.shell'},
'8': {'name': 'keyword.operator.assignment.compound.shell'},
'9': {'name': 'punctuation.definition.array.shell'},
},
'end': '\\)',
'endCaptures': {
'0': {'name': 'punctuation.definition.array.shell'},
},
'patterns': [
{'include': '#comment'},
{
'captures': {
'1': {
'name':
'variable.other.assignment.array.shell entity.other.attribute-name.shell',
},
'2': {
'name':
'keyword.operator.assignment.shell punctuation.definition.assignment.shell',
},
},
'match': '((?<!\\w)[-0-9A-Z_a-z]+(?!\\w))(=)',
},
{
'captures': {
'1': {'name': 'punctuation.definition.bracket.named-array.shell'},
'2': {
'name':
'string.unquoted.shell entity.other.attribute-name.bracket.shell',
},
'3': {'name': 'punctuation.definition.bracket.named-array.shell'},
'4': {'name': 'punctuation.definition.assignment.shell'},
},
'match': '(\\[)(.+?)(])(=)',
},
{'include': '#normal_context'},
{'include': '#simple_unquoted'},
],
},
'assignment_statement': {
'patterns': [
{'include': '#array_value'},
{'include': '#modified_assignment_statement'},
{'include': '#normal_assignment_statement'},
],
},
'basic_command_name': {
'captures': {
'1': {'name': 'storage.modifier.\$1.shell'},
'2': {
'name': 'entity.name.function.call.shell entity.name.command.shell',
'patterns': [
{
'match': '(?<!\\w)(?:continue|return|break)(?!\\w)',
'name': 'keyword.control.\$0.shell',
},
{
'match':
'(?<!\\w)(?:unfunction|continue|autoload|unsetopt|bindkey|builtin|getopts|command|declare|unalias|history|unlimit|typeset|suspend|source|printf|unhash|disown|ulimit|return|which|alias|break|false|print|shift|times|umask|unset|read|type|exec|eval|wait|echo|dirs|jobs|kill|hash|stat|exit|test|trap|true|let|set|pwd|cd|fg|bg|fc|[.:])(?!/)(?!\\w)(?!-)',
'name': 'support.function.builtin.shell',
},
{'include': '#variable'},
],
},
},
'match':
'(?![\\n!#\\&()<>\\[{|]|\$|[\\t ;])(?!nocorrect |nocorrect\\t|nocorrect\$|readonly |readonly\\t|readonly\$|function |function\\t|function\$|foreach |foreach\\t|foreach\$|coproc |coproc\\t|coproc\$|logout |logout\\t|logout\$|export |export\\t|export\$|select |select\\t|select\$|repeat |repeat\\t|repeat\$|pushd |pushd\\t|pushd\$|until |until\\t|until\$|while |while\\t|while\$|local |local\\t|local\$|case |case\\t|case\$|done |done\\t|done\$|elif |elif\\t|elif\$|else |else\\t|else\$|esac |esac\\t|esac\$|popd |popd\\t|popd\$|then |then\\t|then\$|time |time\\t|time\$|for |for\\t|for\$|end |end\\t|end\$|fi |fi\\t|fi\$|do |do\\t|do\$|in |in\\t|in\$|if |if\\t|if\$)(?:((?<=^|[\\t \\&;])(?:readonly|declare|typeset|export|local)(?=[\\t \\&;]|\$))|((?!["\']|\\\\\\n?\$)[^\\t\\n\\r !"\'<>]+?))(?:(?=[\\t ])|(?=[\\n\\&);`{|}]|[\\t ]*#|])(?<!\\\\))',
'name': 'meta.statement.command.name.basic.shell',
},
'block_comment': {
'begin': '\\s*+(/\\*)',
'beginCaptures': {
'1': {'name': 'punctuation.definition.comment.begin.shell'},
},
'end': '\\*/',
'endCaptures': {
'0': {'name': 'punctuation.definition.comment.end.shell'},
},
'name': 'comment.block.shell',
},
'boolean': {
'match': '\\b(?:true|false)\\b',
'name': 'constant.language.\$0.shell',
},
'case_statement': {
'begin': '\\b(case)\\b[\\t ]*+(.+?)[\\t ]*+\\b(in)\\b',
'beginCaptures': {
'1': {'name': 'keyword.control.case.shell'},
'2': {
'patterns': [
{'include': '#initial_context'},
],
},
'3': {'name': 'keyword.control.in.shell'},
},
'end': '\\besac\\b',
'endCaptures': {
'0': {'name': 'keyword.control.esac.shell'},
},
'name': 'meta.case.shell',
'patterns': [
{'include': '#comment'},
{
'captures': {
'1': {'name': 'keyword.operator.pattern.case.default.shell'},
},
'match': '[\\t ]*+(\\* *\\))',
},
{
'begin': '(?<!\\))(?![\\t ]*+(?:esac\\b|\$))',
'beginCaptures': {},
'end': '(?=\\besac\\b)|(\\))',
'endCaptures': {
'1': {'name': 'keyword.operator.pattern.case.shell'},
},
'name': 'meta.case.entry.pattern.shell',
'patterns': [
{'include': '#case_statement_context'},
],
},
{
'begin': '(?<=\\))',
'beginCaptures': {},
'end': '(;;)|(?=\\besac\\b)',
'endCaptures': {
'1': {'name': 'punctuation.terminator.statement.case.shell'},
},
'name': 'meta.case.entry.body.shell',
'patterns': [
{'include': '#typical_statements'},
{'include': '#initial_context'},
],
},
],
},
'case_statement_context': {
'patterns': [
{
'match': '\\*',
'name':
'variable.language.special.quantifier.star.shell keyword.operator.quantifier.star.shell punctuation.definition.arbitrary-repetition.shell punctuation.definition.regex.arbitrary-repetition.shell',
},
{
'match': '\\+',
'name':
'variable.language.special.quantifier.plus.shell keyword.operator.quantifier.plus.shell punctuation.definition.arbitrary-repetition.shell punctuation.definition.regex.arbitrary-repetition.shell',
},
{
'match': '\\?',
'name':
'variable.language.special.quantifier.question.shell keyword.operator.quantifier.question.shell punctuation.definition.arbitrary-repetition.shell punctuation.definition.regex.arbitrary-repetition.shell',
},
{
'match': '@',
'name':
'variable.language.special.at.shell keyword.operator.at.shell punctuation.definition.regex.at.shell',
},
{
'match': '\\|',
'name':
'keyword.operator.orvariable.language.special.or.shell keyword.operator.alternation.ruby.shell punctuation.definition.regex.alternation.shell punctuation.separator.regex.alternation.shell',
},
{'match': '\\\\.', 'name': 'constant.character.escape.shell'},
{
'match': '(?<=\\tin| in|[\\t ]|;;)\\(',
'name': 'keyword.operator.pattern.case.shell',
},
{
'begin': '(?<=\\S)(\\()',
'beginCaptures': {
'1': {
'name':
'punctuation.definition.group.shell punctuation.definition.regex.group.shell',
},
},
'end': '\\)',
'endCaptures': {
'0': {
'name':
'punctuation.definition.group.shell punctuation.definition.regex.group.shell',
},
},
'name': 'meta.parenthese.shell',
'patterns': [
{'include': '#case_statement_context'},
],
},
{
'begin': '\\[',
'beginCaptures': {
'0': {'name': 'punctuation.definition.character-class.shell'},
},
'end': ']',
'endCaptures': {
'0': {'name': 'punctuation.definition.character-class.shell'},
},
'name': 'string.regexp.character-class.shell',
'patterns': [
{'match': '\\\\.', 'name': 'constant.character.escape.shell'},
],
},
{'include': '#string'},
{
'match': '[^\\t\\n )*?@\\[|]',
'name':
'string.unquoted.pattern.shell string.regexp.unquoted.shell',
},
],
},
'command_name_range': {
'begin': '\\G',
'beginCaptures': {},
'end': '(?=[\\t \\&;|]|\$|[\\n)`])|(?=<)',
'endCaptures': {},
'name': 'meta.statement.command.name.shell',
'patterns': [
{
'match': '(?<!\\w)(?:continue|return|break)(?!\\w)',
'name':
'entity.name.function.call.shell entity.name.command.shell keyword.control.\$0.shell',
},
{
'match':
'(?<!\\w)(?:unfunction|continue|autoload|unsetopt|bindkey|builtin|getopts|command|declare|unalias|history|unlimit|typeset|suspend|source|printf|unhash|disown|ulimit|return|which|alias|break|false|print|shift|times|umask|unset|read|type|exec|eval|wait|echo|dirs|jobs|kill|hash|stat|exit|test|trap|true|let|set|pwd|cd|fg|bg|fc|[.:])(?!/)(?!\\w)(?!-)',
'name':
'entity.name.function.call.shell entity.name.command.shell support.function.builtin.shell',
},
{'include': '#variable'},
{
'captures': {
'1': {
'name':
'entity.name.function.call.shell entity.name.command.shell',
},
},
'match': '(?<!\\w)(?<=\\G|["\')}])([^\\t\\n\\r "\\&\');->`{|]+)',
},
{
'begin': '(?:\\G|(?<![\\t\\n #\\&;{|]))(\\\$?)((")|(\'))',
'beginCaptures': {
'1': {
'name':
'meta.statement.command.name.quoted.shell punctuation.definition.string.shell entity.name.function.call.shell entity.name.command.shell',
},
'2': {},
'3': {
'name':
'meta.statement.command.name.quoted.shell string.quoted.double.shell punctuation.definition.string.begin.shell entity.name.function.call.shell entity.name.command.shell',
},
'4': {
'name':
'meta.statement.command.name.quoted.shell string.quoted.single.shell punctuation.definition.string.begin.shell entity.name.function.call.shell entity.name.command.shell',
},
},
'end': '(?<!\\G)(?<=\\2)',
'endCaptures': {},
'patterns': [
{'include': '#continuation_of_single_quoted_command_name'},
{'include': '#continuation_of_double_quoted_command_name'},
],
},
{'include': '#line_continuation'},
{'include': '#simple_unquoted'},
],
},
'command_statement': {
'begin':
'[\\t ]*+(?![\\n!#\\&()<>\\[{|]|\$|[\\t ;])(?!nocorrect |nocorrect\\t|nocorrect\$|readonly |readonly\\t|readonly\$|function |function\\t|function\$|foreach |foreach\\t|foreach\$|coproc |coproc\\t|coproc\$|logout |logout\\t|logout\$|export |export\\t|export\$|select |select\\t|select\$|repeat |repeat\\t|repeat\$|pushd |pushd\\t|pushd\$|until |until\\t|until\$|while |while\\t|while\$|local |local\\t|local\$|case |case\\t|case\$|done |done\\t|done\$|elif |elif\\t|elif\$|else |else\\t|else\$|esac |esac\\t|esac\$|popd |popd\\t|popd\$|then |then\\t|then\$|time |time\\t|time\$|for |for\\t|for\$|end |end\\t|end\$|fi |fi\\t|fi\$|do |do\\t|do\$|in |in\\t|in\$|if |if\\t|if\$)(?!\\\\\\n?\$)',
'beginCaptures': {},
'end': '(?=[\\n\\&);`{|}]|[\\t ]*#|])(?<!\\\\)',
'endCaptures': {},
'name': 'meta.statement.command.shell',
'patterns': [
{'include': '#command_name_range'},
{'include': '#line_continuation'},
{'include': '#option'},
{'include': '#argument'},
{'include': '#string'},
{'include': '#heredoc'},
],
},
'comment': {
'captures': {
'1': {'name': 'comment.line.number-sign.shell meta.shebang.shell'},
'2': {'name': 'punctuation.definition.comment.shebang.shell'},
'3': {'name': 'comment.line.number-sign.shell'},
'4': {'name': 'punctuation.definition.comment.shell'},
},
'match': '(?:^|[\\t ]++)(?:((#!).*)|((#).*))',
},
'comments': {
'patterns': [
{'include': '#block_comment'},
{'include': '#line_comment'},
],
},
'compound-command': {
'patterns': [
{
'begin': '\\[',
'beginCaptures': {
'0': {'name': 'punctuation.definition.logical-expression.shell'},
},
'end': ']',
'endCaptures': {
'0': {'name': 'punctuation.definition.logical-expression.shell'},
},
'name': 'meta.scope.logical-expression.shell',
'patterns': [
{'include': '#logical-expression'},
{'include': '#initial_context'},
],
},
{
'begin': '(?<=\\s|^)\\{(?=\\s|\$)',
'beginCaptures': {
'0': {'name': 'punctuation.definition.group.shell'},
},
'end': '(?<=^|;)\\s*(})',
'endCaptures': {
'1': {'name': 'punctuation.definition.group.shell'},
},
'name': 'meta.scope.group.shell',
'patterns': [
{'include': '#initial_context'},
],
},
],
},
'continuation_of_double_quoted_command_name': {
'begin': '\\G(?<=")',
'beginCaptures': {},
'contentName':
'meta.statement.command.name.continuation string.quoted.double entity.name.function.call entity.name.command',
'end': '"',
'endCaptures': {
'0': {
'name':
'string.quoted.double.shell punctuation.definition.string.end.shell entity.name.function.call.shell entity.name.command.shell',
},
},
'patterns': [
{
'match': '\\\\[\\n"\$\\\\`]',
'name': 'constant.character.escape.shell',
},
{'include': '#variable'},
{'include': '#interpolation'},
],
},
'continuation_of_single_quoted_command_name': {
'begin': '\\G(?<=\')',
'beginCaptures': {},
'contentName':
'meta.statement.command.name.continuation string.quoted.single entity.name.function.call entity.name.command',
'end': '\'',
'endCaptures': {
'0': {
'name':
'string.quoted.single.shell punctuation.definition.string.end.shell entity.name.function.call.shell entity.name.command.shell',
},
},
},
'custom_command_names': {'patterns': []},
'custom_commands': {'patterns': []},
'double_quote_context': {
'patterns': [
{
'match': '\\\\[\\n"\$\\\\`]',
'name': 'constant.character.escape.shell',
},
{'include': '#variable'},
{'include': '#interpolation'},
],
},
'double_quote_escape_char': {
'match': '\\\\[\\n"\$\\\\`]',
'name': 'constant.character.escape.shell',
},
'floating_keyword': {
'patterns': [
{
'match':
'(?<=^|[\\t \\&;])(?:then|elif|else|done|end|do|if|fi)(?=[\\t \\&;]|\$)',
'name': 'keyword.control.\$0.shell',
},
],
},
'for_statement': {
'patterns': [
{
'begin':
'\\b(for)\\b[\\t ]*+((?<!\\w)[-0-9A-Z_a-z]+(?!\\w))[\\t ]*+\\b(in)\\b',
'beginCaptures': {
'1': {'name': 'keyword.control.for.shell'},
'2': {'name': 'variable.other.for.shell'},
'3': {'name': 'keyword.control.in.shell'},
},
'end': '(?=[\\n\\&);`{|}]|[\\t ]*#|])(?<!\\\\)',
'endCaptures': {},
'name': 'meta.for.in.shell',
'patterns': [
{'include': '#string'},
{'include': '#simple_unquoted'},
{'include': '#normal_context'},
],
},
{
'begin': '\\b(for)\\b',
'beginCaptures': {
'1': {'name': 'keyword.control.for.shell'},
},
'end': '(?=[\\n\\&);`{|}]|[\\t ]*#|])(?<!\\\\)',
'endCaptures': {},
'name': 'meta.for.shell',
'patterns': [
{'include': '#arithmetic_double'},
{'include': '#normal_context'},
],
},
],
},
'function_definition': {
'applyEndPatternLast': 1,
'begin':
'[\\t ]*+(?:\\b(function)\\b[\\t ]*+([^\\t\\n\\r "\'()=]+)(?:(\\()[\\t ]*+(\\)))?|([^\\t\\n\\r "\'()=]+)[\\t ]*+(\\()[\\t ]*+(\\)))',
'beginCaptures': {
'1': {'name': 'storage.type.function.shell'},
'2': {'name': 'entity.name.function.shell'},
'3': {'name': 'punctuation.definition.arguments.shell'},
'4': {'name': 'punctuation.definition.arguments.shell'},
'5': {'name': 'entity.name.function.shell'},
'6': {'name': 'punctuation.definition.arguments.shell'},
'7': {'name': 'punctuation.definition.arguments.shell'},
},
'end': '(?<=[)}])',
'endCaptures': {},
'name': 'meta.function.shell',
'patterns': [
{'match': '\\G[\\t\\n ]'},
{
'begin': '\\{',
'beginCaptures': {
'0': {
'name':
'punctuation.definition.group.shell punctuation.section.function.definition.shell',
},
},
'end': '}',
'endCaptures': {
'0': {
'name':
'punctuation.definition.group.shell punctuation.section.function.definition.shell',
},
},
'name': 'meta.function.body.shell',
'patterns': [
{'include': '#initial_context'},
],
},
{
'begin': '\\(',
'beginCaptures': {
'0': {
'name':
'punctuation.definition.group.shell punctuation.section.function.definition.shell',
},
},
'end': '\\)',
'endCaptures': {
'0': {
'name':
'punctuation.definition.group.shell punctuation.section.function.definition.shell',
},
},
'name': 'meta.function.body.shell',
'patterns': [
{'include': '#initial_context'},
],
},
{'include': '#initial_context'},
],
},
'heredoc': {
'patterns': [
{
'begin':
'((?<!<)<<-)[\\t ]*+(["\'])[\\t ]*+([^"\']+?)(?=["\\&\';<\\s])(\\2)(.*)',
'beginCaptures': {
'1': {'name': 'keyword.operator.heredoc.shell'},
'2': {
'name': 'punctuation.definition.string.heredoc.quote.shell',
},
'3': {
'name': 'punctuation.definition.string.heredoc.delimiter.shell',
},
'4': {
'name': 'punctuation.definition.string.heredoc.quote.shell',
},
'5': {
'patterns': [
{'include': '#redirect_fix'},
{'include': '#typical_statements'},
],
},
},
'contentName': 'string.quoted.heredoc.indent.\$3',
'end': '^\\t*\\3(?=[\\&;\\s]|\$)',
'endCaptures': {
'0': {'name': 'punctuation.definition.string.heredoc.\$0.shell'},
},
'patterns': [],
},
{
'begin':
'((?<!<)<<(?!<))[\\t ]*+(["\'])[\\t ]*+([^"\']+?)(?=["\\&\';<\\s])(\\2)(.*)',
'beginCaptures': {
'1': {'name': 'keyword.operator.heredoc.shell'},
'2': {
'name': 'punctuation.definition.string.heredoc.quote.shell',
},
'3': {
'name': 'punctuation.definition.string.heredoc.delimiter.shell',
},
'4': {
'name': 'punctuation.definition.string.heredoc.quote.shell',
},
'5': {
'patterns': [
{'include': '#redirect_fix'},
{'include': '#typical_statements'},
],
},
},
'contentName': 'string.quoted.heredoc.no-indent.\$3',
'end': '^\\3(?=[\\&;\\s]|\$)',
'endCaptures': {
'0': {
'name': 'punctuation.definition.string.heredoc.delimiter.shell',
},
},
'patterns': [],
},
{
'begin': '((?<!<)<<-)[\\t ]*+([^\\t "\']+)(?=["\\&\';<\\s])(.*)',
'beginCaptures': {
'1': {'name': 'keyword.operator.heredoc.shell'},
'2': {
'name': 'punctuation.definition.string.heredoc.delimiter.shell',
},
'3': {
'patterns': [
{'include': '#redirect_fix'},
{'include': '#typical_statements'},
],
},
},
'contentName': 'string.unquoted.heredoc.indent.\$2',
'end': '^\\t*\\2(?=[\\&;\\s]|\$)',
'endCaptures': {
'0': {
'name': 'punctuation.definition.string.heredoc.delimiter.shell',
},
},
'patterns': [
{'include': '#double_quote_escape_char'},
{'include': '#variable'},
{'include': '#interpolation'},
],
},
{
'begin':
'((?<!<)<<(?!<))[\\t ]*+([^\\t "\']+)(?=["\\&\';<\\s])(.*)',
'beginCaptures': {
'1': {'name': 'keyword.operator.heredoc.shell'},
'2': {
'name': 'punctuation.definition.string.heredoc.delimiter.shell',
},
'3': {
'patterns': [
{'include': '#redirect_fix'},
{'include': '#typical_statements'},
],
},
},
'contentName': 'string.unquoted.heredoc.no-indent.\$2',
'end': '^\\2(?=[\\&;\\s]|\$)',
'endCaptures': {
'0': {
'name': 'punctuation.definition.string.heredoc.delimiter.shell',
},
},
'patterns': [
{'include': '#double_quote_escape_char'},
{'include': '#variable'},
{'include': '#interpolation'},
],
},
],
},
'herestring': {
'patterns': [
{
'begin': '(<<<)\\s*((\'))',
'beginCaptures': {
'1': {'name': 'keyword.operator.herestring.shell'},
'2': {'name': 'string.quoted.single.shell'},
'3': {'name': 'punctuation.definition.string.begin.shell'},
},
'contentName': 'string.quoted.single.shell',
'end': '(\')',
'endCaptures': {
'0': {'name': 'string.quoted.single.shell'},
'1': {'name': 'punctuation.definition.string.end.shell'},
},
'name': 'meta.herestring.shell',
},
{
'begin': '(<<<)\\s*(("))',
'beginCaptures': {
'1': {'name': 'keyword.operator.herestring.shell'},
'2': {'name': 'string.quoted.double.shell'},
'3': {'name': 'punctuation.definition.string.begin.shell'},
},
'contentName': 'string.quoted.double.shell',
'end': '(")',
'endCaptures': {
'0': {'name': 'string.quoted.double.shell'},
'1': {'name': 'punctuation.definition.string.end.shell'},
},
'name': 'meta.herestring.shell',
'patterns': [
{'include': '#double_quote_context'},
],
},
{
'captures': {
'1': {'name': 'keyword.operator.herestring.shell'},
'2': {
'name': 'string.unquoted.herestring.shell',
'patterns': [
{'include': '#initial_context'},
],
},
},
'match': '(<<<)\\s*(([^)\\\\\\s]|\\\\.)+)',
'name': 'meta.herestring.shell',
},
],
},
'initial_context': {
'patterns': [
{'include': '#comment'},
{'include': '#pipeline'},
{'include': '#normal_statement_seperator'},
{'include': '#logical_expression_double'},
{'include': '#logical_expression_single'},
{'include': '#assignment_statement'},
{'include': '#case_statement'},
{'include': '#for_statement'},
{'include': '#loop'},
{'include': '#function_definition'},
{'include': '#line_continuation'},
{'include': '#arithmetic_double'},
{'include': '#misc_ranges'},
{'include': '#variable'},
{'include': '#interpolation'},
{'include': '#heredoc'},
{'include': '#herestring'},
{'include': '#redirection'},
{'include': '#pathname'},
{'include': '#floating_keyword'},
{'include': '#alias_statement'},
{'include': '#normal_statement'},
{'include': '#string'},
{'include': '#support'},
],
},
'inline_comment': {
'captures': {
'1': {
'name':
'comment.block.shell punctuation.definition.comment.begin.shell',
},
'2': {'name': 'comment.block.shell'},
'3': {
'patterns': [
{
'match': '\\*/',
'name':
'comment.block.shell punctuation.definition.comment.end.shell',
},
{'match': '\\*', 'name': 'comment.block.shell'},
],
},
},
'match': '(/\\*)((?:[^*]|\\*++[^/])*+(\\*++/))',
},
'interpolation': {
'patterns': [
{'include': '#arithmetic_dollar'},
{'include': '#subshell_dollar'},
{
'begin': '`',
'beginCaptures': {
'0': {
'name': 'punctuation.definition.evaluation.backticks.shell',
},
},
'end': '`',
'endCaptures': {
'0': {
'name': 'punctuation.definition.evaluation.backticks.shell',
},
},
'name': 'string.interpolated.backtick.shell',
'patterns': [
{
'match': '\\\\[\$\\\\`]',
'name': 'constant.character.escape.shell',
},
{
'begin': '(?<=\\W)(?=#)(?!#\\{)',
'beginCaptures': {
'1': {'name': 'punctuation.whitespace.comment.leading.shell'},
},
'end': '(?!\\G)',
'patterns': [
{
'begin': '#',
'beginCaptures': {
'0': {'name': 'punctuation.definition.comment.shell'},
},
'end': '(?=`)',
'name': 'comment.line.number-sign.shell',
},
],
},
{'include': '#initial_context'},
],
},
],
},
'keyword': {
'patterns': [
{
'match':
'(?<=^|[\\&;\\s])(then|else|elif|fi|for|in|do|done|select|continue|esac|while|until|return)(?=[\\&;\\s]|\$)',
'name': 'keyword.control.shell',
},
{
'match':
'(?<=^|[\\&;\\s])(?:export|declare|typeset|local|readonly)(?=[\\&;\\s]|\$)',
'name': 'storage.modifier.shell',
},
],
},
'line_comment': {
'begin': '\\s*+(//)',
'beginCaptures': {
'1': {'name': 'punctuation.definition.comment.shell'},
},
'end': '(?<=\\n)(?<!\\\\\\n)',
'endCaptures': {},
'name': 'comment.line.double-slash.shell',
'patterns': [
{'include': '#line_continuation_character'},
],
},
'line_continuation': {
'match': '\\\\(?=\\n)',
'name': 'constant.character.escape.line-continuation.shell',
},
'logical-expression': {
'patterns': [
{'include': '#arithmetic_no_dollar'},
{
'match': '=[=~]?|!=?|[<>]|&&|\\|\\|',
'name': 'keyword.operator.logical.shell',
},
{
'match':
'(?<!\\S)-(nt|ot|ef|eq|ne|l[et]|g[et]|[GLNOSa-hknopr-uwxz])\\b',
'name': 'keyword.operator.logical.shell',
},
],
},
'logical_expression_context': {
'patterns': [
{'include': '#regex_comparison'},
{'include': '#arithmetic_no_dollar'},
{'include': '#logical-expression'},
{'include': '#logical_expression_single'},
{'include': '#logical_expression_double'},
{'include': '#comment'},
{'include': '#boolean'},
{'include': '#redirect_number'},
{'include': '#numeric_literal'},
{'include': '#pipeline'},
{'include': '#normal_statement_seperator'},
{'include': '#string'},
{'include': '#variable'},
{'include': '#interpolation'},
{'include': '#heredoc'},
{'include': '#herestring'},
{'include': '#pathname'},
{'include': '#floating_keyword'},
{'include': '#support'},
],
},
'logical_expression_double': {
'begin': '\\[\\[',
'beginCaptures': {
'0': {'name': 'punctuation.definition.logical-expression.shell'},
},
'end': ']]',
'endCaptures': {
'0': {'name': 'punctuation.definition.logical-expression.shell'},
},
'name': 'meta.scope.logical-expression.shell',
'patterns': [
{'include': '#logical_expression_context'},
],
},
'logical_expression_single': {
'begin': '\\[',
'beginCaptures': {
'0': {'name': 'punctuation.definition.logical-expression.shell'},
},
'end': ']',
'endCaptures': {
'0': {'name': 'punctuation.definition.logical-expression.shell'},
},
'name': 'meta.scope.logical-expression.shell',
'patterns': [
{'include': '#logical_expression_context'},
],
},
'loop': {
'patterns': [
{
'begin': '(?<=^|[\\&;\\s])(for)\\s+(.+?)\\s+(in)(?=[\\&;\\s]|\$)',
'beginCaptures': {
'1': {'name': 'keyword.control.shell'},
'2': {
'name': 'variable.other.loop.shell',
'patterns': [
{'include': '#string'},
],
},
'3': {'name': 'keyword.control.shell'},
},
'end': '(?<=^|[\\&;\\s])done(?=[\\&;\\s]|\$|\\))',
'endCaptures': {
'0': {'name': 'keyword.control.shell'},
},
'name': 'meta.scope.for-in-loop.shell',
'patterns': [
{'include': '#initial_context'},
],
},
{
'begin': '(?<=^|[\\&;\\s])(while|until)(?=[\\&;\\s]|\$)',
'beginCaptures': {
'1': {'name': 'keyword.control.shell'},
},
'end': '(?<=^|[\\&;\\s])done(?=[\\&;\\s]|\$|\\))',
'endCaptures': {
'0': {'name': 'keyword.control.shell'},
},
'name': 'meta.scope.while-loop.shell',
'patterns': [
{'include': '#initial_context'},
],
},
{
'begin':
'(?<=^|[\\&;\\s])(select)\\s+((?:[^\\\\\\s]|\\\\.)+)(?=[\\&;\\s]|\$)',
'beginCaptures': {
'1': {'name': 'keyword.control.shell'},
'2': {'name': 'variable.other.loop.shell'},
},
'end': '(?<=^|[\\&;\\s])(done)(?=[\\&;\\s]|\$|\\))',
'endCaptures': {
'1': {'name': 'keyword.control.shell'},
},
'name': 'meta.scope.select-block.shell',
'patterns': [
{'include': '#initial_context'},
],
},
{
'begin': '(?<=^|[\\&;\\s])if(?=[\\&;\\s]|\$)',
'beginCaptures': {
'0': {'name': 'keyword.control.if.shell'},
},
'end': '(?<=^|[\\&;\\s])fi(?=[\\&;\\s]|\$)',
'endCaptures': {
'0': {'name': 'keyword.control.fi.shell'},
},
'name': 'meta.scope.if-block.shell',
'patterns': [
{'include': '#initial_context'},
],
},
],
},
'math': {
'patterns': [
{'include': '#variable'},
{
'match':
'\\+{1,2}|-{1,2}|[!~]|\\*{1,2}|[%/]|<[<=]?|>[=>]?|==|!=|^|\\|{1,2}|&{1,2}|[,:=?]|[-%\\&*+/^|]=|<<=|>>=',
'name': 'keyword.operator.arithmetic.shell',
},
{'match': '0[Xx]\\h+', 'name': 'constant.numeric.hex.shell'},
{'match': ';', 'name': 'punctuation.separator.semicolon.range'},
{'match': '0\\d+', 'name': 'constant.numeric.octal.shell'},
{
'match': '\\d{1,2}#[0-9@-Z_a-z]+',
'name': 'constant.numeric.other.shell',
},
{'match': '\\d+', 'name': 'constant.numeric.integer.shell'},
{
'match': '(?<!\\w)[0-9A-Z_a-z]+(?!\\w)',
'name': 'variable.other.normal.shell',
},
],
},
'math_operators': {
'patterns': [
{
'match':
'\\+{1,2}|-{1,2}|[!~]|\\*{1,2}|[%/]|<[<=]?|>[=>]?|==|!=|^|\\|{1,2}|&{1,2}|[,:=?]|[-%\\&*+/^|]=|<<=|>>=',
'name': 'keyword.operator.arithmetic.shell',
},
{'match': '0[Xx]\\h+', 'name': 'constant.numeric.hex.shell'},
{'match': '0\\d+', 'name': 'constant.numeric.octal.shell'},
{
'match': '\\d{1,2}#[0-9@-Z_a-z]+',
'name': 'constant.numeric.other.shell',
},
{'match': '\\d+', 'name': 'constant.numeric.integer.shell'},
],
},
'misc_ranges': {
'patterns': [
{'include': '#logical_expression_single'},
{'include': '#logical_expression_double'},
{'include': '#subshell_dollar'},
{
'begin': '(?<![^\\t ])(\\{)(?![\$\\w])',
'beginCaptures': {
'1': {'name': 'punctuation.definition.group.shell'},
},
'end': '}',
'endCaptures': {
'0': {'name': 'punctuation.definition.group.shell'},
},
'name': 'meta.scope.group.shell',
'patterns': [
{'include': '#initial_context'},
],
},
],
},
'modified_assignment_statement': {
'begin':
'(?<=^|[\\t \\&;])(?:readonly|declare|typeset|export|local)(?=[\\t \\&;]|\$)',
'beginCaptures': {
'0': {'name': 'storage.modifier.\$0.shell'},
},
'end': '(?=[\\n\\&);`{|}]|[\\t ]*#|])(?<!\\\\)',
'endCaptures': {},
'name':
'meta.statement.shell meta.expression.assignment.modified.shell',
'patterns': [
{
'match': '(?<!\\w)-\\w+\\b',
'name':
'string.unquoted.argument.shell constant.other.option.shell',
},
{'include': '#array_value'},
{
'captures': {
'1': {'name': 'variable.other.assignment.shell'},
'2': {'name': 'punctuation.definition.array.access.shell'},
'3': {'name': 'variable.other.assignment.shell'},
'4': {
'name': 'constant.numeric.shell constant.numeric.integer.shell',
},
'5': {'name': 'punctuation.definition.array.access.shell'},
'6': {'name': 'keyword.operator.assignment.shell'},
'7': {'name': 'keyword.operator.assignment.compound.shell'},
'8': {'name': 'keyword.operator.assignment.compound.shell'},
'9': {
'name': 'constant.numeric.shell constant.numeric.hex.shell',
},
'10': {
'name': 'constant.numeric.shell constant.numeric.octal.shell',
},
'11': {
'name': 'constant.numeric.shell constant.numeric.other.shell',
},
'12': {
'name': 'constant.numeric.shell constant.numeric.decimal.shell',
},
'13': {
'name': 'constant.numeric.shell constant.numeric.version.shell',
},
'14': {
'name': 'constant.numeric.shell constant.numeric.integer.shell',
},
},
'match':
'((?<!\\w)[-0-9A-Z_a-z]+(?!\\w))(?:(\\[)((?:(?:\\\$?(?<!\\w)[-0-9A-Z_a-z]+(?!\\w)|@)|\\*)|(-?\\d+))(]))?(?:(?:(=)|(\\+=))|(-=))?(?:(?<=[\\t =]|^|[(\\[{])(?:(?:(?:(?:(?:(0[Xx]\\h+)|(0\\d+))|(\\d{1,2}#[0-9@-Z_a-z]+))|(-?\\d+\\.\\d+))|(-?\\d+(?:\\.\\d+)+))|(-?\\d+))(?=[\\t ]|\$|[);}]))?',
},
{'include': '#normal_context'},
],
},
'modifiers': {
'match':
'(?<=^|[\\t \\&;])(?:readonly|declare|typeset|export|local)(?=[\\t \\&;]|\$)',
'name': 'storage.modifier.\$0.shell',
},
'normal_assignment_statement': {
'begin':
'[\\t ]*+((?<!\\w)[-0-9A-Z_a-z]+(?!\\w))(?:(\\[)((?:(?:\\\$?(?<!\\w)[-0-9A-Z_a-z]+(?!\\w)|@)|\\*)|(-?\\d+))(]))?(?:(?:(=)|(\\+=))|(-=))',
'beginCaptures': {
'1': {'name': 'variable.other.assignment.shell'},
'2': {'name': 'punctuation.definition.array.access.shell'},
'3': {'name': 'variable.other.assignment.shell'},
'4': {
'name': 'constant.numeric.shell constant.numeric.integer.shell',
},
'5': {'name': 'punctuation.definition.array.access.shell'},
'6': {'name': 'keyword.operator.assignment.shell'},
'7': {'name': 'keyword.operator.assignment.compound.shell'},
'8': {'name': 'keyword.operator.assignment.compound.shell'},
},
'end': '(?=[\\n\\&);`{|}]|[\\t ]*#|])(?<!\\\\)',
'endCaptures': {},
'name': 'meta.expression.assignment.shell',
'patterns': [
{'include': '#comment'},
{'include': '#string'},
{'include': '#normal_assignment_statement'},
{
'begin': '(?<=[\\t ])(?![\\t ]|\\w+=)',
'beginCaptures': {},
'end': '(?=[\\n\\&);`{|}]|[\\t ]*#|])(?<!\\\\)',
'endCaptures': {},
'name': 'meta.statement.command.env.shell',
'patterns': [
{'include': '#command_name_range'},
{'include': '#line_continuation'},
{'include': '#option'},
{'include': '#argument'},
{'include': '#string'},
],
},
{'include': '#simple_unquoted'},
{'include': '#normal_context'},
],
},
'normal_context': {
'patterns': [
{'include': '#comment'},
{'include': '#pipeline'},
{'include': '#normal_statement_seperator'},
{'include': '#misc_ranges'},
{'include': '#boolean'},
{'include': '#redirect_number'},
{'include': '#numeric_literal'},
{'include': '#string'},
{'include': '#variable'},
{'include': '#interpolation'},
{'include': '#heredoc'},
{'include': '#herestring'},
{'include': '#redirection'},
{'include': '#pathname'},
{'include': '#floating_keyword'},
{'include': '#support'},
{'include': '#parenthese'},
],
},
'normal_statement': {
'begin':
'(?!^[\\t ]*+\$)(?:(?<=(?:^until| until|\\tuntil|^while| while|\\twhile|^elif| elif|\\telif|^else| else|\\telse|^then| then|\\tthen|^do| do|\\tdo|^if| if|\\tif) )|(?<=^|[!\\&(;`{|]))[\\t ]*+(?!nocorrect\\W|nocorrect\\\$|function\\W|function\\\$|foreach\\W|foreach\\\$|repeat\\W|repeat\\\$|logout\\W|logout\\\$|coproc\\W|coproc\\\$|select\\W|select\\\$|while\\W|while\\\$|pushd\\W|pushd\\\$|until\\W|until\\\$|case\\W|case\\\$|done\\W|done\\\$|elif\\W|elif\\\$|else\\W|else\\\$|esac\\W|esac\\\$|popd\\W|popd\\\$|then\\W|then\\\$|time\\W|time\\\$|for\\W|for\\\$|end\\W|end\\\$|fi\\W|fi\\\$|do\\W|do\\\$|in\\W|in\\\$|if\\W|if\\\$)',
'beginCaptures': {},
'end': '(?=[\\n\\&);`{|}]|[\\t ]*#|])(?<!\\\\)',
'endCaptures': {},
'name': 'meta.statement.shell',
'patterns': [
{'include': '#typical_statements'},
],
},
'normal_statement_seperator': {
'captures': {
'1': {'name': 'punctuation.terminator.statement.semicolon.shell'},
'2': {'name': 'punctuation.separator.statement.and.shell'},
'3': {'name': 'punctuation.separator.statement.or.shell'},
'4': {'name': 'punctuation.separator.statement.background.shell'},
},
'match': '(?:(?:(;)|(&&))|(\\|\\|))|(&)',
},
'numeric_literal': {
'captures': {
'1': {'name': 'constant.numeric.shell constant.numeric.hex.shell'},
'2': {'name': 'constant.numeric.shell constant.numeric.octal.shell'},
'3': {'name': 'constant.numeric.shell constant.numeric.other.shell'},
'4': {
'name': 'constant.numeric.shell constant.numeric.decimal.shell',
},
'5': {
'name': 'constant.numeric.shell constant.numeric.version.shell',
},
'6': {
'name': 'constant.numeric.shell constant.numeric.integer.shell',
},
},
'match':
'(?<=[\\t =]|^|[(\\[{])(?:(?:(?:(?:(?:(0[Xx]\\h+)|(0\\d+))|(\\d{1,2}#[0-9@-Z_a-z]+))|(-?\\d+\\.\\d+))|(-?\\d+(?:\\.\\d+)+))|(-?\\d+))(?=[\\t ]|\$|[);}])',
},
'option': {
'begin': '[\\t ]++(-)((?![\\n!#\\&()<>\\[{|]|\$|[\\t ;]))',
'beginCaptures': {
'1': {
'name':
'string.unquoted.argument.shell constant.other.option.dash.shell',
},
'2': {
'name':
'string.unquoted.argument.shell constant.other.option.shell',
},
},
'contentName': 'string.unquoted.argument constant.other.option',
'end': '(?=[\\t ])|(?=[\\n\\&);`{|}]|[\\t ]*#|])(?<!\\\\)',
'endCaptures': {},
'patterns': [
{'include': '#option_context'},
],
},
'option_context': {
'patterns': [
{'include': '#misc_ranges'},
{'include': '#string'},
{'include': '#variable'},
{'include': '#interpolation'},
{'include': '#heredoc'},
{'include': '#herestring'},
{'include': '#redirection'},
{'include': '#pathname'},
{'include': '#floating_keyword'},
{'include': '#support'},
],
},
'parenthese': {
'patterns': [
{
'begin': '\\(',
'beginCaptures': {
'0': {'name': 'punctuation.section.parenthese.shell'},
},
'end': '\\)',
'endCaptures': {
'0': {'name': 'punctuation.section.parenthese.shell'},
},
'name': 'meta.parenthese.group.shell',
'patterns': [
{'include': '#initial_context'},
],
},
],
},
'pathname': {
'patterns': [
{'match': '(?<=[:=\\s]|^)~', 'name': 'keyword.operator.tilde.shell'},
{'match': '[*?]', 'name': 'keyword.operator.glob.shell'},
{
'begin': '([!*+?@])(\\()',
'beginCaptures': {
'1': {'name': 'keyword.operator.extglob.shell'},
'2': {'name': 'punctuation.definition.extglob.shell'},
},
'end': '\\)',
'endCaptures': {
'0': {'name': 'punctuation.definition.extglob.shell'},
},
'name': 'meta.structure.extglob.shell',
'patterns': [
{'include': '#initial_context'},
],
},
],
},
'pipeline': {
'patterns': [
{
'match': '(?<=^|[\\&;\\s])(time)(?=[\\&;\\s]|\$)',
'name': 'keyword.other.shell',
},
{'match': '[!|]', 'name': 'keyword.operator.pipe.shell'},
],
},
'redirect_fix': {
'captures': {
'1': {'name': 'keyword.operator.redirect.shell'},
'2': {'name': 'string.unquoted.argument.shell'},
},
'match': '(>>?)[\\t ]*+([^\\t\\n "\$\\&-);<>\\\\`|]+)',
},
'redirect_number': {
'captures': {
'1': {'name': 'keyword.operator.redirect.stdout.shell'},
'2': {'name': 'keyword.operator.redirect.stderr.shell'},
'3': {'name': 'keyword.operator.redirect.\$3.shell'},
},
'match': '(?<=[\\t ])(?:(1)|(2)|(\\d+))(?=>)',
},
'redirection': {
'patterns': [
{
'begin': '[<>]\\(',
'beginCaptures': {
'0': {'name': 'punctuation.definition.string.begin.shell'},
},
'end': '\\)',
'endCaptures': {
'0': {'name': 'punctuation.definition.string.end.shell'},
},
'name': 'string.interpolated.process-substitution.shell',
'patterns': [
{'include': '#initial_context'},
],
},
{
'match':
'(?<![<>])(&>|\\d*>&\\d*|\\d*(>>|[<>])|\\d*<&|\\d*<>)(?![<>])',
'name': 'keyword.operator.redirect.shell',
},
],
},
'regex_comparison': {
'match': '=~',
'name': 'keyword.operator.logical.regex.shell',
},
'regexp': {
'patterns': [
{'match': '.+'},
],
},
'simple_options': {
'captures': {
'0': {
'patterns': [
{
'captures': {
'1': {
'name':
'string.unquoted.argument.shell constant.other.option.dash.shell',
},
'2': {
'name':
'string.unquoted.argument.shell constant.other.option.shell',
},
},
'match': '[\\t ]++(-)(\\w+)',
},
],
},
},
'match': '(?:[\\t ]++-\\w+)*',
},
'simple_unquoted': {
'match': '[^\\t\\n "\$\\&-);<>\\\\`|]',
'name': 'string.unquoted.shell',
},
'special_expansion': {
'match': '!|:[-=?]?|[*@]|##?|%%|[%/]',
'name': 'keyword.operator.expansion.shell',
},
'start_of_command': {
'match':
'[\\t ]*+(?![\\n!#\\&()<>\\[{|]|\$|[\\t ;])(?!nocorrect |nocorrect\\t|nocorrect\$|readonly |readonly\\t|readonly\$|function |function\\t|function\$|foreach |foreach\\t|foreach\$|coproc |coproc\\t|coproc\$|logout |logout\\t|logout\$|export |export\\t|export\$|select |select\\t|select\$|repeat |repeat\\t|repeat\$|pushd |pushd\\t|pushd\$|until |until\\t|until\$|while |while\\t|while\$|local |local\\t|local\$|case |case\\t|case\$|done |done\\t|done\$|elif |elif\\t|elif\$|else |else\\t|else\$|esac |esac\\t|esac\$|popd |popd\\t|popd\$|then |then\\t|then\$|time |time\\t|time\$|for |for\\t|for\$|end |end\\t|end\$|fi |fi\\t|fi\$|do |do\\t|do\$|in |in\\t|in\$|if |if\\t|if\$)(?!\\\\\\n?\$)',
},
'string': {
'patterns': [
{'match': '\\\\.', 'name': 'constant.character.escape.shell'},
{
'begin': '\'',
'beginCaptures': {
'0': {'name': 'punctuation.definition.string.begin.shell'},
},
'end': '\'',
'endCaptures': {
'0': {'name': 'punctuation.definition.string.end.shell'},
},
'name': 'string.quoted.single.shell',
},
{
'begin': '\\\$?"',
'beginCaptures': {
'0': {'name': 'punctuation.definition.string.begin.shell'},
},
'end': '"',
'endCaptures': {
'0': {'name': 'punctuation.definition.string.end.shell'},
},
'name': 'string.quoted.double.shell',
'patterns': [
{
'match': '\\\\[\\n"\$\\\\`]',
'name': 'constant.character.escape.shell',
},
{'include': '#variable'},
{'include': '#interpolation'},
],
},
{
'begin': '\\\$\'',
'beginCaptures': {
'0': {'name': 'punctuation.definition.string.begin.shell'},
},
'end': '\'',
'endCaptures': {
'0': {'name': 'punctuation.definition.string.end.shell'},
},
'name': 'string.quoted.single.dollar.shell',
'patterns': [
{
'match': '\\\\[\'\\\\abefnrtv]',
'name': 'constant.character.escape.ansi-c.shell',
},
{
'match': '\\\\[0-9]{3}"',
'name': 'constant.character.escape.octal.shell',
},
{
'match': '\\\\x\\h{2}"',
'name': 'constant.character.escape.hex.shell',
},
{
'match': '\\\\c."',
'name': 'constant.character.escape.control-char.shell',
},
],
},
],
},
'subshell_dollar': {
'patterns': [
{
'begin': '\\\$\\(',
'beginCaptures': {
'0': {'name': 'punctuation.definition.subshell.single.shell'},
},
'end': '\\)',
'endCaptures': {
'0': {'name': 'punctuation.definition.subshell.single.shell'},
},
'name': 'meta.scope.subshell',
'patterns': [
{'include': '#parenthese'},
{'include': '#initial_context'},
],
},
],
},
'support': {
'patterns': [
{
'match': '(?<=^|[\\&;\\s])[.:](?=[\\&;\\s]|\$)',
'name': 'support.function.builtin.shell',
},
],
},
'typical_statements': {
'patterns': [
{'include': '#assignment_statement'},
{'include': '#case_statement'},
{'include': '#for_statement'},
{'include': '#while_statement'},
{'include': '#function_definition'},
{'include': '#command_statement'},
{'include': '#line_continuation'},
{'include': '#arithmetic_double'},
{'include': '#normal_context'},
],
},
'variable': {
'patterns': [
{
'captures': {
'1': {
'name':
'punctuation.definition.variable.shell variable.parameter.positional.all.shell',
},
'2': {'name': 'variable.parameter.positional.all.shell'},
},
'match': '(\\\$)(@(?!\\w))',
},
{
'captures': {
'1': {
'name':
'punctuation.definition.variable.shell variable.parameter.positional.shell',
},
'2': {'name': 'variable.parameter.positional.shell'},
},
'match': '(\\\$)([0-9](?!\\w))',
},
{
'captures': {
'1': {
'name':
'punctuation.definition.variable.shell variable.language.special.shell',
},
'2': {'name': 'variable.language.special.shell'},
},
'match': '(\\\$)([-!#\$*0?_](?!\\w))',
},
{
'begin': '(\\\$)(\\{)[\\t ]*+(?=\\d)',
'beginCaptures': {
'1': {
'name':
'punctuation.definition.variable.shell variable.parameter.positional.shell',
},
'2': {
'name':
'punctuation.section.bracket.curly.variable.begin.shell punctuation.definition.variable.shell variable.parameter.positional.shell',
},
},
'contentName': 'meta.parameter-expansion',
'end': '}',
'endCaptures': {
'0': {
'name':
'punctuation.section.bracket.curly.variable.end.shell punctuation.definition.variable.shell variable.parameter.positional.shell',
},
},
'patterns': [
{'include': '#special_expansion'},
{'include': '#array_access_inline'},
{
'match': '[0-9]+',
'name': 'variable.parameter.positional.shell',
},
{
'match': '(?<!\\w)[-0-9A-Z_a-z]+(?!\\w)',
'name': 'variable.other.normal.shell',
},
{'include': '#variable'},
{'include': '#string'},
],
},
{
'begin': '(\\\$)(\\{)',
'beginCaptures': {
'1': {'name': 'punctuation.definition.variable.shell'},
'2': {
'name':
'punctuation.section.bracket.curly.variable.begin.shell punctuation.definition.variable.shell',
},
},
'contentName': 'meta.parameter-expansion',
'end': '}',
'endCaptures': {
'0': {
'name':
'punctuation.section.bracket.curly.variable.end.shell punctuation.definition.variable.shell',
},
},
'patterns': [
{'include': '#special_expansion'},
{'include': '#array_access_inline'},
{
'match': '(?<!\\w)[-0-9A-Z_a-z]+(?!\\w)',
'name': 'variable.other.normal.shell',
},
{'include': '#variable'},
{'include': '#string'},
],
},
{
'captures': {
'1': {
'name':
'punctuation.definition.variable.shell variable.other.normal.shell',
},
'2': {'name': 'variable.other.normal.shell'},
},
'match': '(\\\$)(\\w+(?!\\w))',
},
],
},
'while_statement': {
'patterns': [
{
'begin': '\\b(while)\\b',
'beginCaptures': {
'1': {'name': 'keyword.control.while.shell'},
},
'end': '(?=[\\n\\&);`{|}]|[\\t ]*#|])(?<!\\\\)',
'endCaptures': {},
'name': 'meta.while.shell',
'patterns': [
{'include': '#line_continuation'},
{'include': '#math_operators'},
{'include': '#option'},
{'include': '#simple_unquoted'},
{'include': '#normal_context'},
{'include': '#string'},
],
},
],
},
},
'scopeName': 'source.shell',
},
);