Skip to content

Commit 1cddc0b

Browse files
committed
Break keyword.control into semantic scopes. Use kebab_break. Readability
1 parent 43a437b commit 1cddc0b

File tree

3 files changed

+184
-83
lines changed

3 files changed

+184
-83
lines changed

PowerShell.sublime-syntax

Lines changed: 137 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,18 @@ variables:
2020
float_suffix: (?i:[fdm](?!b))
2121
integer_suffix: (?i:ul?|lu?)
2222
bytes_unit: (?i:[kmgtp]b)
23+
kebab_break: (?![\w-])
2324

2425
contexts:
2526

27+
pop-before-newline:
28+
- match: (?=\n|$)
29+
pop: true
30+
31+
pop-at-newline:
32+
- match: \n|$
33+
pop: true
34+
2635
main:
2736
- include: comments
2837
- include: redirection
@@ -61,75 +70,128 @@ contexts:
6170
- include: main
6271
- match: \b[\w.-]+\.(?i:exe|com|cmd|bat)\b
6372
scope: variable.function.powershell
64-
- match: \b(?:(?i:begin|break|catch|continue|data|default|define|do|dynamicparam|else|elseif|end|exit|finally|for|foreach(?!-object)|from|if|in|inlinescript|parallel|param|process|return|switch|throw|trap|try|until|var|where(?!-object)|while)|%|\?)(?!\w)
73+
# Exceptions
74+
- match: \b(?i:throw){{kebab_break}}
75+
scope: keyword.control.exception.raise.powershell
76+
- match: \b(?i:try){{kebab_break}}
77+
scope: keyword.control.exception.try.powershell
78+
- match: \b(?i:catch|trap){{kebab_break}}
79+
scope: keyword.control.exception.catch.powershell
80+
- match: \b(?i:finally){{kebab_break}}
81+
scope: keyword.control.exception.finally.powershell
82+
# Conditionals
83+
- match: \b(?i:if){{kebab_break}}
84+
scope: keyword.control.conditional.if.powershell
85+
- match: \b(?i:elseif){{kebab_break}}
86+
scope: keyword.control.conditional.elseif.powershell
87+
- match: \b(?i:else){{kebab_break}}
88+
scope: keyword.control.conditional.else.powershell
89+
- match: \b(?i:switch){{kebab_break}}
90+
scope: keyword.control.conditional.switch.powershell
91+
- match: \?
92+
scope: keyword.control.conditional.select.powershell
93+
- match: \b(?i:where(?!-object)){{kebab_break}}
94+
scope: keyword.control.conditional.select.powershell
95+
# Begin/End
96+
- match: \b(?i:begin){{kebab_break}}
97+
scope: keyword.context.block.begin.powershell
98+
- match: \b(?i:end){{kebab_break}}
99+
scope: keyword.context.block.end.powershell
100+
# Loops
101+
- match: \b(?i:for|foreach(?!-object)){{kebab_break}}
102+
scope: keyword.control.loop.for.powershell
103+
- match: \b(?i:do){{kebab_break}}
104+
scope: keyword.control.loop.do-while.powershell
105+
- match: \b(?i:while){{kebab_break}}
106+
scope: keyword.control.loop.while.powershell
107+
- match: \b(?i:until){{kebab_break}}
108+
scope: keyword.control.loop.repeat-until.powershell
109+
# Flow
110+
- match: \b(?i:break){{kebab_break}}
111+
scope: keyword.control.flow.break.powershell
112+
- match: \b(?i:continue){{kebab_break}}
113+
scope: keyword.control.flow.continue.powershell
114+
- match: \b(?i:exit){{kebab_break}}
115+
scope: keyword.control.flow.exit.powershell
116+
- match: \b(?i:return){{kebab_break}}
117+
scope: keyword.control.flow.return.powershell
118+
# Declaration
119+
- match: \b(?i:var){{kebab_break}}
120+
# scope: storage.type.variable.powershell
121+
scope: keyword.declaration.variable.powershell
122+
- match: \b(?i:(?:dynamic)?param){{kebab_break}}
123+
scope: keyword.declaration.parameter.powershell # This scope is not standard
124+
# Uncategorized keywords
125+
- match: \b(?i:data|default|define|from|in|inlinescript|parallel|process){{kebab_break}}
65126
scope: keyword.control.powershell
66127
- match: \B--%\B
67128
scope: keyword.control.powershell
68129
push:
69130
- meta_content_scope: string.unquoted.powershell
70-
- match: (?=\n|$)
71-
pop: true
131+
- include: pop-before-newline
72132
- match: \b(?i:hidden|static)\b
73133
# This should only be relevant inside a class but will require a rework of how classes are matched. This is a temp fix.
74134
scope: storage.modifier.powershell
75-
- match: \b((?i:class)|%|\?)(?:\s)+([\w-]+)\b
135+
- match: \b((?i:class))\s+([\w-]+)\b
76136
captures:
77137
1: storage.type.class.powershell
78138
2: meta.class.powershell entity.name.class.powershell
79139
# Operators...
80-
- match: \B(-)(?i:as)\b
140+
- match: \B(-)(?i:as){{kebab_break}}
81141
scope: keyword.operator.cast.powershell
82142
captures:
83143
1: punctuation.definition.keyword.powershell
84-
- match: \B(-)(?i:[ic]?(?:eq|ne|[gl][te]))\b
144+
- match: \B(-)(?i:[ic]?(?:eq|ne|[gl][te])){{kebab_break}}
85145
scope: keyword.operator.comparison.powershell
86146
captures:
87147
1: punctuation.definition.keyword.powershell
88-
- match: \B(-)(?i:[ic]?(?:not)?(?:like|match|contains|in))\b
148+
- match: \B(-)(?i:[ic]?(?:not)?(?:like|match|contains|in)){{kebab_break}}
89149
scope: keyword.operator.logical.powershell
90150
captures:
91151
1: punctuation.definition.keyword.powershell
92-
- match: \B(-)(?i:join|split|replace)\b
152+
- match: \B(-)(?i:join|split|replace){{kebab_break}}
93153
scope: keyword.operator.string.powershell
94154
captures:
95155
1: punctuation.definition.keyword.powershell
96-
- match: \B(-)(?i:is(?:not)?)\b
156+
- match: \B(-)(?i:is(?:not)?){{kebab_break}}
97157
scope: keyword.operator.logical.powershell
98158
captures:
99159
1: punctuation.definition.keyword.powershell
100-
- match: \B(-)(?i:and|or|not|xor)\b|!
160+
- match: \B(-)(?i:and|or|not|xor){{kebab_break}}|! # <-- note `!`
101161
scope: keyword.operator.logical.powershell
102162
captures:
103163
1: punctuation.definition.keyword.powershell
104-
- match: \B(-)(?i:band|bor|bnot|bxor|sh[lr])\b
164+
- match: \B(-)(?i:band|bor|bnot|bxor|sh[lr]){{kebab_break}}
105165
scope: keyword.operator.bitwise.powershell
106166
captures:
107167
1: punctuation.definition.keyword.powershell
108-
- match: \B(-)(?i:f)\b
168+
- match: \B(-)(?i:f){{kebab_break}}
109169
scope: keyword.operator.string-format.powershell
110170
captures:
111171
1: punctuation.definition.keyword.powershell
112172
# Flags/Options/Parameters
113-
- match: \B([-/])[\p{L}](?:[\w-]*\w)?
173+
- match: \B([-/])\p{L}(?:[\w-]*\w)?
114174
scope: variable.parameter.option.powershell
115175
captures:
116176
1: punctuation.definition.parameter.powershell
117-
# operators continue...
177+
# Operators continue...
118178
- match: '[+/*%-]?='
119179
scope: keyword.operator.assignment.powershell
120180
- match: (?:\+\+|--)(?![ \t]*\d)
121181
scope: keyword.operator.assignment.powershell
122-
- match: '[+-](?=\.?\d)'
182+
- match: '[+-](?=\.?\d)' # This is sort of heuristic
123183
scope: keyword.operator.unary.powershell
124-
- match: '[+/*%-]'
184+
- match: '[+/*-]'
185+
scope: keyword.operator.arithmetic.powershell
186+
- match: '%(?!\s*\{)'
125187
scope: keyword.operator.arithmetic.powershell
126188
- match: \|\||&&
127189
scope: keyword.operator.logical.powershell
128190
- match: \|
129191
scope: keyword.operator.logical.pipe.powershell
130192
- match: ;
131193
scope: punctuation.terminator.statement.powershell
132-
- match: \`
194+
- match: \`(?=\n|$)
133195
scope: punctuation.separator.continuation.line.powershell
134196
- match: ','
135197
scope: punctuation.separator.sequence.powershell
@@ -167,8 +229,7 @@ contexts:
167229
2: keyword.control.import.require.powershell
168230
push:
169231
- meta_scope: meta.requires.powershell
170-
- match: \n|$
171-
pop: true
232+
- include: pop-at-newline
172233
- include: hashtable
173234
- match: (-)(?i:Modules|PSSnapin|RunAsAdministrator|ShellId|Version)
174235
scope: variable.parameter.option.powershell
@@ -185,7 +246,14 @@ contexts:
185246
3: variable.parameter.powershell
186247

187248
attribute:
188-
- match: (\[)\s*\b(?i)(cmdletbinding|alias|outputtype|parameter|validatenotnull|validatenotnullorempty|validatecount|validateset|allownull|allowemptycollection|allowemptystring|validatescript|validaterange|validatepattern|validatelength)\b
249+
- match: |-
250+
(?xi:
251+
(\[)\s*
252+
(CmdletBinding|Alias|OutputType|Parameter
253+
|Validate(?:Count|NotNull(?:OrEmpty)?|Range|Pattern|Length|Set|Script)
254+
|Allow(?:Null|Empty(?:Collection|String))
255+
)\b
256+
)
189257
captures:
190258
1: punctuation.section.bracket.begin.powershell
191259
2: support.function.attribute.powershell
@@ -209,7 +277,14 @@ contexts:
209277
- include: type
210278
- include: numeric-constant
211279
- include: main
212-
- match: (?i)\b(mandatory|valuefrompipeline|valuefrompipelinebypropertyname|valuefromremainingarguments|position|parametersetname|defaultparametersetname|supportsshouldprocess|positionalbinding|helpuri|confirmimpact|helpmessage)\b(?:\s+)?(=)
280+
- match: |-
281+
(?xi:
282+
\b(Mandatory|ValueFromPipeline(?:ByPropertyName)?
283+
|ValueFromRemainingArguments|Position
284+
|(?:Default)?ParameterSetName|SupportsShouldProcess
285+
|PositionalBinding|HelpUri|ConfirmImpact|HelpMessage)
286+
\s*(=)
287+
)
213288
captures:
214289
1: variable.parameter.attribute.powershell
215290
2: keyword.operator.assignment.powershell
@@ -224,11 +299,28 @@ contexts:
224299
pop: true
225300
226301
commands:
227-
- match: (?:[\w\\:-]*\\)?\b(?i:Add|Approve|Assert|Backup|Block|Build|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy|Debug|Deny|Deploy|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|Format|Get|Grant|Group|Hide|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Mount|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select|Send|Set|Show|Skip|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Write)\-.+?(?:\.(?i:exe|cmd|bat|ps1))?\b
228-
# "Verb-Noun pattern:"
302+
# "Verb-Noun pattern:"
303+
- match: |-
304+
(?x:
305+
(?:[\w\\:-]*\\)? # Path stuff
306+
\b(?i:Add|Approve|Assert|Backup|Block|Build|Checkpoint|Clear|Close # "Official" Verbs
307+
|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom
308+
|ConvertTo|Copy|Debug|Deny|Deploy|Disable|Disconnect|Dismount|Edit
309+
|Enable|Enter|Exit|Expand|Export|Find|Format|Get|Grant|Group|Hide
310+
|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge
311+
|Mount|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push
312+
|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset
313+
|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select
314+
|Send|Set|Show|Skip|Split|Start|Step|Stop|Submit|Suspend|Switch
315+
|Sync|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish
316+
|Unregister|Update|Use|Wait|Watch|Write
317+
)
318+
\-\w+? # Any "noun"
319+
(?:\.(?i:exe|cmd|bat|ps1))?\b # More path stuff
320+
)
229321
scope: support.function.powershell
322+
# Builtin cmdlets with reserved verbs
230323
- match: \b(?i:(?:foreach|where|sort|tee)-object)\b
231-
# Builtin cmdlets with reserved verbs
232324
scope: support.function.powershell
233325

234326
comment-block:
@@ -242,18 +334,25 @@ contexts:
242334
- include: comment-embedded-docs
243335

244336
comment-embedded-docs:
245-
- match: ^\s*(\.)(?i:(COMPONENT|DESCRIPTION|EXAMPLE|EXTERNALHELP|FORWARDHELPCATEGORY|FORWARDHELPTARGETNAME|FUNCTIONALITY|INPUTS|LINK|NOTES|OUTPUTS|REMOTEHELPRUNSPACE|ROLE|SYNOPSIS))
337+
# TODO
338+
# https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comment_based_help
339+
- match: |-
340+
(?xi:
341+
^\s*(\.)
342+
(Component|Description|Example|ForwardHelpTargetName|Functionality
343+
|Inputs|Notes|Outputs|RemoteHelpRunSpace|Role|Synopsis)
344+
)
246345
scope: comment.documentation.embedded.powershell
247346
captures:
248347
1: punctuation.definition.keyword.documentation.powershell
249348
2: keyword.other.documentation.powershell
250-
- match: ^\s*(\.)(?i:(PARAMETER)\s+([a-z0-9-_]+))
349+
- match: ^\s*(\.)(?i:(Parameter)\s+([a-z0-9-_]+))
251350
scope: comment.documentation.embedded.powershell
252351
captures:
253352
1: punctuation.definition.keyword.documentation.powershell
254353
2: keyword.other.documentation.param.powershell
255354
3: variable.parameter.powershell
256-
- match: ^\s*(\.)(?i:(FORWARDHELPTARGETNAME|FORWARDHELPCATEGORY|REMOTEHELPRUNSPACE|EXTERNALHELP)\s+([a-z0-9-_]+))
355+
- match: ^\s*(\.)(?i:(ForwardHelpTargetName|ForwardHelpCategory|ExternalHelp|Link)\s+([a-z0-9-_]+))
257356
scope: comment.documentation.embedded.powershell
258357
captures:
259358
1: punctuation.definition.keyword.documentation.powershell
@@ -266,8 +365,7 @@ contexts:
266365
scope: punctuation.definition.comment.powershell
267366
push:
268367
- meta_scope: comment.line.powershell
269-
- match: \n|$
270-
pop: true
368+
- include: pop-at-newline
271369
- include: comment-embedded-docs
272370

273371
strings:
@@ -431,16 +529,19 @@ contexts:
431529
3: keyword.other.unit.powershell
432530

433531
script-block:
434-
- match: \{
435-
scope: punctuation.section.braces.begin.powershell
532+
- match: (%)?(\{)
533+
captures:
534+
1: keyword.control.loop.for.powershell
535+
2: punctuation.section.braces.begin.powershell
436536
push:
437-
- meta_scope: meta.scriptblock.powershell
537+
- meta_scope: meta.block.powershell
438538
- match: \}
439539
scope: punctuation.section.braces.end.powershell
440540
pop: true
441541
- include: main
442542

443543
type:
544+
# TODO: push a maybe-static-members context
444545
- match: \[
445546
scope: punctuation.section.bracket.begin.powershell
446547
push:
@@ -585,14 +686,13 @@ contexts:
585686
1: punctuation.definition.variable.powershell
586687
2: storage.modifier.scope.powershell
587688
3: variable.other.readwrite.powershell
588-
4: entity.name.function.invocation.powershell
589689
- match: (?i:(\$)(\{)(global|local|private|script|using|workflow):([^}]*[^}`])(\}))
590690
captures:
591691
1: punctuation.definition.variable.powershell
592-
2: storage.modifier.scope.powershell
593-
3: variable.other.readwrite.powershell
594-
4: keyword.other.powershell
595-
5: entity.name.function.invocation.powershell
692+
2: punctuation.section.braces.begin
693+
3: storage.modifier.scope.powershell
694+
4: variable.other.readwrite.powershell
695+
5: punctuation.section.braces.end
596696
- match: (?i:(\$)(\w+:)?\w+)
597697
scope: variable.other.readwrite.powershell
598698
captures:

