Repository navigation
Description
Line continuation in PowerShell suffers from at least two problems:
- The backtick char is hard to see in PowerShell script:
Get-Module pester `
| Foreach { Get-ChildItem $_.ModuleBase -recurse about_*.txt} `
| Foreach {$_.BaseName -replace '\.help',''} | Select-Object -Unique | Sort-Object
Escaping a char like _ makes the line continuation more obvious:
Get-Module pester `_
| Foreach { Get-ChildItem $_.ModuleBase -recurse about_*.txt} `_
| Foreach {$_.BaseName -replace '\.help',''} | Select-Object -Unique | Sort-Object
- The current line continuation mechanism is an escape of a newline (invisible) character. As a result, line continuation is broken if the user has any sort of whitespace (space or tabs) after the backtick since
<backtick><space>|<tab>does not signify line continuation.
The second issue is impossible to see via casual inspection of script and is common when you copy/paste script from a website. By using an escaped char like <backtick>_ there is no longer any issue with whitespace after this line continuation char. That whitespace can safely be ignored by the parser. For an example of this problem, copy the first script sample above and paste into a PowerShell console. It will fail to run because there are spaces after the backticks. :-)
FWIW I'm not sure escaping _ is the best choice but I do think escaping a "visible" character has the benefit of being more obvious. I would love to ditch the escaping and just use a dedicated continuation character like _ (which VB uses) but that is tough with PowerShell where I can have a function named _.
Another option might be to use a double escape:
Get-Module pester ``
| Foreach { Get-ChildItem $_.ModuleBase -recurse about_*.txt} ``
| Foreach {$_.BaseName -replace '\.help',''} | Select-Object -Unique | Sort-Object
I believe such a change would not interfere with the existing line continuation mechanism so existing scripts would continue to work.
Migrated from #2751
Activity
MaximoTrinidad commentedon Dec 1, 2016
Why? I like the used of the backtick. I've been doing this for a long time and I like it. So, why change something that works?
By the way, a script with code having backtick copy/paste to a console work. I use it all the time.
:)
rkeithhill commentedon Dec 1, 2016
If you read the proposal all the way through, it mentions that this would not change the existing mechanism. You can't because that would break too many scripts.
This issue is meant to discuss if it is worth adding another mechanism for line continuation. I know, right? Having more than one way to do something in PowerShell is SHOCKING I tell you. Completely unheard of. ;-)
KirkMunro commentedon Dec 1, 2016
How about adding
...as an optional continuation token? 🤔Sure, there could be a function with that name, but it would kinda make sense...
(pun intended)
KevinMarquette commentedon Dec 1, 2016
The general best practice is to not use the backtick for line continuation. Some times you can just restructure your command like this:
This is also where Here-Strings and Splatting come in handy. I tend to teach people these alternate approaches instead of introducing the backtick.
rkeithhill commentedon Dec 1, 2016
Kevin Marquette (@KevinMarquette) Keep in mind that neither breaking on | or using splatting is an option when invoking a native executable with a lot of lengthy parameters. That said, when I can avoid backtick I too try to avoid it.
KevinMarquette commentedon Dec 1, 2016
There are options for that too.
KevinMarquette commentedon Dec 1, 2016
I should clarify that I am not opposed to having a much better way to express line continuation.
stej commentedon Dec 1, 2016
I personally don't feel it's necessary to add a new language construct. Instead of that first what came on my mind was better text editors support.
A lot of tokens is highlighted in editors, so why not backtick (with Cyan, Salmon, or any other nice color)? And the rest of the line behind the backtick might be in other color with meaning "warning, this might be wrong".
djgrijalva commentedon Dec 1, 2016
Backticks are the devil. We all have widescreen monitors nowadays and know how to use the horizontal scroll bar :). Joking aside, I have found long running lines could be broken into separate lines entirely and often run faster since they are avoiding the pipeline. Multiple pipes just equal slow and lazy IMO.
rkeithhill commentedon Dec 1, 2016
Eska látor! (@stej) there is help for this in Visual Studio Code. I put this setting in my user settings file:
And PSScriptAnalyzer has a rule
PSMisleadingBacktickthat will catch these. But not everyone uses VSCode or PSScriptAnalyzer.MaximoTrinidad commentedon Dec 1, 2016
Nice one Keith Hill (@rkeithhill)!
I'm using VS Code for lightweight coding and I like it. Thanks for sharing the "files.trimTrailingWhitespace": true setting.
:)
Jaykul commentedon Dec 1, 2016
You most certainly can splat to native commands.
The catch is that native switch commands don't accept "true" values ;-)
E.g.
tf vc status /format:detailedCould just as easily be:
I don't like line continuation characters. I wish we didn't have the one we have (Yay C# -- Boo VB).
One problem with line continuation characters is that the only reason for them to exist is to enable people to stay within some arbitrary line width. Next thing you know you've got people trying to make a 249 character file path somehow fit on 80 character lines by splitting it into many strings and appending them together -- as if that actually improved readability.
DWSR commentedon Dec 1, 2016
The reason that I like staying within some "arbitrary line width" is because a lot of devs run portrait monitors. Having a 100 or 120 character limit means that my code fits in the width of the window.
I would love to have a switch to enable a line terminator as opposed to implementing yet another continuation character.
LarryWeiss commentedon Dec 1, 2016
Is there any language that has the concept of "line continuation" that has done it in a way that is better?
PowerShell's "line continuation" at first implied to me that the line was simply spliced together with the next one (as if the line ending was ignored). But that's not turned out to be the way it works. Try
'Power`
Shell'
JamesWTruher commentedon Dec 1, 2016
It's pretty hard to create a good shell that doesn't have some way to split command lines because they can get pretty long. I chose backtick because it was similar to
\(and I couldn't choose\for obvious reasons). Comparing PS to C# is a bit disingenuous they target different usage patterns - C# has a single statement end operator - requiring;at the end of every command would be a pretty rotten interactive shell experience.Bruce and I did think a lot about this in the early days, and tried to be faithful to Unix shell traditions and concepts, even if we weren't always faithful to their implementation, given all the platform considerations.
rkeithhill commentedon Dec 1, 2016
LarryWeiss
On the visibility front yes. Bash and Python use
\for line continuation. But neither tolerates whitespace after\. VB, which uses_, does tolerate whitespace after_.JamesWTruher commentedon Dec 1, 2016
some of those characters still have trouble in a windows environment where you're executing a command.
_is an allowed character for a filename - would I need to escape_in this context?get-content _rkeithhill commentedon Dec 1, 2016
Agreed. That's where an escaped character would be better.
spaghettidba commentedon Dec 4, 2016
FWIW, a number of international keyboards don't even have the backtick key. In the Italian keyboard it's ALT+TN96 or nothing. FWIW again, many laptops don't have TN at all, so there is NO way to type a backtick
iSazonov commentedon Dec 6, 2016
What about
##?mklement0 commentedon May 14, 2017
``is promising - the only existing code it would break is commands (argument-mode statements) that:`, individually escaped,E.g.,
Write-Host You should not end a sentence with a ``. Existing code doing that strikes me as not too likely.Gianluca Sartori (@spaghettidba) brings up a good point, but it is outweighed by the long tradition of ignoring other languages and keyboard layouts in computing :) (e.g.,
\,@)Ilya (@iSazonov): It's quite likely that
##is used in existing code for comments, and even if you limited recognition to##<newline>sequences, the potential for confusion with a comment is great.[Tangent alert]
LarryWeiss: Re line continuation in other languages (to add to Keith Hill (@rkeithhill)'s comment):
Good point; to elaborate on the fundamental difference between POSIX-compatible shells such as Bash and PowerShell with respect to line continuation:
In Bash,
\<newline>is removed from the lines of a command / inside a double-quoted string; this allows splitting command lines at arbitrary points and composing single-line strings spread across several lines inside double quotes.In PowerShell,
`<newline>preserves the newline; this requires splitting to occur between arguments and makes use inside a (double-quoted) string pointless, because a<newline>by itself will do; to get line continuation with a string in a POSIX sense, you must use the workaround of an array of substrings with unary-join.Note that in both environments there is no line continuation in single-quoted strings, where all content is treated literally (with the exception of
''in PS) - so, strictly speaking, your example doesn't apply (inside'...', both the`and the<newline>are retained, and, as with double-quoted strings, just<newline>will do).rkeithhill commentedon Jun 6, 2019
Two years later, I think I'm going to close this. The current situation is "somewhat" sub-optimal but I'm thinking the line-terminator sequence is not worth changing at this point.