Python 3.6 f-string literal support
Python 3.6 has reached its last beta where its features are frozen now. It introduces a new syntactic element: f-string literals. https://docs.python.org/3.6/whatsnew/3.6.html#whatsnew36-pep498
In f-string literals, the content inside braces are treated as real Python expressions with optional format string after a colon character like in format() protocol. The expression expansion may be done inside the format string as well though. (See the examples in the above link.)
Let's add support for this.
Trying to make a PR for this, but needs help! I'm not quite professional in vim syntax writing. 😞
syn region pythonFString start=+[fF]'+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,@Spell
syn region pythonFString start=+[fF]"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,@Spell
syn region pythonFString start=+[fF]"""+ end=+"""+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,pythonDocTest2,pythonSpaceError,@Spell
syn region pythonFString start=+[fF]'''+ end=+'''+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,pythonDocTest,pythonSpaceError,@Spell
...
syn match pythonStrFormat "{{\|}}" contained containedin=pythonString,pythonRawString
syn match pythonStrFormat "{\%(\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*\|\d\+\)\=\%(\.\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*\|\[\%(\d\+\|[^!:\}]\+\)\]\)*\%(![rsa]\)\=\%(:\%({\%(\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*\|\d\+\)}\|\%([^}]\=[<>=^]\)\=[ +-]\=#\=0\=\d*,\=\%(\.\d\+\)\=[bcdeEfFgGnosxX%]\=\)\=\)\=}" contained containedin=pythonString,pythonRawString
syn match pythonStrInterpFormat "{{\|}}" contained containedin=pythonFString
syn match pythonStrInterpFormat "{<any python expression>\%(![rsa]\)\=\%(:\%({\%(\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*\|\d\+\)}\|\%([^}]\=[<>=^]\)\=[ +-]\=#\=0\=\d*,\=\%(\.\d\+\)\=[bcdeEfFgGnosxX%]\=\)\=\)\=}" contained containedin=pythonFString
...
HiLink pythonFString String
HiLink pythonStrInterpFormat Special
I need to make Vim to treat above <any python expression> part like a just normal Python expression. The only rules for them are:
- It should not contain the string terminating quote (e.g., if the current f-string has begun with a single quote, then the expressions may not contain single quote because it will break the Python parser.
- As the content inside braces are limited to expressions, ~~colon and~~ exclamation mark can be used like previous string formatting mini-language. So I've copy-and-pasted the later part from the existing syntax. Update: colon may be used in parenthesized lambda expression, for example,
f"{(lambda: 1)()}"
A nice test case would be something like f"{var} plain {expr1 if True or False else expr2} text {var!r} {dictob['key']:.2f} abc {123_34E+2:g} {(lambda: 1)()}". Somebody please help me to figure out how to do this! 😁
This has been fixed over at the fork vim-python/python-syntax.