summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jimmi HC2018-06-01 09:07:47 +0200
committerGravatar Jimmi HC2018-06-01 09:07:47 +0200
commit5ebe2be10b96410a6182a2aa66ff0d2bd43eed3f (patch)
tree9d6da79c50189aa92d12ba3d68ad2a1eff74cee6
parentId is now gotten through param of arg (diff)
downloadzig-clap-5ebe2be10b96410a6182a2aa66ff0d2bd43eed3f.tar.gz
zig-clap-5ebe2be10b96410a6182a2aa66ff0d2bd43eed3f.tar.xz
zig-clap-5ebe2be10b96410a6182a2aa66ff0d2bd43eed3f.zip
The arg iterator is now responsible for allocation instead of core.Clap
-rw-r--r--examples/core.zig42
-rw-r--r--src/core.zig67
-rw-r--r--src/extended.zig9
-rw-r--r--tests/core.zig2
4 files changed, 61 insertions, 59 deletions
diff --git a/examples/core.zig b/examples/core.zig
index 8bcc928..eb512ef 100644
--- a/examples/core.zig
+++ b/examples/core.zig
@@ -7,8 +7,10 @@ const mem = std.mem;
7const Names = clap.Names; 7const Names = clap.Names;
8const Param = clap.Param; 8const Param = clap.Param;
9 9
10const ArgError = clap.OsArgIterator.Error;
11
10// TODO: More specific error in this func type. 12// TODO: More specific error in this func type.
11const Command = fn(&mem.Allocator, &clap.ArgIterator) error!void; 13const Command = fn(&mem.Allocator, &clap.ArgIterator(ArgError)) error!void;
12 14
13const params = []Param(Command){ 15const params = []Param(Command){
14 Param(Command).init(help, false, Names.prefix("help")), 16 Param(Command).init(help, false, Names.prefix("help")),
@@ -52,11 +54,12 @@ pub fn main() !void {
52 54
53 const allocator = &arena.allocator; 55 const allocator = &arena.allocator;
54 56
55 var args = clap.OsArgIterator.init(); 57 var args = clap.OsArgIterator.init(allocator);
56 var parser = clap.Clap(Command).init(params, &args.iter, allocator); 58 defer args.deinit();
57 defer parser.deinit(); 59
60 const exe = try args.iter.next();
61 var parser = clap.Clap(Command, ArgError).init(params, &args.iter);
58 62
59 const exe = try parser.nextNoParse();
60 const maybe_arg = parser.next() catch |err| b: { 63 const maybe_arg = parser.next() catch |err| b: {
61 debug.warn("{}.\n", @errorName(err)); 64 debug.warn("{}.\n", @errorName(err));
62 // debug.warn(usage); TODO: error: evaluation exceeded 1000 backwards branches 65 // debug.warn(usage); TODO: error: evaluation exceeded 1000 backwards branches
@@ -71,7 +74,7 @@ pub fn main() !void {
71 try arg.param.id(allocator, parser.iter); 74 try arg.param.id(allocator, parser.iter);
72} 75}
73 76
74pub fn help(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) { 77pub fn help(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
75 // debug.warn(usage); TODO: error: evaluation exceeded 1000 backwards branches 78 // debug.warn(usage); TODO: error: evaluation exceeded 1000 backwards branches
76} 79}
77 80
@@ -144,7 +147,7 @@ const missing_build_file =
144 \\ 147 \\
145; 148;
146 149
147fn cmdBuild(allocator: &mem.Allocator, args: &clap.ArgIterator) !void { 150fn cmdBuild(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) !void {
148 var init = false; 151 var init = false;
149 var build_file: []const u8 = "build.zig"; 152 var build_file: []const u8 = "build.zig";
150 var cache_dir: []const u8 = "zig-cache"; 153 var cache_dir: []const u8 = "zig-cache";
@@ -157,8 +160,7 @@ fn cmdBuild(allocator: &mem.Allocator, args: &clap.ArgIterator) !void {
157 var verbose_llvm_ir = false; 160 var verbose_llvm_ir = false;
158 var verbose_cimport = false; 161 var verbose_cimport = false;
159 162
160 var parser = clap.Clap(Build).init(build_params, args, allocator); 163 var parser = clap.Clap(Build, ArgError).init(build_params, args);
161 defer parser.deinit();
162 164
163 while (parser.next() catch |err| { 165 while (parser.next() catch |err| {
164 debug.warn("{}.\n", @errorName(err)); 166 debug.warn("{}.\n", @errorName(err));
@@ -321,17 +323,17 @@ const build_generic_usage =
321; 323;
322 324
323 325
324fn cmdBuildExe(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) { 326fn cmdBuildExe(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
325} 327}
326 328
327// cmd:build-lib /////////////////////////////////////////////////////////////////////////////////// 329// cmd:build-lib ///////////////////////////////////////////////////////////////////////////////////
328 330
329fn cmdBuildLib(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) { 331fn cmdBuildLib(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
330} 332}
331 333
332// cmd:build-obj /////////////////////////////////////////////////////////////////////////////////// 334// cmd:build-obj ///////////////////////////////////////////////////////////////////////////////////
333 335
334fn cmdBuildObj(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) { 336fn cmdBuildObj(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
335} 337}
336 338
337// cmd:fmt ///////////////////////////////////////////////////////////////////////////////////////// 339// cmd:fmt /////////////////////////////////////////////////////////////////////////////////////////
@@ -348,17 +350,17 @@ const usage_fmt =
348 \\ 350 \\
349; 351;
350 352
351fn cmdFmt(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) { 353fn cmdFmt(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
352} 354}
353 355
354// cmd:targets ///////////////////////////////////////////////////////////////////////////////////// 356// cmd:targets /////////////////////////////////////////////////////////////////////////////////////
355 357
356fn cmdTargets(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) { 358fn cmdTargets(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
357} 359}
358 360
359// cmd:version ///////////////////////////////////////////////////////////////////////////////////// 361// cmd:version /////////////////////////////////////////////////////////////////////////////////////
360 362
361fn cmdVersion(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) { 363fn cmdVersion(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
362} 364}
363 365
364// cmd:test //////////////////////////////////////////////////////////////////////////////////////// 366// cmd:test ////////////////////////////////////////////////////////////////////////////////////////
@@ -372,7 +374,7 @@ const usage_test =
372 \\ 374 \\
373; 375;
374 376
375fn cmdTest(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) { 377fn cmdTest(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
376} 378}
377 379
378// cmd:run ///////////////////////////////////////////////////////////////////////////////////////// 380// cmd:run /////////////////////////////////////////////////////////////////////////////////////////
@@ -388,7 +390,7 @@ const usage_run =
388 \\ 390 \\
389; 391;
390 392
391fn cmdRun(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) { 393fn cmdRun(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
392} 394}
393 395
394// cmd:translate-c ///////////////////////////////////////////////////////////////////////////////// 396// cmd:translate-c /////////////////////////////////////////////////////////////////////////////////
@@ -404,7 +406,7 @@ const usage_translate_c =
404 \\ 406 \\
405; 407;
406 408
407fn cmdTranslateC(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) { 409fn cmdTranslateC(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
408} 410}
409 411
410// cmd:zen ///////////////////////////////////////////////////////////////////////////////////////// 412// cmd:zen /////////////////////////////////////////////////////////////////////////////////////////
@@ -426,7 +428,7 @@ const info_zen =
426 \\ 428 \\
427; 429;
428 430
429fn cmdZen(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) { 431fn cmdZen(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
430} 432}
431 433
432// cmd:internal //////////////////////////////////////////////////////////////////////////////////// 434// cmd:internal ////////////////////////////////////////////////////////////////////////////////////
@@ -440,5 +442,5 @@ const usage_internal =
440 \\ 442 \\
441; 443;
442 444
443fn cmdInternal(allocator: &mem.Allocator, args: &clap.ArgIterator) (error{}!void) { 445fn cmdInternal(allocator: &mem.Allocator, args: &clap.ArgIterator(ArgError)) (error{}!void) {
444} 446}
diff --git a/src/core.zig b/src/core.zig
index 8570220..5e47714 100644
--- a/src/core.zig
+++ b/src/core.zig
@@ -136,34 +136,39 @@ pub fn Arg(comptime Id: type) type {
136} 136}
137 137
138/// A interface for iterating over command line arguments 138/// A interface for iterating over command line arguments
139pub const ArgIterator = struct { 139pub fn ArgIterator(comptime E: type) type {
140 const Error = error{OutOfMemory}; 140 return struct {
141 const Self = this;
142 const Error = E;
141 143
142 nextFn: fn(iter: &ArgIterator, allocator: &mem.Allocator) Error!?[]const u8, 144 nextFn: fn(iter: &Self) Error!?[]const u8,
143 145
144 pub fn next(iter: &ArgIterator, allocator: &mem.Allocator) Error!?[]const u8 { 146 pub fn next(iter: &Self) Error!?[]const u8 {
145 return iter.nextFn(iter, allocator); 147 return iter.nextFn(iter);
146 } 148 }
147}; 149 };
150}
148 151
149/// An ::ArgIterator, which iterates over a slice of arguments. 152/// An ::ArgIterator, which iterates over a slice of arguments.
150/// This implementation does not allocate. 153/// This implementation does not allocate.
151pub const ArgSliceIterator = struct { 154pub const ArgSliceIterator = struct {
155 const Error = error{};
156
152 args: []const []const u8, 157 args: []const []const u8,
153 index: usize, 158 index: usize,
154 iter: ArgIterator, 159 iter: ArgIterator(Error),
155 160
156 pub fn init(args: []const []const u8) ArgSliceIterator { 161 pub fn init(args: []const []const u8) ArgSliceIterator {
157 return ArgSliceIterator { 162 return ArgSliceIterator {
158 .args = args, 163 .args = args,
159 .index = 0, 164 .index = 0,
160 .iter = ArgIterator { 165 .iter = ArgIterator(Error) {
161 .nextFn = nextFn, 166 .nextFn = nextFn,
162 }, 167 },
163 }; 168 };
164 } 169 }
165 170
166 fn nextFn(iter: &ArgIterator, allocator: &mem.Allocator) ArgIterator.Error!?[]const u8 { 171 fn nextFn(iter: &ArgIterator(Error)) Error!?[]const u8 {
167 const self = @fieldParentPtr(ArgSliceIterator, "iter", iter); 172 const self = @fieldParentPtr(ArgSliceIterator, "iter", iter);
168 if (self.args.len <= self.index) 173 if (self.args.len <= self.index)
169 return null; 174 return null;
@@ -176,22 +181,30 @@ pub const ArgSliceIterator = struct {
176/// An ::ArgIterator, which wraps the ArgIterator in ::std. 181/// An ::ArgIterator, which wraps the ArgIterator in ::std.
177/// On windows, this iterator allocates. 182/// On windows, this iterator allocates.
178pub const OsArgIterator = struct { 183pub const OsArgIterator = struct {
184 const Error = os.ArgIterator.NextError;
185
186 arena: heap.ArenaAllocator,
179 args: os.ArgIterator, 187 args: os.ArgIterator,
180 iter: ArgIterator, 188 iter: ArgIterator(Error),
181 189
182 pub fn init() OsArgIterator { 190 pub fn init(allocator: &mem.Allocator) OsArgIterator {
183 return OsArgIterator { 191 return OsArgIterator {
192 .arena = heap.ArenaAllocator.init(allocator),
184 .args = os.args(), 193 .args = os.args(),
185 .iter = ArgIterator { 194 .iter = ArgIterator(Error) {
186 .nextFn = nextFn, 195 .nextFn = nextFn,
187 }, 196 },
188 }; 197 };
189 } 198 }
190 199
191 fn nextFn(iter: &ArgIterator, allocator: &mem.Allocator) ArgIterator.Error!?[]const u8 { 200 pub fn deinit(iter: &OsArgIterator) void {
201 iter.arena.deinit();
202 }
203
204 fn nextFn(iter: &ArgIterator(Error)) Error!?[]const u8 {
192 const self = @fieldParentPtr(OsArgIterator, "iter", iter); 205 const self = @fieldParentPtr(OsArgIterator, "iter", iter);
193 if (builtin.os == builtin.Os.windows) { 206 if (builtin.os == builtin.Os.windows) {
194 return try self.args.next(allocator) ?? return null; 207 return try self.args.next(self.allocator) ?? return null;
195 } else { 208 } else {
196 return self.args.nextPosix(); 209 return self.args.nextPosix();
197 } 210 }
@@ -201,7 +214,7 @@ pub const OsArgIterator = struct {
201/// A command line argument parser which, given an ::ArgIterator, will parse arguments according 214/// A command line argument parser which, given an ::ArgIterator, will parse arguments according
202/// to the ::params. ::Clap parses in an iterating manner, so you have to use a loop together with 215/// to the ::params. ::Clap parses in an iterating manner, so you have to use a loop together with
203/// ::Clap.next to parse all the arguments of your program. 216/// ::Clap.next to parse all the arguments of your program.
204pub fn Clap(comptime Id: type) type { 217pub fn Clap(comptime Id: type, comptime ArgError: type) type {
205 return struct { 218 return struct {
206 const Self = this; 219 const Self = this;
207 220
@@ -215,14 +228,12 @@ pub fn Clap(comptime Id: type) type {
215 }; 228 };
216 }; 229 };
217 230
218 arena: heap.ArenaAllocator,
219 params: []const Param(Id), 231 params: []const Param(Id),
220 iter: &ArgIterator, 232 iter: &ArgIterator(ArgError),
221 state: State, 233 state: State,
222 234
223 pub fn init(params: []const Param(Id), iter: &ArgIterator, allocator: &mem.Allocator) Self { 235 pub fn init(params: []const Param(Id), iter: &ArgIterator(ArgError)) Self {
224 var res = Self { 236 var res = Self {
225 .arena = heap.ArenaAllocator.init(allocator),
226 .params = params, 237 .params = params,
227 .iter = iter, 238 .iter = iter,
228 .state = State.Normal, 239 .state = State.Normal,
@@ -231,10 +242,6 @@ pub fn Clap(comptime Id: type) type {
231 return res; 242 return res;
232 } 243 }
233 244
234 pub fn deinit(clap: &Self) void {
235 clap.arena.deinit();
236 }
237
238 /// Get the next ::Arg that matches a ::Param. 245 /// Get the next ::Arg that matches a ::Param.
239 pub fn next(clap: &Self) !?Arg(Id) { 246 pub fn next(clap: &Self) !?Arg(Id) {
240 const ArgInfo = struct { 247 const ArgInfo = struct {
@@ -246,7 +253,7 @@ pub fn Clap(comptime Id: type) type {
246 253
247 switch (clap.state) { 254 switch (clap.state) {
248 State.Normal => { 255 State.Normal => {
249 const full_arg = (try clap.nextNoParse()) ?? return null; 256 const full_arg = (try clap.iter.next()) ?? return null;
250 const arg_info = blk: { 257 const arg_info = blk: {
251 var arg = full_arg; 258 var arg = full_arg;
252 var kind = ArgInfo.Kind.Bare; 259 var kind = ArgInfo.Kind.Bare;
@@ -294,7 +301,7 @@ pub fn Clap(comptime Id: type) type {
294 if (maybe_value) |v| 301 if (maybe_value) |v|
295 break :blk v; 302 break :blk v;
296 303
297 break :blk (try clap.nextNoParse()) ?? return error.MissingValue; 304 break :blk (try clap.iter.next()) ?? return error.MissingValue;
298 }; 305 };
299 306
300 return Arg(Id).init(param, value); 307 return Arg(Id).init(param, value);
@@ -351,7 +358,7 @@ pub fn Clap(comptime Id: type) type {
351 return Arg(Id).init(param, null); 358 return Arg(Id).init(param, null);
352 359
353 if (arg.len <= next_index) { 360 if (arg.len <= next_index) {
354 const value = (try clap.nextNoParse()) ?? return error.MissingValue; 361 const value = (try clap.iter.next()) ?? return error.MissingValue;
355 return Arg(Id).init(param, value); 362 return Arg(Id).init(param, value);
356 } 363 }
357 364
@@ -364,11 +371,5 @@ pub fn Clap(comptime Id: type) type {
364 371
365 return error.InvalidArgument; 372 return error.InvalidArgument;
366 } 373 }
367
368 // Returns the next arg in the underlying arg iterator
369 pub fn nextNoParse(clap: &Self) !?[]const u8 {
370 clap.state = State.Normal;
371 return try clap.iter.next(&clap.arena.allocator);
372 }
373 }; 374 };
374} 375}
diff --git a/src/extended.zig b/src/extended.zig
index b94f6f5..31e6455 100644
--- a/src/extended.zig
+++ b/src/extended.zig
@@ -103,13 +103,13 @@ pub const Command = struct {
103 return res; 103 return res;
104 } 104 }
105 105
106 pub fn parse(comptime command: &const Command, allocator: &mem.Allocator, arg_iter: &core.ArgIterator) !command.Result { 106 pub fn parse(comptime command: &const Command, allocator: &mem.Allocator, arg_iter: var) !command.Result {
107 const Parent = struct {}; 107 const Parent = struct {};
108 var parent = Parent{}; 108 var parent = Parent{};
109 return command.parseHelper(&parent, allocator, arg_iter); 109 return command.parseHelper(&parent, allocator, arg_iter);
110 } 110 }
111 111
112 fn parseHelper(comptime command: &const Command, parent: var, allocator: &mem.Allocator, arg_iter: &core.ArgIterator) !command.Result { 112 fn parseHelper(comptime command: &const Command, parent: var, allocator: &mem.Allocator, arg_iter: var) !command.Result {
113 const Result = struct { 113 const Result = struct {
114 parent: @typeOf(parent), 114 parent: @typeOf(parent),
115 result: command.Result, 115 result: command.Result,
@@ -159,11 +159,10 @@ pub const Command = struct {
159 }; 159 };
160 160
161 var pos: usize = 0; 161 var pos: usize = 0;
162 var iter = core.Clap(usize).init(core_params, arg_iter, allocator); 162 var clap = core.Clap(usize, @typeOf(arg_iter.*).Error).init(core_params, arg_iter);
163 defer iter.deinit();
164 163
165 arg_loop: 164 arg_loop:
166 while (try iter.next()) |arg| : (pos += 1) { 165 while (try clap.next()) |arg| : (pos += 1) {
167 inline for(command.params) |param, i| { 166 inline for(command.params) |param, i| {
168 comptime const field = "result." ++ param.field; 167 comptime const field = "result." ++ param.field;
169 168
diff --git a/tests/core.zig b/tests/core.zig
index d4304a1..91b62fe 100644
--- a/tests/core.zig
+++ b/tests/core.zig
@@ -14,7 +14,7 @@ const Clap = core.Clap;
14 14
15fn testNoErr(params: []const Param(u8), args: []const []const u8, ids: []const u8, values: []const ?[]const u8) void { 15fn testNoErr(params: []const Param(u8), args: []const []const u8, ids: []const u8, values: []const ?[]const u8) void {
16 var arg_iter = ArgSliceIterator.init(args); 16 var arg_iter = ArgSliceIterator.init(args);
17 var iter = Clap(u8).init(params, &arg_iter.iter, debug.global_allocator); 17 var iter = Clap(u8, ArgSliceIterator.Error).init(params, &arg_iter.iter);
18 18
19 var i: usize = 0; 19 var i: usize = 0;
20 while (iter.next() catch unreachable) |arg| : (i += 1) { 20 while (iter.next() catch unreachable) |arg| : (i += 1) {