Skip to content

Commit 1a7dc0b

Browse files
committed
Recognize first statement as a command
1 parent d56121f commit 1a7dc0b

File tree

4 files changed

+758
-273
lines changed

4 files changed

+758
-273
lines changed

PowerShell.sublime-syntax

Lines changed: 112 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,23 @@ contexts:
4646
- include: else-pop
4747

4848
statements:
49-
- include: redirection
5049
- include: classes
51-
- include: expressions
5250
- include: functions
5351
- include: workflows
5452
- include: desired-state-configurations
5553

56-
- match: \B\.(?= )
57-
scope: support.function.source.powershell
58-
5954
- include: exceptions
6055
- include: loops
6156
- include: flow
6257
- include: conditionals
6358

59+
- match: \B\.(?= )
60+
scope: support.function.source.powershell
61+
- match: \&
62+
scope: keyword.operator.call.powershell
63+
64+
- include: expressions
65+
6466
expressions:
6567
# Meta
6668
- include: labels
@@ -80,28 +82,43 @@ contexts:
8082
- include: hashtables
8183
- include: arrays
8284

85+
- include: data-blocks
86+
- include: script-blocks
87+
- include: groups
88+
- include: subexpressions
89+
90+
- include: future-reserved-words
91+
92+
- include: operators
8393
- include: commands
8494

95+
expressions-without-commands:
96+
# Meta
97+
- include: labels
98+
- include: regions
99+
- include: requires-directives
100+
101+
- include: escape-sequences
102+
- include: literal-after
103+
104+
# Normal code
105+
- include: types
106+
- include: strings
107+
- include: numbers
108+
- include: constants
109+
- include: variables
110+
111+
- include: hashtables
112+
- include: arrays
113+
85114
- include: data-blocks
86115
- include: script-blocks
87116
- include: groups
88117
- include: subexpressions
89118

90-
# Consume a string with a trailing dot to prevent members with
91-
# particular names from being recognized as keywords.
92-
- match: \b[\w-]+(?=\.)
93-
scope: variable.other.object.powershell
94-
push: members
95-
96-
# "Reserved for future use"
97-
# https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_reserved_words
98-
- match: \b(?i:define|from){{kebab_break}}
99-
scope: keyword.control.powershell
100-
- match: \b(?i:var){{kebab_break}}
101-
scope: keyword.declaration.variable.powershell
119+
- include: future-reserved-words
102120

103121
- include: operators
104-
- include: parameters
105122

106123
literal-after:
107124
- match: \B--%\B
@@ -111,6 +128,13 @@ contexts:
111128
- meta_content_scope: string.unquoted.powershell
112129
- include: pop-before-eol
113130

131+
future-reserved-words:
132+
# https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_reserved_words
133+
- match: \b(?i:define|from){{kebab_break}}
134+
scope: keyword.control.powershell
135+
- match: \b(?i:var){{kebab_break}}
136+
scope: keyword.declaration.variable.powershell
137+
114138
###[ EXCEPTIONS ]##############################################################
115139

116140
exceptions:
@@ -158,6 +182,7 @@ contexts:
158182
scope: keyword.control.conditional.else.powershell
159183
- match: \b(?i:switch){{kebab_break}}
160184
scope: keyword.control.conditional.switch.powershell
185+
push: in-command
161186
- match: \b(?i:default){{kebab_break}}
162187
scope: keyword.control.conditional.default.powershell
163188
- match: \b(?i:where(?!-object)){{kebab_break}}
@@ -186,7 +211,7 @@ contexts:
186211
captures:
187212
1: keyword.other.array.begin.powershell
188213
2: punctuation.section.group.begin.powershell
189-
push: inside-array
214+
push: [members, inside-array]
190215

191216
inside-array:
192217
- meta_scope: meta.group.array-expression.powershell
@@ -200,7 +225,7 @@ contexts:
200225
captures:
201226
1: keyword.other.hashtable.begin.powershell
202227
2: punctuation.section.braces.begin.powershell
203-
push: inside-hashtable
228+
push: [members, inside-hashtable]
204229

