Expanding valid boolean value types.
Closed this issue · 7 comments
I believe that boolean flags should support any of 1, true, "yes", 0, false, or "no" as values, just as the character between flags and their values can be any of "", " ", or "=".
What do you think?
This is currently supported with custom parsing functions! There's even a specific Builder Function for that specific feature under Value.ParsingFunctions.Builder.altTrue()
(API docs here).
Using that function, you can build a function to parse any set of words as true
. There's an example in the covademo example that I've extracted below:
ValueT.ofType(bool, .{
.name = "cmd_bool",
.description = "A boolean value for the command.",
.parse_fn = Value.ParsingFns.Builder.altTrue(&.{ "true", "t", "yes", "y", "1" }),
}),
Wow this is consistently a far more complex library than I expect. Thanks! I'll close once I've tested this.
What about alternate true and false simultaneously, is that currently accessible in the library?
What about alternate false, is that currently accessible in the library?
There's not a direct Builder Function for that, but it's completely possible by creating your own function that wraps altTrue()
for the parse_fn
field. Rough example would be something like:
// This can be declared directly at the parse_fn field, but declaring it before the Command setup allows you to reuse it for multiple boolean Values easily.
fn altBool(arg: []const u8) !bool {
const altTrue = Value.ParsingFns.Builder.altTrue(&.{ "true", "strings", "list" });
const altFalse = Value.ParsingFns.Builder.altTrue(&.{ "false", "strings", "list" });
// Check for your true words
if (try altTrue(arg)) return true;
// Check for your false words
else if (try altFalse(arg)) return false;
// Error if the arg didn't match either list
return error.InvalidBooleanValue;
}
// Within your Command -> Values setup
...
ValueT.ofType(bool, .{
.name = "cmd_bool",
.description = "A bool that only takes specific words.",
.parse_fn = &altBool,
})
...
const std = @import("std");
const cova = @import("cova");
const ascii = @import("std").ascii;
pub usingnamespace @import("cova");
pub const CommandT = cova.Command.Custom(.{
.subcmds_help_fmt = "{s}:\t" ++ blue ++ "{s}" ++ zero,
.val_config = .{
.vals_help_fmt = "{s} ({s}):\t" ++ blue ++ "{s}" ++ zero,
.set_behavior = .Last,
},
.opt_config = .{
.help_fn = struct {
fn help(self: anytype, writer: anytype) !void {
try self.usage(writer);
try writer.print("\n{?s}{?s}{s}", .{ CommandT.indent_fmt, CommandT.indent_fmt, self.description });
}
}.help,
.usage_fmt = "{c}{?c}{s}{?s} " ++ yell ++ "\"{s}({s})\"" ++ zero,
.allow_abbreviated_long_opts = false,
.short_prefix = null,
.long_prefix = "-",
},
.indent_fmt = " ",
});
const blue = "\x1b[34m";
const yell = "\x1b[93m";
const zero = "\x1b[0m";
pub const setup_cmd: CommandT = .{
.name = "vpxl",
.description = "a VP9 encoder by Matt R Bonnette",
.opts = &.{
.{
.name = "mkv",
.long_name = "mkv",
.val = CommandT.ValueT.ofType([]const u8, .{ .name = "input_path " }),
},
.{
.name = "y4m",
.long_name = "y4m",
.val = CommandT.ValueT.ofType([]const u8, .{ .name = "input_path " }),
},
.{
.name = "yuv",
.long_name = "yuv",
.val = CommandT.ValueT.ofType([]const u8, .{ .name = "input_path " }),
},
.{
.name = "webm",
.long_name = "webm",
.val = CommandT.ValueT.ofType([]const u8, .{ .name = "output_path " }),
},
.{
.name = "ivf",
.long_name = "ivf",
.val = CommandT.ValueT.ofType([]const u8, .{ .name = "output_path " }),
},
.{
.name = "resume",
.long_name = "resume",
.description = "A boolean value for the command.\n",
.val = CommandT.ValueT.ofType(bool, .{
.name = "",
.parse_fn = &parseBool,
}),
},
},
};
pub fn parseBool(arg: []const u8) !bool {
const T = [_][]const u8{ "1", "true", "t", "yes", "y" };
const F = [_][]const u8{ "0", "false", "f", "no", "n" };
for (T) |value| if (ascii.eqlIgnoreCase(value, arg)) return true;
for (F) |value| if (ascii.eqlIgnoreCase(value, arg)) return false;
return error.InvalidBooleanValue;
}
So I need to create a custom value type for this, because your builtin bool type cannot accept values for some reason. I can probably figure this out, but I thought I should show you what I was trying to do more clearly.
"because your builtin bool type cannot accept values for some reason"
This is definitely a bug. Good find! I've fixed it and I'm pushing the commit now.
The new behavior will allow Boolean Options to accept a value if they have a custom parse_fn
.
Wonderful!