An open API service indexing awesome lists of open source software.

https://github.com/srdjan/zigcli

Advent Of Code 2025: Exploring the "Safe DSL Surface with an Unsafe Engine Under the Hood" Pattern in CLI Parsing
https://github.com/srdjan/zigcli

experimental fun zig

Last synced: about 1 month ago
JSON representation

Advent Of Code 2025: Exploring the "Safe DSL Surface with an Unsafe Engine Under the Hood" Pattern in CLI Parsing

Awesome Lists containing this project

README

          

# zigcli — a tiny type-safe Zig embedded DSL for CLI parsing

This repo is a prototype showing the **"safe DSL surface / unsafe engine under the hood"** pattern applied to CLI parsing.

## What you get

- **Typed results**: `parseOutcome()` returns a tagged union of subcommands with strongly typed structs.
- **No help drift**: help output is derived from the same compile-time spec as parsing.
- **Good diagnostics**: errors carry token index + token + optional suggestion.
- **Lists**: repeatable flags like `--tag a --tag b` become slices (`[]const T`).
- **Arena-owned list storage**: list memory is freed automatically by `Owned.deinit()`.

## Quick start

```bash
zig build run -- serve --host 127.0.0.1 --port 8080 -vv --tag a --tag b
zig build run -- gen outdir --force
zig build run -- serve --help
```

## Example spec

See `examples/mytool.zig`.

```zig
const cli = @import("zigcli");

const Mode = enum { fast, slow };

const App = cli.App(cli.app(.{
.name = "mytool",
.commands = .{
cli.cmd("serve", .{
.about = "Run server",
.opts = .{
cli.opt.str("host", .{ .long="--host", .default="127.0.0.1" }),
cli.opt.u16("port", .{ .long="--port", .short='p', .default=8080 }),
cli.opt.count("verbose", .{ .long="--verbose", .short='v' }),
cli.opt.listStr("tag", .{ .long="--tag", .short='t' }),
cli.opt.enumT("mode", Mode, .{ .long="--mode", .default=.fast }),
},
.rest = cli.rest.capture("extra"),
}),
},
}));
```

## Notes / limitations (MVP)

- List values preserve order and are backed by an arena.
- String list elements (`listStr`) store slices pointing into `argv` (owned by `Owned.args`), so they are safe for the lifetime of `Owned`.
- Suggestions use a small bounded edit-distance with threshold ≤ 2.

## License

MIT (feel free to use/modify).