Clarp: command line parsers derived from struct and union types

https://github.com/travisstaloch/clarp

Just wanted to share a command line parser i was working on recently (yes another one). This one takes a struct or union declaration and creates a parser. I’ll keep it short and just share some code and output from the project readme.

One neat thing about this one is that its ‘Usage’ messages are context aware similar to the zig compiler. So a different message is shown when you run exe help vs exe cmd1 help. And it shows a diagnostic message on parse errors. Examples below.

parser definition - entire file

const std = @import("std");
const clarp = @import("clarp");

pub fn main() !void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const allocator = arena.allocator();

    const ArgParser = clarp.Parser(union(enum) {
        cmd1: struct {
            foo: []const u8,
            pub const clarp_options = clarp.Options(@This()){
                .fields = .{
                    .foo = .{ .desc = "Foo desc." },
                },
            };
        },
        cmd2: struct { enum { a, b } = .a },
        pub const clarp_options = clarp.Options(@This()){
            .fields = .{
                .cmd1 = .{ .desc = "Cmd1 desc.", .short = "c1" },
                .cmd2 = .{ .desc = "Cmd2 desc.", .short = "c2" },
            },
        };
    }, .{});


    const args = try std.process.argsAlloc(allocator);
    const parsed = ArgParser.parse(args, .{
        .err_writer = std.io.getStdErr().writer().any(),
    }) catch |e| switch (e) {
        error.HelpShown => return,
        else => return e,
    };
    std.debug.print("{}\n", .{parsed});
}

‘root’ usage:

$ zig-out/bin/testexe help
Usage: testexe [command]

Commands:

  cmd1, c1            Cmd1 description.
  cmd2, c2            Cmd2 description.

General Options:

  help, --help, -h    Print command specific usage.

‘cmd1’ usage:

$ zig-out/bin/testexe cmd1 help
Usage: testexe cmd1 [options]

  Cmd1 description.

Options:

  --foo: string       Foo description.

General Options:

  help, --help, -h    Print command specific usage.

unknown command diagnostics

$ zig-out/bin/testexe foo
Usage: testexe [command]

Commands:

  cmd1, c1            Cmd1 description.
  cmd2, c2            Cmd2 description.

General Options:

  help, --help, -h    Print command specific usage.

error at argument 1: foo
                     ^~~
error: UnknownCommand
#... stack trace omitted
4 Likes