Lua runner with rich builtin stdlib
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
a/README.md

66 lines
3.1 KiB

# `a`
`a` embeds a Lua interpreter and adds a standard library and IO access, so a script can reach the network, a database, the filesystem, and the terminal without additional setup.
```sh
a file.lua # run a script
a # start an interactive REPL
```
Run `a` with a script path to execute it, or with no arguments to start an
interactive REPL.
## The REPL
Running `a` with no arguments starts a read-eval-print loop in the same
sandboxed environment used for scripts, with the full standard library
available. It is convenient for trying out the library or exploring data.
- Bare expressions print their value (`1 + 1` → `2`); tables are pretty-printed
with `utils.dump`.
- Statements that span several lines (a `for` loop, a function body) are
detected as incomplete and keep reading until they parse.
- Async calls such as `os.sleep`, `http.get`, and `task.join` suspend and resume
just as they do in a script — each entry runs on the async executor.
- Line editing and history are provided, with history persisted to
`~/.a_history`. Press Ctrl-D to exit (`os.exit` is not available in the
sandbox).
Each entry is compiled as its own chunk, so a `local` declared on one line is
not visible on the next — assign to a global (drop the `local`) to keep a value
across entries.
## What it is
`a` is not a Lua implementation; it embeds [Lua 5.5](https://www.lua.org/) (via [`mlua`](https://github.com/mlua-rs/mlua)) and adds the parts stock Lua omits. Plain Lua ships almost no standard library and no way to reach the outside world without C modules and a build toolchain. `a` provides a standard library written partly in Rust and partly in Lua, together with IO access.
The result is a single binary that runs a `.lua` file. There is no package manager, build step, or project scaffolding.
## The standard library
The standard library is the main purpose of `a`. Planned surface:
- **Networking** — HTTP client, WebSocket, and MQTT (3.1.1 and 5).
- **SQLite** — access to embedded SQLite databases.
- **Filesystem** — read/write/glob/walk without stock Lua's `io` boilerplate.
- **Terminal UI** — interactive line editing and full-screen TUI, comparable to `ncurses`.
The intent is for the common case to be a single call rather than a multi-step setup.
## How it works
- Embeds Lua 5.5 via `mlua`, on an async core ([`tokio`](https://tokio.rs/)) so IO-heavy scripts don't block.
- A single self-contained binary. No LuaRocks, no make, no virtualenv.
- Scripts run in a **sandboxed** environment modeled on [Luau's safe environment](https://luau.org/sandbox): `io`, `package`, and `debug` are not loaded; `os` is trimmed to its time functions; the bytecode/chunk-loading escape hatches (`load`, `loadfile`, `dofile`, `string.dump`) are removed. The library `a` provides is the supported way to reach the outside world.
- A leading `#!` shebang line is skipped, so scripts can be made executable directly.
## Building
```sh
cargo build --release
# binary at target/release/a
cargo run -- lua/test.lua # run a script during development
```
Requires a Rust toolchain (2024 edition). Lua is vendored and built from source, so no system Lua is needed.