ori-sh-handler-args/README.md

48 lines
3.8 KiB
Markdown

# Demonstration of shell handler accepting arguments
The current shell handler in Web Origami allows passing an argument to a `.sh` file which will be passed to the child process' stdin. Here, we demonstrate how the shell handler could also take arguments and pass those to the child process.
## Rationale
## Sample and walkthrough
In this example, we're going to filter filenames based on a pattern, using both the stdin mechanism and the argument-passing mechanism.
### Modified `sh_handler.js`
To make this possible, I use a local modified version of the [distribution `sh_handler.js`](https://github.com/WebOrigami/origami/blob/main/language/src/handlers/sh_handler.js) in this directory. It accepts optional further arguments after the first inputText argument. If these are present, they will be passed as additional arguments in the shell invocation. Hence, you can use both stdin and arguments, and if you do _not_ want to use stdin, you need to pass `null` as the first argument.
### Data
two markdown files, `a_pubfile.md` and `anotherfile.md`.
### Handlers: stdin approach
* `allfiles.sh` is a one-liner: `fd -e md`. So it returns all Markdown filenames in this tree. As such, it has no need to use `stdin`. (If you don't have `fd`, you can replace the contents of the script with `find -type f -name "*.md"`.)
* `pubfiles.sh` is another one-liner: `rg '_pub' || true`. It selects only filenames matching the pattern `_pub` from its `stdin`. (If you don't have `ripgrep`, you can replace `rg` with `grep`.)
The purpose of this pair is to demonstrate shell script files as pipe filters: you pass the output of allfiles.sh to the input of pubfiles.sh and get a filtered list. In the shell, that works like this: `sh allfiles.sh | sh pubfiles.sh`. In Ori: `ori "pubfiles.sh allfiles.sh()"`. In `site.ori`:
```
{
allfiles: allfiles.sh()
pubfiles: pubfiles.sh(allfiles)
}
```
## Handlers: Argument approach
The remaining shell file `select.sh` takes an argument and passes it through to `fd` as a match pattern. In the shell: `sh select.sh '_pub'`. Ori cli: `ori "select.sh(null, '_pub')"`. In `site.ori`:
```
{
selectedfiles: pubfiles.sh(null, '_pub')
}
```
## Discussion
Whether or not passing arguments to a shell script makes sense in Origami land is actually a subtle question. An Origami project is an interesting type of program in that a lot of config is usually hard-coded. Origami projects are usually things like websites, where there is a single, specific intended output. You don't reuse the project source to generate lots of different outputs; you add data over time (e.g. blog posts) and then regenerate the same site with the latest data set. Hence, it makes sense if database connection strings, or remote http requests, or other 'config' values are hard-coded in the source.
I want to generate a public and a private version of a static website. I could keep two completely separate `site.ori` files, but that would lead to maintenance problems. So the ability to pass a parameter to the part that selects input files allows me to use one `site.ori`.
Still, this isn't technically necessary, because you could do this parameterization in Ori-land and call two different shell scripts: since they are one-liners, it's not a problem to have one script for the public source and one script for the private source. Where this would be more useful is if a shell script was wrapping some more complex, opaque data source or calculation engine. In such a case, it could be conceivable that a shell script handler would be worth distributing and reusing, in which case it might be worth making it configurable.
Making data sources parameterizable might open Web Origami up to other types of projects, like data pipelines. I don't really have a compelling case, but having this option would allow more experimentation.