The structure of a Crush command is a space separated list. The first element of the list is the command, the remaining elements are the arguments:
echo 5
git:commit message="This commit is amazing"
arguments to commands can be passed in named or unnamed:
# These calls are equivalent
http "https://example.com/"
http uri="https://example.com/"
Argument mapping works as follows:
- First, all named arguments are assigned.
- Then, each unnamed argument is assigned to the first argument that is currently not assigned a value.
One can also optionally specify that either stray named or stray unnamed arguments should be collected into a dict or list.
Commands do not only accept arguments. They also accept a single value as it's input and produce a single value as output. The input and output of a command is passed down via a so called pipeline:
host:procs | sort cpu
Many commands consume and produce table streams as input and output. These commands run concurrently, so that the whole result need not be produced before the next step in the pipeline begins work.
The separation of concerns between arguments and input to command is that command arguments configure how a the data should be processed, the input is the data to process and the output is where the processed data ends up.
A character sequence enclosed within double quotes become a string literal value,
e.g. "hello"
. Unquoted character sequences containing only A-Z, a-z, 0-9 and _
are also strings, e.g. user
or hat
.
Unquoted character sequences containing a the letters %
or ?
are a glob,
which is an object that can be used for matching strings.
A character sequence enclosed within single quotes become a file literal, e.g.
'Cargo.yaml'
, i.e. a value of the type file
. An unquoted character sequence
that contains a dot (.
) or a slash ('/'), or begins with a tilde (~
) is also
interpreted as a file literal, e.g. Cargo.yaml
or ~/.ssh
.
A character sequence starting with a caret ($
) is intepreted as a variable
lookup. The first sequence in a command (i.e. the command name) is interpreted
as a variable lookup even without the leading $
. Commands live in
the same namespace as all other variables.
Crush features a number of operators to enable users to write mathematical expressions and a few other operators that are a lot easier to read the code.
These are presented below in order of precedence.
operator | Example | Description |
---|---|---|
:= = |
foo := 7 |
Declare a new variable, reassign an existing variable |
and or |
foo:is_file and foo:stat:len > 4096 |
Logical operators |
> >= < <= == != |
foo > 5 |
Compare two values to each other |
+ - |
1+1 |
Addition and subtraction |
* // |
5*5 |
Multiplication and division |
typeof |
typeof foo |
The type of a value |
neg not |
neg 5 |
Numeric and logical negation |
It is often useful to use the output of a crush command as an argument to a different command. To do this, simply put the command within parenthesis:
"Hello, {name}":format name=(user:me:name)
if the command that you run in a substitution returns a stream, the outer command will be run in parallel with the substitution and may in fact finish running first.
This example will create a command that locates all the files in your computer, and assigns
the output stream to a variable. The find
command in this example will block because there
is nothing reading its output.
all_the_files := (find /)
all_the_files | head 1
Unlike other shells, Crush relies heavily on namespaces to separate different commands
and avoid name clashes. Crush uses :
as the namespace operator as well as the member
access operator. (This is because the content of a namespace is simply its members)
A few of the namespaces in Crush are:
- the
crush
namespace, which contains runtime information about the current shell as well as methods and variables that allow you to reconfigure it, - the
user
namespace which contains information about all the users of this system, - the
fd
namespace, which contains information about open file descriptors, e.g. all open network sockets, unix sockets and open files, and - the
host
namespace, which contains information about the current host, including host name, CPU status, memory usage and operating system.