-
Notifications
You must be signed in to change notification settings - Fork 8k
Description
Summary of the new feature/enhancement
Is there any mileage or desire for an option that enforces the use of semicolon (and only semicolon) as the command terminator for a given script?
I regularly find myself at odds between the "natural" line-continuation points within the PowerShell language, and where I want to place a newline for the long-term readability of my scripts. As such, I find myself resorting to escaping newlines with the backtick, which I am repeatedly led to believe is a bad thing™.
I completely understand why the natural points are what they are, but most of the reasons seem to boil down to the expectation that a newline can terminate the command. If the script parser could be informed that semicolon was the only command terminator in a given script, it could bypass having to make continuation checks at each newline and make whitespace mostly-insignificant. This would allow for better alignment of pipelines and command parameters, without having to resort to backtick and without the language seeming to have opinions as to where line continuation should happen.
Proposed technical implementation details (optional)
I see this as an extension to #Requires
because of its existing script scope, however, the notion of requiring command termination is not semantically ideal. As such, this could reasonably be via any other script-wide directive. It could be a dedicated Set-CommandTermination
command, or maybe an additional parameter to Set-StrictMode
(although there may be lexical scope expectations around such).
It would certainly need to be an opt-in state, so as not to affect existing scripts.
It might be desirable to later extend this to allow for alternate command terminators—such as DoubleNewline
—for those who find semicolons repulsive.
It is intended to facilitate such script formatting as the following (which is appreciably my personal preference), without requiring further complex line-continuation checks:
Instead of...
Import-Module DummyExample
Invoke-DummyPipelineProducer -SomeArgument -OtherArgument |
Invoke-DummyLongParameterList -SomeSwitch -OtherSwitch -SomeParameter 12345 -Expression (
Invoke-DummyMethod | Select-Object -First 1) |
Where-Object { $_.SomeProperty -contains (
Invoke-DummyFilterList -Type A | Select-Object -First 1) } |
Select-Object -ExpandProperty Foo |
ForEach-Object {
if (-not (Test-Dummy $_)) { Invoke-DummyAction $_ }
else { Write-Verbose "$_ already done" }
}
...or the backtick-laden...
Import-Module DummyExample
Invoke-DummyPipelineProducer -SomeArgument -OtherArgument `
| Invoke-DummyLongParameterList `
-SomeSwitch `
-OtherSwitch `
-SomeParameter 12345 `
-Expression (Invoke-DummyMethod | Select-Object -First 1) `
| Where-Object { $_.SomeProperty -contains (
Invoke-DummyFilterList -Type A | Select-Object -First 1 `
) } `
| Select-Object -ExpandProperty Foo `
| ForEach-Object {
if (-not (Test-Dummy $_)) { Invoke-DummyAction $_ }
else { Write-Verbose "$_ already done" }
}
...we could write...
#Requires -CommandTermination Semicolon;
Import-Module DummyExample;
Invoke-DummyPipelineProducer -SomeArgument -OtherArgument
| Invoke-DummyLongParameterList
-SomeSwitch
-OtherSwitch
-SomeParameter 12345
-Expression (Invoke-DummyMethod | Select-Object -First 1)
| Where-Object {
$_.SomeProperty -contains (Invoke-DummyFilterList -Type A
| Select-Object -First 1)
}
| Select-Object -ExpandProperty Foo
| ForEach-Object {
if (-not (Test-Dummy $_)) { Invoke-DummyAction $_ }
else { Write-Verbose "$_ already done" }
};
Unfortunately, I can't comment as to how much effort this would add to the script parser.