Add per-subcommand help via help or --help argument

`lightpanda <subcommand> help`, `lightpanda <subcommand> --help`
now print only the relevant subcommand options plus common options,
instead of the full text.

`lightpanda help <subcommand>` is also supported
(and that's what use internally).
This commit is contained in:
Francis Bouvier
2026-05-11 22:16:52 +02:00
parent e56bd0862a
commit 31ef5246bc
2 changed files with 74 additions and 15 deletions

View File

@@ -268,7 +268,17 @@ pub fn Builder(comptime commands: anytype) type {
inline for (commands) |command| {
// Match a command.
if (std.mem.eql(u8, cmd_str, command.name)) {
return .{ exec_name, try parseCommand(allocator, command, &args) };
const cmd_parsed = parseCommand(allocator, command, &args) catch |err| {
if (err == error.HelpRequested) {
// <subcommand> help requested, return help <subcommand>
var h = @FieldType(Union, "help"){};
if (@hasField(@FieldType(Union, "help"), "subcommand")) {
h.subcommand = command.name;
}
return .{ exec_name, @unionInit(Union, "help", h) };
} else return err;
};
return .{ exec_name, cmd_parsed };
}
}
@@ -291,7 +301,17 @@ pub fn Builder(comptime commands: anytype) type {
inline for (commands) |command| {
if (std.mem.eql(u8, @tagName(command_enum), command.name)) {
return .{ exec_name, try parseCommand(allocator, command, &args) };
const cmd_parsed = parseCommand(allocator, command, &args) catch |err| {
if (err == error.HelpRequested) {
// <subcommand> help requested, return help <subcommand>
var h = @FieldType(Union, "help"){};
if (@hasField(@FieldType(Union, "help"), "subcommand")) {
h.subcommand = command.name;
}
return .{ exec_name, @unionInit(Union, "help", h) };
} else return err;
};
return .{ exec_name, cmd_parsed };
}
}
@@ -587,6 +607,11 @@ pub fn Builder(comptime commands: anytype) type {
}
}
// Subcommand help: `lightpanda fetch help` or `lightpanda fetch --help`
if (std.mem.eql(u8, option_name, "help") or std.mem.eql(u8, option_name, "--help")) {
return error.HelpRequested;
}
// Encountered an option we don't know of.
if (std.mem.startsWith(u8, option_name, "--")) {
log.fatal(.app, "unknown argument", .{ .mode = command.name, .arg = option_name });