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

cmd < <{subcmd} produces syntax error #56

Open
jpco opened this issue Apr 19, 2023 · 3 comments
Open

cmd < <{subcmd} produces syntax error #56

jpco opened this issue Apr 19, 2023 · 3 comments

Comments

@jpco
Copy link
Collaborator

jpco commented Apr 19, 2023

This seems like syntax that should be valid, right? Minimal (useless) example:

; cat < <{echo *}
syntax error

Found while thinking about alternatives to #55.

@memreflect
Copy link
Contributor

cat < <{echo *} and echo * > >{cat} should both be (mostly) behaviorally equivalent to %pipe {echo *} 1 0 {cat}, if this worked, and i can't see a good reason to implement this when the net outcome is the same as with a regular pipe.

Another non-sh shell, fish, currently does not have a %writeto equivalent, but it does have %readfrom in the form of cmd (subcmd | psub).
The fish equivalent of cmd < <{subcmd}, i.e. cmd < (subcmd | psub), just happens to work because of how psub works; it isn't intended to be used in that way.

@jpco
Copy link
Collaborator Author

jpco commented May 31, 2023

The difference between cat < <{echo *}, echo * > >{cat}, and echo * | cat come down to which command runs in the local process (for this example, pretend cat is a builtin).

As es works today, echo * | cat runs both commands in subshells (this is what #55 would change if merged). The %readfrom and %writeto based examples, however, run their respective "outer" command in the local shell, which allows more side effects.

You can see this in action by manually "parsing" the syntax down to hook functions:

; a = b
; {a = c; echo foo bar} | rev
rab oof
; echo $a
b
; # {a = c; echo foo bar} > >{rev}
; %writeto _devfd1 {rev} {%create 1 <={%one $_devfd1} {a = c; echo foo bar}}
rab oof
; echo $a
c

I find the whole "use process substitution to work around pipes being executed in a subprocess" thing in bash to be obnoxious, but at least there's some syntax at all for it.

@memreflect
Copy link
Contributor

I can see your reasoning, but %writeto var {cmd > $var} works fine already:

; # Simple example: equivalent of non-working
  #  {a = c; echo foo bar} > >{rev}
; a = b
; %writeto _devfdz {rev} {{a = c; echo foo bar} > $_devfdz}
rab oof
; echo $a
c

And %readfrom var input {cmd < $var} works as well, if you need Bash's lastpipe behavior as proposed in #55:

; # Adapted from PR #55: equivalent of non-working
  #   {for-each @ l{ accum = $accum $l }} < <{cat input}
; fn for-each lambda {
    let (line = ())
      while {!~ <={line = <=%read} ()} {
        $lambda $line
      }
  }
; cat input
one two
three
four
; %readfrom _devfdz {cat input} {{for-each @ l{ accum = $accum $l }} < $_devfdz}
; for (line = $accum)
    echo $line
one two
three
four

I guess my point is that the benefit does not seem worth the trouble involved in modifying the yacc grammar to be able to obtain

%open 0 <={%one
    !NODE:nredir($_devfdX {%readfrom _devfdX input PLACEHOLDER})
} {cmd}

and subsequently rewrite it to

%readfrom _devfdX input {
    %open 0 <={%one $_devfdX} cmd
}

The same would also need to be done for %writeto _devfdX output with %create 1 as well to get cmd > >{output} working of course.

I certainly agree that the syntax and general behavior of the shell is currently too limited to allow for the desired behavior, but i imagine that's one of the best reasons why the functions are available in es: they allow you to do things that otherwise aren't possible.
With es, you're not at the mercy of the shell's syntax and behaviors.

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

2 participants