205230
inside-hashtable:
206231
- meta_scope: meta.hashtable.powershell
@@ -244,13 +269,14 @@ contexts:
244269
captures:
245270
1: keyword.control.loop.for.powershell
246271
2: punctuation.section.braces.begin.powershell
247-
push: inside-script-block
272+
push: [members, inside-script-block]
248273

249274
inside-script-block:
250275
- meta_scope: meta.block.powershell
251276
- match: \}
252277
scope: punctuation.section.braces.end.powershell
253278
pop: 1
279+
- include: param-block
254280
- include: statements
255281

256282
###[ COMMANDS ]################################################################
@@ -259,6 +285,7 @@ contexts:
259285
- include: commands-verb-noun
260286
- include: commands-reserved
261287
- include: script-invocation
288+
- include: command-freeform
262289

263290
commands-verb-noun:
264291
# The "Verb-Noun" pattern
@@ -270,17 +297,57 @@ contexts:
270297
(?:\.(?i:exe|cmd|bat|ps1))?\b # More path stuff
271298
)
272299
scope: meta.function-call.powershell support.function.powershell
300+
push: in-command
273301
274302
commands-reserved:
275303
# Builtin cmdlets with reserved verbs
276304
- match: \b(?i:(?:ForEach|Where|Sort|Tee)-Object)\b
277305
scope: meta.function-call.powershell support.function.powershell
306+
push: in-command
278307

