From 140ace899ae4ecfafc9b635609b656050c9c355d Mon Sep 17 00:00:00 2001 From: Asherah Connor Date: Sun, 23 Aug 2020 13:48:12 +1000 Subject: parse and validate multiple option --- clap/comptime.zig | 23 +++++++++++++++-------- clap/streaming.zig | 34 ++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 18 deletions(-) (limited to 'clap') diff --git a/clap/comptime.zig b/clap/comptime.zig index 90d34e9..cecfcb2 100644 --- a/clap/comptime.zig +++ b/clap/comptime.zig @@ -13,7 +13,7 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) for (params) |param| { var index: usize = 0; if (param.names.long != null or param.names.short != null) { - const ptr = if (param.takes_value) &options else &flags; + const ptr = if (param.takes_value != .None) &options else &flags; index = ptr.*; ptr.* += 1; } @@ -52,7 +52,7 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) const param = arg.param; if (param.names.long == null and param.names.short == null) { try pos.append(arg.value.?); - } else if (param.takes_value) { + } else if (param.takes_value != .None) { // If we don't have any optional parameters, then this code should // never be reached. debug.assert(res.options.len != 0); @@ -80,7 +80,7 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) pub fn flag(parser: @This(), comptime name: []const u8) bool { const param = comptime findParam(name); - if (param.takes_value) + if (param.takes_value != .None) @compileError(name ++ " is an option and not a flag."); return parser.flags[param.id]; @@ -88,14 +88,21 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) pub fn allOptions(parser: @This(), comptime name: []const u8) [][]const u8 { const param = comptime findParam(name); - if (!param.takes_value) + if (param.takes_value == .None) @compileError(name ++ " is a flag and not an option."); + if (param.takes_value == .One) + @compileError(name ++ " takes one option, not multiple."); return parser.options[param.id].items; } pub fn option(parser: @This(), comptime name: []const u8) ?[]const u8 { - const items = parser.allOptions(name); + const param = comptime findParam(name); + if (param.takes_value == .None) + @compileError(name ++ " is a flag and not an option."); + if (param.takes_value == .Many) + @compileError(name ++ " takes many options, not one."); + const items = parser.options[param.id].items; return if (items.len > 0) items[0] else null; } @@ -127,9 +134,9 @@ test "clap.comptime.ComptimeClap" { clap.parseParam("-a, --aa ") catch unreachable, clap.parseParam("-b, --bb ") catch unreachable, clap.parseParam("-c, --cc ") catch unreachable, - clap.parseParam("-d, --dd ") catch unreachable, + clap.parseParam("-d, --dd ...") catch unreachable, clap.Param(clap.Help){ - .takes_value = true, + .takes_value = .One, }, }); @@ -151,6 +158,6 @@ test "clap.comptime.ComptimeClap" { testing.expectEqualStrings("0", args.option("--cc").?); testing.expectEqual(@as(usize, 1), args.positionals().len); testing.expectEqualStrings("something", args.positionals()[0]); - testing.expectEqualStrings("a", args.option("-d").?); + testing.expectEqualSlices([]const u8, &[_][]const u8{ "a", "b" }, args.allOptions("-d")); testing.expectEqualSlices([]const u8, &[_][]const u8{ "a", "b" }, args.allOptions("--dd")); } diff --git a/clap/streaming.zig b/clap/streaming.zig index 95ee581..b843bff 100644 --- a/clap/streaming.zig +++ b/clap/streaming.zig @@ -75,7 +75,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { if (!mem.eql(u8, name, match)) continue; - if (!param.takes_value) { + if (param.takes_value == .None) { if (maybe_value != null) return error.DoesntTakeValue; @@ -128,7 +128,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { // Before we return, we have to set the new state of the clap defer { - if (arg.len <= next_index or param.takes_value) { + if (arg.len <= next_index or param.takes_value != .None) { parser.state = State.Normal; } else { parser.state = State{ @@ -140,7 +140,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { } } - if (!param.takes_value) + if (param.takes_value == .None) return Arg(Id){ .param = param }; if (arg.len <= next_index) { @@ -194,20 +194,26 @@ test "clap.streaming.StreamingClap: short params" { clap.Param(u8){ .id = 2, .names = clap.Names{ .short = 'c' }, - .takes_value = true, + .takes_value = .One, + }, + clap.Param(u8){ + .id = 3, + .names = clap.Names{ .short = 'd' }, + .takes_value = .Many, }, }; const a = ¶ms[0]; const b = ¶ms[1]; const c = ¶ms[2]; + const d = ¶ms[3]; testNoErr( ¶ms, &[_][]const u8{ "-a", "-b", "-ab", "-ba", "-c", "0", "-c=0", "-ac", - "0", "-ac=0", + "0", "-ac=0", "-d=0", }, &[_]Arg(u8){ Arg(u8){ .param = a }, @@ -222,6 +228,7 @@ test "clap.streaming.StreamingClap: short params" { Arg(u8){ .param = c, .value = "0" }, Arg(u8){ .param = a }, Arg(u8){ .param = c, .value = "0" }, + Arg(u8){ .param = d, .value = "0" }, }, ); } @@ -239,26 +246,33 @@ test "clap.streaming.StreamingClap: long params" { clap.Param(u8){ .id = 2, .names = clap.Names{ .long = "cc" }, - .takes_value = true, + .takes_value = .One, + }, + clap.Param(u8){ + .id = 3, + .names = clap.Names{ .long = "dd" }, + .takes_value = .Many, }, }; const aa = ¶ms[0]; const bb = ¶ms[1]; const cc = ¶ms[2]; + const dd = ¶ms[3]; testNoErr( ¶ms, &[_][]const u8{ "--aa", "--bb", "--cc", "0", - "--cc=0", + "--cc=0", "--dd=0", }, &[_]Arg(u8){ Arg(u8){ .param = aa }, Arg(u8){ .param = bb }, Arg(u8){ .param = cc, .value = "0" }, Arg(u8){ .param = cc, .value = "0" }, + Arg(u8){ .param = dd, .value = "0" }, }, ); } @@ -266,7 +280,7 @@ test "clap.streaming.StreamingClap: long params" { test "clap.streaming.StreamingClap: positional params" { const params = [_]clap.Param(u8){clap.Param(u8){ .id = 0, - .takes_value = true, + .takes_value = .One, }}; testNoErr( @@ -301,11 +315,11 @@ test "clap.streaming.StreamingClap: all params" { .short = 'c', .long = "cc", }, - .takes_value = true, + .takes_value = .One, }, clap.Param(u8){ .id = 3, - .takes_value = true, + .takes_value = .One, }, }; -- cgit v1.2.3