lectures.alex.balgavy.eu

Lecture notes from university.
git clone git://git.alex.balgavy.eu/lectures.alex.balgavy.eu.git
Log | Files | Refs | Submodules

syntax_test_python_strings.py (28371B)


      1 # SYNTAX TEST "Packages/Python/Python.sublime-syntax"
      2 
      3 ###############################
      4 # Strings and embedded syntaxes
      5 ###############################
      6 
      7 var = "\x00 \xaa \xAF \070 \0 \r \n \t \\ \a \b \' \v \f \u0aF1 \UFe0a182f \N{SPACE}"
      8 #     ^ meta.string.python
      9 #      ^^^^ constant.character.escape.hex
     10 #           ^^^^ constant.character.escape.hex
     11 #                ^^^^ constant.character.escape.hex
     12 #                     ^^^^ constant.character.escape.octal
     13 #                          ^^ constant.character.escape
     14 #                             ^^ constant.character.escape
     15 #                                ^^ constant.character.escape
     16 #                                   ^^ constant.character.escape
     17 #                                      ^^ constant.character.escape
     18 #                                         ^^ constant.character.escape
     19 #                                            ^^ constant.character.escape
     20 #                                               ^^ constant.character.escape
     21 #                                                  ^^ constant.character.escape
     22 #                                                     ^^ constant.character.escape
     23 #                                                        ^^^^^^ constant.character.escape.unicode
     24 #                                                               ^^^^^^^^^^ constant.character.escape.unicode
     25 #                                                                          ^^^^^^^^^ constant.character.escape.unicode
     26 
     27 invalid_escapes = "\.  \-"
     28 #                  ^^ invalid.deprecated.character.escape.python
     29 #                      ^^ invalid.deprecated.character.escape.python
     30 
     31 conn.execute("SELECT * FROM foobar")
     32 #              ^ meta.string.python keyword.other.DML.sql
     33 
     34 conn.execute('SELECT * FROM foobar')
     35 #              ^ keyword.other.DML.sql
     36 
     37 conn.execute(U"SELECT * FROM foobar")
     38 #              ^ keyword.other.DML.sql
     39 
     40 conn.execute(U'SELECT * FROM foobar')
     41 #              ^ keyword.other.DML.sql
     42 
     43 # In this example, the Python string is not raw, so \t is a python escape
     44 conn.execute(u"SELECT * FROM foobar WHERE foo = '\t'")
     45 #              ^ keyword.other.DML.sql
     46 #                                                 ^ constant.character.escape.python
     47 
     48 conn.execute(u'SELECT * FROM foobar')
     49 #              ^ keyword.other.DML.sql
     50 
     51 # In this example, the Python string is raw, so the \b should be a SQL escape
     52 conn.execute(r"SELECT * FROM foobar WHERE baz = '\b")
     53 #              ^ meta.string.python keyword.other.DML.sql
     54 #                                                 ^ constant.character.escape.sql
     55 
     56 # This tests to ensure the Python placeholder will be highlighted even in a raw SQL string
     57 conn.execute(r'SELECT * FROM foobar WHERE %s')
     58 #              ^ keyword.other.DML.sql
     59 #                                         ^ constant.other.placeholder.python
     60 
     61 conn.execute(r"SELECT * FROM foobar")
     62 #              ^ keyword.other.DML.sql
     63 
     64 conn.execute(r'SELECT * FROM foobar')
     65 #              ^ keyword.other.DML.sql
     66 
     67 conn.execute(r"""SELECT * FROM foobar WHERE %s and foo = '\t'""")
     68 #                 ^ keyword.other.DML.sql
     69 #                                            ^ constant.other.placeholder.python
     70 #                                                          ^ constant.character.escape.sql
     71 
     72 # Capital R prevents all syntax embedding
     73 conn.execute(R'SELECT * FROM foobar')
     74 #              ^ meta.string.python - keyword.other.DML.sql
     75 
     76 conn.execute(R"SELECT * FROM foobar")
     77 #              ^ - keyword.other.DML.sql
     78 
     79 conn.execute(R"""SELECT * FROM foobar""")
     80 #                ^ - keyword.other.DML.sql
     81 
     82 conn.execute(r'''SELECT * FROM foobar''')
     83 #                 ^ keyword.other.DML.sql
     84 
     85 conn.execute(u"""SELECT * FROM foobar WHERE %s and foo = '\t'""")
     86 #                 ^ keyword.other.DML.sql
     87 #                                            ^ constant.other.placeholder.python
     88 #                                                          ^ constant.character.escape.python
     89 
     90 regex = r'\b ([fobar]*){1}(?:a|b)?'
     91 #         ^ meta.string.python keyword.control.anchor.regexp
     92 #                       ^ keyword.operator.quantifier.regexp
     93 
     94 regex = r'.* # Not a comment (yet)'
     95 #            ^^^^^^^^^^^^^^^^^^^^^ - comment
     96 #                                 ^ punctuation.definition.string.end.python - comment
     97 #                                  ^ - invalid
     98 
     99 regex = r".* # Not a comment (yet)"
    100 #            ^^^^^^^^^^^^^^^^^^^^^ - comment
    101 #                                 ^ punctuation.definition.string.end.python - comment
    102 #                                  ^ - invalid
    103 
    104 regex = r'''\b ([fobar]*){1}(?:a|b)?'''
    105 #           ^ keyword.control.anchor.regexp
    106 #                         ^ keyword.operator.quantifier.regexp
    107 
    108 regex = r"""\b ([fobar]*){1}(?:a|b)?"""
    109 #           ^ keyword.control.anchor.regexp
    110 #                         ^ keyword.operator.quantifier.regexp
    111 
    112 # Capital R prevents all syntax embedding
    113 regex = R'\b ([fobar]*){1}(?:a|b)?'
    114 #         ^ - keyword.control.anchor.regexp
    115 #                       ^ - keyword.operator.quantifier.regexp
    116 
    117 regex = R"\b ([fobar]*){1}(?:a|b)?"
    118 #         ^ - keyword.control.anchor.regexp
    119 #                       ^ - keyword.operator.quantifier.regexp
    120 
    121 bad_string = 'SELECT * FROM users
    122 #                                ^ invalid.illegal.unclosed-string
    123 
    124 more_bad_string = r"
    125 #                   ^ invalid.illegal.unclosed-string.python
    126 
    127 string = '''
    128 
    129 # <- string.quoted.single.block
    130 '''
    131 
    132 string = """
    133 
    134 # <- string.quoted.double.block
    135 """
    136 
    137 string = """
    138 #        ^^^ string.quoted.double.block - string string
    139 \
    140 # <- punctuation.separator.continuation.line.python
    141 """
    142 
    143 string = r"""
    144 #         ^^^ meta.string.python string.quoted.double.block
    145 \
    146 # <- - punctuation
    147 """
    148 
    149 string = r"""
    150     # An indented comment.
    151 #  ^ - comment
    152 #   ^ comment.line.number-sign.regexp
    153 ### <<This comment>> @includes some &punctutation.
    154 # <- comment.line.number-sign.regexp
    155 """
    156 
    157 string = '''
    158 #        ^^^ string.quoted.single.block
    159 '''
    160 
    161 string = r'''
    162 #         ^^^ string.quoted.single.block
    163 '''
    164 
    165 string = r'''
    166     # An indented comment.
    167 #  ^ - comment
    168 #   ^ comment.line.number-sign.regexp
    169 ### <<This comment>> @includes some &punctutation.
    170 # <- comment.line.number-sign.regexp
    171 '''
    172 
    173 string = r'''
    174     [set]
    175 #   ^^^^^ constant.other.character-class.set.regexp
    176 #   ^ punctuation.definition.character-class.begin.regexp
    177 #       ^ punctuation.definition.character-class.end.regexp
    178     (group)
    179 #   ^^^^^^^ meta.group.regexp
    180 #   ^ punctuation.definition.group.begin.regexp
    181 #         ^ punctuation.definition.group.end.regexp
    182     (?<!group)
    183 #   ^^^^^^^^^^ meta.group.assertion.regexp
    184 #   ^ punctuation.definition.group.begin.regexp
    185 #    ^^^ constant.other.assertion.regexp
    186 #            ^ punctuation.definition.group.end.regexp
    187 '''
    188 
    189 query = \
    190     """
    191     SELECT
    192         (
    193         SELECT CASE field
    194             WHEN 1
    195             THEN -- comment's say that
    196 #                              ^ source.sql comment.line.double-dash
    197                 EXISTS(
    198                 select 1)
    199             ELSE NULL
    200         ) as result
    201     """
    202 
    203 query = \
    204     r"""
    205 
    206     SELECT
    207         (
    208         SELECT CASE field
    209             WHEN 1
    210             THEN -- comment's say that
    211 #                              ^ source.sql comment.line.double-dash
    212                 EXISTS(
    213                 select 1)
    214             ELSE NULL
    215         ) as result
    216     """
    217 
    218 query = \
    219 '''
    220 SELECT
    221     (
    222     SELECT CASE field
    223         WHEN 1
    224         THEN -- comment's say that
    225 #                              ^ source.sql comment.line.double-dash
    226             EXISTS(
    227             select 1)
    228         ELSE NULL
    229     ) as result
    230 '''
    231 
    232 sql = 'SELECT * FROM foo -- bar baz'
    233 #       ^ source.sql
    234 #                            ^ source.sql comment.line.double-dash
    235 #                                  ^ punctuation.definition.string.end.python - source.sql
    236 
    237 
    238 # There are many variations of making a byte string
    239 (b'', B'', br'', bR'', BR'', Br'', rb'', Rb'', RB'', rB'')
    240 #^ storage.type.string
    241 #     ^ storage.type.string
    242 #          ^^ storage.type.string
    243 #                ^^ storage.type.string
    244 #                      ^^ storage.type.string
    245 #                            ^^ storage.type.string
    246 #                                  ^^ storage.type.string
    247 #                                        ^^ storage.type.string
    248 #                                              ^^ storage.type.string
    249 #                                                    ^^ storage.type.string
    250 
    251 # Bytes by defaut support placeholders and character escapes, but not unicode
    252 b'This is a \n test, %s no unicode \uDEAD'
    253 # <- storage.type.string
    254 #^ string.quoted.single punctuation.definition.string.begin
    255 #           ^^ constant.character.escape
    256 #                    ^^ constant.other.placeholder
    257 #                                  ^^^^^^ - constant
    258 B'This is a \n test, %s no unicode \uDEAD'
    259 # <- storage.type.string
    260 #^ string.quoted.single punctuation.definition.string.begin
    261 #           ^^ constant.character.escape
    262 #                    ^^ constant.other.placeholder
    263 #                                  ^^^^^^ - constant
    264 b'''This is a \n test, %s no unicode \uDEAD'''
    265 # <- storage.type.string
    266 #^^^ string.quoted.single punctuation.definition.string.begin
    267 #             ^^ constant.character.escape
    268 #                      ^^ constant.other.placeholder
    269 #                                    ^^^^^^ - constant
    270 B'''This is a \n test, %s no unicode \uDEAD'''
    271 # <- storage.type.string
    272 #^^^ string.quoted.single punctuation.definition.string.begin
    273 #             ^^ constant.character.escape
    274 #                      ^^ constant.other.placeholder
    275 #                                    ^^^^^^ - constant
    276 
    277 # Uppercase R raw bytes don't allow anything
    278 bR'This is a \n test, %s no unicode \uDEAD'
    279 # <- storage.type.string
    280 # ^ string.quoted.single punctuation.definition.string.begin
    281 #            ^^ - constant.character.escape
    282 #                     ^^ - constant.other.placeholder
    283 #                                   ^^^^^^ - constant
    284 BR'This is a \n test, %s no unicode \uDEAD'
    285 # <- storage.type.string
    286 # ^ string.quoted.single punctuation.definition.string.begin
    287 #            ^^ - constant.character.escape
    288 #                     ^^ - constant.other.placeholder
    289 #                                   ^^^^^^ - constant
    290 Rb'This is a \n test, %s no unicode \uDEAD'
    291 # <- storage.type.string
    292 # ^ string.quoted.single punctuation.definition.string.begin
    293 #            ^^ - constant.character.escape
    294 #                     ^^ - constant.other.placeholder
    295 #                                   ^^^^^^ - constant
    296 RB'This is a \n test, %s no unicode \uDEAD'
    297 # <- storage.type.string
    298 # ^ string.quoted.single punctuation.definition.string.begin
    299 #            ^^ - constant.character.escape
    300 #                     ^^ - constant.other.placeholder
    301 #                                   ^^^^^^ - constant
    302 bR'''This is a \n test, %s no unicode \uDEAD'''
    303 # <- storage.type.string
    304 # ^^^ string.quoted.single punctuation.definition.string.begin
    305 #              ^^ - constant.character.escape
    306 #                       ^^ - constant.other.placeholder
    307 #                                     ^^^^^^ - constant
    308 BR'''This is a \n test, %s no unicode \uDEAD'''
    309 # <- storage.type.string
    310 # ^^^ string.quoted.single punctuation.definition.string.begin
    311 #              ^^ - constant.character.escape
    312 #                       ^^ - constant.other.placeholder
    313 #                                     ^^^^^^ - constant
    314 Rb'''This is a \n test, %s no unicode \uDEAD'''
    315 # <- storage.type.string
    316 # ^^^ string.quoted.single punctuation.definition.string.begin
    317 #              ^^ - constant.character.escape
    318 #                       ^^ - constant.other.placeholder
    319 #                                     ^^^^^^ - constant
    320 RB'''This is a \n test, %s no unicode \uDEAD'''
    321 # <- storage.type.string
    322 # ^^^ string.quoted.single punctuation.definition.string.begin
    323 #              ^^ - constant.character.escape
    324 #                       ^^ - constant.other.placeholder
    325 #                                     ^^^^^^ - constant
    326 
    327 # Lowercase r raw bytes are interpreted as regex
    328 br'This is a \n (test|with), %s no unicode \uDEAD'
    329 # <- storage.type.string
    330 # ^ string.quoted.single punctuation.definition.string.begin
    331 #            ^^ constant.character.escape.backslash.regexp
    332 #                    ^ keyword.operator.or.regexp
    333 #                            ^^ - constant
    334 #                                          ^^ constant.character.escape.backslash.regexp
    335 #                                            ^^^^ - constant
    336 Br'This is a \n (test|with), %s no unicode \uDEAD'
    337 # <- storage.type.string
    338 # ^ string.quoted.single punctuation.definition.string.begin
    339 #            ^^ constant.character.escape.backslash.regexp
    340 #                    ^ keyword.operator.or.regexp
    341 #                            ^^ - constant
    342 #                                          ^^ constant.character.escape.backslash.regexp
    343 #                                            ^^^^ - constant
    344 rb'This is a \n (test|with), %s no unicode \uDEAD'
    345 # <- storage.type.string
    346 # ^ string.quoted.single punctuation.definition.string.begin
    347 #            ^^ constant.character.escape.backslash.regexp
    348 #                    ^ keyword.operator.or.regexp
    349 #                            ^^ - constant
    350 #                                          ^^ constant.character.escape.backslash.regexp
    351 #                                            ^^^^ - constant
    352 rB'This is a \n (test|with), %s no unicode \uDEAD'
    353 # <- storage.type.string
    354 # ^ string.quoted.single punctuation.definition.string.begin
    355 #            ^^ constant.character.escape.backslash.regexp
    356 #                    ^ keyword.operator.or.regexp
    357 #                            ^^ - constant
    358 #                                          ^^ constant.character.escape.backslash.regexp
    359 #                                            ^^^^ - constant
    360 br'''This is a \n (test|with), %s no unicode \uDEAD'''
    361 # <- storage.type.string
    362 # ^^^ string.quoted.single punctuation.definition.string.begin
    363 #              ^^ constant.character.escape.backslash.regexp
    364 #                      ^ keyword.operator.or.regexp
    365 #                              ^^ - constant
    366 #                                            ^^ constant.character.escape.backslash.regexp
    367 #                                              ^^^^ - constant
    368 Br'''This is a \n (test|with), %s no unicode \uDEAD'''
    369 # <- storage.type.string
    370 # ^^^ string.quoted.single punctuation.definition.string.begin
    371 #              ^^ constant.character.escape.backslash.regexp
    372 #                      ^ keyword.operator.or.regexp
    373 #                              ^^ - constant
    374 #                                            ^^ constant.character.escape.backslash.regexp
    375 #                                              ^^^^ - constant
    376 rb'''This is a \n (test|with), %s no unicode \uDEAD'''
    377 # <- storage.type.string
    378 # ^^^ string.quoted.single punctuation.definition.string.begin
    379 #              ^^ constant.character.escape.backslash.regexp
    380 #                      ^ keyword.operator.or.regexp
    381 #                              ^^ - constant
    382 #                                            ^^ constant.character.escape.backslash.regexp
    383 #                                              ^^^^ - constant
    384 rB'''This is a \n (test|with), %s no unicode \uDEAD'''
    385 # <- storage.type.string
    386 # ^^^ meta.string.python string.quoted.single punctuation.definition.string.begin
    387 #              ^^ constant.character.escape.backslash.regexp
    388 #                      ^ keyword.operator.or.regexp
    389 #                              ^^ - constant
    390 #                                            ^^ constant.character.escape.backslash.regexp
    391 #                                              ^^^^ - constant
    392 
    393 datetime.strptime('2011227', '%Y%V%u')
    394 #                            ^^^^^^^^ string.quoted.single.python
    395 #                             ^^^^^^ constant.other.placeholder.python
    396 datetime.strftime(datetime.now(), '%Y%V%uT')
    397 #                                 ^^^^^^^^^ string.quoted.single.python
    398 #                                  ^^^^^^ constant.other.placeholder.python
    399 #                                        ^ - constant.other.placeholder.python
    400 
    401 '{0:%Y%m%d}'.format(datetime.date.today())
    402 # ^^^^^^^^^^ string.quoted.single.python
    403 # ^^^^^^^^ constant.other.placeholder.python
    404 #   ^^^^^^ constant.other.format-spec.python
    405 '{0:%Y-%m-%d}'.format(datetime.date.today())
    406 # ^^^^^^^^^^^^ string.quoted.single.python
    407 # ^^^^^^^^^^ constant.other.placeholder.python
    408 #   ^^^^^^^^ constant.other.format-spec.python
    409 '{0:%Y-%m-%dT}'.format(datetime.date.today())
    410 # ^^^^^^^^^^^^ string.quoted.single.python
    411 # ^^^^^^^^^^^ constant.other.placeholder.python
    412 #   ^^^^^^^^^ constant.other.format-spec.python
    413 '{0:T}'.format(datetime.date.today())  # This is legal but uninteresting
    414 # ^^^^^ string.quoted.single.python
    415 '{0:%Y}-{0:%m}-{0:%d}'.format(datetime.date.today())
    416 # ^^^^^^^^^^^^^^^^^^^ string.quoted.single.python
    417 # ^^^^^ constant.other.placeholder.python
    418 #  ^^^ constant.other.format-spec.python
    419 #      ^ - constant.other.placeholder.python
    420 #       ^^^^^^ constant.other.placeholder.python
    421 #          ^^ constant.other.format-spec.python
    422 #             ^ - constant.other.placeholder.python
    423 #              ^^^^^^ constant.other.placeholder.python
    424 #                 ^^ constant.other.format-spec.python
    425 '{0:%Y}-{0:%m
    426 # ^^^^^^^^^^^ string.quoted.single.python
    427 # ^^^^^ constant.other.placeholder.python
    428 #  ^^^ constant.other.format-spec.python
    429 #      ^^^^ - constant.other.placeholder.python
    430 #            ^ invalid.illegal.unclosed-string.python
    431 '{0:%Y}-{0:%
    432 # ^^^^^^^^^^^ string.quoted.single.python
    433 # ^^^^^ constant.other.placeholder.python
    434 #  ^^^ constant.other.format-spec.python
    435 #      ^^^^^ - constant.other.placeholder.python
    436 #           ^ invalid.illegal.unclosed-string.python
    437 
    438 x = "hello \
    439 #   ^^^^^^^^^ string.quoted.double.python - invalid.illegal.unclosed-string.python, \
    440 #          ^ punctuation.separator.continuation.line.python, \
    441 world"
    442 #^^^^^ string.quoted.double.python
    443 #     ^ - string.quoted.double.python
    444 #    ^ punctuation.definition.string.end.python
    445 
    446 x = 'hello \
    447 #   ^^^^^^^^^ string.quoted.single.python - invalid.illegal.unclosed-string.python, \
    448 #          ^ punctuation.separator.continuation.line.python, \
    449 world'
    450 #^^^^^ string.quoted.single.python
    451 #     ^ - string.quoted.single.python
    452 #    ^ punctuation.definition.string.end.python
    453 
    454 x = 'hello\s world'
    455 #         ^^ - punctuation.separator.continuation.line.python
    456 #          ^^^^^^^^ - invalid.illegal.unexpected-text.python
    457 
    458 sql = "SELECT `name` FROM `users` \
    459     WHERE `password` LIKE 'abc'"
    460 #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double source.sql
    461 #                              ^ punctuation.definition.string.end.python
    462 
    463 sql = Ur"SELECT `name` FROM `users` \
    464     WHERE `password` LIKE 'abc'"
    465 #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double source.sql
    466 #                              ^ punctuation.definition.string.end.python
    467 
    468 sql = b'just some \
    469 #      ^^^^^^^^^^^^^ string.quoted.single.python - invalid.illegal.unclosed-string.python, \
    470 #                 ^ punctuation.separator.continuation.line.python, \
    471     string'
    472 #^^^^^^^^^^ string.quoted.single
    473 #         ^ punctuation.definition.string.end.python
    474 
    475 # https://docs.python.org/3/library/string.html#formatspec
    476 "First, thou shalt count to {0}"  # References first positional argument
    477 #                           ^^^ constant.other.placeholder.python
    478 "Bring me a {}"                   # Implicitly references the first positional argument
    479 #           ^^ constant.other.placeholder.python
    480 "From {} to {}"                   # Same as "From {0} to {1}"
    481 #     ^^ constant.other.placeholder.python
    482 #       ^^^^ - constant.other.placeholder.python
    483 #           ^^ constant.other.placeholder.python
    484 "My quest is {name}"              # References keyword argument 'name'
    485 #            ^^^^^^ constant.other.placeholder.python
    486 "Weight in tons {0.weight}"       # 'weight' attribute of first positional arg
    487 #               ^^^^^^^^^^ constant.other.placeholder.python
    488 "Units destroyed: {players[0]}"   # First element of keyword argument 'players'.
    489 #                 ^^^^^^^^^^^^ constant.other.placeholder.python
    490 "Harold's a clever {0!s}"         # Calls str() on the argument first
    491 #                  ^^^^^ constant.other.placeholder.python
    492 #                    ^^ storage.modifier.conversion.python
    493 "Bring out the holy {name!r}"     # Calls repr() on the argument first
    494 #                   ^^^^^^^^ constant.other.placeholder.python
    495 "More {!a}"                       # Calls ascii() on the argument first
    496 #     ^^^^ constant.other.placeholder.python
    497 "More {!a: <10s}"                 # Calls ascii() on the argument first, then formats
    498 #     ^^^^^^^^^^ constant.other.placeholder.python
    499 "Escaped {{0}}"                   # outputs: "Escaped {0}"
    500 #        ^^^^^ - constant.other.placeholder.python
    501 #        ^^ constant.character.escape.python
    502 #           ^^ constant.character.escape.python
    503 "Escaped {{}} {} {}"              # outputs: "Escaped {} arg1 arg2"
    504 #        ^^^^ constant.character.escape.python - constant.other.placeholder.python
    505 #             ^^ constant.other.placeholder.python
    506 #               ^ - constant.other.placeholder.python
    507 #                ^^ constant.other.placeholder.python
    508 
    509 datetime.datetime.utcnow().strftime("%Y%m%d%H%M")
    510 #                                    ^^^^^^^^^^ constant.other.placeholder
    511 
    512 "My String %% %s"
    513 #          ^^ constant.other.placeholder
    514 #             ^^ constant.other.placeholder
    515 
    516 "My String %(s)s %s"
    517 #          ^^^^^ constant.other.placeholder
    518 #            ^ variable.other.placeholder
    519 #                ^^ constant.other.placeholder
    520 
    521 "Testing {:,.2f}".format(1000)
    522 #        ^^^^^^^ constant.other.placeholder
    523 #        ^ punctuation.definition.placeholder.begin
    524 #              ^ punctuation.definition.placeholder.end
    525 
    526 "Testing {0:>9,}".format(1000)
    527 #        ^^^^^^^ constant.other.placeholder
    528 
    529 "Testing {:j^9,}".format(1000)
    530 #        ^^^^^^^ constant.other.placeholder
    531 #         ^^^^^ constant.other.format-spec
    532 
    533 "result: {value:{width}.{precision}}"
    534 #        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant.other.placeholder
    535 #              ^^^^^^^^^^^^^^^^^^^^ meta.format-spec.python
    536 #        ^ punctuation.definition.placeholder.begin
    537 #               ^^^^^^^ constant.other.placeholder constant.other.placeholder
    538 #               ^ punctuation.definition.placeholder.begin
    539 #                       ^^^^^^^^^^^ constant.other.placeholder constant.other.placeholder
    540 #                                 ^^ punctuation.definition.placeholder.end
    541 
    542 a=["aaaa{", "bbbb{"]
    543 #       ^ - constant.other.placeholder
    544 #        ^ punctuation.definition.string.end.python
    545 
    546 foo = "{text{" # Comment
    547 #      ^^^^^^ - constant.other.placeholder
    548 #            ^ punctuation.definition.string.end
    549 bar = "}}" # Comment
    550 #      ^^ constant.character.escape
    551 
    552 f"string"
    553 # <- storage.type.string
    554 #^^^^^^^^ string.quoted.double
    555 
    556  RF"""string"""
    557 #^^ storage.type.string - string
    558 #  ^^^^^^^^^^^^ meta.string.interpolated string.quoted.double.block
    559 
    560 F'''string'''
    561 # <- storage.type.string
    562 #^^^^^^^^^^^^ meta.string.interpolated string.quoted.single.block
    563 
    564  rf'string'
    565 #^^ storage.type.string - string
    566 #  ^^^^^^^^ meta.string.interpolated string.quoted.single
    567 
    568 rf'\r\n' f'\r\n' Rf'\r\n'
    569 #  ^^^^ source.regexp constant.character.escape.backslash.regexp
    570 #          ^^^^ constant.character.escape.python
    571 #                   ^^^^ - constant
    572 
    573 rf"\r\n" f"\r\n" Rf'\r\n'
    574 #  ^^^^ source.regexp constant.character.escape.backslash.regexp
    575 #          ^^^^ constant.character.escape.python
    576 #                   ^^^^ - constant
    577 
    578 expr = fr"^\s*({label}|{notlabel})"
    579 #         ^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.python
    580 #         ^ meta.string.interpolated.python string.quoted.double.python source.regexp.python keyword.control.anchor.regexp
    581 #             ^ source.regexp.python meta.group.regexp punctuation.definition.group.begin.regexp
    582 #              ^^^^^^^ source.python meta.string.interpolated.python meta.interpolation.python
    583 #               ^^^^^ source.python.embedded meta.qualified-name.python meta.generic-name.python
    584 #                                ^ source.regexp.python meta.group.regexp punctuation.definition.group.end.regexp
    585 
    586 line = re.sub(rf" ?\{{\\i.?\}}({x})\{{\\i.?\}}", r"\1", line)
    587 #                  ^^^^^ constant.character.escape.backslash.regexp
    588 #                   ^^ constant.character.escape.python
    589 #                          ^^^ constant.character.escape.backslash.regexp
    590 #                           ^^ constant.character.escape.python
    591 #                              ^ punctuation.section.interpolation.begin.python
    592 
    593 f"\{{{x}\}} test"
    594 # ^ invalid.deprecated.character.escape.python
    595 #  ^^ constant.character.escape.python
    596 #    ^ punctuation.section.interpolation.begin.python
    597 
    598 f"{something}"
    599 #^^^^^^^^^^^^ meta.string.interpolated
    600 # <- storage.type.string
    601 #^ punctuation.definition.string.begin
    602 # ^ punctuation.section.interpolation.begin
    603 #           ^ punctuation.section.interpolation.end
    604 #            ^ punctuation.definition.string.end
    605 #  ^^^^^^^^^ source source.python.embedded
    606 #              ^ source - meta, string, source source
    607 
    608 f"{True!a:02f}"
    609 #^^^^^^^^^^^^^^ meta.string.interpolated
    610 # ^ - source source.python.embedded
    611 #  ^^^^ source source.python.embedded constant.language
    612 #      ^^^^^^^ - source source.python.embedded
    613 #      ^^ storage.modifier.conversion - constant.other.format-spec
    614 #        ^^^^ constant.other.format-spec
    615 #            ^ punctuation.section.interpolation.end
    616 #             ^ punctuation.definition.string.end
    617 #              ^ source - meta, string, source source
    618 
    619 f"result: {value:{width}.{precision}}\n"
    620 #         ^ punctuation.section.interpolation.begin.python - source source
    621 #          ^^^^^ source source.python.embedded
    622 #               ^^ - source source
    623 #                ^ punctuation.section.interpolation.begin.python
    624 #                 ^^^^^ source source.python.embedded
    625 #                      ^ punctuation.section.interpolation.end.python
    626 #                       ^ - source source
    627 #                        ^ punctuation.section.interpolation.begin.python
    628 #                         ^^^^^^^^^ source source.python.embedded
    629 #                                  ^^ punctuation.section.interpolation.end.python - source source
    630 #                                    ^^ constant.character.escape
    631 #          ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.interpolation.python
    632 #               ^^^^^^^^^^^^^^^^^^^^ meta.format-spec.python
    633 #          ^^^^^^ - meta.interpolation.python meta.interpolation.python
    634 #                ^^^^^^^ meta.interpolation.python meta.interpolation.python
    635 #                       ^ - meta.interpolation.python meta.interpolation.python
    636 #                        ^^^^^^^^^^^ meta.interpolation.python meta.interpolation.python
    637 #                                   ^^^ - meta.interpolation.python meta.interpolation.python
    638 rf"{value:{width!s:d}}"
    639 # <- storage.type.string.python - string
    640 # ^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated
    641 #          ^^^^^ source source.python.embedded
    642 #               ^^ storage.modifier.conversion
    643 #                 ^^ constant.other.format-spec
    644 
    645 F""" {} {\} }
    646 #^^^^^^^^^^^ meta.string.interpolated
    647 #^^^ punctuation.definition.string.begin
    648 #    ^^ invalid.illegal.empty-expression
    649 #        ^ invalid.illegal.backslash-in-fstring
    650 #           ^ invalid.illegal.stray-brace
    651 """
    652 
    653 fr'''
    654 #    ^ - invalid
    655 '''
    656 
    657 # Most of these were inspired by
    658 # https://github.com/python/cpython/commit/9a4135e939bc223f592045a38e0f927ba170da32
    659 f'{x=:}'
    660 #   ^ storage.modifier.debug.python
    661 f'{x=:.2f}'
    662 #   ^ storage.modifier.debug.python
    663 f'{x=!r}'
    664 #   ^ storage.modifier.debug.python
    665 f'{x=!a}'
    666 #   ^ storage.modifier.debug.python
    667 f'{x=!s:*^20}'
    668 #   ^ storage.modifier.debug.python
    669 #    ^^ storage.modifier.conversion.python
    670 #      ^^^^^ meta.format-spec.python
    671 f'{"Σ"=}'
    672 #     ^ storage.modifier.debug.python
    673 f'{0==1}'
    674 #   ^^ -storage.modifier.debug.python
    675 f'{0!=1}'
    676 #    ^ -storage.modifier.debug.python
    677 f'{0<=1}'
    678 #    ^ -storage.modifier.debug.python
    679 f'{0>=1}'
    680 #    ^ -storage.modifier.debug.python
    681 f'{f(a="3=")}'
    682 #     ^^^^ -storage.modifier.debug.python
    683 
    684 f" {
    685 %   ^ invalid.illegal.unclosed-string
    686    # TODO make this test pass
    687     }"
    688 
    689 f'   \
    690  {1 + 2!a:02f}'
    691 #^^^^^^^^^^^^^^ meta.string.interpolated
    692 # ^^^^^ source source.python.embedded
    693 
    694 f"{d for d in range(10)}"  # yes, this doesn't make sense
    695 #    ^^^ keyword.control.loop.for.generator.python
    696 
    697 f'
    698 # ^ invalid.illegal.unclosed-string
    699 
    700 
    701 # <- - meta
    702 # this test is to ensure we're not matching anything here anymore