-
Notifications
You must be signed in to change notification settings - Fork 6
Value
A Value (also known as a Positional Argument) is an Argument Type that is expected in a specific order and should be interpreted as a specific Type. The full list of available Types can be seen in cova.Value.Generic
and customized via cova.Value.Custom
, but the basics are Boolean, String ([]const u8
), Integer (u/i#
), or Float (f#
). A single Value can store individual or multiple instances of one of these Types. Values are also used to hold and represent the data held by an Option via the cova.Option.Custom.val
field. As such, anything that applies to Values is also "inherited" by Options.
Ultimately, cova.Value.Custom
is what library users will most often end up dealing with.
The base data for a Value is held within a cova.Value.Typed
instance. However, to provide flexibility for the Cova library and library users, the cova.Value.Generic
union will wrap any cova.Value.Typed
. This allows Values to hold data for nearly any arbitrary Type and still be handled in a generic manner in cases such as function parameters, function returns, collections, etc. That said, if the actual parsed data of the Value is needed, the appropriate cova.Value.Generic
field must be used. Field names for this union are simply the Value's Child Type name with the exception of []const u8
which is the .string
field.
Finally, the cova.Value.Custom
sets up and wraps cova.Value.Generic
union. This Type is used similarly to cova.Command.Custom
and cova.Option.Custom
. It allows common-to-all properties of Values within a project to be configured and provides easy methods for accessing properties of individual Values.
This process mirrors that of Option Types nearly one-for-one. A cova.Value.Config
can be configured directly within the Command Config via the cova.Command.Config.val_config
field. If not configured, the defaults will be used. A major feature of the Custom Value Type and Generic Value Union combination is the ability to set custom types for the Generic Value Union. This is accomplished via the cova.Value.Config
, by setting the cova.Value.Config.custom_types
field.
Adding custom Child Types allows Cova to parse argument tokens into virtually any Type. This is accomplished by first adding the custom Child Types to the Value.Config.custom_types
field, then (non-primitive Types) specifying parsing functions for these Types via Value.Config.child_type_parse_fns
as seen here:
const CommandT = cova.Command.Custom(cova.Command.Config{
.global_help_prefix = "Example",
.val_config = .{
.custom_types = &.{
std.net.Address,
std.fs.File,
},
.child_type_parse_fns = &.{
.{
.ChildT = std.net.Address,
.parse_fn = struct{
pub fn parseIP(addr: []const u8, _: std.mem.Allocator) !std.net.Address {
var iter = std.mem.splitScalar(u8, addr, ':');
return net.Address.parseIp(
iter.first(),
try std.fmt.parseInt(u16, iter.next() orelse "-", 10),
) catch |err| {
std.log.err("The provided IP address '{s}' is invalid.", .{ addr });
return err;
};
}
}.parseIP,
},
.{
.ChildT = std.fs.File,
.parse_fn = struct{
pub fn parseFile(path: []const u8, _: std.mem.Allocator) !std.fs.File {
var cwd = std.fs.cwd();
return cwd.openFile(path, .{ .lock = .shared }) catch |err| {
std.log.err("The provided path to the File '{s}' is invalid.", .{ path });
return err;
};
}
}.parseFile,
},
},
}
});
Similar to Options, Values are designed to be set up within a Command. Specifically, within a Command's cova.Command.Custom.vals
field. This can be done using a combination of Zig's Union and Anonymous Struct (Tuple) syntax or by using the cova.Value.ofType()
function.
Values can be given a Default value using the cova.Value.Typed.default_val
field as well as an alternate Parsing Function and a Validation Function using the cova.Value.Typed.parse_fn
and cova.Value.Typed.valid_fn
fields respectively. An example of how to create an anonymous function for these fields can be seen below. There are also common functions and function builders available within both cova.Value.ParsingFns
and cova.Value.ValidationFns
.
These functions allow for simple and powerful additions to how Values are parsed. For instance, the true
value for Booleans can be expanded to include more words (i.e. true = "yes", "y", "on"
), a numeric value can be limited to a certain range of numbers (i.e. arg > 10 and arg <= 1000
), or an arbitrary string can be converted to something else (i.e. "eight" = 8
). Moreover, since these functions all follow normal Zig syntax, they can be combined into higher level functions for more complex parsing and validation. Finally, the custom parsing functions in particular allow Custom Types to be parsed directly from a given argument token. For example, converting a given filepath into a std.fs.File
as seen above.
Example:
// Within a Command
...
.vals = &.{
Value.ofType([]const u8, .{
.name = "str_val",
.description = "A string value for the command.",
}),
// Using Zig's union creation syntax
.{ .generic = .{ .u128, .{
.name = "cmd_u128",
.description = "A u128 value for the command.",
// Default Value
.default_val = 654321,
// Validation Function
.valid_fn = struct{ fn valFn(val: u128) bool { return val > 123 and val < 987654321; } }.valFn,
} } },
}
Values will be parsed to their corresponding types which can then be retrieved using get()
for Individual Values or getAll()
for Multi-Values.
Looking for Cova's API Documentation? Click here!