Skip to content

Commit 8ff35b3

Browse files
vpetrovykh1st1
authored andcommitted
Scope from, import, and as the same way in imports. (#165)
Use `keyword.control.import.python` scope for `from`, `import`, and `as` keywords when they appear as part of an import statement. Use `keyword.control.flow.python` scope for `from` and `as` if they appear elsewhere. Issue: #123.
1 parent ea55e27 commit 8ff35b3

File tree

11 files changed

+557
-56
lines changed

11 files changed

+557
-56
lines changed

grammars/MagicPython.cson

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,32 @@ repository:
259259
name: "storage.type.function.python"
260260
match: "\\b((async\\s+)?\\s*def)\\b"
261261
}
262+
{
263+
name: "keyword.control.flow.python"
264+
comment: '''
265+
if `as` is eventually followed by `:` or line continuation
266+
it's probably control flow like:
267+
with foo as bar, \\
268+
Foo as Bar:
269+
try:
270+
do_stuff()
271+
except Exception as e:
272+
pass
273+
274+
'''
275+
match: "\\b(?<!\\.)as\\b(?=.*[:\\\\])"
276+
}
277+
{
278+
name: "keyword.control.import.python"
279+
comment: "other legal use of `as` is in an import"
280+
match: "\\b(?<!\\.)as\\b"
281+
}
262282
{
263283
name: "keyword.control.flow.python"
264284
match: '''
265285
(?x)
266286
\\b(?<!\\.)(
267-
as | async | continue | del | assert | break | finally | for
287+
async | continue | del | assert | break | finally | for
268288
| from | elif | else | if | except | pass | raise
269289
| return | try | while | with
270290
)\\b
@@ -997,27 +1017,41 @@ repository:
9971017
match: "(}(?!}))"
9981018
import:
9991019
comment: '''
1000-
Import statements
1020+
Import statements used to correctly mark `from`, `import`, and `as`
10011021
10021022
'''
10031023
patterns: [
10041024
{
1005-
match: '''
1006-
(?x)
1007-
\\s* \\b(from) \\s*(\\.+)\\s* (import\\b)?
1008-
1009-
'''
1010-
captures:
1025+
begin: "\\b(?<!\\.)(from)\\b(?=.+import)"
1026+
end: "$|(?=import)"
1027+
beginCaptures:
10111028
"1":
10121029
name: "keyword.control.import.python"
1013-
"2":
1030+
patterns: [
1031+
{
10141032
name: "punctuation.separator.period.python"
1015-
"3":
1016-
name: "keyword.control.import.python"
1033+
match: "\\.+"
1034+
}
1035+
{
1036+
include: "#expression"
1037+
}
1038+
]
10171039
}
10181040
{
1019-
name: "keyword.control.import.python"
1020-
match: "\\b(?<!\\.)import\\b"
1041+
begin: "\\b(?<!\\.)(import)\\b"
1042+
end: "$"
1043+
beginCaptures:
1044+
"1":
1045+
name: "keyword.control.import.python"
1046+
patterns: [
1047+
{
1048+
name: "keyword.control.import.python"
1049+
match: "\\b(?<!\\.)as\\b"
1050+
}
1051+
{
1052+
include: "#expression"
1053+
}
1054+
]
10211055
}
10221056
]
10231057
"class-declaration":
@@ -1837,13 +1871,13 @@ repository:
18371871
(?x)
18381872
\\b(?:
18391873
(
1840-
and | as | assert | async | await | break | class | continue | def
1874+
and | assert | async | await | break | class | continue | def
18411875
| del | elif | else | except | finally | for | from | global
18421876
| if | in | is | (?<=\\.)lambda | lambda(?=\\s*[\\.=])
18431877
| nonlocal | not | or | pass | raise | return | try | while | with
18441878
| yield
18451879
) | (
1846-
import
1880+
as | import
18471881
)
18481882
)\\b
18491883

grammars/MagicPython.tmLanguage

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -416,13 +416,37 @@
416416
<key>match</key>
417417
<string>\b((async\s+)?\s*def)\b</string>
418418
</dict>
419+
<dict>
420+
<key>name</key>
421+
<string>keyword.control.flow.python</string>
422+
<key>comment</key>
423+
<string>if `as` is eventually followed by `:` or line continuation
424+
it's probably control flow like:
425+
with foo as bar, \
426+
Foo as Bar:
427+
try:
428+
do_stuff()
429+
except Exception as e:
430+
pass
431+
</string>
432+
<key>match</key>
433+
<string>\b(?&lt;!\.)as\b(?=.*[:\\])</string>
434+
</dict>
435+
<dict>
436+
<key>name</key>
437+
<string>keyword.control.import.python</string>
438+
<key>comment</key>
439+
<string>other legal use of `as` is in an import</string>
440+
<key>match</key>
441+
<string>\b(?&lt;!\.)as\b</string>
442+
</dict>
419443
<dict>
420444
<key>name</key>
421445
<string>keyword.control.flow.python</string>
422446
<key>match</key>
423447
<string>(?x)
424448
\b(?&lt;!\.)(
425-
as | async | continue | del | assert | break | finally | for
449+
async | continue | del | assert | break | finally | for
426450
| from | elif | else | if | except | pass | raise
427451
| return | try | while | with
428452
)\b
@@ -1531,39 +1555,63 @@
15311555
<key>import</key>
15321556
<dict>
15331557
<key>comment</key>
1534-
<string>Import statements
1558+
<string>Import statements used to correctly mark `from`, `import`, and `as`
15351559
</string>
15361560
<key>patterns</key>
15371561
<array>
15381562
<dict>
1539-
<key>match</key>
1540-
<string>(?x)
1541-
\s* \b(from) \s*(\.+)\s* (import\b)?
1542-
</string>
1543-
<key>captures</key>
1563+
<key>begin</key>
1564+
<string>\b(?&lt;!\.)(from)\b(?=.+import)</string>
1565+
<key>end</key>
1566+
<string>$|(?=import)</string>
1567+
<key>beginCaptures</key>
15441568
<dict>
15451569
<key>1</key>
15461570
<dict>
15471571
<key>name</key>
15481572
<string>keyword.control.import.python</string>
15491573
</dict>
1550-
<key>2</key>
1574+
</dict>
1575+
<key>patterns</key>
1576+
<array>
15511577
<dict>
15521578
<key>name</key>
15531579
<string>punctuation.separator.period.python</string>
1580+
<key>match</key>
1581+
<string>\.+</string>
15541582
</dict>
1555-
<key>3</key>
1583+
<dict>
1584+
<key>include</key>
1585+
<string>#expression</string>
1586+
</dict>
1587+
</array>
1588+
</dict>
1589+
<dict>
1590+
<key>begin</key>
1591+
<string>\b(?&lt;!\.)(import)\b</string>
1592+
<key>end</key>
1593+
<string>$</string>
1594+
<key>beginCaptures</key>
1595+
<dict>
1596+
<key>1</key>
15561597
<dict>
15571598
<key>name</key>
15581599
<string>keyword.control.import.python</string>
15591600
</dict>
15601601
</dict>
1561-
</dict>
1562-
<dict>
1563-
<key>name</key>
1564-
<string>keyword.control.import.python</string>
1565-
<key>match</key>
1566-
<string>\b(?&lt;!\.)import\b</string>
1602+
<key>patterns</key>
1603+
<array>
1604+
<dict>
1605+
<key>name</key>
1606+
<string>keyword.control.import.python</string>
1607+
<key>match</key>
1608+
<string>\b(?&lt;!\.)as\b</string>
1609+
</dict>
1610+
<dict>
1611+
<key>include</key>
1612+
<string>#expression</string>
1613+
</dict>
1614+
</array>
15671615
</dict>
15681616
</array>
15691617
</dict>
@@ -2836,13 +2884,13 @@ indirectly through syntactic constructs
28362884
<string>(?x)
28372885
\b(?:
28382886
(
2839-
and | as | assert | async | await | break | class | continue | def
2887+
and | assert | async | await | break | class | continue | def
28402888
| del | elif | else | except | finally | for | from | global
28412889
| if | in | is | (?&lt;=\.)lambda | lambda(?=\s*[\.=])
28422890
| nonlocal | not | or | pass | raise | return | try | while | with
28432891
| yield
28442892
) | (
2845-
import
2893+
as | import
28462894
)
28472895
)\b
28482896
</string>

grammars/src/MagicPython.syntax.yaml

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -359,11 +359,25 @@ repository:
359359
patterns:
360360
- name: storage.type.function.python
361361
match: \b((async\s+)?\s*def)\b
362+
- name: keyword.control.flow.python
363+
comment: |
364+
if `as` is eventually followed by `:` or line continuation
365+
it's probably control flow like:
366+
with foo as bar, \
367+
Foo as Bar:
368+
try:
369+
do_stuff()
370+
except Exception as e:
371+
pass
372+
match: \b(?<!\.)as\b(?=.*[:\\])
373+
- name: keyword.control.import.python
374+
comment: other legal use of `as` is in an import
375+
match: \b(?<!\.)as\b
362376
- name: keyword.control.flow.python
363377
match: |
364378
(?x)
365379
\b(?<!\.)(
366-
as | async | continue | del | assert | break | finally | for
380+
async | continue | del | assert | break | finally | for
367381
| from | elif | else | if | except | pass | raise
368382
| return | try | while | with
369383
)\b
@@ -842,17 +856,25 @@ repository:
842856

843857
import:
844858
comment: |
845-
Import statements
859+
Import statements used to correctly mark `from`, `import`, and `as`
846860
patterns:
847-
- match: |
848-
(?x)
849-
\s* \b(from) \s*(\.+)\s* (import\b)?
850-
captures:
861+
- begin: \b(?<!\.)(from)\b(?=.+import)
862+
end: $|(?=import)
863+
beginCaptures:
851864
'1': {name: keyword.control.import.python}
852-
'2': {name: punctuation.separator.period.python}
853-
'3': {name: keyword.control.import.python}
854-
- name: keyword.control.import.python
855-
match: \b(?<!\.)import\b
865+
patterns:
866+
- name: punctuation.separator.period.python
867+
match: \.+
868+
- include: '#expression'
869+
870+
- begin: \b(?<!\.)(import)\b
871+
end: $
872+
beginCaptures:
873+
'1': {name: keyword.control.import.python}
874+
patterns:
875+
- name: keyword.control.import.python
876+
match: \b(?<!\.)as\b
877+
- include: '#expression'
856878

857879
class-declaration:
858880
patterns:
@@ -1385,13 +1407,13 @@ repository:
13851407
(?x)
13861408
\b(?:
13871409
(
1388-
and | as | assert | async | await | break | class | continue | def
1410+
and | assert | async | await | break | class | continue | def
13891411
| del | elif | else | except | finally | for | from | global
13901412
| if | in | is | (?<=\.)lambda | lambda(?=\s*[\.=])
13911413
| nonlocal | not | or | pass | raise | return | try | while | with
13921414
| yield
13931415
) | (
1394-
import
1416+
as | import
13951417
)
13961418
)\b
13971419
captures:

0 commit comments

Comments
 (0)