diff options
Diffstat (limited to 'index.zig')
| -rw-r--r-- | index.zig | 46 |
1 files changed, 42 insertions, 4 deletions
| @@ -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 | |||
| 336 | test "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 | } | ||