noccylabs/preflight

$ git tag
0.1

$ git branch
* master

The PreFlight Scripting Language

Variables and Constants

Local

Local variables are local to the script, not the function/context.

    local varname="value";

Global

Globals are shared between the scripts.

    global varname="value";

Context

The context is generated from data on runtime.

    func "makedoc" {
        exec "pandoc doc/Manual.md -o doc/Manual.{{context.format}}";
    }
    makedoc format="pdf";
    makedoc format="html";

Global functions

echo

Output stuff.

    echo "Hello World!";
    echo "I am {{context.file}}";

include

Includes and evaluates a script.

    include "functions.pfs";

exec

Executes a shell command.

    exec "ls -l /opt" output="all";
    exec "find / -iname '*.tmp' | tee /tmp/tempfiles" output="none" progress=true;

func

Defines a function.

    func "hello" context="local" {
        echo "Hello {{context.who}}";
    }
    hello who="World";

return

Returns from the current context (function)

fail

Returns from the current context and tells the user the reason for doing so.

    func "myexec" {
        if "!context.cmd" {
            fail "No command (cmd) specified";
        }
        exec "{{context.cmd}} {{context.args}}";
    }

abort

Aborts the execution of all script environments on the stack.

    abort "The quality of your code is too low! Fix and try again.";

task

You can define your rules in tasks, which is a sane approach. The tasks will pass unless fail is called or an exec call ends with a non-zero exit code.

    task "Feeding the goats" {
        feed_goats;
    }
    task "Making coffee" {
        fill_water_container;
        grind_beans type="java";
        brew_coffee strength=10.0;
    }

Any attributes are passed on through the context.

    task "Do something that's usually loud" output="none" {
        exec "loud_task.sh";
    }

Conditionals and loops

if/then/else

Both the if block and then then block can have a body. If both have a body, they are both executed in order.

    if "expr" { .. }
    then { .. }
    else { .. }

The state is maintained past the then/else, up until the next if. This can be exploited:

    if "context.output == 'all'";
        echo "Processing stuff...";
    }
    process_stuff;
    then {
        echo "Done processing stuff...";
    }

switch/case

    switch "expr" {
        case "a" { .. }
        case "b" { .. }
    }

each

The each conditional enumerates a provided set of values and evaluates a block passing the value as a local.

    each "foo" "bar" "baz" {
        echo "{{value}}";
    }

    each "Bob" "John" "Rich" as="name" {
        echo "Hello, {{name}}!";
    }