The arg iterator is now responsible for allocation instead of core.Clap
This commit is contained in:
parent
8ff2b3ff83
commit
5ebe2be10b
|
@ -7,8 +7,10 @@ const mem = std.mem;
|
|||
const Names = clap.Names;
|
||||
const Param = clap.Param;
|
||||
|
||||
const ArgError = clap.OsArgIterator.Error;
|
||||
|
||||
// TODO: More specific error in this func type.
|
||||
const Command = fn(&mem.Allocator, &clap.ArgIterator) error!void;
|
||||
const Command = fn(&mem.Allocator, &clap.ArgIterator(ArgError)) error!void;
|
||||
|
||||
const params = []Param(Command){
|
||||
Param(Command).init(help, false, Names.prefix("help")),
|
||||
|
@ -52,11 +54,12 @@ pub fn main() !void {
|
|||
|
||||
const allocator = &arena.allocator;
|
||||
|
||||
var args = clap.OsArgIterator.init();
|
||||
var parser = clap.Clap(Command).init(params, &args.iter, allocator);
|
||||
defer parser.deinit();
|
||||
var args = clap.OsArgIterator.init(allocator);
|
||||
defer args.deinit();
|
||||
|
||||
const exe = try args.iter.next();
|
||||
var parser = clap.Clap(Command, ArgError).init(params, &args.iter);
|
||||
|
||||
const exe = try parser.nextNoParse();
|
||||
const maybe_arg = parser.next() catch |err| b: {
|
||||
debug.warn("{}.\n", @errorName(err));
|
||||
// debug.warn(usage); TODO: error: evaluation exceeded 1000 backwards branches
|
||||
|
@ -71,7 +74,7 @@ pub fn main() !void {
|
|||
try arg.param.id(allocator, parser.iter);
|
||||
}
|
||||
|
||||
pub fn help(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) {
|
||||
pub fn help(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
|
||||
// debug.warn(usage); TODO: error: evaluation exceeded 1000 backwards branches
|
||||
}
|
||||
|
||||
|
@ -144,7 +147,7 @@ const missing_build_file =
|
|||
\\
|
||||
;
|
||||
|
||||
fn cmdBuild(allocator: &mem.Allocator, args: &clap.ArgIterator) !void {
|
||||
fn cmdBuild(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) !void {
|
||||
var init = false;
|
||||
var build_file: []const u8 = "build.zig";
|
||||
var cache_dir: []const u8 = "zig-cache";
|
||||
|
@ -157,8 +160,7 @@ fn cmdBuild(allocator: &mem.Allocator, args: &clap.ArgIterator) !void {
|
|||
var verbose_llvm_ir = false;
|
||||
var verbose_cimport = false;
|
||||
|
||||
var parser = clap.Clap(Build).init(build_params, args, allocator);
|
||||
defer parser.deinit();
|
||||
var parser = clap.Clap(Build, ArgError).init(build_params, args);
|
||||
|
||||
while (parser.next() catch |err| {
|
||||
debug.warn("{}.\n", @errorName(err));
|
||||
|
@ -321,17 +323,17 @@ const build_generic_usage =
|
|||
;
|
||||
|
||||
|
||||
fn cmdBuildExe(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) {
|
||||
fn cmdBuildExe(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
|
||||
}
|
||||
|
||||
// cmd:build-lib ///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fn cmdBuildLib(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) {
|
||||
fn cmdBuildLib(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
|
||||
}
|
||||
|
||||
// cmd:build-obj ///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fn cmdBuildObj(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) {
|
||||
fn cmdBuildObj(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
|
||||
}
|
||||
|
||||
// cmd:fmt /////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -348,17 +350,17 @@ const usage_fmt =
|
|||
\\
|
||||
;
|
||||
|
||||
fn cmdFmt(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) {
|
||||
fn cmdFmt(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
|
||||
}
|
||||
|
||||
// cmd:targets /////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fn cmdTargets(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) {
|
||||
fn cmdTargets(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
|
||||
}
|
||||
|
||||
// cmd:version /////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fn cmdVersion(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) {
|
||||
fn cmdVersion(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
|
||||
}
|
||||
|
||||
// cmd:test ////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -372,7 +374,7 @@ const usage_test =
|
|||
\\
|
||||
;
|
||||
|
||||
fn cmdTest(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) {
|
||||
fn cmdTest(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
|
||||
}
|
||||
|
||||
// cmd:run /////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -388,7 +390,7 @@ const usage_run =
|
|||
\\
|
||||
;
|
||||
|
||||
fn cmdRun(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) {
|
||||
fn cmdRun(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
|
||||
}
|
||||
|
||||
// cmd:translate-c /////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -404,7 +406,7 @@ const usage_translate_c =
|
|||
\\
|
||||
;
|
||||
|
||||
fn cmdTranslateC(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) {
|
||||
fn cmdTranslateC(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
|
||||
}
|
||||
|
||||
// cmd:zen /////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -426,7 +428,7 @@ const info_zen =
|
|||
\\
|
||||
;
|
||||
|
||||
fn cmdZen(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) {
|
||||
fn cmdZen(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
|
||||
}
|
||||
|
||||
// cmd:internal ////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -440,5 +442,5 @@ const usage_internal =
|
|||
\\
|
||||
;
|
||||
|
||||
fn cmdInternal(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) {
|
||||
fn cmdInternal(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
|
||||
}
|
||||
|
|
69
src/core.zig
69
src/core.zig
|
@ -136,34 +136,39 @@ pub fn Arg(comptime Id: type) type {
|
|||
}
|
||||
|
||||
/// A interface for iterating over command line arguments
|
||||
pub const ArgIterator = struct {
|
||||
const Error = error{OutOfMemory};
|
||||
pub fn ArgIterator(comptime E: type) type {
|
||||
return struct {
|
||||
const Self = this;
|
||||
const Error = E;
|
||||
|
||||
nextFn: fn(iter: &ArgIterator, allocator: &mem.Allocator) Error!?[]const u8,
|
||||
nextFn: fn(iter: &Self) Error!?[]const u8,
|
||||
|
||||
pub fn next(iter: &ArgIterator, allocator: &mem.Allocator) Error!?[]const u8 {
|
||||
return iter.nextFn(iter, allocator);
|
||||
}
|
||||
};
|
||||
pub fn next(iter: &Self) Error!?[]const u8 {
|
||||
return iter.nextFn(iter);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// An ::ArgIterator, which iterates over a slice of arguments.
|
||||
/// This implementation does not allocate.
|
||||
pub const ArgSliceIterator = struct {
|
||||
const Error = error{};
|
||||
|
||||
args: []const []const u8,
|
||||
index: usize,
|
||||
iter: ArgIterator,
|
||||
iter: ArgIterator(Error),
|
||||
|
||||
pub fn init(args: []const []const u8) ArgSliceIterator {
|
||||
return ArgSliceIterator {
|
||||
.args = args,
|
||||
.index = 0,
|
||||
.iter = ArgIterator {
|
||||
.iter = ArgIterator(Error) {
|
||||
.nextFn = nextFn,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn nextFn(iter: &ArgIterator, allocator: &mem.Allocator) ArgIterator.Error!?[]const u8 {
|
||||
fn nextFn(iter: &ArgIterator(Error)) Error!?[]const u8 {
|
||||
const self = @fieldParentPtr(ArgSliceIterator, "iter", iter);
|
||||
if (self.args.len <= self.index)
|
||||
return null;
|
||||
|
@ -176,22 +181,30 @@ pub const ArgSliceIterator = struct {
|
|||
/// An ::ArgIterator, which wraps the ArgIterator in ::std.
|
||||
/// On windows, this iterator allocates.
|
||||
pub const OsArgIterator = struct {
|
||||
args: os.ArgIterator,
|
||||
iter: ArgIterator,
|
||||
const Error = os.ArgIterator.NextError;
|
||||
|
||||
pub fn init() OsArgIterator {
|
||||
arena: heap.ArenaAllocator,
|
||||
args: os.ArgIterator,
|
||||
iter: ArgIterator(Error),
|
||||
|
||||
pub fn init(allocator: &mem.Allocator) OsArgIterator {
|
||||
return OsArgIterator {
|
||||
.arena = heap.ArenaAllocator.init(allocator),
|
||||
.args = os.args(),
|
||||
.iter = ArgIterator {
|
||||
.iter = ArgIterator(Error) {
|
||||
.nextFn = nextFn,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn nextFn(iter: &ArgIterator, allocator: &mem.Allocator) ArgIterator.Error!?[]const u8 {
|
||||
pub fn deinit(iter: &OsArgIterator) void {
|
||||
iter.arena.deinit();
|
||||
}
|
||||
|
||||
fn nextFn(iter: &ArgIterator(Error)) Error!?[]const u8 {
|
||||
const self = @fieldParentPtr(OsArgIterator, "iter", iter);
|
||||
if (builtin.os == builtin.Os.windows) {
|
||||
return try self.args.next(allocator) ?? return null;
|
||||
return try self.args.next(self.allocator) ?? return null;
|
||||
} else {
|
||||
return self.args.nextPosix();
|
||||
}
|
||||
|
@ -201,7 +214,7 @@ pub const OsArgIterator = struct {
|
|||
/// A command line argument parser which, given an ::ArgIterator, will parse arguments according
|
||||
/// to the ::params. ::Clap parses in an iterating manner, so you have to use a loop together with
|
||||
/// ::Clap.next to parse all the arguments of your program.
|
||||
pub fn Clap(comptime Id: type) type {
|
||||
pub fn Clap(comptime Id: type, comptime ArgError: type) type {
|
||||
return struct {
|
||||
const Self = this;
|
||||
|
||||
|
@ -215,14 +228,12 @@ pub fn Clap(comptime Id: type) type {
|
|||
};
|
||||
};
|
||||
|
||||
arena: heap.ArenaAllocator,
|
||||
params: []const Param(Id),
|
||||
iter: &ArgIterator,
|
||||
iter: &ArgIterator(ArgError),
|
||||
state: State,
|
||||
|
||||
pub fn init(params: []const Param(Id), iter: &ArgIterator, allocator: &mem.Allocator) Self {
|
||||
pub fn init(params: []const Param(Id), iter: &ArgIterator(ArgError)) Self {
|
||||
var res = Self {
|
||||
.arena = heap.ArenaAllocator.init(allocator),
|
||||
.params = params,
|
||||
.iter = iter,
|
||||
.state = State.Normal,
|
||||
|
@ -231,10 +242,6 @@ pub fn Clap(comptime Id: type) type {
|
|||
return res;
|
||||
}
|
||||
|
||||
pub fn deinit(clap: &Self) void {
|
||||
clap.arena.deinit();
|
||||
}
|
||||
|
||||
/// Get the next ::Arg that matches a ::Param.
|
||||
pub fn next(clap: &Self) !?Arg(Id) {
|
||||
const ArgInfo = struct {
|
||||
|
@ -246,7 +253,7 @@ pub fn Clap(comptime Id: type) type {
|
|||
|
||||
switch (clap.state) {
|
||||
State.Normal => {
|
||||
const full_arg = (try clap.nextNoParse()) ?? return null;
|
||||
const full_arg = (try clap.iter.next()) ?? return null;
|
||||
const arg_info = blk: {
|
||||
var arg = full_arg;
|
||||
var kind = ArgInfo.Kind.Bare;
|
||||
|
@ -294,7 +301,7 @@ pub fn Clap(comptime Id: type) type {
|
|||
if (maybe_value) |v|
|
||||
break :blk v;
|
||||
|
||||
break :blk (try clap.nextNoParse()) ?? return error.MissingValue;
|
||||
break :blk (try clap.iter.next()) ?? return error.MissingValue;
|
||||
};
|
||||
|
||||
return Arg(Id).init(param, value);
|
||||
|
@ -351,7 +358,7 @@ pub fn Clap(comptime Id: type) type {
|
|||
return Arg(Id).init(param, null);
|
||||
|
||||
if (arg.len <= next_index) {
|
||||
const value = (try clap.nextNoParse()) ?? return error.MissingValue;
|
||||
const value = (try clap.iter.next()) ?? return error.MissingValue;
|
||||
return Arg(Id).init(param, value);
|
||||
}
|
||||
|
||||
|
@ -364,11 +371,5 @@ pub fn Clap(comptime Id: type) type {
|
|||
|
||||
return error.InvalidArgument;
|
||||
}
|
||||
|
||||
// Returns the next arg in the underlying arg iterator
|
||||
pub fn nextNoParse(clap: &Self) !?[]const u8 {
|
||||
clap.state = State.Normal;
|
||||
return try clap.iter.next(&clap.arena.allocator);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -103,13 +103,13 @@ pub const Command = struct {
|
|||
return res;
|
||||
}
|
||||
|
||||
pub fn parse(comptime command: &const Command, allocator: &mem.Allocator, arg_iter: &core.ArgIterator) !command.Result {
|
||||
pub fn parse(comptime command: &const Command, allocator: &mem.Allocator, arg_iter: var) !command.Result {
|
||||
const Parent = struct {};
|
||||
var parent = Parent{};
|
||||
return command.parseHelper(&parent, allocator, arg_iter);
|
||||
}
|
||||
|
||||
fn parseHelper(comptime command: &const Command, parent: var, allocator: &mem.Allocator, arg_iter: &core.ArgIterator) !command.Result {
|
||||
fn parseHelper(comptime command: &const Command, parent: var, allocator: &mem.Allocator, arg_iter: var) !command.Result {
|
||||
const Result = struct {
|
||||
parent: @typeOf(parent),
|
||||
result: command.Result,
|
||||
|
@ -159,11 +159,10 @@ pub const Command = struct {
|
|||
};
|
||||
|
||||
var pos: usize = 0;
|
||||
var iter = core.Clap(usize).init(core_params, arg_iter, allocator);
|
||||
defer iter.deinit();
|
||||
var clap = core.Clap(usize, @typeOf(arg_iter.*).Error).init(core_params, arg_iter);
|
||||
|
||||
arg_loop:
|
||||
while (try iter.next()) |arg| : (pos += 1) {
|
||||
while (try clap.next()) |arg| : (pos += 1) {
|
||||
inline for(command.params) |param, i| {
|
||||
comptime const field = "result." ++ param.field;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ const Clap = core.Clap;
|
|||
|
||||
fn testNoErr(params: []const Param(u8), args: []const []const u8, ids: []const u8, values: []const ?[]const u8) void {
|
||||
var arg_iter = ArgSliceIterator.init(args);
|
||||
var iter = Clap(u8).init(params, &arg_iter.iter, debug.global_allocator);
|
||||
var iter = Clap(u8, ArgSliceIterator.Error).init(params, &arg_iter.iter);
|
||||
|
||||
var i: usize = 0;
|
||||
while (iter.next() catch unreachable) |arg| : (i += 1) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user