for Shell Scripts
Install basho first.
If you have npm > 5.2.0, you can use the npx command to try basho without installing.
The option -j can be omitted for the first expression.
The option -p avoids printing the final result. I am not sure where you'd need to use it, but it's there.
Working with strings will need quoting, since bash will chew the quotes for itself. So you’ll need to use single quotes around your double quotes.
You can pipe an expression into a subsequent expression. The variable ‘x’ is always used as a placeholder for receiving the previous input.
If an expression has spaces, it is important to quote it. In the following example, see how 'x + 100' is quoted.
Similarly, if an expression contains bash special characters it is necessary to quote them. In the following example, the expression is quotes since '>' is the bash redirection operator.
As a best practice, it is wise to quote all expressions (except maybe the trivially simple).
Lazy evaluation and exit conditions
You may choose to terminate the pipeline with the 'terminate' option -t when a condition is met. Since the pipeline is lazy, further expressions (or bash commands) are not evaluated.
Execute shell commands with the 'execute' option -e. The shell command is expanded as a JS template string, with the variable ‘x’ holding the input from the preceding command in the pipeline. Remember to quote or escape characters which hold a special meaning in your shell, such as \$, >, <, |, () etc.
Tip: Single quotes are far easier to work with, since double quotes will try to expand \$variables inside it.
You can extend the pipeline further after a shell command. The shell command’s output becomes the input for the next command.
basho can receive input via stdin. As always, ‘x’ represents the input.
You can pipe multi-line output from other commands.
There’s nothing stopping you from piping basho's output either.
Importing JS files
You can import a function from a JS file or an npm module with the --import option. The --import option takes two parameters; a filename or module name and an alias for the import. An import is available in all subsequent expressions throughout the pipeline.
Arrays, map, filter, flatMap and reduce
If the input to an expression is an array, the subsequent expression or command is executed for each item in the array. It's the equivalent of a map() function.
An input can also be an object, which you can expand in the template string.
You can use an Array of objects.
Array of arrays, sure.
If the input is an array, basho processes each item one-by-one (like a map() function). But sometimes, you want to process the entire array at once. Use the -a option for this.
Filter arrays with the 'filter' option -f.
Reduce with the 'reduce' option -r. The first parameter is the lambda, the second parameter is the initial value of the accumulator.
There's also the 'flatMap' option -m.
A flatMap can be used to flatten an array of arrays as well.
Btw, you could also access an array index in the template literal as the variable ‘i’ in lambdas and shell command templates.
Arguments and Reusable Expressions
Sometimes you want to pass additional arguments or reuse an expression multiple times in the pipeline. You can define expressions with the 'define' option -d and they get stored as fields in a variable named 'k'. See usage below.
Here's how to use the define option to pass arguments
Here's how to use it for reusable expressions.
Can be used in shell commands as well. Remember to quote though.
Subroutines are mini-pipelines within a parent pipeline. This allows us to define a set of operations which could be repeatedly called for each item.
Subroutines are defined with the --sub option followed by the name of the sub. The sub continues till an --endsub is found. The sub is stored for subsequent usage is the variable 'k'.
Nested Subroutines? Sure.
Named expressions, Seeking and Combining expressions
The 'name' option -n gives a name to the result of the expression, so that you can recall it later with the -s (seek) or -c (combine) options.
The -s option allows you to seek a named result.
The -c option allows you to combine/multiplex streams into an sequence of arrays.
The 'goto' option -g allows you to recurse to a previous named expression. It takes two parameters; (1) an expression name and (2) a predicate which stops the recursion.
Here's an expression that keeps recursing and adding 100 till it exceeds 1000.
Recursion is powerful. For instance, along with a promise that sleeps for a specified time, recursion can use used to periodically run a command. Usage is left to the reader as an exercise.
Multi-line string inputs and JSON Parsing
With the 'string' option --str basho can treat the entire input as a single string with newlines (instead of an array of lines).
If the input is JSON, there's a convenient shortcut so that you don't have to write JSON.parse. The 'json' option --json.
If an JS expression evaluates to a promise, it is resolved before passing it to the next command in the pipeline.
You can add a 'log' option -l anywhere in the pipeline to print the current value. Prints a newline at the end.
The 'write' option -w does the same thing as -l, but without the newline.
You can handle an error with the --error option, and choose to return an arbitrary value in its place. If unhandled, the pipeline is terminated immediately. In the following example, x.split() results in an exception on the second input (10) since a number does have the split() method. The error handler expression replaces the exception with the string 'skipped'.
If the first argument to basho is --ignoreerror, basho will not exit on error. It will simply move to the next item.
The --printerror option works like --ignoreerror, but prints the error.
Note that ignoreerror and printerror must not be preceded by any option except the --import option.
Real world examples
Count the number of occurences of a word in a line of text.
Recursively list all typescript files
Count the number of typescript files
Get the weather in bangalore
Who wrote Harry Potter and the Philosopher's Stone?
Find all git hosted sub directories which might need a pull
Find all git hosted sub directories which need to be pushed to remote
Check if basho version is at least 0.0.43
Here Documents for complex commands
Complex commands require a lot of quoting which makes code ugly. Fortunately, a shell feature called Here Documents hugely simplifies this use case. You can pretty much avoid all quoting!
Note that you need to specify each argument in a separate line (which helps readability as well). And when invoking basho, remember to use quotes around the variable (see example below). Indentation is ignored, so you can use it for formatting.
Asterisks don't get substituted - if you need substitution, use <<EOF instead of << "EOF".
For better legibility in multi-line commands, brackets can help. A line containing an opening or closing bracket should contain nothing else, as in the example below. Brackets cannot be nested.
Typing basho without any parameters does nothing but might make you happy. Or reflective. This of course, is the original purpose of this app.