%YAML 1.2 --- name: python scope: source.python version: 2 file_extensions: - py - py3 - pyw - pyi - pyx - pyx.in - pxd - pxd.in - pxi - pxi.in - rpy - cpy - gyp - gypi - vpy - smk - wscript - bazel - bzl hidden_file_extensions: - SConstruct - SConscript - Snakefile first_line_match: |- (?xi: ^ \#! .* \bpython(?:\d(?:\.\d+)?)?\b # shebang | ^ \s* \# .*? -\*- .*? \bpython(?:\d(?:\.\d+)?)?\b .*? -\*- # editorconfig ) variables: # We support unicode here because Python 3 is the future identifier_continue: '[[:alnum:]_]' identifier: '[[:alpha:]_]{{identifier_continue}}*\b' identifier_constant: '(?:[\p{Lu}_][\p{Lu}_\d]*)?[\p{Lu}]{2,}[\p{Lu}_\d]*\b' # require 2 consecutive upper-case letters digits: (?:\d+(?:_\d+)*) exponent: (?:[eE][-+]?{{digits}}) path: '({{identifier}}[ ]*\.[ ]*)*{{identifier}}' illegal_names: (?:and|as|assert|break|class|continue|def|del|elif|else|except|finally|for|from|global|if|import|in|is|lambda|not|or|pass|raise|return|try|while|with|yield) strftime_spec: (?:%(?:[aAwdbBGmyYHIpMSfzZjuUVWcxX%]|-[dmHIMSj])) augmented_assignment_operators: |- (?x: >>= | <<= | \*\*= | //= | \+= | -= | \*= | /= | %= | @= | &= | \|= | \^= ) assignment_operator: '=(?!=)' colon: ':(?!=)' string_prefix: '[bBrRfFuU]{,2}' # Prefer ranged quantifiers over python interpolation in raw f-strings fstring_regexp_interpolation_begin: '\{(?!\d+(?:,\d*)?\})' sql_indicator: |- (?x: \s* (?: # dml statements SELECT | INSERT | REPLACE | DELETE | TRUNCATE | UPDATE | MERGE\s+INTO # ddl statements | ADD | ALTER | CREATE | DROP # conditional | IF \s+ (?: NOT \s+ )? EXISTS # declaration | DECLARE | WITH | BEGIN ) \s ) builtin_exceptions: |- (?x: ArithmeticError | AssertionError | AttributeError | BaseException | BlockingIOError | BrokenPipeError | BufferError | BytesWarning | ChildProcessError | ConnectionAbortedError | ConnectionRefusedError | ConnectionResetError | DeprecationWarning | EnvironmentError | EOFError | Exception | FileExistsError | FileNotFoundError | FloatingPointError | FutureWarning | GeneratorExit | ImportError | ImportWarning | IndentationError | IndexError | InterruptedError | IOError | IsADirectoryError | KeyboardInterrupt | KeyError | LookupError | MemoryError | ModuleNotFoundError | NameError | NotADirectoryError | NotImplemented | NotImplementedError | OSError | OverflowError | PendingDeprecationWarning | PermissionError | ProcessLookupError | RecursionError | ReferenceError | ResourceWarning | RuntimeError | RuntimeWarning | StandardError | StopAsyncIteration | StopIteration | SyntaxError | SyntaxWarning | SystemError | SystemExit | TabError | TimeoutError | TypeError | UnboundLocalError | UnicodeDecodeError | UnicodeEncodeError | UnicodeTranslateError | UnicodeWarning | UserWarning | ValueError | VMSError | Warning | WindowsError | ZeroDivisionError )\b builtin_functions: |- (?x: __import__ | all | abs | any | ascii | bin | callable | chr | classmethod | compile | delattr | dir | divmod | enumerate | eval | filter | format | getattr | globals | hasattr | hash | help | hex | id | input | isinstance | issubclass | iter | len | locals | map | max | min | next | oct | open | ord | pow | property | range | repr | reversed | round | setattr | sorted | staticmethod | sum | super | type(?=\s*\() | vars | zip # Python 2 functions | apply | cmp | coerce | execfile | intern | raw_input | reduce | reload | unichr | xrange # Python 3 functions | aiter| anext| breakpoint | exec | print )\b builtin_types: |- (?x: bool | bytearray | bytes | complex | dict | float | frozenset | int | list | memoryview | object | set | slice | str | tuple # Python 2 types | basestring | long | unicode # Python 2 types prone to conflicts # | buffer | file )\b typing_functions: |- (?x: assert_type | assert_never | clear_overloads | dataclass_transform | final | get_args | get_origin | get_overloads | get_type_hints | is_typeddict | no_type_check | no_type_check_decorator | overload | override | reveal_type | runtime_checkable )\b typing_types: |- (?x: # Super-special typing primitives. Annotated | Any | Callable | ClassVar | Concatenate | Final | ForwardRef | Generic | Literal | Optional | ParamSpec | Protocol | Tuple | Type | TypeVar | TypeVarTuple | Union # ABCs (from collections.abc). | AbstractSet | ByteString | Container | ContextManager | Hashable | ItemsView | Iterable | Iterator | KeysView | Mapping | MappingView | MutableMapping | MutableSequence | MutableSet | Sequence | Sized | ValuesView | Awaitable | AsyncIterator | AsyncIterable | Coroutine | Collection | AsyncGenerator | AsyncContextManager # Structural checks, a.k.a. protocols. | Reversible | SupportsAbs | SupportsBytes | SupportsComplex | SupportsFloat | SupportsIndex | SupportsInt | SupportsRound # Concrete collection types. | ChainMap | Counter | Deque | Dict | DefaultDict | List | OrderedDict | Set | FrozenSet | NamedTuple | TypedDict | Generator # Other concrete types. | BinaryIO | IO | Match | Pattern | TextIO # One-off things. | AnyStr | LiteralString | Never | NewType | NoReturn | NotRequired | ParamSpecArgs | ParamSpecKwargs | Required | Self | Text | TypeAlias | TypeGuard | Unpack )\b magic_functions: |- (?x: __(?: # unary operators invert | neg | pos | abs # binary operators | add | and | contains | div | divmod | floordiv | lshift | mod | mul | or | pow | rshift | sub | truediv | xor # right-hand binary operators | radd | rand | rdiv | rdivmod | rfloordiv | rlshift | rmod | rmul | ror | rpow | rrshift | rsub | rtruediv | rxor # in-place operator assignments | iadd | iand | idiv | ifloordiv | ilshift | imod | imul | ior | ipow | irshift | isub | itruediv | ixor # comparisons | eq | ge | gt | le | lt | ne | cmp | rcmp # py2 # primary coercion | bool | str | nonzero | unicode # py2 # number coercion (converts something to a number) | bytes | complex | float | index | int | round | long # py2 # other "coercion" | format | len | length_hint | hash | repr | reversed | coerce | hex | oct # py2 | fspath # iterator (and 'await') | iter | next | aiter | anext | await # attribute and item access | delattr | delitem | delslice | getattr | getattribute | getitem | getslice | setattr | setitem | setslice | dir | missing # context manager | enter | exit | aenter | aexit # other class magic | call | del | init | new | init_subclass | instancecheck | subclasscheck # pickling | getnewargs | getnewargs_ex | getstate | setstate | reduce | reduce_ex # descriptors | delete | get | set | set_name # class-specific | subclasses # dataclasses (PEP 557) | post_init # for typing core support (PEP 560) | class_getitem | mro_entries )__\b ) magic_variables: |- (?x: __(?: # generic object class | dict | doc | module | name # module-specific / global | all | file | package # functions & methods | annotations | closure | code | defaults | func | globals | kwdefaults | self | qualname # classes (attributes) | bases | prepare | slots | metaclass | mro # Python 2 | members | methods # Python 3.12 (PEP 698) | override )__\b ) ############################################################################## contexts: main: - meta_include_prototype: false - match: '' push: [statements, shebang] statements: - include: docstrings - include: line-statements - include: block-statements - include: class-definitions - include: function-definitions - include: type-definitions - include: statement-terminators - include: expression-as-a-statement block-statements: - include: case-statements - include: conditional-statements - include: exception-statements - include: for-statements - include: match-statements - include: while-statements - include: with-statements line-statements: - include: decorators - include: assignment-statements - include: import-statements - include: modifier-statements - include: flow-statements - include: other-statements # Always include these last and only one at a time! expression-as-a-statement: - include: line-continuations - include: illegal-assignment-expressions - include: lambdas - include: expressions-common - include: qualified-name expression-in-a-statement: # Differs from expression-as-a-statement in that: # - invalid-name matches will pop the current context # - assignment expressions - include: assignment-expressions - include: lambdas - include: expressions-common - include: illegal-name - include: qualified-name expression-in-a-group: # Always include this last! # Differs from expression-in-a-statement in that: # - no assignment expressions allowed # - accessor and lambda matching continues into the next line - include: line-continuations - include: illegal-assignment-expressions - include: lambda-in-groups - include: expressions-common - include: illegal-name - include: qualified-name expression-in-a-sequence: # Always include this last! # Differs from expression-in-a-statement in that: # - accessor and lambda matching continues into the next line - include: for-expressions - include: line-continuations - include: assignment-expressions - include: lambda-in-groups - include: expressions-common - include: illegal-name - include: qualified-name expressions-common: - include: dictionaries-and-sets - include: generators-groups-and-tuples - include: lists - include: comments - include: constants - include: numbers - include: strings - include: keywords - include: operators - include: function-calls - include: items - include: illegal-stray-brackets - include: illegal-stray-braces - include: illegal-stray-parens ###[ COMMENTS ]############################################################### comments: # Special Sphinx comment syntax to denote documentation # https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#directive-autoattribute - match: '#:' scope: punctuation.definition.comment.python push: comment-sphinxdoc-body - match: \# scope: punctuation.definition.comment.python push: - comment-body - type-hint comment-body: - meta_scope: comment.line.number-sign.python - match: \n pop: 1 comment-sphinxdoc-body: - meta_scope: comment.line.documentation.python - match: \n pop: 1 shebang: - meta_include_prototype: false - match: ^\#! scope: punctuation.definition.comment.python set: shebang-body - match: ^|(?=\S) # Note: Ensure to highlight shebang if Python is embedded. pop: 1 shebang-body: - meta_include_prototype: false - meta_scope: comment.line.shebang.python # Note: Keep sync with first_line_match! - match: python(?:\d(?:\.\d+)?)?\b scope: constant.language.shebang.python - match: \n pop: 1 ###[ TYPE HINTS ]############################################################# type-hint: # 1st type hint may be of any type - match: (type)(:) captures: 1: keyword.other.type.python 2: punctuation.separator.type.python set: type-hint-any - include: else-pop - include: eol-pop type-hint-any: - meta_scope: meta.type.python - include: type-hint-end - match: ignore\b scope: keyword.other.ignore.python set: - type-hint-type - type-hint-error-list - match: (?=\S) set: - type-hint-ignore - type-hint-begin type-hint-ignore: # 2nd type hint may only be a `type: ignore` # As it isn't a real start of a comment `#` is not scoped punctuation. - match: \s*\#\s*((type)(:)\s*(ignore\b)) captures: 1: meta.type.python 2: keyword.other.type.python 3: punctuation.separator.type.python 4: keyword.other.ignore.python set: type-hint-error-list - include: immediately-pop type-hint-type: # 2nd type hint must not be a `type: ignore` # As it isn't a real start of a comment `#` is not scoped punctuation. - match: \s*\#\s*((type)(:)(?!\s*ignore\b)) captures: 1: meta.type.python 2: keyword.other.type.python 3: punctuation.separator.type.python set: type-hint-begin - include: immediately-pop type-hint-error-list: - meta_content_scope: meta.type.python - match: \[ scope: punctuation.section.sequence.begin.python set: type-hint-error-list-body - include: type-hint-end type-hint-error-list-body: - meta_scope: meta.type.python meta.sequence.list.errors.python - match: \] scope: punctuation.section.sequence.end.python pop: 1 - include: type-hint-end - include: sequence-separators - match: \b[[:alpha:]_-][[:alnum:]_-]+\b scope: constant.other.error-code.python type-hint-begin: - meta_content_scope: meta.type.python - match: \( scope: punctuation.section.parameters.begin.python set: type-hint-function-parameter-list-body - match: (?=\S) set: type-hint-body type-hint-function-parameter-list-body: - meta_scope: meta.type.function.parameters.python - match: \) scope: punctuation.section.parameters.end.python set: type-hint-function-return-type - include: type-hint-body type-hint-function-return-type: - meta_content_scope: meta.type.function.python - match: -> scope: punctuation.separator.return-type.python set: type-hint-function-return-type-body - include: type-hint-end type-hint-function-return-type-body: - meta_scope: meta.type.function.return-type.python - include: type-hint-body type-hint-body: - meta_scope: meta.type.python - include: type-hint-end - include: type-hint-expressions type-hint-end: - match: (?=\s*[\n#]) pop: 1 type-hint-expressions: - include: type-hint-lists - include: type-separators - include: type-constants - include: constants - include: double-quoted-strings - include: single-quoted-strings - include: builtin-exceptions - include: builtin-types - include: qualified-name type-hint-lists: - match: \[ scope: punctuation.section.brackets.begin.python push: type-hint-list-body type-hint-list-body: # As annotations contain normal expressions use a generic `meta.brackets` # for sake of consistent scoping/highlighting. - meta_scope: meta.brackets.python - match: \] scope: punctuation.section.brackets.end.python pop: 1 - include: type-hint-body type-constants: # Note: Enables `None = None` in type hints. - match: None\b scope: constant.language.null.python type-separators: # Note: Scoped as normal arithmetic operator for consistency reasons with # type-hints in annotations, which share syntax with normal expressions - match: \| scope: keyword.operator.arithmetic.python - include: sequence-separators ###[ DECORATORS ]############################################################# decorators: - match: ^\s*(@) captures: 1: meta.annotation.python punctuation.definition.annotation.python push: decorator-body decorator-body: - meta_content_scope: meta.annotation.python - include: line-continuation-or-pop - include: assignment-expressions - include: lambdas - include: dictionaries-and-sets - include: generators-groups-and-tuples - include: lists - include: constants - include: numbers - include: strings - include: keywords - include: operators - include: decorator-function-calls - include: decorator-variables - include: illegal-stray-brackets - include: illegal-stray-braces - include: illegal-stray-parens decorator-function-calls: - match: (?=(?:\.\s*)?{{path}}\s*\() # now we do push: - function-call-argument-list - decorator-function-call-name - qualified-name-until-leaf decorator-function-call-name: - meta_content_scope: meta.function-call.identifier.python - match: (\.)\s* captures: 1: punctuation.accessor.dot.python set: qualified-decorator-function-call-name - match: '' set: unqualified-decorator-function-call-name qualified-decorator-function-call-name: - meta_scope: meta.function-call.identifier.python meta.path.python - include: unqualified-decorator-variable-name unqualified-decorator-function-call-name: - meta_scope: meta.function-call.identifier.python - include: unqualified-decorator-variable-name decorator-variables: - match: (?=(?:\.\s*)?{{identifier}}) push: - after-expression - decorator-variable-name - qualified-name-until-leaf decorator-variable-name: - match: (\.)\s* captures: 1: punctuation.accessor.dot.python set: qualified-decorator-variable-name - match: '' set: unqualified-decorator-variable-name qualified-decorator-variable-name: - meta_scope: meta.path.python - include: unqualified-decorator-variable-name unqualified-decorator-variable-name: - include: illegal-name - match: '{{identifier}}' scope: variable.annotation.python pop: 1 - include: immediately-pop ###[ IMPORT STATEMENTS ]###################################################### import-statements: - match: import\b scope: keyword.control.import.python push: - imports-import-body - expect-absolute-import - match: from\b scope: keyword.control.import.from.python push: - imports-from-body - maybe-relative-import imports-import-body: - meta_scope: meta.statement.import.python - include: line-continuation-or-pop - match: ',' scope: punctuation.separator.import-list.python push: expect-absolute-import - include: imports-as - include: qualified-name - include: import-illegal-names imports-from-body: - meta_scope: meta.statement.import.python - meta_content_scope: meta.import-source.python - include: imports-from-import - match: as\b scope: keyword.control.import.as.python set: imports-from-import-names - match: '{{illegal_names}}\b' scope: meta.import-path.python invalid.illegal.name.python - match: '{{identifier}}' scope: meta.import-path.python meta.import-name.python - match: \s*(\.)\s*(?={{identifier}}|$) scope: meta.import-path.python captures: 1: punctuation.accessor.dot.python - match: \s*(\.\s*\S+) # matches and consumes the remainder of "abc.123" or "abc.+" scope: meta.import-path.python captures: 1: invalid.illegal.name.python - include: line-continuation-or-pop - include: else-pop imports-from-import: - meta_include_prototype: false - match: import\b scope: keyword.control.import.python set: imports-from-import-body imports-from-import-body: - meta_scope: meta.statement.import.python - include: line-continuation-or-pop - match: \* scope: constant.other.wildcard.asterisk.python set: expect-import-end - match: (?=\() set: imports-from-import-list - match: (?=\S) set: imports-from-import-names imports-from-import-list: - meta_include_prototype: false - match: \( scope: punctuation.section.import-list.begin.python set: imports-from-import-list-body imports-from-import-list-body: - meta_scope: meta.statement.import.python meta.import-list.python - match: \) scope: punctuation.section.import-list.end.python pop: 1 - include: comments - include: imports-as-inlist - include: import-names - include: import-illegal-names-inlist imports-as-inlist: - match: as\b scope: keyword.control.import.as.python push: imports-as-inlist-body imports-as-inlist-body: - match: (?={{identifier}}) set: name-content - include: import-illegal-names-inlist - include: else-pop import-illegal-names-inlist: - match: '[^\s,)]+' scope: invalid.illegal.name.import.python imports-from-import-names: - meta_scope: meta.statement.import.python - include: line-continuation-or-pop - include: imports-as - include: import-names - include: import-illegal-names imports-as: - match: as\b scope: keyword.control.import.as.python push: imports-as-body imports-as-body: - include: line-continuation-or-pop - match: (?={{identifier}}) set: name-content - include: import-illegal-names - include: else-pop import-illegal-names: - match: '[^\s,]+' scope: invalid.illegal.name.import.python import-names: - match: ',' scope: punctuation.separator.import-list.python - include: name expect-import-end: - match: $ pop: 1 - match: (?=#) pop: 1 - match: '[^\s#]+' scope: invalid.illegal.unexpected-import.python expect-absolute-import: - include: line-continuation-or-pop - match: \.+ scope: invalid.illegal.unexpected-relative-import.python - include: else-pop maybe-relative-import: - include: line-continuation-or-pop - match: \.+ scope: meta.import-path.python keyword.control.import.relative.python - include: else-pop ###[ CLASS DEFINITIONS ]###################################################### class-definitions: - match: ^\s*(class)\b scope: meta.class.python captures: 1: keyword.declaration.class.python push: - class-definition-base-list - type-parameter-list - class-definition-name class-definition-name: - include: illegal-name - match: '{{identifier}}' scope: entity.name.class.python pop: 1 - include: class-definition-end class-definition-base-list: - meta_include_prototype: false - meta_content_scope: meta.class.python - match: \( scope: punctuation.section.inheritance.begin.python set: class-definition-base-list-body - include: class-definition-end class-definition-base-list-body: - meta_scope: meta.class.inheritance.python - match: \) scope: punctuation.section.inheritance.end.python set: class-definition-end - match: '{{colon}}' scope: invalid.illegal.no-closing-parens.python pop: 1 - match: ',' scope: punctuation.separator.inheritance.python - include: illegal-name - include: constants - match: ({{identifier}})\s*({{assignment_operator}}) captures: 1: variable.parameter.class-inheritance.python 2: keyword.operator.assignment.python - match: (?={{identifier}}\s*\.) push: qualified-base-class-name - match: '{{identifier}}' scope: entity.other.inherited-class.python - include: expression-in-a-group qualified-base-class-name: - meta_scope: meta.path.python - match: '({{identifier}})\s*(\.)\s*' captures: 1: variable.namespace.python 2: punctuation.accessor.dot.python - match: '{{identifier}}' scope: entity.other.inherited-class.python pop: 1 - include: immediately-pop class-definition-end: - meta_content_scope: meta.class.python - match: '{{colon}}' scope: meta.class.python punctuation.section.class.begin.python pop: 1 - include: line-continuation-or-pop ###[ FUNCTION DEFINITIONS ]################################################### function-definitions: - match: ^\s*(?:(async)\s+)?(def)\b scope: meta.function.python captures: 1: keyword.declaration.async.python 2: keyword.declaration.function.python push: - function-parameter-list - type-parameter-list - function-definition-name function-definition-name: - include: illegal-name - match: '{{magic_functions}}' scope: entity.name.function.python support.function.magic.python pop: 1 - match: '{{identifier}}' scope: entity.name.function.python pop: 1 - include: function-definition-end function-parameter-list: - meta_include_prototype: false - meta_content_scope: meta.function.python - match: \( scope: meta.function.parameters.python punctuation.section.parameters.begin.python set: - function-parameter-list-body - function-parameter-allow-unpack-operators - include: function-definition-end function-parameter-list-body: - meta_content_scope: meta.function.parameters.python - match: \) scope: meta.function.parameters.python punctuation.section.parameters.end.python set: function-after-parameters - match: ',' scope: punctuation.separator.parameters.python push: function-parameter-allow-unpack-operators - match: / scope: storage.modifier.positional-args-only.python push: function-parameter-expect-comma - match: '{{assignment_operator}}' scope: keyword.operator.assignment.python set: function-parameter-default-value - match: '{{colon}}' scope: punctuation.separator.annotation.python set: function-parameter-annotation - include: comments - include: function-parameter-tuples - include: parameter-names - include: line-continuations - include: illegal-assignment-expressions function-parameter-allow-unpack-operators: - match: (?=\*(?!\*)) branch_point: unpack-or-separator branch: - function-parameter-unpack-operator - function-parameter-named-only-operator - include: allow-unpack-operators function-parameter-named-only-operator: - meta_include_prototype: false - match: \* scope: storage.modifier.named-args-only.python pop: 2 function-parameter-unpack-operator: - meta_include_prototype: false - match: \* scope: keyword.operator.unpacking.sequence.python set: function-parameter-unpack-operator-check function-parameter-unpack-operator-check: - meta_include_prototype: false - include: comments - match: (?=,) fail: unpack-or-separator - match: ^(?!\s*([#,]|$))|(?=\S) pop: 2 function-parameter-expect-comma: - meta_include_prototype: false - include: comments - match: (?=[,)]) pop: 1 - match: '[^\s,)]+' scope: invalid.illegal.expected-comma.python function-parameter-annotation: - meta_include_prototype: false - meta_scope: meta.function.parameters.annotation.python - include: line-continuations - match: (?=\S) set: function-parameter-annotation-body function-parameter-annotation-body: - meta_scope: meta.function.parameters.annotation.python - meta_content_scope: meta.type.python - match: \s*(?=[,)=]) set: function-parameter-list-body # Scope newline `meta.type` only, if type continues on next line. # Note: This is required to workaround ST's line blindness. - match: (?=\s*\n) branch_point: function-parameter-annotation-end branch: - function-parameter-annotation-continue - function-parameter-annotation-end - include: function-parameter-annotation-content function-parameter-annotation-content: # Note: maybe type-hint expressions - include: type-constants - include: expression-in-a-group function-parameter-annotation-continue: - meta_include_prototype: false - match: \s*(?=[,)=]) fail: function-parameter-annotation-end - include: comments - include: else-pop function-parameter-annotation-end: - meta_include_prototype: false - match: '' pop: 2 push: function-parameter-list-body function-parameter-default-value: - meta_scope: meta.function.parameters.default-value.python - match: (?=[,)=]) set: function-parameter-list-body - include: expression-in-a-group function-parameter-tuples: # python 2 style tuple arguments # removed from python 3 since PEP-3113 - match: \( scope: punctuation.section.group.begin.python push: - function-parameter-tuple-body - allow-unpack-operators function-parameter-tuple-body: - meta_scope: meta.group.python - match: \) scope: punctuation.section.group.end.python set: after-expression - match: ',' scope: punctuation.separator.parameters.python push: allow-unpack-operators # default values should follow the argument - match: '{{assignment_operator}}' push: function-parameter-illegal-annotation # python 2 does not support type annotations - match: '{{colon}}' push: function-parameter-illegal-default-value - include: comments - include: parameter-names - include: line-continuations - include: illegal-assignment-expressions function-parameter-illegal-annotation: - meta_include_prototype: false - meta_scope: invalid.illegal.default-value.python - match: (?=[,)=]) pop: 1 function-parameter-illegal-default-value: - meta_include_prototype: false - meta_scope: invalid.illegal.annotation.python - match: (?=[,)=]) pop: 1 function-after-parameters: - meta_content_scope: meta.function.python - match: -> scope: punctuation.separator.return-type.python set: function-return-type - include: function-definition-end function-return-type: - meta_include_prototype: false - meta_scope: meta.function.return-type.python - include: line-continuation-or-pop - match: (?=\S) set: function-return-type-body function-return-type-body: - meta_content_scope: meta.function.return-type.python meta.type.python - match: (\s*)({{colon}}) captures: 1: meta.function.return-type.python 2: meta.function.python punctuation.section.function.begin.python pop: 1 - include: line-continuation-or-pop - include: function-return-type-content function-return-type-content: # Note: maybe type-hint expressions - include: illegal-assignment-expressions - include: type-constants - include: expression-in-a-statement function-definition-end: - match: '{{colon}}' scope: meta.function.python punctuation.section.function.begin.python pop: 1 - include: line-continuation-or-pop - include: illegal-assignment-expressions ###[ TYPE DEFINITIONS ]####################################################### type-definitions: - match: ^(?=\s*type\b) branch_point: type-definitions branch: - type-definition - type-definition-fallback type-definition: - meta_include_prototype: false - match: \s*(type)\b captures: 1: keyword.declaration.class.python set: - type-definition-meta - type-definition-value-assignment - type-parameter-list - type-definition-name type-definition-meta: - meta_include_prototype: false - meta_scope: meta.type-alias.python - include: immediately-pop type-definition-name: - include: illegal-name - match: '{{identifier}}' scope: entity.name.type.alias.python pop: 1 - include: line-continuations - match: (?=\S) fail: type-definitions type-definition-value-assignment: - match: = scope: keyword.operator.assignment.python set: variable-annotation - include: line-continuation-or-pop type-definition-fallback: # Fallback context, used, if `type` doesn't seem to start a type alias - match: (?={{path}}\s*\() set: - function-call-argument-list - function-call-wrapper - qualified-name-until-leaf - include: generic-name ###[ TYPE PARAMETERS ]######################################################## type-parameter-lists: - match: \[ scope: meta.generic.python punctuation.definition.generic.begin.python push: - type-parameter-list-body - allow-unpack-operators type-parameter-list: - match: \[ scope: meta.generic.python punctuation.definition.generic.begin.python set: - type-parameter-list-body - allow-unpack-operators - include: line-continuation-or-pop - include: else-pop type-parameter-list-body: - meta_content_scope: meta.generic.python - match: \] scope: meta.generic.python punctuation.definition.generic.end.python pop: 1 - match: ',' scope: punctuation.separator.parameters.python push: allow-unpack-operators - match: '{{colon}}' scope: meta.generic.python punctuation.separator.bound.python set: type-parameter-bound - include: comments - include: illegal-names - match: '{{identifier}}' scope: variable.parameter.type.python - include: line-continuations type-parameter-bound: - meta_include_prototype: false - meta_content_scope: meta.generic.bound.python - include: line-continuations - match: (?=\S) set: type-parameter-bound-body type-parameter-bound-body: - meta_scope: meta.generic.bound.python - meta_content_scope: meta.type.python - match: \s*(?=[],=]) set: type-parameter-list-body # Scope newline `meta.type` only, if type continues on next line. # Note: This is required to workaround ST's line blindness. - match: (?=\s*\n) branch_point: type-parameter-bound-end branch: - type-parameter-bound-continue - type-parameter-bound-end - include: type-parameter-bound-content type-parameter-bound-content: # Note: maybe type-hint expressions - include: type-constants - include: expression-in-a-group type-parameter-bound-continue: - meta_include_prototype: false - match: \s*(?=[],=]) fail: type-parameter-bound-end - include: comments - include: else-pop type-parameter-bound-end: - meta_include_prototype: false - match: '' pop: 2 push: type-parameter-list-body ###[ ASSIGNMENT STATEMENTS ]################################################## assignment-statements: - match: '{{colon}}' scope: punctuation.separator.annotation.python push: variable-annotation - match: '{{augmented_assignment_operators}}' scope: keyword.operator.assignment.augmented.python push: assignment-statement-value - match: '{{assignment_operator}}' scope: keyword.operator.assignment.python assignment-statement-value: - include: line-continuation-or-pop - include: illegal-assignment-expressions - include: expression-in-a-statement variable-annotation: - meta_include_prototype: false - include: line-continuation-or-pop - match: (?=\S) set: variable-annotation-body variable-annotation-body: - meta_content_scope: meta.type.python - match: (?=\s*[\n#):;=\]}]) pop: 1 - include: line-continuations - include: variable-annotation-content variable-annotation-content: # Note: maybe type-hint expressions - include: type-constants - include: expression-in-a-statement ###[ CASE STATEMENTS ]######################################################## case-statements: # https://www.python.org/dev/peps/pep-0634 - match: (?=case\b) branch_point: case-statements branch: - case-statement - structural-pattern-fallback case-statement: - match: case scope: meta.statement.conditional.case.python keyword.control.conditional.case.python set: - case-statement-pattern - case-statement-begin case-statement-begin: # fail if match is directly followed by `:` or end of statement - match: (?=$|#|;|:) fail: case-statements - include: allow-unpack-operators case-statement-end: - match: '{{colon}}' scope: meta.statement.conditional.case.python punctuation.section.block.conditional.case.python pop: 1 case-statement-fail: - match: (?=$|#|;) fail: case-statements case-statement-guard: - meta_content_scope: meta.statement.conditional.case.guard.python - include: case-statement-end - include: case-statement-fail - include: line-continuations - include: expression-in-a-statement case-statement-pattern: - meta_content_scope: meta.statement.conditional.case.patterns.python - match: (?=if\b) set: case-statement-guard - include: case-statement-end - include: case-statement-fail - include: case-pattern-expressions case-pattern-expressions: - include: case-pattern-capture-targets - include: case-pattern-classes - include: case-pattern-dictionaries - include: case-pattern-groups-or-tuples - include: case-pattern-lists - include: case-pattern-operators - include: illegal-assignment-expressions - include: sequence-separators - include: comments - include: booleans - include: nones - include: numbers - include: strings - include: illegal-names - include: qualified-name - include: illegal-stray-brackets - include: illegal-stray-braces - include: illegal-stray-parens - include: line-continuations case-pattern-capture-targets: - match: as\b scope: keyword.control.conditional.case.as.python push: case-pattern-capture-target case-pattern-capture-target: - include: wildcard-variable - include: illegal-name - include: generic-name - include: else-pop case-pattern-classes: - match: (?=(\.\s*)?{{path}}\s*\() push: - case-pattern-class-arguments-begin - case-pattern-class-wrapper - qualified-name-until-leaf case-pattern-class-wrapper: - match: (\.)\s* scope: meta.path.python captures: 1: punctuation.accessor.dot.python set: qualified-case-pattern-class-name - match: '' set: unqualified-case-pattern-class-name qualified-case-pattern-class-name: - meta_content_scope: meta.function-call.identifier.python meta.path.python - include: builtin-types - include: illegal-names - include: class-names - include: immediately-pop unqualified-case-pattern-class-name: - meta_scope: meta.function-call.identifier.python - include: builtin-types - include: illegal-names - include: class-names - include: immediately-pop case-pattern-class-arguments-begin: - meta_include_prototype: false - match: \( scope: punctuation.section.arguments.begin.python set: - case-pattern-class-arguments-body - allow-unpack-operators case-pattern-class-arguments-body: - meta_scope: meta.function-call.arguments.python - match: \) scope: punctuation.section.arguments.end.python pop: 1 - include: argument-separators - include: case-pattern-keyword-arguments - include: case-pattern-expressions case-pattern-keyword-arguments: - match: (?={{identifier}}\s*{{assignment_operator}}) push: case-pattern-keyword-argument-name case-pattern-keyword-argument-name: - match: '{{assignment_operator}}' scope: keyword.operator.assignment.python set: allow-unpack-operators - include: parameter-names case-pattern-operators: - match: '[-+]' scope: keyword.operator.arithmetic.python - match: \| scope: keyword.operator.logical.python case-pattern-dictionaries: - include: empty-dictionaries - match: \{ scope: punctuation.section.mapping.begin.python push: case-pattern-dictionary-body case-pattern-dictionary-end: - match: \} scope: punctuation.section.mapping.end.python pop: 1 case-pattern-dictionary-body: - meta_scope: meta.mapping.python - include: case-pattern-dictionary-end - include: comments - include: illegal-assignment-expressions - match: ',' scope: punctuation.separator.sequence.python - match: \*\* scope: keyword.operator.unpacking.mapping.python set: case-pattern-dictionary-unpacking - match: '{{colon}}' scope: punctuation.separator.key-value.python set: case-pattern-dictionary-value - match: (?=\S) set: case-pattern-dictionary-key case-pattern-dictionary-unpacking: - meta_content_scope: meta.mapping.python - match: (?=\s*[,:}]) set: case-pattern-dictionary-body - include: case-pattern-expressions case-pattern-dictionary-key: - meta_content_scope: meta.mapping.key.python - match: (?=\s*[,:}]) set: case-pattern-dictionary-body - include: case-pattern-expressions case-pattern-dictionary-value: - meta_include_prototype: false - meta_content_scope: meta.mapping.python - include: comments - match: (?=\S) set: - case-pattern-dictionary-value-body - allow-unpack-operators case-pattern-dictionary-value-body: - meta_content_scope: meta.mapping.value.python - match: (?=\s*[,}]) set: case-pattern-dictionary-body - include: case-pattern-expressions case-pattern-groups-or-tuples: - include: empty-tuples - match: (?=\() branch_point: case-pattern-groups-or-tuples branch: - case-pattern-group - case-pattern-tuple case-pattern-group: - match: \( scope: punctuation.section.group.begin.python set: case-pattern-group-body case-pattern-group-body: - meta_scope: meta.group.python - match: \) scope: punctuation.section.group.end.python pop: 1 - match: (?=,) fail: case-pattern-groups-or-tuples - include: case-pattern-expressions case-pattern-lists: - include: empty-lists - match: \[ scope: punctuation.section.sequence.begin.python push: - case-pattern-list-body - allow-unpack-operators case-pattern-list-body: - meta_scope: meta.sequence.list.python - match: \] scope: punctuation.section.sequence.end.python pop: 1 - include: case-pattern-expressions case-pattern-tuple: - match: \( scope: punctuation.section.sequence.begin.python set: - case-pattern-tuple-body - allow-unpack-operators case-pattern-tuple-body: - meta_scope: meta.sequence.tuple.python - match: \) scope: punctuation.section.sequence.end.python pop: 1 - include: case-pattern-expressions ###[ CONDITIONAL STATEMENTS ]################################################# conditional-statements: - match: if\b scope: keyword.control.conditional.if.python push: if-statement-condition - match: elif\b scope: keyword.control.conditional.elseif.python push: elif-statement-condition - match: (else)(?:\s*(:)|\b) scope: meta.statement.conditional.else.python captures: 1: keyword.control.conditional.else.python 2: punctuation.section.block.conditional.else.python if-statement-condition: - meta_scope: meta.statement.conditional.if.python - match: '{{colon}}' scope: punctuation.section.block.conditional.if.python pop: 1 - include: line-continuation-or-pop - include: expression-in-a-statement elif-statement-condition: - meta_scope: meta.statement.conditional.elseif.python - match: '{{colon}}' scope: punctuation.section.block.conditional.elseif.python pop: 1 - include: line-continuation-or-pop - include: expression-in-a-statement ###[ EXCEPTION STATEMENTS ]################################################### exception-statements: - match: (try)(?:\s*(:)|\b) scope: meta.statement.exception.try.python captures: 1: keyword.control.exception.try.python 2: punctuation.section.block.exception.try.python - match: (finally)(?:\s*(:)|\b) scope: meta.statement.exception.finally.python captures: 1: keyword.control.exception.finally.python 2: punctuation.section.block.exception.finally.python - match: except\b scope: keyword.control.exception.catch.python push: except-statement-exception-list except-statement-exception-list: - meta_scope: meta.statement.exception.catch.python - match: '{{colon}}' scope: punctuation.section.block.exception.catch.python pop: 1 - match: as\b scope: keyword.control.exception.catch.as.python set: except-statement-as - include: illegal-assignment-expressions - include: line-continuation-or-pop - include: expression-in-a-statement except-statement-as: - meta_content_scope: meta.statement.exception.catch.python - match: '{{colon}}' scope: meta.statement.exception.catch.python punctuation.section.block.exception.catch.python pop: 1 - include: illegal-assignment-expressions - include: line-continuation-or-pop - include: name ###[ FOR STATEMENTS ]######################################################### for-statements: - match: (?:(async)\s+)?(for)\b captures: 1: storage.modifier.async.python 2: keyword.control.loop.for.python push: for-statement-target-list for-statement-target-list: - meta_scope: meta.statement.loop.for.python - match: '{{colon}}' scope: invalid.illegal.missing-in.python pop: 1 - match: in\b scope: keyword.control.loop.for.in.python set: for-statement-in - include: line-continuation-or-pop - include: expression-in-a-statement for-statement-in: - meta_content_scope: meta.statement.loop.for.python - match: '{{colon}}' scope: meta.statement.loop.for.python punctuation.section.block.loop.for.python pop: 1 - include: line-continuation-or-pop - include: expression-in-a-statement ###[ MATCH STATEMENTS ]####################################################### match-statements: - match: (?=match\b) branch_point: match-statements branch: - match-statement - structural-pattern-fallback match-statement: - match: match scope: keyword.control.conditional.match.python set: - match-statement-body - match-statement-begin match-statement-begin: # fail if match is directly followed by `:` or end of statement - match: (?=$|#|;|:) fail: match-statements - include: line-continuations - include: allow-unpack-operators match-statement-body: - meta_scope: meta.statement.conditional.match.python - match: (?=$|#|;) fail: match-statements - include: match-statement-end - include: line-continuations - include: expression-in-a-statement match-statement-end: - match: '{{colon}}' scope: punctuation.section.block.conditional.match.python set: maybe-first-case-statement maybe-first-case-statement: # Disable detentation of first case statement by special indentation rule. # see: https://github.com/sublimehq/Packages/issues/3456 - match: case\b scope: meta.statement.conditional.case.python keyword.control.conditional.case.python set: - meta-disable-dedentation - case-statement-pattern - allow-unpack-operators - include: comments - include: else-pop meta-disable-dedentation: - meta_include_prototype: false - meta_scope: meta.disable-dedentation.python - include: else-pop structural-pattern-fallback: # Fallback context, which is used if `match` or `case` don't seem to # start a structural match pattern statement. - match: (?={{path}}\s*\() set: - function-call-argument-list - function-call-wrapper - qualified-name-until-leaf - include: generic-name ###[ MODIFIER STATEMENTS ]#################################################### modifier-statements: - match: global\b scope: storage.modifier.global.python push: modifier-statement-body - match: nonlocal\b scope: storage.modifier.nonlocal.python push: modifier-statement-body modifier-statement-body: - meta_scope: meta.statement.modifier.python - include: line-continuation-or-pop - include: name - match: ',' scope: punctuation.separator.storage-list.python - match: \S+ scope: invalid.illegal.name.storage.python ###[ WHILE STATEMENTS ]####################################################### while-statements: - match: while\b scope: keyword.control.loop.while.python push: while-statement-condition while-statement-condition: - meta_scope: meta.statement.loop.while.python - match: '{{colon}}' scope: punctuation.section.block.loop.while.python pop: 1 - include: line-continuation-or-pop - include: expression-in-a-statement ###[ WITH STATEMENTS ]######################################################## with-statements: - match: (?:(async)\s+)?(with)\b captures: 1: storage.modifier.async.python 2: keyword.control.flow.with.python branch_point: with-statement-tuple branch: - with-statement-tuple - with-statement-plain with-statement-plain: - meta_scope: meta.statement.with.python - match: '{{colon}}' scope: punctuation.section.block.with.python pop: 1 - match: as\b scope: keyword.control.flow.with.as.python push: with-statement-plain-as - include: line-continuation-or-pop - include: expression-in-a-statement with-statement-plain-as: - include: line-continuation-or-pop - include: generators-groups-and-tuples - include: lists - include: name - include: else-pop with-statement-tuple: - meta_scope: meta.statement.with.python - match: \( scope: punctuation.section.sequence.begin.python set: - with-statement-tuple-end - with-statement-tuple-body - include: with-statement-tuple-else-fail with-statement-tuple-body: - meta_scope: meta.sequence.tuple.python - match: \) scope: punctuation.section.sequence.end.python pop: 1 - match: as\b scope: keyword.control.flow.with.as.python push: with-statement-tuple-as - include: expression-in-a-sequence with-statement-tuple-as: - include: comments - include: generators-groups-and-tuples - include: lists - include: name - include: else-pop with-statement-tuple-end: - meta_content_scope: meta.statement.with.python - match: '{{colon}}' scope: meta.statement.with.python punctuation.section.block.with.python pop: 1 - include: with-statement-tuple-else-fail with-statement-tuple-else-fail: - include: line-continuations - match: (?=\S|$) fail: with-statement-tuple ###[ FLOW STATEMENTS ]######################################################## flow-statements: - match: assert\b scope: keyword.control.flow.assert.python - match: return\b scope: keyword.control.flow.return.python - match: break\b scope: keyword.control.flow.break.python - match: continue\b scope: keyword.control.flow.continue.python - match: pass\b scope: keyword.control.flow.pass.python - match: raise\b scope: keyword.control.flow.raise.python push: raise-statement-body raise-statement-body: - meta_scope: meta.statement.raise.python - match: from\b scope: keyword.control.flow.raise.from.python set: raise-statement-from - include: line-continuation-or-pop - include: expression-in-a-statement raise-statement-from: - meta_content_scope: meta.statement.raise.python - include: line-continuation-or-pop - include: expression-in-a-statement ###[ OTHER STATEMENTS ]####################################################### other-statements: - match: del\b scope: keyword.other.del.python - match: exec\b(?!\s*($|[,.()\]}])) scope: keyword.other.exec.python - match: print\b(?!\s*([,.()\]}])) scope: keyword.other.print.python ###[ FOR EXPRESSIONS ]######################################################## for-expressions: - match: (?:(async)\s+)?(for)\b captures: 1: storage.modifier.async.python 2: keyword.control.loop.for.generator.python push: for-expression-target-list for-expression-target-list: - meta_scope: meta.expression.generator.python - match: in\b scope: keyword.control.loop.for.in.python pop: 1 - match: (?=[)\]}]) pop: 1 - include: expression-in-a-group ###[ FLOW EXPRESSIONS ]####################################################### keywords: - match: if\b scope: keyword.control.conditional.if.python - match: else\b scope: keyword.control.conditional.else.python - match: await\b scope: keyword.control.flow.await.python - match: (yield)(?:\s+(from))?\b captures: 1: keyword.control.flow.yield.python 2: keyword.control.flow.yield-from.python ###[ FUNCTION CALLS ]######################################################### function-calls: - match: (?=(\.\s*)?{{path}}\s*\() push: - function-call-argument-list - function-call-wrapper - qualified-name-until-leaf function-call-wrapper: - match: (\.)\s* scope: meta.path.python captures: 1: punctuation.accessor.dot.python set: qualified-function-call-name - match: '' set: unqualified-function-call-name qualified-function-call-name: - meta_content_scope: meta.function-call.identifier.python meta.path.python - include: dotted-name-specials - include: constant-names - include: function-names - include: immediately-pop unqualified-function-call-name: - meta_scope: meta.function-call.identifier.python - include: name-specials - include: function-names - include: immediately-pop function-call-argument-list: - meta_include_prototype: false - match: \( scope: punctuation.section.arguments.begin.python set: - function-call-argument-list-body - allow-unpack-operators function-call-argument-list-body: - meta_scope: meta.function-call.arguments.python - match: \) scope: punctuation.section.arguments.end.python set: after-expression - include: arguments arguments: - include: argument-separators - include: keyword-arguments - include: expression-in-a-sequence argument-separators: - match: ',' scope: punctuation.separator.arguments.python push: allow-unpack-operators keyword-arguments: - match: (?={{identifier}}\s*{{assignment_operator}}) push: keyword-argument-name keyword-argument-name: - match: '{{assignment_operator}}' scope: keyword.operator.assignment.python set: - keyword-argument-value - allow-unpack-operators - include: parameter-names keyword-argument-value: - match: (?=[,)]|:(?!=)) pop: 1 - include: expression-in-a-group ###[ LAMBDAS ]################################################################ lambda-in-groups: # A lambda keyword within a group may be part of a generator expression # Hence pop contexts off stack if `for` keyword is matched in order to # not scope it invalid. - match: lambda(?=\s|:|$) scope: meta.function.inline.python storage.type.function.inline.python keyword.declaration.function.inline.python push: - lambda-in-group-parameters - allow-unpack-operators lambda-in-group-parameters: - meta_content_scope: meta.function.inline.parameters.python - match: '{{colon}}' scope: meta.function.inline.python punctuation.section.function.begin.python set: - meta_include_prototype: false - match: '' set: lambda-in-group-body - include: lambda-in-group-end - include: lambda-parameters-common lambda-in-group-body: - meta_scope: meta.function.inline.body.python - include: lambda-in-group-end - include: lambda-body lambda-in-group-end: - match: (?=for\b) pop: 1 lambdas: - match: lambda(?=\s|:|$) scope: meta.function.inline.python storage.type.function.inline.python keyword.declaration.function.inline.python push: - lambda-parameters - allow-unpack-operators lambda-parameters: - meta_content_scope: meta.function.inline.parameters.python - match: '{{colon}}' scope: meta.function.inline.python punctuation.section.function.begin.python set: - meta_include_prototype: false - match: '' set: lambda-body - include: lambda-parameters-common lambda-parameters-common: - match: ',' scope: punctuation.separator.parameters.python push: allow-unpack-operators - match: '{{assignment_operator}}' scope: keyword.operator.assignment.python push: - keyword-argument-value - allow-unpack-operators - include: function-parameter-tuples - include: parameter-names - include: illegal-assignment-expressions - include: line-continuation-or-pop - match: \S scope: invalid.illegal.expected-parameter.python lambda-body: - meta_scope: meta.function.inline.body.python - include: illegal-assignment-expressions # We don't know whether we are within a grouped # or line-statement context at this point. # If we're in a group, the underlying context will take over # at the end of the line. - match: (?=[,:)}\]])|$ pop: 1 - include: line-continuation-or-pop - include: expression-in-a-statement ###[ GENERATORS GROUPS TUBLES ]############################################### generators-groups-and-tuples: - include: empty-tuples - match: (?=\() branch_point: generators-groups-and-tuples branch: - maybe-group - maybe-tuple - maybe-generator maybe-group: - match: \( scope: punctuation.section.group.begin.python set: group-body group-body: - meta_scope: meta.group.python - match: \) scope: punctuation.section.group.end.python set: after-expression - match: (?=,|\bfor\b) fail: generators-groups-and-tuples - include: expression-in-a-sequence maybe-generator: - match: \( scope: punctuation.section.sequence.begin.python set: generator-body generator-body: - meta_scope: meta.sequence.generator.python - match: \) scope: punctuation.section.sequence.end.python set: after-expression - include: expression-in-a-sequence maybe-tuple: - match: \( scope: punctuation.section.sequence.begin.python set: tuple-body tuple-body: - meta_scope: meta.sequence.tuple.python - match: \) scope: punctuation.section.sequence.end.python set: after-expression - match: (?=for\b) fail: generators-groups-and-tuples - include: expression-in-a-sequence empty-tuples: - match: (\()\s*(\)) scope: meta.sequence.tuple.empty.python captures: 1: punctuation.section.sequence.begin.python 2: punctuation.section.sequence.end.python push: after-expression illegal-stray-parens: - match: \) scope: invalid.illegal.stray.python ###[ LISTS ]################################################################## lists: - include: empty-lists - match: \[ scope: punctuation.section.sequence.begin.python push: - list-body - allow-unpack-operators list-body: - meta_scope: meta.sequence.list.python - match: \] scope: punctuation.section.sequence.end.python set: after-expression - include: expression-in-a-sequence empty-lists: - match: (\[)\s*(\]) scope: meta.sequence.list.empty.python captures: 1: punctuation.section.sequence.begin.python 2: punctuation.section.sequence.end.python push: after-expression illegal-stray-brackets: - match: \] scope: invalid.illegal.stray.python ###[ DICTIONARIES AND SETS ]################################################## dictionaries-and-sets: - include: empty-dictionaries - match: (?=\{) branch_point: dictionaries-and-sets branch: - maybe-set - maybe-dictionary maybe-dictionary: - match: \{ scope: punctuation.section.mapping.begin.python set: allow-dictionary-unpack-operator dictionary-end: - match: \} scope: meta.mapping.python punctuation.section.mapping.end.python set: after-expression dictionary-separator: - match: ',' scope: punctuation.separator.sequence.python set: allow-dictionary-unpack-operator allow-dictionary-unpack-operator: - meta_scope: meta.mapping.python - include: comments - match: \*{3,} scope: invalid.illegal.syntax.python set: dictionary-unpacking-body - match: \*\* scope: keyword.operator.unpacking.mapping.python set: dictionary-unpacking-body - match: \* scope: invalid.illegal.unexpected-operator.python set: dictionary-unpacking-body - match: (?=\S) set: dictionary-body - match: ^(?!\s*([#*]|$)) set: dictionary-body dictionary-unpacking-body: - meta_content_scope: meta.mapping.python - include: dictionary-end - include: dictionary-separator - include: expression-in-a-group dictionary-body: - meta_content_scope: meta.mapping.python - include: dictionary-end - include: comments - include: illegal-assignment-expressions - include: illegal-commas - match: '{{colon}}' scope: meta.mapping.python punctuation.separator.key-value.python set: dictionary-value - match: (?=\S) set: directory-key-body directory-key-body: - meta_scope: meta.mapping.key.python - match: (?=\s*[,:}]) set: dictionary-body - include: expression-in-a-group dictionary-value: - meta_include_prototype: false - meta_content_scope: meta.mapping.python - include: dictionary-end - include: dictionary-separator - match: (?=\S) set: directory-value-body directory-value-body: - meta_content_scope: meta.mapping.value.python - match: (?=\s*[,}]) set: after-dictionary-value - match: (?=\s*(?:async|for)\b) set: dictionary-generator-body - include: expression-in-a-group after-dictionary-value: - meta_include_prototype: false - meta_content_scope: meta.mapping.python - include: dictionary-end - include: dictionary-separator dictionary-generator-body: - meta_content_scope: meta.mapping.python - include: dictionary-end - include: illegal-commas - include: expression-in-a-sequence maybe-set: - match: \{ scope: punctuation.section.set.begin.python set: - maybe-set-body - maybe-set-begin maybe-set-begin: - match: (?=\*\*) # looks like a dictionary fail: dictionaries-and-sets - include: allow-sequence-unpack-operators maybe-set-body: - meta_scope: meta.set.python - match: (?=,|:=) set: set-body - match: (?=:) fail: dictionaries-and-sets - include: set-body set-body: - meta_scope: meta.set.python - match: \} scope: punctuation.section.set.end.python set: after-expression - match: ',' scope: punctuation.separator.set.python push: allow-sequence-unpack-operators - include: expression-in-a-sequence - include: illegal-colons allow-sequence-unpack-operators: - include: comments - match: \*{3,} scope: invalid.illegal.syntax.python pop: 1 - match: \*\* scope: invalid.illegal.unexpected-operator.python pop: 1 - match: \* scope: keyword.operator.unpacking.sequence.python pop: 1 - include: else-pop - match: ^(?!\s*([#*]|$)) pop: 1 empty-dictionaries: - match: (\{)\s*(\}) scope: meta.mapping.empty.python captures: 1: punctuation.section.mapping.begin.python 2: punctuation.section.mapping.end.python push: after-expression illegal-colons: - match: '{{colon}}' scope: invalid.illegal.unexpected-colon.python illegal-commas: - match: ',' scope: invalid.illegal.unexpected-comma.python illegal-stray-braces: - match: \} scope: invalid.illegal.stray.python ###[ ITEM ACCESS ]############################################################ items: - match: (?={{path}}\s*\[) push: - item-access - qualified-name-content item-access: - match: \[ scope: punctuation.section.brackets.begin.python set: maybe-item-access-body maybe-item-access-body: - meta_scope: meta.brackets.python - match: \] scope: punctuation.section.brackets.end.python set: after-expression - match: '{{colon}}' scope: punctuation.separator.slice.python - include: expression-in-a-group ###[ OPERATORS ]############################################################## assignment-expressions: - match: := scope: keyword.operator.assignment.inline.python illegal-assignment-expressions: - match: := scope: invalid.illegal.assignment.python illegal-assignment: - match: \:?= scope: invalid.illegal.assignment.python pop: 1 - include: line-continuation-or-pop - include: else-pop operators: - match: '{{augmented_assignment_operators}}' scope: invalid.illegal.assignment.python - match: <> scope: invalid.deprecated.operator.python - match: <<|>>|\*\*|//|[-%&*+/@^|~] scope: keyword.operator.arithmetic.python - match: <=|>=|==|\!=|<|> scope: keyword.operator.comparison.python - match: = scope: invalid.illegal.assignment.python - match: (?:and|in|is|not|or)\b scope: keyword.operator.logical.python - include: sequence-separators allow-unpack-operators: # Match unpacking operators, if present - include: comments - match: \*{3,} scope: invalid.illegal.syntax.python pop: 1 - match: \*\* scope: keyword.operator.unpacking.mapping.python pop: 1 - match: \* scope: keyword.operator.unpacking.sequence.python pop: 1 - include: else-pop - match: ^(?!\s*([#*]|$)) pop: 1 sequence-separators: - match: ',' scope: punctuation.separator.sequence.python push: allow-unpack-operators statement-terminators: - match: ; scope: punctuation.terminator.statement.python ###[ IDENTIFIERS ]############################################################ name: - match: (?={{identifier}}) push: name-content name-content: - include: name-specials - include: constant-names - include: generic-names - include: immediately-pop dotted-name: - match: \s*(\.)\s*(?={{identifier}}) captures: 1: punctuation.accessor.dot.python push: dotted-name-content dotted-name-content: - include: dotted-name-specials - include: constant-names - include: generic-names - include: immediately-pop qualified-name: - match: (?={{path}}) push: qualified-name-content - match: \. scope: punctuation.accessor.dot.python qualified-name-content: - meta_scope: meta.path.python - include: name - include: dotted-name - include: immediately-pop qualified-name-until-leaf: # Push this together with another context to match a qualified name # until the last non-special identifier (if any). # This allows the leaf to be scoped individually. - meta_scope: meta.path.python # If a line continuation follows, this may or may not be the last leaf (most likley not though) - match: (?={{identifier}}\s*(\.|\\)) push: name-content - match: (\.)\s*(?={{identifier}}\s*(\.|\\)) captures: 1: punctuation.accessor.dot.python push: dotted-name-content - match: \.(?!\s*{{identifier}}) # don't match last dot scope: punctuation.accessor.dot.python - match: (?=\S|$) pop: 1 name-specials: - include: builtin-exceptions - include: builtin-functions - include: builtin-types - include: magic-functions - include: magic-variables - include: class-variables - include: wildcard-variables - include: illegal-names dotted-name-specials: - include: magic-functions - include: magic-variables - include: illegal-names builtin-exceptions: - match: '{{builtin_exceptions}}' scope: support.class.exception.python builtin-functions: - match: '{{builtin_functions}}' scope: support.function.builtin.python - match: '{{typing_functions}}' scope: support.function.typing.python builtin-types: - match: '{{builtin_types}}' scope: support.type.python - match: '{{typing_types}}' scope: support.class.typing.python magic-functions: # these methods have magic interpretation by python and are generally called indirectly through syntactic constructs # https://docs.python.org/2/reference/datamodel.html # https://docs.python.org/3/reference/datamodel.html - match: '{{magic_functions}}' scope: support.function.magic.python magic-variables: # magic variables which a class/module/object may have. # https://docs.python.org/3/library/inspect.html#types-and-members # https://docs.python.org/3/reference/datamodel.html#object.__slots__ # https://docs.python.org/3/reference/datamodel.html#preparing-the-class-namespace - match: '{{magic_variables}}' scope: support.variable.magic.python class-names: - match: '{{identifier}}' scope: support.class.python constant-names: - match: '{{identifier_constant}}' scope: variable.other.constant.python function-names: - match: '{{identifier}}' scope: variable.function.python generic-names: - match: '{{identifier}}' scope: meta.generic-name.python generic-name: - match: '{{identifier}}' scope: meta.generic-name.python pop: 1 illegal-names: - match: '{{illegal_names}}\b' scope: invalid.illegal.name.python illegal-name: - match: '{{illegal_names}}\b' scope: invalid.illegal.name.python pop: 1 class-variables: - match: (?:self|cls)\b scope: variable.language.python parameter-names: - include: illegal-names - match: '{{identifier}}' scope: variable.parameter.python wildcard-variables: - match: _(?!{{identifier_continue}}) scope: variable.language.anonymous.python wildcard-variable: - match: _(?!{{identifier_continue}}) scope: variable.language.anonymous.python pop: 1 ###[ LITERALS ]############################################################### constants: - include: booleans - include: nones - match: (?:Ellipsis|NotImplemented|__debug__)\b scope: constant.language.python push: illegal-assignment - match: \.{3}(?!\w) scope: constant.language.python booleans: - match: False\b scope: constant.language.boolean.false.python push: illegal-assignment - match: True\b scope: constant.language.boolean.true.python push: illegal-assignment nones: - match: None\b scope: constant.language.null.python push: illegal-assignment numbers: # https://docs.python.org/3/reference/lexical_analysis.html#numeric-literals # hexadecimal - match: (0[xX])(\h*)([lL]) # py2 scope: meta.number.integer.hexadecimal.python captures: 1: constant.numeric.base.python 2: constant.numeric.value.python 3: constant.numeric.suffix.python - match: (0[xX])((?:_?\h)+) scope: meta.number.integer.hexadecimal.python captures: 1: constant.numeric.base.python 2: constant.numeric.value.python # octal - match: (0[oO]?)((?=[oO]|[0-7])[0-7]*)([lL]) # py2 scope: meta.number.integer.octal.python captures: 1: constant.numeric.base.python 2: constant.numeric.value.python 3: constant.numeric.suffix.python - match: (0)([0-7]+)(\d*) # py2 scope: meta.number.integer.octal.python captures: 1: constant.numeric.base.python 2: constant.numeric.value.python 3: invalid.illegal.digit.python - match: (0[oO])((?:_?[0-7])+)(\d*) scope: meta.number.integer.octal.python captures: 1: constant.numeric.base.python 2: constant.numeric.value.python 3: invalid.illegal.digit.python # binary - match: (0[bB])([01]*)([lL]) # py2 scope: meta.number.integer.binary.python captures: 1: constant.numeric.base.python 2: constant.numeric.value.python 3: constant.numeric.suffix.python - match: (0[bB])((?:_?[01])*)(\d*) scope: meta.number.integer.binary.python captures: 1: constant.numeric.base.python 2: constant.numeric.value.python 3: invalid.illegal.digit.python # complex - match: |- (?x) ( # 1.j, 1.1j, 1.1e1j, 1.1e-1j, 1.e1j, 1.e-1 | 1e1j, 1e-1j {{digits}} (\.)? {{digits}}? {{exponent}}? # .1j, .1e1j, .1e-1j | (\.) {{digits}} {{exponent}}? ) ([jJ]) scope: meta.number.imaginary.decimal.python captures: 1: constant.numeric.value.python 2: punctuation.separator.decimal.python 3: punctuation.separator.decimal.python 4: constant.numeric.suffix.python # floating point - match: |- (?x: # 1., 1.1, 1.1e1, 1.1e-1, 1.e1, 1.e-1 | 1e1, 1e-1 {{digits}} (?: (\.) {{digits}}? {{exponent}}? | {{exponent}} ) # .1, .1e1, .1e-1 | (\.) {{digits}} {{exponent}}? ) scope: meta.number.float.decimal.python constant.numeric.value.python captures: 1: punctuation.separator.decimal.python 2: punctuation.separator.decimal.python # integer - match: ([1-9]\d*|0)([lL])\b # py2 scope: meta.number.integer.decimal.python captures: 1: constant.numeric.value.python 2: constant.numeric.suffix.python - match: (?:(0?)[1-9][\d_]*|0) scope: meta.number.integer.decimal.python constant.numeric.value.python captures: 1: invalid.illegal.digits.python ###[ DOCSTRINGS ]############################################################# docstrings: - include: double-quoted-docstrings - include: single-quoted-docstrings double-quoted-docstrings: - match: ^\s*(?i)(u)?(""") captures: 1: storage.type.string.python 2: comment.block.documentation.python punctuation.definition.comment.begin.python push: maybe-double-quoted-docstring-summery - match: ^\s*(?i)(ur|ru?)(""") captures: 1: storage.type.string.python 2: comment.block.documentation.python punctuation.definition.comment.begin.python push: maybe-double-quoted-raw-docstring-summery maybe-double-quoted-docstring-summery: - meta_content_scope: comment.block.documentation.python - include: double-quoted-docstring-end - match: (?=\S) set: double-quoted-docstring-summery double-quoted-docstring-summery: - meta_content_scope: comment.block.documentation.summary.python - match: $ set: double-quoted-docstring-body - include: double-quoted-docstring-body double-quoted-docstring-end: - match: '"""' scope: comment.block.documentation.python punctuation.definition.comment.end.python pop: 1 double-quoted-docstring-body: - meta_content_scope: comment.block.documentation.python - include: double-quoted-docstring-end - include: escaped-unicode-chars - include: escaped-chars maybe-double-quoted-raw-docstring-summery: - meta_content_scope: comment.block.documentation.python - include: double-quoted-docstring-end - match: (?=\S) set: double-quoted-raw-docstring-summery double-quoted-raw-docstring-summery: - meta_content_scope: comment.block.documentation.summary.python - match: $ set: double-quoted-raw-docstring-body - include: double-quoted-raw-docstring-body double-quoted-raw-docstring-body: - meta_content_scope: comment.block.documentation.python - include: double-quoted-docstring-end - include: escaped-raw-quotes single-quoted-docstrings: - match: ^\s*(?i)(u)?(''') captures: 1: storage.type.string.python 2: comment.block.documentation.python punctuation.definition.comment.begin.python push: maybe-single-quoted-docstring-summery - match: ^\s*(?i)(ur|ru?)(''') captures: 1: storage.type.string.python 2: comment.block.documentation.python punctuation.definition.comment.begin.python push: maybe-single-quoted-raw-docstring-summery single-quoted-docstring-end: - match: "'''" scope: comment.block.documentation.python punctuation.definition.comment.end.python pop: 1 maybe-single-quoted-docstring-summery: - meta_content_scope: comment.block.documentation.python - include: single-quoted-docstring-end - match: (?=\S) set: single-quoted-docstring-summery single-quoted-docstring-summery: - meta_content_scope: comment.block.documentation.summary.python - match: $ set: single-quoted-docstring-body - include: single-quoted-docstring-body single-quoted-docstring-body: - meta_content_scope: comment.block.documentation.python - include: single-quoted-docstring-end - include: escaped-unicode-chars - include: escaped-chars maybe-single-quoted-raw-docstring-summery: - meta_content_scope: comment.block.documentation.python - include: single-quoted-docstring-end - match: (?=\S) set: single-quoted-raw-docstring-summery single-quoted-raw-docstring-summery: - meta_content_scope: comment.block.documentation.summary.python - match: $ set: single-quoted-raw-docstring-body - include: single-quoted-raw-docstring-body single-quoted-raw-docstring-body: - meta_content_scope: comment.block.documentation.python - include: single-quoted-docstring-end - include: escaped-raw-quotes ###[ STRINGS ]################################################################ strings: - match: (?={{string_prefix}}['"]) push: string string: - meta_include_prototype: false # triple-quoted versions must be matched first - include: triple-double-quoted-string - include: double-quoted-string - include: triple-single-quoted-string - include: single-quoted-string ###[ TRIPLE DOUBLE QUOTED STRINGS ]########################################### triple-double-quoted-string: - include: triple-double-quoted-plain-raw-b-string - include: triple-double-quoted-raw-b-string - include: triple-double-quoted-plain-raw-f-string - include: triple-double-quoted-raw-f-string - include: triple-double-quoted-plain-raw-u-string - include: triple-double-quoted-raw-u-string - include: triple-double-quoted-b-string - include: triple-double-quoted-f-string - include: triple-double-quoted-u-string triple-double-quoted-string-end: - match: '"""' scope: meta.string.python string.quoted.double.block.python punctuation.definition.string.end.python set: after-expression triple-double-quoted-string-pop: - match: (?=""") pop: 1 triple-double-quoted-plain-raw-b-string: # Triple-quoted capital R raw string, bytes, no syntax embedding - match: ([bB]R|R[bB])(""") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python set: triple-double-quoted-plain-raw-b-string-body triple-double-quoted-plain-raw-b-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.block.python - include: triple-double-quoted-string-end - include: triple-double-quoted-plain-raw-b-string-content triple-double-quoted-plain-raw-b-string-content: - include: string-prototype - include: escaped-raw-quotes triple-double-quoted-raw-b-string: # Triple-quoted raw string, bytes, will use regex - match: ([bB]r|r[bB])(""") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python set: triple-double-quoted-raw-b-string-body triple-double-quoted-raw-b-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.block.python source.regexp.python - include: triple-double-quoted-string-end - match: '' push: scope:source.regexp.python#base-literal with_prototype: - include: triple-double-quoted-string-pop - include: triple-double-quoted-raw-b-string-content triple-double-quoted-raw-b-string-content: - include: string-prototype triple-double-quoted-plain-raw-f-string: # Triple-quoted raw f-string - match: ([fF]R|R[fF])(""") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python set: triple-double-quoted-plain-raw-f-string-body triple-double-quoted-plain-raw-f-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.block.python - include: triple-double-quoted-string-end - include: triple-double-quoted-plain-raw-f-string-content triple-double-quoted-plain-raw-f-string-content: - include: string-prototype - include: escaped-raw-quotes - include: triple-double-quoted-f-string-replacements triple-double-quoted-raw-f-string: # Triple-quoted raw f-string, treated as regex - match: ([fF]r|r[fF])(""") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python set: triple-double-quoted-raw-f-string-body triple-double-quoted-raw-f-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.block.python source.regexp.python - include: triple-double-quoted-string-end - match: '' push: scope:source.regexp.python#base-literal with_prototype: - include: triple-double-quoted-string-pop - include: triple-double-quoted-raw-f-string-content triple-double-quoted-raw-f-string-content: - include: string-prototype - include: triple-double-quoted-f-string-replacements-regexp triple-double-quoted-plain-raw-u-string: # Triple-quoted capital R raw string, unicode or not, no syntax embedding - match: ([uU]?R)(""") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python set: triple-double-quoted-plain-raw-u-string-body triple-double-quoted-plain-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.block.python - include: triple-double-quoted-string-end - include: triple-double-quoted-plain-raw-u-string-content triple-double-quoted-plain-raw-u-string-content: - include: string-prototype - include: escaped-raw-quotes - include: escaped-unicode-chars triple-double-quoted-raw-u-string: # Triple-quoted raw string, unicode or not, will detect SQL, otherwise regex - match: ([uU]?r)(""") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python set: triple-double-quoted-raw-u-string-body triple-double-quoted-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.block.python - include: triple-double-quoted-string-end - include: triple-double-quoted-raw-u-string-syntax triple-double-quoted-raw-u-string-syntax: - match: (?={{sql_indicator}}) set: triple-double-quoted-sql-raw-u-string-body - match: (?=\S) set: triple-double-quoted-regexp-raw-u-string-body triple-double-quoted-regexp-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.block.python source.regexp.python - include: triple-double-quoted-string-end - match: '' push: scope:source.regexp.python#base-literal with_prototype: - include: triple-double-quoted-string-pop - include: triple-double-quoted-regexp-raw-u-string-content triple-double-quoted-regexp-raw-u-string-content: - include: string-prototype - include: escaped-unicode-chars triple-double-quoted-sql-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python - include: triple-double-quoted-string-end - match: '' push: scope:source.sql with_prototype: - include: triple-double-quoted-string-pop - include: triple-double-quoted-sql-raw-u-string-content triple-double-quoted-sql-raw-u-string-content: - include: string-prototype - include: escaped-raw-quotes - include: escaped-unicode-chars - include: string-placeholders - include: triple-double-quoted-string-replacements triple-double-quoted-b-string: # Triple-quoted string, bytes, no syntax embedding - match: ([bB])(""") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python set: triple-double-quoted-b-string-body triple-double-quoted-b-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.block.python - include: triple-double-quoted-string-end - include: triple-double-quoted-b-string-content triple-double-quoted-b-string-content: - include: string-prototype - include: string-continuations - include: escaped-chars - include: string-placeholders - include: triple-double-quoted-string-replacements triple-double-quoted-f-string: # Triple-quoted f-string - match: ([fF])(""") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python set: triple-double-quoted-f-string-body triple-double-quoted-f-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.block.python - include: triple-double-quoted-string-end - include: triple-double-quoted-f-string-content triple-double-quoted-f-string-content: - include: string-prototype - include: string-continuations - include: triple-double-quoted-f-string-replacements - include: escaped-unicode-chars - include: escaped-chars triple-double-quoted-u-string: # Triple-quoted string, unicode or not, will detect SQL - match: ([uU]?)(""") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python set: triple-double-quoted-u-string-body triple-double-quoted-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.block.python - include: triple-double-quoted-string-end - include: string-continuations - include: triple-double-quoted-u-string-syntax triple-double-quoted-u-string-syntax: - match: (?={{sql_indicator}}) set: triple-double-quoted-sql-u-strings-body - match: (?=\S) set: double-quoted-plain-u-block-string-body double-quoted-plain-u-block-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.block.python - include: triple-double-quoted-string-end - include: triple-double-quoted-u-string-content triple-double-quoted-sql-u-strings-body: - meta_include_prototype: false - meta_content_scope: meta.string.python - include: triple-double-quoted-string-end - match: '' push: scope:source.sql with_prototype: - include: triple-double-quoted-string-pop - include: triple-double-quoted-u-string-content triple-double-quoted-u-string-content: - include: string-prototype - include: string-continuations - include: escaped-unicode-chars - include: escaped-chars - include: string-placeholders - include: triple-double-quoted-string-replacements triple-double-quoted-string-replacements: - include: escaped-string-braces - match: (?=\{) branch_point: triple-double-quoted-string-replacement branch: - triple-double-quoted-string-replacement - string-replacement-fallback triple-double-quoted-string-replacement: - match: \{ scope: punctuation.definition.placeholder.begin.python set: triple-double-quoted-string-replacement-body triple-double-quoted-string-replacement-body: - meta_scope: constant.other.placeholder.python - include: string-replacement-body - match: \[ scope: punctuation.section.brackets.begin.python push: triple-double-string-replacement-brackets-body - match: ':' scope: punctuation.separator.format-spec.python push: triple-double-quoted-string-replacement-formatspec-body - match: (?!\w) # restrict field names to reduce risk of false positives fail: triple-double-quoted-string-replacement triple-double-string-replacement-brackets-body: - include: string-replacement-brackets-body - include: triple-double-quoted-string-replacement-fail triple-double-quoted-string-replacement-formatspec-body: - meta_content_scope: meta.format-spec.python constant.other.format-spec.python - include: string-replacement-formatspec-body - match: \{ scope: punctuation.definition.placeholder.begin.python push: triple-double-quoted-string-replacement-body - include: triple-double-quoted-string-replacement-fail triple-double-quoted-string-replacement-fail: - match: (?="""|$) fail: triple-double-quoted-string-replacement triple-double-quoted-f-string-replacements: - include: f-string-replacements - match: \{ scope: punctuation.section.interpolation.begin.python push: - f-string-replacement-meta - triple-double-quoted-f-string-replacement-formatspec - triple-double-quoted-f-string-replacement-expression triple-double-quoted-f-string-replacements-regexp: # Same as f-string-replacements, but will reset the entire scope stack. - include: f-string-replacements-regexp - match: '{{fstring_regexp_interpolation_begin}}' scope: punctuation.section.interpolation.begin.python push: - f-string-replacement-regexp-meta - triple-double-quoted-f-string-replacement-formatspec - triple-double-quoted-f-string-replacement-expression triple-double-quoted-f-string-replacement-expression: - meta_content_scope: source.python.embedded - include: f-string-replacement-expression triple-double-quoted-f-string-replacement-formatspec: - meta_include_prototype: false - match: ':' scope: punctuation.separator.format-spec.python set: triple-double-quoted-f-string-replacement-formatspec-body - include: triple-double-quoted-f-string-replacement-end triple-double-quoted-f-string-replacement-formatspec-body: - meta_content_scope: meta.format-spec.python constant.other.format-spec.python - include: triple-double-quoted-f-string-replacement-end - include: triple-double-quoted-f-string-replacements triple-double-quoted-f-string-replacement-end: - include: f-string-replacement-end - match: (?=""") pop: 2 ###[ DOUBLE QUOTED STRINGS ]################################################## double-quoted-strings: - match: (?={{string_prefix}}"(?!")) push: double-quoted-string double-quoted-string: - meta_include_prototype: false - include: double-quoted-plain-raw-b-string - include: double-quoted-raw-b-string - include: double-quoted-plain-raw-f-string - include: double-quoted-raw-f-string - include: double-quoted-plain-raw-u-string - include: double-quoted-raw-u-string - include: double-quoted-b-string - include: double-quoted-f-string - include: double-quoted-u-string double-quoted-string-end: - match: '"' scope: meta.string.python string.quoted.double.python punctuation.definition.string.end.python set: after-expression - match: \n scope: meta.string.python string.quoted.double.python invalid.illegal.unclosed-string.python set: after-expression - include: string-continuations double-quoted-string-pop: - match: (?="|\n) pop: 1 - include: string-continuations double-quoted-plain-raw-b-string: # Single-line capital R raw string, bytes, no syntax embedding - match: ([bB]R|R[bB])(") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python set: double-quoted-plain-raw-b-string-body double-quoted-plain-raw-b-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.python - include: double-quoted-string-end - include: double-quoted-plain-raw-b-string-content double-quoted-plain-raw-b-string-content: - include: string-prototype - include: escaped-raw-quotes double-quoted-raw-b-string: # Single-line raw string, bytes, treated as regex - match: ([bB]r|r[bB])(") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python set: double-quoted-raw-b-string-body double-quoted-raw-b-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.python source.regexp.python - include: double-quoted-string-end - match: '' push: scope:source.regexp.python#base-literal with_prototype: - include: double-quoted-string-pop - include: double-quoted-raw-b-string-content double-quoted-raw-b-string-content: - include: string-prototype double-quoted-plain-raw-f-string: # Single-line raw f-string - match: (R[fF]|[fF]R)(") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python set: double-quoted-plain-raw-f-string-body double-quoted-plain-raw-f-string-body: - meta_content_scope: meta.string.python string.quoted.double.python - meta_include_prototype: false - include: double-quoted-string-end - include: double-quoted-plain-raw-f-string-content double-quoted-plain-raw-f-string-content: - include: string-prototype - include: escaped-raw-quotes - include: double-quoted-f-string-replacements double-quoted-raw-f-string: # Single-line raw f-string, treated as regex - match: (r[fF]|[fF]r)(") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python set: double-quoted-raw-f-string-body double-quoted-raw-f-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.python source.regexp.python - include: double-quoted-string-end - match: '' push: scope:source.regexp.python#base-literal with_prototype: - include: double-quoted-string-pop - include: double-quoted-raw-f-string-content double-quoted-raw-f-string-content: - include: string-prototype - include: double-quoted-f-string-replacements-regexp double-quoted-plain-raw-u-string: # Single-line capital R raw string, unicode or not, no syntax embedding - match: ([uU]?R)(") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python set: double-quoted-plain-raw-u-string-body double-quoted-plain-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.python - include: double-quoted-string-end - include: double-quoted-plain-raw-u-string-content double-quoted-plain-raw-u-string-content: - include: string-prototype - include: escaped-raw-quotes double-quoted-raw-u-string: - match: ([uU]?r)(") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python set: double-quoted-raw-u-string-body double-quoted-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.block.python - include: double-quoted-string-end - include: double-quoted-raw-u-string-syntax double-quoted-raw-u-string-syntax: # Single-line raw string, unicode or not, starting with a SQL keyword - match: (?={{sql_indicator}}) set: double-quoted-sql-raw-u-string-body # Single-line raw string, unicode or not, treated as regex - match: (?=\S) set: double-quoted-regexp-raw-u-string-body double-quoted-regexp-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.python source.regexp.python - include: double-quoted-string-end - match: '' push: scope:source.regexp.python#base-literal with_prototype: - include: double-quoted-string-pop - include: double-quoted-regexp-raw-u-string-content double-quoted-regexp-raw-u-string-content: - include: string-prototype double-quoted-sql-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python - include: double-quoted-string-end - match: '' push: scope:source.sql with_prototype: - include: double-quoted-string-pop - include: double-quoted-sql-raw-u-string-content double-quoted-sql-raw-u-string-content: - include: string-prototype - include: escaped-raw-quotes - include: string-placeholders - include: double-quoted-string-replacements double-quoted-b-string: # Single-line string, bytes - match: ([bB])(") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python set: double-quoted-b-string-body double-quoted-b-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.python - include: double-quoted-string-end - include: double-quoted-b-string-content double-quoted-b-string-content: - include: string-prototype - include: escaped-chars - include: string-placeholders - include: double-quoted-string-replacements double-quoted-f-string: # Single-line f-string - match: ([fF])(") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python set: double-quoted-f-string-body double-quoted-f-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.python - include: double-quoted-string-end - include: double-quoted-f-string-content double-quoted-f-string-content: - include: string-prototype - include: double-quoted-f-string-replacements - include: escaped-unicode-chars - include: escaped-chars double-quoted-u-string: - match: ([uU]?)(") captures: 1: storage.type.string.python 2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python set: double-quoted-u-string-body double-quoted-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.python - include: double-quoted-string-end - include: double-quoted-u-string-syntax double-quoted-u-string-syntax: # Single-line string, unicode or not, starting with a SQL keyword - match: (?={{sql_indicator}}) set: double-quoted-sql-u-string-body # Single-line string, unicode or not - match: (?=\S) set: double-quoted-plain-u-string-body double-quoted-plain-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.double.python - include: double-quoted-string-end - include: double-quoted-u-string-content double-quoted-sql-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python - include: double-quoted-string-end - match: '' push: scope:source.sql with_prototype: - include: double-quoted-string-pop - include: double-quoted-u-string-content double-quoted-u-string-content: - include: string-prototype - include: escaped-unicode-chars - include: escaped-chars - include: string-placeholders - include: double-quoted-string-replacements double-quoted-string-replacements: - include: escaped-string-braces - match: (?=\{) branch_point: double-quoted-string-replacement branch: - double-quoted-string-replacement - string-replacement-fallback double-quoted-string-replacement: - match: \{ scope: punctuation.definition.placeholder.begin.python set: double-quoted-string-replacement-body double-quoted-string-replacement-body: - meta_scope: constant.other.placeholder.python - include: string-replacement-body - match: \[ scope: punctuation.section.brackets.begin.python push: double-quoted-string-replacement-brackets-body - match: ':' scope: punctuation.separator.format-spec.python push: double-quoted-string-replacement-formatspec-body - match: (?!\w) # restrict field names to reduce risk of false positives fail: double-quoted-string-replacement double-quoted-string-replacement-brackets-body: - include: string-replacement-brackets-body - include: double-quoted-string-replacement-fail double-quoted-string-replacement-formatspec-body: - meta_content_scope: meta.format-spec.python constant.other.format-spec.python - include: string-replacement-formatspec-body - match: \{ scope: punctuation.definition.placeholder.begin.python push: double-quoted-string-replacement-body - include: double-quoted-string-replacement-fail double-quoted-string-replacement-fail: - match: (?="|$) fail: double-quoted-string-replacement double-quoted-f-string-replacements: - include: f-string-replacements - match: \{ scope: punctuation.section.interpolation.begin.python push: - f-string-replacement-meta - double-quoted-f-string-replacement-formatspec - double-quoted-f-string-replacement-expression double-quoted-f-string-replacements-regexp: # Same as f-string-replacements, but will reset the entire scope stack. - include: f-string-replacements-regexp - match: '{{fstring_regexp_interpolation_begin}}' scope: punctuation.section.interpolation.begin.python push: - f-string-replacement-regexp-meta - double-quoted-f-string-replacement-formatspec - double-quoted-f-string-replacement-expression double-quoted-f-string-replacement-expression: - meta_content_scope: source.python.embedded - include: f-string-replacement-expression - include: eol-pop double-quoted-f-string-replacement-formatspec: - meta_include_prototype: false - match: ':' scope: punctuation.separator.format-spec.python set: double-quoted-f-string-replacement-formatspec-body - include: double-quoted-f-string-replacement-end double-quoted-f-string-replacement-formatspec-body: - meta_content_scope: meta.format-spec.python constant.other.format-spec.python - include: double-quoted-f-string-replacement-end - include: double-quoted-f-string-replacements double-quoted-f-string-replacement-end: - include: f-string-replacement-end - match: (?="|$) pop: 2 ###[ TRIPLE SINGLE QUOTED STRINGS ]########################################### triple-single-quoted-string: - include: triple-single-quoted-plain-raw-b-string - include: triple-single-quoted-raw-b-string - include: triple-single-quoted-plain-raw-f-string - include: triple-single-quoted-raw-f-string - include: triple-single-quoted-plain-raw-u-string - include: triple-single-quoted-raw-u-string - include: triple-single-quoted-b-string - include: triple-single-quoted-f-string - include: triple-single-quoted-u-string triple-single-quoted-string-end: - match: "'''" scope: meta.string.python string.quoted.single.block.python punctuation.definition.string.end.python set: after-expression triple-single-quoted-string-pop: - match: (?=''') pop: 1 triple-single-quoted-plain-raw-b-string: # Triple-quoted capital R raw string, bytes, no syntax embedding - match: ([bB]R|R[bB])(''') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python set: triple-single-quoted-plain-raw-b-string-body triple-single-quoted-plain-raw-b-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.block.python - include: triple-single-quoted-string-end - include: triple-single-quoted-plain-raw-b-string-content triple-single-quoted-plain-raw-b-string-content: - include: string-prototype - include: escaped-raw-quotes triple-single-quoted-raw-b-string: # Triple-quoted raw string, bytes, will use regex - match: ([bB]r|r[bB])(''') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python set: triple-single-quoted-raw-b-string-body triple-single-quoted-raw-b-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.block.python source.regexp.python - include: triple-single-quoted-string-end - match: '' push: scope:source.regexp.python#base-literal with_prototype: - include: triple-single-quoted-string-pop - include: triple-single-quoted-raw-b-string-content triple-single-quoted-raw-b-string-content: - include: string-prototype triple-single-quoted-plain-raw-f-string: # Triple-quoted raw f-string - match: ([fF]R|R[fF])(''') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python set: triple-single-quoted-plain-raw-f-string-body triple-single-quoted-plain-raw-f-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.block.python - include: triple-single-quoted-string-end - include: triple-single-quoted-plain-raw-f-string-content triple-single-quoted-plain-raw-f-string-content: - include: string-prototype - include: escaped-raw-quotes - include: triple-single-quoted-f-string-replacements triple-single-quoted-raw-f-string: # Triple-quoted raw f-string, treated as regex - match: ([fF]r|r[fF])(''') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python set: triple-single-quoted-raw-f-string-body triple-single-quoted-raw-f-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.block.python source.regexp.python - include: triple-single-quoted-string-end - match: '' push: scope:source.regexp.python#base-literal with_prototype: - include: triple-single-quoted-string-pop - include: triple-single-quoted-raw-f-string-content triple-single-quoted-raw-f-string-content: - include: string-prototype - include: triple-single-quoted-f-string-replacements-regexp triple-single-quoted-plain-raw-u-string: # Triple-quoted capital R raw string, unicode or not, no syntax embedding - match: ([uU]?R)(''') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python set: triple-single-quoted-plain-raw-u-string-body triple-single-quoted-plain-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.block.python - include: triple-single-quoted-string-end - include: triple-single-quoted-plain-raw-u-string-content triple-single-quoted-plain-raw-u-string-content: - include: string-prototype - include: escaped-raw-quotes triple-single-quoted-raw-u-string: # Triple-quoted raw string, unicode or not, will detect SQL, otherwise regex - match: ([uU]?r)(''') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python set: triple-single-quoted-raw-u-string-body triple-single-quoted-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.block.python - include: triple-single-quoted-string-end - include: triple-single-quoted-raw-u-string-syntax triple-single-quoted-raw-u-string-syntax: - match: (?={{sql_indicator}}) set: triple-single-quoted-sql-raw-u-string-body - match: (?=\S) set: triple-single-quoted-regexp-raw-u-string-body triple-single-quoted-regexp-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.block.python source.regexp.python - include: triple-single-quoted-string-end - match: '' push: scope:source.regexp.python#base-literal with_prototype: - include: triple-single-quoted-string-pop - include: triple-single-quoted-regexp-raw-u-string-content triple-single-quoted-regexp-raw-u-string-content: - include: string-prototype - include: escaped-unicode-chars triple-single-quoted-sql-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python - include: triple-single-quoted-string-end - match: '' push: scope:source.sql with_prototype: - include: triple-single-quoted-string-pop - include: triple-single-quoted-sql-raw-u-string-content triple-single-quoted-sql-raw-u-string-content: - include: string-prototype - include: escaped-raw-quotes - include: escaped-unicode-chars - include: string-placeholders - include: triple-single-quoted-string-replacements triple-single-quoted-b-string: # Triple-quoted string, bytes, no syntax embedding - match: ([bB])(''') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python set: triple-single-quoted-b-string-body triple-single-quoted-b-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.block.python - include: triple-single-quoted-string-end - include: triple-single-quoted-b-string-content triple-single-quoted-b-string-content: - include: string-prototype - include: string-continuations - include: escaped-chars - include: string-placeholders - include: triple-single-quoted-string-replacements triple-single-quoted-f-string: # Triple-quoted f-string - match: ([fF])(''') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python set: triple-single-quoted-f-string-body triple-single-quoted-f-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.block.python - include: triple-single-quoted-string-end - include: triple-single-quoted-f-string-content triple-single-quoted-f-string-content: - include: string-prototype - include: string-continuations - include: triple-single-quoted-f-string-replacements - include: escaped-unicode-chars - include: escaped-chars triple-single-quoted-u-string: # Triple-quoted string, unicode or not, will detect SQL - match: ([uU]?)(''') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python set: triple-single-quoted-u-string-body triple-single-quoted-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.block.python - include: triple-single-quoted-string-end - include: string-continuations - include: triple-single-quoted-u-string-syntax triple-single-quoted-u-string-syntax: - match: (?={{sql_indicator}}) set: triple-single-quoted-sql-u-string-body - match: (?=\S) set: single-quoted-plain-u-block-string-body single-quoted-plain-u-block-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.block.python - include: triple-single-quoted-string-end - include: triple-single-quoted-u-string-content triple-single-quoted-sql-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python - include: triple-single-quoted-string-end - match: '' push: scope:source.sql with_prototype: - include: triple-single-quoted-string-pop - include: triple-single-quoted-u-string-content triple-single-quoted-u-string-content: - include: string-prototype - include: string-continuations - include: escaped-unicode-chars - include: escaped-chars - include: string-placeholders - include: triple-single-quoted-string-replacements triple-single-quoted-string-replacements: - include: escaped-string-braces - match: (?=\{) branch_point: triple-single-quoted-string-replacement branch: - triple-single-quoted-string-replacement - string-replacement-fallback triple-single-quoted-string-replacement: - match: \{ scope: punctuation.definition.placeholder.begin.python set: triple-single-quoted-string-replacement-body triple-single-quoted-string-replacement-body: - meta_scope: constant.other.placeholder.python - include: string-replacement-body - match: \[ scope: punctuation.section.brackets.begin.python push: triple-single-string-replacement-brackets-body - match: ':' scope: punctuation.separator.format-spec.python push: triple-single-quoted-string-replacement-formatspec-body - match: (?!\w) # restrict field names to reduce risk of false positives fail: triple-single-quoted-string-replacement triple-single-string-replacement-brackets-body: - include: string-replacement-brackets-body - include: triple-single-quoted-string-replacement-fail triple-single-quoted-string-replacement-formatspec-body: - meta_content_scope: meta.format-spec.python constant.other.format-spec.python - include: string-replacement-formatspec-body - match: \{ scope: punctuation.definition.placeholder.begin.python push: triple-single-quoted-string-replacement-body - include: triple-single-quoted-string-replacement-fail triple-single-quoted-string-replacement-fail: - match: (?='''|$) fail: triple-single-quoted-string-replacement triple-single-quoted-f-string-replacements: - include: f-string-replacements - match: \{ scope: punctuation.section.interpolation.begin.python push: - f-string-replacement-meta - triple-single-quoted-f-string-replacement-formatspec - triple-single-quoted-f-string-replacement-expression triple-single-quoted-f-string-replacements-regexp: # Same as f-string-replacements, but will reset the entire scope stack. - include: f-string-replacements-regexp - match: '{{fstring_regexp_interpolation_begin}}' scope: punctuation.section.interpolation.begin.python push: - f-string-replacement-regexp-meta - triple-single-quoted-f-string-replacement-formatspec - triple-single-quoted-f-string-replacement-expression triple-single-quoted-f-string-replacement-expression: - meta_content_scope: source.python.embedded - include: f-string-replacement-expression triple-single-quoted-f-string-replacement-formatspec: - meta_include_prototype: false - match: ':' scope: punctuation.separator.format-spec.python set: triple-single-quoted-f-string-replacement-formatspec-body - include: triple-single-quoted-f-string-replacement-end triple-single-quoted-f-string-replacement-formatspec-body: - meta_content_scope: meta.format-spec.python constant.other.format-spec.python - include: triple-single-quoted-f-string-replacement-end - include: triple-single-quoted-f-string-replacements triple-single-quoted-f-string-replacement-end: - include: f-string-replacement-end - match: (?=''') pop: 2 ###[ SINGLE QUOTED STRINGS ]################################################## single-quoted-strings: - match: (?={{string_prefix}}'(?!')) push: single-quoted-string single-quoted-string: - meta_include_prototype: false - include: single-quoted-plain-raw-b-string - include: single-quoted-raw-b-string - include: single-quoted-plain-raw-f-string - include: single-quoted-raw-f-string - include: single-quoted-plain-raw-u-string - include: single-quoted-raw-u-string - include: single-quoted-b-string - include: single-quoted-f-string - include: single-quoted-u-string single-quoted-string-end: - match: "'" scope: meta.string.python string.quoted.single.python punctuation.definition.string.end.python set: after-expression - match: \n scope: meta.string.python string.quoted.single.python invalid.illegal.unclosed-string.python set: after-expression - include: string-continuations single-quoted-string-pop: - match: (?='|\n) pop: 1 - include: string-continuations single-quoted-plain-raw-b-string: # Single-line capital R raw string, bytes, no syntax embedding - match: ([bB]R|R[bB])(') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python set: single-quoted-plain-raw-b-string-body single-quoted-plain-raw-b-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.python - include: single-quoted-string-end - include: single-quoted-plain-raw-b-string-content single-quoted-plain-raw-b-string-content: - include: string-prototype - include: escaped-raw-quotes single-quoted-raw-b-string: # Single-line raw string, bytes, treated as regex - match: ([bB]r|r[bB])(') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python set: single-quoted-raw-b-string-body single-quoted-raw-b-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.python source.regexp.python - include: single-quoted-string-end - match: '' push: scope:source.regexp.python#base-literal with_prototype: - include: single-quoted-string-pop - include: single-quoted-raw-b-string-content single-quoted-raw-b-string-content: - include: string-prototype single-quoted-plain-raw-u-string: # Single-line capital R raw string, unicode or not, no syntax embedding - match: ([uU]?R)(') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python set: single-quoted-plain-raw-u-string-body single-quoted-plain-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.python - include: single-quoted-string-end - include: single-quoted-plain-raw-u-string-content single-quoted-plain-raw-u-string-content: - include: string-prototype - include: escaped-raw-quotes single-quoted-raw-u-string: - match: ([uU]?r)(') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python set: single-quoted-raw-u-string-body single-quoted-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.python - include: single-quoted-string-end - include: single-quoted-raw-u-string-syntax single-quoted-raw-u-string-syntax: # Single-line raw string, unicode or not, starting with a SQL keyword - match: (?={{sql_indicator}}) set: single-quoted-sql-raw-u-string-body # Single-line raw string, unicode or not, treated as regex - match: (?=\S) set: single-quoted-regexp-raw-u-string-body single-quoted-regexp-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.python source.regexp.python - include: single-quoted-string-end - match: '' push: scope:source.regexp.python#base-literal with_prototype: - include: single-quoted-string-pop - include: single-quoted-regexp-raw-u-string-content single-quoted-regexp-raw-u-string-content: - include: string-prototype single-quoted-sql-raw-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python - include: single-quoted-string-end - match: '' push: scope:source.sql with_prototype: - include: single-quoted-string-pop - include: single-quoted-sql-raw-u-string-content single-quoted-sql-raw-u-string-content: - include: string-prototype - include: escaped-raw-quotes - include: string-placeholders - include: single-quoted-string-replacements single-quoted-plain-raw-f-string: # Single-line raw f-string - match: ([fF]R|R[fF])(') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python set: single-quoted-plain-raw-f-string-body single-quoted-plain-raw-f-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.python - include: single-quoted-string-end - include: single-quoted-plain-raw-f-string-content single-quoted-plain-raw-f-string-content: - include: string-prototype - include: escaped-raw-quotes - include: single-quoted-f-string-replacements single-quoted-raw-f-string: # Single-line raw f-string, treated as regex - match: ([fF]r|r[fF])(') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python set: single-quoted-raw-f-string-body single-quoted-raw-f-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.python source.regexp.python - include: single-quoted-string-end - match: '' push: scope:source.regexp.python#base-literal with_prototype: - include: single-quoted-string-pop - include: single-quoted-raw-f-string-content single-quoted-raw-f-string-content: - include: string-prototype - include: single-quoted-f-string-replacements-regexp single-quoted-b-string: # Single-line string, bytes - match: ([bB])(') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python set: single-quoted-b-string-body single-quoted-b-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.python - include: single-quoted-string-end - include: single-quoted-b-string-content single-quoted-b-string-content: - include: string-prototype - include: escaped-chars - include: string-placeholders - include: single-quoted-string-replacements single-quoted-f-string: # Single-line f-string - match: ([fF])(') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python set: single-quoted-f-string-body single-quoted-f-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.python - include: single-quoted-string-end - include: single-quoted-f-string-content single-quoted-f-string-content: - include: string-prototype - include: single-quoted-f-string-replacements - include: escaped-unicode-chars - include: escaped-chars single-quoted-u-string: - match: ([uU]?)(') captures: 1: storage.type.string.python 2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python set: single-quoted-u-string-body single-quoted-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.python - include: single-quoted-string-end - include: single-quoted-u-string-syntax single-quoted-u-string-syntax: # Single-line string, unicode or not, starting with a SQL keyword - match: (?={{sql_indicator}}) set: single-quoted-sql-u-string-body # Single-line string, unicode or not - match: (?=\S) set: single-quoted-plain-u-string-body single-quoted-plain-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python string.quoted.single.python - include: single-quoted-string-end - include: single-quoted-u-string-content single-quoted-sql-u-string-body: - meta_include_prototype: false - meta_content_scope: meta.string.python - include: single-quoted-string-end - match: '' push: scope:source.sql with_prototype: - include: single-quoted-string-pop - include: single-quoted-u-string-content single-quoted-u-string-content: - include: string-prototype - include: escaped-unicode-chars - include: escaped-chars - include: string-placeholders - include: single-quoted-string-replacements single-quoted-string-replacements: - include: escaped-string-braces - match: (?=\{) branch_point: single-quoted-string-replacement branch: - single-quoted-string-replacement - string-replacement-fallback single-quoted-string-replacement: - match: \{ scope: punctuation.definition.placeholder.begin.python set: single-quoted-string-replacement-body single-quoted-string-replacement-body: - meta_scope: constant.other.placeholder.python - include: string-replacement-body - match: \[ scope: punctuation.section.brackets.begin.python push: single-string-replacement-brackets-body - match: ':' scope: punctuation.separator.format-spec.python push: single-quoted-string-replacement-formatspec-body - match: (?!\w) # restrict field names to reduce risk of false positives fail: single-quoted-string-replacement single-string-replacement-brackets-body: - include: string-replacement-brackets-body - include: single-quoted-string-replacement-fail single-quoted-string-replacement-formatspec-body: - meta_content_scope: meta.format-spec.python constant.other.format-spec.python - include: string-replacement-formatspec-body - match: \{ scope: punctuation.definition.placeholder.begin.python push: single-quoted-string-replacement-body - include: single-quoted-string-replacement-fail single-quoted-string-replacement-fail: - match: (?='|$) fail: single-quoted-string-replacement single-quoted-f-string-replacements: - include: f-string-replacements - match: \{ scope: punctuation.section.interpolation.begin.python push: - f-string-replacement-meta - single-quoted-f-string-replacement-formatspec - single-quoted-f-string-replacement-expression single-quoted-f-string-replacements-regexp: # Same as f-string-replacements, but will reset the entire scope stack. - include: f-string-replacements-regexp - match: '{{fstring_regexp_interpolation_begin}}' scope: punctuation.section.interpolation.begin.python push: - f-string-replacement-regexp-meta - single-quoted-f-string-replacement-formatspec - single-quoted-f-string-replacement-expression single-quoted-f-string-replacement-expression: - meta_content_scope: source.python.embedded - include: f-string-replacement-expression - include: eol-pop single-quoted-f-string-replacement-formatspec: - meta_include_prototype: false - match: ':' scope: punctuation.separator.format-spec.python set: single-quoted-f-string-replacement-formatspec-body - include: single-quoted-f-string-replacement-end single-quoted-f-string-replacement-formatspec-body: - meta_content_scope: meta.format-spec.python constant.other.format-spec.python - include: single-quoted-f-string-replacement-end - include: single-quoted-f-string-replacements single-quoted-f-string-replacement-end: - include: f-string-replacement-end - match: (?='|$) pop: 2 ###[ STRING CONTENTS ]######################################################## string-continuations: - match: \\$ scope: punctuation.separator.continuation.line.python push: - meta_include_prototype: false - match: ^ pop: 1 escaped-chars: - match: \\x\h{2} scope: constant.character.escape.hex.python - match: \\[0-7]{1,3} scope: constant.character.escape.octal.python - match: \\[\\"'abfnrtv] scope: constant.character.escape.python - match: \\. # deprecated in 3.6 and will eventually be a syntax error scope: invalid.deprecated.character.escape.python escaped-unicode-chars: - match: \\u\h{4} scope: constant.character.escape.unicode.16bit.python - match: \\U\h{8} scope: constant.character.escape.unicode.32bit.python - match: \\N\{[-a-zA-Z ]+\} scope: constant.character.escape.unicode.name.python escaped-raw-quotes: # consume escaped quotes in raw-strings to preven them terminating strings # but don't scope them as escapes as they are treated literal - match: \\[\\'"] escaped-string-braces: - match: \{\{|\}\} scope: constant.character.escape.python string-placeholders: - match: |- # printf style (?x) % ( \( ({{identifier}}) \) )? # mapping key \#? # alternate form 0? # pad with zeros \-? # left-adjust \ ? # implicit sign [+-]? # sign (\d*|\*) # width (\. (\d*|\*))? # precision [hlL]? # length modifier (but ignored) [acdeEfFgGiorsuxX%] scope: constant.other.placeholder.python captures: 2: variable.other.placeholder.python - match: '{{strftime_spec}}' scope: constant.other.placeholder.python string-replacement-body: - match: \} scope: punctuation.definition.placeholder.end.python pop: 1 - match: \. scope: punctuation.accessor.dot.python - match: '![ars]\b' scope: storage.modifier.conversion.python - include: escaped-chars string-replacement-brackets-body: - meta_scope: meta.brackets.python - match: \] scope: punctuation.section.brackets.end.python pop: 1 - include: eol-pop - include: escaped-chars string-replacement-formatspec-body: - match: \} scope: punctuation.definition.placeholder.end.python pop: 2 - include: escaped-chars string-replacement-fallback: - match: \{ pop: 1 f-string-replacements: # https://peps.python.org/pep-0498 # https://peps.python.org/pep-0701 # https://docs.python.org/3.6/reference/lexical_analysis.html#f-strings - match: (\\)?(?:\{\{|\}\}) scope: constant.character.escape.python captures: 1: invalid.deprecated.character.escape.python - include: invalid-f-string-replacements f-string-replacement-meta: - clear_scopes: 1 - meta_include_prototype: false - meta_scope: meta.interpolation.python - include: immediately-pop f-string-replacements-regexp: # Same as f-string-replacements, but will reset the entire scope stack # and has an additional match. - match: \\?(\{\{|\}\}) scope: constant.character.escape.regexp captures: 1: constant.character.escape.python - include: invalid-f-string-replacements f-string-replacement-regexp-meta: # Same as f-string-replacement, but with clear_scopes: true - clear_scopes: true - meta_include_prototype: false - meta_scope: source.python meta.string.python meta.interpolation.python - include: immediately-pop f-string-replacement-expression: - match: (?:\s*(=)\s*)?(![ars])?(?=[:}]) captures: 1: storage.modifier.debug.python 2: storage.modifier.conversion.python pop: 1 - match: \\ scope: invalid.illegal.backslash-in-fstring.python - include: expression-in-a-sequence f-string-replacement-end: - match: \} scope: punctuation.section.interpolation.end.python pop: 2 invalid-f-string-replacements: - match: \{\s*\} scope: invalid.illegal.empty-expression.python - include: illegal-stray-braces # for use by inheriting syntaxes to easily inject string interpolation # in any kind of quoted or unquoted string string-prototype: [] ###[ PROTOTYPES ]############################################################# after-expression: - match: \s*(?=\() set: function-call-argument-list - match: \s*(?=\[) set: item-access - match: \s*(\\)\s*$ captures: 1: punctuation.separator.continuation.line.python push: line-continuation-body - include: immediately-pop else-pop: - match: (?=\S) pop: 1 eol-pop: - match: $ pop: 1 immediately-pop: - match: '' pop: 1 line-continuation-or-pop: - include: line-continuations - match: (?=\s*[\n;#]) pop: 1 line-continuations: - match: (\\)\s*$ captures: 1: punctuation.separator.continuation.line.python push: line-continuation-body line-continuation-body: - meta_include_prototype: false # This prevents strings after a continuation from being a docstring - include: triple-double-quoted-string - include: triple-single-quoted-string - match: ^(?!\s*{{string_prefix}}['"]{3}) pop: 1