{"id":26465510,"url":"https://github.com/kioz-wang/zargs","last_synced_at":"2025-03-19T10:36:28.021Z","repository":{"id":280553984,"uuid":"942387228","full_name":"kioz-wang/zargs","owner":"kioz-wang","description":"Another Comptime-argparse for Zig! Let's start to build your command line!","archived":false,"fork":false,"pushed_at":"2025-03-19T04:49:48.000Z","size":110,"stargazers_count":6,"open_issues_count":6,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-19T05:27:13.977Z","etag":null,"topics":["argument-parser","command-line","positional-arguments","subcommands","zig","zig-package","ziglang"],"latest_commit_sha":null,"homepage":"https://kioz-wang.github.io/zargs/","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kioz-wang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-04T03:10:36.000Z","updated_at":"2025-03-19T04:59:43.000Z","dependencies_parsed_at":"2025-03-19T05:24:12.285Z","dependency_job_id":"9a40e7d4-fc85-4d30-a4ff-2cfe0b51b16d","html_url":"https://github.com/kioz-wang/zargs","commit_stats":null,"previous_names":["kioz-wang/command","kioz-wang/zargs"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kioz-wang%2Fzargs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kioz-wang%2Fzargs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kioz-wang%2Fzargs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kioz-wang%2Fzargs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kioz-wang","download_url":"https://codeload.github.com/kioz-wang/zargs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244409381,"owners_count":20448153,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["argument-parser","command-line","positional-arguments","subcommands","zig","zig-package","ziglang"],"created_at":"2025-03-19T10:36:27.504Z","updated_at":"2025-03-19T10:36:28.013Z","avatar_url":"https://github.com/kioz-wang.png","language":"Zig","funding_links":[],"categories":["Libraries","Language Essentials"],"sub_categories":["Command Line and Argument Parser"],"readme":"# zargs\n\n\u003e other language: [中文简体](README.zh-CN.md)\n\nAnother Comptime-argparse for Zig! Let's start to build your command line!\n\n```zig\nconst std = @import(\"std\");\nconst zargs = @import(\"zargs\");\nconst Command = zargs.Command;\nconst Arg = zargs.Arg;\n\npub fn main() !void {\n    // Like Py3 argparse, https://docs.python.org/3.13/library/argparse.html\n    const remove = Command.new(\"remove\")\n        .opt(\"verbose\", u32, .{ .short = 'v' })\n        .optArg(\"count\", u32, .{ .short = 'c', .argName = \"CNT\", .default = 9 })\n        .posArg(\"name\", []const u8, .{});\n\n    // Like Rust clap, https://docs.rs/clap/latest/clap/\n    const cmd = Command.new(\"demo\").requireSub(\"action\")\n        .about(\"This is a demo intended to be showcased in the README.\")\n        .author(\"KiozWang\")\n        .homepage(\"https://github.com/kioz-wang/zargs\")\n        .arg(Arg.opt(\"verbose\", u32)\n            .short('v')\n            .help(\"help of verbose\"))\n        .sub(Command.new(\"install\")\n            .arg(Arg.posArg(\"name\", []const u8))\n            .arg(\n            Arg.optArg(\"output\", []const u8)\n                .short('o')\n                .long(\"out\"),\n        ))\n        .sub(remove);\n\n    var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;\n    const allocator = gpa.allocator();\n\n    const args = cmd.parse(allocator) catch |err| {\n        std.debug.print(\"Fail to parse because of {any}\\n\", .{err});\n        std.debug.print(\"\\n{s}\\n\", .{cmd.usage()});\n        std.process.exit(1);\n    };\n    defer cmd.destroy(\u0026args, allocator);\n    switch (args.action) {\n        .install =\u003e |a| {\n            std.debug.print(\"Installing {s}\\n\", .{a.name});\n        },\n        .remove =\u003e |a| {\n            std.debug.print(\"Removing {s}\\n\", .{a.name});\n            std.debug.print(\"{any}\\n\", .{a});\n        },\n    }\n    std.debug.print(\"Success to do {s}\\n\", .{@tagName(args.action)});\n}\n```\n\n## Background\n\nAs a system level programming language, there should be an elegant solution for parsing command line arguments.\n\n`zargs` draws inspiration from the API styles of [Py3 argparse](https://docs.python.org/3.13/library/argparse.html) and [Rust clap](https://docs.rs/clap/latest/clap/). It provides all parameter information during editing, reflects the parameter structure and parser at compile time, along with everything else needed, and supports dynamic memory allocation for parameters at runtime.\n\n## Installation\n\n### fetch\n\nGet the latest version:\n\n```bash\nzig fetch --save git+https://github.com/kioz-wang/zargs\n```\n\nTo fetch a specific version (e.g., `v0.14.3`):\n\n```bash\nzig fetch --save https://github.com/kioz-wang/zargs/archive/refs/tags/v0.14.3.tar.gz\n```\n\n#### Version Notes\n\n\u003e See https://github.com/kioz-wang/zargs/releases\n\nThe version number follows the format `vx.y.z`:\n- **x**: Currently fixed at 0. It will increment to 1 when the project stabilizes. Afterward, it will increment by 1 for any breaking changes.\n- **y**: Represents the supported Zig version. For example, `vx.14.z` supports [Zig 0.14.0](https://github.com/ziglang/zig/releases/tag/0.14.0).\n- **z**: Iteration version, where even numbers indicate releases with new features or significant changes (see [milestones](https://github.com/kioz-wang/zargs/milestones)), and odd numbers indicate releases with fixes or minor changes.\n\n### import\n\nUse `addImport` in your `build.zig` (e.g.):\n\n```zig\nconst exe = b.addExecutable(.{\n    .name = \"your_app\",\n    .root_source_file = b.path(\"src/main.zig\"),\n    .target = b.standardTargetOptions(.{}),\n    .optimize = b.standardOptimizeOption(.{}),\n});\nexe.root_module.addImport(\"zargs\", b.dependency(\"zargs\", .{}).module(\"zargs\"));\nb.installArtifact(exe);\n\nconst run_cmd = b.addRunArtifact(exe);\nrun_cmd.step.dependOn(b.getInstallStep());\nif (b.args) |args| {\n    run_cmd.addArgs(args);\n}\n\nconst run_step = b.step(\"run\", \"Run the app\");\nrun_step.dependOn(\u0026run_cmd.step);\n```\n\nAfter importing the `zargs`, you will obtain the iterator (`TokenIter`), command builder (`Command`), and universal parsing function (`parseAny`):\n\n```zig\nconst zargs = @import(\"zargs\");\n```\n\n\u003e For more information and usage details about these three powerful tools, please refer to the [documentation](#APIs).\n\n## Features\n\n### Options, Arguments, Subcommands\n\n#### Terminology\n\n- Option (`opt`)\n    - Single Option (`singleOpt`)\n        - Boolean Option (`boolOpt`), `T == bool`\n        - Accumulative Option (`repeatOpt`), `@typeInfo(T) == .int`\n    - Option with Argument (`argOpt`)\n        - Option with Single Argument (`singleArgOpt`), T\n        - Option with Fixed Number of Arguments (`arrayArgOpt`), `[n]T`\n        - Option with Variable Number of Arguments (`multiArgOpt`), `[]T`\n- Argument (`arg`)\n    - Option Argument (`optArg`) (equivalent to Option with Argument)\n    - Positional Argument (`posArg`)\n        - Single Positional Argument (`singlePosArg`), T\n        - Fixed Number of Positional Arguments (`arrayPosArg`), `[n]T`\n- Subcommand (`subCmd`)\n\n#### Matching and Parsing\n\nMatching and parsing are driven by an iterator. For options, the option is always matched first, and if it takes an argument, the argument is then parsed. For positional arguments, parsing is attempted directly.\n\nFor arguments, T must be the smallest parsable unit: `[]const u8` -\u003e T\n\n- `.int`\n- `.float`\n- `.bool`\n- `.enum`: By default, `std.meta.stringToEnum` is used, but the parse method takes precedence.\n- `.struct`: A struct with a parse method.\n\nIf T is not parsable, a custom parser (`.parseFn`) can be defined for the argument. Obviously, a parser cannot be configured for a single option, as it would be meaningless.\n\n#### Default Values and Optionality\n\nOptions and arguments can be configured with default values (`.default`). Once configured, the option or argument becomes optional.\n\nEven if not explicitly configured, single options always have default values: boolean options default to `false`, and accumulative options default to `0`. Therefore, single options are always optional.\n\n#### Callbacks\n\nA callback (`.callBackFn`) can be configured, which will be executed after matching and parsing.\n\n#### Subcommands\n\nA command cannot have both positional arguments and subcommands simultaneously.\n\n#### Representation\n\nFor the parser, except for accumulative options and options with a variable number of arguments, no option can appear more than once.\n\nVarious representations are primarily supported by the iterator.\n\nOptions are further divided into short options and long options:\n- **Short Option**: `-v`\n- **Long Option**: `--verbose`\n\nOptions with a single argument can use a connector to link the option and the argument:\n- **Short Option**: `-o=hello`, `-o hello`\n- **Long Option**: `--output=hello`, `--output hello`\n\n\u003e Dropping the connector or whitespace for short options is not allowed, as it results in poor readability!\n\nFor options with a fixed number of arguments, connectors cannot be used, and all arguments must be provided at once. For example, with a long option:\n```bash\n--files f0 f1 f2 # [3]const T\n```\n\nOptions with a variable number of arguments are similar to options with a single argument but can appear multiple times, e.g.:\n```bash\n--file f0 -v --file=f1 --greet # []const T\n```\n\nMultiple short options can share a prefix, but if an option takes an argument, it must be placed last, e.g.:\n```bash\n-Rns\n-Rnso hello\n-Rnso=hello\n```\n\nOnce a positional argument appears, the parser informs the iterator to only return positional arguments, even if the arguments might have an option prefix, e.g.:\n```bash\n-o hello a b -v # -o is an option with a single argument, so a, b, -v are all positional arguments\n```\n\nAn option terminator can be used to inform the iterator to only return positional arguments, e.g.:\n```bash\n--output hello -- a b -v\n```\n\nDouble quotes can be used to avoid iterator ambiguity, e.g., to pass a negative number `-1`, double quotes must be used:\n```bash\n--num \\\"-1\\\"\n```\n\n\u003e Since the shell removes double quotes, escape characters are also required! If a connector is used, escaping is unnecessary: `--num=\"-1\"`.\n\n### Compile-Time Command Construction\n\nAs shown in the example at the beginning of the article, command construction can be completed in a single line of code through chaining.\n\n#### CallBackFn for Command\n\n```zig\ncomptime cmd.callBack(struct {\n        const C = cmd;\n        fn f(_: *C.Result()) void {\n            std.debug.print(\"CallBack of {s}\\n\", .{ C.name });\n        }\n    }.f);\n```\n\n### Compile-Time Parser Generation\n\n```zig\nconst args = try cmd.parse(allocator);\ndefer cmd.destroy(\u0026args, allocator);\n```\n\nSimply call `parse` to generate the parser and argument structure. This method internally creates a system iterator, which is destroyed after use.\n\nAdditionally, `parseFrom` supports passing a custom iterator and optionally avoids using a memory allocator. If no allocator is used, there is no need to defer destroy.\n\n#### Retrieving Remaining Command-Line Arguments\n\nWhen the parser has completed its task, if you still need to handle the remaining arguments manually, you can call the iterator's `nextAllBase` method.\n\nIf further parsing of the arguments is required, you can use the `parseAny` function.\n\n#### Versatile iterators\n\nFlexible for real and test scenarios\n\n- System iterator (`init`): get real command line arguments.\n- General iterator (`initGeneral`): splits command line arguments from a one-line string.\n- Line iterator (`initLine`): same as regular iterator, but you can specify delimiters.\n- List iterator (`initList`): iterates over a list of strings.\n\nShort option prefixes (`-`), long option prefixes (`--`), connectors (`=`), option terminators (`--`) can be customized for iterators (see [presentation](#presentation) for usage scenarios).\n\n### Compile-Time Usage and Help Generation\n\n```zig\n_ = cmd.usage();\n_ = cmd.help();\n```\n\n## APIs\n\nSee https://kioz-wang.github.io/zargs/#doc.command.Command\n\n## Examples\n\n### builtin\n\n\u003e Look at [here](examples/)\n\nTo build all examples:\n\n```bash\nzig build examples\n```\n\nTo list all examples (all step prefixed `ex-` are examples):\n\n```bash\nzig build -l\n```\n\nTo execute an example:\n\n```bash\nzig build ex-01.add -- -h\n```\n\n### more\n\n\u003e Welcome to submit PRs to link your project that use `zargs`!\n\nMore real-world examples are coming!\n\n- [filepacker](https://github.com/kioz-wang/filepacker/blob/master/src/main.zig)\n\n## License\n\n[MIT](LICENSE) © Kioz Wang\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkioz-wang%2Fzargs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkioz-wang%2Fzargs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkioz-wang%2Fzargs/lists"}