I’m working on a CLI app without using external dependencies and have a rough sketch in mind.
The CLI is going to work like:
zig run src/main.zig -- --create --name "foo" --due "today" --priority 8
zig run src/main.zig -- --delete --name "foo"
and its outline looks like:
const Action = enum {
default,
help,
create,
delete,
};
const ActionMap: StaticStringMap(Action) = .initComptime(.{
.{ "--help", .help },
.{ "--list", .list },
.{ "--create", .create },
.{ "--delete", .delete },
});
const CreateTodoOption = enum {
name,
due,
priority,
};
const CreateTodoOptions: StaticStringMap(CreateTodoOption) = .initComptime(.{
.{ "--name", .name },
.{ "--due", .due },
.{ "--priority", .priority },
});
const Args = struct {
action: Action // Action is an enum
create: CreateArgs // CreateArgs is a struct
delete: DeleteArgs // DeleteArgs is a struct
pub fn init() Args {}
pub fn parse(self: *Args, gpa: Allocator, out: Io.Writer, iter: *ArgIterator) !Args {
// create output buffer
// skip program name
// iterate over the arguments
// // use static string map to get enum from string
// // switch based on enum by calling a different parse method in the relevant struct (CreateArgs or DeleteArgs)
// return the modified Args object
}
}}
const CreateArgs = struct {
name: ?[]const u8,
due: ?[]const u8,
priority: u16,
pub fn parse(self: *CreateArgs, gpa: Allocator, out: Io.Writer, iter: *ArgIterator, arg: []const u8) !CreateArgs {
// Using parameter `arg`, get enum value from `CreateTodoOptions`
// switch based on value by (check for errors)
// return the modified Args object
}
}
// ...
// Delete related things will be similar to Create
// ...
Questions:
How can I unit test the Args struct? Haven’t found an example on testing std.process.ArgIterator.
The idea is for the help menu text to have usage information and for unit testing to cover them and document behavior like no argument provided, duplicate argument, etc.
Is there a better way to design the app?
( No change was made to build.zig after zig init )