summaryrefslogtreecommitdiff
path: root/clap/comptime.zig
diff options
context:
space:
mode:
Diffstat (limited to 'clap/comptime.zig')
-rw-r--r--clap/comptime.zig70
1 files changed, 42 insertions, 28 deletions
diff --git a/clap/comptime.zig b/clap/comptime.zig
index 122ff16..7808f52 100644
--- a/clap/comptime.zig
+++ b/clap/comptime.zig
@@ -14,7 +14,7 @@ pub fn ComptimeClap(
14 var flags: usize = 0; 14 var flags: usize = 0;
15 var single_options: usize = 0; 15 var single_options: usize = 0;
16 var multi_options: usize = 0; 16 var multi_options: usize = 0;
17 var converted_params: []const clap.Param(usize) = &[_]clap.Param(usize){}; 17 var converted_params: []const clap.Param(usize) = &.{};
18 for (params) |param| { 18 for (params) |param| {
19 var index: usize = 0; 19 var index: usize = 0;
20 if (param.names.long != null or param.names.short != null) { 20 if (param.names.long != null or param.names.short != null) {
@@ -27,18 +27,18 @@ pub fn ComptimeClap(
27 ptr.* += 1; 27 ptr.* += 1;
28 } 28 }
29 29
30 const converted = clap.Param(usize){ 30 converted_params = converted_params ++ [_]clap.Param(usize){.{
31 .id = index, 31 .id = index,
32 .names = param.names, 32 .names = param.names,
33 .takes_value = param.takes_value, 33 .takes_value = param.takes_value,
34 }; 34 }};
35 converted_params = converted_params ++ [_]clap.Param(usize){converted};
36 } 35 }
37 36
38 return struct { 37 return struct {
39 single_options: [single_options]?[]const u8,
40 multi_options: [multi_options][]const []const u8, 38 multi_options: [multi_options][]const []const u8,
41 flags: [flags]bool, 39 single_options: [single_options][]const u8,
40 single_options_is_set: std.PackedIntArray(u1, single_options),
41 flags: std.PackedIntArray(u1, flags),
42 pos: []const []const u8, 42 pos: []const []const u8,
43 allocator: *mem.Allocator, 43 allocator: *mem.Allocator,
44 44
@@ -52,9 +52,12 @@ pub fn ComptimeClap(
52 var pos = std.ArrayList([]const u8).init(allocator); 52 var pos = std.ArrayList([]const u8).init(allocator);
53 53
54 var res = @This(){ 54 var res = @This(){
55 .single_options = [_]?[]const u8{null} ** single_options, 55 .multi_options = .{undefined} ** multi_options,
56 .multi_options = [_][]const []const u8{undefined} ** multi_options, 56 .single_options = .{undefined} ** single_options,
57 .flags = [_]bool{false} ** flags, 57 .single_options_is_set = std.PackedIntArray(u1, single_options).init(
58 .{0} ** single_options,
59 ),
60 .flags = std.PackedIntArray(u1, flags).init(.{0} ** flags),
58 .pos = undefined, 61 .pos = undefined,
59 .allocator = allocator, 62 .allocator = allocator,
60 }; 63 };
@@ -69,16 +72,18 @@ pub fn ComptimeClap(
69 try pos.append(arg.value.?); 72 try pos.append(arg.value.?);
70 } else if (param.takes_value == .one) { 73 } else if (param.takes_value == .one) {
71 debug.assert(res.single_options.len != 0); 74 debug.assert(res.single_options.len != 0);
72 if (res.single_options.len != 0) 75 if (res.single_options.len != 0) {
73 res.single_options[param.id] = arg.value.?; 76 res.single_options[param.id] = arg.value.?;
77 res.single_options_is_set.set(param.id, 1);
78 }
74 } else if (param.takes_value == .many) { 79 } else if (param.takes_value == .many) {
75 debug.assert(multis.len != 0); 80 debug.assert(multis.len != 0);
76 if (multis.len != 0) 81 if (multis.len != 0)
77 try multis[param.id].append(arg.value.?); 82 try multis[param.id].append(arg.value.?);
78 } else { 83 } else {
79 debug.assert(res.flags.len != 0); 84 debug.assert(res.flags.len() != 0);
80 if (res.flags.len != 0) 85 if (res.flags.len() != 0)
81 res.flags[param.id] = true; 86 res.flags.set(param.id, 1);
82 } 87 }
83 } 88 }
84 89
@@ -100,7 +105,7 @@ pub fn ComptimeClap(
100 if (param.takes_value != .none) 105 if (param.takes_value != .none)
101 @compileError(name ++ " is an option and not a flag."); 106 @compileError(name ++ " is an option and not a flag.");
102 107
103 return parser.flags[param.id]; 108 return parser.flags.get(param.id) != 0;
104 } 109 }
105 110
106 pub fn option(parser: @This(), comptime name: []const u8) ?[]const u8 { 111 pub fn option(parser: @This(), comptime name: []const u8) ?[]const u8 {
@@ -109,6 +114,8 @@ pub fn ComptimeClap(
109 @compileError(name ++ " is a flag and not an option."); 114 @compileError(name ++ " is a flag and not an option.");
110 if (param.takes_value == .many) 115 if (param.takes_value == .many)
111 @compileError(name ++ " takes many options, not one."); 116 @compileError(name ++ " takes many options, not one.");
117 if (parser.single_options_is_set.get(param.id) == 0)
118 return null;
112 return parser.single_options[param.id]; 119 return parser.single_options[param.id];
113 } 120 }
114 121
@@ -146,30 +153,37 @@ pub fn ComptimeClap(
146} 153}
147 154
148test "" { 155test "" {
149 const Clap = ComptimeClap(clap.Help, comptime &[_]clap.Param(clap.Help){ 156 const Clap = ComptimeClap(clap.Help, comptime &.{
150 clap.parseParam("-a, --aa ") catch unreachable, 157 clap.parseParam("-a, --aa") catch unreachable,
151 clap.parseParam("-b, --bb ") catch unreachable, 158 clap.parseParam("-b, --bb") catch unreachable,
152 clap.parseParam("-c, --cc <V>") catch unreachable, 159 clap.parseParam("-c, --cc <V>") catch unreachable,
153 clap.parseParam("-d, --dd <V>...") catch unreachable, 160 clap.parseParam("-d, --dd <V>...") catch unreachable,
154 clap.parseParam("<P>") catch unreachable, 161 clap.parseParam("<P>") catch unreachable,
155 }); 162 });
156 163
157 var iter = clap.args.SliceIterator{ 164 var iter = clap.args.SliceIterator{
158 .args = &[_][]const u8{ 165 .args = &.{
159 "-a", "-c", "0", "something", "-d", "a", "--dd", "b", 166 "-a", "-c", "0", "something", "-d", "a", "--dd", "b",
160 }, 167 },
161 }; 168 };
162 var args = try Clap.parse(&iter, .{ .allocator = testing.allocator }); 169 var args = try Clap.parse(&iter, .{ .allocator = testing.allocator });
163 defer args.deinit(); 170 defer args.deinit();
164 171
165 testing.expect(args.flag("-a")); 172 try testing.expect(args.flag("-a"));
166 testing.expect(args.flag("--aa")); 173 try testing.expect(args.flag("--aa"));
167 testing.expect(!args.flag("-b")); 174 try testing.expect(!args.flag("-b"));
168 testing.expect(!args.flag("--bb")); 175 try testing.expect(!args.flag("--bb"));
169 testing.expectEqualStrings("0", args.option("-c").?); 176 try testing.expectEqualStrings("0", args.option("-c").?);
170 testing.expectEqualStrings("0", args.option("--cc").?); 177 try testing.expectEqualStrings("0", args.option("--cc").?);
171 testing.expectEqual(@as(usize, 1), args.positionals().len); 178 try testing.expectEqual(@as(usize, 1), args.positionals().len);
172 testing.expectEqualStrings("something", args.positionals()[0]); 179 try testing.expectEqualStrings("something", args.positionals()[0]);
173 testing.expectEqualSlices([]const u8, &[_][]const u8{ "a", "b" }, args.options("-d")); 180 try testing.expectEqualSlices([]const u8, &.{ "a", "b" }, args.options("-d"));
174 testing.expectEqualSlices([]const u8, &[_][]const u8{ "a", "b" }, args.options("--dd")); 181 try testing.expectEqualSlices([]const u8, &.{ "a", "b" }, args.options("--dd"));
182}
183
184test "empty" {
185 const Clap = ComptimeClap(clap.Help, comptime &.{});
186 var iter = clap.args.SliceIterator{ .args = &.{} };
187 var args = try Clap.parse(&iter, .{ .allocator = testing.allocator });
188 defer args.deinit();
175} 189}