parser: don't force pass userdata as a pointer
This is an interesting change. While I think generally passing in constant userdata is not terribly useful, the previous implementation precluded it entirely. Interface types, for example, are often passed directly and stored as constants (they hold pointers to their mutable state). Since we type erase this so it can be bound to the generic interface object, non-pointer objects must be passed by reference to avoid binding the parser interface to a temporary stack copy of the object. This means we have to handle these cases slightly differently. Also, while technically being classified as pointers, slices don't really behave like pointers, which is understandable but annoying. There's a bit of asymmetry here, as CommandBuilder(*u32) and CommandBuilder (u32) both require an *u32 when binding the parser interface. This is of course because pointers do not need to be rewrapped to be type erased. The same code path could be used for both cases, but then the user would have to pass in a pointer to a pointer, which actually looks a bit silly because then it potentially means having to do &&my_var.
This commit is contained in:
@@ -6,7 +6,7 @@ const CommandBuilder = noclip.CommandBuilder;
|
||||
const Choice = enum { first, second };
|
||||
|
||||
const cli = cmd: {
|
||||
var cmd = CommandBuilder(u32){
|
||||
var cmd = CommandBuilder(*u32){
|
||||
.description =
|
||||
\\The definitive noclip demonstration utility
|
||||
\\
|
||||
@@ -71,14 +71,14 @@ const cli = cmd: {
|
||||
};
|
||||
|
||||
const subcommand = cmd: {
|
||||
var cmd = CommandBuilder(void){
|
||||
var cmd = CommandBuilder([]const u8){
|
||||
.description =
|
||||
\\Perform some sort of work
|
||||
\\
|
||||
\\This subcommand is a mystery. It probably does something, but nobody is sure what.
|
||||
,
|
||||
};
|
||||
cmd.add_flag(.{}, .{
|
||||
cmd.simple_flag(.{
|
||||
.name = "flag",
|
||||
.truthy = .{ .short_tag = "-f", .long_tag = "--flag" },
|
||||
.falsy = .{ .long_tag = "--no-flag" },
|
||||
@@ -88,15 +88,16 @@ const subcommand = cmd: {
|
||||
break :cmd cmd;
|
||||
};
|
||||
|
||||
fn sub_handler(_: *void, result: subcommand.Output()) !void {
|
||||
fn sub_handler(context: []const u8, result: subcommand.Output()) !void {
|
||||
std.debug.print("subcommand: {s}\n", .{result.argument});
|
||||
std.debug.print("context: {s}\n", .{context});
|
||||
}
|
||||
|
||||
fn cli_handler(context: *u32, result: cli.Output()) !void {
|
||||
_ = context;
|
||||
|
||||
std.debug.print("context: {d}\n", .{context.*});
|
||||
std.debug.print("callback is working {any}\n", .{result.choice});
|
||||
std.debug.print("callback is working {d}\n", .{result.default});
|
||||
context.* += 1;
|
||||
}
|
||||
|
||||
pub fn main() !u8 {
|
||||
@@ -106,9 +107,10 @@ pub fn main() !u8 {
|
||||
|
||||
var parser = cli.create_parser(cli_handler, allocator);
|
||||
var context: u32 = 2;
|
||||
const sc: []const u8 = "whassup";
|
||||
|
||||
var subcon = subcommand.create_parser(sub_handler, allocator);
|
||||
try parser.add_subcommand("verb", subcon.interface());
|
||||
try parser.add_subcommand("verb", subcon.interface(&sc));
|
||||
|
||||
const iface = parser.interface(&context);
|
||||
iface.execute() catch return 1;
|
||||
|
Reference in New Issue
Block a user