summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--README.md26
-rw-r--r--clap.zig36
-rw-r--r--clap/comptime.zig19
-rw-r--r--clap/streaming.zig40
-rw-r--r--example/simple-ex.zig14
-rw-r--r--example/simple.zig11
-rw-r--r--example/streaming-clap.zig15
7 files changed, 87 insertions, 74 deletions
diff --git a/README.md b/README.md
index 3156539..ad9f026 100644
--- a/README.md
+++ b/README.md
@@ -25,8 +25,8 @@ into master on every `zig` release.
25The simplest way to use this library is to just call the `clap.parse` function. 25The simplest way to use this library is to just call the `clap.parse` function.
26 26
27```zig 27```zig
28const std = @import("std");
29const clap = @import("clap"); 28const clap = @import("clap");
29const std = @import("std");
30 30
31const debug = std.debug; 31const debug = std.debug;
32 32
@@ -41,11 +41,10 @@ pub fn main() !void {
41 }; 41 };
42 42
43 // Initalize our diagnostics, which can be used for reporting useful errors. 43 // Initalize our diagnostics, which can be used for reporting useful errors.
44 // This is optional. You can also just pass `null` to `parser.next` if you 44 // This is optional. You can also pass `.{}` to `clap.parse` if you don't
45 // don't care about the extra information `Diagnostics` provides. 45 // care about the extra information `Diagnostics` provides.
46 var diag: clap.Diagnostic = undefined; 46 var diag = clap.Diagnostic{};
47 47 var args = clap.parse(clap.Help, &params, .{ .diagnostic = &diag }) catch |err| {
48 var args = clap.parse(clap.Help, &params, std.heap.page_allocator, &diag) catch |err| {
49 // Report useful error and exit 48 // Report useful error and exit
50 diag.report(std.io.getStdErr().outStream(), err) catch {}; 49 diag.report(std.io.getStdErr().outStream(), err) catch {};
51 return err; 50 return err;
@@ -107,8 +106,8 @@ The `StreamingClap` is the base of all the other parsers. It's a streaming parse
107`args.Iterator` to provide it with arguments lazily. 106`args.Iterator` to provide it with arguments lazily.
108 107
109```zig 108```zig
110const std = @import("std");
111const clap = @import("clap"); 109const clap = @import("clap");
110const std = @import("std");
112 111
113const debug = std.debug; 112const debug = std.debug;
114 113
@@ -137,19 +136,18 @@ pub fn main() !void {
137 var iter = try clap.args.OsIterator.init(allocator); 136 var iter = try clap.args.OsIterator.init(allocator);
138 defer iter.deinit(); 137 defer iter.deinit();
139 138
140 // Initialize our streaming parser. 139 // Initalize our diagnostics, which can be used for reporting useful errors.
140 // This is optional. You can also leave the `diagnostic` field unset if you
141 // don't care about the extra information `Diagnostic` provides.
142 var diag = clap.Diagnostic{};
141 var parser = clap.StreamingClap(u8, clap.args.OsIterator){ 143 var parser = clap.StreamingClap(u8, clap.args.OsIterator){
142 .params = &params, 144 .params = &params,
143 .iter = &iter, 145 .iter = &iter,
146 .diagnostic = &diag,
144 }; 147 };
145 148
146 // Initalize our diagnostics, which can be used for reporting useful errors.
147 // This is optional. You can also just pass `null` to `parser.next` if you
148 // don't care about the extra information `Diagnostics` provides.
149 var diag: clap.Diagnostic = undefined;
150
151 // Because we use a streaming parser, we have to consume each argument parsed individually. 149 // Because we use a streaming parser, we have to consume each argument parsed individually.
152 while (parser.next(&diag) catch |err| { 150 while (parser.next() catch |err| {
153 // Report useful error and exit 151 // Report useful error and exit
154 diag.report(std.io.getStdErr().outStream(), err) catch {}; 152 diag.report(std.io.getStdErr().outStream(), err) catch {};
155 return err; 153 return err;
diff --git a/clap.zig b/clap.zig
index 4548a48..b31cd1d 100644
--- a/clap.zig
+++ b/clap.zig
@@ -1,6 +1,7 @@
1const std = @import("std"); 1const std = @import("std");
2 2
3const debug = std.debug; 3const debug = std.debug;
4const heap = std.heap;
4const io = std.io; 5const io = std.io;
5const mem = std.mem; 6const mem = std.mem;
6const testing = std.testing; 7const testing = std.testing;
@@ -307,7 +308,6 @@ pub fn Args(comptime Id: type, comptime params: []const Param(Id)) type {
307 exe_arg: ?[]const u8, 308 exe_arg: ?[]const u8,
308 309
309 pub fn deinit(a: *@This()) void { 310 pub fn deinit(a: *@This()) void {
310 a.clap.deinit();
311 a.arena.deinit(); 311 a.arena.deinit();
312 } 312 }
313 313
@@ -329,20 +329,37 @@ pub fn Args(comptime Id: type, comptime params: []const Param(Id)) type {
329 }; 329 };
330} 330}
331 331
332/// Options that can be set to customize the behavior of parsing.
333pub const ParseOptions = struct {
334 /// The allocator used for all memory allocations. Defaults to the `heap.page_allocator`.
335 /// Note: You should probably override this allocator if you are calling `parseEx`. Unlike
336 /// `parse`, `parseEx` does not wrap the allocator so the heap allocator can be
337 /// quite expensive. (TODO: Can we pick a better default? For `parse`, this allocator
338 /// is fine, as it wraps it in an arena)
339 allocator: *mem.Allocator = heap.page_allocator,
340 diagnostic: ?*Diagnostic = null,
341};
342
332/// Same as `parseEx` but uses the `args.OsIterator` by default. 343/// Same as `parseEx` but uses the `args.OsIterator` by default.
333pub fn parse( 344pub fn parse(
334 comptime Id: type, 345 comptime Id: type,
335 comptime params: []const Param(Id), 346 comptime params: []const Param(Id),
336 allocator: *mem.Allocator, 347 opt: ParseOptions,
337 diag: ?*Diagnostic,
338) !Args(Id, params) { 348) !Args(Id, params) {
339 var iter = try args.OsIterator.init(allocator); 349 var iter = try args.OsIterator.init(opt.allocator);
340 const clap = try parseEx(Id, params, allocator, &iter, diag); 350 var res = Args(Id, params){
341 return Args(Id, params){
342 .arena = iter.arena, 351 .arena = iter.arena,
343 .clap = clap,
344 .exe_arg = iter.exe_arg, 352 .exe_arg = iter.exe_arg,
353 .clap = undefined,
345 }; 354 };
355
356 // Let's reuse the arena from the `OSIterator` since we already have
357 // it.
358 res.clap = try parseEx(Id, params, &iter, .{
359 .allocator = &res.arena.allocator,
360 .diagnostic = opt.diagnostic,
361 });
362 return res;
346} 363}
347 364
348/// Parses the command line arguments passed into the program based on an 365/// Parses the command line arguments passed into the program based on an
@@ -350,12 +367,11 @@ pub fn parse(
350pub fn parseEx( 367pub fn parseEx(
351 comptime Id: type, 368 comptime Id: type,
352 comptime params: []const Param(Id), 369 comptime params: []const Param(Id),
353 allocator: *mem.Allocator,
354 iter: anytype, 370 iter: anytype,
355 diag: ?*Diagnostic, 371 opt: ParseOptions,
356) !ComptimeClap(Id, params) { 372) !ComptimeClap(Id, params) {
357 const Clap = ComptimeClap(Id, params); 373 const Clap = ComptimeClap(Id, params);
358 return try Clap.parse(allocator, iter, diag); 374 return try Clap.parse(iter, opt);
359} 375}
360 376
361/// Will print a help message in the following format: 377/// Will print a help message in the following format:
diff --git a/clap/comptime.zig b/clap/comptime.zig
index 8ab61cb..9bec38e 100644
--- a/clap/comptime.zig
+++ b/clap/comptime.zig
@@ -1,10 +1,10 @@
1const clap = @import("../clap.zig"); 1const clap = @import("../clap.zig");
2const std = @import("std"); 2const std = @import("std");
3 3
4const testing = std.testing; 4const debug = std.debug;
5const heap = std.heap; 5const heap = std.heap;
6const mem = std.mem; 6const mem = std.mem;
7const debug = std.debug; 7const testing = std.testing;
8 8
9/// Deprecated: Use `parseEx` instead 9/// Deprecated: Use `parseEx` instead
10pub fn ComptimeClap( 10pub fn ComptimeClap(
@@ -42,7 +42,8 @@ pub fn ComptimeClap(
42 pos: []const []const u8, 42 pos: []const []const u8,
43 allocator: *mem.Allocator, 43 allocator: *mem.Allocator,
44 44
45 pub fn parse(allocator: *mem.Allocator, iter: anytype, diag: ?*clap.Diagnostic) !@This() { 45 pub fn parse(iter: anytype, opt: clap.ParseOptions) !@This() {
46 const allocator = opt.allocator;
46 var multis = [_]std.ArrayList([]const u8){undefined} ** multi_options; 47 var multis = [_]std.ArrayList([]const u8){undefined} ** multi_options;
47 for (multis) |*multi| { 48 for (multis) |*multi| {
48 multi.* = std.ArrayList([]const u8).init(allocator); 49 multi.* = std.ArrayList([]const u8).init(allocator);
@@ -62,7 +63,7 @@ pub fn ComptimeClap(
62 .params = converted_params, 63 .params = converted_params,
63 .iter = iter, 64 .iter = iter,
64 }; 65 };
65 while (try stream.next(diag)) |arg| { 66 while (try stream.next()) |arg| {
66 const param = arg.param; 67 const param = arg.param;
67 if (param.names.long == null and param.names.short == null) { 68 if (param.names.long == null and param.names.short == null) {
68 try pos.append(arg.value.?); 69 try pos.append(arg.value.?);
@@ -81,19 +82,17 @@ pub fn ComptimeClap(
81 } 82 }
82 } 83 }
83 84
84 for (multis) |*multi, i| { 85 for (multis) |*multi, i|
85 res.multi_options[i] = multi.toOwnedSlice(); 86 res.multi_options[i] = multi.toOwnedSlice();
86 }
87 res.pos = pos.toOwnedSlice(); 87 res.pos = pos.toOwnedSlice();
88 88
89 return res; 89 return res;
90 } 90 }
91 91
92 pub fn deinit(parser: *@This()) void { 92 pub fn deinit(parser: @This()) void {
93 for (parser.multi_options) |o| 93 for (parser.multi_options) |o|
94 parser.allocator.free(o); 94 parser.allocator.free(o);
95 parser.allocator.free(parser.pos); 95 parser.allocator.free(parser.pos);
96 parser.* = undefined;
97 } 96 }
98 97
99 pub fn flag(parser: @This(), comptime name: []const u8) bool { 98 pub fn flag(parser: @This(), comptime name: []const u8) bool {
@@ -155,14 +154,12 @@ test "" {
155 clap.parseParam("<P>") catch unreachable, 154 clap.parseParam("<P>") catch unreachable,
156 }); 155 });
157 156
158 var buf: [1024]u8 = undefined;
159 var fb_allocator = heap.FixedBufferAllocator.init(buf[0..]);
160 var iter = clap.args.SliceIterator{ 157 var iter = clap.args.SliceIterator{
161 .args = &[_][]const u8{ 158 .args = &[_][]const u8{
162 "-a", "-c", "0", "something", "-d", "a", "--dd", "b", 159 "-a", "-c", "0", "something", "-d", "a", "--dd", "b",
163 }, 160 },
164 }; 161 };
165 var args = try Clap.parse(&fb_allocator.allocator, &iter, null); 162 var args = try Clap.parse(&iter, .{ .allocator = testing.allocator });
166 defer args.deinit(); 163 defer args.deinit();
167 164
168 testing.expect(args.flag("-a")); 165 testing.expect(args.flag("-a"));
diff --git a/clap/streaming.zig b/clap/streaming.zig
index 11145f0..8030a67 100644
--- a/clap/streaming.zig
+++ b/clap/streaming.zig
@@ -40,12 +40,13 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
40 iter: *ArgIterator, 40 iter: *ArgIterator,
41 state: State = .normal, 41 state: State = .normal,
42 positional: ?*const clap.Param(Id) = null, 42 positional: ?*const clap.Param(Id) = null,
43 diagnostic: ?*clap.Diagnostic = null,
43 44
44 /// Get the next Arg that matches a Param. 45 /// Get the next Arg that matches a Param.
45 pub fn next(parser: *@This(), diag: ?*clap.Diagnostic) !?Arg(Id) { 46 pub fn next(parser: *@This()) !?Arg(Id) {
46 switch (parser.state) { 47 switch (parser.state) {
47 .normal => return try parser.normal(diag), 48 .normal => return try parser.normal(),
48 .chaining => |state| return try parser.chainging(state, diag), 49 .chaining => |state| return try parser.chainging(state),
49 .rest_are_positional => { 50 .rest_are_positional => {
50 const param = parser.positionalParam() orelse unreachable; 51 const param = parser.positionalParam() orelse unreachable;
51 const value = (try parser.iter.next()) orelse return null; 52 const value = (try parser.iter.next()) orelse return null;
@@ -54,7 +55,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
54 } 55 }
55 } 56 }
56 57
57 fn normal(parser: *@This(), diag: ?*clap.Diagnostic) !?Arg(Id) { 58 fn normal(parser: *@This()) !?Arg(Id) {
58 const arg_info = (try parser.parseNextArg()) orelse return null; 59 const arg_info = (try parser.parseNextArg()) orelse return null;
59 const arg = arg_info.arg; 60 const arg = arg_info.arg;
60 switch (arg_info.kind) { 61 switch (arg_info.kind) {
@@ -70,7 +71,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
70 continue; 71 continue;
71 if (param.takes_value == .None) { 72 if (param.takes_value == .None) {
72 if (maybe_value != null) 73 if (maybe_value != null)
73 return err(diag, arg, .{ .long = name }, error.DoesntTakeValue); 74 return parser.err(arg, .{ .long = name }, error.DoesntTakeValue);
74 75
75 return Arg(Id){ .param = param }; 76 return Arg(Id){ .param = param };
76 } 77 }
@@ -80,18 +81,18 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
80 break :blk v; 81 break :blk v;
81 82
82 break :blk (try parser.iter.next()) orelse 83 break :blk (try parser.iter.next()) orelse
83 return err(diag, arg, .{ .long = name }, error.MissingValue); 84 return parser.err(arg, .{ .long = name }, error.MissingValue);
84 }; 85 };
85 86
86 return Arg(Id){ .param = param, .value = value }; 87 return Arg(Id){ .param = param, .value = value };
87 } 88 }
88 89
89 return err(diag, arg, .{ .long = name }, error.InvalidArgument); 90 return parser.err(arg, .{ .long = name }, error.InvalidArgument);
90 }, 91 },
91 .short => return try parser.chainging(.{ 92 .short => return try parser.chainging(.{
92 .arg = arg, 93 .arg = arg,
93 .index = 0, 94 .index = 0,
94 }, diag), 95 }),
95 .positional => if (parser.positionalParam()) |param| { 96 .positional => if (parser.positionalParam()) |param| {
96 // If we find a positional with the value `--` then we 97 // If we find a positional with the value `--` then we
97 // interpret the rest of the arguments as positional 98 // interpret the rest of the arguments as positional
@@ -104,12 +105,12 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
104 105
105 return Arg(Id){ .param = param, .value = arg }; 106 return Arg(Id){ .param = param, .value = arg };
106 } else { 107 } else {
107 return err(diag, arg, .{}, error.InvalidArgument); 108 return parser.err(arg, .{}, error.InvalidArgument);
108 }, 109 },
109 } 110 }
110 } 111 }
111 112
112 fn chainging(parser: *@This(), state: State.Chaining, diag: ?*clap.Diagnostic) !?Arg(Id) { 113 fn chainging(parser: *@This(), state: State.Chaining) !?Arg(Id) {
113 const arg = state.arg; 114 const arg = state.arg;
114 const index = state.index; 115 const index = state.index;
115 const next_index = index + 1; 116 const next_index = index + 1;
@@ -136,13 +137,13 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
136 const next_is_eql = if (next_index < arg.len) arg[next_index] == '=' else false; 137 const next_is_eql = if (next_index < arg.len) arg[next_index] == '=' else false;
137 if (param.takes_value == .None) { 138 if (param.takes_value == .None) {
138 if (next_is_eql) 139 if (next_is_eql)
139 return err(diag, arg, .{ .short = short }, error.DoesntTakeValue); 140 return parser.err(arg, .{ .short = short }, error.DoesntTakeValue);
140 return Arg(Id){ .param = param }; 141 return Arg(Id){ .param = param };
141 } 142 }
142 143
143 if (arg.len <= next_index) { 144 if (arg.len <= next_index) {
144 const value = (try parser.iter.next()) orelse 145 const value = (try parser.iter.next()) orelse
145 return err(diag, arg, .{ .short = short }, error.MissingValue); 146 return parser.err(arg, .{ .short = short }, error.MissingValue);
146 147
147 return Arg(Id){ .param = param, .value = value }; 148 return Arg(Id){ .param = param, .value = value };
148 } 149 }
@@ -153,7 +154,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
153 return Arg(Id){ .param = param, .value = arg[next_index..] }; 154 return Arg(Id){ .param = param, .value = arg[next_index..] };
154 } 155 }
155 156
156 return err(diag, arg, .{ .short = arg[index] }, error.InvalidArgument); 157 return parser.err(arg, .{ .short = arg[index] }, error.InvalidArgument);
157 } 158 }
158 159
159 fn positionalParam(parser: *@This()) ?*const clap.Param(Id) { 160 fn positionalParam(parser: *@This()) ?*const clap.Param(Id) {
@@ -194,8 +195,8 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
194 return ArgInfo{ .arg = full_arg, .kind = .positional }; 195 return ArgInfo{ .arg = full_arg, .kind = .positional };
195 } 196 }
196 197
197 fn err(diag: ?*clap.Diagnostic, arg: []const u8, names: clap.Names, _err: anytype) @TypeOf(_err) { 198 fn err(parser: @This(), arg: []const u8, names: clap.Names, _err: anytype) @TypeOf(_err) {
198 if (diag) |d| 199 if (parser.diagnostic) |d|
199 d.* = .{ .arg = arg, .name = names }; 200 d.* = .{ .arg = arg, .name = names };
200 return _err; 201 return _err;
201 } 202 }
@@ -210,7 +211,7 @@ fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, r
210 }; 211 };
211 212
212 for (results) |res| { 213 for (results) |res| {
213 const arg = (c.next(null) catch unreachable) orelse unreachable; 214 const arg = (c.next() catch unreachable) orelse unreachable;
214 testing.expectEqual(res.param, arg.param); 215 testing.expectEqual(res.param, arg.param);
215 const expected_value = res.value orelse { 216 const expected_value = res.value orelse {
216 testing.expectEqual(@as(@TypeOf(arg.value), null), arg.value); 217 testing.expectEqual(@as(@TypeOf(arg.value), null), arg.value);
@@ -220,18 +221,19 @@ fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, r
220 testing.expectEqualSlices(u8, expected_value, actual_value); 221 testing.expectEqualSlices(u8, expected_value, actual_value);
221 } 222 }
222 223
223 if (c.next(null) catch unreachable) |_| 224 if (c.next() catch unreachable) |_|
224 unreachable; 225 unreachable;
225} 226}
226 227
227fn testErr(params: []const clap.Param(u8), args_strings: []const []const u8, expected: []const u8) void { 228fn testErr(params: []const clap.Param(u8), args_strings: []const []const u8, expected: []const u8) void {
228 var diag: clap.Diagnostic = undefined; 229 var diag = clap.Diagnostic{};
229 var iter = args.SliceIterator{ .args = args_strings }; 230 var iter = args.SliceIterator{ .args = args_strings };
230 var c = StreamingClap(u8, args.SliceIterator){ 231 var c = StreamingClap(u8, args.SliceIterator){
231 .params = params, 232 .params = params,
232 .iter = &iter, 233 .iter = &iter,
234 .diagnostic = &diag,
233 }; 235 };
234 while (c.next(&diag) catch |err| { 236 while (c.next() catch |err| {
235 var buf: [1024]u8 = undefined; 237 var buf: [1024]u8 = undefined;
236 var slice_stream = io.fixedBufferStream(&buf); 238 var slice_stream = io.fixedBufferStream(&buf);
237 diag.report(slice_stream.outStream(), err) catch unreachable; 239 diag.report(slice_stream.outStream(), err) catch unreachable;
diff --git a/example/simple-ex.zig b/example/simple-ex.zig
index d6ecc44..f504d63 100644
--- a/example/simple-ex.zig
+++ b/example/simple-ex.zig
@@ -1,5 +1,5 @@
1const std = @import("std");
2const clap = @import("clap"); 1const clap = @import("clap");
2const std = @import("std");
3 3
4const debug = std.debug; 4const debug = std.debug;
5 5
@@ -21,11 +21,13 @@ pub fn main() !void {
21 defer iter.deinit(); 21 defer iter.deinit();
22 22
23 // Initalize our diagnostics, which can be used for reporting useful errors. 23 // Initalize our diagnostics, which can be used for reporting useful errors.
24 // This is optional. You can also just pass `null` to `parser.next` if you 24 // This is optional. You can also pass `.{}` to `clap.parse` if you don't
25 // don't care about the extra information `Diagnostics` provides. 25 // care about the extra information `Diagnostics` provides.
26 var diag: clap.Diagnostic = undefined; 26 var diag = clap.Diagnostic{};
27 27 var args = clap.parseEx(clap.Help, &params, &iter, .{
28 var args = clap.parseEx(clap.Help, &params, allocator, &iter, &diag) catch |err| { 28 .allocator = allocator,
29 .diagnostic = &diag,
30 }) catch |err| {
29 // Report useful error and exit 31 // Report useful error and exit
30 diag.report(std.io.getStdErr().outStream(), err) catch {}; 32 diag.report(std.io.getStdErr().outStream(), err) catch {};
31 return err; 33 return err;
diff --git a/example/simple.zig b/example/simple.zig
index 270e344..392dca3 100644
--- a/example/simple.zig
+++ b/example/simple.zig
@@ -1,5 +1,5 @@
1const std = @import("std");
2const clap = @import("clap"); 1const clap = @import("clap");
2const std = @import("std");
3 3
4const debug = std.debug; 4const debug = std.debug;
5 5
@@ -14,11 +14,10 @@ pub fn main() !void {
14 }; 14 };
15 15
16 // Initalize our diagnostics, which can be used for reporting useful errors. 16 // Initalize our diagnostics, which can be used for reporting useful errors.
17 // This is optional. You can also just pass `null` to `parser.next` if you 17 // This is optional. You can also pass `.{}` to `clap.parse` if you don't
18 // don't care about the extra information `Diagnostics` provides. 18 // care about the extra information `Diagnostics` provides.
19 var diag: clap.Diagnostic = undefined; 19 var diag = clap.Diagnostic{};
20 20 var args = clap.parse(clap.Help, &params, .{ .diagnostic = &diag }) catch |err| {
21 var args = clap.parse(clap.Help, &params, std.heap.page_allocator, &diag) catch |err| {
22 // Report useful error and exit 21 // Report useful error and exit
23 diag.report(std.io.getStdErr().outStream(), err) catch {}; 22 diag.report(std.io.getStdErr().outStream(), err) catch {};
24 return err; 23 return err;
diff --git a/example/streaming-clap.zig b/example/streaming-clap.zig
index 941070f..f8d873d 100644
--- a/example/streaming-clap.zig
+++ b/example/streaming-clap.zig
@@ -1,5 +1,5 @@
1const std = @import("std");
2const clap = @import("clap"); 1const clap = @import("clap");
2const std = @import("std");
3 3
4const debug = std.debug; 4const debug = std.debug;
5 5
@@ -28,19 +28,18 @@ pub fn main() !void {
28 var iter = try clap.args.OsIterator.init(allocator); 28 var iter = try clap.args.OsIterator.init(allocator);
29 defer iter.deinit(); 29 defer iter.deinit();
30 30
31 // Initialize our streaming parser. 31 // Initalize our diagnostics, which can be used for reporting useful errors.
32 // This is optional. You can also leave the `diagnostic` field unset if you
33 // don't care about the extra information `Diagnostic` provides.
34 var diag = clap.Diagnostic{};
32 var parser = clap.StreamingClap(u8, clap.args.OsIterator){ 35 var parser = clap.StreamingClap(u8, clap.args.OsIterator){
33 .params = &params, 36 .params = &params,
34 .iter = &iter, 37 .iter = &iter,
38 .diagnostic = &diag,
35 }; 39 };
36 40
37 // Initalize our diagnostics, which can be used for reporting useful errors.
38 // This is optional. You can also just pass `null` to `parser.next` if you
39 // don't care about the extra information `Diagnostics` provides.
40 var diag: clap.Diagnostic = undefined;
41
42 // Because we use a streaming parser, we have to consume each argument parsed individually. 41 // Because we use a streaming parser, we have to consume each argument parsed individually.
43 while (parser.next(&diag) catch |err| { 42 while (parser.next() catch |err| {
44 // Report useful error and exit 43 // Report useful error and exit
45 diag.report(std.io.getStdErr().outStream(), err) catch {}; 44 diag.report(std.io.getStdErr().outStream(), err) catch {};
46 return err; 45 return err;