Tests/syntax_test_Function.ps1

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ function Verb-Noun {
9898
# ^ meta.attribute punctuation.section.group.end
9999
# ^ meta.attribute punctuation.section.bracket.end
100100
Param
101-
# <- keyword.control
101+
#^^^^^ keyword.declaration.parameter
102102
(
103103
# <- punctuation.section.group.begin
104104
# Param1 help description
@@ -322,11 +322,11 @@ function Verb-Noun {
322322
# <- meta.attribute punctuation.section.bracket.begin
323323
# ^ meta.attribute support.function.attribute
324324
# ^ meta.attribute punctuation.section.group.begin
325-
# ^ meta.attribute meta.scriptblock
326-
# ^^^^^^^^^ meta.scriptblock support.function
327-
# ^ meta.scriptblock punctuation.definition.variable
328-
# ^ meta.scriptblock variable.language
329-
# ^ meta.attribute meta.scriptblock
325+
# ^ meta.attribute meta.block
326+
# ^^^^^^^^^ meta.block support.function
327+
# ^ meta.block punctuation.definition.variable
328+
# ^ meta.block variable.language
329+
# ^ meta.attribute meta.block
330330
# ^ meta.attribute punctuation.section.group.end
331331
# ^ meta.attribute punctuation.section.bracket.end
332332
[string]
@@ -370,7 +370,7 @@ function Verb-Noun {
370370
# <- punctuation.section.group.end
371371

372372
Begin
373-
# <- keyword.control
373+
#^^^^^ keyword.context.block.begin
374374
{
375375
}
376376
Process {
@@ -387,7 +387,7 @@ function Verb-Noun {
387387
}
388388
}
389389
End {
390-
# <- keyword.control
390+
#^^^ keyword.context.block.end
391391

392392
}
393393
}

0 commit comments

Comments
 (0)