From 7f9eabeecfde0d909ab50a8fb10ad3fedff93d03 Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Mon, 25 Jul 2022 18:15:45 +0200 Subject: Add clap.parsers.enumeration for parsing enums closes #78 --- README.md | 5 +++++ clap/parsers.zig | 37 +++++++++++++++++++++++++++++++++++++ example/simple-ex.zig | 5 +++++ 3 files changed, 47 insertions(+) diff --git a/README.md b/README.md index 8457118..d37a222 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ pub fn main() !void { const params = comptime clap.parseParamsComptime( \\-h, --help Display this help and exit. \\-n, --number An option parameter, which takes a value. + \\-a, --answer An option parameter which takes an enum. \\-s, --string ... An option parameter which can be specified multiple times. \\... \\ @@ -103,10 +104,12 @@ pub fn main() !void { // Declare our own parsers which are used to map the argument strings to other // types. + const YesNo = enum { yes, no }; const parsers = comptime .{ .STR = clap.parsers.string, .FILE = clap.parsers.string, .INT = clap.parsers.int(usize, 10), + .ANSWER = clap.parsers.enumeration(YesNo), }; var diag = clap.Diagnostic{}; @@ -122,6 +125,8 @@ pub fn main() !void { debug.print("--help\n", .{}); if (res.args.number) |n| debug.print("--number = {}\n", .{n}); + if (res.args.answer) |a| + debug.print("--answer = {s}\n", .{@tagName(a)}); for (res.args.string) |s| debug.print("--string = {s}\n", .{s}); for (res.positionals) |pos| diff --git a/clap/parsers.zig b/clap/parsers.zig index 49b95a9..208a1aa 100644 --- a/clap/parsers.zig +++ b/clap/parsers.zig @@ -1,6 +1,7 @@ const std = @import("std"); const fmt = std.fmt; +const testing = std.testing; pub const default = .{ .string = string, @@ -23,6 +24,10 @@ pub fn string(in: []const u8) error{}![]const u8 { return in; } +test "string" { + try testing.expectEqualStrings("aa", try string("aa")); +} + pub fn int(comptime T: type, comptime radix: u8) fn ([]const u8) fmt.ParseIntError!T { return struct { fn parse(in: []const u8) fmt.ParseIntError!T { @@ -31,6 +36,14 @@ pub fn int(comptime T: type, comptime radix: u8) fn ([]const u8) fmt.ParseIntErr }.parse; } +test "int" { + try testing.expectEqual(@as(u8, 0), try int(u8, 10)("0")); + try testing.expectEqual(@as(u8, 1), try int(u8, 10)("1")); + try testing.expectEqual(@as(u8, 10), try int(u8, 10)("10")); + try testing.expectEqual(@as(u8, 0x10), try int(u8, 0)("0x10")); + try testing.expectEqual(@as(u8, 0b10), try int(u8, 0)("0b10")); +} + pub fn float(comptime T: type) fn ([]const u8) fmt.ParseFloatError!T { return struct { fn parse(in: []const u8) fmt.ParseFloatError!T { @@ -39,6 +52,30 @@ pub fn float(comptime T: type) fn ([]const u8) fmt.ParseFloatError!T { }.parse; } +test "float" { + try testing.expectEqual(@as(f32, 0), try float(f32)("0")); +} + +pub const EnumError = error{ + NameNotPartOfEnum, +}; + +pub fn enumeration(comptime T: type) fn ([]const u8) EnumError!T { + return struct { + fn parse(in: []const u8) EnumError!T { + return std.meta.stringToEnum(T, in) orelse error.NameNotPartOfEnum; + } + }.parse; +} + +test "enumeration" { + const E = enum { a, b, c }; + try testing.expectEqual(E.a, try enumeration(E)("a")); + try testing.expectEqual(E.b, try enumeration(E)("b")); + try testing.expectEqual(E.c, try enumeration(E)("c")); + try testing.expectError(EnumError.NameNotPartOfEnum, enumeration(E)("d")); +} + fn ReturnType(comptime P: type) type { return @typeInfo(P).Fn.return_type.?; } diff --git a/example/simple-ex.zig b/example/simple-ex.zig index d0d214d..fb20d07 100644 --- a/example/simple-ex.zig +++ b/example/simple-ex.zig @@ -11,6 +11,7 @@ pub fn main() !void { const params = comptime clap.parseParamsComptime( \\-h, --help Display this help and exit. \\-n, --number An option parameter, which takes a value. + \\-a, --answer An option parameter which takes an enum. \\-s, --string ... An option parameter which can be specified multiple times. \\... \\ @@ -18,10 +19,12 @@ pub fn main() !void { // Declare our own parsers which are used to map the argument strings to other // types. + const YesNo = enum { yes, no }; const parsers = comptime .{ .STR = clap.parsers.string, .FILE = clap.parsers.string, .INT = clap.parsers.int(usize, 10), + .ANSWER = clap.parsers.enumeration(YesNo), }; var diag = clap.Diagnostic{}; @@ -37,6 +40,8 @@ pub fn main() !void { debug.print("--help\n", .{}); if (res.args.number) |n| debug.print("--number = {}\n", .{n}); + if (res.args.answer) |a| + debug.print("--answer = {s}\n", .{@tagName(a)}); for (res.args.string) |s| debug.print("--string = {s}\n", .{s}); for (res.positionals) |pos| -- cgit v1.2.3