summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jimmi Holst Christensen2024-10-22 16:58:02 +0200
committerGravatar Jimmi Holst Christensen2024-10-22 16:58:02 +0200
commit51336730a3b17badf4b50626e556e0348961bf01 (patch)
treeb52a8d4eb9e81f47c99fcb12a0aea6141f2c38a3
parentMove updated README to template (diff)
downloadzig-clap-51336730a3b17badf4b50626e556e0348961bf01.tar.gz
zig-clap-51336730a3b17badf4b50626e556e0348961bf01.tar.xz
zig-clap-51336730a3b17badf4b50626e556e0348961bf01.zip
refactor: Remove workaround in `parseEx` that required `anyerror`
-rw-r--r--clap.zig69
1 files changed, 22 insertions, 47 deletions
diff --git a/clap.zig b/clap.zig
index 8040852..999f87b 100644
--- a/clap.zig
+++ b/clap.zig
@@ -741,26 +741,30 @@ pub fn parseEx(
741 .assignment_separators = opt.assignment_separators, 741 .assignment_separators = opt.assignment_separators,
742 }; 742 };
743 while (try stream.next()) |arg| { 743 while (try stream.next()) |arg| {
744 // TODO: We cannot use `try` inside the inline for because of a compiler bug that 744 inline for (params) |*param| continue_params_loop: {
745 // generates an infinite loop. For now, use a variable to store the error 745 if (param != arg.param)
746 // and use `try` outside. The downside of this is that we have to use 746 // This is a trick to emulate a runtime `continue` in an `inline for`.
747 // `anyerror` :( 747 break :continue_params_loop;
748 var res: anyerror!void = {}; 748
749 inline for (params) |*param| { 749 const parser = comptime switch (param.takes_value) {
750 if (param == arg.param) { 750 .none => null,
751 res = parseArg( 751 .one, .many => @field(value_parsers, param.id.value()),
752 Id, 752 };
753 param.*, 753
754 value_parsers, 754 const longest = comptime param.names.longest();
755 allocator, 755 const name = longest.name[0..longest.name.len].*;
756 &arguments, 756 switch (longest.kind) {
757 &positionals, 757 .short, .long => switch (param.takes_value) {
758 arg, 758 .none => @field(arguments, &name) +|= 1,
759 ); 759 .one => @field(arguments, &name) = try parser(arg.value.?),
760 .many => {
761 const value = try parser(arg.value.?);
762 try @field(arguments, &name).append(allocator, value);
763 },
764 },
765 .positional => try positionals.append(try parser(arg.value.?)),
760 } 766 }
761 } 767 }
762
763 try res;
764 } 768 }
765 769
766 // We are done parsing, but our arguments are stored in lists, and not slices. Map the list 770 // We are done parsing, but our arguments are stored in lists, and not slices. Map the list
@@ -784,35 +788,6 @@ pub fn parseEx(
784 }; 788 };
785} 789}
786 790
787fn parseArg(
788 comptime Id: type,
789 comptime param: Param(Id),
790 comptime value_parsers: anytype,
791 allocator: mem.Allocator,
792 arguments: anytype,
793 positionals: anytype,
794 arg: streaming.Arg(Id),
795) !void {
796 const parser = comptime switch (param.takes_value) {
797 .none => undefined,
798 .one, .many => @field(value_parsers, param.id.value()),
799 };
800
801 const longest = comptime param.names.longest();
802 const name = longest.name[0..longest.name.len].*;
803 switch (longest.kind) {
804 .short, .long => switch (param.takes_value) {
805 .none => @field(arguments, &name) +|= 1,
806 .one => @field(arguments, &name) = try parser(arg.value.?),
807 .many => {
808 const value = try parser(arg.value.?);
809 try @field(arguments, &name).append(allocator, value);
810 },
811 },
812 .positional => try positionals.append(try parser(arg.value.?)),
813 }
814}
815
816/// The result of `parseEx`. Is owned by the caller and should be freed with `deinit`. 791/// The result of `parseEx`. Is owned by the caller and should be freed with `deinit`.
817pub fn ResultEx( 792pub fn ResultEx(
818 comptime Id: type, 793 comptime Id: type,