parser: run subcommand parsing/callbacks iteratively

This changes the parse/callback flow so that subcommands are run
iteratively from the base command rather than recursively. The primary
advantages of this approach are some stack space savings and much less
convoluted backtraces for deeply nested command hierarchies. The
overall order of operations has not changed, i.e. the full command
line is parsed before command callback dispatch starts.

Fixes: #12
This commit is contained in:
2024-04-06 11:38:55 -07:00
parent 074db7f4f6
commit a961b1930a
2 changed files with 53 additions and 30 deletions

View File

@@ -8,15 +8,15 @@ const Choice = enum { first, second };
const cli = cmd: {
var cmd = CommandBuilder(*u32){
.description =
\\The definitive noclip demonstration utility
\\The definitive noclip demonstration utility.
\\
\\This command demonstrates the functionality of the noclip library. cool!
\\
\\> // implementing factorial recursively is a silly thing to do
\\> pub fn fact(n: u64) u64 {
\\> if (n == 0) return 1;
\\> return n*fact(n - 1);
\\> }
\\> // implementing factorial recursively is a silly thing to do
\\> pub fn fact(n: u64) u64 {
\\> if (n == 0) return 1;
\\> return n*fact(n - 1);
\\> }
\\
\\Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
\\incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
@@ -135,6 +135,16 @@ pub fn main() !u8 {
try base.addSubcommand("main", try cli.createInterface(allocator, cliHandler, &context));
try base.addSubcommand("other", try subcommand.createInterface(allocator, subHandler, &sc));
const group = try noclip.commandGroup(allocator, .{ .description = "final level of a deeply nested subcommand" });
const subcon = try noclip.commandGroup(allocator, .{ .description = "third level of a deeply nested subcommand" });
const nested = try noclip.commandGroup(allocator, .{ .description = "second level of a deeply nested subcommand" });
const deeply = try noclip.commandGroup(allocator, .{ .description = "start of a deeply nested subcommand" });
try base.addSubcommand("deeply", deeply);
try deeply.addSubcommand("nested", nested);
try nested.addSubcommand("subcommand", subcon);
try subcon.addSubcommand("group", group);
try group.addSubcommand("run", try cli.createInterface(allocator, cliHandler, &context));
try base.execute();
return 0;