Permalink
Fetching contributors…
Cannot retrieve contributors at this time
1883 lines (1805 sloc) 66.4 KB
%YAML 1.2
---
name: Python
file_extensions:
- py
- py3
- pyw
- pyi
- pyx
- pyx.in
- pxd
- pxd.in
- pxi
- pxi.in
- rpy
- cpy
- SConstruct
- Sconstruct
- sconstruct
- SConscript
- gyp
- gypi
- Snakefile
- wscript
first_line_match: ^#!\s*/.*\bpython(\d(\.\d)?)?\b
scope: source.python
variables:
# We support unicode here because Python 3 is the future
identifier_continue: '[[:alnum:]_]'
identifier: '\b[[:alpha:]_]{{identifier_continue}}*\b'
identifier_constant: '\b(?:[\p{Lu}_][\p{Lu}_\d]*)?[\p{Lu}]{2,}[\p{Lu}_\d]*\b' # require 2 consecutive upper-case letters
digitpart: (?:\d(?:_?\d)*)
path: '({{identifier}} *\. *)*{{identifier}}'
sql_indicator: \s*(?:SELECT|INSERT|UPDATE|DELETE|CREATE|REPLACE|ALTER|WITH)\b
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)
format_spec: |-
(?x:
(?:.? [<>=^])? # fill align
[ +-]? # sign
\#? # alternate form
# technically, octal and hexadecimal integers are also supported as 'width', but rarely used
\d* # width
,? # thousands separator
(?:\.\d+)? # precision
[bcdeEfFgGnosxX%]? # type
)
strftime_spec: '(?:%(?:[aAwdbBGmyYHIpMSfzZjuUVWcxX%]|-[dmHIMSj]))'
contexts:
main:
- include: statements
statements:
- include: docstrings
- include: line-statements
- include: block-statements
- include: classes
- include: functions
- include: modifiers
- include: assignments
- match: ;
scope: punctuation.terminator.statement.python
- include: line-expressions
line-statements:
- include: imports
- include: decorators
- match: \b(raise)\b
scope: keyword.control.flow.raise.python
push:
- meta_scope: meta.statement.raise.python
- include: line-continuation-or-pop
- match: \b(from)\b
scope: keyword.control.flow.raise.from.python
set:
- meta_scope: meta.statement.raise.python
- include: line-continuation-or-pop
- include: expressions
- include: expressions
- match: \b(assert)\b
scope: keyword.other.assert.python
- match: \b(del)\b
scope: keyword.other.del.python
- match: \b(print)\b(?! *([,.()\]}]))
scope: keyword.other.print.python
- match: \b(exec)\b(?! *($|[,.()\]}]))
scope: keyword.other.exec.python
- match: \b(return)\b
scope: keyword.control.flow.return.python
- match: \b(break)\b
scope: keyword.control.flow.break.python
- match: \b(continue)\b
scope: keyword.control.flow.continue.python
- match: \b(pass)\b
scope: keyword.control.flow.pass.python
- match: ':'
scope: punctuation.separator.annotation.variable.python
imports:
- match: \b(import)\b
scope: keyword.control.import.python
push:
- meta_scope: meta.statement.import.python
- include: line-continuation-or-pop
- match: ','
scope: punctuation.separator.import-list.python
- match: \.
scope: invalid.illegal.unexpected-relative-import.python
- include: import-alias
- include: qualified-name
- match: (?=\S)
pop: true
- match: \b(from)\b
scope: keyword.control.import.from.python
push:
- meta_scope: meta.statement.import.python
- meta_content_scope: meta.import-source.python
- include: line-continuation-or-pop
- match: \b(import)\b
scope: keyword.control.import.python
set:
- meta_scope: meta.statement.import.python
- include: line-continuation-or-pop
- match: ' *(\()'
captures:
1: punctuation.section.import-list.begin.python
set:
- meta_scope: meta.statement.import.python
- include: comments
- match: \)
scope: punctuation.section.import-list.end.python
pop: true
- include: import-name-list
- match: (?=\S)
pop: true
- match: ''
set:
- meta_scope: meta.statement.import.python
- include: line-continuation-or-pop
- include: import-name-list
- match: (?=\S)
pop: true
- match: (?=\S)
pop: true
- include: import-from-name
- match: (?=\S)
pop: true
import-name-list:
- match: ','
scope: punctuation.separator.import-list.python
- include: import-alias
- include: name
- match: \*
scope: constant.language.import-all.python
- match: \S+
scope: invalid.illegal.name.import.python
import-alias:
- match: \b(as)\b
scope: keyword.control.import.as.python
import-from-name:
- match: \.+
scope: meta.import-path.python keyword.control.import.relative.python
- match: (?={{path}})
push:
- meta_scope: meta.import-path.python
- match: '{{illegal_names}}\b'
scope: invalid.illegal.name.python
- match: '{{identifier}}'
scope: meta.import-name.python
- match: \s*(\.) *(?:({{illegal_names}}\b)|({{identifier}}))
captures:
1: punctuation.accessor.dot.python
2: invalid.illegal.name.python
3: meta.import-name.python
- match: \ *(\. *\S+) # matches and consumes the remainder of "abc.123" or "abc.+"
captures:
1: invalid.illegal.name.python
pop: true
- match: ''
pop: true
block-statements:
# async for ... in ...:
- match: \b(async +)?(for)\b
captures:
1: storage.modifier.async.python
2: keyword.control.flow.for.python
push:
- meta_scope: meta.statement.for.python
- include: line-continuation-or-pop
- match: \b(in)\b
scope: keyword.control.flow.for.in.python
set:
- meta_scope: meta.statement.for.python
- include: line-continuation-or-pop
- match: ':'
scope: punctuation.section.block.for.python
pop: true
- include: expressions
- match: ':'
scope: invalid.illegal.missing-in.python
pop: true
- include: target-list
# async with ... as ...:
- match: \b(async +)?(with)\b
captures:
1: storage.modifier.async.python
2: keyword.control.flow.with.python
push: with-body
# except ... as ...:
- match: \b(except)\b
scope: keyword.control.flow.except.python
push:
- meta_scope: meta.statement.except.python
- include: line-continuation-or-pop
- match: ':'
scope: punctuation.section.block.except.python
pop: true
- match: '\b(as)\b'
scope: keyword.control.flow.as.python
set:
- meta_content_scope: meta.statement.except.python
- include: line-continuation-or-pop
- match: ':'
scope: meta.statement.except.python punctuation.section.block.except.python
pop: true
- include: name
- include: target-list
- match: \bif\b
scope: keyword.control.flow.conditional.python
push:
- meta_scope: meta.statement.if.python
- include: line-continuation-or-pop
- match: ':'
scope: punctuation.section.block.conditional.python
pop: true
- include: expressions
- match: \bwhile\b
scope: keyword.control.flow.while.python
push:
- meta_scope: meta.statement.while.python
- include: line-continuation-or-pop
- match: ':'
scope: punctuation.section.block.while.python
pop: true
- include: expressions
- match: \b(elif|else)\b(?:\s*(:))?
scope: meta.statement.conditional.python
captures:
1: keyword.control.flow.conditional.python
2: punctuation.section.block.python
- match: \b(try)\b(?:\s*(:))?
scope: meta.statement.try.python
captures:
1: keyword.control.flow.try.python
2: punctuation.section.block.try.python
- match: \b(finally)\b(?:\s*(:))?
scope: meta.statement.finally.python
captures:
1: keyword.control.flow.finally.python
2: punctuation.section.block.finally.python
with-body:
- meta_scope: meta.statement.with.python
- include: line-continuation-or-pop
- match: \b(as)\b
scope: keyword.control.flow.with.as.python
set: with-as
- match: ':'
scope: punctuation.section.block.with.python
pop: true
- match: ','
scope: punctuation.separator.with-resources.python
- include: expressions
with-as:
- meta_scope: meta.statement.with.python
- include: line-continuation-or-pop
- match: ':'
scope: punctuation.section.block.with.python
pop: true
- match: ','
scope: punctuation.separator.with-resources.python
set: with-body
- include: name
- include: groups
- include: lists
expressions-common:
- include: comments
- include: constants
- include: numbers
- include: yields
- include: operators
- include: lambda
- match: \b(await)\b
scope: keyword.other.await.python
- include: inline-if
- include: strings
- include: function-calls
- include: item-access
- include: groups
- match: \)
scope: invalid.illegal.stray.brace.round.python
- match: \]
scope: invalid.illegal.stray.brace.square.python
- match: \}
scope: invalid.illegal.stray.brace.curly.python
- include: lists
- include: dictionaries-and-sets
- include: line-continuation
line-expressions: # Always include this last!
- include: expressions-common
- include: qualified-name
expressions: # Always include this last!
# Differs from the line scope in that invalid-name matches will pop the current context
# and matches accessors continued on a different line
- include: expressions-common
- include: illegal-names-pop
- include: qualified-name
- match: '(\.) *(?={{identifier}})'
captures:
1: punctuation.accessor.dot.python
push:
- include: magic-function-names
- include: magic-variable-names
- include: illegal-names
- include: generic-names
- match: ''
pop: true
after-expression:
# direct function call
- match: '\s*(\()'
captures:
1: punctuation.section.arguments.begin.python
push:
- meta_scope: meta.function-call.arguments.python
- match: \)
scope: punctuation.section.arguments.end.python
pop: true
- include: arguments
# item access
- match: '\s*(\[)'
captures:
1: meta.item-access.python punctuation.section.brackets.begin.python
push:
- meta_content_scope: meta.item-access.arguments.python
- match: \]
scope: meta.item-access.python punctuation.section.brackets.end.python
pop: true
- match: ':'
scope: punctuation.separator.slice.python
- include: expressions
# indirect function call following attribute access
- include: function-calls
# arbitrary attribute access
- match: '\s*(\.)'
captures:
1: punctuation.accessor.dot.python
push:
- include: magic-function-names
- include: magic-variable-names
- include: illegal-names
- include: generic-names
- match: ''
pop: true
- match: ''
pop: true
comments:
- match: "#"
scope: punctuation.definition.comment.python
push:
- meta_scope: comment.line.number-sign.python
- match: \n
pop: true
constants:
- match: \b(None|True|False|Ellipsis|NotImplemented|__debug__)\b
scope: constant.language.python
- match: \.{3}(?!\w)
scope: constant.language.python
numbers:
# https://docs.python.org/3/reference/lexical_analysis.html#numeric-literals
# hexadecimal
- match: \b(?i)(0x)\h*(L) # py2
scope: constant.numeric.integer.long.hexadecimal.python
captures:
1: punctuation.definition.numeric.hexadecimal.python
2: storage.type.numeric.long.python
- match: \b(?i)(0x)(_?\h)+
scope: constant.numeric.integer.hexadecimal.python
captures:
1: punctuation.definition.numeric.hexadecimal.python
# octal
- match: \b(?i)(0o?)(?=o|[0-7])[0-7]*(L) # py2
scope: constant.numeric.integer.long.octal.python
captures:
1: punctuation.definition.integer.octal.python
2: storage.type.numeric.long.python
- match: \b(?i)(0)[0-7]+ # py2
scope: constant.numeric.integer.octal.python
captures:
1: punctuation.definition.numeric.octal.python
- match: \b(?i)(0o)(_?[0-7])+
scope: constant.numeric.integer.octal.python
captures:
1: punctuation.definition.numeric.octal.python
# binary
- match: \b(?i)(0b)[01]*(L) # py2
scope: constant.numeric.integer.long.binary.python
captures:
1: punctuation.definition.numeric.binary.python
2: storage.type.numeric.long.python
- match: \b(?i)(0b)(_?[01])*
scope: constant.numeric.integer.binary.python
captures:
1: punctuation.definition.numeric.binary.python
# complex
- match: (?i){{digitpart}}?(\.){{digitpart}}(?:e[\-\+]?{{digitpart}})?(j) # mandatory fraction
scope: constant.numeric.complex.python
captures:
1: punctuation.separator.decimal.python
2: storage.type.numeric.complex.python
- match: \b(?i)(?:{{digitpart}}(?:(\.){{digitpart}}?)?|(\.){{digitpart}})(?:e[\-\+]?{{digitpart}})(j) # mandatory exponent
scope: constant.numeric.complex.python
captures:
1: punctuation.separator.decimal.python
2: punctuation.separator.decimal.python
3: storage.type.numeric.complex.python
- match: (?i){{digitpart}}(\.)?(j) # mandatory digitpart
scope: constant.numeric.complex.python
captures:
1: punctuation.separator.decimal.python
2: storage.type.numeric.complex.python
# floating point
- match: (?i){{digitpart}}?(\.){{digitpart}}(?:e[\-\+]?{{digitpart}})? # mandatory fraction
scope: constant.numeric.float.python
captures:
1: punctuation.separator.decimal.python
- match: \b(?i)(?:{{digitpart}}(?:(\.){{digitpart}}?)?|(\.){{digitpart}})(?:e[\-\+]?{{digitpart}}) # mandatory exponent
scope: constant.numeric.float.python
captures:
1: punctuation.separator.decimal.python
2: punctuation.separator.decimal.python
- match: (?i){{digitpart}}(\.) # mandatory digitpart
scope: constant.numeric.float.python
captures:
1: punctuation.separator.decimal.python
# integer
- match: \b(?i)(?:[1-9]\d*|0)(L)\b # py2
scope: constant.numeric.integer.long.decimal.python
captures:
1: storage.type.numeric.long.python
- match: \b(?i)([1-9][\d_]*|0)\b
scope: constant.numeric.integer.decimal.python
modifiers:
- match: \b(?:(global)|(nonlocal))\b
captures:
1: storage.modifier.global.python
2: storage.modifier.nonlocal.python
push:
- include: line-continuation-or-pop
- match: ','
scope: punctuation.separator.storage-list.python
- include: name
- match: \S+
scope: invalid.illegal.name.storage.python
yields:
- match: \b(yield)(?:\s+(from))?\b
captures:
1: keyword.control.flow.yield.python
2: keyword.control.flow.yield-from.python
assignments:
- match: \+=|-=|\*=|/=|//=|%=|@=|&=|\|=|\^=|>>=|<<=|\*\*=
scope: keyword.operator.assignment.augmented.python
- match: '=(?!=)'
scope: keyword.operator.assignment.python
operators:
- match: <>
scope: invalid.deprecated.operator.python
- match: <\=|>\=|\=\=|<|>|\!\=
scope: keyword.operator.comparison.python
- match: \+|\-|\*|\*\*|/|//|%|<<|>>|&|\||\^|~
scope: keyword.operator.arithmetic.python
- match: \b(and|in|is|not|or)\b
comment: keyword operators that evaluate to True or False
scope: keyword.operator.logical.python
- match: '@'
scope: keyword.operator.matrix.python
allow-unpack-operators:
# Match unpacking operators, if present
- include: comments
- match: \*{3,}
scope: invalid.illegal.syntax.python
pop: true
- match: \*\*
scope: keyword.operator.unpacking.mapping.python
pop: true
- match: \*
scope: keyword.operator.unpacking.sequence.python
pop: true
- match: (?=\S)
pop: true
classes:
- match: '^\s*(class)\b'
captures:
1: storage.type.class.python
push:
- meta_scope: meta.class.python
- include: line-continuation-or-pop
- match: ':'
scope: punctuation.section.class.begin.python
pop: true
- match: "(?={{identifier}})"
push:
- meta_content_scope: entity.name.class.python
- include: entity-name-class
- match: ''
pop: true
- match: \(
scope: punctuation.section.inheritance.begin.python
set:
- meta_scope: meta.class.inheritance.python
- match: \)
scope: punctuation.section.inheritance.end.python
set:
- include: line-continuation-or-pop
- match: ':'
scope: meta.class.python punctuation.section.class.begin.python
pop: true
- match: (?=\S)
pop: true
- match: ':'
scope: invalid.illegal.no-closing-parens.python
pop: true
- match: ','
scope: punctuation.separator.inheritance.python
- include: illegal-names-pop
- match: ({{identifier}}) *(=)
captures:
1: variable.parameter.class-inheritance.python
2: keyword.operator.assignment.python
- match: (?={{path}})
push:
- meta_scope: entity.other.inherited-class.python
- match: '{{identifier}}(?: *(\.) *)?'
captures:
1: punctuation.accessor.dot.python
- match: ''
pop: true
- include: expressions
functions:
- match: '^\s*(?:(async)\s+)?(def)\b'
captures:
1: storage.modifier.async.python
2: storage.type.function.python
push:
- meta_scope: meta.function.python
- include: line-continuation-or-pop
- match: ':'
scope: punctuation.section.function.begin.python
pop: true
- match: "(?={{identifier}})"
push:
- meta_content_scope: entity.name.function.python
- include: entity-name-function
- match: ''
pop: true
- match: '(?=\()'
set:
- match: \(
scope: meta.function.parameters.python punctuation.section.parameters.begin.python
set: [function-parameters, allow-unpack-operators]
function-parameters:
- meta_content_scope: meta.function.parameters.python
- match: \)
scope: punctuation.section.parameters.end.python
set: function-after-parameters
- include: comments
- match: ','
scope: punctuation.separator.parameters.python
push: allow-unpack-operators
- match: '(?==)'
set:
- match: '='
scope: keyword.operator.assignment.python
set:
- meta_scope: meta.function.parameters.default-value.python
- match: '(?=[,)])'
set: [function-parameters, allow-unpack-operators]
- include: expressions
- match: '(?=:)'
set:
- match: ':'
scope: punctuation.separator.annotation.parameter.python
set:
- meta_scope: meta.function.parameters.annotation.python
- match: '(?=[,)=])'
set: function-parameters
- include: expressions
- include: function-parameters-tuple
- include: illegal-names
- match: '{{identifier}}'
scope: variable.parameter.python
- include: line-continuation
function-parameters-tuple:
# python 2 style tuple arguments
# removed from python 3 since PEP-3113
- match: \(
scope: punctuation.section.group.begin.python
push:
- meta_scope: meta.group.python
- match: \)
scope: punctuation.section.group.end.python
set: after-expression
- include: comments
- match: ','
scope: punctuation.separator.parameters.python
push: allow-unpack-operators
# default values should follow the argument
- match: '(?==)'
push:
- meta_scope: invalid.illegal.default-value.python
- match: '(?=[,)=])'
pop: true
# python 2 does not support type annotations
- match: '(?=:)'
push:
- meta_scope: invalid.illegal.annotation.python
- match: '(?=[,)=])'
pop: true
- include: illegal-names
- match: '{{identifier}}'
scope: variable.parameter.python
- include: line-continuation
function-after-parameters:
- meta_content_scope: meta.function.python
- match: '(?=->)'
set:
- meta_content_scope: meta.function.annotation.return.python
- match: ->
scope: punctuation.separator.annotation.return.python
- match: '(?=:)'
set: function-after-parameters
- include: line-continuation-or-pop
- include: expressions
- match: ':'
scope: meta.function.python punctuation.section.function.begin.python
pop: true
- include: comments
- match: (?=\S)
pop: true
decorators:
- match: ^\s*(?=@)
push:
# Due to line continuations, we don't know whether this is a "function call" yet
- meta_content_scope: meta.annotation.python
- match: '@'
scope: punctuation.definition.annotation.python
- match: $
pop: true
- include: line-continuation-or-pop
- match: (?=\.?\s*{{path}}\s*\() # now we do
set: [decorator-function-call-wrapper, qualified-name-until-leaf]
- match: (?=\.?\s*{{path}})
push: [decorator-wrapper, qualified-name-until-leaf]
- match: \S
scope: invalid.illegal.character.python
pop: true
decorator-wrapper:
- match: (\.)\s*
captures:
1: punctuation.accessor.dot.python
set:
- meta_scope: meta.qualified-name.python
- meta_content_scope: variable.annotation.python
- include: dotted-name-specials
- include: generic-names
- match: ''
pop: true
- match: ''
set:
- meta_scope: meta.qualified-name.python variable.annotation.python
- include: name-specials
- include: generic-names
- match: ''
pop: true
decorator-function-call-wrapper:
- meta_scope: meta.annotation.function.python
- match: \)
scope: punctuation.section.arguments.end.python
set: after-expression
- match: \(
scope: meta.annotation.function.python punctuation.section.arguments.begin.python
push:
- clear_scopes: 1
- meta_content_scope: meta.annotation.arguments.python
- match: (?=\))
pop: true
- include: arguments
- match: (\.)\s*
captures:
1: punctuation.accessor.dot.python
push:
- meta_scope: meta.qualified-name.python
- meta_content_scope: variable.annotation.function.python
- include: dotted-name-specials
- include: generic-names
- match: ''
pop: true
- match: ''
push:
- meta_scope: meta.qualified-name.python variable.annotation.function.python
- include: name-specials
- include: generic-names
- match: ''
pop: true
item-access:
- match: '(?={{path}}\s*\[)'
push:
- match: \]
scope: meta.item-access.python punctuation.section.brackets.end.python
set: after-expression
- match: '(?={{path}}\s*\[)'
push:
- meta_content_scope: meta.item-access.python
- match: '(?=\s*\[)'
pop: true
- include: qualified-name
- match: \[
scope: meta.item-access.python punctuation.section.brackets.begin.python
push:
- meta_content_scope: meta.item-access.arguments.python
- match: '(?=\])'
pop: true
- match: ':'
scope: punctuation.separator.slice.python
- include: expressions
function-calls:
- match: '(?=(\.\s*)?{{path}}\s*\()'
push: [function-call-wrapper, qualified-name-until-leaf]
function-call-wrapper:
- meta_scope: meta.function-call.python
- match: (?=\() # need to remove meta.function-call.python from opening parens
set:
- match: \(
scope: punctuation.section.arguments.begin.python
set:
- meta_scope: meta.function-call.arguments.python
- match: \)
scope: punctuation.section.arguments.end.python
set: after-expression
- include: arguments
- match: (\.)\s*(?={{identifier}})
captures:
1: punctuation.accessor.dot.python
push:
- meta_scope: meta.qualified-name.python
- meta_content_scope: variable.function.python
- include: dotted-name-specials
- include: generic-names
- match: ''
pop: true
- match: (?={{identifier}})
push:
- meta_scope: meta.qualified-name.python variable.function.python
- include: name-specials
- include: generic-names
- match: ''
pop: true
arguments:
- include: keyword-arguments
- match: ','
scope: punctuation.separator.arguments.python
push: allow-unpack-operators
- include: inline-for
- include: expressions
keyword-arguments:
- match: '(?={{identifier}}\s*=(?!=))'
push:
- include: line-continuation-or-pop
- match: '='
scope: keyword.operator.assignment.python
set:
- match: (?=\s*[,):])
pop: true
- include: expressions
- include: illegal-names
- match: '{{identifier}}'
scope: variable.parameter.python
lambda:
- match: \b(lambda)(?=\s|:|$)
scope: storage.type.function.inline.python
push: [lambda-parameters, allow-unpack-operators]
lambda-parameters:
- meta_scope: meta.function.inline.python
- meta_content_scope: meta.function.inline.parameters.python
- include: line-continuation-or-pop
- match: '\:'
scope: punctuation.section.function.begin.python
pop: true
- match: ','
scope: punctuation.separator.parameters.python
push: allow-unpack-operators
- include: keyword-arguments
- include: function-parameters-tuple
- include: illegal-names
- match: '{{identifier}}'
scope: variable.parameter.python
- match: '\S'
scope: invalid.illegal.expected-parameter.python
groups:
- match: \(
scope: punctuation.section.group.begin.python
push:
- meta_scope: meta.group.python
- match: \)
scope: punctuation.section.group.end.python
set: after-expression
- match: ','
scope: punctuation.separator.tuple.python
- include: inline-for
- include: expressions
lists:
- match: '(\[)(\s*(\]))\b'
captures:
1: punctuation.section.list.begin.python
2: meta.empty-list.python
3: punctuation.section.list.end.python
- match: \[
scope: punctuation.section.list.begin.python
push:
- meta_scope: meta.structure.list.python
- match: \]
scope: punctuation.section.list.end.python
set: after-expression
- match: ','
scope: punctuation.separator.list.python
push: allow-unpack-operators
- include: inline-for
- include: expressions
dictionaries-and-sets:
- match: '(\{)(\s*(\}))'
scope: meta.structure.dictionary.python
captures:
1: punctuation.section.dictionary.begin.python
2: meta.empty-dictionary.python
3: punctuation.section.dictionary.end.python
- match: \{
scope: punctuation.section.dictionary-or-set.begin.python
push:
- meta_scope: meta.structure.dictionary-or-set.python
- match: \}
scope: punctuation.section.dictionary-or-set.end.python
set: after-expression
- match: ','
scope: punctuation.separator.dictionary-or-set.python
push: allow-unpack-operators
- match: ':'
scope: punctuation.separator.key-value.python
- include: inline-for
- include: expressions
builtin-exceptions:
- match: |-
(?x)\b(
(
Arithmetic|Assertion|Attribute|BlockingIO|BrokenPipe|Buffer|ChildProcess|
Connection(Aborted|Refused|Reset)?|EOF|Environment|FileExists|
FileNotFound|FloatingPoint|Interrupted|IO|IsADirectoryError|
Import|Indentation|Index|Key|Lookup|Memory|Name|NotADirectory|
NotImplemented|OS|Overflow|Permission|ProcessLookup|Reference|
Runtime|Standard|Syntax|System|Tab|Timeout|Type|UnboundLocal|
Unicode(Encode|Decode|Translate)?|Value|VMS|Windows|ZeroDivision
)Error|
((Pending)?Deprecation|Runtime|Syntax|User|Future|Import|Unicode|Bytes)?Warning|
(Base)?Exception|
SystemExit|StopIteration|NotImplemented|KeyboardInterrupt|GeneratorExit
)\b
scope: support.type.exception.python
builtin-functions:
- match: |-
(?x)\b(
__import__|all|abs|any|apply|ascii|bin|breakpoint|callable|chr|classmethod|cmp|coerce|
compile|delattr|dir|divmod|enumerate|eval|exec|execfile|filter|format|getattr|
globals|hasattr|hash|help|hex|id|input|intern|isinstance|issubclass|iter|
len|locals|map|max|min|next|oct|open|ord|pow|print|property|range|
raw_input|reduce|reload|repr|reversed|round|setattr|sorted|staticmethod|
sum|super|type|unichr|vars|zip
)\b
scope: support.function.builtin.python
builtin-types:
- match: |-
(?x)\b(
basestring|bool|buffer|bytearray|bytes|complex|dict|float|frozenset|int|
list|long|memoryview|object|range|set|slice|str|tuple|unicode|xrange
)\b
scope: support.type.python
name:
- match: '(?={{identifier}})'
push:
- include: name-specials
- match: '{{identifier_constant}}'
scope: variable.other.constant.python
- include: generic-names
- match: ''
pop: true
dotted-name:
- match: '\s*(\.)\s*(?={{identifier}})'
captures:
1: punctuation.accessor.dot.python
push:
- include: dotted-name-specials
- match: '{{identifier_constant}}'
scope: variable.other.constant.python
- include: generic-names
- match: ''
pop: true
qualified-name:
- match: '(?={{path}})'
push:
- meta_scope: meta.qualified-name.python
- include: name
- include: dotted-name
- match: ''
pop: true
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.qualified-name.python
# If a line continuation follows, this may or may not be the last leaf (most likley not though)
- match: (?={{identifier}}\s*(\.|\\))
push:
- include: name-specials
- include: generic-names
- match: ''
pop: true
- match: (\.)\s*(?={{identifier}}\s*(\.|\\))
captures:
1: punctuation.accessor.dot.python
push:
- include: dotted-name-specials
- include: generic-names
- match: ''
pop: true
- match: \.(?!\s*{{identifier}}) # don't match last dot
scope: punctuation.accessor.dot.python
- match: (?=\S|$)
pop: true
name-specials:
- include: builtin-functions
- include: builtin-types
- include: builtin-exceptions
- include: illegal-names
- include: magic-function-names
- include: magic-variable-names
- include: language-variables
dotted-name-specials:
- include: magic-function-names
- include: magic-variable-names
- include: illegal-names
entity-name-class:
- include: illegal-names
- include: generic-names
entity-name-function:
- include: magic-function-names
- include: illegal-names
- include: generic-names
generic-names:
- match: '{{identifier}}'
scope: meta.generic-name.python
illegal-names:
- match: \b{{illegal_names}}\b
scope: invalid.illegal.name.python
illegal-names-pop:
- match: \b{{illegal_names}}\b
scope: invalid.illegal.name.python
pop: true
language-variables:
- match: \b(self|cls)\b
scope: variable.language.python
- match: _(?!{{identifier_continue}})
scope: variable.language.python
line-continuation:
- match: (\\)(.*)$\n?
captures:
1: punctuation.separator.continuation.line.python
2: invalid.illegal.unexpected-text.python
# make sure to resume parsing at next line
push:
# This prevents strings after a continuation from being a docstring
- include: strings
- match: (?=\S|^\s*$|\n) # '\n' for when we matched a string earlier
pop: true
line-continuation-or-pop:
- include: line-continuation
- match: (?=\s*($|;|#))
pop: true
magic-function-names:
# https://docs.python.org/2/reference/datamodel.html
# https://docs.python.org/3/reference/datamodel.html
- match: |-
(?x)\b__(?:
# unary operators
invert|neg|pos|abs|
# binary operators
add|and|div|divmod|floordiv|lshift|mod|mul|or|pow|rshift|sub|truediv|xor|
contains|
# 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
comment: these methods have magic interpretation by python and are generally called indirectly through syntactic constructs
scope: support.function.magic.python
magic-variable-names:
# 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: |-
(?x)\b__(?:
# 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
)__\b
scope: support.variable.magic.python
docstrings:
- match: ^\s*(?=(?i)(ur|ru|u|r)?("""|'''))
push:
- match: (?i)(u)?("""|''')
captures:
1: storage.type.string.python
2: punctuation.definition.comment.begin.python
set:
- meta_scope: comment.block.documentation.python
- include: escaped-unicode-char
- include: escaped-char
- match: '\2'
scope: punctuation.definition.comment.end.python
pop: true
- match: (?i)(u?ru?)("""|''')
captures:
1: storage.type.string.python
2: punctuation.definition.comment.begin.python
set:
- meta_scope: comment.block.documentation.python
- match: '\2'
scope: punctuation.definition.comment.end.python
pop: true
escaped-char:
- match: '(\\x\h{2})|(\\[0-7]{3})|(\\[\\"''abfnrtv])'
captures:
1: constant.character.escape.hex.python
2: constant.character.escape.octal.python
3: constant.character.escape.python
- match: \\. # deprecated in 3.6 and will eventually be a syntax error
scope: invalid.deprecated.character.escape.python
escaped-unicode-char:
- match: '(\\U\h{8})|(\\u\h{4})|(\\N\{[a-zA-Z ]+\})'
captures:
1: constant.character.escape.unicode.16-bit-hex.python
2: constant.character.escape.unicode.32-bit-hex.python
3: constant.character.escape.unicode.name.python
line-continuation-inside-string:
- match: (\\)$\n?
captures:
1: punctuation.separator.continuation.line.python
- match: \n
scope: invalid.illegal.unclosed-string.python
set: after-expression
constant-placeholder:
- 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
- match: '\{\{|\}\}'
scope: constant.character.escape.python
- include: formatting-syntax
formatting-syntax:
# https://docs.python.org/3.6/library/string.html#formatstrings
- match: |- # simple form
(?x)
(\{)
(?: [\w.\[\]]+)? # field_name
( ! [ars])? # conversion
( : (?:{{format_spec}}| # format_spec OR
[^}%]*%.[^}]*) # any format-like string
)?
(\})
scope: constant.other.placeholder.python
captures:
1: punctuation.definition.placeholder.begin.python
2: storage.modifier.conversion.python
3: constant.other.format-spec.python
4: punctuation.definition.placeholder.end.python
- match: \{(?=[^\}"']+\{[^"']*\}) # complex (nested) form
scope: punctuation.definition.placeholder.begin.python
push:
- meta_scope: constant.other.placeholder.python
- match: \}
scope: punctuation.definition.placeholder.end.python
pop: true
- match: '[\w.\[\]]+'
- match: '![ars]'
scope: storage.modifier.conversion.python
- match: ':'
push:
- meta_scope: meta.format-spec.python constant.other.format-spec.python
- match: (?=\})
pop: true
- include: formatting-syntax
f-string-content:
# https://www.python.org/dev/peps/pep-0498/
# https://docs.python.org/3.6/reference/lexical_analysis.html#f-strings
- match: \{\{|\}\}
scope: constant.character.escape.python
- match: \{\s*\}
scope: invalid.illegal.empty-expression.python
- match: (?=\{)
push: f-string-replacement
- match: \}
scope: invalid.illegal.stray-brace.python
f-string-replacement:
- clear_scopes: 1
- match: \}
scope: meta.interpolation.python punctuation.section.interpolation.end.python
pop: true
- match: \{
scope: punctuation.section.interpolation.begin.python
push:
- meta_scope: meta.interpolation.python
- match: (?=\})
pop: true
- match: '![ars]'
scope: storage.modifier.conversion.python
- match: ':'
push:
- meta_scope: meta.format-spec.python constant.other.format-spec.python
# Because replacements can also be used *within* the format-spec,
# basically any character is valid and matching {{format_spec}} is useless.
# - match: '{{format_spec}}'
- match: (?=\})
pop: true
- include: f-string-content
- match: ''
push:
- meta_content_scope: source.python.embedded
- match: (?=![^=]|:|\})
pop: true
- match: \\
scope: invalid.illegal.backslash-in-fstring.python
- include: inline-for
- include: expressions
string-quoted-double-block:
# 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
push:
- meta_content_scope: meta.string.python string.quoted.double.block.python
- match: '"""'
scope: punctuation.definition.string.end.python
set: after-expression
- include: escaped-unicode-char
# 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
push:
- meta_content_scope: meta.string.python string.quoted.double.block.python
- match: '"""'
scope: punctuation.definition.string.end.python
set: after-expression
# 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
push:
- meta_content_scope: meta.string.python string.quoted.double.block.python
- match: '(?={{sql_indicator}})'
set:
- meta_scope: meta.string.python string.quoted.double.block.python
- match: '"""'
scope: punctuation.definition.string.end.python
set: after-expression
- match: ''
push: scope:source.sql
with_prototype:
- match: '(?=""")'
pop: true
- include: escaped-unicode-char
- include: constant-placeholder
- match: '(?=\S)'
set:
- meta_scope: meta.string.python string.quoted.double.block.python
- match: '"""'
scope: punctuation.definition.string.end.python
set: after-expression
- match: ''
push: scope:source.regexp.python
with_prototype:
- match: '(?=""")'
pop: true
- include: escaped-unicode-char
# 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
push:
- meta_content_scope: meta.string.python string.quoted.double.block.python
- match: '"""'
scope: punctuation.definition.string.end.python
set: after-expression
- match: ''
embed: scope:source.regexp.python
escape: (?=""")
# Triple-quoted raw f-string
- match: ((?i)fr|rf)(""")
captures:
1: storage.type.string.python
2: meta.string.interpolated.python string.quoted.double.block.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.interpolated.python string.quoted.double.block.python
- match: '"""'
scope: punctuation.definition.string.begin.python
set: after-expression
- include: f-string-content
# Triple-quoted f-string
- match: ((?i)f|f)(""")
captures:
1: storage.type.string.python
2: meta.string.interpolated.python string.quoted.double.block.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.interpolated.python string.quoted.double.block.python
- match: '"""'
scope: punctuation.definition.string.begin.python
set: after-expression
- include: escaped-unicode-char
- include: escaped-char
- include: f-string-content
# 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
push:
- meta_content_scope: meta.string.python string.quoted.double.block.python
- match: '(?={{sql_indicator}})'
set:
- meta_scope: meta.string.python string.quoted.double.block.python
- match: '"""'
scope: punctuation.definition.string.end.python
set: after-expression
- match: ''
push: scope:source.sql
with_prototype:
- match: '(?=""")'
pop: true
- include: escaped-unicode-char
- include: escaped-char
- include: constant-placeholder
- match: '(?=\S)'
set:
- meta_scope: meta.string.python string.quoted.double.block.python
- match: '"""'
scope: punctuation.definition.string.end.python
set: after-expression
- include: escaped-unicode-char
- include: escaped-char
- include: constant-placeholder
# 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
push:
- meta_content_scope: meta.string.python string.quoted.double.block.python
- match: '"""'
scope: punctuation.definition.string.end.python
set: after-expression
- include: escaped-char
- include: constant-placeholder
string-quoted-double:
# 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
push:
- meta_content_scope: meta.string.python string.quoted.double.python
- match: '"'
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-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
push:
- meta_content_scope: meta.string.python string.quoted.double.python
- match: '"'
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-string
# Single-line raw string, unicode or not, starting with a SQL keyword
- match: '([uU]?r)(")(?={{sql_indicator}})'
captures:
1: storage.type.string.python
2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.python string.quoted.double.python
- match: '"'
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-string
- match: ''
push: scope:source.sql
with_prototype:
- match: '(?="|\n)'
pop: true
- include: constant-placeholder
- include: line-continuation-inside-string
# Single-line raw string, unicode or not, treated as regex
- match: '([uU]?r)(")'
captures:
1: storage.type.string.python
2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.python string.quoted.double.python
- match: '"'
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-string
- match: ''
push: scope:source.regexp.python
with_prototype:
- match: '(?="|\n)'
pop: true
- include: line-continuation-inside-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
push:
- meta_content_scope: meta.string.python string.quoted.double.python
- match: '"'
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-string
- match: ''
embed: scope:source.regexp.python
escape: (?="|\n)
# Single-line raw f-string
- match: ((?i)fr|rf)(")
captures:
1: storage.type.string.python
2: meta.string.interpolated.python string.quoted.double.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.interpolated.python string.quoted.double.python
- match: '"'
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-string
- include: f-string-content
# Single-line f-string
- match: ((?i)f|f)(")
captures:
1: storage.type.string.python
2: meta.string.interpolated.python string.quoted.double.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.interpolated.python string.quoted.double.python
- match: '"'
scope: punctuation.definition.string.end.python
set: after-expression
- include: escaped-unicode-char
- include: escaped-char
- include: line-continuation-inside-string
- include: f-string-content
# Single-line string, unicode or not, starting with a SQL keyword
- match: '([uU]?)(")(?={{sql_indicator}})'
captures:
1: storage.type.string.python
2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.python string.quoted.double.python
- match: '"'
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-string
- match: ''
push: scope:source.sql
with_prototype:
- match: '(?="|\n)'
pop: true
- include: escaped-unicode-char
- include: escaped-char
- include: line-continuation-inside-string
- include: constant-placeholder
# Single-line string, unicode or not
- match: '([uU]?)(")'
captures:
1: storage.type.string.python
2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.python string.quoted.double.python
- match: '"'
scope: punctuation.definition.string.end.python
set: after-expression
- include: escaped-unicode-char
- include: escaped-char
- include: line-continuation-inside-string
- include: constant-placeholder
# 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
push:
- meta_content_scope: meta.string.python string.quoted.double.python
- match: '"'
scope: punctuation.definition.string.end.python
set: after-expression
- include: escaped-char
- include: line-continuation-inside-string
- include: constant-placeholder
string-quoted-single-block:
# 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
push:
- meta_content_scope: meta.string.python string.quoted.single.block.python
- match: "'''"
scope: punctuation.definition.string.end.python
set: after-expression
# 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
push:
- meta_content_scope: meta.string.python string.quoted.single.block.python
- match: "'''"
scope: punctuation.definition.string.end.python
set: after-expression
# 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
push:
- meta_content_scope: meta.string.python string.quoted.single.block.python
- match: '(?={{sql_indicator}})'
set:
- meta_scope: meta.string.python string.quoted.single.block.python
- match: "'''"
scope: punctuation.definition.string.end.python
set: after-expression
- match: ''
push: scope:source.sql
with_prototype:
- match: (?=''')
pop: true
- include: escaped-unicode-char
- include: escaped-char
- include: constant-placeholder
- match: '(?=\S)'
set:
- meta_scope: meta.string.python string.quoted.single.block.python
- match: "'''"
scope: punctuation.definition.string.end.python
set: after-expression
- match: ''
push: scope:source.regexp.python
with_prototype:
- match: (?=''')
pop: true
- include: escaped-unicode-char
# 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
push:
- meta_content_scope: meta.string.python string.quoted.single.block.python
- match: "'''"
scope: punctuation.definition.string.end.python
set: after-expression
- match: ''
embed: scope:source.regexp.python
escape: (?=''')
# Triple-quoted raw f-string
- match: ((?i)fr|rf)(''')
captures:
1: storage.type.string.python
2: meta.string.interpolated.python string.quoted.single.block.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.interpolated.python string.quoted.single.block.python
- match: "'''"
scope: punctuation.definition.string.begin.python
set: after-expression
- include: f-string-content
# Triple-quoted f-string
- match: ([fF])(''')
captures:
1: storage.type.string.python
2: meta.string.interpolated.python string.quoted.single.block.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.interpolated.python string.quoted.single.block.python
- match: "'''"
scope: punctuation.definition.string.begin.python
set: after-expression
- include: escaped-unicode-char
- include: escaped-char
- include: f-string-content
# 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
push:
- meta_content_scope: meta.string.python string.quoted.single.block.python
- match: '(?={{sql_indicator}})'
set:
- meta_scope: meta.string.python string.quoted.single.block.python
- match: "'''"
scope: punctuation.definition.string.end.python
set: after-expression
- match: ''
push: scope:source.sql
with_prototype:
- match: (?=''')
pop: true
- include: escaped-unicode-char
- include: escaped-char
- include: constant-placeholder
- match: '(?=\S)'
set:
- meta_scope: meta.string.python string.quoted.single.block.python
- match: "'''"
scope: punctuation.definition.string.end.python
set: after-expression
- include: escaped-unicode-char
- include: escaped-char
- include: constant-placeholder
# 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
push:
- meta_content_scope: meta.string.python string.quoted.single.block.python
- match: "'''"
scope: punctuation.definition.string.end.python
set: after-expression
- include: escaped-char
- include: constant-placeholder
string-quoted-single:
# 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
push:
- meta_content_scope: meta.string.python string.quoted.single.python
- match: "'"
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-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
push:
- meta_content_scope: meta.string.python string.quoted.single.python
- match: "'"
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-string
# Single-line raw string, unicode or not, starting with a SQL keyword
- match: '([uU]?r)('')(?={{sql_indicator}})'
captures:
1: storage.type.string.python
2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.python string.quoted.single.python
- match: "'"
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-string
- match: ''
push: scope:source.sql
with_prototype:
- match: '(?=''|\n)'
pop: true
- include: line-continuation-inside-string
- include: constant-placeholder
# Single-line raw string, unicode or not, treated as regex
- match: '([uU]?r)('')'
captures:
1: storage.type.string.python
2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.python string.quoted.single.python
- match: "'"
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-string
- match: ''
push: scope:source.regexp.python
with_prototype:
- match: '(?=''|\n)'
pop: true
- include: line-continuation-inside-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
push:
- meta_content_scope: meta.string.python string.quoted.single.python
- match: "'"
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-string
- match: ''
push: scope:source.regexp.python
with_prototype:
- match: '(?=''|\n)'
pop: true
- include: line-continuation-inside-string
# Single-line raw f-string
- match: ((?i)fr|rf)(')
captures:
1: storage.type.string.python
2: meta.string.interpolated.python string.quoted.single.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.interpolated.python string.quoted.single.python
- match: "'"
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-string
- include: f-string-content
# Single-line f-string
- match: ((?i)f|f)(')
captures:
1: storage.type.string.python
2: meta.string.interpolated.python string.quoted.single.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.interpolated.python string.quoted.single.python
- match: "'"
scope: punctuation.definition.string.end.python
set: after-expression
- include: escaped-unicode-char
- include: escaped-char
- include: line-continuation-inside-string
- include: f-string-content
# Single-line string, unicode or not, starting with a SQL keyword
- match: '([uU]?)('')(?={{sql_indicator}})'
captures:
1: storage.type.string.python
2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.python string.quoted.single.python
- match: "'"
scope: punctuation.definition.string.end.python
set: after-expression
- include: line-continuation-inside-string
- match: ''
push: scope:source.sql
with_prototype:
- match: '(?=''|\n)'
pop: true
- include: escaped-unicode-char
- include: escaped-char
- include: line-continuation-inside-string
- include: constant-placeholder
# Single-line string, unicode or not
- match: '([uU]?)('')'
captures:
1: storage.type.string.python
2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python
push:
- meta_content_scope: meta.string.python string.quoted.single.python
- match: "'"
scope: punctuation.definition.string.end.python
set: after-expression
- include: escaped-unicode-char
- include: escaped-char
- include: line-continuation-inside-string
- include: constant-placeholder
# 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
push:
- meta_content_scope: meta.string.python string.quoted.single.python
- match: "'"
scope: punctuation.definition.string.end.python
set: after-expression
- include: escaped-char
- include: line-continuation-inside-string
- include: constant-placeholder
strings:
# block versions must be matched first
- include: string-quoted-double-block
- include: string-quoted-double
- include: string-quoted-single-block
- include: string-quoted-single
inline-for:
- match: \b(?:(async)\s+)?(for)\b
captures:
1: storage.modifier.async.python
2: keyword.control.flow.for.generator.python
push:
- include: comments
- meta_scope: meta.expression.generator.python
- match: \b(in)\b
scope: keyword.control.flow.for.in.python
pop: true
- match: '(?=[)\]}])'
scope: invalid.illegal.missing-in.python
pop: true
- include: illegal-names-pop
- include: target-list
inline-if:
- match: \b(if)\b
scope: keyword.control.flow.if.inline.python
- match: \b(else)\b
scope: keyword.control.flow.else.inline.python
target-list:
- match: ','
scope: punctuation.separator.target-list.python
- match: \(
scope: punctuation.section.target-list.begin.python
push:
- include: comments
- match: ','
scope: punctuation.separator.target-list.python
- match: \)
scope: punctuation.section.target-list.end.python
pop: true
- include: target-list
- include: name
- include: name