Skip to content

Commit

Permalink
Enable setting bool options to false
Browse files Browse the repository at this point in the history
Closes #7 #31
  • Loading branch information
sam701 committed Dec 18, 2023
1 parent cf4a6a8 commit 588c003
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 7 deletions.
47 changes: 41 additions & 6 deletions src/parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const argp = @import("./arg.zig");
const Printer = @import("./Printer.zig");
const vref = @import("./value_ref.zig");
const mkRef = vref.mkRef;
const value_parser = @import("value_parser.zig");
const str_true = value_parser.str_true;
const str_false = value_parser.str_false;

pub const ParseResult = command.ExecFn;

Expand Down Expand Up @@ -39,6 +42,7 @@ pub fn Parser(comptime Iterator: type) type {
app: *const command.App,
command_path: std.ArrayList(*const command.Command),
position_argument_ix: usize = 0,
next_arg: ?[]const u8 = null,

pub fn init(app: *const command.App, it: Iterator, alloc: Allocator) !Self {
return Self{
Expand All @@ -60,9 +64,9 @@ pub fn Parser(comptime Iterator: type) type {
pub fn parse(self: *Self) anyerror!ParseResult {
try self.command_path.append(&self.app.command);

_ = self.next_arg();
_ = self.nextArg();
var args_only = false;
while (self.next_arg()) |arg| {
while (self.nextArg()) |arg| {
if (args_only) {
try self.handlePositionalArgument(arg);
} else if (argp.interpret(arg)) |interpretation| {
Expand Down Expand Up @@ -207,10 +211,19 @@ pub fn Parser(comptime Iterator: type) type {
return args_only;
}

fn next_arg(self: *Self) ?[]const u8 {
fn nextArg(self: *Self) ?[]const u8 {
if (self.next_arg) |arg| {
self.next_arg = null;
return arg;
}
return self.arg_iterator.next();
}

fn putArgBack(self: *Self, value: []const u8) void {
std.debug.assert(self.next_arg == null);
self.next_arg = value;
}

fn process_option(self: *Self, option_interpretation: *const argp.OptionInterpretation) !void {
var opt: *command.Option = switch (option_interpretation.option_type) {
.long => self.find_option_by_name(option_interpretation.name),
Expand All @@ -226,10 +239,32 @@ pub fn Parser(comptime Iterator: type) type {
}

if (opt.value_ref.value_data.is_bool) {
try opt.value_ref.put("true", self.alloc);
// TODO: bool argument can be explicitly passed as a value
if (option_interpretation.value) |opt_value| {
var lw = try self.alloc.alloc(u8, opt_value.len);
defer self.alloc.free(lw);

lw = std.ascii.lowerString(lw, opt_value);
try opt.value_ref.put(lw, self.alloc);
return;
}

const following_arg = self.nextArg();
if (following_arg) |arg| {
if (arg.len > 0 and arg[0] != '-') {
var lw = try self.alloc.alloc(u8, arg.len);
defer self.alloc.free(lw);

lw = std.ascii.lowerString(lw, arg);
if (std.mem.eql(u8, lw, str_true) or std.mem.eql(u8, lw, str_false)) {
try opt.value_ref.put(lw, self.alloc);
return;
}
}
self.putArgBack(arg);
}
try opt.value_ref.put(str_true, self.alloc);
} else {
const arg = option_interpretation.value orelse self.next_arg() orelse {
const arg = option_interpretation.value orelse self.nextArg() orelse {
self.fail("missing argument for {s}", .{opt.long_name});
unreachable;
};
Expand Down
27 changes: 27 additions & 0 deletions src/tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,33 @@ test "int and float" {
try expect(15.25 == bb);
}

test "bools" {
var aa: bool = true;
var bb: bool = false;
var cc: bool = false;
var aa_opt = command.Option{
.long_name = "aa",
.help = "option aa",
.value_ref = mkRef(&aa),
};
var bb_opt = command.Option{
.long_name = "bb",
.help = "option bb",
.value_ref = mkRef(&bb),
};
var cc_opt = command.Option{
.long_name = "cc",
.short_alias = 'c',
.help = "option cc",
.value_ref = mkRef(&cc),
};

try runOptions(&.{ "abc", "--aa=faLSE", "-c", "--bb", "trUE" }, &.{ &aa_opt, &bb_opt, &cc_opt });
try expect(!aa);
try expect(bb);
try expect(cc);
}

test "optional values" {
var aa: ?i32 = null;
var bb: ?f32 = 500;
Expand Down
10 changes: 9 additions & 1 deletion src/value_parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,22 @@ fn floatData(comptime ValueType: type, comptime DestinationType: type) ValueData
};
}

pub const str_true = "true";
pub const str_false = "false";

fn boolData(comptime DestinationType: type) ValueData {
return .{
.value_size = @sizeOf(DestinationType),
.is_bool = true,
.value_parser = struct {
fn parser(dest: *anyopaque, value: []const u8) anyerror!void {
const dt: *DestinationType = @ptrCast(@alignCast(dest));
dt.* = std.mem.eql(u8, value, "true");

if (std.mem.eql(u8, value, str_true)) {
dt.* = true;
} else if (std.mem.eql(u8, value, str_false)) {
dt.* = false;
} else return error.ParseBoolError;
}
}.parser,
.type_name = "bool",
Expand Down

0 comments on commit 588c003

Please sign in to comment.