execline
Software
www.skarnet.org

Blocks

You can read the discussion that led to the current block implementation.

A command line (and thus an execline script) is one-dimensional. But a Unix execution flow can be two-dimensional: when two instructions are sequenced, for instance. In that case, we need a way to extract two command lines from one argv. That is precisely what blocks are made for.

execline commands that need more than one linear set of arguments use blocks. For instance, the foreground command needs to spawn a first process, then execute into a second one. It reads the command line for the first process from a block, and the command line for the second process from the rest of the argv. In the following script:

 #!/command/execlineb
 foreground { echo 1 } echo 2
echo 1 is read from a block and spawned; then echo 2 is executed.

execlineb syntax

In execlineb scripts, blocks are delimited by braces - nothing more. They can be nested.

argv syntax

The story is quite different in an argv - or in an execline script, that gets literally translated into an argv. Blocks are not delimited by braces. They are made of quoted arguments and terminated by a single semicolon. A quoted argument begins with a tilda (~). Nested blocks are represented by arguments being quoted several times; a semicolon terminator inside a block gets quoted too.

Actually, the block-reading commands know nothing about braces; they only understand the "quoted arguments + semicolon" syntax. So if you want to use foreground from your shell to sequence echo 1 and echo 2, you will have to write

 $ foreground ~echo ~1 \; echo 2
(since the semicolon is a shell reserved word, it needs to be escaped by a backslash).

You do not really need to quote every argument inside a block in that simple case. The following command works as well:

 $ foreground echo 1 \; echo 2
However, this is bad practice, because it leads to a security hole (the same as in execline-0.x): commands that perform substitution inside a block may produce bare semicolons, which may modify your script's execution flow.
 $ define FOO ';' foreground ~echo '~${FOO}' ~rm ~-rf ~/ \; echo blah
is safe, whereas
 $ define FOO ';' foreground echo '${FOO}' rm -rf / \; echo blah
has very much unwanted results. (Kids, don't try this at home.)

You can use the EXECLINE_STRICT environment variable to check proper block quoting. If that variable contains 1, commands that read blocks will print a warning message everytime they find an unquoted argument inside a block. If that variable contains 2 or more, the command will die instantly.
You can use execlineb's or execline's -w or -W switch to set EXECLINE_STRICT to 1 or 2.