Refactored clap to use inline loops where possible.
Time to study the differences in the assemply
This commit is contained in:
parent
e22a541c08
commit
79f0c9cee9
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*.zig text eol=lf
|
108
clap.zig
108
clap.zig
|
@ -22,16 +22,16 @@ pub fn Option(comptime Result: type, comptime ParseError: type) type {
|
||||||
IgnoresRequired
|
IgnoresRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
parser: fn(&Result, []const u8) ParseError!void,
|
parse: fn(&Result, []const u8) ParseError!void,
|
||||||
help: []const u8,
|
help: []const u8,
|
||||||
kind: Kind,
|
kind: Kind,
|
||||||
takes_value: bool,
|
takes_value: bool,
|
||||||
short: ?u8,
|
short: ?u8,
|
||||||
long: ?[]const u8,
|
long: ?[]const u8,
|
||||||
|
|
||||||
pub fn init(parser: fn(&Result, []const u8) ParseError!void) Self {
|
pub fn init(parse_fn: fn(&Result, []const u8) ParseError!void) Self {
|
||||||
return Self {
|
return Self {
|
||||||
.parser = parser,
|
.parse = parse_fn,
|
||||||
.help = "",
|
.help = "",
|
||||||
.kind = Kind.Optional,
|
.kind = Kind.Optional,
|
||||||
.takes_value = false,
|
.takes_value = false,
|
||||||
|
@ -82,10 +82,12 @@ pub fn Parser(comptime Result: type, comptime ParseError: type, comptime default
|
||||||
// This limits the user to 128 required arguments, which is more than
|
// This limits the user to 128 required arguments, which is more than
|
||||||
// enough.
|
// enough.
|
||||||
const required_mask = comptime blk: {
|
const required_mask = comptime blk: {
|
||||||
|
var required_index : u128 = 0;
|
||||||
var required_res : u128 = 0;
|
var required_res : u128 = 0;
|
||||||
for (options) |option, i| {
|
for (options) |option, i| {
|
||||||
if (option.kind == OptionT.Kind.Required) {
|
if (option.kind == OptionT.Kind.Required) {
|
||||||
required_res = (required_res << 1) | 0x1;
|
required_res |= 0x1 << required_index;
|
||||||
|
required_index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +95,17 @@ pub fn Parser(comptime Result: type, comptime ParseError: type, comptime default
|
||||||
};
|
};
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn parse(args: []const []const u8) !Result {
|
fn newRequired(option: &const OptionT, old_required: u128, index: usize) u128 {
|
||||||
|
switch (option.kind) {
|
||||||
|
OptionT.Kind.Required => {
|
||||||
|
return bits.set(u128, old_required, u7(index), false);
|
||||||
|
},
|
||||||
|
OptionT.Kind.IgnoresRequired => return 0,
|
||||||
|
else => return old_required,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse(args: []const []const u8) !Result {
|
||||||
var result = *defaults;
|
var result = *defaults;
|
||||||
var required = required_mask;
|
var required = required_mask;
|
||||||
|
|
||||||
|
@ -111,57 +123,61 @@ pub fn Parser(comptime Result: type, comptime ParseError: type, comptime default
|
||||||
const arg = pair.arg;
|
const arg = pair.arg;
|
||||||
const kind = pair.kind;
|
const kind = pair.kind;
|
||||||
|
|
||||||
var required_index : usize = 0;
|
success: {
|
||||||
for (options) |option, op_i| {
|
var required_index = usize(0);
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
Arg.Kind.None => {
|
Arg.Kind.None => {
|
||||||
if (option.short != null) continue;
|
inline for (options) |option| {
|
||||||
if (option.long != null) continue;
|
defer if (option.kind == OptionT.Kind.Required) required_index += 1;
|
||||||
|
if (option.short != null) continue;
|
||||||
|
if (option.long != null) continue;
|
||||||
|
|
||||||
try option.parser(&result, arg);
|
try option.parse(&result, arg);
|
||||||
|
required = newRequired(option, required, required_index);
|
||||||
switch (option.kind) {
|
break :success;
|
||||||
OptionT.Kind.Required => {
|
|
||||||
required = bits.set(u128, required, u7(required_index), false);
|
|
||||||
required_index += 1;
|
|
||||||
},
|
|
||||||
OptionT.Kind.IgnoresRequired => {
|
|
||||||
required = 0;
|
|
||||||
required_index += 1;
|
|
||||||
},
|
|
||||||
else => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
},
|
},
|
||||||
Arg.Kind.Short => {
|
Arg.Kind.Short => {
|
||||||
const short = option.short ?? continue;
|
inline for (options) |option| {
|
||||||
if (arg.len != 1 or arg[0] != short) continue;
|
defer if (option.kind == OptionT.Kind.Required) required_index += 1;
|
||||||
|
const short = option.short ?? continue;
|
||||||
|
if (arg.len == 1 and arg[0] == short) {
|
||||||
|
if (option.takes_value) {
|
||||||
|
arg_i += 1;
|
||||||
|
if (args.len <= arg_i) return error.OptionMissingValue;
|
||||||
|
|
||||||
|
try option.parse(&result, args[arg_i]);
|
||||||
|
} else {
|
||||||
|
try option.parse(&result, []u8{});
|
||||||
|
}
|
||||||
|
|
||||||
|
required = newRequired(option, required, required_index);
|
||||||
|
break :success;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Arg.Kind.Long => {
|
Arg.Kind.Long => {
|
||||||
const long = option.long ?? continue;
|
inline for (options) |option| {
|
||||||
if (!mem.eql(u8, long, arg)) continue;
|
defer if (option.kind == OptionT.Kind.Required) required_index += 1;
|
||||||
|
const long = option.long ?? continue;
|
||||||
|
if (mem.eql(u8, arg, long)) {
|
||||||
|
if (option.takes_value) {
|
||||||
|
arg_i += 1;
|
||||||
|
if (args.len <= arg_i) return error.OptionMissingValue;
|
||||||
|
|
||||||
|
try option.parse(&result, args[arg_i]);
|
||||||
|
} else {
|
||||||
|
try option.parse(&result, []u8{});
|
||||||
|
}
|
||||||
|
|
||||||
|
required = newRequired(option, required, required_index);
|
||||||
|
break :success;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option.takes_value) arg_i += 1;
|
|
||||||
if (args.len <= arg_i) return error.MissingValueToArgument;
|
|
||||||
try option.parser(&result, args[arg_i]);
|
|
||||||
|
|
||||||
switch (option.kind) {
|
|
||||||
OptionT.Kind.Required => {
|
|
||||||
required = bits.set(u128, required, u7(required_index), false);
|
|
||||||
required_index += 1;
|
|
||||||
},
|
|
||||||
OptionT.Kind.IgnoresRequired => {
|
|
||||||
required = 0;
|
|
||||||
required_index += 1;
|
|
||||||
},
|
|
||||||
else => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
return error.InvalidArgument;
|
return error.InvalidArgument;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,7 +310,7 @@ test "clap.parse.Example" {
|
||||||
Case {
|
Case {
|
||||||
.args = [][]const u8 { "-g" },
|
.args = [][]const u8 { "-g" },
|
||||||
.res = Color { .r = 0, .g = 0, .b = 0 },
|
.res = Color { .r = 0, .g = 0, .b = 0 },
|
||||||
.err = error.MissingValueToArgument,
|
.err = error.OptionMissingValue,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user