Browse Source

Add support for Python 3.6 f-string literal and underscore in numbers.

Joongi Kim 8 years ago
parent
commit
e07541aa59
2 changed files with 37 additions and 15 deletions
  1. 29
    13
      syntax/python.vim
  2. 8
    2
      test.py

+ 29
- 13
syntax/python.vim View File

186
   syn match   pythonStatement   "\<async\s\+for\>" display
186
   syn match   pythonStatement   "\<async\s\+for\>" display
187
 endif
187
 endif
188
 
188
 
189
+syn cluster pythonExpression contains=pythonStatement,pythonRepeat,pythonConditional,pythonOperator,pythonNumber,pythonHexNumber,pythonOctNumber,pythonBinNumber,pythonFloat,pythonString,pythonBytes,pythonBoolean,pythonBuiltinObj,pythonBuiltinFunc
190
+
189
 "
191
 "
190
 " Decorators (new in Python 2.4)
192
 " Decorators (new in Python 2.4)
191
 "
193
 "
276
   syn region pythonString   start=+"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,@Spell
278
   syn region pythonString   start=+"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,@Spell
277
   syn region pythonString   start=+"""+ end=+"""+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,pythonDocTest2,pythonSpaceError,@Spell
279
   syn region pythonString   start=+"""+ end=+"""+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,pythonDocTest2,pythonSpaceError,@Spell
278
   syn region pythonString   start=+'''+ end=+'''+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,pythonDocTest,pythonSpaceError,@Spell
280
   syn region pythonString   start=+'''+ end=+'''+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,pythonDocTest,pythonSpaceError,@Spell
281
+
282
+  syn region pythonFString   start=+[fF]'+ skip=+\\\\\|\\'\|\\$+ excludenl end=+'+ end=+$+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,@Spell
283
+  syn region pythonFString   start=+[fF]"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end=+$+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,@Spell
284
+  syn region pythonFString   start=+[fF]"""+ end=+"""+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,pythonDocTest2,pythonSpaceError,@Spell
285
+  syn region pythonFString   start=+[fF]'''+ end=+'''+ keepend contains=pythonBytesEscape,pythonBytesEscapeError,pythonUniEscape,pythonUniEscapeError,pythonDocTest,pythonSpaceError,@Spell
279
 endif
286
 endif
280
 
287
 
281
 if s:Python2Syntax()
288
 if s:Python2Syntax()
326
     syn match pythonStrFormat "{{\|}}" contained containedin=pythonString,pythonUniString,pythonUniRawString,pythonRawString
333
     syn match pythonStrFormat "{{\|}}" contained containedin=pythonString,pythonUniString,pythonUniRawString,pythonRawString
327
     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,pythonUniString,pythonUniRawString,pythonRawString
334
     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,pythonUniString,pythonUniRawString,pythonRawString
328
   else
335
   else
329
-    syn match pythonStrFormat "{{\|}}" contained containedin=pythonString,pythonRawString
330
-    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
336
+    syn match pythonStrFormat "{{\|}}" contained containedin=pythonString,pythonRawString,pythonFString
337
+    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
338
+    syn region pythonStrInterpRegion start="{"he=e+1,rs=e+1 end="\%(![rsa]\)\=\%(:\%({\%(\%([^[:cntrl:][:space:][:punct:][:digit:]]\|_\)\%([^[:cntrl:][:punct:][:space:]]\|_\)*\|\d\+\)}\|\%([^}]\=[<>=^]\)\=[ +-]\=#\=0\=\d*,\=\%(\.\d\+\)\=[bcdeEfFgGnosxX%]\=\)\=\)\=}"hs=s-1,re=s-1 extend contained containedin=pythonFString contains=pythonStrInterpRegion,@pythonExpression
331
   endif
339
   endif
332
 endif
340
 endif
333
 
341
 
370
 
378
 
371
   syn match   pythonOctError	"\<0[oO]\=\o*[8-9]\d*[lL]\=\>" display
379
   syn match   pythonOctError	"\<0[oO]\=\o*[8-9]\d*[lL]\=\>" display
372
   syn match   pythonBinError	"\<0[bB][01]*[2-9]\d*[lL]\=\>" display
380
   syn match   pythonBinError	"\<0[bB][01]*[2-9]\d*[lL]\=\>" display
381
+
382
+  syn match   pythonFloat	"\.\d\+\%([eE][+-]\=\d\+\)\=[jJ]\=\>" display
383
+  syn match   pythonFloat	"\<\d\+[eE][+-]\=\d\+[jJ]\=\>" display
384
+  syn match   pythonFloat	"\<\d\+\.\d*\%([eE][+-]\=\d\+\)\=[jJ]\=" display
373
 else
385
 else
374
   syn match   pythonHexError	"\<0[xX]\x*[g-zG-Z]\x*\>" display
386
   syn match   pythonHexError	"\<0[xX]\x*[g-zG-Z]\x*\>" display
375
   syn match   pythonOctError	"\<0[oO]\=\o*\D\+\d*\>" display
387
   syn match   pythonOctError	"\<0[oO]\=\o*\D\+\d*\>" display
376
   syn match   pythonBinError	"\<0[bB][01]*\D\+\d*\>" display
388
   syn match   pythonBinError	"\<0[bB][01]*\D\+\d*\>" display
377
 
389
 
