Skip to content

Commit b93c9a4

Browse files
committed
Make fstrings more robust when dealing with comples formatting.
1 parent 8beee2f commit b93c9a4

14 files changed

+758
-169
lines changed

grammars/MagicPython.cson

+197-36
Original file line numberDiff line numberDiff line change
@@ -282,18 +282,15 @@ repository:
282282
match: "\\b(?<!\\.)(class)\\b"
283283
}
284284
]
285-
"expression-base":
286-
comment: "All valid Python expressions"
285+
"expression-bare":
286+
comment: "valid Python expressions w/o comments and line continuation"
287287
patterns: [
288288
{
289289
include: "#backticks"
290290
}
291291
{
292292
include: "#illegal-anno"
293293
}
294-
{
295-
include: "#comments"
296-
}
297294
{
298295
include: "#literal"
299296
}
@@ -348,11 +345,24 @@ repository:
348345
{
349346
include: "#special-variables"
350347
}
348+
{
349+
include: "#ellipsis"
350+
}
351351
{
352352
include: "#line-continuation"
353353
}
354+
]
355+
"expression-base":
356+
comment: "valid Python expressions with comments and line continuation"
357+
patterns: [
358+
{
359+
include: "#comments"
360+
}
354361
{
355-
include: "#ellipsis"
362+
include: "#expression-bare"
363+
}
364+
{
365+
include: "#line-continuation"
356366
}
357367
]
358368
expression:
@@ -869,35 +879,36 @@ repository:
869879
match: "(}(?!}))"
870880
}
871881
]
872-
"fstring-terminator":
882+
"fstring-illegal-single-brace":
883+
comment: "it is illegal to have a multiline brace inside a single-line string"
884+
begin: "(\\{)(?=[^\\n}]*$\\n?)"
885+
end: "(\\})|(?=\\n)"
886+
beginCaptures:
887+
"1":
888+
name: "constant.character.format.placeholder.other.python"
889+
endCaptures:
890+
"2":
891+
name: "constant.character.format.placeholder.other.python"
873892
patterns: [
874893
{
875-
match: '''
876-
(?x)
877-
(![rsa])
878-
( : \\w? [<>=^]? [-+ ]? \\#?
879-
\\d* ,? (\\.\\d+)? [bcdeEfFgGnosxX%]? )?
880-
881-
'''
882-
captures:
883-
"1":
884-
name: "storage.type.format.python"
885-
"2":
886-
name: "support.other.format.python"
894+
include: "#fstring-terminator-single"
887895
}
888896
{
889-
match: '''
890-
(?x)
891-
(![rsa])?
892-
( : \\w? [<>=^]? [-+ ]? \\#?
893-
\\d* ,? (\\.\\d+)? [bcdeEfFgGnosxX%]? )
894-
895-
'''
896-
captures:
897-
"1":
898-
name: "storage.type.format.python"
899-
"2":
900-
name: "support.other.format.python"
897+
include: "#f-expression"
898+
}
899+
]
900+
"f-expression":
901+
comment: "All valid Python expressions, except comments and line cont"
902+
patterns: [
903+
{
904+
include: "#expression-bare"
905+
}
906+
{
907+
include: "#member-access"
908+
}
909+
{
910+
comment: "Tokenize identifiers to help linters"
911+
match: "(?x) \\b ([[:alpha:]_]\\w*) \\b"
901912
}
902913
]
903914
"escape-sequence-unicode":
@@ -3409,6 +3420,9 @@ repository:
34093420
{
34103421
include: "#fstring-guts"
34113422
}
3423+
{
3424+
include: "#fstring-illegal-single-brace"
3425+
}
34123426
{
34133427
include: "#fstring-single-brace"
34143428
}
@@ -3440,7 +3454,7 @@ repository:
34403454
begin: "(\\{)"
34413455
end: '''
34423456
(?x)
3443-
(\\})
3457+
(\\})|(?=\\n)
34443458
34453459
'''
34463460
beginCaptures:
@@ -3451,10 +3465,82 @@ repository:
34513465
name: "constant.character.format.placeholder.other.python"
34523466
patterns: [
34533467
{
3454-
include: "#fstring-terminator"
3468+
include: "#fstring-terminator-single"
34553469
}
34563470
{
3457-
include: "#expression"
3471+
include: "#f-expression"
3472+
}
3473+
]
3474+
"fstring-terminator-single":
3475+
patterns: [
3476+
{
3477+
name: "storage.type.format.python"
3478+
match: "(![rsa])(?=})"
3479+
}
3480+
{
3481+
match: '''
3482+
(?x)
3483+
(![rsa])?
3484+
( : \\w? [<>=^]? [-+ ]? \\#?
3485+
\\d* ,? (\\.\\d+)? [bcdeEfFgGnosxX%]? )(?=})
3486+
3487+
'''
3488+
captures:
3489+
"1":
3490+
name: "storage.type.format.python"
3491+
"2":
3492+
name: "support.other.format.python"
3493+
}
3494+
{
3495+
include: "#fstring-terminator-single-tail"
3496+
}
3497+
]
3498+
"fstring-terminator-single-tail":
3499+
begin: "(![rsa])?(:)(?=.*?{)"
3500+
end: "(?=})|(?=\\n)"
3501+
beginCaptures:
3502+
"1":
3503+
name: "storage.type.format.python"
3504+
"2":
3505+
name: "support.other.format.python"
3506+
patterns: [
3507+
{
3508+
include: "#fstring-illegal-single-brace"
3509+
}
3510+
{
3511+
include: "#fstring-single-brace"
3512+
}
3513+
{
3514+
name: "support.other.format.python"
3515+
match: "([bcdeEfFgGnosxX%])(?=})"
3516+
}
3517+
{
3518+
name: "support.other.format.python"
3519+
match: "(\\.\\d+)"
3520+
}
3521+
{
3522+
name: "support.other.format.python"
3523+
match: "(,)"
3524+
}
3525+
{
3526+
name: "support.other.format.python"
3527+
match: "(\\d+)"
3528+
}
3529+
{
3530+
name: "support.other.format.python"
3531+
match: "(\\#)"
3532+
}
3533+
{
3534+
name: "support.other.format.python"
3535+
match: "([-+ ])"
3536+
}
3537+
{
3538+
name: "support.other.format.python"
3539+
match: "([<>=^])"
3540+
}
3541+
{
3542+
name: "support.other.format.python"
3543+
match: "(\\w)"
34583544
}
34593545
]
34603546
"fstring-quoted-multi-line":
@@ -3474,6 +3560,9 @@ repository:
34743560
{
34753561
include: "#fstring-guts"
34763562
}
3563+
{
3564+
include: "#fstring-illegal-multi-brace"
3565+
}
34773566
{
34783567
include: "#fstring-multi-brace"
34793568
}
@@ -3516,9 +3605,81 @@ repository:
35163605
name: "constant.character.format.placeholder.other.python"
35173606
patterns: [
35183607
{
3519-
include: "#fstring-terminator"
3608+
include: "#fstring-terminator-multi"
35203609
}
35213610
{
3522-
include: "#expression"
3611+
include: "#f-expression"
3612+
}
3613+
]
3614+
"fstring-terminator-multi":
3615+
patterns: [
3616+
{
3617+
name: "storage.type.format.python"
3618+
match: "(![rsa])(?=})"
3619+
}
3620+
{
3621+
match: '''
3622+
(?x)
3623+
(![rsa])?
3624+
( : \\w? [<>=^]? [-+ ]? \\#?
3625+
\\d* ,? (\\.\\d+)? [bcdeEfFgGnosxX%]? )(?=})
3626+
3627+
'''
3628+
captures:
3629+
"1":
3630+
name: "storage.type.format.python"
3631+
"2":
3632+
name: "support.other.format.python"
3633+
}
3634+
{
3635+
include: "#fstring-terminator-multi-tail"
3636+
}
3637+
]
3638+
"fstring-terminator-multi-tail":
3639+
begin: "(![rsa])?(:)(?=.*?{)"
3640+
end: "(?=})"
3641+
beginCaptures:
3642+
"1":
3643+
name: "storage.type.format.python"
3644+
"2":
3645+
name: "support.other.format.python"
3646+
patterns: [
3647+
{
3648+
include: "#fstring-illegal-multi-brace"
3649+
}
3650+
{
3651+
include: "#fstring-multi-brace"
3652+
}
3653+
{
3654+
name: "support.other.format.python"
3655+
match: "([bcdeEfFgGnosxX%])(?=})"
3656+
}
3657+
{
3658+
name: "support.other.format.python"
3659+
match: "(\\.\\d+)"
3660+
}
3661+
{
3662+
name: "support.other.format.python"
3663+
match: "(,)"
3664+
}
3665+
{
3666+
name: "support.other.format.python"
3667+
match: "(\\d+)"
3668+
}
3669+
{
3670+
name: "support.other.format.python"
3671+
match: "(\\#)"
3672+
}
3673+
{
3674+
name: "support.other.format.python"
3675+
match: "([-+ ])"
3676+
}
3677+
{
3678+
name: "support.other.format.python"
3679+
match: "([<>=^])"
3680+
}
3681+
{
3682+
name: "support.other.format.python"
3683+
match: "(\\w)"
35233684
}
35243685
]

0 commit comments

Comments
 (0)