ziglang/zig
261
5.9k
Fork
You've already forked zig
763

std: introduce std.cli, automatically parse command-line arguments into a second "juicy main" parameter #35304

Open
castholm wants to merge 24 commits from castholm/zig:cli-args-parser into master
pull from: castholm/zig:cli-args-parser
merge into: ziglang:master
ziglang:master
ziglang:elfv2
ziglang:spork8
ziglang:restricted
ziglang:0.16.x
ziglang:panic-rewrite
ziglang:parking-futex-lockfree
ziglang:windows-Io-cleanup
ziglang:Io-watch
ziglang:ParseCommandLineOptions
ziglang:windows-async-files
ziglang:poll-ring
ziglang:debug-file-leaks-differently
ziglang:debug-file-leaks
ziglang:ProcessPrng
ziglang:elfv2-dyn
ziglang:jobserver
ziglang:threadtheft
ziglang:io-threaded-no-queue
ziglang:0.15.x
ziglang:Io.net
ziglang:comptime-allocator
ziglang:restricted-function-pointers
ziglang:cli
ziglang:wasm-linker-writer
ziglang:wrangle-writer-buffering
ziglang:sha1-stream
ziglang:async-await-demo
ziglang:fixes
ziglang:0.14.x
ziglang:ast-node-methods
ziglang:macos-debug-info
ziglang:make-vs-configure
ziglang:fuzz-macos
ziglang:sans-aro
ziglang:ArrayList-reserve
ziglang:incr-bug
ziglang:llvm-ir-nosanitize-metadata
ziglang:ci-tarballs
ziglang:ci-scripts
ziglang:threadpool
ziglang:0.12.x
ziglang:new-pkg-hash
ziglang:json-diagnostics
ziglang:more-doctests
ziglang:rework-comptime-mutation
ziglang:0.11.x
ziglang:ci-perf-comment
ziglang:stage2-async
ziglang:0.10.x
ziglang:autofix
ziglang:0.9.x
ziglang:aro
ziglang:hcs
ziglang:0.8.x
ziglang:0.7.x
Contributor
Copy link

Implements #30677 (based roughly on the design outlined in this comment)
Implements #24510 (the second half of the original "juicy main" proposal)

This PR introduces APIs for parsing command-line arguments, situated underneath the new namespace std.cli.

std.cli.ArgsParser, automatic parsing into a second "juicy main" parameter

std.cli.ArgsParser is a minimal, opinionated, high-level API for parsing a process's arguments into a struct instance. While it exists as a regular API that can be called from code, in practice users will be more likely to use it indirectly by declaring a "juicy main" function with a second parameter.

Below is a simple example program that will automatically parse a command-line invocation like program_name https://server.example.com --poll-interval 30 --debug:

// User-defined structconstArgs=struct{server:[:0]constu8,@"--poll-interval":i32=60,@"--debug":bool=false,};pubfnmain(init:std.process.Init,args:Args)!void{// ...}

Fields whose names begin with @"--" are considered to be options and receive their values from the command line via --name=value or --name value. All other fields are considered to be positional arguments and receive their values from the command line in the same order they are declared.

Supported field types are integers (e.g. i32), floats (e.g. f64), enums (e.g. enum { red, green, blue }) and strings ([:0]const u8, with or without a sentinel), as well as optionals (?T) and slices ([]T) of the aforementioned types. Option fields additionally support void and bool (and their optional equivalents ?void and ?bool).

The API automatically handles printing of usage error messages in response to incorrect usage. It also automatically handles the -h/--help option (and --version option, if applicable) by generating help text, which can be customized by declaring pub const @"--help": std.cli.Help(T):

