codekingpro/portable-devtools
115k
1" Vim syntax file2" Language: Python3" Maintainer: Zvezdan Petkovic <zpetkovic@acm.org>4" Last Change: 2025 Sep 085" 2025 Sep 25 by Vim Project: fix wrong type highlighting #183946" 2025 Dec 03 by Vim Project: highlight t-strings #186797" 2026 Jan 26 by Vim Project: highlight constants #189228" 2026 Mar 11 by Vim Project: fix number performance #196309" Credits: Neil Schemenauer <nas@python.ca>10" Dmitry Vasiliev11" Rob B12" Jon Parise13"14" This version is a major rewrite by Zvezdan Petkovic.15"16" - introduced highlighting of doctests17" - updated keywords, built-ins, and exceptions18" - corrected regular expressions for19"20" * functions21" * decorators22" * strings23" * escapes24" * numbers25" * space error26"27" - corrected synchronization28" - more highlighting is ON by default, except29" - space error highlighting is OFF by default30"31" Optional highlighting can be controlled using these variables.32"33" let python_no_builtin_highlight = 134" let python_no_doctest_code_highlight = 135" let python_no_doctest_highlight = 136" let python_no_exception_highlight = 137" let python_no_number_highlight = 138" let python_space_error_highlight = 139" let python_constant_highlight = 140"41" All the options above can be switched on together.42"43" let python_highlight_all = 144"45" The use of Python 2 compatible syntax highlighting can be enforced.46" The straddling code (Python 2 and 3 compatible), up to Python 3.5,47" will be also supported.48"49" let python_use_python2_syntax = 150"51" This option will exclude all modern Python 3.6 or higher features.52"53 54" quit when a syntax file was already loaded.55if exists("b:current_syntax")56 finish57endif58 59" Use of Python 2 and 3.5 or lower requested.60if exists("python_use_python2_syntax")61 runtime! syntax/python2.vim62 finish63endif64 65" We need nocompatible mode in order to continue lines with backslashes.66" Original setting will be restored.67let s:cpo_save = &cpo68set cpo&vim69 70if exists("python_no_doctest_highlight")71 let python_no_doctest_code_highlight = 172endif73 74if exists("python_highlight_all")75 if exists("python_no_builtin_highlight")76 unlet python_no_builtin_highlight77 endif78 if exists("python_no_doctest_code_highlight")79 unlet python_no_doctest_code_highlight80 endif81 if exists("python_no_doctest_highlight")82 unlet python_no_doctest_highlight83 endif84 if exists("python_no_exception_highlight")85 unlet python_no_exception_highlight86 endif87 if exists("python_no_number_highlight")88 unlet python_no_number_highlight89 endif90 let python_space_error_highlight = 191 let python_constant_highlight = 192endif93 94" Keep Python keywords in alphabetical order inside groups for easy95" comparison with the table in the 'Python Language Reference'96" https://docs.python.org/reference/lexical_analysis.html#keywords.97" Groups are in the order presented in NAMING CONVENTIONS in syntax.txt.98" Exceptions come last at the end of each group (class and def below).99"100" The list can be checked using:101"102" python3 -c 'import keyword, pprint; pprint.pprint(keyword.kwlist + keyword.softkwlist, compact=True)'103"104syn keyword pythonBoolean False True105syn keyword pythonConstant None106syn keyword pythonStatement as assert break continue del global107syn keyword pythonStatement lambda nonlocal pass return with yield108syn keyword pythonStatement class nextgroup=pythonClass skipwhite109syn keyword pythonStatement def nextgroup=pythonFunction skipwhite110syn keyword pythonConditional elif else if111syn keyword pythonRepeat for while112syn keyword pythonOperator and in is not or113syn keyword pythonException except finally raise try114syn keyword pythonInclude from import115syn keyword pythonAsync async await116 117" Soft keywords118" These keywords do not mean anything unless used in the right context.119" See https://docs.python.org/3/reference/lexical_analysis.html#soft-keywords120" for more on this.121syn match pythonConditional "^\s*\zscase\%(\s\+.*:.*$\)\@="122syn match pythonConditional "^\s*\zsmatch\%(\s\+.*:\s*\%(#.*\)\=$\)\@="123syn match pythonStatement "\<type\ze\s\+\h\w*" nextgroup=pythonType skipwhite124 125" These names are special by convention. While they aren't real keywords,126" giving them distinct highlighting provides a nice visual cue.127syn keyword pythonClassVar self cls128 129" Decorators130" A dot must be allowed because of @MyClass.myfunc decorators.131syn match pythonDecorator "@" display contained132syn match pythonDecoratorName "@\s*\h\%(\w\|\.\)*" display contains=pythonDecorator133 134" Python 3.5 introduced the use of the same symbol for matrix multiplication:135" https://www.python.org/dev/peps/pep-0465/. We now have to exclude the136" symbol from highlighting when used in that context.137" Single line multiplication.138syn match pythonMatrixMultiply139 \ "\%(\w\|[])]\)\s*@"140 \ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonClass,pythonFunction,pythonType,pythonDoctestValue141 \ transparent142" Multiplication continued on the next line after backslash.143syn match pythonMatrixMultiply144 \ "[^\\]\\\s*\n\%(\s*\.\.\.\s\)\=\s\+@"145 \ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonClass,pythonFunction,pythonType,pythonDoctestValue146 \ transparent147" Multiplication in a parenthesized expression over multiple lines with @ at148" the start of each continued line; very similar to decorators and complex.149syn match pythonMatrixMultiply150 \ "^\s*\%(\%(>>>\|\.\.\.\)\s\+\)\=\zs\%(\h\|\%(\h\|[[(]\).\{-}\%(\w\|[])]\)\)\s*\n\%(\s*\.\.\.\s\)\=\s\+@\%(.\{-}\n\%(\s*\.\.\.\s\)\=\s\+@\)*"151 \ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonClass,pythonFunction,pythonType,pythonDoctestValue152 \ transparent153 154syn match pythonClass "\h\w*" display contained155syn match pythonFunction "\h\w*" display contained156syn match pythonType "\h\w*" display contained157 158syn match pythonComment "#.*$" contains=pythonTodo,@Spell159syn keyword pythonTodo FIXME NOTE NOTES TODO XXX contained160 161" Triple-quoted strings can contain doctests.162syn region pythonString matchgroup=pythonQuotes163 \ start=+[uU]\=\z(['"]\)+ end="\z1" skip="\\\\\|\\\z1"164 \ contains=pythonEscape,pythonUnicodeEscape,@Spell165syn region pythonString matchgroup=pythonTripleQuotes166 \ start=+[uU]\=\z('''\|"""\)+ end="\z1" keepend167 \ contains=pythonEscape,pythonUnicodeEscape,pythonSpaceError,pythonDoctest,@Spell168syn region pythonRawString matchgroup=pythonQuotes169 \ start=+[rR]\z(['"]\)+ end="\z1" skip="\\\\\|\\\z1"170 \ contains=@Spell171syn region pythonRawString matchgroup=pythonTripleQuotes172 \ start=+[rR]\z('''\|"""\)+ end="\z1" keepend173 \ contains=pythonSpaceError,pythonDoctest,@Spell174 175" Formatted string literals (f-strings)176" https://docs.python.org/3/reference/lexical_analysis.html#f-strings177" Template string literals (t-strings)178" https://docs.python.org/3/reference/lexical_analysis.html#template-string-literals179syn region pythonFString180 \ matchgroup=pythonQuotes181 \ start=+\c[FT]\z(['"]\)+182 \ end="\z1"183 \ skip="\\\\\|\\\z1"184 \ contains=pythonFStringField,pythonFStringSkip,pythonEscape,pythonUnicodeEscape,@Spell185syn region pythonFString186 \ matchgroup=pythonTripleQuotes187 \ start=+\c[FT]\z('''\|"""\)+188 \ end="\z1"189 \ keepend190 \ contains=pythonFStringField,pythonFStringSkip,pythonEscape,pythonUnicodeEscape,pythonSpaceError,pythonDoctest,@Spell191syn region pythonRawFString192 \ matchgroup=pythonQuotes193 \ start=+\c\%([FT]R\|R[FT]\)\z(['"]\)+194 \ end="\z1"195 \ skip="\\\\\|\\\z1"196 \ contains=pythonFStringField,pythonFStringSkip,@Spell197syn region pythonRawFString198 \ matchgroup=pythonTripleQuotes199 \ start=+\c\%([FT]R\|R[FT]\)\z('''\|"""\)+200 \ end="\z1"201 \ keepend202 \ contains=pythonFStringField,pythonFStringSkip,pythonSpaceError,pythonDoctest,@Spell203 204" Bytes205syn region pythonBytes206 \ matchgroup=pythonQuotes207 \ start=+\cB\z(['"]\)+208 \ end="\z1"209 \ skip="\\\\\|\\\z1"210 \ contains=pythonEscape211syn region pythonBytes212 \ matchgroup=pythonTripleQuotes213 \ start=+\cB\z('''\|"""\)+214 \ end="\z1"215 \ keepend216 \ contains=pythonEscape217syn region pythonRawBytes218 \ matchgroup=pythonQuotes219 \ start=+\c\%(BR\|RB\)\z(['"]\)+220 \ end="\z1"221 \ skip="\\\\\|\\\z1"222syn region pythonRawBytes223 \ matchgroup=pythonTripleQuotes224 \ start=+\c\%(BR\|RB\)\z('''\|"""\)+225 \ end="\z1"226 \ keepend227 228" F-string replacement fields229"230" - Matched parentheses, brackets and braces are skipped231" - A bare = (followed by optional whitespace) enables debugging232" - A bare ! prefixes a conversion field (followed by optional whitespace)233" - A bare : begins a format specification234" - Matched braces inside a format specification are skipped235"236syn region pythonFStringField237 \ matchgroup=pythonFStringDelimiter238 \ start=/{/239 \ end=/\%(=\s*\)\=\%(!\a\s*\)\=\%(:\%({\_[^}]*}\|[^{}]*\)\+\)\=}/240 \ contained241 \ contains=ALLBUT,pythonFStringField,pythonClass,pythonFunction,pythonType,pythonDoctest,pythonDoctestValue,@Spell242syn match pythonFStringFieldSkip /(\_[^()]*)\|\[\_[^][]*]\|{\_[^{}]*}/243 \ contained244 \ contains=ALLBUT,pythonFStringField,pythonClass,pythonFunction,pythonType,pythonDoctest,pythonDoctestValue,@Spell245 246" Doubled braces are not replacement fields247syn match pythonFStringSkip /{{/ transparent contained contains=NONE248 249syn match pythonEscape +\\[abfnrtv'"\\]+ contained250syn match pythonEscape "\\\o\{1,3}" contained251syn match pythonEscape "\\x\x\{2}" contained252syn match pythonUnicodeEscape "\%(\\u\x\{4}\|\\U\x\{8}\)" contained253" Python allows case-insensitive Unicode IDs: http://www.unicode.org/charts/254" The specification: https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-4/#G135165255syn match pythonUnicodeEscape "\\N{\a\+\%(\%(\s\a\+[[:alnum:]]*\)\|\%(-[[:alnum:]]\+\)\)*}" contained256syn match pythonEscape "\\$"257 258" It is very important to understand all details before changing the259" regular expressions below or their order.260" The word boundaries are *not* the floating-point number boundaries261" because of a possible leading or trailing decimal point.262" The expressions below ensure that all valid number literals are263" highlighted, and invalid number literals are not. For example,264"265" - a decimal point in '4.' at the end of a line is highlighted,266" - a second dot in 1.0.0 is not highlighted,267" - 08 is not highlighted,268" - 08e0 or 08j are highlighted,269"270" and so on, as specified in the 'Python Language Reference'.271" https://docs.python.org/reference/lexical_analysis.html#numeric-literals272if !exists("python_no_number_highlight")273 " numbers (including complex)274 syn match pythonNumber "\<0[oO]_\=\o\+\%(_\o\+\)*\>"275 syn match pythonNumber "\<0[xX]_\=\x\+\%(_\x\+\)*\>"276 syn match pythonNumber "\<0[bB]_\=[01]\+\%(_[01]\+\)*\>"277 syn match pythonNumber "\<\%([1-9]\d*\%(_\d\+\)*\|0\+\%(_0\+\)*\)\>"278 syn match pythonNumber "\<\d\+\%(_\d\+\)*[jJ]\>"279 syn match pythonNumber "\<\d\+\%(_\d\+\)*[eE][+-]\=\d\+\%(_\d\+\)*[jJ]\=\>"280 " \d\.281 syn match pythonNumber282 \ "\<\d\+\%(_\d\+\)*\.\%([eE][+-]\=\d\+\%(_\d\+\)*\)\=[jJ]\=\%(\W\|$\)\@="283 " \d\.\d284 syn match pythonNumber285 \ "\<\d\+\%(_\d\+\)*\.\d\+\%(_\d\+\)*\%([eE][+-]\=\d\+\%(_\d\+\)*\)\=[jJ]\=\>"286 " \.\d287 syn match pythonNumber288 \ "\%(^\|\W\)\@1<=\.\d\+\%(_\d\+\)*\%([eE][+-]\=\d\+\%(_\d\+\)*\)\=[jJ]\=\>"289endif290 291" Group the built-ins in the order in the 'Python Library Reference' for292" easier comparison.293" https://docs.python.org/library/constants.html294" http://docs.python.org/library/functions.html295" Python built-in functions are in alphabetical order.296"297" The list can be checked using:298"299" python3 -c 'import builtins, pprint; pprint.pprint(dir(builtins), compact=True)'300"301" The constants added by the `site` module are not listed below because they302" should not be used in programs, only in interactive interpreter.303" Similarly for some other attributes and functions `__`-enclosed from the304" output of the above command.305"306if !exists("python_no_builtin_highlight")307 " built-in constants308 " 'False', 'True', and 'None' are also reserved words in Python 3309 syn keyword pythonBoolean False True310 syn keyword pythonConstant None NotImplemented Ellipsis __debug__311 " constants added by the `site` module312 syn keyword pythonBuiltin quit exit copyright credits license313 " built-in functions314 syn keyword pythonBuiltin abs all any ascii bin bool breakpoint bytearray315 syn keyword pythonBuiltin bytes callable chr classmethod compile complex316 syn keyword pythonBuiltin delattr dict dir divmod enumerate eval exec317 syn keyword pythonBuiltin filter float format frozenset getattr globals318 syn keyword pythonBuiltin hasattr hash help hex id input int isinstance319 syn keyword pythonBuiltin issubclass iter len list locals map max320 syn keyword pythonBuiltin memoryview min next object oct open ord pow321 syn keyword pythonBuiltin print property range repr reversed round set322 syn keyword pythonBuiltin setattr slice sorted staticmethod str sum super323 syn keyword pythonBuiltin tuple vars zip __import__324 " only match `type` as a builtin when it's not followed by an identifier325 syn match pythonBuiltin "\<type\>\ze\(\s\+\h\w*\)\@!"326 " avoid highlighting attributes as builtins327 syn match pythonAttribute /\.\h\w*/hs=s+1328 \ contains=ALLBUT,pythonBuiltin,pythonClass,pythonFunction,pythonType,pythonAsync329 \ transparent330 " the ellipsis literal `...` can be used in multiple syntactic contexts331 syn match pythonEllipsis "\.\@1<!\.\.\.\ze\.\@!" display332endif333 334" From the 'Python Library Reference' class hierarchy at the bottom.335" http://docs.python.org/library/exceptions.html336if !exists("python_no_exception_highlight")337 " builtin base exceptions (used mostly as base classes for other exceptions)338 syn keyword pythonExceptions BaseException Exception339 syn keyword pythonExceptions ArithmeticError BufferError LookupError340 " builtin exceptions (actually raised)341 syn keyword pythonExceptions AssertionError AttributeError EOFError342 syn keyword pythonExceptions FloatingPointError GeneratorExit ImportError343 syn keyword pythonExceptions IndentationError IndexError KeyError344 syn keyword pythonExceptions KeyboardInterrupt MemoryError345 syn keyword pythonExceptions ModuleNotFoundError NameError346 syn keyword pythonExceptions NotImplementedError OSError OverflowError347 syn keyword pythonExceptions RecursionError ReferenceError RuntimeError348 syn keyword pythonExceptions StopAsyncIteration StopIteration SyntaxError349 syn keyword pythonExceptions SystemError SystemExit TabError TypeError350 syn keyword pythonExceptions UnboundLocalError UnicodeDecodeError351 syn keyword pythonExceptions UnicodeEncodeError UnicodeError352 syn keyword pythonExceptions UnicodeTranslateError ValueError353 syn keyword pythonExceptions ZeroDivisionError354 " builtin exception aliases for OSError355 syn keyword pythonExceptions EnvironmentError IOError WindowsError356 " builtin OS exceptions in Python 3357 syn keyword pythonExceptions BlockingIOError BrokenPipeError358 syn keyword pythonExceptions ChildProcessError ConnectionAbortedError359 syn keyword pythonExceptions ConnectionError ConnectionRefusedError360 syn keyword pythonExceptions ConnectionResetError FileExistsError361 syn keyword pythonExceptions FileNotFoundError InterruptedError362 syn keyword pythonExceptions IsADirectoryError NotADirectoryError363 syn keyword pythonExceptions PermissionError ProcessLookupError TimeoutError364 " builtin warnings365 syn keyword pythonExceptions BytesWarning DeprecationWarning FutureWarning366 syn keyword pythonExceptions ImportWarning PendingDeprecationWarning367 syn keyword pythonExceptions ResourceWarning RuntimeWarning368 syn keyword pythonExceptions SyntaxWarning UnicodeWarning369 syn keyword pythonExceptions UserWarning Warning370endif371 372if exists("python_space_error_highlight")373 " trailing whitespace374 syn match pythonSpaceError display excludenl "\s\+$"375 " mixed tabs and spaces376 syn match pythonSpaceError display " \+\t"377 syn match pythonSpaceError display "\t\+ "378endif379 380" Do not spell doctests inside strings.381" Notice that the end of a string, either ''', or """, will end the contained382" doctest too. Thus, we do *not* need to have it as an end pattern.383if !exists("python_no_doctest_highlight")384 if !exists("python_no_doctest_code_highlight")385 syn region pythonDoctest386 \ start="^\s*>>>\s" end="^\s*$"387 \ contained contains=ALLBUT,pythonDoctest,pythonEllipsis,pythonClass,pythonFunction,pythonType,@Spell388 syn region pythonDoctestValue389 \ start=+^\s*\%(>>>\s\|\.\.\.\s\|"""\|'''\)\@!\S\++ end="$"390 \ contained contains=pythonEllipsis391 syn match pythonEllipsis "\%(^\s*\)\@<!\.\@1<!\zs\.\.\.\ze\.\@!" display392 \ contained containedin=pythonDoctest393 else394 syn region pythonDoctest395 \ start="^\s*>>>" end="^\s*$"396 \ contained contains=@NoSpell397 endif398endif399 400" Sync at the beginning of (async) function or class definitions.401syn sync match pythonSync grouphere NONE "^\%(def\|class\|async\s\+def\)\s\+\h\w*\s*[(:]"402 403" The default highlight links. Can be overridden later.404hi def link pythonBoolean Statement405hi def link pythonConstant Statement406hi def link pythonStatement Statement407hi def link pythonConditional Conditional408hi def link pythonRepeat Repeat409hi def link pythonOperator Operator410hi def link pythonException Exception411hi def link pythonInclude Include412hi def link pythonAsync Statement413hi def link pythonClassVar Identifier414hi def link pythonDecorator Define415hi def link pythonDecoratorName Function416hi def link pythonClass Structure417hi def link pythonFunction Function418hi def link pythonType Type419hi def link pythonComment Comment420hi def link pythonTodo Todo421hi def link pythonString String422hi def link pythonRawString String423hi def link pythonFString String424hi def link pythonRawFString String425hi def link pythonBytes String426hi def link pythonRawBytes String427hi def link pythonQuotes String428hi def link pythonTripleQuotes pythonQuotes429hi def link pythonEscape Special430hi def link pythonUnicodeEscape pythonEscape431hi def link pythonFStringDelimiter Special432if !exists("python_no_number_highlight")433 hi def link pythonNumber Number434endif435if !exists("python_no_builtin_highlight")436 hi! def link pythonBoolean Function437 hi! def link pythonConstant Function438 hi def link pythonBuiltin Function439 hi def link pythonEllipsis pythonBuiltin440endif441if !exists("python_no_exception_highlight")442 hi def link pythonExceptions Structure443endif444if exists("python_space_error_highlight")445 hi def link pythonSpaceError Error446endif447if !exists("python_no_doctest_highlight")448 hi def link pythonDoctest Special449 hi def link pythonDoctestValue Define450endif451if exists("python_constant_highlight")452 hi! def link pythonBoolean Boolean453 hi! def link pythonConstant Constant454endif455 456let b:current_syntax = "python"457 458let &cpo = s:cpo_save459unlet s:cpo_save460 461" vim:set sw=2 sts=2 ts=8 noet:462 