Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add match and case syntax Python 3.10 #237

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 17 additions & 0 deletions grammars/MagicPython.cson
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,23 @@ repository:

'''
}
{
name: "keyword.control.flow.python"
comment: '''
`match` and `case` are only soft keywords. Match if
followed by `:` or anything that allows for line continuation.

'''
match: '''
(?x)
(?:^\\s*)\\b(
match | case
)\\b(?:
(?=.*[:\\\\]) | (?=\\s*[\\(\\[\\{])
)

'''
}
{
name: "storage.modifier.declaration.python"
match: '''
Expand Down
16 changes: 16 additions & 0 deletions grammars/MagicPython.tmLanguage
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,22 @@ it's probably control flow like:
| from | elif | else | if | except | pass | raise
| return | try | while | with
)\b
</string>
</dict>
<dict>
<key>name</key>
<string>keyword.control.flow.python</string>
<key>comment</key>
<string>`match` and `case` are only soft keywords. Match if
followed by `:` or anything that allows for line continuation.
</string>
<key>match</key>
<string>(?x)
(?:^\s*)\b(
match | case
)\b(?:
(?=.*[:\\]) | (?=\s*[\(\[\{])
)
</string>
</dict>
<dict>
Expand Down
11 changes: 11 additions & 0 deletions grammars/src/MagicPython.syntax.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,17 @@ repository:
| from | elif | else | if | except | pass | raise
| return | try | while | with
)\b
- name: keyword.control.flow.python
comment: |
`match` and `case` are only soft keywords. Match if
followed by `:` or anything that allows for line continuation.
match: |
(?x)
(?:^\s*)\b(
match | case
)\b(?:
(?=.*[:\\]) | (?=\s*[\(\[\{])
)
- name: storage.modifier.declaration.python
match: |
(?x)
Expand Down
208 changes: 208 additions & 0 deletions test/atom-spec/python-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13020,6 +13020,214 @@ describe("Grammar Tests", function() {
expect(tokens[8][11].scopes).toEqual(["source.python","constant.language.python"]);
});

it("test/statements/match1.py",
function() {
tokens = grammar.tokenizeLines("match status:\n case 100:\n pass\n case \\\n 200:\n pass\n case (\n 300\n ):\n pass\n case [\n 400\n ]:\n pass\n case {\n 500: \"\",\n }:\n pass\n case Point(x, y) as p:\n pass\n case 600 | 700:\n pass\n case _:")
expect(tokens[0][0].value).toBe("match");
expect(tokens[0][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[0][1].value).toBe(" ");
expect(tokens[0][1].scopes).toEqual(["source.python"]);
expect(tokens[0][2].value).toBe("status");
expect(tokens[0][2].scopes).toEqual(["source.python"]);
expect(tokens[0][3].value).toBe(":");
expect(tokens[0][3].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
expect(tokens[1][0].value).toBe(" case");
expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[1][1].value).toBe(" ");
expect(tokens[1][1].scopes).toEqual(["source.python"]);
expect(tokens[1][2].value).toBe("100");
expect(tokens[1][2].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
expect(tokens[1][3].value).toBe(":");
expect(tokens[1][3].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
expect(tokens[2][0].value).toBe(" ");
expect(tokens[2][0].scopes).toEqual(["source.python"]);
expect(tokens[2][1].value).toBe("pass");
expect(tokens[2][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[3][0].value).toBe(" case");
expect(tokens[3][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[3][1].value).toBe(" ");
expect(tokens[3][1].scopes).toEqual(["source.python"]);
expect(tokens[3][2].value).toBe("\\");
expect(tokens[3][2].scopes).toEqual(["source.python","punctuation.separator.continuation.line.python"]);
expect(tokens[3][3].value).toBe("");
expect(tokens[3][3].scopes).toEqual(["source.python"]);
expect(tokens[4][0].value).toBe(" ");
expect(tokens[4][0].scopes).toEqual(["source.python"]);
expect(tokens[4][1].value).toBe("200");
expect(tokens[4][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
expect(tokens[4][2].value).toBe(":");
expect(tokens[4][2].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
expect(tokens[5][0].value).toBe(" ");
expect(tokens[5][0].scopes).toEqual(["source.python"]);
expect(tokens[5][1].value).toBe("pass");
expect(tokens[5][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[6][0].value).toBe(" case");
expect(tokens[6][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[6][1].value).toBe(" ");
expect(tokens[6][1].scopes).toEqual(["source.python"]);
expect(tokens[6][2].value).toBe("(");
expect(tokens[6][2].scopes).toEqual(["source.python","punctuation.parenthesis.begin.python"]);
expect(tokens[7][0].value).toBe(" ");
expect(tokens[7][0].scopes).toEqual(["source.python"]);
expect(tokens[7][1].value).toBe("300");
expect(tokens[7][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
expect(tokens[8][0].value).toBe(" ");
expect(tokens[8][0].scopes).toEqual(["source.python"]);
expect(tokens[8][1].value).toBe(")");
expect(tokens[8][1].scopes).toEqual(["source.python","punctuation.parenthesis.end.python"]);
expect(tokens[8][2].value).toBe(":");
expect(tokens[8][2].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
expect(tokens[9][0].value).toBe(" ");
expect(tokens[9][0].scopes).toEqual(["source.python"]);
expect(tokens[9][1].value).toBe("pass");
expect(tokens[9][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[10][0].value).toBe(" case");
expect(tokens[10][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[10][1].value).toBe(" ");
expect(tokens[10][1].scopes).toEqual(["source.python"]);
expect(tokens[10][2].value).toBe("[");
expect(tokens[10][2].scopes).toEqual(["source.python","punctuation.definition.list.begin.python"]);
expect(tokens[11][0].value).toBe(" ");
expect(tokens[11][0].scopes).toEqual(["source.python"]);
expect(tokens[11][1].value).toBe("400");
expect(tokens[11][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
expect(tokens[12][0].value).toBe(" ");
expect(tokens[12][0].scopes).toEqual(["source.python"]);
expect(tokens[12][1].value).toBe("]");
expect(tokens[12][1].scopes).toEqual(["source.python","punctuation.definition.list.end.python"]);
expect(tokens[12][2].value).toBe(":");
expect(tokens[12][2].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
expect(tokens[13][0].value).toBe(" ");
expect(tokens[13][0].scopes).toEqual(["source.python"]);
expect(tokens[13][1].value).toBe("pass");
expect(tokens[13][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[14][0].value).toBe(" case");
expect(tokens[14][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[14][1].value).toBe(" ");
expect(tokens[14][1].scopes).toEqual(["source.python"]);
expect(tokens[14][2].value).toBe("{");
expect(tokens[14][2].scopes).toEqual(["source.python","punctuation.definition.dict.begin.python"]);
expect(tokens[15][0].value).toBe(" ");
expect(tokens[15][0].scopes).toEqual(["source.python"]);
expect(tokens[15][1].value).toBe("500");
expect(tokens[15][1].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
expect(tokens[15][2].value).toBe(":");
expect(tokens[15][2].scopes).toEqual(["source.python","punctuation.separator.dict.python"]);
expect(tokens[15][3].value).toBe(" ");
expect(tokens[15][3].scopes).toEqual(["source.python"]);
expect(tokens[15][4].value).toBe("\"");
expect(tokens[15][4].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.begin.python"]);
expect(tokens[15][5].value).toBe("\"");
expect(tokens[15][5].scopes).toEqual(["source.python","string.quoted.single.python","punctuation.definition.string.end.python"]);
expect(tokens[15][6].value).toBe(",");
expect(tokens[15][6].scopes).toEqual(["source.python","punctuation.separator.element.python"]);
expect(tokens[16][0].value).toBe(" ");
expect(tokens[16][0].scopes).toEqual(["source.python"]);
expect(tokens[16][1].value).toBe("}");
expect(tokens[16][1].scopes).toEqual(["source.python","punctuation.definition.dict.end.python"]);
expect(tokens[16][2].value).toBe(":");
expect(tokens[16][2].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
expect(tokens[17][0].value).toBe(" ");
expect(tokens[17][0].scopes).toEqual(["source.python"]);
expect(tokens[17][1].value).toBe("pass");
expect(tokens[17][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[18][0].value).toBe(" case");
expect(tokens[18][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[18][1].value).toBe(" ");
expect(tokens[18][1].scopes).toEqual(["source.python"]);
expect(tokens[18][2].value).toBe("Point");
expect(tokens[18][2].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.generic.python"]);
expect(tokens[18][3].value).toBe("(");
expect(tokens[18][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.begin.python"]);
expect(tokens[18][4].value).toBe("x");
expect(tokens[18][4].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
expect(tokens[18][5].value).toBe(",");
expect(tokens[18][5].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
expect(tokens[18][6].value).toBe(" ");
expect(tokens[18][6].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
expect(tokens[18][7].value).toBe("y");
expect(tokens[18][7].scopes).toEqual(["source.python","meta.function-call.python","meta.function-call.arguments.python"]);
expect(tokens[18][8].value).toBe(")");
expect(tokens[18][8].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
expect(tokens[18][9].value).toBe(" ");
expect(tokens[18][9].scopes).toEqual(["source.python"]);
expect(tokens[18][10].value).toBe("as");
expect(tokens[18][10].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[18][11].value).toBe(" ");
expect(tokens[18][11].scopes).toEqual(["source.python"]);
expect(tokens[18][12].value).toBe("p");
expect(tokens[18][12].scopes).toEqual(["source.python"]);
expect(tokens[18][13].value).toBe(":");
expect(tokens[18][13].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
expect(tokens[19][0].value).toBe(" ");
expect(tokens[19][0].scopes).toEqual(["source.python"]);
expect(tokens[19][1].value).toBe("pass");
expect(tokens[19][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[20][0].value).toBe(" case");
expect(tokens[20][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[20][1].value).toBe(" ");
expect(tokens[20][1].scopes).toEqual(["source.python"]);
expect(tokens[20][2].value).toBe("600");
expect(tokens[20][2].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
expect(tokens[20][3].value).toBe(" ");
expect(tokens[20][3].scopes).toEqual(["source.python"]);
expect(tokens[20][4].value).toBe("|");
expect(tokens[20][4].scopes).toEqual(["source.python","keyword.operator.bitwise.python"]);
expect(tokens[20][5].value).toBe(" ");
expect(tokens[20][5].scopes).toEqual(["source.python"]);
expect(tokens[20][6].value).toBe("700");
expect(tokens[20][6].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
expect(tokens[20][7].value).toBe(":");
expect(tokens[20][7].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
expect(tokens[21][0].value).toBe(" ");
expect(tokens[21][0].scopes).toEqual(["source.python"]);
expect(tokens[21][1].value).toBe("pass");
expect(tokens[21][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[22][0].value).toBe(" case");
expect(tokens[22][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[22][1].value).toBe(" ");
expect(tokens[22][1].scopes).toEqual(["source.python"]);
expect(tokens[22][2].value).toBe("_");
expect(tokens[22][2].scopes).toEqual(["source.python"]);
expect(tokens[22][3].value).toBe(":");
expect(tokens[22][3].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
});

it("test/statements/match2.py",
function() {
tokens = grammar.tokenizeLines("match = 1\nif match == 2:\n pass")
expect(tokens[0][0].value).toBe("match");
expect(tokens[0][0].scopes).toEqual(["source.python"]);
expect(tokens[0][1].value).toBe(" ");
expect(tokens[0][1].scopes).toEqual(["source.python"]);
expect(tokens[0][2].value).toBe("=");
expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
expect(tokens[0][3].value).toBe(" ");
expect(tokens[0][3].scopes).toEqual(["source.python"]);
expect(tokens[0][4].value).toBe("1");
expect(tokens[0][4].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
expect(tokens[1][0].value).toBe("if");
expect(tokens[1][0].scopes).toEqual(["source.python","keyword.control.flow.python"]);
expect(tokens[1][1].value).toBe(" ");
expect(tokens[1][1].scopes).toEqual(["source.python"]);
expect(tokens[1][2].value).toBe("match");
expect(tokens[1][2].scopes).toEqual(["source.python"]);
expect(tokens[1][3].value).toBe(" ");
expect(tokens[1][3].scopes).toEqual(["source.python"]);
expect(tokens[1][4].value).toBe("==");
expect(tokens[1][4].scopes).toEqual(["source.python","keyword.operator.comparison.python"]);
expect(tokens[1][5].value).toBe(" ");
expect(tokens[1][5].scopes).toEqual(["source.python"]);
expect(tokens[1][6].value).toBe("2");
expect(tokens[1][6].scopes).toEqual(["source.python","constant.numeric.dec.python"]);
expect(tokens[1][7].value).toBe(":");
expect(tokens[1][7].scopes).toEqual(["source.python","punctuation.separator.colon.python"]);
expect(tokens[2][0].value).toBe(" ");
expect(tokens[2][0].scopes).toEqual(["source.python"]);
expect(tokens[2][1].value).toBe("pass");
expect(tokens[2][1].scopes).toEqual(["source.python","keyword.control.flow.python"]);
});

it("test/statements/nonlocal1.py",
function() {
tokens = grammar.tokenizeLines("nonlocal a, b, c")
Expand Down