UserDocs
Table of Contents

All that is gold does not glitter,
Not all those who wander are lost;
The old that is strong does not wither,
Deep roots are not reached by the frost.
From the ashes a fire shall be woken,
A light from the shadows shall spring;
Renewed shall be blade that was broken,
The crownless again shall be king.
- J.R.R. Tolkien, The Fellowship of the Ring
Welcome, to the home page of Marko Štajgár
My Crafts & Projects -> flow -> documentation
1. The Flow Shell - User Documentation
1.1. Introduction
Flow is a minimalistic, (trying to be) bloatfree Unix-style shell written in Rust. It embeds a lightweight Lisp-inspired interpreter for shell scripting, with almost zero external dependencies (only glob is imported). Flow combines familiar POSIX command execution with the power of S-expressions for scripting.
1.2. How to install & run
If you don't have rust & cargo installed, I suggest you follow the guide for installation via rustup (optional).
Then clone the repository and simply build & run using cargo run
.
1.3. Main Features currently implemented
- Posix style command execution
- Lisp like syntax (not turing complete at the moment)
2. Running Flow
Flow supports two primary modes: interactive REPL and script-file execution. You can also enable debug mode for detailed tracing.
2.1. REPL Mode
Entering repl doesnt require any additional work aside from simply running the program binary
Syntax:
./PathToTheFlowBinary
Example (in my setup I have exported the binary to PATH):
flow
2.2. File Execution Mode
Pass one or more .flw
script files as arguments, they run in the order provided:
Syntax:
./PathToTheFlowBinary arg1 ... pathToFile ... argN
Example (in my setup I have exported the binary to PATH):
flow ./script1.flw ./script2.flw
2.3. Debug Mode
Include the debug flag anywhere among your arguments to enable tracing. Flow will output:
FUNCTION_ENTER
- function name, module, and argument values upon entry.FUNCTION_INFO
- mid-execution debug messagesFUNCTION_EXIT
- return values upon exit
Syntax:
./PathToTheFlowBinary arg1 ... debug ... argN
Example (in my setup I have exported the binary to PATH):
flow debug
3. Configuration
Configuration of Flow is mainly done through the classic concept of a unix /.*rc
file, in this case a .flowrc
file.
Flow reads thescript named .flowrc
in your home directory by default. If it does not exist, Flow creates it automatically.
3.1. Custom Config Location
Use the rcloc flag as a command line argument to specify a custom path:
Syntax:
./PathToTheFlowBinary arg1 ... rcloc pathToFlowRcFile ... argN
Example (in my setup I have exported the binary to PATH):
flow rcloc ./$HOME/.config/flowConfig/
3.2. Configuration Options
The .flowrc
file is nothing more than a Flow script that is run automatically before any custom command execution, every configuration command/option can be executed also through all execution methods such as the repl
.
Flow reserves these environment variables for its configuration:
PS1
- lets you define a custom prompt.HISTLOCATION
- lets you define a custom location for the.flow_history
file
4. Shell History
In REPL mode, Flow collects session commands in memory and writes them to .flow_history
upon exit.
To customize .flow_history
location, set HISTLOCATION
in .flowrc
or via environment before launching Flow.
5. Flow Shell Syntax
Flow's syntax belongs to the Lisp family, with two recognition modes:
- Inputs beginning with `(` are treated as a single Lisp S-expression.
- All other inputs are parsed as POSIX-style shell commands.
5.1. Comments
Single-line comments start with `;` and continue to end of line:
Syntax:
; The desired comemnt goes here...
Example:
(exec ; First comment ( ls | ; Second comment grep *.rs ) )
5.2. Variables
There are two types of variables supported:
- Environment variables
- Local runtime variables
5.2.1. Environment Variables
One can set/change the desired environment variable with the envar
keyword, where one is obligated to provide the following:
- Variable Name
- Value
Value is evaluated at runtime and can be any Flow lisp expression as long as it evaluates to OS string.
Syntax:
(envar ENVAR_NAME VALUE)
Example:
(envar PS1 "new prompt >")
Retrieving the value is possible only if the variable name is prefixed with $ in the corresponding identifier.
Syntax:
($ENVAR_NAME)
Example:
(envar PS2 $PS1)
5.2.2. Local Variables
One can set the desired local variable with the var
keyword, where one is obligated to provide the following:
- Variable Name
- Value
The value is evaluated at runtime and can be any Flow lisp expression.
Syntax:
(var VAR_NAME VALUE)
Example:
(var newVar "Hello World!")
Retrieving the value back is possible only if the variable name is prefixed with # in the corresponding identifier.
Syntax:
(#NAME)
Example:
(var secondNewVar #newVar)
6. Commands & Features
There are two ways of executing commands, one is simply entering the command name with arguments, pipes, redirects etc. The second one is as a Flow Lisp expression with the exec
keyword.
6.1. Default Shell Mode
This mode of command execution is almost identical to well known shells like bash.
The syntax goes as follows:
command_name arg1 arg2 arg3 ...
Example:
grep #someVariable
6.2. Flow Lisp Mode
Wrap commands in Default Shell Mode in an S-expression with `exec`.
The syntax goes as follows:
(exec (command_name arg1 arg2 arg3 ...))
Example:
(exec ( echo #someVariable ) )
6.3. Globbing
6.4. Piping
Use `|` to pipe stdout to stdin of the next command. Pipelines in Flow are identical to `bash`.
Syntax: The syntax goes as follows:
(exec ( command1_name arg1 arg2 arg3 ... | command2_name arg1 arg2 arg3 ... | ... ))
Example:
(exec ( ls *.md | grep #desiredFiles ))
6.5. I/O Redirection
The redirection of inputs or outputs is done similarly to other well known posix shells, for more info please refer to documentation for bash.
The major difference is that in flow (at this time) only one redirection per command is allowed.
Example:
(exec ( grep Something < textOfSomethings.txt | grep SomethingSpecial > textOfSomethingsSpecial.txt )) ; another command run in default mode ls ?.txt &> listOutput.txt
6.5.1. Input Redirection
Redirecting input opens the file whose name results from the expansion of word for reading on file descriptor 0, or the standard input (file descriptor 0)
Syntax:
command_name arg1 ... < PathToFileWithInput
6.5.2. Output Redirection
Redirecting output opens the file whose name results from the expansion of word for writing on file descriptor 1, or the standard output (file descriptor 1). If the file does not exist it is created, if it does exist it is truncated to zero size.
Syntax:
command_name arg1 ... > PathToFileToOutput
6.5.3. Standard Error Redirection
Redirecting standard error output opens the file whose name results from the expansion of word for writing on file descriptor 2, or the standard error output (file descriptor 2). If the file does not exist it is created, if it does exist it is truncated to zero size.
Syntax:
command_name arg1 ... 2> PathToFileToOutput
6.5.4. Redirecting Standard Output and Standard Error
This construct redirects both the standard output (file descriptor 1) and the standard error output (file descriptor 2) to the file whose name is the expansion of word.
Syntax:
command_name arg1 ... &> PathToFileToOutput