# zargs - Zero-overhead Argument Parser for Zig A type-safe, compile-time command-line argument parser for Zig that uses struct introspection to automatically generate parsers. ## Features - ✅ **Type-safe**: Arguments are defined as struct fields with compile-time type checking - ✅ **Zero runtime overhead**: All metadata extraction happens at compile time - ✅ **Flexible syntax**: Supports `--flag`, `--flag=value`, `-f`, `-f value`, and multi-flags (`-abc`) - ✅ **Rich types**: Bool, integers, strings, enums, lists, and optional types - ✅ **Automatic help**: Generates professional help text from struct metadata - ✅ **Multi-module**: Multiple modules can register arguments with collision detection - ✅ **Memory safe**: No leaks, proper cleanup with `defer` - ✅ **Zero dependencies**: Pure Zig, no external dependencies ## Quick Start ```zig const std = @import("std"); const zargs = @import("zargs"); const Config = struct { verbose: bool = false, output: []const u8 = "output.txt", count: u32 = 10, pub const meta = .{ .verbose = .{ .short = 'v', .help = "Enable verbose output" }, .output = .{ .short = 'o', .help = "Output file path" }, .count = .{ .short = 'c', .help = "Number of items" }, }; }; pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator(); const args = try std.process.argsAlloc(allocator); defer std.process.argsFree(allocator, args); const config = zargs.parse(Config, allocator, args) catch |err| { if (err == error.HelpRequested) return; return err; }; std.debug.print("Output: {s}\n", .{config.output}); } ``` ## Usage ### Define Your Configuration ```zig const Config = struct { // Boolean flag (default: false) verbose: bool = false, // String argument (default: "output.txt") output: []const u8 = "output.txt", // Integer argument (default: 10) count: u32 = 10, // Enum argument (default: .balanced) mode: enum { fast, slow, balanced } = .balanced, // Optional argument (default: null) name: ?[]const u8 = null, // String list (can be repeated or comma-separated) files: []const []const u8 = &[_][]const u8{}, // Add metadata for help text and short flags pub const meta = .{ .verbose = .{ .short = 'v', .help = "Enable verbose output", }, .output = .{ .short = 'o', .help = "Output file path", }, .count = .{ .short = 'c', .help = "Number of items to process", }, .mode = .{ .short = 'm', .help = "Processing mode", }, .name = .{ .help = "Optional name parameter", }, .files = .{ .short = 'f', .help = "Input files (can be repeated)", }, }; }; ``` ### Parse Arguments ```zig // Simple parsing (shows help automatically) const config = try zargs.parse(Config, allocator, args); // Advanced: manual registry for multi-module apps var registry = zargs.ArgumentRegistry.init(allocator); defer registry.deinit(); try registry.registerMetadata(Module1Config, "Module1"); try registry.registerMetadata(Module2Config, "Module2"); try zargs.parseArgv(®istry, args); const mod1 = try zargs.populateStruct(Module1Config, ®istry, allocator); const mod2 = try zargs.populateStruct(Module2Config, ®istry, allocator); ``` ## Command-Line Syntax ### Boolean Flags ```bash ./program --verbose # Sets verbose = true ./program -v # Short form ./program -vdq # Multi-flag (sets verbose, debug, quiet) ``` ### String Arguments ```bash ./program --output=file.txt # With equals ./program --output file.txt # Space-separated ./program -o file.txt # Short form ``` ### Integer Arguments ```bash ./program --count=42 ./program --count 0xFF # Hex supported ./program --count 0b1010 # Binary supported ``` ### Enum Arguments ```bash ./program --mode=fast ./program --mode slow ``` ### List Arguments ```bash ./program --files=a.txt,b.txt,c.txt # Comma-separated ./program --files=a.txt --files=b.txt # Repeated (both work!) ``` ### Help ```bash ./program --help ./program -h ``` ## Supported Types - **Booleans**: `bool` - **Integers**: `u8`, `u16`, `u32`, `u64`, `i8`, `i16`, `i32`, `i64` - **Strings**: `[]const u8` - **Enums**: Any Zig enum type - **Lists**: `[]const []const u8` (string lists) - **Optionals**: `?T` for any supported type `T` ## Help Text Generation zargs automatically generates professional help text: ``` Usage: program [OPTIONS] Options: -h, --help Show this help message -c, --count Number of items to process -m, --mode Processing mode -o, --output Output file path [default: output.txt] -v, --verbose Enable verbose output [default: false] ``` ## Advanced Features ### Collision Detection When multiple modules register the same argument name: - **Compatible** (same type): Allowed, warns - **Incompatible** (different types): Compile error ```zig // Both modules can register --verbose (bool) try registry.registerMetadata(Module1, "Module1"); // has verbose: bool try registry.registerMetadata(Module2, "Module2"); // has verbose: bool - OK! // This would error at compile time: // Module1 has verbose: bool // Module2 has verbose: u32 - COMPILE ERROR! ``` ### Custom Metadata ```zig pub const meta = .{ .field_name = .{ .short = 'x', // Short flag (optional) .help = "Description", // Help text (optional) .required = true, // Override default requirement (optional) }, }; ``` ## Examples See the `examples/` directory for complete examples: - `simple.zig` - Basic single-struct usage - `multi_module.zig` - Multiple modules with shared registry ## Building Requires Zig 0.14 or later (tested with Zig 0.15.2). ```bash zig build zig build test ``` ## API Reference ### Main Functions - `parse(T, allocator, argv)` - Parse arguments into struct T - `parseWithRegistry(T, registry, allocator, argv)` - Parse with existing registry ### Core Types - `ArgumentRegistry` - Central registry for argument metadata - `ArgumentType` - Enum of supported argument types - `ParsedValue` - Tagged union of parsed values - `ArgumentMetadata` - Complete metadata for an argument ### Utilities - `generateHelpText(registry, allocator, program_name)` - Generate help text - `parseArgv(registry, argv)` - Parse argv into registry - `populateStruct(T, registry, allocator)` - Populate struct from parsed values ## Design Philosophy zargs is designed for **game engines and plugin architectures** where: - Arguments are scattered across many modules - Not all modules may load in every run - Comprehensive documentation is still needed - Type safety is non-negotiable ## Version Current version: `0.1.0-dev` ## License [Add your license here] ## Contributing Contributions welcome! Please ensure: - All tests pass (`zig build test`) - No memory leaks (tests check with `std.testing.allocator`) - Code follows existing style - New features have tests and documentation ## Acknowledgments Built with ❤️ in Zig, following best practices from the Zig standard library.