9fd78ccd
refactor: help and version print from one place
a73x 2026-08-27 07:15
Commit message
src/cli/flags.zig
| Old | New | ||
|---|---|---|---|
| @@ -125,6 +125,28 @@ fn aliasHit(comptime T: type, comptime field: []const u8, a: []const u8) bool { | |||
| 125 | return false; | 125 | return false; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | pub fn help(usage: []const u8) u8 { | ||
| 129 | // stdout, unlike every refusal: a usage someone ASKED for is output, | ||
| 130 | // and they may well have piped it into a pager. version shares both | ||
| 131 | // the rule and the reason. | ||
| 132 | writeOut(usage); | ||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | pub fn version(prog: []const u8, ver: []const u8) u8 { | ||
| 137 | // Both strings are the caller's: cliflags is layer 0 and cannot see | ||
| 138 | // build_options, where the version it prints lives. | ||
| 139 | var buf: [64]u8 = undefined; | ||
| 140 | writeOut(std.fmt.bufPrint(&buf, "{s} {s}\n", .{ prog, ver }) catch unreachable); | ||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | /// A short write is not an error: a usage page down a pipe can take two. | ||
| 145 | fn writeOut(bytes: []const u8) void { | ||
| 146 | var off: usize = 0; | ||
| 147 | while (off < bytes.len) off += std.posix.write(std.posix.STDOUT_FILENO, bytes[off..]) catch return; | ||
| 148 | } | ||
| 149 | |||
| 128 | pub fn flagName(comptime field: []const u8) []const u8 { | 150 | pub fn flagName(comptime field: []const u8) []const u8 { |
| 129 | comptime var name: []const u8 = "--"; | 151 | comptime var name: []const u8 = "--"; |
| 130 | inline for (field) |c| name = name ++ [_]u8{if (c == '_') '-' else c}; | 152 | inline for (field) |c| name = name ++ [_]u8{if (c == '_') '-' else c}; |
src/cli/main.zig
| Old | New | ||
|---|---|---|---|
| @@ -258,11 +258,7 @@ fn usageCode(u: Usage) u8 { | |||
| 258 | 258 | ||
| 259 | fn usageExit(u: Usage) u8 { | 259 | fn usageExit(u: Usage) u8 { |
| 260 | switch (u) { | 260 | switch (u) { |
| 261 | // stdout, unlike every refusal below: a usage someone asked for is | 261 | .help => return cliflags.help(usage), |
| 262 | // output, and they may well have piped it into a pager. | ||
| 263 | .help => { | ||
| 264 | _ = std.posix.write(std.posix.STDOUT_FILENO, usage) catch {}; | ||
| 265 | }, | ||
| 266 | .no_command => std.debug.print("{s}", .{usage}), | 262 | .no_command => std.debug.print("{s}", .{usage}), |
| 267 | .unknown_command => std.debug.print("{s}", .{usage}), | 263 | .unknown_command => std.debug.print("{s}", .{usage}), |
| 268 | .unknown_arg => |a| std.debug.print("unknown argument: {s}\n{s}", .{ a, usage }), | 264 | .unknown_arg => |a| std.debug.print("unknown argument: {s}\n{s}", .{ a, usage }), |
| @@ -374,12 +370,7 @@ pub fn main() !u8 { | |||
| 374 | // The socket path resolved above is unused here and unchecked (see | 370 | // The socket path resolved above is unused here and unchecked (see |
| 375 | // the length guard above): asking a binary its version must work | 371 | // the length guard above): asking a binary its version must work |
| 376 | // with no daemon and no runtime dir. | 372 | // with no daemon and no runtime dir. |
| 377 | .version => { | 373 | .version => return cliflags.version("muxd", build_options.version), |
| 378 | var vbuf: [64]u8 = undefined; | ||
| 379 | const s = std.fmt.bufPrint(&vbuf, "muxd {s}\n", .{build_options.version}) catch unreachable; | ||
| 380 | _ = std.posix.write(std.posix.STDOUT_FILENO, s) catch {}; | ||
| 381 | return 0; | ||
| 382 | }, | ||
| 383 | .help => return usageExit(.help), | 374 | .help => return usageExit(.help), |
| 384 | .keygen => return keygen(alloc), | 375 | .keygen => return keygen(alloc), |
| 385 | .start => return startCmd(alloc, sock_path, args[2..]), | 376 | .start => return startCmd(alloc, sock_path, args[2..]), |
src/cli/mux_main.zig
| Old | New | ||
|---|---|---|---|
| @@ -321,18 +321,8 @@ pub fn main() !u8 { | |||
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | switch (parsed) { | 323 | switch (parsed) { |
| 324 | .version => { | 324 | .version => return cliflags.version("mux", build_options.version), |
| 325 | var vbuf: [64]u8 = undefined; | 325 | .help => return cliflags.help(usage), |
| 326 | const s = std.fmt.bufPrint(&vbuf, "mux {s}\n", .{build_options.version}) catch unreachable; | ||
| 327 | _ = std.posix.write(std.posix.STDOUT_FILENO, s) catch {}; | ||
| 328 | return 0; | ||
| 329 | }, | ||
| 330 | .help => { | ||
| 331 | // stdout, unlike every refusal below: a usage someone asked for | ||
| 332 | // is output, and they may well have piped it into a pager. | ||
| 333 | _ = std.posix.write(std.posix.STDOUT_FILENO, usage) catch {}; | ||
| 334 | return 0; | ||
| 335 | }, | ||
| 336 | .usage_error => { | 326 | .usage_error => { |
| 337 | std.debug.print("{s}", .{usage}); | 327 | std.debug.print("{s}", .{usage}); |
| 338 | return 2; | 328 | return 2; |
| @@ -523,18 +513,8 @@ fn wallMain(alloc: std.mem.Allocator, args: []const [:0]const u8) !u8 { | |||
| 523 | } | 513 | } |
| 524 | switch (outcome) { | 514 | switch (outcome) { |
| 525 | .ok => {}, | 515 | .ok => {}, |
| 526 | .help => { | 516 | .help => return cliflags.help(usage), |
| 527 | // stdout, unlike the refusals below: a usage someone asked for | 517 | .version => return cliflags.version("mux", build_options.version), |
| 528 | // is output, and they may well have piped it into a pager. | ||
| 529 | _ = std.posix.write(std.posix.STDOUT_FILENO, usage) catch {}; | ||
| 530 | return 0; | ||
| 531 | }, | ||
| 532 | .version => { | ||
| 533 | var vbuf: [64]u8 = undefined; | ||
| 534 | const s = std.fmt.bufPrint(&vbuf, "mux {s}\n", .{build_options.version}) catch unreachable; | ||
| 535 | _ = std.posix.write(std.posix.STDOUT_FILENO, s) catch {}; | ||
| 536 | return 0; | ||
| 537 | }, | ||
| 538 | .missing_value, .bad_number => { | 518 | .missing_value, .bad_number => { |
| 539 | std.debug.print("{s}", .{usage}); | 519 | std.debug.print("{s}", .{usage}); |
| 540 | return 2; | 520 | return 2; |
src/cli/muxa.zig
| Old | New | ||
|---|---|---|---|
| @@ -1203,19 +1203,10 @@ pub fn main() !u8 { | |||
| 1203 | proto.writeAllFd(std.posix.STDERR_FILENO, usage) catch {}; | 1203 | proto.writeAllFd(std.posix.STDERR_FILENO, usage) catch {}; |
| 1204 | return 2; | 1204 | return 2; |
| 1205 | }, | 1205 | }, |
| 1206 | // A usage someone ASKED for is the answer, not a diagnostic, so it | 1206 | // Help and version go to stdout — the one place muxa otherwise |
| 1207 | // goes to stdout — the one place muxa otherwise reserves for JSON, | 1207 | // reserves for JSON, and the only two verbs allowed to spend it. |
| 1208 | // and the only two verbs that are allowed to spend it. | 1208 | error.Help => return cliflags.help(usage), |
| 1209 | error.Help => { | 1209 | error.Version => return cliflags.version("muxa", build_options.version), |
| 1210 | proto.writeAllFd(std.posix.STDOUT_FILENO, usage) catch {}; | ||
| 1211 | return 0; | ||
| 1212 | }, | ||
| 1213 | error.Version => { | ||
| 1214 | var vbuf: [64]u8 = undefined; | ||
| 1215 | const s = std.fmt.bufPrint(&vbuf, "muxa {s}\n", .{build_options.version}) catch unreachable; | ||
| 1216 | proto.writeAllFd(std.posix.STDOUT_FILENO, s) catch {}; | ||
| 1217 | return 0; | ||
| 1218 | }, | ||
| 1219 | }; | 1210 | }; |
| 1220 | 1211 | ||
| 1221 | // Started BEFORE the connect, not after: over QUIC the handshake is | 1212 | // Started BEFORE the connect, not after: over QUIC the handshake is |
src/cli/webhub_main.zig
| Old | New | ||
|---|---|---|---|
| @@ -141,18 +141,8 @@ pub fn main() !u8 { | |||
| 141 | else => |e| return e, | 141 | else => |e| return e, |
| 142 | }; | 142 | }; |
| 143 | var parsed = switch (result) { | 143 | var parsed = switch (result) { |
| 144 | // stdout, unlike the refusal above: a usage someone asked for is | 144 | .help => return cliflags.help(usage), |
| 145 | // output, and they may well have piped it into a pager. | 145 | .version => return cliflags.version("muxweb", build_options.version), |
| 146 | .help => { | ||
| 147 | _ = std.posix.write(std.posix.STDOUT_FILENO, usage) catch {}; | ||
| 148 | return 0; | ||
| 149 | }, | ||
| 150 | .version => { | ||
| 151 | var vbuf: [64]u8 = undefined; | ||
| 152 | const s = std.fmt.bufPrint(&vbuf, "muxweb {s}\n", .{build_options.version}) catch unreachable; | ||
| 153 | _ = std.posix.write(std.posix.STDOUT_FILENO, s) catch {}; | ||
| 154 | return 0; | ||
| 155 | }, | ||
| 156 | .serve => |p| p, | 146 | .serve => |p| p, |
| 157 | }; | 147 | }; |
| 158 | defer parsed.deinit(); | 148 | defer parsed.deinit(); |