|
|
||
|---|---|---|
| .gitignore | ||
| README.md | ||
| a_pubfile.md | ||
| allfiles.sh | ||
| anotherfile.md | ||
| config.ori | ||
| package-lock.json | ||
| package.json | ||
| pubfiles.sh | ||
| select.sh | ||
| sh_handler.js | ||
| site.ori | ||
README.md
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 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.shis a one-liner:fd -e md. So it returns all Markdown filenames in this tree. As such, it has no need to usestdin. (If you don't havefd, you can replace the contents of the script withfind -type f -name "*.md".)pubfiles.shis another one-liner:rg '_pub' || true. It selects only filenames matching the pattern_pubfrom itsstdin. (If you don't haveripgrep, you can replacergwithgrep.)
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.