constArgs=struct{op:enum{sum,min,max},first_value:i32,rest_values:[]consti32,@"--output":?[:0]constu8,@"--pretty":bool=true,@"--verbose":?void,pubconst@"--help":std.cli.Help(Args)=.{.command_name="calculatinator",.description="Calculates numerical properties of sequences of numbers.",.args=.{.op=.{.display="(sum|min|max)",.description="Numerical property of interest"},.first_value=.{.display="<value>...",.description="Integer values"},.rest_values=.{.hidden=true},.@"--output"=.{.display="<file>",.description="Output to a file instead of stdout"},.@"--pretty"=.{.description="Pretty-print output"},.@"--verbose"=.{.description="Output verbose diagnostics to stderr"},},};pubconst@"--version":std.SemanticVersion=.{.major=1,.minor=2,.patch=0};};pubfnmain(init:std.process.Init,args:Args)!void{// ...}

Screenshot from 2026年05月13日 02-28-32

(Plaintext --help output)

Usage: calculatinator [<option>...] (sum|min|max) <value>...
Calculates numerical properties of sequences of numbers.
Arguments:
 (sum|min|max) Numerical property of interest
 <value>... Integer values
Options:
 --output=<file> Output to a file instead of stdout
 --[no-]pretty Pretty-print output
 --verbose Output verbose diagnostics to stderr
 -h, --help Print this help and exit
 --version Print version and exit

std.cli.ArgsParser is intentionally designed to be simple and straight to the point, offloading the responsibility of parsing options and positional arguments on the command line into primitives, so that users can quickly get into action and focus on writing the code that makes their applications unique.

Extensibility or customizability are explicit non-goals. It is, for example, not possible customize the parser's behavior or parse custom types, and only long options names like --foo are supported, not short aliases like -f. The goal is to provide a simple and intuitive interface for receiving program arguments via the command line, which is something that many programs will eventually find themselves needing to do, even if they are not fully-fledged CLIs. Users developing more sophisticated CLIs will probably need to opt out of using this API and instead parse the process's arguments via other means. std.cli.ArgsTokenizer, described in more detail below, may assist with such endeavors.

std.cli.ArgsTokenizer (lower level getopt_long-style iterator API)

std.cli.ArgsTokenizer is a lower level API that tokenizes/splits an []const []const u8 argument vector into positional arguments and options based on a user-specified set of recognized options. It is roughly equivalent in functionality and behavior to getopt_long, the granddaddy of all parsers which established the de-facto command-line option parsing behavior.

Developers of advanced CLIs whose needs cannot be fulfilled by std.cli.ArgsParser are encouraged to give std.cli.ArgsTokenizer a try and see if it can serve as a foundational building block for their custom parsing approaches. It handles all standard forms of options and option-arguments (-fbar, -f bar, --foo=bar, --foo bar), stacked short options (-xyzfbar), the -- end-of-options delimiter and other de-facto conventions. It exposes two different variants of its functions, one for statically known sets of options and a second for runtime-known sets, and an important detail about its design is that the set of options can be swapped out mid-iteration for tasks like parsing subcommands.

testArgsTokenizer{constOption=union(enum){@"--amend":void,@"-m":[]constu8,@"--message":[]constu8,};varamend:bool=false;varmessage:?[]constu8=null;varpositionals:std.ArrayList([]constu8)=.empty;deferpositionals.deinit(std.testing.allocator);constargs:[]const[]constu8=&.{"git","commit","--amend","-mFix bugs"};vartokenizer:std.cli.ArgsTokenizer=.init(args);constprogram_name=tokenizer.nextPositional();while(tokenizer.next(Option))|token|switch(token){.option=>|option|switch(option){.@"--amend"=>{amend=true;},.@"-m",.@"--message"=>|arg|{message=arg;},},.end_of_options=>{},.positional=>|arg|{trypositionals.append(std.testing.allocator,arg);},.invalid_option=>|invalid|{returninvalid.err;},};trystd.testing.expectEqualStrings("git",program_nameorelse"");trystd.testing.expectEqual(1,positionals.items.len);trystd.testing.expectEqualStrings("commit",positionals.items[0]);trystd.testing.expectEqual(true,amend);trystd.testing.expectEqualStrings("Fix bugs",messageorelse"");}

std.cli.ArgsTokenizer is used internally by std.cli.ArgsParser. I also believe that the tokenizer API is powerful/flexible enough that it could replace/enhance significant portions of the manual argument parsing that is performed inside the Zig compiler itself.

Pre-merge checklist

  • Port all of the compiler's internal tools to these APIs (those underneath tools/; not the compiler itself)
  • Properly document std.cli.ArgsParser with doc comments that clearly describe the parser's behavior and any relevant restrictions
  • Add more tests for std.cli.ArgsParser, both in the form of test declarations and standalone tests
  • Implement subcommand parsing (via union(enum))

Breaking changes

  • Relatively minor, but std.fmt.parseInt() and std.fmt.parseUnsigned() now reject inputs that contain consecutive underscores, e.g. 1_2__3 or 0xffff__ff80. This is for consistency with std.fmt.parseFloat(), and with Zig itself.

Follow-up tasks

Should this PR be merged, I also intend to open issues proposing the following changes to std:

  • Move std.Io.Terminal to std.cli.Terminal
  • Add more styles (e.g. italic) to std.cli.Terminal.Color
  • Enhance std.cli.Terminal with functionality for detecting the terminal's width and rendering text with word wrapping (intended for rendering help text)
Implements #30677 (based roughly on [the design outlined in this comment](https://codeberg.org/ziglang/zig/issues/30677#issuecomment-13545359)) Implements [#24510](https://github.com/ziglang/zig/issues/24510#:~:text=%2C%0A%20%20%20%20%20%20%20%20//%20...%0A%20%20%20%20%7D%2C%0A%7D%3B-,The%20second%20arg,-is%20user%2Ddefined) (the second half of the original "juicy main" proposal) This PR introduces APIs for parsing command-line arguments, situated underneath the new namespace `std.cli`. ## `std.cli.ArgsParser`, automatic parsing into a second "juicy main" parameter `std.cli.ArgsParser` is a minimal, opinionated, high-level API for parsing a process's arguments into a struct instance. While it exists as a regular API that can be called from code, in practice users will be more likely to use it indirectly by declaring a "juicy main" function with a second parameter. Below is a simple example program that will automatically parse a command-line invocation like `program_name https://server.example.com --poll-interval 30 --debug`: ```zig // User-defined struct const Args = struct { server: [:0]const u8, @"--poll-interval": i32 = 60, @"--debug": bool = false, }; pub fn main(init: std.process.Init, args: Args) !void { // ... } ``` Fields whose names begin with `@"--"` are considered to be options and receive their values from the command line via `--name=value` or `--name value`. All other fields are considered to be positional arguments and receive their values from the command line in the same order they are declared. Supported field types are integers (e.g. `i32`), floats (e.g. `f64`), enums (e.g. `enum { red, green, blue }`) and strings (`[:0]const u8`, with or without a sentinel), as well as optionals (`?T`) and slices (`[]T`) of the aforementioned types. Option fields additionally support `void` and `bool` (and their optional equivalents `?void` and `?bool`). The API automatically handles printing of usage error messages in response to incorrect usage. It also automatically handles the `-h`/`--help` option (and `--version` option, if applicable) by generating help text, which can be customized by declaring `pub const @"--help": std.cli.Help(T)`: ```zig const Args = struct { op: enum { sum, min, max }, first_value: i32, rest_values: []const i32, @"--output": ?[:0]const u8, @"--pretty": bool = true, @"--verbose": ?void, pub const @"--help": std.cli.Help(Args) = .{ .command_name = "calculatinator", .description = "Calculates numerical properties of sequences of numbers.", .args = .{ .op = .{ .display = "(sum|min|max)", .description = "Numerical property of interest" }, .first_value = .{ .display = "<value>...", .description = "Integer values" }, .rest_values = .{ .hidden = true }, .@"--output" = .{ .display = "<file>", .description = "Output to a file instead of stdout" }, .@"--pretty" = .{ .description = "Pretty-print output" }, .@"--verbose" = .{ .description = "Output verbose diagnostics to stderr" }, }, }; pub const @"--version": std.SemanticVersion = .{ .major = 1, .minor = 2, .patch = 0 }; }; pub fn main(init: std.process.Init, args: Args) !void { // ... } ``` ![Screenshot from 2026年05月13日 02-28-32](/attachments/55d53f7b-6935-4fb1-b884-aaa129af458e) <details><summary> (Plaintext `--help` output) </summary> ``` Usage: calculatinator [<option>...] (sum|min|max) <value>... Calculates numerical properties of sequences of numbers. Arguments: (sum|min|max) Numerical property of interest <value>... Integer values Options: --output=<file> Output to a file instead of stdout --[no-]pretty Pretty-print output --verbose Output verbose diagnostics to stderr -h, --help Print this help and exit --version Print version and exit ``` </details> `std.cli.ArgsParser` is intentionally designed to be simple and straight to the point, offloading the responsibility of parsing options and positional arguments on the command line into primitives, so that users can quickly get into action and focus on writing the code that makes their applications unique. Extensibility or customizability are explicit non-goals. It is, for example, not possible customize the parser's behavior or parse custom types, and only long options names like `--foo` are supported, not short aliases like `-f`. The goal is to provide a simple and intuitive interface for receiving program arguments via the command line, which is something that many programs will eventually find themselves needing to do, even if they are not fully-fledged CLIs. Users developing more sophisticated CLIs will probably need to opt out of using this API and instead parse the process's arguments via other means. `std.cli.ArgsTokenizer`, described in more detail below, may assist with such endeavors. ## `std.cli.ArgsTokenizer` (lower level `getopt_long`-style iterator API) `std.cli.ArgsTokenizer` is a lower level API that tokenizes/splits an `[]const []const u8` argument vector into positional arguments and options based on a user-specified set of recognized options. It is roughly equivalent in functionality and behavior to [`getopt_long`](https://sourceware.org/glibc/manual/latest/html_node/Getopt-Long-Options.html), the granddaddy of all parsers which established the de-facto command-line option parsing behavior. Developers of advanced CLIs whose needs cannot be fulfilled by `std.cli.ArgsParser` are encouraged to give `std.cli.ArgsTokenizer` a try and see if it can serve as a foundational building block for their custom parsing approaches. It handles all standard forms of options and option-arguments (`-fbar`, `-f bar`, `--foo=bar`, `--foo bar`), stacked short options (`-xyzfbar`), the `--` end-of-options delimiter and other de-facto conventions. It exposes two different variants of its functions, one for statically known sets of options and a second for runtime-known sets, and an important detail about its design is that the set of options can be swapped out mid-iteration for tasks like parsing subcommands. ```zig test ArgsTokenizer { const Option = union(enum) { @"--amend": void, @"-m": []const u8, @"--message": []const u8, }; var amend: bool = false; var message: ?[]const u8 = null; var positionals: std.ArrayList([]const u8) = .empty; defer positionals.deinit(std.testing.allocator); const args: []const []const u8 = &.{ "git", "commit", "--amend", "-mFix bugs" }; var tokenizer: std.cli.ArgsTokenizer = .init(args); const program_name = tokenizer.nextPositional(); while (tokenizer.next(Option)) |token| switch (token) { .option => |option| switch (option) { .@"--amend" => { amend = true; }, .@"-m", .@"--message" => |arg| { message = arg; }, }, .end_of_options => {}, .positional => |arg| { try positionals.append(std.testing.allocator, arg); }, .invalid_option => |invalid| { return invalid.err; }, }; try std.testing.expectEqualStrings("git", program_name orelse ""); try std.testing.expectEqual(1, positionals.items.len); try std.testing.expectEqualStrings("commit", positionals.items[0]); try std.testing.expectEqual(true, amend); try std.testing.expectEqualStrings("Fix bugs", message orelse ""); } ``` `std.cli.ArgsTokenizer` is used internally by `std.cli.ArgsParser`. I also believe that the tokenizer API is powerful/flexible enough that it could replace/enhance significant portions of the manual argument parsing that is performed inside the Zig compiler itself. ## Pre-merge checklist - [x] Port all of the compiler's internal tools to these APIs (those underneath `tools/`; not the compiler itself) - [x] Properly document `std.cli.ArgsParser` with doc comments that clearly describe the parser's behavior and any relevant restrictions - [x] Add more tests for `std.cli.ArgsParser`, both in the form of `test` declarations and standalone tests - [x] Implement subcommand parsing (via `union(enum)`) ## Breaking changes - Relatively minor, but `std.fmt.parseInt()` and `std.fmt.parseUnsigned()` now reject inputs that contain consecutive underscores, e.g. `1_2__3` or `0xffff__ff80`. This is for consistency with `std.fmt.parseFloat()`, and with Zig itself. ## Follow-up tasks Should this PR be merged, I also intend to open issues proposing the following changes to `std`: - Move `std.Io.Terminal` to `std.cli.Terminal` - Add more styles (e.g. italic) to `std.cli.Terminal.Color` - Enhance `std.cli.Terminal` with functionality for detecting the terminal's width and rendering text with word wrapping (intended for rendering help text)
Contributor
Copy link

I can't help it, but I REALLY dislike the struct with field names like that. That would prevent me from using this.

I can't help it, but I REALLY dislike the struct with field names like that. That would prevent me from using this.
castholm force-pushed cli-args-parser from c1d6de6d7b
All checks were successful
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / x86_64-netbsd-release (pull_request) Successful in 41m23s
ci / x86_64-openbsd-release (pull_request) Successful in 43m38s
ci / x86_64-netbsd-debug (pull_request) Successful in 44m54s
ci / x86_64-freebsd-debug (pull_request) Successful in 45m9s
ci / x86_64-freebsd-release (pull_request) Successful in 45m41s
ci / x86_64-windows-release (pull_request) Successful in 47m7s
ci / x86_64-windows-debug (pull_request) Successful in 51m16s
ci / x86_64-openbsd-debug (pull_request) Successful in 52m34s
ci / aarch64-macos-release (pull_request) Successful in 1h0m54s
ci / x86_64-linux-debug (pull_request) Successful in 1h7m51s
ci / aarch64-macos-debug (pull_request) Successful in 1h10m43s
ci / aarch64-linux-release (pull_request) Successful in 1h26m19s
ci / s390x-linux-release (pull_request) Successful in 1h32m11s
ci / loongarch64-linux-release (pull_request) Successful in 1h42m30s
ci / powerpc64le-linux-release (pull_request) Successful in 2h15m49s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 2h16m17s
ci / x86_64-linux-release (pull_request) Successful in 2h31m52s
ci / aarch64-linux-debug (pull_request) Successful in 2h37m36s
ci / s390x-linux-debug (pull_request) Successful in 2h39m3s
ci / loongarch64-linux-debug (pull_request) Successful in 2h50m51s
ci / powerpc64le-linux-debug (pull_request) Successful in 4h2m25s
ci / aarch64-freebsd-debug (pull_request) Successful in 3h55m57s
ci / aarch64-freebsd-release (pull_request) Successful in 2h55m36s
ci / aarch64-netbsd-debug (pull_request) Successful in 4h53m33s
ci / aarch64-netbsd-release (pull_request) Successful in 3h59m5s
to 280a6f9a85
Some checks failed
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / aarch64-freebsd-release (pull_request) Has been cancelled
ci / aarch64-netbsd-debug (pull_request) Has been cancelled
ci / aarch64-netbsd-release (pull_request) Has been cancelled
ci / x86_64-freebsd-debug (pull_request) Has been cancelled
ci / x86_64-openbsd-release (pull_request) Has been cancelled
ci / x86_64-freebsd-release (pull_request) Has been cancelled
ci / x86_64-openbsd-debug (pull_request) Has been cancelled
ci / x86_64-netbsd-debug (pull_request) Has been cancelled
ci / x86_64-netbsd-release (pull_request) Has been cancelled
ci / x86_64-windows-debug (pull_request) Has been cancelled
ci / aarch64-linux-debug (pull_request) Has been cancelled
ci / x86_64-linux-debug-llvm (pull_request) Has been cancelled
ci / x86_64-windows-release (pull_request) Has been cancelled
ci / aarch64-linux-release (pull_request) Has been cancelled
ci / x86_64-linux-debug (pull_request) Has been cancelled
ci / loongarch64-linux-debug (pull_request) Has been cancelled
ci / x86_64-linux-release (pull_request) Has been cancelled
ci / loongarch64-linux-release (pull_request) Has been cancelled
ci / s390x-linux-debug (pull_request) Has been cancelled
ci / s390x-linux-release (pull_request) Has been cancelled
ci / aarch64-macos-debug (pull_request) Has been cancelled
ci / aarch64-macos-release (pull_request) Has been cancelled
ci / powerpc64le-linux-release (pull_request) Has been cancelled
ci / aarch64-freebsd-debug (pull_request) Has been cancelled
ci / powerpc64le-linux-debug (pull_request) Has been cancelled
2026年05月16日 01:04:57 +02:00
Compare
castholm force-pushed cli-args-parser from 280a6f9a85
Some checks failed
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / aarch64-freebsd-release (pull_request) Has been cancelled
ci / aarch64-netbsd-debug (pull_request) Has been cancelled
ci / aarch64-netbsd-release (pull_request) Has been cancelled
ci / x86_64-freebsd-debug (pull_request) Has been cancelled
ci / x86_64-openbsd-release (pull_request) Has been cancelled
ci / x86_64-freebsd-release (pull_request) Has been cancelled
ci / x86_64-openbsd-debug (pull_request) Has been cancelled
ci / x86_64-netbsd-debug (pull_request) Has been cancelled
ci / x86_64-netbsd-release (pull_request) Has been cancelled
ci / x86_64-windows-debug (pull_request) Has been cancelled
ci / aarch64-linux-debug (pull_request) Has been cancelled
ci / x86_64-linux-debug-llvm (pull_request) Has been cancelled
ci / x86_64-windows-release (pull_request) Has been cancelled
ci / aarch64-linux-release (pull_request) Has been cancelled
ci / x86_64-linux-debug (pull_request) Has been cancelled
ci / loongarch64-linux-debug (pull_request) Has been cancelled
ci / x86_64-linux-release (pull_request) Has been cancelled
ci / loongarch64-linux-release (pull_request) Has been cancelled
ci / s390x-linux-debug (pull_request) Has been cancelled
ci / s390x-linux-release (pull_request) Has been cancelled
ci / aarch64-macos-debug (pull_request) Has been cancelled
ci / aarch64-macos-release (pull_request) Has been cancelled
ci / powerpc64le-linux-release (pull_request) Has been cancelled
ci / aarch64-freebsd-debug (pull_request) Has been cancelled
ci / powerpc64le-linux-debug (pull_request) Has been cancelled
to 201a120e22
All checks were successful
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / x86_64-netbsd-release (pull_request) Successful in 40m45s
ci / x86_64-freebsd-release (pull_request) Successful in 43m24s
ci / x86_64-freebsd-debug (pull_request) Successful in 45m19s
ci / x86_64-openbsd-release (pull_request) Successful in 45m42s
ci / x86_64-netbsd-debug (pull_request) Successful in 45m47s
ci / x86_64-windows-release (pull_request) Successful in 47m54s
ci / x86_64-windows-debug (pull_request) Successful in 51m46s
ci / x86_64-openbsd-debug (pull_request) Successful in 54m18s
ci / x86_64-linux-debug (pull_request) Successful in 57m7s
ci / aarch64-macos-release (pull_request) Successful in 1h1m1s
ci / aarch64-macos-debug (pull_request) Successful in 1h13m29s
ci / aarch64-linux-release (pull_request) Successful in 1h26m55s
ci / s390x-linux-release (pull_request) Successful in 1h28m16s
ci / loongarch64-linux-release (pull_request) Successful in 1h41m12s
ci / powerpc64le-linux-release (pull_request) Successful in 1h52m27s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 2h10m23s
ci / s390x-linux-debug (pull_request) Successful in 2h16m30s
ci / x86_64-linux-release (pull_request) Successful in 2h24m3s
ci / aarch64-linux-debug (pull_request) Successful in 2h36m43s
ci / loongarch64-linux-debug (pull_request) Successful in 2h45m20s
ci / aarch64-freebsd-debug (pull_request) Successful in 4h17m18s
ci / powerpc64le-linux-debug (pull_request) Successful in 4h35m55s
ci / aarch64-freebsd-release (pull_request) Successful in 3h16m42s
ci / aarch64-netbsd-debug (pull_request) Successful in 4h19m0s
ci / aarch64-netbsd-release (pull_request) Successful in 3h31m12s
2026年05月16日 01:12:55 +02:00
Compare
Author
Contributor
Copy link

I've updated all the internal tools to make use of the new API. Some important notes:

  • Options in docgen, doctest, incr-check that were previously mandatory have been converted into positional arguments (options cannot be made required by the parser API, by design). These tools are invoked by the build script (which has been updated) so this hopefully shouldn't affect anything negatively.
  • I swapped order of the source and destination parameters to update_mingw around, and changed it so that the destination parameter should point to the root of the Zig source tree, not the lib directory, for consistency with update_glicb/freebsd/netbsd/openbsd_libc.
  • The -fqemu, -fwine, -fwasmtime, -fdarling options in incr-check have been renamed to --qemu, --wine, --wasmtime, --darling because the parser API doesn't support single-dash option names. Again, because this tool is invoked by the build script I hope this isn't a problem.
  • For tools that previously didn't have help, but had top-level doc comments, I've converted those doc comments to the help summary multiline string literal and placed the args struct at the very top of the files.

Before and after --help outputs

docgen.zig

Before:

Usage: docgen [options] input output
 Generates an HTML document from a docgen template.
Options:
 --code-dir dir Path to directory containing code example outputs
 -h, --help Print this help and exit

After:

Usage: docgen [<option>...] [--] <code-dir> <input-file> <output-file>
Generates an HTML document from a docgen template.
Arguments:
 <code-dir> Path to directory containing code example outputs
 <input-file> Path to input file
 <output-file> Path to output file
Options:
 -h, --help Print this help and exit

doctest.zig

Before:

Usage: doctest [options] -i input -o output
 Compiles and possibly runs a code example, capturing output and rendering
 it to HTML documentation.
Options:
 -h, --help Print this help and exit
 -i input Source code file path
 -o output Where to write output HTML docs to
 --zig zig Path to the zig compiler
 --zig-lib-dir dir Override the zig compiler library path
 --cache-root dir Path to local .zig-cache/

After:

Usage: doctest [<option>...] [--] <zig-exe> <cache-root> <input-path> <output-path>
Compiles and possibly runs a code example,
capturing output and rendering it to HTML documentation.
Arguments:
 <zig-exe> Path to the zig compiler
 <cache-root> Path to local .zig-cache/
 <input-path> Source code file path
 <output-path> Where to write output HTML docs to
Options:
 --zig-lib-dir=<dir> Override the zig compiler library path
 -h, --help Print this help and exit

dump-cov.zig

Before:

usage: ./dump-cov path/to/exe path/to/coverage [target]
 if omitted, 'target' defaults to 'native'
 example: dump-cov zig-out/test .zig-cache/v/xxxxxxxx x86_64-linux

After:

Usage: dump-cov [<option>...] [--] <exe-path> <cov-path> [<target-query>]
Reads a Zig coverage file and prints human-readable information to stdout,
including file:line:column information for each PC.
Example: dump-cov zig-out/test .zig-cache/v/xxxxxxxx x86_64-linux
Arguments:
 <exe-path> Path to executable
 <cov-path> Path to coverage file
 <target-query> If omitted, defaults to 'native'
Options:
 -h, --help Print this help and exit

fetch_them_macos_headers.zig

Before:

fetch_them_macos_headers [options] [cc args]
Options:
 --sysroot Path to macOS SDK
General Options:
-h, --help Print this help and exit

After:

Usage: fetch_them_macos_headers [<option>...] [--] [<cc-args>...]
Arguments:
 <cc-args>... Additional arguments to forward to CC
Options:
 --sysroot=<path> Path to macOS SDK
 -h, --help Print this help and exit

gen_macos_headers_c.zig

Before:

gen_macos_headers_c [dir]
General Options:
-h, --help Print this help and exit

After:

Usage: gen_macos_headers_c [<option>...] [--] <dir>
Arguments:
 <dir> Directory to search for headers
Options:
 -h, --help Print this help and exit

gen_outline_atomics.zig

Before: N/A

After:

Usage: gen_outline_atomics [<option>...]
Options:
 -h, --help Print this help and exit

gen_spirv_spec.zig

Before:

Usage: ./gen_spirv_spec <SPIRV-Headers repository path> <path/to/zig/src/codegen/spirv/extinst.zig.grammar.json>
Generates Zig bindings for SPIR-V specifications found in the SPIRV-Headers
repository. The result, printed to stdout, should be used to update
files in src/codegen/spirv. Don't forget to format the output.
<SPIRV-Headers repository path> should point to a clone of
https://github.com/KhronosGroup/SPIRV-Headers/

After:

Usage: gen_spirv_spec [<option>...] [--] <spirv-headers-repo-dir> <extinst-zig-grammar-json>
Generates Zig bindings for SPIR-V specifications found in the SPIRV-Headers
repository. The result, printed to stdout, should be used to update
files in src/codegen/spirv. Don't forget to format the output.
Arguments:
 <spirv-headers-repo-dir> Should point to a clone of https://github.com/KhronosGroup/SPIRV-Headers/
 <extinst-zig-grammar-json> Path to zig/src/codegen/spirv/extinst.zig.grammar.json
Options:
 -h, --help Print this help and exit

gen_stubs.zig

Before: N/A

After:

Usage: gen_stubs [<option>...] [--] <build-all-dir>
Example: gen_stubs /path/to/musl/build-all >libc.S
The directory 'build-all' is expected to contain these subdirectories:
* aarch64
* arm
* i386
* hexagon
* loongarch64
* mips
* mips64
* mipsn32
* powerpc
* powerpc64
* riscv32
* riscv64
* s390x
* x32 (currently broken)
* x86_64
...each with 'lib/libc.so' inside of them.
When building the resulting libc.S file, these defines are required:
* `-DTIME32`: When the target's primary time ABI is 32-bit
* `-DPTR64`: When the target has 64-bit pointers
* One of the following, corresponding to the CPU architecture:
 - `-DARCH_aarch64`
 - `-DARCH_arm`
 - `-DARCH_i386`
 - `-DARCH_hexagon`
 - `-DARCH_loongarch64`
 - `-DARCH_mips`
 - `-DARCH_mips64`
 - `-DARCH_mipsn32`
 - `-DARCH_powerpc`
 - `-DARCH_powerpc64`
 - `-DARCH_riscv32`
 - `-DARCH_riscv64`
 - `-DARCH_s390x`
 - `-DARCH_x32`
 - `-DARCH_x86_64`
* One of the following, corresponding to the CPU architecture family:
 - `-DFAMILY_aarch64`
 - `-DFAMILY_arm`
 - `-DFAMILY_hexagon`
 - `-DFAMILY_loongarch`
 - `-DFAMILY_mips`
 - `-DFAMILY_powerpc`
 - `-DFAMILY_riscv`
 - `-DFAMILY_s390x`
 - `-DFAMILY_x86`
Arguments:
 <build-all-dir> Directory containing '<arch>/lib/libc.so'
Options:
 -h, --help Print this help and exit

generate_c_size_and_align_checks.zig

Before:

Usage: ./generate_c_size_and_align_checks [target_triple]

After:

Usage: zig run tools/generate_c_size_and_align_checks.zig -- [<option>...] [--] <target-triple>
Prints _Static_asserts for the size and alignment of all the basic built-in
C types. The output can be run through a compiler for the specified target
to verify that Zig's values are the same as those used by a C compiler
for the target.
Arguments:
 <target-triple> Zig target triple (e.g. x86_64-linux-gnu)
Options:
 -h, --help Print this help and exit

generate_JSONTestSuite.zig

Before: N/A

After:

Usage: generate_JSONTestSuite [<option>...]
Run this program inside the test_parsing/ directory of this repo:
https://github.com/nst/JSONTestSuite
Options:
 -h, --help Print this help and exit

generate_linux_syscalls.zig

Before:

Usage: ./generate_linux_syscalls /path/to/linux
Alternative Usage: zig run /path/to/git/zig/tools/generate_linux_syscalls.zig -- /path/to/linux
Generates the list of Linux syscalls for each supported cpu arch, using the Linux development tree.
Prints to stdout Zig code which you can use to replace the file lib/std/os/linux/syscalls.zig.

After:

Usage: generate_linux_syscalls [<option>...] [--] <linux-dir>
Alternative Usage: zig run /path/to/git/zig/tools/generate_linux_syscalls.zig -- /path/to/linux
Generates the list of Linux syscalls for each supported cpu arch, using the Linux development tree.
Prints to stdout Zig code which you can use to replace the file lib/std/os/linux/syscalls.zig.
Arguments:
 <linux-dir> Path to Linux source tree
Options:
 -h, --help Print this help and exit

incr-check.zig

Before:

Usage: incr-check <zig binary path> <input file> [options]
Options:
 --target triple-backend
 --quiet
 --zig-lib-dir /path/to/zig/lib
 --zig-cc-binary /path/to/zig
 -fqemu
 -fwine
 -fwasmtime
Debug Options:
 --preserve-tmp
 --debug-log foo

After:

Usage: incr-check [<option>...] [--] <zig-exe> <input-file> <triple-backend>
Arguments:
 <zig-exe> Path to Zig binary
 <input-file> Path to input file
 <triple-backend> Target triple-backend (e.g. 'x86_64-linux-selfhosted')
Options:
 --[no-]quiet Suppress log messages about e.g. skipped tests
 --zig-lib-dir=<path> Override path to Zig lib directory
 --zig-cc-binary=<path> Path to CC Zig exe
 --[no-]qemu Enable QEMU integration
 --[no-]wine Enable Wine integration
 --[no-]wasmtime Enable Wasmtime integration
 --[no-]darling Enable Darling integration
 --[no-]preserve-tmp Preserve temp directory
 --debug-log=<arg> --debug-log arguments to forward to the Zig compiler
 -h, --help Print this help and exit

migrate_langref.zig

Before: N/A

After:

Usage: migrate_langref [<option>...] [--] <input-file> <output-file>
Arguments:
 <input-file> Path to input file
 <output-file> Path to output file
Options:
 -h, --help Print this help and exit

process_headers.zig

Before:

Usage: ./process_headers [--search-path <dir>] --out <dir> --abi <name>
--search-path can be used any number of times.
 subdirectories of search paths look like, e.g. x86_64-linux-gnu
--out is a dir that will be created, and populated with the results
--abi is either glibc, musl, freebsd, netbsd, or openbsd

After:

Usage: process_headers [<option>...] [--] <out-dir> (musl|glibc|freebsd|netbsd|openbsd)
Arguments:
 <out-dir> Dir that will be created, and populated with the results
 (musl|glibc|freebsd|netbsd|openbsd) Libc vendor
Options:
 --search-path=<path> Search paths, subdirectories look like, e.g. x86_64-linux-gnu
 -h, --help Print this help and exit

update-linux-headers.zig

Before:

Usage: ./process_headers [--search-path <dir>] --out <dir> --abi <name>
--search-path can be used any number of times.
 subdirectories of search paths look like, e.g. x86_64-linux-gnu
--out is a dir that will be created, and populated with the results

After:

Usage: update-linux-headers [<option>...] [--] <out-dir>
Arguments:
 <out-dir> Dir that will be created, and populated with the results
Options:
 --search-path=<path> Search paths, subdirectories look like, e.g. x86_64-linux-gnu
 -h, --help Print this help and exit

update_clang_options.zig

Before:

Usage: ./update_clang_options /path/to/llvm-tblgen /path/to/git/llvm/llvm-project
Prints to stdout Zig code which you can use to replace the file src/clang_options.zon.

After:

Usage: update_clang_options [<option>...] [--] <llvm-tblgen-exe> <llvm-src-root>
Prints to stdout Zig code which you can use to replace the file src/clang_options.zon.
Arguments:
 <llvm-tblgen-exe> Path to llvm-tblgen executable
 <llvm-src-root> Path to llvm-project source tree
Options:
 -h, --help Print this help and exit

update_cpu_features.zig

Before:

Usage: ./update_cpu_features /path/to/llvm-tblgen /path/git/llvm-project /path/git/zig [zig_name filter]
Updates lib/std/target/<target>.zig from llvm/lib/Target/<Target>/<Target>.td .
On a less beefy system, or when debugging, compile with -fsingle-threaded.

After:

Usage: update_cpu_features [<option>...] [--] <llvm-tblgen-exe> <llvm-src-root> <zig-src-root> [<filter>]
Updates lib/std/target/<target>.zig from llvm/lib/Target/<Target>/<Target>.td.
On a less beefy system, or when debugging, compile with -fsingle-threaded.
Arguments:
 <llvm-tblgen-exe> Path to llvm-tblgen executable
 <llvm-src-root> Path to llvm-project source tree
 <zig-src-root> Path to Zig source tree
 <filter> Optional Zig name filter
Options:
 -h, --help Print this help and exit

update_crc_catalog.zig

Before:

Usage: ./update_crc_catalog /path/git/zig

After:

Usage: update_crc_catalog [<option>...] [--] <zig-src-root>
Arguments:
 <zig-src-root> Path to Zig source tree
Options:
 -h, --help Print this help and exit

update_freebsd_libc.zig

Before: N/A

After:

Usage: zig run tools/update_freebsd_libc.zig -- [<option>...] [--] <freebsd-src-path> <zig-src-path>
This script updates the .c, .h, .s, and .S files that make up the start
files such as crt1.o.
Example usage:
zig run tools/update_freebsd_libc.zig -- ~/Downloads/freebsd-src .
Arguments:
 <freebsd-src-path> Path to FreeBSD source tree
 <zig-src-path> Path to Zig source tree
Options:
 -h, --help Print this help and exit

update_glibc.zig

Before: N/A

After:

Usage: zig run tools/update_glibc.zig -- [<option>...] [--] <glibc-src-path> <zig-src-path>
This script updates the .c, .h, .s, and .S files that make up the start
files such as crt1.o.
Not to be confused with https://codeberg.org/ziglang/libc-abi-tools
which updates the 'abilists' file.
Example usage:
zig run tools/update_glibc.zig -- ~/Downloads/glibc .
Arguments:
 <glibc-src-path> Path to glibc source tree
 <zig-src-path> Path to Zig source tree
Options:
 -h, --help Print this help and exit

update_mingw.zig

Before: N/A

After:

Usage: zig run tools/update_mingw.zig -- [<option>...] [--] <mingw-src-path> <zig-src-path>
This script updates mingw-w64 crt and library files.
Example usage:
zig run tools/update_mingw.zig -- ~/Downloads/mingw-w64 .
Arguments:
 <mingw-src-path> Path to mingw-w64 source tree
 <zig-src-path> Path to Zig source tree
Options:
 -h, --help Print this help and exit

update_netbsd_libc.zig

Before: N/A

After:

Usage: zig run tools/update_netbsd_libc.zig -- [<option>...] [--] <netbsd-src-path> <zig-src-path>
This script updates the .c, .h, .s, and .S files that make up the start
files such as crt1.o.
Example usage:
zig run tools/update_netbsd_libc.zig -- ~/Downloads/netbsd-src .
Arguments:
 <netbsd-src-path> Path to NetBSD source tree
 <zig-src-path> Path to Zig source tree
Options:
 -h, --help Print this help and exit

update_openbsd_libc.zig

Before: N/A

After:

Usage: zig run tools/update_openbsd_libc.zig -- [<option>...] [--] <openbsd-src-path> <zig-src-path>
This script updates the .c, .h, .s, and .S files that make up the start
files such as crt1.o.
Example usage:
zig run tools/update_openbsd_libc.zig -- ~/Downloads/openbsd-src .
Arguments:
 <openbsd-src-path> Path to OpenBSD source tree
 <zig-src-path> Path to Zig source tree
Options:
 -h, --help Print this help and exit

Some reflections, mostly wrt. help text generation:

  • Maybe a good future enhancement to std.Io/cli.Terminal would be to offer a writer mode that strips ANSI SGR control sequences when disabled/unsupported, so that people can pre-bake ANSI styling into their help string literals. Also relevant: #9502 do you want ANSI color code support for std.fmt.format?
  • Maybe std.cli.Help should have header/footer or prolog/epilog fields, for adding sections of text before Usage: and after the last option? On the other hand, infodumping pages after pages of details about your program is better left to a README or man pages.
  • It would be neat, but probably overkill, if the default option-argument display selection (<value>) tried to choose based on a limited set of common names or suffixes, e.g. names like --input/--output or those ending in -path or -file use <path> by default.
  • I wonder if it would make sense to add a assume_zig_run: bool = false field to std.cli.Help, for files/scripts that are meant to be compiled and run directly via zig run, which when set would render the usage message as Usage: zig run filename.zig -- [<option>...] instead of Usage: filename.exe. (Probably not, and as I've demonstrated when I update some of these tools, you can achieve the same effect manually by setting command_name.)
I've updated all the internal tools to make use of the new API. Some important notes: - Options in `docgen`, `doctest`, `incr-check` that were previously mandatory have been converted into positional arguments (options cannot be made required by the parser API, by design). These tools are invoked by the build script (which has been updated) so this hopefully shouldn't affect anything negatively. - I swapped order of the source and destination parameters to `update_mingw` around, and changed it so that the destination parameter should point to the root of the Zig source tree, not the `lib` directory, for consistency with `update_glicb/freebsd/netbsd/openbsd_libc`. - The `-fqemu`, `-fwine`, `-fwasmtime`, `-fdarling` options in `incr-check` have been renamed to `--qemu`, `--wine`, `--wasmtime`, `--darling` because the parser API doesn't support single-dash option names. Again, because this tool is invoked by the build script I hope this isn't a problem. - For tools that previously didn't have help, but had top-level doc comments, I've converted those doc comments to the help summary multiline string literal and placed the args struct at the very top of the files. <details><summary> Before and after `--help` outputs </summary> ### `docgen.zig` Before: ``` Usage: docgen [options] input output Generates an HTML document from a docgen template. Options: --code-dir dir Path to directory containing code example outputs -h, --help Print this help and exit ``` After: ``` Usage: docgen [<option>...] [--] <code-dir> <input-file> <output-file> Generates an HTML document from a docgen template. Arguments: <code-dir> Path to directory containing code example outputs <input-file> Path to input file <output-file> Path to output file Options: -h, --help Print this help and exit ``` ### `doctest.zig` Before: ``` Usage: doctest [options] -i input -o output Compiles and possibly runs a code example, capturing output and rendering it to HTML documentation. Options: -h, --help Print this help and exit -i input Source code file path -o output Where to write output HTML docs to --zig zig Path to the zig compiler --zig-lib-dir dir Override the zig compiler library path --cache-root dir Path to local .zig-cache/ ``` After: ``` Usage: doctest [<option>...] [--] <zig-exe> <cache-root> <input-path> <output-path> Compiles and possibly runs a code example, capturing output and rendering it to HTML documentation. Arguments: <zig-exe> Path to the zig compiler <cache-root> Path to local .zig-cache/ <input-path> Source code file path <output-path> Where to write output HTML docs to Options: --zig-lib-dir=<dir> Override the zig compiler library path -h, --help Print this help and exit ``` ### `dump-cov.zig` Before: ``` usage: ./dump-cov path/to/exe path/to/coverage [target] if omitted, 'target' defaults to 'native' example: dump-cov zig-out/test .zig-cache/v/xxxxxxxx x86_64-linux ``` After: ``` Usage: dump-cov [<option>...] [--] <exe-path> <cov-path> [<target-query>] Reads a Zig coverage file and prints human-readable information to stdout, including file:line:column information for each PC. Example: dump-cov zig-out/test .zig-cache/v/xxxxxxxx x86_64-linux Arguments: <exe-path> Path to executable <cov-path> Path to coverage file <target-query> If omitted, defaults to 'native' Options: -h, --help Print this help and exit ``` ### `fetch_them_macos_headers.zig` Before: ``` fetch_them_macos_headers [options] [cc args] Options: --sysroot Path to macOS SDK General Options: -h, --help Print this help and exit ``` After: ``` Usage: fetch_them_macos_headers [<option>...] [--] [<cc-args>...] Arguments: <cc-args>... Additional arguments to forward to CC Options: --sysroot=<path> Path to macOS SDK -h, --help Print this help and exit ``` ### `gen_macos_headers_c.zig` Before: ``` gen_macos_headers_c [dir] General Options: -h, --help Print this help and exit ``` After: ``` Usage: gen_macos_headers_c [<option>...] [--] <dir> Arguments: <dir> Directory to search for headers Options: -h, --help Print this help and exit ``` ### `gen_outline_atomics.zig` Before: N/A After: ``` Usage: gen_outline_atomics [<option>...] Options: -h, --help Print this help and exit ``` ### `gen_spirv_spec.zig` Before: ``` Usage: ./gen_spirv_spec <SPIRV-Headers repository path> <path/to/zig/src/codegen/spirv/extinst.zig.grammar.json> Generates Zig bindings for SPIR-V specifications found in the SPIRV-Headers repository. The result, printed to stdout, should be used to update files in src/codegen/spirv. Don't forget to format the output. <SPIRV-Headers repository path> should point to a clone of https://github.com/KhronosGroup/SPIRV-Headers/ ``` After: ``` Usage: gen_spirv_spec [<option>...] [--] <spirv-headers-repo-dir> <extinst-zig-grammar-json> Generates Zig bindings for SPIR-V specifications found in the SPIRV-Headers repository. The result, printed to stdout, should be used to update files in src/codegen/spirv. Don't forget to format the output. Arguments: <spirv-headers-repo-dir> Should point to a clone of https://github.com/KhronosGroup/SPIRV-Headers/ <extinst-zig-grammar-json> Path to zig/src/codegen/spirv/extinst.zig.grammar.json Options: -h, --help Print this help and exit ``` ### `gen_stubs.zig` Before: N/A After: ``` Usage: gen_stubs [<option>...] [--] <build-all-dir> Example: gen_stubs /path/to/musl/build-all >libc.S The directory 'build-all' is expected to contain these subdirectories: * aarch64 * arm * i386 * hexagon * loongarch64 * mips * mips64 * mipsn32 * powerpc * powerpc64 * riscv32 * riscv64 * s390x * x32 (currently broken) * x86_64 ...each with 'lib/libc.so' inside of them. When building the resulting libc.S file, these defines are required: * `-DTIME32`: When the target's primary time ABI is 32-bit * `-DPTR64`: When the target has 64-bit pointers * One of the following, corresponding to the CPU architecture: - `-DARCH_aarch64` - `-DARCH_arm` - `-DARCH_i386` - `-DARCH_hexagon` - `-DARCH_loongarch64` - `-DARCH_mips` - `-DARCH_mips64` - `-DARCH_mipsn32` - `-DARCH_powerpc` - `-DARCH_powerpc64` - `-DARCH_riscv32` - `-DARCH_riscv64` - `-DARCH_s390x` - `-DARCH_x32` - `-DARCH_x86_64` * One of the following, corresponding to the CPU architecture family: - `-DFAMILY_aarch64` - `-DFAMILY_arm` - `-DFAMILY_hexagon` - `-DFAMILY_loongarch` - `-DFAMILY_mips` - `-DFAMILY_powerpc` - `-DFAMILY_riscv` - `-DFAMILY_s390x` - `-DFAMILY_x86` Arguments: <build-all-dir> Directory containing '<arch>/lib/libc.so' Options: -h, --help Print this help and exit ``` ### `generate_c_size_and_align_checks.zig` Before: ``` Usage: ./generate_c_size_and_align_checks [target_triple] ``` After: ``` Usage: zig run tools/generate_c_size_and_align_checks.zig -- [<option>...] [--] <target-triple> Prints _Static_asserts for the size and alignment of all the basic built-in C types. The output can be run through a compiler for the specified target to verify that Zig's values are the same as those used by a C compiler for the target. Arguments: <target-triple> Zig target triple (e.g. x86_64-linux-gnu) Options: -h, --help Print this help and exit ``` ### `generate_JSONTestSuite.zig` Before: N/A After: ``` Usage: generate_JSONTestSuite [<option>...] Run this program inside the test_parsing/ directory of this repo: https://github.com/nst/JSONTestSuite Options: -h, --help Print this help and exit ``` ### `generate_linux_syscalls.zig` Before: ``` Usage: ./generate_linux_syscalls /path/to/linux Alternative Usage: zig run /path/to/git/zig/tools/generate_linux_syscalls.zig -- /path/to/linux Generates the list of Linux syscalls for each supported cpu arch, using the Linux development tree. Prints to stdout Zig code which you can use to replace the file lib/std/os/linux/syscalls.zig. ``` After: ``` Usage: generate_linux_syscalls [<option>...] [--] <linux-dir> Alternative Usage: zig run /path/to/git/zig/tools/generate_linux_syscalls.zig -- /path/to/linux Generates the list of Linux syscalls for each supported cpu arch, using the Linux development tree. Prints to stdout Zig code which you can use to replace the file lib/std/os/linux/syscalls.zig. Arguments: <linux-dir> Path to Linux source tree Options: -h, --help Print this help and exit ``` ### `incr-check.zig` Before: ``` Usage: incr-check <zig binary path> <input file> [options] Options: --target triple-backend --quiet --zig-lib-dir /path/to/zig/lib --zig-cc-binary /path/to/zig -fqemu -fwine -fwasmtime Debug Options: --preserve-tmp --debug-log foo ``` After: ``` Usage: incr-check [<option>...] [--] <zig-exe> <input-file> <triple-backend> Arguments: <zig-exe> Path to Zig binary <input-file> Path to input file <triple-backend> Target triple-backend (e.g. 'x86_64-linux-selfhosted') Options: --[no-]quiet Suppress log messages about e.g. skipped tests --zig-lib-dir=<path> Override path to Zig lib directory --zig-cc-binary=<path> Path to CC Zig exe --[no-]qemu Enable QEMU integration --[no-]wine Enable Wine integration --[no-]wasmtime Enable Wasmtime integration --[no-]darling Enable Darling integration --[no-]preserve-tmp Preserve temp directory --debug-log=<arg> --debug-log arguments to forward to the Zig compiler -h, --help Print this help and exit ``` ### `migrate_langref.zig` Before: N/A After: ``` Usage: migrate_langref [<option>...] [--] <input-file> <output-file> Arguments: <input-file> Path to input file <output-file> Path to output file Options: -h, --help Print this help and exit ``` ### `process_headers.zig` Before: ``` Usage: ./process_headers [--search-path <dir>] --out <dir> --abi <name> --search-path can be used any number of times. subdirectories of search paths look like, e.g. x86_64-linux-gnu --out is a dir that will be created, and populated with the results --abi is either glibc, musl, freebsd, netbsd, or openbsd ``` After: ``` Usage: process_headers [<option>...] [--] <out-dir> (musl|glibc|freebsd|netbsd|openbsd) Arguments: <out-dir> Dir that will be created, and populated with the results (musl|glibc|freebsd|netbsd|openbsd) Libc vendor Options: --search-path=<path> Search paths, subdirectories look like, e.g. x86_64-linux-gnu -h, --help Print this help and exit ``` ### `update-linux-headers.zig` Before: ``` Usage: ./process_headers [--search-path <dir>] --out <dir> --abi <name> --search-path can be used any number of times. subdirectories of search paths look like, e.g. x86_64-linux-gnu --out is a dir that will be created, and populated with the results ``` After: ``` Usage: update-linux-headers [<option>...] [--] <out-dir> Arguments: <out-dir> Dir that will be created, and populated with the results Options: --search-path=<path> Search paths, subdirectories look like, e.g. x86_64-linux-gnu -h, --help Print this help and exit ``` ### `update_clang_options.zig` Before: ``` Usage: ./update_clang_options /path/to/llvm-tblgen /path/to/git/llvm/llvm-project Prints to stdout Zig code which you can use to replace the file src/clang_options.zon. ``` After: ``` Usage: update_clang_options [<option>...] [--] <llvm-tblgen-exe> <llvm-src-root> Prints to stdout Zig code which you can use to replace the file src/clang_options.zon. Arguments: <llvm-tblgen-exe> Path to llvm-tblgen executable <llvm-src-root> Path to llvm-project source tree Options: -h, --help Print this help and exit ``` ### `update_cpu_features.zig` Before: ``` Usage: ./update_cpu_features /path/to/llvm-tblgen /path/git/llvm-project /path/git/zig [zig_name filter] Updates lib/std/target/<target>.zig from llvm/lib/Target/<Target>/<Target>.td . On a less beefy system, or when debugging, compile with -fsingle-threaded. ``` After: ``` Usage: update_cpu_features [<option>...] [--] <llvm-tblgen-exe> <llvm-src-root> <zig-src-root> [<filter>] Updates lib/std/target/<target>.zig from llvm/lib/Target/<Target>/<Target>.td. On a less beefy system, or when debugging, compile with -fsingle-threaded. Arguments: <llvm-tblgen-exe> Path to llvm-tblgen executable <llvm-src-root> Path to llvm-project source tree <zig-src-root> Path to Zig source tree <filter> Optional Zig name filter Options: -h, --help Print this help and exit ``` ### `update_crc_catalog.zig` Before: ``` Usage: ./update_crc_catalog /path/git/zig ``` After: ``` Usage: update_crc_catalog [<option>...] [--] <zig-src-root> Arguments: <zig-src-root> Path to Zig source tree Options: -h, --help Print this help and exit ``` ### `update_freebsd_libc.zig` Before: N/A After: ``` Usage: zig run tools/update_freebsd_libc.zig -- [<option>...] [--] <freebsd-src-path> <zig-src-path> This script updates the .c, .h, .s, and .S files that make up the start files such as crt1.o. Example usage: zig run tools/update_freebsd_libc.zig -- ~/Downloads/freebsd-src . Arguments: <freebsd-src-path> Path to FreeBSD source tree <zig-src-path> Path to Zig source tree Options: -h, --help Print this help and exit ``` ### `update_glibc.zig` Before: N/A After: ``` Usage: zig run tools/update_glibc.zig -- [<option>...] [--] <glibc-src-path> <zig-src-path> This script updates the .c, .h, .s, and .S files that make up the start files such as crt1.o. Not to be confused with https://codeberg.org/ziglang/libc-abi-tools which updates the 'abilists' file. Example usage: zig run tools/update_glibc.zig -- ~/Downloads/glibc . Arguments: <glibc-src-path> Path to glibc source tree <zig-src-path> Path to Zig source tree Options: -h, --help Print this help and exit ``` ### `update_mingw.zig` Before: N/A After: ``` Usage: zig run tools/update_mingw.zig -- [<option>...] [--] <mingw-src-path> <zig-src-path> This script updates mingw-w64 crt and library files. Example usage: zig run tools/update_mingw.zig -- ~/Downloads/mingw-w64 . Arguments: <mingw-src-path> Path to mingw-w64 source tree <zig-src-path> Path to Zig source tree Options: -h, --help Print this help and exit ``` ### `update_netbsd_libc.zig` Before: N/A After: ``` Usage: zig run tools/update_netbsd_libc.zig -- [<option>...] [--] <netbsd-src-path> <zig-src-path> This script updates the .c, .h, .s, and .S files that make up the start files such as crt1.o. Example usage: zig run tools/update_netbsd_libc.zig -- ~/Downloads/netbsd-src . Arguments: <netbsd-src-path> Path to NetBSD source tree <zig-src-path> Path to Zig source tree Options: -h, --help Print this help and exit ``` ### `update_openbsd_libc.zig` Before: N/A After: ``` Usage: zig run tools/update_openbsd_libc.zig -- [<option>...] [--] <openbsd-src-path> <zig-src-path> This script updates the .c, .h, .s, and .S files that make up the start files such as crt1.o. Example usage: zig run tools/update_openbsd_libc.zig -- ~/Downloads/openbsd-src . Arguments: <openbsd-src-path> Path to OpenBSD source tree <zig-src-path> Path to Zig source tree Options: -h, --help Print this help and exit ``` </details> Some reflections, mostly wrt. help text generation: - Maybe a good future enhancement to `std.Io/cli.Terminal` would be to offer a writer mode that strips ANSI SGR control sequences when disabled/unsupported, so that people can pre-bake ANSI styling into their help string literals. Also relevant: [#9502 do you want ANSI color code support for `std.fmt.format`?](https://github.com/ziglang/zig/issues/9502) - Maybe `std.cli.Help` should have header/footer or prolog/epilog fields, for adding sections of text before `Usage:` and after the last option? On the other hand, infodumping pages after pages of details about your program is better left to a README or man pages. - It would be neat, but probably overkill, if the default option-argument display selection (`<value>`) tried to choose based on a limited set of common names or suffixes, e.g. names like `--input`/`--output` or those ending in `-path` or `-file` use `<path>` by default. - I wonder if it would make sense to add a `assume_zig_run: bool = false` field to `std.cli.Help`, for files/scripts that are meant to be compiled and run directly via `zig run`, which when set would render the usage message as `Usage: zig run filename.zig -- [<option>...]` instead of `Usage: filename.exe`. (Probably not, and as I've demonstrated when I update some of these tools, you can achieve the same effect manually by setting `command_name`.)
Author
Contributor
Copy link

@lukasl wrote in #35304 (comment):

I can't help it, but I REALLY dislike the struct with field names like that. That would prevent me from using this.

Do you think you could elaborate on why you feel it bothers you? Is it purely an aesthetic preference and a subjective distaste for @"", or is it a concern about readability and developer ergonomics/typing?

The API could be redesigned to work with a struct like

constArgs=Struct{positional:struct{script:[]constu8,},options:struct{cache_dir:?[:0]constu8,debug:bool=false,},};

similar to what was originally proposed by Josh Wolfe in #24601.

However, I would still argue that the design I'm proposing with this PR has a number of advantages. One of the main ones is that options are provided on the command line exactly as the fields are named, unlike the original proposal where it's ambiguous to an unassuming user as for whether the field a: i32 will become the short option -a or the long option --a, or whether cache_dir becomes --cache_dir or --cache-dir. Here, what you see is exactly what you get.

I also feel that requiring options to be named like actual options is intuitive. If I was completely new to a language and saw a struct with fields named like @"--output", I would immediately clock it as having to do with command-line options. Because args parsing is a common task that you're likely to run into early on, it's also a good opportunity for introducing newcomes to the language to the @"" identifier syntax and teaching them that Zig allows any arbitrary identifier name using this form. Structurally, this design is also the simplest, with a completely flattened struct.

I'll admit that I too was initially a bit concerned about whether args.@"--option" would feel like too much visual noise, but now after having updated the 20+ internal tools I don't feel like it was much of an issue at all. It certainly didn't bother me any more than something like assert(@typeInfo(@TypeOf(foo)).@"struct".layout == .@"extern") 😛

@lukasl wrote in https://codeberg.org/ziglang/zig/pulls/35304#issuecomment-14920083: > I can't help it, but I REALLY dislike the struct with field names like that. That would prevent me from using this. Do you think you could elaborate on why you feel it bothers you? Is it purely an aesthetic preference and a subjective distaste for `@""`, or is it a concern about readability and developer ergonomics/typing? The API *could* be redesigned to work with a struct like ```zig const Args = Struct { positional: struct { script: []const u8, }, options: struct { cache_dir: ?[:0]const u8, debug: bool = false, }, }; ``` similar to what was originally proposed by Josh Wolfe in [#24601](https://github.com/ziglang/zig/issues/24601). However, I would still argue that the design I'm proposing with this PR has a number of advantages. One of the main ones is that options are provided on the command line exactly as the fields are named, unlike the original proposal where it's ambiguous to an unassuming user as for whether the field `a: i32` will become the short option `-a` or the long option `--a`, or whether `cache_dir` becomes `--cache_dir` or `--cache-dir`. Here, what you see is exactly what you get. I also feel that requiring options to be named like actual options is intuitive. If I was completely new to a language and saw a struct with fields named like `@"--output"`, I would immediately clock it as having to do with command-line options. Because args parsing is a common task that you're likely to run into early on, it's also a good opportunity for introducing newcomes to the language to the `@""` identifier syntax and teaching them that Zig allows any arbitrary identifier name using this form. Structurally, this design is also the simplest, with a completely flattened struct. I'll admit that I too was initially a bit concerned about whether `args.@"--option"` would feel like too much visual noise, but now after having updated the 20+ internal tools I don't feel like it was much of an issue at all. It certainly didn't bother me any more than something like `assert(@typeInfo(@TypeOf(foo)).@"struct".layout == .@"extern")` 😛
First-time contributor
Copy link

Maybe a good future enhancement to std.Io/cli.Terminal would be to offer a writer mode that strips ANSI SGR control sequences when disabled/unsupported, so that people can pre-bake ANSI styling into their help string literals

How are you going to deal with terminal feature detection? That's pretty much an unsolved problem that would pollute stdlib imo.
The "standard" way of doing that with terminfo/termcaps is not something I'd ever want in std. This article provides some insights.
How would you handle blinking text for example? Not all terminals support that, including popular and modern terminal emulators such as Kitty, and Alacritty, and there is no direct/standardized way to handle that.
I like the idea of a writer that strips unsupported escape sequences at comptime, but that implies two things:

  • The user has to choose a set of supported terminals (how?)
  • Heuristics, you can only guess with so much accuracy

I think it is more than reasonable however, to include ANSI color codes, as of status quo, since those have been supported by hardware since the 70-80s. A good rule of thumb could be "if the Linux kernel's terminal can display it, it's safe to support it", because the Linux kernel's terminal aims to be compatible with virtually all terminal hardware. Note that I said "display", not parse, as it reduces truecolor escape sequences and 8 bit colors to color codes anyways. In theory, a terminal emulator could not implement these escape sequences, but I think it is more than reasonable to have color codes as a baseline.

Another approach would be to specify that the style may not be displayed depending on the terminal. That is also more reasonable than feature detection imo. In that case, it would be acceptable to support commonly defined sequences, basically ANSI + XTerm (truecolor, 8 bit color codes, and all SRG sequences relevant to printing stylized text).
In that regard, doing anything other than rendering stylized text (bg, fg color, bold, italic...), line by line, should be out of scope for an std API.

Don't hesitate to tell me if I misunderstood what you meant or completely missed the point.

Side Note: The std.Io.Terminal.setColor function could also use escape sequences for windows, as Windows 10 supports ANSI escape sequences as well, that could remove duplication (which is mostly why win10 started supporting it). I don't know if that would be more efficient however. The MSDN doc specifies that these APIs are present for backwards compatibilty, whilst not being deprecated.

> Maybe a good future enhancement to std.Io/cli.Terminal would be to offer a writer mode that strips ANSI SGR control sequences when disabled/unsupported, so that people can pre-bake ANSI styling into their help string literals How are you going to deal with terminal feature detection? That's pretty much an unsolved problem that would pollute stdlib imo. The "standard" way of doing that with terminfo/termcaps is not something I'd *ever* want in std. [This article](https://lobste.rs/s/m1j4b4/terminfo_at_this_point_time_is_net) provides some insights. How would you handle blinking text for example? Not all terminals support that, including popular and modern terminal emulators such as Kitty, and Alacritty, and there is no direct/standardized way to handle that. I like the idea of a writer that strips unsupported escape sequences at comptime, but that implies two things: - The user has to choose a set of supported terminals (how?) - Heuristics, you can only guess with so much accuracy I think it is more than reasonable however, to include ANSI color codes, as of status quo, since those have been supported by *hardware* since the 70-80s. A good rule of thumb could be "if the Linux kernel's terminal can display it, it's safe to support it", because the Linux kernel's terminal aims to be compatible with virtually all terminal *hardware*. Note that I said "display", not parse, as it reduces truecolor escape sequences and 8 bit colors to color codes anyways. In theory, a terminal emulator could not implement these escape sequences, but I think it is more than reasonable to have color codes as a baseline. Another approach would be to specify that the style may not be displayed depending on the terminal. That is also more reasonable than feature detection imo. In that case, it would be acceptable to support *commonly* defined sequences, basically ANSI + XTerm (truecolor, 8 bit color codes, and all SRG sequences relevant to printing stylized text). In that regard, doing anything other than rendering stylized text (bg, fg color, bold, italic...), line by line, should be out of scope for an std API. ***Don't hesitate to tell me if I misunderstood what you meant or completely missed the point.*** **Side Note**: The `std.Io.Terminal.setColor` function could also use escape sequences for windows, as Windows 10 supports ANSI escape sequences as well, that could remove duplication (which is mostly why win10 started supporting it). I don't know if that would be more efficient however. [The MSDN doc](https://learn.microsoft.com/en-us/windows/console/setconsoletextattribute) specifies that these APIs are present for backwards compatibilty, whilst not being deprecated.
First-time contributor
Copy link

Personaly I think this is quite useless, its simple to implement something like this with a tiny bit of comptime. If this was added I wouldnt even use it tbh because argument parsing is already easy.

Personaly I think this is quite *useless*, its simple to implement something like this with a tiny bit of comptime. If this was added I wouldnt even use it tbh because argument parsing is already easy.
castholm force-pushed cli-args-parser from 201a120e22
All checks were successful
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / x86_64-netbsd-release (pull_request) Successful in 40m45s
ci / x86_64-freebsd-release (pull_request) Successful in 43m24s
ci / x86_64-freebsd-debug (pull_request) Successful in 45m19s
ci / x86_64-openbsd-release (pull_request) Successful in 45m42s
ci / x86_64-netbsd-debug (pull_request) Successful in 45m47s
ci / x86_64-windows-release (pull_request) Successful in 47m54s
ci / x86_64-windows-debug (pull_request) Successful in 51m46s
ci / x86_64-openbsd-debug (pull_request) Successful in 54m18s
ci / x86_64-linux-debug (pull_request) Successful in 57m7s
ci / aarch64-macos-release (pull_request) Successful in 1h1m1s
ci / aarch64-macos-debug (pull_request) Successful in 1h13m29s
ci / aarch64-linux-release (pull_request) Successful in 1h26m55s
ci / s390x-linux-release (pull_request) Successful in 1h28m16s
ci / loongarch64-linux-release (pull_request) Successful in 1h41m12s
ci / powerpc64le-linux-release (pull_request) Successful in 1h52m27s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 2h10m23s
ci / s390x-linux-debug (pull_request) Successful in 2h16m30s
ci / x86_64-linux-release (pull_request) Successful in 2h24m3s
ci / aarch64-linux-debug (pull_request) Successful in 2h36m43s
ci / loongarch64-linux-debug (pull_request) Successful in 2h45m20s
ci / aarch64-freebsd-debug (pull_request) Successful in 4h17m18s
ci / powerpc64le-linux-debug (pull_request) Successful in 4h35m55s
ci / aarch64-freebsd-release (pull_request) Successful in 3h16m42s
ci / aarch64-netbsd-debug (pull_request) Successful in 4h19m0s
ci / aarch64-netbsd-release (pull_request) Successful in 3h31m12s
to 86f581c99f
All checks were successful
ci / x86_64-netbsd-debug (pull_request) Successful in 56m0s
ci / x86_64-netbsd-release (pull_request) Successful in 58m1s
ci / x86_64-freebsd-release (pull_request) Successful in 59m51s
ci / x86_64-freebsd-debug (pull_request) Successful in 1h3m29s
ci / x86_64-windows-release (pull_request) Successful in 1h4m12s
ci / x86_64-linux-debug (pull_request) Successful in 1h5m16s
ci / x86_64-windows-debug (pull_request) Successful in 1h14m15s
ci / x86_64-openbsd-release (pull_request) Successful in 1h29m44s
ci / aarch64-linux-release (pull_request) Successful in 1h32m1s
ci / aarch64-macos-release (pull_request) Successful in 1h39m11s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h40m0s
ci / aarch64-macos-debug (pull_request) Successful in 1h58m22s
ci / powerpc64le-linux-release (pull_request) Successful in 2h27m9s
ci / aarch64-linux-debug (pull_request) Successful in 2h37m6s
ci / x86_64-linux-release (pull_request) Successful in 3h28m41s
ci / s390x-linux-debug (pull_request) Successful in 2h31m17s
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / s390x-linux-release (pull_request) Successful in 1h55m44s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 3h48m49s
ci / powerpc64le-linux-debug (pull_request) Successful in 5h50m7s
ci / loongarch64-linux-release (pull_request) Successful in 2h10m30s
ci / loongarch64-linux-debug (pull_request) Successful in 3h11m40s
ci / aarch64-netbsd-debug (pull_request) Successful in 4h0m27s
ci / aarch64-freebsd-debug (pull_request) Successful in 3h58m51s
ci / aarch64-netbsd-release (pull_request) Successful in 3h28m8s
ci / aarch64-freebsd-release (pull_request) Successful in 3h52m17s
2026年05月20日 00:58:23 +02:00
Compare
Author
Contributor
Copy link

@Souleymeine wrote in #35304 (comment):

How are you going to deal with terminal feature detection? That's pretty much an unsolved problem that would pollute stdlib imo.

std.Io.Terminal already handles detection of color support/preferences in a simple, de-facto standardized manner using the NO_COLOR/CLICOLOR_FORCE environment variables and std.file.enableAnsiEscapeCodes/std.file.isTty, and it already handles modern Windows ANSI escape code support.

I am not suggesting adding terminfo support or any kind of emulation. My proposition is simply that there should be a writer or function that, if ANSI escape codes are detected as unsupported or disabled using the already existing means, strips SGR sequences (as a binary "keep all" or "strip all" toggle and not on a sequence-by-sequence basis). Which sequences one would use, out of concern for feature support and presentation issues, would be up to each user's own judgment, just like it is now with the (albeit limited) set of styles defined in std.Io.Terminal.Color.

As you can see from parts of this change set, calling setColor inline is quite cumbersome and limits the ability to take a pre-styled string as an input, so something like a stripping writer would be an improvement over status quo and relatively trivial to implement.

@Souleymeine wrote in https://codeberg.org/ziglang/zig/pulls/35304#issuecomment-15197520: > How are you going to deal with terminal feature detection? That's pretty much an unsolved problem that would pollute stdlib imo. `std.Io.Terminal` already handles detection of color support/preferences in a simple, de-facto standardized manner using the `NO_COLOR`/`CLICOLOR_FORCE` environment variables and `std.file.enableAnsiEscapeCodes`/`std.file.isTty`, and it already handles modern Windows ANSI escape code support. I am not suggesting adding terminfo support or any kind of emulation. My proposition is simply that there should be a writer or function that, if ANSI escape codes are detected as unsupported or disabled using the already existing means, strips SGR sequences (as a binary "keep all" or "strip all" toggle and not on a sequence-by-sequence basis). Which sequences one would use, out of concern for feature support and presentation issues, would be up to each user's own judgment, just like it is now with the (albeit limited) set of styles defined in `std.Io.Terminal.Color`. As you can see from parts of this change set, calling `setColor` inline is quite cumbersome and limits the ability to take a pre-styled string as an input, so something like a stripping writer would be an improvement over status quo and relatively trivial to implement.
castholm force-pushed cli-args-parser from 86f581c99f
All checks were successful
ci / x86_64-netbsd-debug (pull_request) Successful in 56m0s
ci / x86_64-netbsd-release (pull_request) Successful in 58m1s
ci / x86_64-freebsd-release (pull_request) Successful in 59m51s
ci / x86_64-freebsd-debug (pull_request) Successful in 1h3m29s
ci / x86_64-windows-release (pull_request) Successful in 1h4m12s
ci / x86_64-linux-debug (pull_request) Successful in 1h5m16s
ci / x86_64-windows-debug (pull_request) Successful in 1h14m15s
ci / x86_64-openbsd-release (pull_request) Successful in 1h29m44s
ci / aarch64-linux-release (pull_request) Successful in 1h32m1s
ci / aarch64-macos-release (pull_request) Successful in 1h39m11s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h40m0s
ci / aarch64-macos-debug (pull_request) Successful in 1h58m22s
ci / powerpc64le-linux-release (pull_request) Successful in 2h27m9s
ci / aarch64-linux-debug (pull_request) Successful in 2h37m6s
ci / x86_64-linux-release (pull_request) Successful in 3h28m41s
ci / s390x-linux-debug (pull_request) Successful in 2h31m17s
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / s390x-linux-release (pull_request) Successful in 1h55m44s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 3h48m49s
ci / powerpc64le-linux-debug (pull_request) Successful in 5h50m7s
ci / loongarch64-linux-release (pull_request) Successful in 2h10m30s
ci / loongarch64-linux-debug (pull_request) Successful in 3h11m40s
ci / aarch64-netbsd-debug (pull_request) Successful in 4h0m27s
ci / aarch64-freebsd-debug (pull_request) Successful in 3h58m51s
ci / aarch64-netbsd-release (pull_request) Successful in 3h28m8s
ci / aarch64-freebsd-release (pull_request) Successful in 3h52m17s
to 07ff4307ca
All checks were successful
ci / x86_64-netbsd-release (pull_request) Successful in 52m54s
ci / x86_64-openbsd-release (pull_request) Successful in 54m21s
ci / x86_64-netbsd-debug (pull_request) Successful in 56m33s
ci / x86_64-freebsd-debug (pull_request) Successful in 59m4s
ci / x86_64-freebsd-release (pull_request) Successful in 58m53s
ci / x86_64-windows-release (pull_request) Successful in 59m37s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h10m42s
ci / x86_64-windows-debug (pull_request) Successful in 1h23m14s
ci / x86_64-linux-debug (pull_request) Successful in 1h26m52s
ci / aarch64-linux-release (pull_request) Successful in 1h41m12s
ci / aarch64-macos-release (pull_request) Successful in 1h43m53s
ci / aarch64-macos-debug (pull_request) Successful in 2h8m34s
ci / powerpc64le-linux-release (pull_request) Successful in 2h11m18s
ci / s390x-linux-release (pull_request) Successful in 2h15m31s
ci / aarch64-linux-debug (pull_request) Successful in 2h28m2s
ci / s390x-linux-debug (pull_request) Successful in 2h46m46s
ci / loongarch64-linux-release (pull_request) Successful in 2h18m22s
ci / x86_64-linux-release (pull_request) Successful in 3h7m31s
ci / loongarch64-linux-debug (pull_request) Successful in 3h29m35s
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / x86_64-linux-debug-llvm (pull_request) Successful in 4h17m47s
ci / powerpc64le-linux-debug (pull_request) Successful in 5h19m1s
ci / aarch64-netbsd-debug (pull_request) Successful in 4h22m30s
ci / aarch64-netbsd-release (pull_request) Successful in 3h36m10s
ci / aarch64-freebsd-debug (pull_request) Successful in 4h17m58s
ci / aarch64-freebsd-release (pull_request) Successful in 3h8m34s
2026年05月21日 23:48:59 +02:00
Compare
castholm force-pushed cli-args-parser from 07ff4307ca
All checks were successful
ci / x86_64-netbsd-release (pull_request) Successful in 52m54s
ci / x86_64-openbsd-release (pull_request) Successful in 54m21s
ci / x86_64-netbsd-debug (pull_request) Successful in 56m33s
ci / x86_64-freebsd-debug (pull_request) Successful in 59m4s
ci / x86_64-freebsd-release (pull_request) Successful in 58m53s
ci / x86_64-windows-release (pull_request) Successful in 59m37s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h10m42s
ci / x86_64-windows-debug (pull_request) Successful in 1h23m14s
ci / x86_64-linux-debug (pull_request) Successful in 1h26m52s
ci / aarch64-linux-release (pull_request) Successful in 1h41m12s
ci / aarch64-macos-release (pull_request) Successful in 1h43m53s
ci / aarch64-macos-debug (pull_request) Successful in 2h8m34s
ci / powerpc64le-linux-release (pull_request) Successful in 2h11m18s
ci / s390x-linux-release (pull_request) Successful in 2h15m31s
ci / aarch64-linux-debug (pull_request) Successful in 2h28m2s
ci / s390x-linux-debug (pull_request) Successful in 2h46m46s
ci / loongarch64-linux-release (pull_request) Successful in 2h18m22s
ci / x86_64-linux-release (pull_request) Successful in 3h7m31s
ci / loongarch64-linux-debug (pull_request) Successful in 3h29m35s
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / x86_64-linux-debug-llvm (pull_request) Successful in 4h17m47s
ci / powerpc64le-linux-debug (pull_request) Successful in 5h19m1s
ci / aarch64-netbsd-debug (pull_request) Successful in 4h22m30s
ci / aarch64-netbsd-release (pull_request) Successful in 3h36m10s
ci / aarch64-freebsd-debug (pull_request) Successful in 4h17m58s
ci / aarch64-freebsd-release (pull_request) Successful in 3h8m34s
to 82039e49d0
Some checks failed
ci / x86_64-netbsd-debug (pull_request) Successful in 56m34s
ci / x86_64-freebsd-release (pull_request) Failing after 37m18s
ci / x86_64-netbsd-release (pull_request) Successful in 55m52s
ci / x86_64-freebsd-debug (pull_request) Failing after 1h4m17s
ci / aarch64-macos-release (pull_request) Successful in 1h38m29s
ci / x86_64-openbsd-release (pull_request) Successful in 1h5m4s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h14m39s
ci / aarch64-macos-debug (pull_request) Successful in 2h6m33s
ci / x86_64-windows-debug (pull_request) Successful in 1h9m22s
ci / x86_64-windows-release (pull_request) Successful in 1h4m38s
ci / aarch64-linux-release (pull_request) Successful in 1h44m13s
ci / aarch64-linux-debug (pull_request) Successful in 2h26m24s
ci / powerpc64le-linux-release (pull_request) Successful in 2h19m32s
ci / aarch64-freebsd-debug (pull_request) Has been cancelled
ci / aarch64-freebsd-release (pull_request) Has been cancelled
ci / aarch64-netbsd-debug (pull_request) Has been cancelled
ci / aarch64-netbsd-release (pull_request) Has been cancelled
ci / loongarch64-linux-debug (pull_request) Has been cancelled
ci / loongarch64-linux-release (pull_request) Has been cancelled
ci / riscv64-linux-debug (pull_request) Has been cancelled
ci / riscv64-linux-release (pull_request) Has been cancelled
ci / x86_64-linux-debug (pull_request) Has been cancelled
ci / x86_64-linux-debug-llvm (pull_request) Has been cancelled
ci / x86_64-linux-release (pull_request) Has been cancelled
ci / s390x-linux-debug (pull_request) Has been cancelled
ci / s390x-linux-release (pull_request) Has been cancelled
ci / powerpc64le-linux-debug (pull_request) Has been cancelled
2026年05月27日 01:47:34 +02:00
Compare
alexrp force-pushed cli-args-parser from 82039e49d0
Some checks failed
ci / x86_64-netbsd-debug (pull_request) Successful in 56m34s
ci / x86_64-freebsd-release (pull_request) Failing after 37m18s
ci / x86_64-netbsd-release (pull_request) Successful in 55m52s
ci / x86_64-freebsd-debug (pull_request) Failing after 1h4m17s
ci / aarch64-macos-release (pull_request) Successful in 1h38m29s
ci / x86_64-openbsd-release (pull_request) Successful in 1h5m4s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h14m39s
ci / aarch64-macos-debug (pull_request) Successful in 2h6m33s
ci / x86_64-windows-debug (pull_request) Successful in 1h9m22s
ci / x86_64-windows-release (pull_request) Successful in 1h4m38s
ci / aarch64-linux-release (pull_request) Successful in 1h44m13s
ci / aarch64-linux-debug (pull_request) Successful in 2h26m24s
ci / powerpc64le-linux-release (pull_request) Successful in 2h19m32s
ci / aarch64-freebsd-debug (pull_request) Has been cancelled
ci / aarch64-freebsd-release (pull_request) Has been cancelled
ci / aarch64-netbsd-debug (pull_request) Has been cancelled
ci / aarch64-netbsd-release (pull_request) Has been cancelled
ci / loongarch64-linux-debug (pull_request) Has been cancelled
ci / loongarch64-linux-release (pull_request) Has been cancelled
ci / riscv64-linux-debug (pull_request) Has been cancelled
ci / riscv64-linux-release (pull_request) Has been cancelled
ci / x86_64-linux-debug (pull_request) Has been cancelled
ci / x86_64-linux-debug-llvm (pull_request) Has been cancelled
ci / x86_64-linux-release (pull_request) Has been cancelled
ci / s390x-linux-debug (pull_request) Has been cancelled
ci / s390x-linux-release (pull_request) Has been cancelled
ci / powerpc64le-linux-debug (pull_request) Has been cancelled
to d532744a70
Some checks failed
ci / aarch64-macos-release (pull_request) Successful in 1h20m57s
ci / x86_64-netbsd-debug (pull_request) Successful in 52m30s
ci / x86_64-netbsd-release (pull_request) Successful in 55m2s
ci / x86_64-freebsd-release (pull_request) Successful in 59m8s
ci / x86_64-freebsd-debug (pull_request) Successful in 1h2m10s
ci / aarch64-macos-debug (pull_request) Successful in 2h32m8s
ci / aarch64-linux-release (pull_request) Successful in 1h32m49s
ci / aarch64-linux-debug (pull_request) Successful in 2h28m14s
ci / powerpc64le-linux-release (pull_request) Successful in 2h31m50s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h3m15s
ci / x86_64-openbsd-release (pull_request) Successful in 1h3m45s
ci / powerpc64le-linux-debug (pull_request) Successful in 3h21m18s
ci / x86_64-windows-release (pull_request) Successful in 1h6m49s
ci / x86_64-windows-debug (pull_request) Successful in 1h30m55s
ci / s390x-linux-release (pull_request) Successful in 1h30m47s
ci / x86_64-linux-debug (pull_request) Successful in 1h10m53s
ci / s390x-linux-debug (pull_request) Successful in 3h22m31s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 4h0m58s
ci / x86_64-linux-release (pull_request) Successful in 4h33m24s
ci / aarch64-freebsd-debug (pull_request) Has been cancelled
ci / aarch64-freebsd-release (pull_request) Has been cancelled
ci / aarch64-netbsd-debug (pull_request) Has been cancelled
ci / aarch64-netbsd-release (pull_request) Has been cancelled
ci / riscv64-linux-debug (pull_request) Has been cancelled
ci / riscv64-linux-release (pull_request) Has been cancelled
ci / loongarch64-linux-debug (pull_request) Has been cancelled
ci / loongarch64-linux-release (pull_request) Has been cancelled
2026年05月27日 05:44:50 +02:00
Compare
castholm force-pushed cli-args-parser from d532744a70
Some checks failed
ci / aarch64-macos-release (pull_request) Successful in 1h20m57s
ci / x86_64-netbsd-debug (pull_request) Successful in 52m30s
ci / x86_64-netbsd-release (pull_request) Successful in 55m2s
ci / x86_64-freebsd-release (pull_request) Successful in 59m8s
ci / x86_64-freebsd-debug (pull_request) Successful in 1h2m10s
ci / aarch64-macos-debug (pull_request) Successful in 2h32m8s
ci / aarch64-linux-release (pull_request) Successful in 1h32m49s
ci / aarch64-linux-debug (pull_request) Successful in 2h28m14s
ci / powerpc64le-linux-release (pull_request) Successful in 2h31m50s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h3m15s
ci / x86_64-openbsd-release (pull_request) Successful in 1h3m45s
ci / powerpc64le-linux-debug (pull_request) Successful in 3h21m18s
ci / x86_64-windows-release (pull_request) Successful in 1h6m49s
ci / x86_64-windows-debug (pull_request) Successful in 1h30m55s
ci / s390x-linux-release (pull_request) Successful in 1h30m47s
ci / x86_64-linux-debug (pull_request) Successful in 1h10m53s
ci / s390x-linux-debug (pull_request) Successful in 3h22m31s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 4h0m58s
ci / x86_64-linux-release (pull_request) Successful in 4h33m24s
ci / aarch64-freebsd-debug (pull_request) Has been cancelled
ci / aarch64-freebsd-release (pull_request) Has been cancelled
ci / aarch64-netbsd-debug (pull_request) Has been cancelled
ci / aarch64-netbsd-release (pull_request) Has been cancelled
ci / riscv64-linux-debug (pull_request) Has been cancelled
ci / riscv64-linux-release (pull_request) Has been cancelled
ci / loongarch64-linux-debug (pull_request) Has been cancelled
ci / loongarch64-linux-release (pull_request) Has been cancelled
to d80f9fb878
All checks were successful
ci / x86_64-netbsd-debug (pull_request) Successful in 51m17s
ci / x86_64-netbsd-release (pull_request) Successful in 54m33s
ci / x86_64-freebsd-release (pull_request) Successful in 54m27s
ci / aarch64-macos-release (pull_request) Successful in 1h14m10s
ci / x86_64-freebsd-debug (pull_request) Successful in 1h1m1s
ci / aarch64-macos-debug (pull_request) Successful in 1h37m43s
ci / aarch64-linux-release (pull_request) Successful in 1h41m22s
ci / x86_64-openbsd-release (pull_request) Successful in 1h3m42s
ci / powerpc64le-linux-release (pull_request) Successful in 2h8m2s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h20m26s
ci / aarch64-linux-debug (pull_request) Successful in 2h25m42s
ci / x86_64-windows-release (pull_request) Successful in 53m32s
ci / x86_64-windows-debug (pull_request) Successful in 1h7m49s
ci / powerpc64le-linux-debug (pull_request) Successful in 5h15m2s
ci / s390x-linux-release (pull_request) Successful in 1h27m35s
ci / s390x-linux-debug (pull_request) Successful in 2h32m55s
ci / x86_64-linux-debug (pull_request) Successful in 1h1m7s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 4h7m44s
ci / x86_64-linux-release (pull_request) Successful in 4h14m25s
ci / loongarch64-linux-release (pull_request) Successful in 2h16m24s
ci / loongarch64-linux-debug (pull_request) Successful in 3h20m39s
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / aarch64-freebsd-debug (pull_request) Has been skipped
ci / aarch64-freebsd-release (pull_request) Has been skipped
ci / aarch64-netbsd-debug (pull_request) Has been skipped
ci / aarch64-netbsd-release (pull_request) Has been skipped
2026年05月28日 00:59:09 +02:00
Compare
Author
Contributor
Copy link

std.cli.ArgsParser can now parse subcommands, represented as tagged unions:

constCommand=union(enum){multiply:struct{x:i32,y:i32,pubconst@"--help":std.cli.Help(@This())=.{.description="Multiplies two integers and prints the product.",.args=.{.x=.{.description="First factor"},.y=.{.description="Second factor"},},};},divide:struct{x:i32,y:i32,@"--round":enum{@"toward-zero",down,up}=.@"toward-zero",pubconst@"--help":std.cli.Help(@This())=.{.description="Divides two integers and prints the quotient.",.args=.{.x=.{.description="Dividend"},.y=.{.description="Divisor (must not be 0)"},.@"--round"=.{.display="(toward-zero|down|up)",.description="Rounding mode"},},};},pubconst@"--help":std.cli.Help(@This())=.{.command_name="math",.description="Math!",.args=.{.multiply=.{.description="Multiply integers"},.divide=.{.description="Divide integers"},},};};pubfnmain(init:std.process.Init,cmd:Command)!void{// ...}
$ ./math --help
Usage: math [<option>...] <command> [<argument>...]
Math!
Commands:
 multiply Multiply integers
 divide Divide integers
Options:
 -h, --help Print this help and exit
$ ./math divide 10
error: incorrect number of arguments (expected 2)
Try 'math divide --help' for more information.
$ ./math divide --help
Usage: math divide [<option>...] [--] <x> <y>
Divides two integers and prints the quotient.
Arguments:
 <x> Dividend
 <y> Divisor (must not be 0)
Options:
 --round=(toward-zero|down|up) Rounding mode
 -h, --help Print this help and exit
`std.cli.ArgsParser` can now parse subcommands, represented as tagged unions: ```zig const Command = union(enum) { multiply: struct { x: i32, y: i32, pub const @"--help": std.cli.Help(@This()) = .{ .description = "Multiplies two integers and prints the product.", .args = .{ .x = .{ .description = "First factor" }, .y = .{ .description = "Second factor" }, }, }; }, divide: struct { x: i32, y: i32, @"--round": enum { @"toward-zero", down, up } = .@"toward-zero", pub const @"--help": std.cli.Help(@This()) = .{ .description = "Divides two integers and prints the quotient.", .args = .{ .x = .{ .description = "Dividend" }, .y = .{ .description = "Divisor (must not be 0)" }, .@"--round" = .{ .display = "(toward-zero|down|up)", .description = "Rounding mode" }, }, }; }, pub const @"--help": std.cli.Help(@This()) = .{ .command_name = "math", .description = "Math!", .args = .{ .multiply = .{ .description = "Multiply integers" }, .divide = .{ .description = "Divide integers" }, }, }; }; pub fn main(init: std.process.Init, cmd: Command) !void { // ... } ``` ``` $ ./math --help Usage: math [<option>...] <command> [<argument>...] Math! Commands: multiply Multiply integers divide Divide integers Options: -h, --help Print this help and exit ``` ``` $ ./math divide 10 error: incorrect number of arguments (expected 2) Try 'math divide --help' for more information. ``` ``` $ ./math divide --help Usage: math divide [<option>...] [--] <x> <y> Divides two integers and prints the quotient. Arguments: <x> Dividend <y> Divisor (must not be 0) Options: --round=(toward-zero|down|up) Rounding mode -h, --help Print this help and exit ```
castholm force-pushed cli-args-parser from d80f9fb878
All checks were successful
ci / x86_64-netbsd-debug (pull_request) Successful in 51m17s
ci / x86_64-netbsd-release (pull_request) Successful in 54m33s
ci / x86_64-freebsd-release (pull_request) Successful in 54m27s
ci / aarch64-macos-release (pull_request) Successful in 1h14m10s
ci / x86_64-freebsd-debug (pull_request) Successful in 1h1m1s
ci / aarch64-macos-debug (pull_request) Successful in 1h37m43s
ci / aarch64-linux-release (pull_request) Successful in 1h41m22s
ci / x86_64-openbsd-release (pull_request) Successful in 1h3m42s
ci / powerpc64le-linux-release (pull_request) Successful in 2h8m2s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h20m26s
ci / aarch64-linux-debug (pull_request) Successful in 2h25m42s
ci / x86_64-windows-release (pull_request) Successful in 53m32s
ci / x86_64-windows-debug (pull_request) Successful in 1h7m49s
ci / powerpc64le-linux-debug (pull_request) Successful in 5h15m2s
ci / s390x-linux-release (pull_request) Successful in 1h27m35s
ci / s390x-linux-debug (pull_request) Successful in 2h32m55s
ci / x86_64-linux-debug (pull_request) Successful in 1h1m7s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 4h7m44s
ci / x86_64-linux-release (pull_request) Successful in 4h14m25s
ci / loongarch64-linux-release (pull_request) Successful in 2h16m24s
ci / loongarch64-linux-debug (pull_request) Successful in 3h20m39s
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / aarch64-freebsd-debug (pull_request) Has been skipped
ci / aarch64-freebsd-release (pull_request) Has been skipped
ci / aarch64-netbsd-debug (pull_request) Has been skipped
ci / aarch64-netbsd-release (pull_request) Has been skipped
to 06672fd9ce
All checks were successful
ci / aarch64-macos-release (pull_request) Successful in 1h39m24s
ci / aarch64-macos-debug (pull_request) Successful in 2h11m50s
ci / x86_64-freebsd-debug (pull_request) Successful in 1h4m50s
ci / x86_64-freebsd-release (pull_request) Successful in 1h4m38s
ci / x86_64-netbsd-debug (pull_request) Successful in 1h3m50s
ci / aarch64-linux-release (pull_request) Successful in 1h37m28s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h13m16s
ci / powerpc64le-linux-release (pull_request) Successful in 2h16m35s
ci / aarch64-linux-debug (pull_request) Successful in 2h30m36s
ci / x86_64-openbsd-release (pull_request) Successful in 1h3m17s
ci / x86_64-netbsd-release (pull_request) Successful in 48m49s
ci / x86_64-windows-release (pull_request) Successful in 1h11m47s
ci / x86_64-windows-debug (pull_request) Successful in 1h28m10s
ci / s390x-linux-release (pull_request) Successful in 1h43m4s
ci / x86_64-linux-debug (pull_request) Successful in 55m21s
ci / powerpc64le-linux-debug (pull_request) Successful in 4h57m58s
ci / s390x-linux-debug (pull_request) Successful in 2h53m45s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 3h54m28s
ci / x86_64-linux-release (pull_request) Successful in 4h7m32s
ci / loongarch64-linux-release (pull_request) Successful in 2h11m9s
ci / loongarch64-linux-debug (pull_request) Successful in 3h35m59s
ci / aarch64-freebsd-debug (pull_request) Has been skipped
ci / aarch64-freebsd-release (pull_request) Has been skipped
ci / aarch64-netbsd-release (pull_request) Has been skipped
ci / aarch64-netbsd-debug (pull_request) Has been skipped
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
2026年06月07日 22:36:34 +02:00
Compare
@ -0,0 +22,4 @@
//! followed by its argument, separated by either `=` or whitespace;
//! for example, `--foo=bar` or `--foo bar`.
//! - An *optional-argument option* receives its argument in the same way as
//! as the non-whitespace-separated form of a required-argument option;
Contributor
Copy link

The word "as" is duplicated across the two lines here.

The word "as" is duplicated across the two lines here.
castholm marked this conversation as resolved
castholm force-pushed cli-args-parser from 06672fd9ce
All checks were successful
ci / aarch64-macos-release (pull_request) Successful in 1h39m24s
ci / aarch64-macos-debug (pull_request) Successful in 2h11m50s
ci / x86_64-freebsd-debug (pull_request) Successful in 1h4m50s
ci / x86_64-freebsd-release (pull_request) Successful in 1h4m38s
ci / x86_64-netbsd-debug (pull_request) Successful in 1h3m50s
ci / aarch64-linux-release (pull_request) Successful in 1h37m28s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h13m16s
ci / powerpc64le-linux-release (pull_request) Successful in 2h16m35s
ci / aarch64-linux-debug (pull_request) Successful in 2h30m36s
ci / x86_64-openbsd-release (pull_request) Successful in 1h3m17s
ci / x86_64-netbsd-release (pull_request) Successful in 48m49s
ci / x86_64-windows-release (pull_request) Successful in 1h11m47s
ci / x86_64-windows-debug (pull_request) Successful in 1h28m10s
ci / s390x-linux-release (pull_request) Successful in 1h43m4s
ci / x86_64-linux-debug (pull_request) Successful in 55m21s
ci / powerpc64le-linux-debug (pull_request) Successful in 4h57m58s
ci / s390x-linux-debug (pull_request) Successful in 2h53m45s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 3h54m28s
ci / x86_64-linux-release (pull_request) Successful in 4h7m32s
ci / loongarch64-linux-release (pull_request) Successful in 2h11m9s
ci / loongarch64-linux-debug (pull_request) Successful in 3h35m59s
ci / aarch64-freebsd-debug (pull_request) Has been skipped
ci / aarch64-freebsd-release (pull_request) Has been skipped
ci / aarch64-netbsd-release (pull_request) Has been skipped
ci / aarch64-netbsd-debug (pull_request) Has been skipped
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
to edabb898de
All checks were successful
ci / aarch64-macos-release (pull_request) Successful in 1h58m6s
ci / x86_64-netbsd-release (pull_request) Successful in 1h12m26s
ci / x86_64-netbsd-debug (pull_request) Successful in 1h18m16s
ci / aarch64-linux-release (pull_request) Successful in 1h44m17s
ci / x86_64-freebsd-debug (pull_request) Successful in 1h18m14s
ci / x86_64-freebsd-release (pull_request) Successful in 1h14m38s
ci / x86_64-openbsd-release (pull_request) Successful in 1h24m58s
ci / x86_64-openbsd-debug (pull_request) Successful in 1h31m59s
ci / powerpc64le-linux-release (pull_request) Successful in 2h20m51s
ci / aarch64-macos-debug (pull_request) Successful in 3h31m3s
ci / aarch64-linux-debug (pull_request) Successful in 3h10m36s
ci / x86_64-windows-release (pull_request) Successful in 1h23m5s
ci / x86_64-windows-debug (pull_request) Successful in 1h52m26s
ci / powerpc64le-linux-debug (pull_request) Successful in 4h14m26s
ci / aarch64-freebsd-debug (pull_request) Has been skipped
ci / aarch64-freebsd-release (pull_request) Has been skipped
ci / x86_64-linux-debug (pull_request) Successful in 1h45m14s
ci / s390x-linux-release (pull_request) Successful in 1h39m58s
ci / x86_64-linux-debug-llvm (pull_request) Successful in 3h48m47s
ci / aarch64-netbsd-debug (pull_request) Has been skipped
ci / aarch64-netbsd-release (pull_request) Has been skipped
ci / x86_64-linux-release (pull_request) Successful in 4h6m53s
ci / s390x-linux-debug (pull_request) Successful in 6h51m52s
ci / loongarch64-linux-release (pull_request) Successful in 2h31m0s
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / loongarch64-linux-debug (pull_request) Successful in 4h5m47s
2026年06月25日 23:34:56 +02:00
Compare
Contributor
Copy link

@castholm wrote in #35304 (comment):

Do you think you could elaborate on why you feel it bothers you? Is it purely an aesthetic preference and a subjective distaste for @"", or is it a concern about readability and developer ergonomics/typing?

Yes, it's subjective distaste for @"". In my view, any such escaping mechanism should be used as a tool to deal with exceptional cases, not to handle common cases. I see this as a hack around the fact that Zig doesn't have Go-style field name tags, and I personally don't think stdlib should adopt such hacks. My personal opinion is that the positional / options split would be a much better solution, with the convention that _ is replaced by - for the CLI args.

@castholm wrote in https://codeberg.org/ziglang/zig/pulls/35304#issuecomment-15044859: > Do you think you could elaborate on why you feel it bothers you? Is it purely an aesthetic preference and a subjective distaste for `@""`, or is it a concern about readability and developer ergonomics/typing? Yes, it's subjective distaste for `@""`. In my view, any such escaping mechanism should be used as a tool to deal with exceptional cases, not to handle common cases. I see this as a hack around the fact that Zig doesn't have Go-style field name tags, and I personally don't think stdlib should adopt such hacks. My personal opinion is that the `positional` / `options` split would be a much better solution, with the convention that `_` is replaced by `-` for the CLI args.
All checks were successful
ci / aarch64-macos-release (pull_request) Successful in 1h58m6s
Required
Details
ci / x86_64-netbsd-release (pull_request) Successful in 1h12m26s
Required
Details
ci / x86_64-netbsd-debug (pull_request) Successful in 1h18m16s
Required
Details
ci / aarch64-linux-release (pull_request) Successful in 1h44m17s
Required
Details
ci / x86_64-freebsd-debug (pull_request) Successful in 1h18m14s
Required
Details
ci / x86_64-freebsd-release (pull_request) Successful in 1h14m38s
Required
Details
ci / x86_64-openbsd-release (pull_request) Successful in 1h24m58s
Required
Details
ci / x86_64-openbsd-debug (pull_request) Successful in 1h31m59s
Required
Details
ci / powerpc64le-linux-release (pull_request) Successful in 2h20m51s
Required
Details
ci / aarch64-macos-debug (pull_request) Successful in 3h31m3s
Required
Details
ci / aarch64-linux-debug (pull_request) Successful in 3h10m36s
Required
Details
ci / x86_64-windows-release (pull_request) Successful in 1h23m5s
Required
Details
ci / x86_64-windows-debug (pull_request) Successful in 1h52m26s
Required
Details
ci / powerpc64le-linux-debug (pull_request) Successful in 4h14m26s
Required
Details
ci / aarch64-freebsd-debug (pull_request) Has been skipped
ci / aarch64-freebsd-release (pull_request) Has been skipped
ci / x86_64-linux-debug (pull_request) Successful in 1h45m14s
Required
Details
ci / s390x-linux-release (pull_request) Successful in 1h39m58s
Required
Details
ci / x86_64-linux-debug-llvm (pull_request) Successful in 3h48m47s
Required
Details
ci / aarch64-netbsd-debug (pull_request) Has been skipped
ci / aarch64-netbsd-release (pull_request) Has been skipped
ci / x86_64-linux-release (pull_request) Successful in 4h6m53s
Required
Details
ci / s390x-linux-debug (pull_request) Successful in 6h51m52s
Required
Details
ci / loongarch64-linux-release (pull_request) Successful in 2h31m0s
ci / riscv64-linux-debug (pull_request) Has been skipped
ci / riscv64-linux-release (pull_request) Has been skipped
ci / loongarch64-linux-debug (pull_request) Successful in 4h5m47s
This pull request has changes conflicting with the target branch.
  • tools/docgen.zig
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u cli-args-parser:castholm-cli-args-parser
git switch castholm-cli-args-parser
Sign in to join this conversation.
No reviewers
Labels
Clear labels
abi/f32
abi/ilp32
abi/sf
accepted
This proposal is planned.
arch/21k
arch/6502
arch/aarch64
arch/alpha
arch/amdgcn
arch/arc
arch/arc32
arch/arc64
arch/arm
arch/avr
arch/bfin
arch/bpf
arch/colossus
arch/cris
arch/csky
arch/dlx
arch/epiphany
arch/fr30
arch/frv
arch/hexagon
arch/hppa
arch/hppa64
arch/ia64
arch/kalimba
arch/kvx
arch/lanai
arch/lm32
arch/loongarch32
arch/loongarch64
arch/m32r
arch/m68k
arch/m88k
arch/mcore
arch/microblaze
arch/mips
arch/mips64
arch/mmix
arch/moxie
arch/mrisc32
arch/msp430
arch/nds32
arch/ns32k
arch/nvptx
arch/or1k
arch/powerpc
arch/powerpc64
arch/propeller
arch/riscv32
arch/riscv64
arch/rl78
arch/rx
arch/s390x
arch/sh
arch/sparc
arch/sparc64
arch/spirv
arch/spu
arch/tricore
arch/v850
arch/vax
arch/vc4
arch/ve
arch/wasm
arch/x86
arch/x86_64
arch/xcore
arch/xtensa
autodoc
The web application for interactive documentation and generation of its assets.
backend/c
The C backend outputs C source code.
backend/llvm
The LLVM backend outputs an LLVM bitcode module.
backend/self-hosted
The self-hosted backends produce machine code directly.
binutils
Zig's included binary utilities: zig ar, zig dlltool, zig lib, zig ranlib, zig objcopy, and zig rc.
breaking
Implementing this issue could cause existing code to no longer compile or have different behavior.
build system
The Zig build system - zig build, std.Build, the build runner, and package management.
debug info
An issue related to debug information (e.g. DWARF) produced by the Zig compiler.
docs
An issue with documentation, e.g. the language reference or standard library doc comments.
error message
This issue points out an error message that is unhelpful and should be improved.
frontend
Tokenization, parsing, AstGen, ZonGen, Sema, Legalize, and Liveness.
fuzzing
An issue related to Zig's integrated fuzz testing.
incremental
Reuse of internal compiler state for faster compilation.
lib/c
This issue relates to Zig's libc implementation and/or vendored libcs.
lib/compiler-rt
This issue relates to Zig's compiler-rt library.
lib/cxx
This issue relates to Zig's vendored libc++ and/or libc++abi.
lib/std
This issue relates to Zig's standard library.
lib/tsan
This issue relates to Zig's vendored libtsan.
lib/ubsan-rt
This issue relates to Zig's ubsan-rt library.
lib/unwind
This issue relates to Zig's vendored libunwind.
linking
Zig's integrated object file and incremental linker.
miscompilation
The compiler reports success but produces semantically incorrect code.
os/android
os/contiki
os/dragonfly
os/driverkit
os/emscripten
os/freebsd
os/fuchsia
os/haiku
os/hermit
os/hurd
os/illumos
os/ios
os/linux
os/maccatalyst
os/macos
os/managarm
os/netbsd
os/ohos
os/openbsd
os/plan9
os/redox
os/rtems
os/serenity
os/tvos
os/uefi
os/visionos
os/wasi
os/watchos
os/windows
proposal
This issue suggests language modifications. If it also has the "accepted" label then it is planned.
release notes
This issue or pull request should be mentioned in the release notes.
testing
This issue is related to testing the compiler, standard library, or other parts of Zig.
zig cc
Zig as a drop-in C-family compiler.
zig fmt
The Zig source code formatter.
zig reduce
The Zig source code reduction tool.
bounty
https://ziglang.org/news/announcing-donor-bounties
bug
Observed behavior contradicts documented or intended behavior.
contributor-friendly
This issue is limited in scope and/or knowledge of project internals.
downstream
An issue with a third-party project that uses this project.
enhancement
Solving this issue will likely involve adding new logic or components to the codebase.
infra
An issue related to project infrastructure, e.g. continuous integration.
optimization
A task to improve performance and/or resource usage.
question
No questions on the issue tracker; use a community space instead.
regression
Something that used to work in a previous version stopped working
upstream
An issue with a third-party project that this project uses.
use case
Describes a real use case that is difficult or impossible, but does not propose a solution.
No labels
abi/f32
abi/ilp32
abi/sf
accepted
arch/21k
arch/6502
arch/aarch64
arch/alpha
arch/amdgcn
arch/arc
arch/arc32
arch/arc64
arch/arm
arch/avr
arch/bfin
arch/bpf
arch/colossus
arch/cris
arch/csky
arch/dlx
arch/epiphany
arch/fr30
arch/frv
arch/hexagon
arch/hppa
arch/hppa64
arch/ia64
arch/kalimba
arch/kvx
arch/lanai
arch/lm32
arch/loongarch32
arch/loongarch64
arch/m32r
arch/m68k
arch/m88k
arch/mcore
arch/microblaze
arch/mips
arch/mips64
arch/mmix
arch/moxie
arch/mrisc32
arch/msp430
arch/nds32
arch/ns32k
arch/nvptx
arch/or1k
arch/powerpc
arch/powerpc64
arch/propeller
arch/riscv32
arch/riscv64
arch/rl78
arch/rx
arch/s390x
arch/sh
arch/sparc
arch/sparc64
arch/spirv
arch/spu
arch/tricore
arch/v850
arch/vax
arch/vc4
arch/ve
arch/wasm
arch/x86
arch/x86_64
arch/xcore
arch/xtensa
autodoc
backend/c
backend/llvm
backend/self-hosted
binutils
breaking
build system
debug info
docs
error message
frontend
fuzzing
incremental
lib/c
lib/compiler-rt
lib/cxx
lib/std
lib/tsan
lib/ubsan-rt
lib/unwind
linking
miscompilation
os/android
os/contiki
os/dragonfly
os/driverkit
os/emscripten
os/freebsd
os/fuchsia
os/haiku
os/hermit
os/hurd
os/illumos
os/ios
os/linux
os/maccatalyst
os/macos
os/managarm
os/netbsd
os/ohos
os/openbsd
os/plan9
os/redox
os/rtems
os/serenity
os/tvos
os/uefi
os/visionos
os/wasi
os/watchos
os/windows
proposal
release notes
testing
zig cc
zig fmt
zig reduce
bounty
bug
contributor-friendly
downstream
enhancement
infra
optimization
question
regression
upstream
use case
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
6 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ziglang/zig!35304
Reference in a new issue
ziglang/zig
No description provided.
Delete branch "castholm/zig:cli-args-parser"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?