Writing Scripts
Script Basics
Section titled “Script Basics”lash scripts use the .lash file extension and are run with:
lash myscript.lashNo shebang needed, though you can add one if you want to make scripts directly executable:
#!/usr/bin/env lash
echo "hello from lash"The usage Block
Section titled “The usage Block”Declare expected arguments with a usage block. lash handles parsing, type validation, constraint checking, and --help generation for you:
usage { Deploy a service to the specified environment. --- service: string - Service name to deploy env: string - Target environment [staging, production] optional port: int = 8080 - Port to bind optional dry_run: bool = false - Preview without deploying}
echo "deploying $service to $env on port $port"if dry_run { echo "(dry run -- no changes made)"}The block has two sections separated by ---:
- Description — free-form text describing the script.
- Argument definitions — one per line.
Arguments without optional are positional and required. Arguments with optional are passed as --name value flags.
Running It
Section titled “Running It”lash deploy.lash myapp staginglash deploy.lash myapp production --port 9090lash deploy.lash myapp staging --dry_run truelash deploy.lash --help--help auto-generates formatted help output from the usage block.
Supported Types
Section titled “Supported Types”| Type | Description | Example |
|---|---|---|
string | Arbitrary text | "hello" |
int | Integer number | 42 |
float | Floating-point number | 3.14 |
bool | Boolean flag | true |
semver | Semantic version string | "1.2.3" |
Constraints
Section titled “Constraints”Restrict argument values beyond type checking:
usage { Process data files. --- format: string - Output format [json, csv, xml] quality: int - Quality level 1..100 name: string - Identifier /^[a-z][a-z0-9_]+$/}- Enum:
[val1, val2, val3]— value must be one of the listed options. - Regex:
/pattern/— value must match the pattern. - Range:
min..max— numeric value must be in the inclusive range.
Validation Errors
Section titled “Validation Errors”When arguments fail validation, lash produces human-friendly messages indicating which argument failed, the expected type or constraint, and what was provided.
Special Variables
Section titled “Special Variables”| Variable | Description |
|---|---|
$0 | Path to the current script |
$1-$N | Positional arguments by index |
$# | Number of arguments passed |
$@ | All arguments as a list |
echo "script: $0"echo "first arg: $1"echo "total args: $#"
for arg in $@ { echo " arg: $arg"}Unit Tests
Section titled “Unit Tests”lash scripts can contain inline unit tests using unittest blocks. Tests are ignored during normal execution and only run with the --test flag.
fn add(a, b) { a + b}
fn clamp(val, lo, hi) { if val < lo { lo } else if val > hi { hi } else { val }}
# adds two positive numbersunittest { let result = add(2, 3) result.must.equal(5)}
# adds negative numbersunittest { add(-1, -2).must.equal(-3)}
# clamps value above maximumunittest { clamp(150, 0, 100).must.equal(100)}
# clamps value below minimumunittest { clamp(-5, 0, 100).must.equal(0)}
# preserves value within rangeunittest { clamp(50, 0, 100).must.equal(50)}The comment immediately before a unittest block becomes the test name.
Assertion Methods
Section titled “Assertion Methods”The .must property is available on any value and returns an assertion proxy:
| Assertion | Description |
|---|---|
.must.equal(expected) | Value equality (string comparison) |
.must.notEqual(expected) | Value inequality |
.must.beGreaterThan(expected) | Numeric greater-than |
.must.beLessThan(expected) | Numeric less-than |
.must.contain(value) | String/list contains |
.must.startWith(value) | String starts with |
.must.endWith(value) | String ends with |
Override the default failure message with .because("reason"):
result.must.equal(42).because("calculation should return 42")Note that equal() uses string comparison. 5.must.equal(5.0) fails because "5" != "5.0". Compare values of the same type.
Running Tests
Section titled “Running Tests”lash script.lash --testOutput:
[PASS] adds two positive numbers[PASS] adds negative numbers[PASS] clamps value above maximum[PASS] clamps value below minimum[PASS] preserves value within range
5 tests: 5 passed, 0 failedA failed assertion stops the current test but does not abort remaining tests. Each unittest block runs in a fresh child scope — tests cannot affect each other.
Verbose Output
Section titled “Verbose Output”Combine with --log-verbose to see test names printed before execution:
lash script.lash --test --log-verbose