hdima / python-syntax

Python syntax highlighting script for Vim
http://www.vim.org/scripts/script.php?script_id=790
MIT License
363 stars 109 forks source link

Python 3.6 f-string literal support #58

Open achimnol opened 7 years ago

achimnol commented 7 years ago

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.

achimnol commented 7 years ago

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:

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! 😁

nfnty commented 7 years ago

This has been fixed over at the fork vim-python/python-syntax.