2 ms·
Since there are lots of alternative shells being mentioned, I thought I'd give my tuppence. I want two things from a shell: - Easy process execution, including
by chriswarbo 6y ago
Since there are lots of alternative shells being mentioned, I thought I'd give my tuppence. I want two things from a shell:
- Easy process execution, including branching on exit codes, overriding env vars, providing a working directory, etc. This must support concurrent processes (e.g. pipelines).
- Easy file and stdio management (i.e. piping). This must support streaming (passing along chunks of data as they arrive, rather than gathering them into big intermediate values).
Scripting language REPLs provide everything else I care about (string handling, looping, variables, etc.). Their built-in support for these two things is usually really bad, but libraries can plug that gap. I've tried a few for Python, Haskell, Scala, etc. but the best experience I had was Racket's shell-pipeline library ( https://docs.racket-lang.org/shell-pipeline https://docs.racket-lang.org/shell-pipeline it's also used by the Rash shell that I've not used https://docs.racket-lang.org/rash https://docs.racket-lang.org/rash ). This makes really good use of Racket features, e.g.
- Quasiquoting for mixing commands with normal functions in a simple, sane way
- S-expression syntax works well for shell-like code, e.g. no comma-separation, distinguishing between (unquoted) symbols for names, flags, etc. and quoted strings for data, allowing special characters in names (e.g. to allow things like > in our pipeline), etc. Of course, Racket can be written with I-expressions, sweet-expressions, etc. too, but I've never bothered.
- Stdio redirection works with Racket's existing "ports" mechanism
- Env vars can be managed using Racket "parameters" (dynamically-scoped variables)
(Note that the API seems to have changed a bit since the version I used, so I'm not sure how the new stuff like laziness fits in)