all: continue organization and add bakery

The bakery bakes the user context type into an object so that it
doesn't have to be specified over and over again. This ends up being a
nicer way of specifying the CLI parameters, except for the fact that
it requires a slightly odd comptime block construct due to `var` not
working at the top level for some reason (and `comptime var` also not
working).
This commit is contained in:
2022-11-27 01:31:20 -08:00
parent b1bac01257
commit 04722f938e
6 changed files with 357 additions and 239 deletions

View File

@@ -4,53 +4,51 @@ const noclip = @import("noclip");
const context: []const u8 = "hello friend";
const ContextType = @TypeOf(context);
const helpFlag = noclip.HelpFlag(.{ .UserContext = ContextType });
const subcommand = blk: {
var cmd = noclip.Command(ContextType, .{ .name = "subcommand", .help = "this a sub command" });
cmd.add(cmd.defaultHelpFlag);
cmd.add(cmd.StringOption{ .name = "meta", .short = "-m" });
cmd.add(cmd.StringArgument{ .name = "sub" });
break :blk cmd;
};
const subData: noclip.CommandData = .{ .name = "subcommand", .help = "this a sub command" };
const subFlag: noclip.StringOption(ContextType) = .{ .name = "meta", .short = "-m" };
const subArg: noclip.StringArg(ContextType) = .{ .name = "sub" };
const subSpec = .{ helpFlag, subFlag, subArg };
const subCommand: noclip.CommandParser(subData, subSpec, ContextType, subCallback) = .{};
const command = blk: {
var cmd = noclip.Command(ContextType, .{ .name = "main", .help = "main CLI entry point" });
cmd.add(cmd.Flag{ .name = "flag", .truthy = .{ .short = "-f", .long = "--flag" }, .falsy = .{ .long = "--no-flag" } });
cmd.add(cmd.StringOption{
.name = "input",
.short = "-i",
.long = "--input",
.handler = printHandler,
.envVar = "OPTS_INPUT",
});
cmd.add(cmd.StringOption{ .name = "output", .long = "--output", .default = "waoh" });
cmd.add(cmd.Option(i32){ .name = "number", .short = "-n", .long = "--number" });
cmd.add(cmd.StringArgument{ .name = "argument" });
cmd.add(cmd.Argument(u32){ .name = "another", .default = 0 });
fn wrecker(zontext: ContextType, input: []const u8) ![]const u8 {
std.debug.print("ctx: {s}\n", .{zontext});
cmd.add(subcommand.Parser(subCallback));
break :blk cmd;
};
fn printHandler(ctx: ContextType, input: []const u8) ![]const u8 {
std.debug.print("ctx: {s}\n", .{ctx});
return input;
}
const cdata: noclip.CommandData = .{ .name = "main", .help = "main CLI entry point" };
const flagCheck: noclip.FlagOption(ContextType) = .{
.name = "flag",
.truthy = .{ .short = "-f", .long = "--flag" },
.falsy = .{ .long = "--no-flag" },
};
const inputOption: noclip.StringOption(ContextType) = .{
.name = "input",
.short = "-i",
.long = "--input",
.handler = wrecker,
.envVar = "OPTS_INPUT",
};
const outputOption: noclip.StringOption(ContextType) = .{ .name = "output", .long = "--output", .default = "waoh" };
const numberOption: noclip.ValuedOption(.{ .Output = i32, .UserContext = ContextType }) = .{ .name = "number", .short = "-n", .long = "--number" };
const argCheck: noclip.StringArg(ContextType) = .{ .name = "argument" };
const argAgain: noclip.StringArg(ContextType) = .{ .name = "another", .default = "nope" };
const mainSpec = .{
helpFlag,
flagCheck,
inputOption,
outputOption,
numberOption,
argCheck,
argAgain,
subCommand,
};
pub fn subCallback(_: ContextType, result: noclip.CommandResult(subSpec, ContextType)) !void {
std.debug.print("subcommand {any}!!!\n", .{result});
pub fn subCallback(_: ContextType, result: subcommand.CommandResult()) !void {
std.debug.print(
\\subcommand: {{
\\ .meta = {s}
\\ .sub = {s}
\\}}
\\
,
.{ result.meta, result.sub },
);
}
pub fn mainCommand(_: ContextType, result: noclip.CommandResult(mainSpec, ContextType)) !void {
pub fn mainCommand(_: ContextType, result: command.CommandResult()) !void {
std.debug.print(
\\arguments: {{
\\ .flag = {any}
@@ -58,7 +56,7 @@ pub fn mainCommand(_: ContextType, result: noclip.CommandResult(mainSpec, Contex
\\ .output = {s}
\\ .number = {d}
\\ .argument = {s}
\\ .another = {s}
\\ .another = {d}
\\}}
\\
,
@@ -74,7 +72,7 @@ pub fn mainCommand(_: ContextType, result: noclip.CommandResult(mainSpec, Contex
}
pub fn main() !void {
var command: noclip.CommandParser(cdata, mainSpec, ContextType, mainCommand) = .{};
var parser = command.Parser(mainCommand);
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
@@ -83,5 +81,5 @@ pub fn main() !void {
var argit = try std.process.argsWithAllocator(allocator);
_ = argit.next();
try command.execute(allocator, std.process.ArgIterator, &argit, context);
try parser.execute(allocator, std.process.ArgIterator, &argit, context);
}