Skip to content

Commit a0824b9

Browse files
ymtszwkeathley
authored andcommitted
Capture double/single-quoted atoms used as keys in keyword lists or maps (#93)
* Add captures for quoted atoms as keyword list keys. Note: in this file Elixir atoms are refered to as 'symbols' as in Ruby or other languages. This might be better changed to 'atoms', but for now I used 'symbols' in my hunks for consistency. * Test tokenizations of atoms-as-keys * Only matches for atoms without nested quotes; Scrap the initial idea (matches for any letters inside quotes, then warn for unescaped quotes) since it does not work properly when there are multiple quoted-atom-key in a line.
1 parent 861d991 commit a0824b9

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

grammars/elixir.cson

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,36 @@
13571357
}
13581358
]
13591359
}
1360+
{
1361+
'comment': """
1362+
symbols with single-quoted string, used as keys in Keyword lists.
1363+
1364+
In this case, `:` is suffixed to single-quoted string.
1365+
Leading letter `'` is exactly the same as in ordinary single-quoted string,
1366+
so this pattern is slightly difficult to capture.
1367+
1368+
This pattern only matches symbols when they do not have line breaks OR
1369+
(escaped or unescaped) single-quotes inside outermost single-quotes.
1370+
Thus, it will not match for patterns like `'foo\'bar':`.
1371+
"""
1372+
'match': '(\')([^\']*)(\':)(?!:)'
1373+
'name': 'constant.other.symbol.single-quoted.elixir'
1374+
'captures': {
1375+
'1':
1376+
'name': 'punctuation.definition.constant.elixir'
1377+
'2':
1378+
'patterns': [
1379+
{
1380+
'include': '#interpolated_elixir'
1381+
}
1382+
{
1383+
'include': '#escaped_char'
1384+
}
1385+
]
1386+
'3':
1387+
'name': 'punctuation.definition.constant.elixir'
1388+
}
1389+
}
13601390
{
13611391
'begin': ':"'
13621392
'captures':
@@ -1433,6 +1463,26 @@
14331463
}
14341464
]
14351465
}
1466+
{
1467+
'comment': 'symbols defined by double-quoted string, used as keys in Keyword lists.'
1468+
'match': '(")([^"]*)(":)(?!:)'
1469+
'name': 'constant.other.symbol.double-quoted.elixir'
1470+
'captures': {
1471+
'1':
1472+
'name': 'punctuation.definition.constant.elixir'
1473+
'2':
1474+
'patterns': [
1475+
{
1476+
'include': '#interpolated_elixir'
1477+
}
1478+
{
1479+
'include': '#escaped_char'
1480+
}
1481+
]
1482+
'3':
1483+
'name': 'punctuation.definition.constant.elixir'
1484+
}
1485+
}
14361486
{
14371487
'begin': '"'
14381488
'beginCaptures':

spec/elixir-spec.coffee

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,30 @@ describe "Elixir grammar", ->
152152
expect(tokens[0]).toEqual value: 'case', scopes: ['source.elixir', 'constant.other.symbol.elixir']
153153
expect(tokens[1]).toEqual value: ':', scopes: ['source.elixir', 'constant.other.symbol.elixir', 'punctuation.definition.constant.elixir']
154154

155+
{tokens} = grammar.tokenizeLine(':"symbol"')
156+
expect(tokens[0]).toEqual value: ':"', scopes: ['source.elixir', 'constant.other.symbol.double-quoted.elixir', 'punctuation.definition.constant.elixir']
157+
expect(tokens[1]).toEqual value: 'symbol', scopes: ['source.elixir', 'constant.other.symbol.double-quoted.elixir']
158+
expect(tokens[2]).toEqual value: '"', scopes: ['source.elixir', 'constant.other.symbol.double-quoted.elixir', 'punctuation.definition.constant.elixir']
159+
160+
{tokens} = grammar.tokenizeLine('"symbol as key":')
161+
expect(tokens[0]).toEqual value: '"', scopes: ['source.elixir', 'constant.other.symbol.double-quoted.elixir', 'punctuation.definition.constant.elixir']
162+
expect(tokens[1]).toEqual value: 'symbol as key', scopes: ['source.elixir', 'constant.other.symbol.double-quoted.elixir']
163+
expect(tokens[2]).toEqual value: '":', scopes: ['source.elixir', 'constant.other.symbol.double-quoted.elixir', 'punctuation.definition.constant.elixir']
164+
165+
{tokens} = grammar.tokenizeLine('"symbol as key with unescaped " inside":')
166+
expect(tokens[0]).toEqual value: '"', scopes: ['source.elixir', 'string.quoted.double.elixir', 'punctuation.definition.string.begin.elixir']
167+
expect(tokens[1]).toEqual value: 'symbol as key with unescaped ', scopes: ['source.elixir', 'string.quoted.double.elixir']
168+
expect(tokens[2]).toEqual value: '"', scopes: ['source.elixir', 'string.quoted.double.elixir', 'punctuation.definition.string.end.elixir']
169+
expect(tokens[3]).toEqual value: ' inside', scopes: ['source.elixir']
170+
expect(tokens[4]).toEqual value: '"', scopes: ['source.elixir', 'string.quoted.double.elixir', 'punctuation.definition.string.begin.elixir']
171+
expect(tokens[5]).toEqual value: ':', scopes: ['source.elixir', 'string.quoted.double.elixir']
172+
173+
{tokens} = grammar.tokenizeLine('"symbol as key with escaped \\" inside":')
174+
expect(tokens[2]).toEqual value: '\\"', scopes: ['source.elixir', 'string.quoted.double.elixir', 'constant.character.escape.elixir']
175+
expect(tokens[3]).toEqual value: ' inside', scopes: ['source.elixir', 'string.quoted.double.elixir']
176+
expect(tokens[4]).toEqual value: '"', scopes: ['source.elixir', 'string.quoted.double.elixir', 'punctuation.definition.string.end.elixir']
177+
expect(tokens[5]).toEqual value: ':', scopes: ['source.elixir', 'punctuation.separator.other.elixir']
178+
155179
it "tokenizes comments", ->
156180
{tokens} = grammar.tokenizeLine("# TODO: stuff")
157181
expect(tokens[0]).toEqual value: '#', scopes: ['source.elixir', 'comment.line.number-sign.elixir', 'punctuation.definition.comment.elixir']

0 commit comments

Comments
 (0)