-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot save multi-line output in a variable (support $() command substitution syntax) #159
Comments
And for the record, doing such a replacement makes it impossible to look at the status of the original command* (e.g. in issue #158), because Fish provides no replacement for bash's *without really stupid things like piping the output to a file temporarily |
As a separate idea, if there was some flag to |
The lack of a way to quote a command substitution has just reared its head in another location: the inability to use command substitution with |
For me it looks quite natural: no output - no arguments. One empty line of output - one empty argument. Concerning the multi-line output I completely agree with you. It would be very nice to have possibility to do command substitution inside double quotes, something like "$()", because substituting "()" is dangerous. |
As an alternative to |
Shorter ways to do the same: |
I assume you mean As for The use of this is for piping to another process. Obviously storing it back in a variable would just split it again, but I can say |
You are right. |
This outputs 1:
This outputs 3:
I don't understand why newlines from a substitution result in arrays, while spaces from a substitution do not. I wonder how bad it would be to treat whitespace uniformly here. |
I think that it's perfectly consistent behaviour (considering that fish distinguishes whitespaces). From my experience automatic expanding space-separated strings to array makes it difficult to cope with space containing strings and lead to rather extensive subquoting. From the other hand: additional splitting can be implemented by additional command. But if fish will split all whitespaces it will be difficult to glue them back if needed. |
My suggestion was actually in the other direction: treat newlines like spaces (so they do not split). So
would output 1. On the other hand, then we would need some way to split a string. I also think kballard's suggestion of quoted substitutions via e.g. |
I completely agree about "$(echo hello)". |
Personally I'm very -1 to One of the things that drew me to fish was that it simplifies all of the crazy different ways to do things that bash/zsh/etc have. See the design doc, the law of orthogonality. To quote,
I think it would be a serious degradation of fish's principles to add From what I understand, adding a third quoting syntax ( Understanding the whitespace rules right now is a big pain point. Currently:
That I get. Quotes prevent splitting. Cool.
Ok and it looks like subcommands are automatically considered quoted...
And newlines don't count as whitespace when you're splitting things, that's cool I guess
Wait, what?! Something's seriously smelly here. If And, of course, the big scripting problem is that the data isn't preserved by
We had newlines and now we have spaces. I understand why it all works like this but it definitely doesn't seem very fish-like. User focus is violated here, orthogonality certainly isn't helped. I'm not sure what the answer is, but any or all of these are options I like better than
Concerning option 2, it would mean that unquoted command substitution would act like this:
Which is a big change, but is at least consistent. Many of these are more work-arounds than solutions. And even if we fix I'm most in favor of 1. or 2. above, but either way I'm against adding
Most of my ideas above are still half-baked, but I think more carefully designing the text-splitting rules is a far superior option to adding more syntax and flags on top of the existing ones in an attempt to patch all the holes. That sort of activity is what got bash where it is today. |
Thank you for the thoughtful comments Soares. I think there might be a point of confusion. The $() proposal is to add a way to do command substitutions within double quotes. It need not work outside of them:
In that way I think it's similar to your suggestion 2 above. The dollar sign has the advantages of not requiring escaping parens within double quotes (which would be irritating), and because it doesn't conflict with any existing valid syntax. This was an element of kballard's "Fish Scripting Wishlist" from June 21. To quote Kevin:
So "$()" would solve several problems, which is why it's interesting. I think we'd also like to avoid splitting on newlines as you suggest in 3 above. The main blocker there is the sheer quantity of work required to vet all existing fish code, and in adding the new 'dice' command. |
Cool. I'm much less opposed to that syntax if it's only in double quotes. (Note: In fish 1.x variables in double quotes expanded to the first arg in that variable array and there was no way to slice/get the other args. This was a concession to Axel Liljencrantz IIRC, who didn't want double quotes in the first place and insisted on having something that set double quotes apart, which I thought was stupid. I was right on the brink of a rant about the magical things that double quotes do before I realized that double quotes are pretty sane in fish2.0. Nice work on that!) It's still weird to me to use Also I'm wary of conflating Also I think that expanding an empty variable should yield
problem, which is a serious gotcha for newcomers. |
What is POSIX Expanding an empty variable should never yield |
Bash's Especially since fish keeps command substitution but changes the syntax from Which is why I'm tentatively in favor of biting the bullet and allowing |
I would consider interpreting |
Yeah, I concede that that might be the best course of action from where we're standing. However, the converse to your statement is this: Remember that the only substitution that occurs outside of quotes is Having It's a shit situation. |
If you really want to be pure, you could introduce Of course, at this point, you may then say "what about That said, from a practical standpoint, I think making these changes here is unnecessary. I'd rather just introduce |
Yeah, if the language were being designed from the get-go I'd recommend axing the bare version. If Just a note: If you have long double quoted strings, you can already
It's one character more and it doesn't require extra syntax. It's really only the edge-case of |
No you can't.
The desired behavior is
|
Right. Sorry. I meant to say that you can do that if we make variables not be split on newlines by default and add a |
Soares, out of curiosity, where did you get name for the |
For some reason I thought the existing Seeing now that I was thinking of |
Soares, thank you for that long argumented answer. I now agree with you (: |
@Soares, very well written and good arguments, I agree with consistency here, I don't see the point of having one syntax in double quotes and one outside of double quotes. To summarize, either only |
Last related comment was over a year ago. This is still a big missing feature with no good/standard way of doing it. Are we not happy with |
We have |
I agree with keeping this open. We'll probably end up supporting First step I guess is to design it. In bash
do we want to allow that, to arbitrary depth? Or can we start with something useful but more restricted, which would be easier to implement? |
I think we can hack the parser to close double quotes on The cost here is the more complex quoting syntax - a single regex will no longer be enough to correctly highlight such strings. If we don't support quotes inside Not sure what to do about unquoted Alternatively, if we want to avoid making the quoting syntax more complex, we could support unquoted echo "no interpolation "$(echo "(but nested quotes)")" for you" That may be less elegant but does not require to understand the concept of command substitutions inside quotes. We could try to make this as convenient to type as the bash version: |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This adds a hack to the parser. Given a command echo "x$()y z" we virtually insert double quotes before and after the command substitution, so the command internally looks like echo "x"$()"y z" This makes the quoting syntax more complex. It is no longer possible to describe all quoted strings with a single regex. This will make external highlighters a bit more complicated to implement. The upside (some more Bash compatibility) seems worth it. Unquoted $() ist left unsupported for now. Closes fish-shell#159
This adds a hack to the parser. Given a command echo "x$()y z" we virtually insert double quotes before and after the command substitution, so the command internally looks like echo "x"$()"y z" This makes the quoting syntax more complex. It is no longer possible to describe all quoted strings with a single regex. This will make external highlighters a bit more complicated to implement. The upside (some more Bash compatibility) seems worth it. Unquoted $() ist left unsupported for now. Closes fish-shell#159
This adds a hack to the parser. Given a command echo "x$()y z" we virtually insert double quotes before and after the command substitution, so the command internally looks like echo "x"$()"y z" This makes the quoting syntax more complex. It is no longer possible to describe all quoted strings with a single regex. This will make external highlighters a bit more complicated to implement. The upside (more Bash compatibility) seems worth it. Unquoted $() ist left unsupported for now. Closes fish-shell#159
This adds a hack to the parser. Given a command echo "x$()y z" we virtually insert double quotes before and after the command substitution, so the command internally looks like echo "x"$()"y z" This makes the quoting syntax more complex. It is no longer possible to describe all quoted strings with a single regex. This will make external highlighters a bit more complicated to implement. The upside (more Bash compatibility) seems worth it. Unquoted $() ist left unsupported for now. Closes fish-shell#159
This adds a hack to the parser. Given a command echo "x$()y z" we virtually insert double quotes before and after the command substitution, so the command internally looks like echo "x"$()"y z" Since the command substitution establishes a new quoting context, this makes the quoting syntax more complex. It is no longer possible to describe all quoted strings with a single regex. This will make external highlighters more complex. The upside (more Bash compatibility) seems worth it. Closes fish-shell#159
This adds a hack to the parser. Given a command echo "x$()y z" we virtually insert double quotes before and after the command substitution, so the command internally looks like echo "x"$()"y z" Since the command substitution establishes a new quoting context, this makes the quoting syntax more complex. It is no longer possible to describe all quoted strings with a single regex. This will make external highlighters more complex. The upside (more Bash compatibility) seems worth it. Closes fish-shell#159
This adds a hack to the parser. Given a command echo "x$()y z" we virtually insert double quotes before and after the command substitution, so the command internally looks like echo "x"$()"y z" This allows to reuse the existing logic for handling (recursive) command substitutions.. Since the command substitution establishes a new quoting context, this makes the quoting syntax more complex. It is no longer possible to describe all quoted strings with a single regex. This will make external highlighters more complex. The upside (more Bash compatibility) seems worth it. Closes fish-shell#159
This adds a hack to the parser. Given a command echo "x$()y z" we virtually insert double quotes before and after the command substitution, so the command internally looks like echo "x"$()"y z" This allows to reuse the existing logic for handling (recursive) command substitutions.. Since the command substitution establishes a new quoting context, this makes the quoting syntax more complex. It is no longer possible to describe all quoted strings with a single regex. This will make external highlighters more complex. The upside (more Bash compatibility) seems worth it. Closes fish-shell#159
This adds a hack to the parser. Given a command echo "x$()y z" we virtually insert double quotes before and after the command substitution, so the command internally looks like echo "x"$()"y z" This hack allows to reuse the existing logic for handling (recursive) command substitutions. This makes the quoting syntax more complex; external highlighters should consider adding this if possible. The upside (more Bash compatibility) seems worth it. Closes fish-shell#159
This adds a hack to the parser. Given a command echo "x$()y z" we virtually insert double quotes before and after the command substitution, so the command internally looks like echo "x"$()"y z" This hack allows to reuse the existing logic for handling (recursive) command substitutions. This makes the quoting syntax more complex; external highlighters should consider adding this if possible. The upside (more Bash compatibility) seems worth it. Closes #159
The new support for For anyone curious on how the new Usage Documentation
Example Usage$ echo "zero $(echo one\ntwo\nthree) four"
zero one
two
three four And just to close things out I want to quote my favorite comment #8059 (comment) from the PR by @ridiculousfish themself regarding @krobelus's implementation 😁 👏 :
P.S. @krobelus do you have a Paypal/Patreon/Github Sponsors/GitTip/etc.? I'd love to send you a tip as a thank you for working on this feature and knocking it out of the park, your work here closes one of the longest outstanding issues I've been waiting for on the fish project, and I'd love to show my thanks. 🙏 |
This adds a hack to the parser. Given a command echo "x$()y z" we virtually insert double quotes before and after the command substitution, so the command internally looks like echo "x"$()"y z" This hack allows to reuse the existing logic for handling (recursive) command substitutions. This makes the quoting syntax more complex; external highlighters should consider adding this if possible. The upside (more Bash compatibility) seems worth it. Closes fish-shell#159
There seems to be no way to capture multi-line output in a shell variable. Any attempt to do so splits each line into a separate array element. In bash I'd simply put double-quotes around my
$()
invocation, but in fish you cannot quote a command substitution. This is rather unfortunate because it means I cannot capture multi-line output in a variable and send it back to a separate command without really weird contrivances, such as replacing all newlines with NUL when saving and reverting the process when emitting.The text was updated successfully, but these errors were encountered: