diff options
| author | 2022-03-21 23:01:55 +0100 | |
|---|---|---|
| committer | 2022-03-21 23:01:55 +0100 | |
| commit | dc70efb14f9946a9ce1359cc5c731c445aff7298 (patch) | |
| tree | 6c31ec3e7b07b97fcfb1bf6aeeb101de6a1fd4c9 | |
| parent | Allow for clap to parse argument values into types (diff) | |
| download | zig-clap-dc70efb14f9946a9ce1359cc5c731c445aff7298.tar.gz zig-clap-dc70efb14f9946a9ce1359cc5c731c445aff7298.tar.xz zig-clap-dc70efb14f9946a9ce1359cc5c731c445aff7298.zip | |
Workaround infinit loop caused by `try` inside `inline for`
fixes #72
| -rw-r--r-- | clap.zig | 78 |
1 files changed, 59 insertions, 19 deletions
| @@ -421,29 +421,26 @@ pub fn parseEx( | |||
| 421 | .diagnostic = opt.diagnostic, | 421 | .diagnostic = opt.diagnostic, |
| 422 | }; | 422 | }; |
| 423 | while (try stream.next()) |arg| { | 423 | while (try stream.next()) |arg| { |
| 424 | // TODO: We cannot use `try` inside the inline for because of a compiler bug that | ||
| 425 | // generates an infinit loop. For now, use a variable to store the error | ||
| 426 | // and use `try` outside. The downside of this is that we have to use | ||
| 427 | // `anyerror` :( | ||
| 428 | var res: anyerror!void = {}; | ||
| 424 | inline for (params) |*param| { | 429 | inline for (params) |*param| { |
| 425 | if (param == arg.param) { | 430 | if (param == arg.param) { |
| 426 | const parser = comptime switch (param.takes_value) { | 431 | res = parseArg( |
| 427 | .none => undefined, | 432 | Id, |
| 428 | .one, .many => @field(value_parsers, param.id.value()), | 433 | param.*, |
| 429 | }; | 434 | value_parsers, |
| 430 | 435 | allocator, | |
| 431 | // TODO: Update opt.diagnostics when `parser` fails. This is blocked by compiler | 436 | &arguments, |
| 432 | // bugs that causes an infinit loop. | 437 | &positionals, |
| 433 | const longest = comptime param.names.longest(); | 438 | arg, |
| 434 | switch (longest.kind) { | 439 | ); |
| 435 | .short, .long => switch (param.takes_value) { | ||
| 436 | .none => @field(arguments, longest.name) = true, | ||
| 437 | .one => @field(arguments, longest.name) = try parser(arg.value.?), | ||
| 438 | .many => { | ||
| 439 | const value = try parser(arg.value.?); | ||
| 440 | try @field(arguments, longest.name).append(allocator, value); | ||
| 441 | }, | ||
| 442 | }, | ||
| 443 | .positinal => try positionals.append(try parser(arg.value.?)), | ||
| 444 | } | ||
| 445 | } | 440 | } |
| 446 | } | 441 | } |
| 442 | |||
| 443 | try res; | ||
| 447 | } | 444 | } |
| 448 | 445 | ||
| 449 | var result_args = Arguments(Id, params, value_parsers, .slice){}; | 446 | var result_args = Arguments(Id, params, value_parsers, .slice){}; |
| @@ -465,6 +462,34 @@ pub fn parseEx( | |||
| 465 | }; | 462 | }; |
| 466 | } | 463 | } |
| 467 | 464 | ||
| 465 | fn parseArg( | ||
| 466 | comptime Id: type, | ||
| 467 | comptime param: Param(Id), | ||
| 468 | comptime value_parsers: anytype, | ||
| 469 | allocator: mem.Allocator, | ||
| 470 | arguments: anytype, | ||
| 471 | positionals: anytype, | ||
| 472 | arg: streaming.Arg(Id), | ||
| 473 | ) !void { | ||
| 474 | const parser = comptime switch (param.takes_value) { | ||
| 475 | .none => undefined, | ||
| 476 | .one, .many => @field(value_parsers, param.id.value()), | ||
| 477 | }; | ||
| 478 | |||
| 479 | const longest = comptime param.names.longest(); | ||
| 480 | switch (longest.kind) { | ||
| 481 | .short, .long => switch (param.takes_value) { | ||
| 482 | .none => @field(arguments, longest.name) = true, | ||
| 483 | .one => @field(arguments, longest.name) = try parser(arg.value.?), | ||
| 484 | .many => { | ||
| 485 | const value = try parser(arg.value.?); | ||
| 486 | try @field(arguments, longest.name).append(allocator, value); | ||
| 487 | }, | ||
| 488 | }, | ||
| 489 | .positinal => try positionals.append(try parser(arg.value.?)), | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 468 | pub fn ResultEx( | 493 | pub fn ResultEx( |
| 469 | comptime Id: type, | 494 | comptime Id: type, |
| 470 | comptime params: []const Param(Id), | 495 | comptime params: []const Param(Id), |
| @@ -580,6 +605,21 @@ fn Arguments( | |||
| 580 | } }); | 605 | } }); |
| 581 | } | 606 | } |
| 582 | 607 | ||
| 608 | test "str and u64" { | ||
| 609 | const params = comptime &.{ | ||
| 610 | parseParam("--str <str>") catch unreachable, | ||
| 611 | parseParam("--num <u64>") catch unreachable, | ||
| 612 | }; | ||
| 613 | |||
| 614 | var iter = args.SliceIterator{ | ||
| 615 | .args = &.{ "--num", "10", "--str", "cooley_rec_inp_ptr" }, | ||
| 616 | }; | ||
| 617 | var res = try parseEx(Help, params, parsers.default, &iter, .{ | ||
| 618 | .allocator = testing.allocator, | ||
| 619 | }); | ||
| 620 | defer res.deinit(); | ||
| 621 | } | ||
| 622 | |||
| 583 | test "" { | 623 | test "" { |
| 584 | const params = comptime &.{ | 624 | const params = comptime &.{ |
| 585 | parseParam("-a, --aa") catch unreachable, | 625 | parseParam("-a, --aa") catch unreachable, |