UserDocs

Table of Contents

Bombadil

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:

  1. FUNCTION_ENTER - function name, module, and argument values upon entry.
  2. FUNCTION_INFO - mid-execution debug messages
  3. FUNCTION_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:

  1. PS1 - lets you define a custom prompt.
  2. 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:

  1. Inputs beginning with `(` are treated as a single Lisp S-expression.
  2. 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:

  1. Environment variables
  2. 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:

  1. Variable Name
  2. 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:

  1. Variable Name
  2. 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)
5.2.2.1. Local Variable Types

There ae currently only two types supported:

  1. Integer - a 64 bit unsigned integer.
  2. String - traditional string data type.

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

In the case of Flow, globbing follows the POSIX 2 standard and is identical to using globs wildcard matching, so for more info please refer these manpages.

Example:

(exec ( ls *.md))

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

Author: Marko Štajgár MarkoStajgar

Last Updated: 2025-08-25 Mon 10:32

Emacs 29.4 (Org mode 9.6.15)

Validate