PowerShell
PowerShell copied to clipboard
Introduce a new, single-line raw string literal (single-line here-string alternative)
Note: This idea was first proposed by @bergmeister and fleshed out by @lzybkr in https://github.com/PowerShell/PowerShell/issues/2337#issuecomment-391152107, but only in the context of a proposal focused on something different (allowing indentation of the closing delimiter of here-strings).
Summary of the new feature/enhancement
To complement the existing raw / semi-raw, invariably multi-line here-string literals (@'<newline>...<newline>'@
/ @"<newline>...<newline>"@
), it would be convenient to have a single-line variant.
For lack of a better term I'll call the new variant a raw string literal.
For instance, here's how you could express verbatim string 6' 2"
:
# Note: leading and trailing whitespace inside the value will be ignored.
# single-quoted
@' 6' 2" '@
# double-quoted - as with double-quoted here-strings, string interpolation and `-escaping would work.
@" $feet' 2" "@
To avoid the need for escaping, allow a variable number of quotes in the delimiter to avoid the need for escaping; e.g.:
@'' using @' in here is now fine ''@
A use case that would benefit is wanting to pass a command line written for the native shell as-is to it (see also: #13068); e.g. (on Unix):
# WISHFUL THINKING
sh -c @' python -c 'print("hi")' | cat -n '@
Proposed technical implementation details (optional)
Backward compatibility assessment:
Since with the current here-string literals no (non-whitespace) characters are allowed on the same line after the opening delimiter, and given that trying to do that is currently a syntax error, this new string-literal variant is safe to introduce.
Disambiguation:
Anything that starts with @'
or @"
and is followed by non-whitespace characters on the same line is interpreted as the new raw string literal, requiring the closing delimiter to be on the same line.
- Note: Conceivably, we could let the new variant span multiple lines as well, but it strikes me as conceptually cleaner to restrict the multi-line forms to the established here-string syntax.
Insignificant leading and trailing whitespace:
Ignoring whitespace surrounding the value serves two purposes:
- It makes it easier to visually distinguish the delimiters from the enclosed value (e.g.,
@' 6' 2" '@
vs.@'6' 2"'@
) - Since supporting a variable number of quotes in the delimiter is desirable (e.g.,
@'' @' is fine ''@
), ignoring surrounding whitespace solves the problem of enclosed values starting or ending with a quote that would otherwise break the syntax (e.g., to embed verbatim'hi
,@''hi'@
wouldn't work syntactically, but@' 'hi '@
- with surrounding whitespace stripped on parsing - does.
@TSlivede proposes the following alternatives, which consider all whitespace significant, albeit at the expense of the visual separation between the delimiters and the value:
- limiting the number of quotes to 3 at most - see below.
- instead of making the number of quotes variable, duplicate the
@
symbol - see below.
Values that need surrounding whitespace to be significant:
In cases where you need the enclosed values start and/or end with whitespace, the following solutions are possible:
-
Use the double-quoted form, where
`
-escaping can be used to escape the spaces.- E.g., to get verbatim
<space>a"b'<space>
, you'd use@"` a"b'` "@
.
- E.g., to get verbatim
-
Alternatively, @TSlivede proposes considering only one leading/trailing space insignificant, in which case you merely need to add one extra space each to values with significant whitespace, in both the single- and double-quoted forms; e.g.,
@'<space> a"b <space>'@
and@"<space> a"b <space>"@
. However, a concern is that user may not expect that only a specific number (i.e., one) of spaces is insignificant; see below. -
Alternatively, use the established multi-line here-string forms, where all whitespace is significant.
Thanks for creating an explicit issue for this!
Alternative suggestion regarding the removal of "Insignificant leading and trailing whitespace":
How about considering only a maximum of one leading space and one trailing space as "insignificant" and remove it?
This would still allow this:
- It makes it easier to visually distinguish the delimiters from the enclosed value (e.g.,
@' 6' 2" '@
vs.@'6' 2"'@
)- Since supporting a variable number of quotes in the delimiter is desirable (e.g.,
@'' @' is fine ''@
), ignoring surrounding whitespace solves the problem of enclosed values starting or ending with a quote that would otherwise break the syntax (e.g., to embed verbatim'hi
,@''hi'@
wouldn't work syntactically, but@' 'hi '@
- with surrounding whitespace stripped on parsing - does.
And it would also improve "Values that need surrounding whitespace to be significant":
Just put one more space to the beginning and one more to the end.
Thanks, @TSlivede, I've folded your suggestion into the OP. I like it, but a slight concern is that the fact that the behavior is tied to a specific number of spaces, i.e., exactly one, could be a bit obscure, and that people may be more used to any number of leading/trailing spaces being insignificant, such as in inline code elements enclosed in `
in Markup.
people may be more used to any number of leading/trailing spaces being are insignificant
Yes you are right, the syntax I suggested might be very surprising to new users, maybe it's not such a good idea after all.
It could for example be especially problematic, if someone wants a string leading with e.g. 4 spaces. To test if spaces are preserved he enters @' test string'@
(4 spaces) and powershell prints test string
(three spaces), which looks very similar to four leading spaces. That user would probably not notice the missing space and would now have a very subtle bug in his code...
Good points. I take it then that this would require at least the initial leading space to be escaped with `
?
@vexx32, yes, but note that the use of `
for escaping requires a switch to the double-quoted form, because in the single-quoted one the `
would be a literal that is retained. Using a single-quoted (invariably multi-line) here-string instead avoids that.
@TSlivede :) I've unindented the paragraph, and I've also added our (later) concern about the suggestion expressed therein.
Another alternative idea:
Allow only a maximum of three quotes in the delimiters and don't remove leading/trailing whitespace.
This way we would lose the visual advantage
- It makes it easier to visually distinguish the delimiters from the enclosed value (e.g.,
@' 6' 2" '@
vs.@'6' 2"'@
)
(@' 6' 2" '@
and @'6' 2"'@
would not be equivalent)
But we would gain an easy option for leading or trailing significant whitespace.
Leading quotes would also be easy: As only a maximum of three quotes are considered part of the string delimiter, the fourth quote would be a literal quote.
e.g., to embed verbatim 'hi
one could use @''''hi'''@
As with my previous suggestion the behavior is tied to a specific number of quotes (not spaces in this case 😉). But three quotes is something users might already have seen for here strings: python, kotlin, scala, groovy
Addition to that suggestion: To allow embedding literal '''@
maybe allow multiple (unlimited?) @
symbols in the string delimiters. E.g.:
@@'some string containing >>>'@<<< - delimited with multiple @-symbols'@@
This issue has not had any activity in 6 months, if there is no further activity in 7 days, the issue will be closed automatically.
Activity in this case refers only to comments on the issue. If the issue is closed and you are the author, you can re-open the issue using the button below. Please add more information to be considered during retriage. If you are not the author but the issue is impacting you after it has been closed, please submit a new issue with updated details and a link to this issue and the original.