summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--index.zig46
1 files changed, 42 insertions, 4 deletions
diff --git a/index.zig b/index.zig
index 7b82211..7351515 100644
--- a/index.zig
+++ b/index.zig
@@ -119,9 +119,9 @@ pub fn Clap(comptime Result: type) type {
119 } 119 }
120 120
121 if (param.takes_value) |parser| { 121 if (param.takes_value) |parser| {
122 try parser.parse(&@field(result, param.field), ??arg.value); 122 try parser.parse(getFieldPtr(&result, param.field), ??arg.value);
123 } else { 123 } else {
124 @field(result, param.field) = true; 124 *getFieldPtr(&result, param.field) = true;
125 } 125 }
126 handled[i] = true; 126 handled[i] = true;
127 } 127 }
@@ -130,6 +130,23 @@ pub fn Clap(comptime Result: type) type {
130 130
131 return result; 131 return result;
132 } 132 }
133
134 fn GetFieldPtrReturn(comptime Struct: type, comptime field: []const u8) type {
135 var inst: Struct = undefined;
136 const dot_index = comptime mem.indexOfScalar(u8, field, '.') ?? {
137 return @typeOf(&@field(inst, field));
138 };
139
140 return GetFieldPtrReturn(@typeOf(@field(inst, field[0..dot_index])), field[dot_index + 1..]);
141 }
142
143 fn getFieldPtr(curr: var, comptime field: []const u8) GetFieldPtrReturn(@typeOf(curr).Child, field) {
144 const dot_index = comptime mem.indexOfScalar(u8, field, '.') ?? {
145 return &@field(curr, field);
146 };
147
148 return getFieldPtr(&@field(curr, field[0..dot_index]), field[dot_index + 1..]);
149 }
133 }; 150 };
134} 151}
135 152
@@ -148,12 +165,12 @@ pub const Parser = struct {
148 }; 165 };
149 } 166 }
150 167
151 fn parse(comptime parser: Parser, field_ptr: takePtr(parser.FieldType), arg: []const u8) parser.Errors!void { 168 fn parse(comptime parser: Parser, field_ptr: TakePtr(parser.FieldType), arg: []const u8) parser.Errors!void {
152 return @ptrCast(parseFunc(parser.FieldType, parser.Errors), parser.func)(field_ptr, arg); 169 return @ptrCast(parseFunc(parser.FieldType, parser.Errors), parser.func)(field_ptr, arg);
153 } 170 }
154 171
155 // TODO: This is a workaround, since we don't have pointer reform yet. 172 // TODO: This is a workaround, since we don't have pointer reform yet.
156 fn takePtr(comptime T: type) type { return &T; } 173 fn TakePtr(comptime T: type) type { return &T; }
157 174
158 fn parseFunc(comptime FieldType: type, comptime Errors: type) type { 175 fn parseFunc(comptime FieldType: type, comptime Errors: type) type {
159 return fn(&FieldType, []const u8) Errors!void; 176 return fn(&FieldType, []const u8) Errors!void;
@@ -315,3 +332,24 @@ test "clap: position" {
315 testNoErr(clap, [][]const u8 { "-a", "-b" }, default.with("a", true).with("b", true)); 332 testNoErr(clap, [][]const u8 { "-a", "-b" }, default.with("a", true).with("b", true));
316 testErr(clap, [][]const u8 { "-b", "-a" }, error.InvalidPosition); 333 testErr(clap, [][]const u8 { "-b", "-a" }, error.InvalidPosition);
317} 334}
335
336test "clap: sub fields" {
337 const B = struct {
338 a: bool,
339 };
340 const A = struct {
341 b: B,
342 };
343
344 const clap = comptime Clap(A) {
345 .defaults = A { .b = B { .a = false } },
346 .params = []Param {
347 Param.short('a')
348 .with("field", "b.a"),
349 }
350 };
351
352 var arg_iter = core.ArgSliceIterator.init([][]const u8{ "-a" });
353 const res = clap.parse(debug.global_allocator, &arg_iter.iter) catch unreachable;
354 debug.assert(res.b.a == true);
355}