diff options
| author | 2020-08-23 13:48:12 +1000 | |
|---|---|---|
| committer | 2020-09-06 17:31:27 +0200 | |
| commit | 140ace899ae4ecfafc9b635609b656050c9c355d (patch) | |
| tree | c8f6e57a5ed51a1040fe1fd88892a0f73d6a50b1 | |
| parent | parse multiple options (diff) | |
| download | zig-clap-140ace899ae4ecfafc9b635609b656050c9c355d.tar.gz zig-clap-140ace899ae4ecfafc9b635609b656050c9c355d.tar.xz zig-clap-140ace899ae4ecfafc9b635609b656050c9c355d.zip | |
parse and validate multiple option
| -rw-r--r-- | clap.zig | 106 | ||||
| -rw-r--r-- | clap/comptime.zig | 23 | ||||
| -rw-r--r-- | clap/streaming.zig | 34 |
3 files changed, 111 insertions, 52 deletions
| @@ -25,6 +25,12 @@ pub const Names = struct { | |||
| 25 | long: ?[]const u8 = null, | 25 | long: ?[]const u8 = null, |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | pub const Values = enum { | ||
| 29 | None, | ||
| 30 | One, | ||
| 31 | Many, | ||
| 32 | }; | ||
| 33 | |||
| 28 | /// Represents a parameter for the command line. | 34 | /// Represents a parameter for the command line. |
| 29 | /// Parameters come in three kinds: | 35 | /// Parameters come in three kinds: |
| 30 | /// * Short ("-a"): Should be used for the most commonly used parameters in your program. | 36 | /// * Short ("-a"): Should be used for the most commonly used parameters in your program. |
| @@ -50,7 +56,7 @@ pub fn Param(comptime Id: type) type { | |||
| 50 | return struct { | 56 | return struct { |
| 51 | id: Id = Id{}, | 57 | id: Id = Id{}, |
| 52 | names: Names = Names{}, | 58 | names: Names = Names{}, |
| 53 | takes_value: bool = false, | 59 | takes_value: Values = .None, |
| 54 | }; | 60 | }; |
| 55 | } | 61 | } |
| 56 | 62 | ||
| @@ -86,8 +92,13 @@ pub fn parseParam(line: []const u8) !Param(Help) { | |||
| 86 | const start = mem.indexOfScalar(u8, help_msg, '<').? + 1; | 92 | const start = mem.indexOfScalar(u8, help_msg, '<').? + 1; |
| 87 | const len = mem.indexOfScalar(u8, help_msg[start..], '>') orelse break :blk; | 93 | const len = mem.indexOfScalar(u8, help_msg[start..], '>') orelse break :blk; |
| 88 | res.id.value = help_msg[start..][0..len]; | 94 | res.id.value = help_msg[start..][0..len]; |
| 89 | res.takes_value = true; | 95 | if (mem.startsWith(u8, help_msg[start + len + 1 ..], "...")) { |
| 90 | help_msg = help_msg[start + len + 1 ..]; | 96 | res.takes_value = .Many; |
| 97 | help_msg = help_msg[start + len + 1 + 3 ..]; | ||
| 98 | } else { | ||
| 99 | res.takes_value = .One; | ||
| 100 | help_msg = help_msg[start + len + 1 ..]; | ||
| 101 | } | ||
| 91 | } | 102 | } |
| 92 | } | 103 | } |
| 93 | 104 | ||
| @@ -110,8 +121,13 @@ pub fn parseParam(line: []const u8) !Param(Help) { | |||
| 110 | const start = mem.indexOfScalar(u8, help_msg, '<').? + 1; | 121 | const start = mem.indexOfScalar(u8, help_msg, '<').? + 1; |
| 111 | const len = mem.indexOfScalar(u8, help_msg[start..], '>') orelse break :blk; | 122 | const len = mem.indexOfScalar(u8, help_msg[start..], '>') orelse break :blk; |
| 112 | res.id.value = help_msg[start..][0..len]; | 123 | res.id.value = help_msg[start..][0..len]; |
| 113 | res.takes_value = true; | 124 | if (mem.startsWith(u8, help_msg[start + len + 1 ..], "...")) { |
| 114 | help_msg = help_msg[start + len + 1 ..]; | 125 | res.takes_value = .Many; |
| 126 | help_msg = help_msg[start + len + 1 + 3 ..]; | ||
| 127 | } else { | ||
| 128 | res.takes_value = .One; | ||
| 129 | help_msg = help_msg[start + len + 1 ..]; | ||
| 130 | } | ||
| 115 | } | 131 | } |
| 116 | } | 132 | } |
| 117 | 133 | ||
| @@ -134,7 +150,20 @@ test "parseParam" { | |||
| 134 | .short = 's', | 150 | .short = 's', |
| 135 | .long = find(text, "long"), | 151 | .long = find(text, "long"), |
| 136 | }, | 152 | }, |
| 137 | .takes_value = true, | 153 | .takes_value = .One, |
| 154 | }, try parseParam(text)); | ||
| 155 | |||
| 156 | text = "-s, --long <value>... Help text"; | ||
| 157 | testing.expectEqual(Param(Help){ | ||
| 158 | .id = Help{ | ||
| 159 | .msg = find(text, "Help text"), | ||
| 160 | .value = find(text, "value"), | ||
| 161 | }, | ||
| 162 | .names = Names{ | ||
| 163 | .short = 's', | ||
| 164 | .long = find(text, "long"), | ||
| 165 | }, | ||
| 166 | .takes_value = .Many, | ||
| 138 | }, try parseParam(text)); | 167 | }, try parseParam(text)); |
| 139 | 168 | ||
| 140 | text = "--long <value> Help text"; | 169 | text = "--long <value> Help text"; |
| @@ -147,7 +176,7 @@ test "parseParam" { | |||
| 147 | .short = null, | 176 | .short = null, |
| 148 | .long = find(text, "long"), | 177 | .long = find(text, "long"), |
| 149 | }, | 178 | }, |
| 150 | .takes_value = true, | 179 | .takes_value = .One, |
| 151 | }, try parseParam(text)); | 180 | }, try parseParam(text)); |
| 152 | 181 | ||
| 153 | text = "-s <value> Help text"; | 182 | text = "-s <value> Help text"; |
| @@ -160,7 +189,7 @@ test "parseParam" { | |||
| 160 | .short = 's', | 189 | .short = 's', |
| 161 | .long = null, | 190 | .long = null, |
| 162 | }, | 191 | }, |
| 163 | .takes_value = true, | 192 | .takes_value = .One, |
| 164 | }, try parseParam(text)); | 193 | }, try parseParam(text)); |
| 165 | 194 | ||
| 166 | text = "-s, --long Help text"; | 195 | text = "-s, --long Help text"; |
| @@ -173,7 +202,7 @@ test "parseParam" { | |||
| 173 | .short = 's', | 202 | .short = 's', |
| 174 | .long = find(text, "long"), | 203 | .long = find(text, "long"), |
| 175 | }, | 204 | }, |
| 176 | .takes_value = false, | 205 | .takes_value = .None, |
| 177 | }, try parseParam(text)); | 206 | }, try parseParam(text)); |
| 178 | 207 | ||
| 179 | text = "-s Help text"; | 208 | text = "-s Help text"; |
| @@ -186,7 +215,7 @@ test "parseParam" { | |||
| 186 | .short = 's', | 215 | .short = 's', |
| 187 | .long = null, | 216 | .long = null, |
| 188 | }, | 217 | }, |
| 189 | .takes_value = false, | 218 | .takes_value = .None, |
| 190 | }, try parseParam(text)); | 219 | }, try parseParam(text)); |
| 191 | 220 | ||
| 192 | text = "--long Help text"; | 221 | text = "--long Help text"; |
| @@ -199,7 +228,7 @@ test "parseParam" { | |||
| 199 | .short = null, | 228 | .short = null, |
| 200 | .long = find(text, "long"), | 229 | .long = find(text, "long"), |
| 201 | }, | 230 | }, |
| 202 | .takes_value = false, | 231 | .takes_value = .None, |
| 203 | }, try parseParam(text)); | 232 | }, try parseParam(text)); |
| 204 | 233 | ||
| 205 | text = "--long <A | B> Help text"; | 234 | text = "--long <A | B> Help text"; |
| @@ -212,7 +241,7 @@ test "parseParam" { | |||
| 212 | .short = null, | 241 | .short = null, |
| 213 | .long = find(text, "long"), | 242 | .long = find(text, "long"), |
| 214 | }, | 243 | }, |
| 215 | .takes_value = true, | 244 | .takes_value = .One, |
| 216 | }, try parseParam(text)); | 245 | }, try parseParam(text)); |
| 217 | 246 | ||
| 218 | testing.expectError(error.NoParamFound, parseParam("Help")); | 247 | testing.expectError(error.NoParamFound, parseParam("Help")); |
| @@ -334,8 +363,11 @@ fn printParam( | |||
| 334 | 363 | ||
| 335 | try stream.print("--{}", .{l}); | 364 | try stream.print("--{}", .{l}); |
| 336 | } | 365 | } |
| 337 | if (param.takes_value) | 366 | switch (param.takes_value) { |
| 338 | try stream.print(" <{}>", .{valueText(context, param)}); | 367 | .None => {}, |
| 368 | .One => try stream.print(" <{}>", .{valueText(context, param)}), | ||
| 369 | .Many => try stream.print(" <{}>...", .{valueText(context, param)}), | ||
| 370 | } | ||
| 339 | } | 371 | } |
| 340 | 372 | ||
| 341 | /// A wrapper around helpFull for simple helpText and valueText functions that | 373 | /// A wrapper around helpFull for simple helpText and valueText functions that |
| @@ -400,28 +432,30 @@ test "clap.help" { | |||
| 400 | try help( | 432 | try help( |
| 401 | slice_stream.outStream(), | 433 | slice_stream.outStream(), |
| 402 | comptime &[_]Param(Help){ | 434 | comptime &[_]Param(Help){ |
| 403 | parseParam("-a Short flag. ") catch unreachable, | 435 | parseParam("-a Short flag. ") catch unreachable, |
| 404 | parseParam("-b <V1> Short option.") catch unreachable, | 436 | parseParam("-b <V1> Short option.") catch unreachable, |
| 405 | parseParam("--aa Long flag. ") catch unreachable, | 437 | parseParam("--aa Long flag. ") catch unreachable, |
| 406 | parseParam("--bb <V2> Long option. ") catch unreachable, | 438 | parseParam("--bb <V2> Long option. ") catch unreachable, |
| 407 | parseParam("-c, --cc Both flag. ") catch unreachable, | 439 | parseParam("-c, --cc Both flag. ") catch unreachable, |
| 408 | parseParam("-d, --dd <V3> Both option. ") catch unreachable, | 440 | parseParam("-d, --dd <V3> Both option. ") catch unreachable, |
| 441 | parseParam("-d, --dd <V3>... Both repeated option. ") catch unreachable, | ||
| 409 | Param(Help){ | 442 | Param(Help){ |
| 410 | .id = Help{ | 443 | .id = Help{ |
| 411 | .msg = "Positional. This should not appear in the help message.", | 444 | .msg = "Positional. This should not appear in the help message.", |
| 412 | }, | 445 | }, |
| 413 | .takes_value = true, | 446 | .takes_value = .One, |
| 414 | }, | 447 | }, |
| 415 | }, | 448 | }, |
| 416 | ); | 449 | ); |
| 417 | 450 | ||
| 418 | const expected = "" ++ | 451 | const expected = "" ++ |
| 419 | "\t-a \tShort flag.\n" ++ | 452 | "\t-a \tShort flag.\n" ++ |
| 420 | "\t-b <V1> \tShort option.\n" ++ | 453 | "\t-b <V1> \tShort option.\n" ++ |
| 421 | "\t --aa \tLong flag.\n" ++ | 454 | "\t --aa \tLong flag.\n" ++ |
| 422 | "\t --bb <V2>\tLong option.\n" ++ | 455 | "\t --bb <V2> \tLong option.\n" ++ |
| 423 | "\t-c, --cc \tBoth flag.\n" ++ | 456 | "\t-c, --cc \tBoth flag.\n" ++ |
| 424 | "\t-d, --dd <V3>\tBoth option.\n"; | 457 | "\t-d, --dd <V3> \tBoth option.\n" ++ |
| 458 | "\t-d, --dd <V3>...\tBoth repeated option.\n"; | ||
| 425 | 459 | ||
| 426 | const actual = slice_stream.getWritten(); | 460 | const actual = slice_stream.getWritten(); |
| 427 | if (!mem.eql(u8, actual, expected)) { | 461 | if (!mem.eql(u8, actual, expected)) { |
| @@ -458,7 +492,7 @@ pub fn usageFull( | |||
| 458 | const cs = cos.outStream(); | 492 | const cs = cos.outStream(); |
| 459 | for (params) |param| { | 493 | for (params) |param| { |
| 460 | const name = param.names.short orelse continue; | 494 | const name = param.names.short orelse continue; |
| 461 | if (param.takes_value) | 495 | if (param.takes_value != .None) |
| 462 | continue; | 496 | continue; |
| 463 | 497 | ||
| 464 | if (cos.bytes_written == 0) | 498 | if (cos.bytes_written == 0) |
| @@ -470,7 +504,7 @@ pub fn usageFull( | |||
| 470 | 504 | ||
| 471 | var positional: ?Param(Id) = null; | 505 | var positional: ?Param(Id) = null; |
| 472 | for (params) |param| { | 506 | for (params) |param| { |
| 473 | if (!param.takes_value and param.names.short != null) | 507 | if (param.takes_value == .None and param.names.short != null) |
| 474 | continue; | 508 | continue; |
| 475 | 509 | ||
| 476 | const prefix = if (param.names.short) |_| "-" else "--"; | 510 | const prefix = if (param.names.short) |_| "-" else "--"; |
| @@ -485,8 +519,11 @@ pub fn usageFull( | |||
| 485 | try cs.writeByte(' '); | 519 | try cs.writeByte(' '); |
| 486 | 520 | ||
| 487 | try cs.print("[{}{}", .{ prefix, name }); | 521 | try cs.print("[{}{}", .{ prefix, name }); |
| 488 | if (param.takes_value) | 522 | switch (param.takes_value) { |
| 489 | try cs.print(" <{}>", .{try valueText(context, param)}); | 523 | .None => {}, |
| 524 | .One => try cs.print(" <{}>", .{try valueText(context, param)}), | ||
| 525 | .Many => try cs.print(" <{}>...", .{try valueText(context, param)}), | ||
| 526 | } | ||
| 490 | 527 | ||
| 491 | try cs.writeByte(']'); | 528 | try cs.writeByte(']'); |
| 492 | } | 529 | } |
| @@ -575,10 +612,10 @@ test "usage" { | |||
| 575 | .id = Help{ | 612 | .id = Help{ |
| 576 | .value = "file", | 613 | .value = "file", |
| 577 | }, | 614 | }, |
| 578 | .takes_value = true, | 615 | .takes_value = .One, |
| 579 | }, | 616 | }, |
| 580 | }); | 617 | }); |
| 581 | try testUsage("[-ab] [-c <value>] [-d <v>] [--e] [--f] [--g <value>] [--h <v>] <file>", comptime &[_]Param(Help){ | 618 | try testUsage("[-ab] [-c <value>] [-d <v>] [--e] [--f] [--g <value>] [--h <v>] [-i <v>...] <file>", comptime &[_]Param(Help){ |
| 582 | parseParam("-a") catch unreachable, | 619 | parseParam("-a") catch unreachable, |
| 583 | parseParam("-b") catch unreachable, | 620 | parseParam("-b") catch unreachable, |
| 584 | parseParam("-c <value>") catch unreachable, | 621 | parseParam("-c <value>") catch unreachable, |
| @@ -587,11 +624,12 @@ test "usage" { | |||
| 587 | parseParam("--f") catch unreachable, | 624 | parseParam("--f") catch unreachable, |
| 588 | parseParam("--g <value>") catch unreachable, | 625 | parseParam("--g <value>") catch unreachable, |
| 589 | parseParam("--h <v>") catch unreachable, | 626 | parseParam("--h <v>") catch unreachable, |
| 627 | parseParam("-i <v>...") catch unreachable, | ||
| 590 | Param(Help){ | 628 | Param(Help){ |
| 591 | .id = Help{ | 629 | .id = Help{ |
| 592 | .value = "file", | 630 | .value = "file", |
| 593 | }, | 631 | }, |
| 594 | .takes_value = true, | 632 | .takes_value = .One, |
| 595 | }, | 633 | }, |
| 596 | }); | 634 | }); |
| 597 | } | 635 | } |
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)) | |||
| 13 | for (params) |param| { | 13 | for (params) |param| { |
| 14 | var index: usize = 0; | 14 | var index: usize = 0; |
| 15 | if (param.names.long != null or param.names.short != null) { | 15 | if (param.names.long != null or param.names.short != null) { |
| 16 | const ptr = if (param.takes_value) &options else &flags; | 16 | const ptr = if (param.takes_value != .None) &options else &flags; |
| 17 | index = ptr.*; | 17 | index = ptr.*; |
| 18 | ptr.* += 1; | 18 | ptr.* += 1; |
| 19 | } | 19 | } |
| @@ -52,7 +52,7 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) | |||
| 52 | const param = arg.param; | 52 | const param = arg.param; |
| 53 | if (param.names.long == null and param.names.short == null) { | 53 | if (param.names.long == null and param.names.short == null) { |
| 54 | try pos.append(arg.value.?); | 54 | try pos.append(arg.value.?); |
| 55 | } else if (param.takes_value) { | 55 | } else if (param.takes_value != .None) { |
| 56 | // If we don't have any optional parameters, then this code should | 56 | // If we don't have any optional parameters, then this code should |
| 57 | // never be reached. | 57 | // never be reached. |
| 58 | debug.assert(res.options.len != 0); | 58 | debug.assert(res.options.len != 0); |
| @@ -80,7 +80,7 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) | |||
| 80 | 80 | ||
| 81 | pub fn flag(parser: @This(), comptime name: []const u8) bool { | 81 | pub fn flag(parser: @This(), comptime name: []const u8) bool { |
| 82 | const param = comptime findParam(name); | 82 | const param = comptime findParam(name); |
| 83 | if (param.takes_value) | 83 | if (param.takes_value != .None) |
| 84 | @compileError(name ++ " is an option and not a flag."); | 84 | @compileError(name ++ " is an option and not a flag."); |
| 85 | 85 | ||
| 86 | return parser.flags[param.id]; | 86 | return parser.flags[param.id]; |
| @@ -88,14 +88,21 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) | |||
| 88 | 88 | ||
| 89 | pub fn allOptions(parser: @This(), comptime name: []const u8) [][]const u8 { | 89 | pub fn allOptions(parser: @This(), comptime name: []const u8) [][]const u8 { |
| 90 | const param = comptime findParam(name); | 90 | const param = comptime findParam(name); |
| 91 | if (!param.takes_value) | 91 | if (param.takes_value == .None) |
| 92 | @compileError(name ++ " is a flag and not an option."); | 92 | @compileError(name ++ " is a flag and not an option."); |
| 93 | if (param.takes_value == .One) | ||
| 94 | @compileError(name ++ " takes one option, not multiple."); | ||
| 93 | 95 | ||
| 94 | return parser.options[param.id].items; | 96 | return parser.options[param.id].items; |
| 95 | } | 97 | } |
| 96 | 98 | ||
| 97 | pub fn option(parser: @This(), comptime name: []const u8) ?[]const u8 { | 99 | pub fn option(parser: @This(), comptime name: []const u8) ?[]const u8 { |
| 98 | const items = parser.allOptions(name); | 100 | const param = comptime findParam(name); |
| 101 | if (param.takes_value == .None) | ||
| 102 | @compileError(name ++ " is a flag and not an option."); | ||
| 103 | if (param.takes_value == .Many) | ||
| 104 | @compileError(name ++ " takes many options, not one."); | ||
| 105 | const items = parser.options[param.id].items; | ||
| 99 | return if (items.len > 0) items[0] else null; | 106 | return if (items.len > 0) items[0] else null; |
| 100 | } | 107 | } |
| 101 | 108 | ||
| @@ -127,9 +134,9 @@ test "clap.comptime.ComptimeClap" { | |||
| 127 | clap.parseParam("-a, --aa ") catch unreachable, | 134 | clap.parseParam("-a, --aa ") catch unreachable, |
| 128 | clap.parseParam("-b, --bb ") catch unreachable, | 135 | clap.parseParam("-b, --bb ") catch unreachable, |
| 129 | clap.parseParam("-c, --cc <V>") catch unreachable, | 136 | clap.parseParam("-c, --cc <V>") catch unreachable, |
| 130 | clap.parseParam("-d, --dd <V>") catch unreachable, | 137 | clap.parseParam("-d, --dd <V>...") catch unreachable, |
| 131 | clap.Param(clap.Help){ | 138 | clap.Param(clap.Help){ |
| 132 | .takes_value = true, | 139 | .takes_value = .One, |
| 133 | }, | 140 | }, |
| 134 | }); | 141 | }); |
| 135 | 142 | ||
| @@ -151,6 +158,6 @@ test "clap.comptime.ComptimeClap" { | |||
| 151 | testing.expectEqualStrings("0", args.option("--cc").?); | 158 | testing.expectEqualStrings("0", args.option("--cc").?); |
| 152 | testing.expectEqual(@as(usize, 1), args.positionals().len); | 159 | testing.expectEqual(@as(usize, 1), args.positionals().len); |
| 153 | testing.expectEqualStrings("something", args.positionals()[0]); | 160 | testing.expectEqualStrings("something", args.positionals()[0]); |
| 154 | testing.expectEqualStrings("a", args.option("-d").?); | 161 | testing.expectEqualSlices([]const u8, &[_][]const u8{ "a", "b" }, args.allOptions("-d")); |
| 155 | testing.expectEqualSlices([]const u8, &[_][]const u8{ "a", "b" }, args.allOptions("--dd")); | 162 | testing.expectEqualSlices([]const u8, &[_][]const u8{ "a", "b" }, args.allOptions("--dd")); |
| 156 | } | 163 | } |
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 { | |||
| 75 | 75 | ||
| 76 | if (!mem.eql(u8, name, match)) | 76 | if (!mem.eql(u8, name, match)) |
| 77 | continue; | 77 | continue; |
| 78 | if (!param.takes_value) { | 78 | if (param.takes_value == .None) { |
| 79 | if (maybe_value != null) | 79 | if (maybe_value != null) |
| 80 | return error.DoesntTakeValue; | 80 | return error.DoesntTakeValue; |
| 81 | 81 | ||
| @@ -128,7 +128,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { | |||
| 128 | 128 | ||
| 129 | // Before we return, we have to set the new state of the clap | 129 | // Before we return, we have to set the new state of the clap |
| 130 | defer { | 130 | defer { |
| 131 | if (arg.len <= next_index or param.takes_value) { | 131 | if (arg.len <= next_index or param.takes_value != .None) { |
| 132 | parser.state = State.Normal; | 132 | parser.state = State.Normal; |
| 133 | } else { | 133 | } else { |
| 134 | parser.state = State{ | 134 | parser.state = State{ |
| @@ -140,7 +140,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { | |||
| 140 | } | 140 | } |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | if (!param.takes_value) | 143 | if (param.takes_value == .None) |
| 144 | return Arg(Id){ .param = param }; | 144 | return Arg(Id){ .param = param }; |
| 145 | 145 | ||
| 146 | if (arg.len <= next_index) { | 146 | if (arg.len <= next_index) { |
| @@ -194,20 +194,26 @@ test "clap.streaming.StreamingClap: short params" { | |||
| 194 | clap.Param(u8){ | 194 | clap.Param(u8){ |
| 195 | .id = 2, | 195 | .id = 2, |
| 196 | .names = clap.Names{ .short = 'c' }, | 196 | .names = clap.Names{ .short = 'c' }, |
| 197 | .takes_value = true, | 197 | .takes_value = .One, |
| 198 | }, | ||
| 199 | clap.Param(u8){ | ||
| 200 | .id = 3, | ||
| 201 | .names = clap.Names{ .short = 'd' }, | ||
| 202 | .takes_value = .Many, | ||
| 198 | }, | 203 | }, |
| 199 | }; | 204 | }; |
| 200 | 205 | ||
| 201 | const a = ¶ms[0]; | 206 | const a = ¶ms[0]; |
| 202 | const b = ¶ms[1]; | 207 | const b = ¶ms[1]; |
| 203 | const c = ¶ms[2]; | 208 | const c = ¶ms[2]; |
| 209 | const d = ¶ms[3]; | ||
| 204 | 210 | ||
| 205 | testNoErr( | 211 | testNoErr( |
| 206 | ¶ms, | 212 | ¶ms, |
| 207 | &[_][]const u8{ | 213 | &[_][]const u8{ |
| 208 | "-a", "-b", "-ab", "-ba", | 214 | "-a", "-b", "-ab", "-ba", |
| 209 | "-c", "0", "-c=0", "-ac", | 215 | "-c", "0", "-c=0", "-ac", |
| 210 | "0", "-ac=0", | 216 | "0", "-ac=0", "-d=0", |
| 211 | }, | 217 | }, |
| 212 | &[_]Arg(u8){ | 218 | &[_]Arg(u8){ |
| 213 | Arg(u8){ .param = a }, | 219 | Arg(u8){ .param = a }, |
| @@ -222,6 +228,7 @@ test "clap.streaming.StreamingClap: short params" { | |||
| 222 | Arg(u8){ .param = c, .value = "0" }, | 228 | Arg(u8){ .param = c, .value = "0" }, |
| 223 | Arg(u8){ .param = a }, | 229 | Arg(u8){ .param = a }, |
| 224 | Arg(u8){ .param = c, .value = "0" }, | 230 | Arg(u8){ .param = c, .value = "0" }, |
| 231 | Arg(u8){ .param = d, .value = "0" }, | ||
| 225 | }, | 232 | }, |
| 226 | ); | 233 | ); |
| 227 | } | 234 | } |
| @@ -239,26 +246,33 @@ test "clap.streaming.StreamingClap: long params" { | |||
| 239 | clap.Param(u8){ | 246 | clap.Param(u8){ |
| 240 | .id = 2, | 247 | .id = 2, |
| 241 | .names = clap.Names{ .long = "cc" }, | 248 | .names = clap.Names{ .long = "cc" }, |
| 242 | .takes_value = true, | 249 | .takes_value = .One, |
| 250 | }, | ||
| 251 | clap.Param(u8){ | ||
| 252 | .id = 3, | ||
| 253 | .names = clap.Names{ .long = "dd" }, | ||
| 254 | .takes_value = .Many, | ||
| 243 | }, | 255 | }, |
| 244 | }; | 256 | }; |
| 245 | 257 | ||
| 246 | const aa = ¶ms[0]; | 258 | const aa = ¶ms[0]; |
| 247 | const bb = ¶ms[1]; | 259 | const bb = ¶ms[1]; |
| 248 | const cc = ¶ms[2]; | 260 | const cc = ¶ms[2]; |
| 261 | const dd = ¶ms[3]; | ||
| 249 | 262 | ||
| 250 | testNoErr( | 263 | testNoErr( |
| 251 | ¶ms, | 264 | ¶ms, |
| 252 | &[_][]const u8{ | 265 | &[_][]const u8{ |
| 253 | "--aa", "--bb", | 266 | "--aa", "--bb", |
| 254 | "--cc", "0", | 267 | "--cc", "0", |
| 255 | "--cc=0", | 268 | "--cc=0", "--dd=0", |
| 256 | }, | 269 | }, |
| 257 | &[_]Arg(u8){ | 270 | &[_]Arg(u8){ |
| 258 | Arg(u8){ .param = aa }, | 271 | Arg(u8){ .param = aa }, |
| 259 | Arg(u8){ .param = bb }, | 272 | Arg(u8){ .param = bb }, |
| 260 | Arg(u8){ .param = cc, .value = "0" }, | 273 | Arg(u8){ .param = cc, .value = "0" }, |
| 261 | Arg(u8){ .param = cc, .value = "0" }, | 274 | Arg(u8){ .param = cc, .value = "0" }, |
| 275 | Arg(u8){ .param = dd, .value = "0" }, | ||
| 262 | }, | 276 | }, |
| 263 | ); | 277 | ); |
| 264 | } | 278 | } |
| @@ -266,7 +280,7 @@ test "clap.streaming.StreamingClap: long params" { | |||
| 266 | test "clap.streaming.StreamingClap: positional params" { | 280 | test "clap.streaming.StreamingClap: positional params" { |
| 267 | const params = [_]clap.Param(u8){clap.Param(u8){ | 281 | const params = [_]clap.Param(u8){clap.Param(u8){ |
| 268 | .id = 0, | 282 | .id = 0, |
| 269 | .takes_value = true, | 283 | .takes_value = .One, |
| 270 | }}; | 284 | }}; |
| 271 | 285 | ||
| 272 | testNoErr( | 286 | testNoErr( |
| @@ -301,11 +315,11 @@ test "clap.streaming.StreamingClap: all params" { | |||
| 301 | .short = 'c', | 315 | .short = 'c', |
| 302 | .long = "cc", | 316 | .long = "cc", |
| 303 | }, | 317 | }, |
| 304 | .takes_value = true, | 318 | .takes_value = .One, |
| 305 | }, | 319 | }, |
| 306 | clap.Param(u8){ | 320 | clap.Param(u8){ |
| 307 | .id = 3, | 321 | .id = 3, |
| 308 | .takes_value = true, | 322 | .takes_value = .One, |
| 309 | }, | 323 | }, |
| 310 | }; | 324 | }; |
| 311 | 325 | ||