Skip to content

Commit 622b7c4

Browse files
committed
Compiling now, working out some various kinks
1 parent 7afea16 commit 622b7c4

File tree

1 file changed

+29
-24
lines changed

1 file changed

+29
-24
lines changed

src/sneaky.zig

+29-24
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub const CliError = error{ InvalidArg, InvalidNumberOfArgs, CliArgumentNotFound
99
const ArgMetadata = struct {
1010
key: []const u8,
1111
value: []const u8,
12-
comptime typ: std.builtin.Type = type,
12+
comptime typ: type = type,
1313
optional: bool,
1414
};
1515

@@ -126,17 +126,17 @@ pub fn Snek(comptime CliInterface: type) type {
126126
};
127127

128128
unwrap_for: inline for (cli_reflected.Struct.fields) |field| {
129-
const arg = self.arg_metadata.get(field.name);
129+
const arg = self.arg_metadata.get(field.name) orelse null;
130130

131131
// If arg does NOT exist and the field is NOT optional, its an error case, so handle accordingly
132-
if (!arg) {
132+
if (arg == null) {
133133
switch (@typeInfo(field.type)) {
134134
.Optional => {
135-
continue :unwrap_for;
135+
break :unwrap_for;
136136
},
137137
else => {
138138
// Check if there is a default value, if there is, move on (same case as an optional). Else, error case
139-
if (field.default_value) continue :unwrap_for;
139+
if (field.default_value == null) break :unwrap_for;
140140

141141
std.debug.print("Required arugment {s} was not found in CLI flags. Check -help menu for required flags", .{field.name});
142142
return CliError.RequiredArgumentNotFound;
@@ -184,6 +184,10 @@ pub fn Snek(comptime CliInterface: type) type {
184184
// Skip first line, its always the name of the calling function
185185
_ = args.skip();
186186

187+
const interface: CliInterface = undefined;
188+
189+
const cli_reflected = @typeInfo(@TypeOf(interface));
190+
187191
while (args.next()) |arg| {
188192
if (arg[0] != '-') {
189193
return CliError.InvalidCommand;
@@ -213,33 +217,34 @@ pub fn Snek(comptime CliInterface: type) type {
213217
}
214218

215219
// No struct field of this name was found. Send error instead of moving on
216-
if (!@hasField(CliInterface, arg_key_d)) return CliError.InvalidCommand;
220+
if (!self.hasKey(arg_key_d)) return CliError.InvalidCommand;
221+
222+
var is_optional: bool = false;
223+
comptime var typ: type = undefined;
224+
inline for (cli_reflected.Struct.fields) |field| {
225+
switch (@typeInfo(field.type)) {
226+
.Optional => {
227+
is_optional = true;
228+
},
229+
else => {
230+
typ = @TypeOf(field.type);
231+
},
232+
}
233+
}
217234

218235
// .typ is used to eventually switch when we marshal the type of the value into the struct field
219-
try self.arg_metadata.put(arg_key_d, .{ .key = arg_key_d, .value = std.mem.trim(u8, arg_val_d, " "), .optional = self.isOptional(arg_key_d), .typ = extractTypeInfoFromKey(arg_key_d) });
236+
try self.arg_metadata.put(arg_key_d, .{ .key = arg_key_d, .value = std.mem.trim(u8, arg_val_d, " "), .optional = is_optional, .typ = typ });
220237
}
221238
}
222239

223-
fn extractTypeInfoFromKey(key: []const u8) std.builtin.Type {
224-
const s_enum = std.meta.stringToEnum(CliInterface, key);
225-
226-
// We assume that the field is already found since it passed the hasKey check. So we do *not* handle the null case.
227-
const field_info = std.meta.fieldInfo(CliInterface, s_enum.?);
228-
229-
return @typeInfo(field_info);
230-
}
231-
232-
fn isOptional(self: *Self, key: []const u8) bool {
240+
fn hasKey(self: *Self, key: []const u8) bool {
233241
_ = self;
234242

235-
switch (extractTypeInfoFromKey(key)) {
236-
.Optional => {
237-
return true;
238-
},
239-
else => {
240-
return false;
241-
},
243+
inline for (std.meta.fields(CliInterface)) |field| {
244+
if (std.mem.eql(u8, key, field.name)) return true;
242245
}
246+
247+
return false;
243248
}
244249

245250
// Ensures passed in value is a struct. It cannot be anything else so strict checking is applied to public functions

0 commit comments

Comments
 (0)