NOTE: Accord was made for use with zig master, it is not guaranteed to and likely will not work on release versions
-a -b -c -d 12
and -abcd12
.--option long
and --option=long
.--
will be considered a positional argument. The index for this will also be stored, so you can slice the positionals before or after --
if you want to have a distinction between them.items
storing the actual slice, separator_index
storing the aforementioned index of --
if it exists, and beforeSeparator
and afterSeparator
functions to get the positionals before and after the --
(if there’s no --
, then before will return everything and after will return nothing).
positionals.deinit(allocator)
.[]const u8
)accord.Flag
, when a flag argument is used it will return the opposite of its default valueFlag
)accord.Mask(int or enum type)
Flag
)
true_strings
and false_strings
settings to determine what is considered as true/false. Note that these are case insensitive.
true_strings = &.{ "true", "t", "yes", "1" }
false_strings &.{ "false", "f", "no", "0" }
radix
u8 setting, defaults to 0.
0b
= binary0o
= octal0x
= hexadecimalenum_parsing
enum setting with the values name
, value
, and both
, defaults to name
. Enums also inherit integer parsing settings for when parsing by value
.
name
means it will try to match the value with the names of the fields in the enum.value
means it will try to match the values of the fields.both
means it will first try to match the field values, and if that fails it will try to match the field names.null_strings
to determine when the value is parsed as null
. Note that these are case insensitive. Optionals also inherit options from their child type.
null_strings = &.{ "null", "nul", "nil" }
array_delimiter
and mask_delimiter
setting respectively, defaults to ","
for arrays and "|"
for masks. They will also inherit any settings from their child type (e.g. an array or mask of enums would also have the enum_parsing
and radix
settings available)In addition to all default types built into the library, you can also easily define your own custom parsing by fulfilling a particular interface.
All basic types supported in the library are also implemented through this system, so you can reference all of them for examples, the following is how the parsing interface for integers is implemented:
pub fn IntegerInterface(comptime T: type) type {
return struct {
pub const AccordParseSettings = struct {
radix: u8 = 0,
};
pub fn accordParse(parse_string: []const u8, comptime settings: anytype) AccordError!T {
const result = (if (settings.radix == 16)
std.fmt.parseInt(T, std.mem.trimLeft(u8, parse_string, "#"), settings.radix)
else
std.fmt.parseInt(T, parse_string, settings.radix));
return result catch error.OptionUnexpectedValue;
}
};
}
You can also implement custom no-argument flags by omitting the first argument in the function. The implementation of Flag
is as follows:
pub const Flag = struct {
pub fn accordParse(comptime settings: anytype) !bool {
return !settings.default_value;
}
};
The following is a truncated example of the enum parsing interface which demonstrates merging settings from other types. When merging settings like this, you may have the same field in multiple structs so long as they have the same type, and it will prioritize the default value of the setting of the earliest struct that has the field.
pub fn EnumInterface(comptime T: type) type {
const Tag = @typeInfo(T).Enum.tag_type;
returnt struct {
pub const AccordParseSettings = MergeStructs(&.{
struct {
const EnumSetting = enum { name, value, both };
enum_parsing: EnumSetting = .name,
},
InterfaceSettings(GetInterface(Tag)),
});
};
const allocator = std.heap.page_allocator;
var args_iterator = std.process.args();
const options = try accord.parse(&.{
//short name //long name //type //default value //parse options
accord.option('s', "string", []const u8, "default", .{}),
accord.option('c', "color", u32, 0x000000, .{ .radix = 16 }),
accord.option('f', "float", f32, 0.0, .{}),
accord.option('m', "mask", accord.Mask(u8), 0, .{}),
accord.option('a', "", accord.Flag, false, .{}), // option without long option
accord.option(0, "option", accord.Flag, false, .{}), // option without short option
accord.option('i', "optionalintarray", [2]?u32, .{ 0, 0 }, .{ .array_delimiter = "%" }),
}, allocator, &args_iterator);
defer options.positionals.deinit(allocator);
The above example called as
command positional1 -s"some string" --color ff0000 positional2 -f 1.2e4 --mask="2|3" -a positional3 --optionalintarray="null%23" -- --option positional4 positional5
would result in the following value:
{
string = "some string"
color = 0xff0000
float = 12000.0
mask = 3
a = true
option = false
intarray = { null, 23 }
positionals.items = { "command", "positional1", "positional2", "positional3", "--option", "positional4", "positional5" }
positionals.beforeSeparator() = { "command", "positional1", "positional2", "positional3" }
positionals.afterSeparator() = { "--option", "positional4", "positional5" }
}