378
-  syn match   pythonHexNumber	"\<0[xX]\x\+\>" display
379
-  syn match   pythonOctNumber "\<0[oO]\o\+\>" display
380
-  syn match   pythonBinNumber "\<0[bB][01]\+\>" display
390
+  syn match   pythonHexNumber	"\<0[xX][_0-9a-fA-F]*\x\>" display
391
+  syn match   pythonOctNumber "\<0[oO][_0-7]*\o\>" display
392
+  syn match   pythonBinNumber "\<0[bB][_01]*[01]\>" display
381
 
393
 
382
-  syn match   pythonNumberError	"\<\d\+\D\>" display
383
-  syn match   pythonNumberError	"\<0\d\+\>" display
394
+  syn match   pythonNumberError	"\<\d[_0-9]*\D\>" display
395
+  syn match   pythonNumberError	"\<0[_0-9]\+\>" display
396
+  syn match   pythonNumberError	"\<\%(_[_0-9]\+\|[_0-9]\+_\)\>" display
384
   syn match   pythonNumber	"\<\d\>" display
397
   syn match   pythonNumber	"\<\d\>" display
385
-  syn match   pythonNumber	"\<[1-9]\d\+\>" display
386
-  syn match   pythonNumber	"\<\d\+[jJ]\>" display
398
+  syn match   pythonNumber	"\<[1-9][_0-9]*\d\>" display
399
+  syn match   pythonNumber	"\<\d[jJ]\>" display
400
+  syn match   pythonNumber	"\<[1-9][_0-9]*\d[jJ]\>" display
387
 
401
 
388
   syn match   pythonOctError	"\<0[oO]\=\o*[8-9]\d*\>" display
402
   syn match   pythonOctError	"\<0[oO]\=\o*[8-9]\d*\>" display
389
   syn match   pythonBinError	"\<0[bB][01]*[2-9]\d*\>" display
403
   syn match   pythonBinError	"\<0[bB][01]*[2-9]\d*\>" display
390
-endif
391
 
404
 
392
-syn match   pythonFloat		"\.\d\+\%([eE][+-]\=\d\+\)\=[jJ]\=\>" display
393
-syn match   pythonFloat		"\<\d\+[eE][+-]\=\d\+[jJ]\=\>" display
394
-syn match   pythonFloat		"\<\d\+\.\d*\%([eE][+-]\=\d\+\)\=[jJ]\=" display
405
+  syn match   pythonFloat	"\.\d\%([_0-9]*\d\)\=\%([eE][+-]\=\d\%([_0-9]*\d\)\=\)\=[jJ]\=\>" display
406
+  syn match   pythonFloat	"\<\d\%([_0-9]*\d\)\=[eE][+-]\=\d\%([_0-9]*\d\)\=[jJ]\=\>" display
407
+  syn match   pythonFloat	"\<\d\%([_0-9]*\d\)\=\.\d\%([_0-9]*\d\)\=\%([eE][+-]\=\d\%([_0-9]*\d\)\=\)\=[jJ]\=" display
408
+endif
395
 
409
 
396
 "
410
 "
397
 " Builtin objects and types
411
 " Builtin objects and types
536
     HiLink pythonBytesError         Error
550
     HiLink pythonBytesError         Error
537
     HiLink pythonBytesEscape        Special
551
     HiLink pythonBytesEscape        Special
538
     HiLink pythonBytesEscapeError   Error
552
     HiLink pythonBytesEscapeError   Error
553
+    HiLink pythonFString            String
554
+    HiLink pythonStrInterpRegion    Special
539
   endif
555
   endif
540
 
556
 
541
   HiLink pythonStrFormatting    Special
557
   HiLink pythonStrFormatting    Special

+ 8
- 2
test.py View File

61
 
61
 
62
 # Numbers
62
 # Numbers
63
 
63
 
64
-0 1 2 9 10 0x1f .3 12.34 0j 0j 34.2E-3 0b10 0o77 1023434 0x0
64
+0 1 2 9 10 0x1f .3 12.34 0j 124j 34.2E-3 0b10 0o77 1023434 0x0
65
+1_1 1_1.2_2 1_2j 0x_1f 0x1_f 34_56e-3 34_56e+3_1 0o7_7
65
 
66
 
66
 # Erroneous numbers
67
 # Erroneous numbers
67
 
68
 
68
-077 100L 0xfffffffL 0L 08 0xk 0x  0b102 0o78 0o123LaB
69
+077 100L 0xfffffffL 0L 08 0xk 0x 0b102 0o78 0o123LaB
70
+0_ 0_1 _0 0_x1f 0x1f_ 0_b77 0b77_ ._2 .2_ 1_j
69
 
71
 
70
 # Strings
72
 # Strings
71
 
73
 
103
 "${test} ${test ${test}aname $$$ $test+nope"
105
 "${test} ${test ${test}aname $$$ $test+nope"
104
 b"${test} ${test ${test}aname $$$ $test+nope"
106
 b"${test} ${test ${test}aname $$$ $test+nope"
105
 
107
 
108
+f"{var}...{arr[123]} normal {var['{'] // 0xff} \"xzcb\" 'xzcb' {var['}'] + 1} text"
109
+f"{expr1 if True or False else expr2} wow {','.join(c.lower() for c in 'asdf')}"
110
+f"hello {expr:.2f} yes {(lambda: 0b1)():#03x} lol {var!r}"
111
+
106
 # Doctests.
112
 # Doctests.
107
 
113
 
108
 """
114
 """