279308
script-invocation:
280309
- match: \b(?i:[a-z]:)?[\w.\\/-]+\.(?i:exe|com|cmd|bat|ps1)\b
281-
scope: variable.function.powershell
310+
scope: meta.function-call.powershell variable.function.powershell
311+
push: in-command
312+
313+
command-freeform:
314+
- match: '{{identifier_function}}'
315+
scope: meta.function-call.powershell variable.function.powershell
316+
push: in-command
317+
318+
in-command:
319+
# - meta_scope: region.pinkish
320+
- include: line-continuations
321+
- include: pop-eol
322+
- match: (?=[)}])
323+
pop: 1
324+
- match: ';'
325+
scope: punctuation.terminator.statement.powershell
326+
pop: 1
327+
- match: (\|)\s*\n
328+
captures:
329+
1: keyword.operator.logical.pipe.powershell
330+
push:
331+
- match: ^
332+
pop: 2
333+
- match: \|
334+
scope: keyword.operator.logical.pipe.powershell
335+
pop: 1
336+
- include: redirection
337+
- include: cli-parameters
338+
- include: expressions-without-commands
339+
- match: (?=\S)
340+
push:
341+
- meta_include_prototype: false
342+
- meta_scope: string.unquoted.powershell
343+
- match: (?=[\s#|>;,]|$)
344+
pop: 1
345+
- match: '[\\/:.]'
346+
scope: punctuation.separator.powershell
347+
- include: escape-sequences
348+
282349

283-
parameters:
350+
cli-parameters:
284351
# Flags/Options/Parameters
285352
- match: \B(--?|[/+])\p{L}(?:[\w-]*\w)?
286353
scope: variable.parameter.option.powershell
@@ -426,9 +493,7 @@ contexts:
426493
scope: punctuation.section.block.end.powershell
427494
pop: 2
428495

429-
- match: \b(?i:(?:Dynamic)?Param){{kebab_break}}
430-
scope: keyword.declaration.parameter.powershell # This scope is not standard
431-
push: expect-param-context
496+
- include: param-block
432497

433498
- match: \b(?i:Begin|Process|End|Clean){{kebab_break}}
434499
scope: keyword.context.block.powershell
@@ -438,6 +503,11 @@ contexts:
438503
- include: workflow-execution-contexts
439504
- include: statements
440505

506+
param-block:
507+
- match: \b(?i:(?:Dynamic)?Param){{kebab_break}}
508+
scope: keyword.declaration.parameter.powershell # This scope is not standard
509+
push: expect-param-context
510+
441511
expect-function-context:
442512
- meta_scope: meta.block.powershell
443513
- match: \{
@@ -647,9 +717,9 @@ contexts:
647717
members:
648718
- match: (?=\.\.)
649719
pop: 1
650-
- match: \?\.(?={{identifier_simple}})
720+
- match: \?\.(?=\$?{{identifier_simple}})
651721
scope: punctuation.accessor.null-coalescing.powershell
652-
- match: \??\.(?={{identifier_simple}})
722+
- match: \??\.(?=\$?{{identifier_simple}})
653723
scope: punctuation.accessor.dot.powershell
654724
- match: ::(?={{identifier_simple}})
655725
scope: punctuation.accessor.double-colon.powershell
@@ -785,10 +855,7 @@ contexts:
785855
scope: keyword.operator.ternary.powershell
786856
- match: ;
787857
scope: punctuation.terminator.statement.powershell
788-
- match: \`(?=\n|$)
789-
scope: punctuation.separator.continuation.line.powershell
790858
- include: comma-separators
791-
# TODO: Distinguish call operator from background operator
792859
- match: '&'
793860
scope: keyword.operator.background.powershell
794861
- match: \.\.(?=\-?\d|\(|\$)
@@ -1121,6 +1188,19 @@ contexts:
11211188

11221189
###[ COMPONENTS ]##############################################################
11231190

1191+
line-continuations:
1192+
- match: (`)\n
1193+
captures:
1194+
1: punctuation.separator.continuation.line.powershell
1195+
push: line-continuation-body
1196+
- match: '`(\s+)\n'
1197+
captures:
1198+
1: invalid.illegal.unexpected-whitespace.powershell
1199+
1200+
line-continuation-body:
1201+
- match: ^
1202+
pop: 1
1203+
11241204
comma-separators:
11251205
- match: ','
11261206
scope: punctuation.separator.sequence.powershell
@@ -1132,7 +1212,7 @@ contexts:
11321212
scope: constant.character.escape.powershell
11331213

11341214
pop-eol:
1135-
- match: $
1215+
- match: $\n?
11361216
pop: 1
11371217

11381218
pop-before-eol:

Tests/syntax_test_Class.ps1

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,15 @@ class BookList {
347347
$b.Author -eq $Book.Author -and
348348
$b.PublishDate -eq $Book.PublishDate
349349
}.GetNewClosure()
350+
#^^^^^^^^^^^^^^^^^^^^^^^^ meta.class.powershell meta.function.powershell
351+
#^^^^^^^^ meta.block.powershell
352+
# ^ punctuation.section.braces.end.powershell
353+
# ^ punctuation.accessor.dot.powershell
354+
# ^^^^^^^^^^^^^ meta.function-call.powershell variable.function.powershell
355+
# @@@@@@@@@@@@@ reference
356+
# ^^ meta.function-call.arguments.powershell
357+
# ^ punctuation.section.arguments.begin.powershell
358+
# ^ punctuation.section.arguments.end.powershell
350359
if ([BookList]::Books.Find($FindPredicate)) {
351360
# @@@@ reference
352361
throw "Book '$Book' already in list"
@@ -397,6 +406,16 @@ class BookList {
397406
param($b)
398407
$b.$Property -eq $Value
399408
}.GetNewClosure())
409+
#^^^^^^^^^^^^^^^^^^^^^^^^^ meta.class.powershell meta.function.powershell meta.function-call.arguments.powershell
410+
#^^^^^^^^ meta.block.powershell
411+
# ^ punctuation.section.braces.end.powershell
412+
# ^ punctuation.accessor.dot.powershell
413+
# ^^^^^^^^^^^^^ meta.function-call.powershell variable.function.powershell
414+
# @@@@@@@@@@@@@ reference
415+
# ^^ meta.function-call.arguments.powershell
416+
# ^ punctuation.section.arguments.begin.powershell
417+
# ^ punctuation.section.arguments.end.powershell
418+
# ^ punctuation.section.arguments.end.powershell
400419
if ($Index -ge 0) {
401420
[BookList]::Books.RemoveAt($Index)
402421
# @@@@@@@@ reference

0 commit comments

Comments
 (0)