Skip to content

Commit a49b5d0

Browse files
feat(editor): add Power Query (M) language support (#639)
- Add powerquery.tmLanguage.json grammar file - Register Power Query in languages array with proper scope - Add 'powerquery' to Language type definition
1 parent d542824 commit a49b5d0

File tree

3 files changed

+353
-1
lines changed

3 files changed

+353
-1
lines changed

src/renderer/components/editor/grammars/languages.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,12 @@ export const languages: LanguageOption[] = [
640640
grammar: () => import('./textmate/powershell.tmLanguage.json'),
641641
scopeName: 'source.powershell',
642642
},
643+
{
644+
name: 'Power Query',
645+
value: 'powerquery',
646+
grammar: () => import('./textmate/powerquery.tmLanguage.json'),
647+
scopeName: 'source.powerquery',
648+
},
643649
{
644650
name: 'Praat',
645651
value: 'praat',
@@ -992,7 +998,6 @@ export const oldLanguageMap: Record<any, Language> = {
992998
'objective-c': 'objectivec',
993999
'pascaligo': 'plain_text',
9941000
'postiats': 'plain_text',
995-
'powerquery': 'plain_text',
9961001
'pug': 'jade',
9971002
'redis': 'plain_text',
9981003
'sb': 'plain_text',
Lines changed: 346 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,346 @@
1+
{
2+
"name": "powerquery",
3+
"scopeName": "source.powerquery",
4+
"fileTypes": ["pq", "pqm"],
5+
"uuid": "41968B57-12E6-4AC5-92A4-A837010E8B0A",
6+
"patterns": [
7+
{
8+
"include": "#Noise"
9+
},
10+
{
11+
"include": "#LiteralExpression"
12+
},
13+
{
14+
"include": "#Keywords"
15+
},
16+
{
17+
"include": "#ImplicitVariable"
18+
},
19+
{
20+
"include": "#IntrinsicVariable"
21+
},
22+
{
23+
"include": "#Operators"
24+
},
25+
{
26+
"include": "#DotOperators"
27+
},
28+
{
29+
"include": "#TypeName"
30+
},
31+
{
32+
"include": "#RecordExpression"
33+
},
34+
{
35+
"include": "#Punctuation"
36+
},
37+
{
38+
"include": "#QuotedIdentifier"
39+
},
40+
{
41+
"include": "#Identifier"
42+
}
43+
],
44+
"repository": {
45+
"Keywords": {
46+
"match": "\\b(?:(and|or|not)|(if|then|else)|(try|catch|otherwise)|(as|each|in|is|let|meta|type|error)|(section|shared))\\b",
47+
"captures": {
48+
"1": {
49+
"name": "keyword.operator.word.logical.powerquery"
50+
},
51+
"2": {
52+
"name": "keyword.control.conditional.powerquery"
53+
},
54+
"3": {
55+
"name": "keyword.control.exception.powerquery"
56+
},
57+
"4": {
58+
"name": "keyword.other.powerquery"
59+
},
60+
"5": {
61+
"name": "keyword.powerquery"
62+
}
63+
}
64+
},
65+
"TypeName": {
66+
"match": "\\b(?:(optional|nullable)|(action|any|anynonnull|binary|date|datetime|datetimezone|duration|function|list|logical|none|null|number|record|table|text|time|type))\\b",
67+
"captures": {
68+
"1": {
69+
"name": "storage.modifier.powerquery"
70+
},
71+
"2": {
72+
"name": "storage.type.powerquery"
73+
}
74+
}
75+
},
76+
"LiteralExpression": {
77+
"patterns": [
78+
{
79+
"include": "#String"
80+
},
81+
{
82+
"include": "#NumericConstant"
83+
},
84+
{
85+
"include": "#LogicalConstant"
86+
},
87+
{
88+
"include": "#NullConstant"
89+
},
90+
{
91+
"include": "#FloatNumber"
92+
},
93+
{
94+
"include": "#DecimalNumber"
95+
},
96+
{
97+
"include": "#HexNumber"
98+
},
99+
{
100+
"include": "#IntNumber"
101+
}
102+
]
103+
},
104+
"Noise": {
105+
"patterns": [
106+
{
107+
"include": "#BlockComment"
108+
},
109+
{
110+
"include": "#LineComment"
111+
},
112+
{
113+
"include": "#Whitespace"
114+
}
115+
]
116+
},
117+
"Whitespace": {
118+
"match": "\\s+"
119+
},
120+
"BlockComment": {
121+
"begin": "/\\*",
122+
"end": "\\*/",
123+
"name": "comment.block.powerquery"
124+
},
125+
"LineComment": {
126+
"match": "//.*",
127+
"name": "comment.line.double-slash.powerquery"
128+
},
129+
"String": {
130+
"begin": "\"",
131+
"beginCaptures": {
132+
"0": {
133+
"name": "punctuation.definition.string.begin.powerquery"
134+
}
135+
},
136+
"end": "\"(?!\")",
137+
"endCaptures": {
138+
"0": {
139+
"name": "punctuation.definition.string.end.powerquery"
140+
}
141+
},
142+
"patterns": [
143+
{
144+
"match": "\"\"",
145+
"name": "constant.character.escape.quote.powerquery"
146+
},
147+
{
148+
"include": "#EscapeSequence"
149+
}
150+
],
151+
"name": "string.quoted.double.powerquery"
152+
},
153+
"QuotedIdentifier": {
154+
"begin": "#\"",
155+
"beginCaptures": {
156+
"0": {
157+
"name": "punctuation.definition.quotedidentifier.begin.powerquery"
158+
}
159+
},
160+
"end": "\"(?!\")",
161+
"endCaptures": {
162+
"0": {
163+
"name": "punctuation.definition.quotedidentifier.end.powerquery"
164+
}
165+
},
166+
"patterns": [
167+
{
168+
"match": "\"\"",
169+
"name": "constant.character.escape.quote.powerquery"
170+
},
171+
{
172+
"include": "#EscapeSequence"
173+
}
174+
],
175+
"name": "entity.name.powerquery"
176+
},
177+
"EscapeSequence": {
178+
"begin": "#\\(",
179+
"beginCaptures": {
180+
"0": {
181+
"name": "punctuation.definition.escapesequence.begin.powerquery"
182+
}
183+
},
184+
"end": "\\)",
185+
"endCaptures": {
186+
"0": {
187+
"name": "punctuation.definition.escapesequence.end.powerquery"
188+
}
189+
},
190+
"patterns": [
191+
{
192+
"match": "(#|\\h{4}|\\h{8}|cr|lf|tab)(?:,(#|\\h{4}|\\h{8}|cr|lf|tab))*"
193+
},
194+
{
195+
"match": "[^\\)]",
196+
"name": "invalid.illegal.escapesequence.powerquery"
197+
}
198+
],
199+
"name": "constant.character.escapesequence.powerquery"
200+
},
201+
"LogicalConstant": {
202+
"match": "\\b(true|false)\\b",
203+
"name": "constant.language.logical.powerquery"
204+
},
205+
"NullConstant": {
206+
"match": "\\b(null)\\b",
207+
"name": "constant.language.null.powerquery"
208+
},
209+
"NumericConstant": {
210+
"match": "(?<![\\d\\w])(#infinity|#nan)\\b",
211+
"captures": {
212+
"1": {
213+
"name": "constant.language.numeric.float.powerquery"
214+
}
215+
}
216+
},
217+
"HexNumber": {
218+
"match": "0(x|X)\\h+",
219+
"name": "constant.numeric.integer.hexadecimal.powerquery"
220+
},
221+
"IntNumber": {
222+
"match": "\\b(\\d+)\\b",
223+
"captures": {
224+
"1": {
225+
"name": "constant.numeric.integer.powerquery"
226+
}
227+
}
228+
},
229+
"DecimalNumber": {
230+
"match": "(?<![\\d\\w])(\\d*\\.\\d+)\\b",
231+
"name": "constant.numeric.decimal.powerquery"
232+
},
233+
"FloatNumber": {
234+
"match": "(\\d*\\.)?\\d+(e|E)(\\+|-)?\\d+",
235+
"name": "constant.numeric.float.powerquery"
236+
},
237+
"InclusiveIdentifier": {
238+
"match": "@",
239+
"captures": {
240+
"0": {
241+
"name": "inclusiveidentifier.powerquery"
242+
}
243+
}
244+
},
245+
"Identifier": {
246+
"match": "(?x:(?<![\\._\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}\\p{Nd}\\p{Pc}\\p{Mn}\\p{Mc}\\p{Cf}])(@?)([_\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}][_\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}\\p{Nd}\\p{Pc}\\p{Mn}\\p{Mc}\\p{Cf}]*(?:\\.[_\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}][_\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}\\p{Nd}\\p{Pc}\\p{Mn}\\p{Mc}\\p{Cf}])*)\\b)",
247+
"captures": {
248+
"1": {
249+
"name": "keyword.operator.inclusiveidentifier.powerquery"
250+
},
251+
"2": {
252+
"name": "entity.name.powerquery"
253+
}
254+
}
255+
},
256+
"Operators": {
257+
"match": "(=>)|(=)|(<>|<|>|<=|>=)|(&)|(\\+|-|\\*|\\/)|(!)|(\\?)",
258+
"captures": {
259+
"1": {
260+
"name": "keyword.operator.function.powerquery"
261+
},
262+
"2": {
263+
"name": "keyword.operator.assignment-or-comparison.powerquery"
264+
},
265+
"3": {
266+
"name": "keyword.operator.comparison.powerquery"
267+
},
268+
"4": {
269+
"name": "keyword.operator.combination.powerquery"
270+
},
271+
"5": {
272+
"name": "keyword.operator.arithmetic.powerquery"
273+
},
274+
"6": {
275+
"name": "keyword.operator.sectionaccess.powerquery"
276+
},
277+
"7": {
278+
"name": "keyword.operator.optional.powerquery"
279+
}
280+
}
281+
},
282+
"DotOperators": {
283+
"match": "(?<!\\.)(?:(\\.\\.\\.)|(\\.\\.))(?!\\.)",
284+
"captures": {
285+
"1": {
286+
"name": "keyword.operator.ellipsis.powerquery"
287+
},
288+
"2": {
289+
"name": "keyword.operator.list.powerquery"
290+
}
291+
}
292+
},
293+
"RecordExpression": {
294+
"begin": "\\[",
295+
"beginCaptures": {
296+
"0": {
297+
"name": "punctuation.section.brackets.begin.powerquery"
298+
}
299+
},
300+
"end": "\\]",
301+
"endCaptures": {
302+
"0": {
303+
"name": "punctuation.section.brackets.end.powerquery"
304+
}
305+
},
306+
"patterns": [
307+
{
308+
"include": "$self"
309+
}
310+
],
311+
"contentName": "meta.recordexpression.powerquery"
312+
},
313+
"Punctuation": {
314+
"match": "(,)|(\\()|(\\))|({)|(})",
315+
"captures": {
316+
"1": {
317+
"name": "punctuation.separator.powerquery"
318+
},
319+
"2": {
320+
"name": "punctuation.section.parens.begin.powerquery"
321+
},
322+
"3": {
323+
"name": "punctuation.section.parens.end.powerquery"
324+
},
325+
"4": {
326+
"name": "punctuation.section.braces.begin.powerquery"
327+
},
328+
"5": {
329+
"name": "punctuation.section.braces.end.powerquery"
330+
}
331+
}
332+
},
333+
"ImplicitVariable": {
334+
"match": "\\b_\\b",
335+
"name": "keyword.operator.implicitvariable.powerquery"
336+
},
337+
"IntrinsicVariable": {
338+
"match": "(?<![\\d\\w])(#sections|#shared)\\b",
339+
"captures": {
340+
"1": {
341+
"name": "constant.language.intrinsicvariable.powerquery"
342+
}
343+
}
344+
}
345+
}
346+
}

src/renderer/components/editor/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ export type Language =
120120
| 'pig'
121121
| 'plain_text'
122122
| 'powershell'
123+
| 'powerquery'
123124
| 'praat'
124125
| 'prisma'
125126
| 'prolog'

0 commit comments

Comments
 (0)