summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core.zig67
-rw-r--r--src/extended.zig9
2 files changed, 38 insertions, 38 deletions
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