CLI Applications

41.1 Argument Parsing

Libraries: zig-clap, zig-cli, yazap, flags (comptime struct-based), argzon.

pub fn main() !void {
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var args = try std.process.argsWithAllocator(allocator);
    defer args.deinit();
    _ = args.skip();                                    // program name
    var verbose = false;
    var name: []const u8 = "World";
    while (args.next()) |arg| {
        if (std.mem.eql(u8, arg, "-v") or std.mem.eql(u8, arg, "--verbose")) {
            verbose = true;
        } else if (std.mem.startsWith(u8, arg, "--name=")) {
            name = arg["--name=".len..];
        } else {
            std.debug.print("unknown arg: {s}\n", .{arg});
            std.process.exit(2);
        }
    }
    if (verbose) std.debug.print("verbose on\n", .{});
    std.debug.print("Hello, {s}\n", .{name});
}

41.2 Logging

const log = std.log.scoped(.myapp);
log.info("started with {d} workers", .{4});
log.warn("disk {d}% full", .{91});
log.err("failed: {s}", .{"timeout"});
log.debug("details", .{});              // compiled out above the configured level

pub const std_options: std.Options = .{   // in the root file: configure logging
    .log_level = .info,
    .logFn = myLogFn,
};

41.3 Terminal UX

ANSI colors via escape codes or std.io.tty.Config (std.Io.tty in newer versions), std.Progress (built-in progress reporting, as used by zig build), TUI libraries libvaxis, zigzag, termbox bindings.

Distribution: tiny static binaries cross-compiled for every OS from one machine, installed via GitHub Releases, Homebrew taps, or package managers.