Skip to content
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

Add a syntax for capturing outputs as a string #1416

Open
sauyon opened this issue Oct 27, 2021 · 5 comments
Open

Add a syntax for capturing outputs as a string #1416

sauyon opened this issue Oct 27, 2021 · 5 comments

Comments

@sauyon
Copy link
Contributor

sauyon commented Oct 27, 2021

I think it would be nice to have a $(cmd) which stringifies the output of the command automatically, as I find in most cases where I'm using output capture in a traditional way, what I really want is (cmd | slurp).

I've chosen the syntax as it's currently never valid elvish to write $( (and obviously mirroring POSIX subshell syntax), but I have no real preference. Perhaps it would be good to force users to use something else in case they attempt to use $(cmd) without understanding what the difference between elvish and POSIX shells would be.

Any comments would be appreciated.

See #1415 for a proposed implementation.

@xiaq
Copy link
Member

xiaq commented Oct 28, 2021

Two questions:

  • How does behave for value-outputting commands? In your PR the value outputs would be joined by \n but is that intended?

  • Should this preserve trailing newlines?

Personally I don't think this operation is often enough to warrant a new operator and ( ... | slurp ) feels good enough to me.

@zzamboni
Copy link
Contributor

zzamboni commented Oct 31, 2021

I tend to agree with @xiaq on this one. I am not a big fan of too much magic syntax. $(...) has the advantage of mirroring the POSIX syntax, so it's not something completely new. However, one of the things I like about Elvish is that it normally expects you to be explicit about what you want to do. Adding this would mean there are now two ways to capture output: the existing (...) and the new $(...), and for a newcomer, the difference might not be obvious (e.g. both would behave the same if the enclosed command outputs a single line of text). I think it's best to keep a single output capture syntax, and use the explicit (... | slurp) when you want to get everything in a single string.

@krader1961
Copy link
Contributor

$(...) has the advantage of mirroring the POSIX syntax, so it's not something completely new.

The counter argument is that the unquoted behavior in a POSIX shell depends on the value of $IFS. I would argue that the proposal to introduce $(...) to Elvish essentially assumes $IFS is the empty string in a POSIX shell. Which is effectively never true in a POSIX shell script.

Also, a POSIX shell only has a byte stream between commands on each side of a pipe operator. Whereas Elvish also has a value channel. The Elvish slurp command converts the byte stream to a single object on the value stream. I think the explicit conversion of byte stream input to value stream output using slurp is preferable to magic syntax that is likely to be misinterpreted in light of its meaning in a POSIX shell.

@sauyon
Copy link
Contributor Author

sauyon commented Nov 5, 2021

  • How does behave for value-outputting commands? In your PR the value outputs would be joined by \n but is that intended?

I was originally thinking it would be a stringification of everything, but thinking more on it I'm not sure that's actually what I'd want. Perhaps calling it a single-value capture and doing something like turning multiple values into a list would make more sense?

* Should this preserve trailing newlines?

I'm not sure. While I think in an ideal world it would, I think that would be somewhat unusable given the current standard.

Personally I don't think this operation is often enough to warrant a new operator and ( ... | slurp ) feels good enough to me.

After thinking about this for a bit, I think that my main issue is with the use of (...) in a context that should only ever be single-valued. I agree that in the vast majority of cases the splitting behavior of elvish is perfectly sensible, but personally I feel that it's a bit strange that something as simple as var x = (cmd) is somewhat fragile, especially when using external commands.

I think if the syntax weren't already established I would have made (...) always single-valued somehow, and then had @(...) which seems to me more like it should expand into multiple values in an expression like cmd @(...), but that's probably not realistic at this point.

@krader1961
Copy link
Contributor

personally I feel that it's a bit strange that something as simple as var x = (cmd) is somewhat fragile

Hmmm, I would argue that the absence of | slurp makes it pretty clear you expect cmd to output a single line on the byte stream or a single value. If that isn't true it seems to me to be a good thing that it throws an exception. Sure, elvish could support something like $(cmd) as an alternative to (cmd | slurp) but that eliminates just five characters and adds something else people need to learn about Elvish syntax. Given how seldom slurp seems to be used I don't think the added complexity to the syntax is justified. Of the third-party modules I personally use slurp is most often used like this: var body = (slurp < $file). Something your alternative syntax wouldn't support; i.e., that couldn't be replaced with var body = $($file).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants