From c9a3b90160207c53628d545e1d46917469b9009e Mon Sep 17 00:00:00 2001 From: Lyssieth Date: Fri, 29 Nov 2024 19:36:56 +0200 Subject: [PATCH] Fixups --- src/args/args.zig | 41 ++++++++++++++++++++++++++++++-- src/args/parsers/num.zig | 2 +- src/args/parsers/numNullable.zig | 11 +++++++++ src/args/parsers/parsers.zig | 1 + 4 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/args/parsers/numNullable.zig diff --git a/src/args/args.zig b/src/args/args.zig index 923a053..fc9c82a 100644 --- a/src/args/args.zig +++ b/src/args/args.zig @@ -167,6 +167,7 @@ fn initFromParsed(comptime T: type, allocator: Allocator, flags: []Arg) !T { } const fie = &@field(result, field.name); + const fieldType = @typeInfo(@TypeOf(fie.*.value)); const extra: Extra = fie.*.extra; switch (extra) { @@ -242,8 +243,6 @@ fn initFromParsed(comptime T: type, allocator: Allocator, flags: []Arg) !T { return error.InvalidFlag; } - const fieldType = @typeInfo(@TypeOf(fie.*.value)); - switch (fieldType) { .Optional => |_| { log.debug("flag `{s}` is optional, and we couldn't find a value for it, so leaving as default value", .{f.name}); @@ -358,6 +357,17 @@ fn initFromParsed(comptime T: type, allocator: Allocator, flags: []Arg) !T { return error.InvalidPositional; } } else { + switch (fieldType) { + .Optional => { + if (!builtin.is_test) { + log.warn("could not find positional argument for `{s}`, using default value", .{field.name}); + } + comptime continue; + }, + + else => {}, + } + if (builtin.is_test) { // early return to not pollute the stderr return error.NoArgumentFound; @@ -529,6 +539,33 @@ test "missing positional because empty arg" { try t.expectError(error.NoArgumentFound, result); } +test "positional has default value so we get a free pass" { + const args = try t.allocator.alloc([]const u8, 1); + defer t.allocator.free(args); + + args[0] = "--toggle"; + + const Demo = struct { + allocator: Allocator, + + positional: Marker(?u8) = .{ + .value = 255, + .extra = .{ + .Positional = .{}, + }, + .parse = parsers.numNullable(u8), + }, + + fn deinit(self: *@This()) void { + self.* = undefined; + } + }; + + const result = try parseArgsFromSlice(Demo, t.allocator, args); + + try t.expectEqual(255, result.positional.value); +} + test "parse fn (positional)" { const args = try t.allocator.alloc([]const u8, 3); defer t.allocator.free(args); diff --git a/src/args/parsers/num.zig b/src/args/parsers/num.zig index 35c4971..c722cef 100644 --- a/src/args/parsers/num.zig +++ b/src/args/parsers/num.zig @@ -3,7 +3,7 @@ const std = @import("std"); pub fn num(comptime T: type) *const fn (value: []const u8) anyerror!T { const container = struct { fn func(value: []const u8) anyerror!T { - return std.fmt.parseInt(T, value, 10); + return try std.fmt.parseInt(T, value, 10); } }; diff --git a/src/args/parsers/numNullable.zig b/src/args/parsers/numNullable.zig new file mode 100644 index 0000000..19299fd --- /dev/null +++ b/src/args/parsers/numNullable.zig @@ -0,0 +1,11 @@ +const std = @import("std"); + +pub fn numNullable(comptime T: type) *const fn (value: []const u8) anyerror!?T { + const container = struct { + fn func(value: []const u8) anyerror!?T { + return try std.fmt.parseInt(T, value, 10); + } + }; + + return &container.func; +} diff --git a/src/args/parsers/parsers.zig b/src/args/parsers/parsers.zig index c4fc550..91e57d6 100644 --- a/src/args/parsers/parsers.zig +++ b/src/args/parsers/parsers.zig @@ -8,6 +8,7 @@ pub fn ParseSignature(comptime T: type) type { } pub const num = @import("./num.zig").num; +pub const numNullable = @import("./numNullable.zig").numNullable; pub const boolean = @import("./boolean.zig").boolean; pub const enumLiteral = @import("./enumLiteral.zig").enumLiteral;