wryun / es-shell

es: a shell with higher-order functions
http://wryun.github.io/es-shell/
Other
307 stars 25 forks source link

Should `%run` be the built-in way binaries are run? #80

Open jpco opened 8 months ago

jpco commented 8 months ago

es has a hook function called %run for fork/exec-ing a binary with the given arguments as its argv. This is cool, but the function isn't actually used by es itself without some hackery to %pathsearch

fn %pathsearch name {
  result %run <={access -n $prog -1e -xf $path} $prog
}

and then potentially doing something to deal with the fact that %whatis bin now returns the ugly

%run /path/to/bin bin

and then feeling sad about the fact that if a user passes in an absolute path, %run just won't be called.

It seems more es-ish to just replace the forkexec() calls in eval() with calls to %run (or maybe fall back to $&run, if %run isn't set). Outside of $&run, eval() is the only place where forkexec() gets called, so this would be a complete implementation of the hook function.

A concrete possibility this enables is the setting of a bash- or zsh-like $_ for any invoked binary (from man bash, this: "the full pathname used to invoke each command executed and placed in the environment exported to that command"), like this:

let (r = $fn-%run)
fn %run cmd args {
  local (_ = $cmd) $r $cmd $args
}
memreflect commented 8 months ago

I like the idea of replacing the forkexec() calls in eval() with %run invocations.

If the result is non-zero from $&run, a custom %run hook might throw an exception, differentiating a nonzero exit code from the richer results made possible by functions in es, which results two nice side effects:

Of course, how such changes interact with if, %background/wait, fork, and %pipe requires investigation, unlike your proposed change that will "just work".

jpco commented 8 months ago

Hmm, those are interesting ideas -- I'd never thought about the idea that with enough runtime support, it could be possible to change the shell's idea of true/false. I'm not sure I'd want to use that shell, but it's certainly interesting to consider :)

Questions of design aside... Unfortunately, exceptions coming from %run don't work with subshells, as you suspect. You might be able to do some hackery to make it work, but I'm not sure it would end up any simpler than the built-in eval_exitonfalse mechanism. I'd be happy to be proven false, though: I have no great love for evalflags/runflags.

The basic challenge is that %run is called exactly in the context the binary is run -- redirections, subshells, and all. It's a highly chaotic set of conditions, and what's worse is that with all the behaviors the binaries themselves can have, it's hard for %run to do much of anything that's robust and known to be independent of the binary's output. I still think it's a good idea to have %run, but it is hard to do a lot with it effectively.