summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md38
-rw-r--r--clap.zig51
-rw-r--r--clap/comptime.zig14
-rw-r--r--clap/streaming.zig84
-rw-r--r--example/comptime-clap.zig12
-rw-r--r--example/simple-error.zig4
-rw-r--r--example/simple.zig11
-rw-r--r--example/streaming-clap.zig11
8 files changed, 167 insertions, 58 deletions
diff --git a/README.md b/README.md
index 2037b04..fbb3e35 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,16 @@ pub fn main() !void {
42 }, 42 },
43 }; 43 };
44 44
45 var args = try clap.parse(clap.Help, &params, std.heap.page_allocator); 45 // Initalize our diagnostics, which can be used for reporting useful errors.
46 // This is optional. You can also just pass `null` to `parser.next` if you
47 // don't care about the extra information `Diagnostics` provides.
48 var diag: clap.Diagnostic = undefined;
49
50 var args = clap.parse(clap.Help, &params, std.heap.page_allocator, &diag) catch |err| {
51 // Report useful error and exit
52 diag.report(std.io.getStdErr().outStream(), err) catch {};
53 return err;
54 };
46 defer args.deinit(); 55 defer args.deinit();
47 56
48 if (args.flag("--help")) 57 if (args.flag("--help"))
@@ -66,13 +75,11 @@ const std = @import("std");
66const clap = @import("clap"); 75const clap = @import("clap");
67 76
68pub fn main() !void { 77pub fn main() !void {
69 // First we specify what parameters our program can take.
70 // We can use `parseParam` to parse a string to a `Param(Help)`
71 const params = comptime [_]clap.Param(clap.Help){ 78 const params = comptime [_]clap.Param(clap.Help){
72 clap.parseParam("-h, --help Display this help and exit.") catch unreachable, 79 clap.parseParam("-h, --help Display this help and exit.") catch unreachable,
73 }; 80 };
74 81
75 var args = try clap.parse(clap.Help, &params, std.heap.direct_allocator); 82 var args = try clap.parse(clap.Help, &params, std.heap.direct_allocator, null);
76 defer args.deinit(); 83 defer args.deinit();
77 84
78 _ = args.flag("--helps"); 85 _ = args.flag("--helps");
@@ -118,14 +125,24 @@ pub fn main() !void {
118 .takes_value = .One, 125 .takes_value = .One,
119 }, 126 },
120 }; 127 };
128 const Clap = clap.ComptimeClap(clap.Help, clap.args.OsIterator, &params);
121 129
122 // We then initialize an argument iterator. We will use the OsIterator as it nicely 130 // We then initialize an argument iterator. We will use the OsIterator as it nicely
123 // wraps iterating over arguments the most efficient way on each os. 131 // wraps iterating over arguments the most efficient way on each os.
124 var iter = try clap.args.OsIterator.init(allocator); 132 var iter = try clap.args.OsIterator.init(allocator);
125 defer iter.deinit(); 133 defer iter.deinit();
126 134
135 // Initalize our diagnostics, which can be used for reporting useful errors.
136 // This is optional. You can also just pass `null` to `parser.next` if you
137 // don't care about the extra information `Diagnostics` provides.
138 var diag: clap.Diagnostic = undefined;
139
127 // Parse the arguments 140 // Parse the arguments
128 var args = try clap.ComptimeClap(clap.Help, &params).parse(allocator, clap.args.OsIterator, &iter); 141 var args = Clap.parse(allocator, &iter, &diag) catch |err| {
142 // Report useful error and exit
143 diag.report(std.io.getStdErr().outStream(), err) catch {};
144 return err;
145 };
129 defer args.deinit(); 146 defer args.deinit();
130 147
131 if (args.flag("--help")) 148 if (args.flag("--help"))
@@ -182,8 +199,17 @@ pub fn main() !void {
182 .iter = &iter, 199 .iter = &iter,
183 }; 200 };
184 201
202 // Initalize our diagnostics, which can be used for reporting useful errors.
203 // This is optional. You can also just pass `null` to `parser.next` if you
204 // don't care about the extra information `Diagnostics` provides.
205 var diag: clap.Diagnostic = undefined;
206
185 // Because we use a streaming parser, we have to consume each argument parsed individually. 207 // Because we use a streaming parser, we have to consume each argument parsed individually.
186 while (try parser.next()) |arg| { 208 while (parser.next(&diag) catch |err| {
209 // Report useful error and exit
210 diag.report(std.io.getStdErr().outStream(), err) catch {};
211 return err;
212 }) |arg| {
187 // arg.param will point to the parameter which matched the argument. 213 // arg.param will point to the parameter which matched the argument.
188 switch (arg.param.id) { 214 switch (arg.param.id) {
189 'h' => debug.warn("Help!\n", .{}), 215 'h' => debug.warn("Help!\n", .{}),
diff --git a/clap.zig b/clap.zig
index c312251..016aea6 100644
--- a/clap.zig
+++ b/clap.zig
@@ -261,7 +261,7 @@ fn find(str: []const u8, f: []const u8) []const u8 {
261pub fn Args(comptime Id: type, comptime params: []const Param(Id)) type { 261pub fn Args(comptime Id: type, comptime params: []const Param(Id)) type {
262 return struct { 262 return struct {
263 arena: std.heap.ArenaAllocator, 263 arena: std.heap.ArenaAllocator,
264 clap: ComptimeClap(Id, params), 264 clap: ComptimeClap(Id, args.OsIterator, params),
265 exe_arg: ?[]const u8, 265 exe_arg: ?[]const u8,
266 266
267 pub fn deinit(a: *@This()) void { 267 pub fn deinit(a: *@This()) void {
@@ -287,15 +287,62 @@ pub fn Args(comptime Id: type, comptime params: []const Param(Id)) type {
287 }; 287 };
288} 288}
289 289
290/// Optional diagnostics used for reporting useful errors
291pub const Diagnostic = struct {
292 name: Names,
293
294 /// Default diagnostics reporter when all you want is English with no colors.
295 /// Use this as a reference for implementing your own if needed.
296 pub fn report(diag: Diagnostic, stream: var, err: anyerror) !void {
297 const prefix = if (diag.name.short) |_| "-" else "--";
298 const name = if (diag.name.short) |*c| @as(*const [1]u8, c)[0..] else diag.name.long.?;
299
300 switch (err) {
301 error.DoesntTakeValue => try stream.print("The argument '{}{}' does not take a value\n", .{ prefix, name }),
302 error.MissingValue => try stream.print("The argument '{}{}' requires a value but none was supplied\n", .{ prefix, name }),
303 error.InvalidArgument => try stream.print("Invalid argument '{}{}'\n", .{ prefix, name }),
304 else => try stream.print("Error while parsing arguments: {}\n", .{@errorName(err)}),
305 }
306 }
307};
308
309fn testDiag(names: Names, err: anyerror, expected: []const u8) void {
310 var buf: [1024]u8 = undefined;
311 var slice_stream = io.fixedBufferStream(&buf);
312 (Diagnostic{ .name = names }).report(slice_stream.outStream(), err) catch unreachable;
313
314 const actual = slice_stream.getWritten();
315 if (!mem.eql(u8, actual, expected)) {
316 debug.warn("\n============ Expected ============\n", .{});
317 debug.warn("{}", .{expected});
318 debug.warn("============= Actual =============\n", .{});
319 debug.warn("{}", .{actual});
320 testing.expect(false);
321 }
322}
323
324test "Diagnostic.report" {
325 testDiag(.{ .short = 'c' }, error.DoesntTakeValue, "The argument '-c' does not take a value\n");
326 testDiag(.{ .long = "cc" }, error.DoesntTakeValue, "The argument '--cc' does not take a value\n");
327 testDiag(.{ .short = 'c' }, error.MissingValue, "The argument '-c' requires a value but none was supplied\n");
328 testDiag(.{ .long = "cc" }, error.MissingValue, "The argument '--cc' requires a value but none was supplied\n");
329 testDiag(.{ .short = 'c' }, error.InvalidArgument, "Invalid argument '-c'\n");
330 testDiag(.{ .long = "cc" }, error.InvalidArgument, "Invalid argument '--cc'\n");
331 testDiag(.{ .short = 'c' }, error.SomethingElse, "Error while parsing arguments: SomethingElse\n");
332 testDiag(.{ .long = "cc" }, error.SomethingElse, "Error while parsing arguments: SomethingElse\n");
333}
334
290/// Parses the command line arguments passed into the program based on an 335/// Parses the command line arguments passed into the program based on an
291/// array of `Param`s. 336/// array of `Param`s.
292pub fn parse( 337pub fn parse(
293 comptime Id: type, 338 comptime Id: type,
294 comptime params: []const Param(Id), 339 comptime params: []const Param(Id),
295 allocator: *mem.Allocator, 340 allocator: *mem.Allocator,
341 diag: ?*Diagnostic,
296) !Args(Id, params) { 342) !Args(Id, params) {
297 var iter = try args.OsIterator.init(allocator); 343 var iter = try args.OsIterator.init(allocator);
298 const clap = try ComptimeClap(Id, params).parse(allocator, args.OsIterator, &iter); 344 const Clap = ComptimeClap(Id, args.OsIterator, params);
345 const clap = try Clap.parse(allocator, &iter, diag);
299 return Args(Id, params){ 346 return Args(Id, params){
300 .arena = iter.arena, 347 .arena = iter.arena,
301 .clap = clap, 348 .clap = clap,
diff --git a/clap/comptime.zig b/clap/comptime.zig
index 28ec42b..6846770 100644
--- a/clap/comptime.zig
+++ b/clap/comptime.zig
@@ -6,7 +6,11 @@ const heap = std.heap;
6const mem = std.mem; 6const mem = std.mem;
7const debug = std.debug; 7const debug = std.debug;
8 8
9pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) type { 9pub fn ComptimeClap(
10 comptime Id: type,
11 comptime ArgIter: type,
12 comptime params: []const clap.Param(Id),
13) type {
10 var flags: usize = 0; 14 var flags: usize = 0;
11 var single_options: usize = 0; 15 var single_options: usize = 0;
12 var multi_options: usize = 0; 16 var multi_options: usize = 0;
@@ -38,7 +42,7 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id))
38 pos: []const []const u8, 42 pos: []const []const u8,
39 allocator: *mem.Allocator, 43 allocator: *mem.Allocator,
40 44
41 pub fn parse(allocator: *mem.Allocator, comptime ArgIter: type, iter: *ArgIter) !@This() { 45 pub fn parse(allocator: *mem.Allocator, iter: *ArgIter, diag: ?*clap.Diagnostic) !@This() {
42 var multis = [_]std.ArrayList([]const u8){undefined} ** multi_options; 46 var multis = [_]std.ArrayList([]const u8){undefined} ** multi_options;
43 for (multis) |*multi| { 47 for (multis) |*multi| {
44 multi.* = std.ArrayList([]const u8).init(allocator); 48 multi.* = std.ArrayList([]const u8).init(allocator);
@@ -58,7 +62,7 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id))
58 .params = converted_params, 62 .params = converted_params,
59 .iter = iter, 63 .iter = iter,
60 }; 64 };
61 while (try stream.next()) |arg| { 65 while (try stream.next(diag)) |arg| {
62 const param = arg.param; 66 const param = arg.param;
63 if (param.names.long == null and param.names.short == null) { 67 if (param.names.long == null and param.names.short == null) {
64 try pos.append(arg.value.?); 68 try pos.append(arg.value.?);
@@ -143,7 +147,7 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id))
143} 147}
144 148
145test "clap.comptime.ComptimeClap" { 149test "clap.comptime.ComptimeClap" {
146 const Clap = ComptimeClap(clap.Help, comptime &[_]clap.Param(clap.Help){ 150 const Clap = ComptimeClap(clap.Help, clap.args.SliceIterator, comptime &[_]clap.Param(clap.Help){
147 clap.parseParam("-a, --aa ") catch unreachable, 151 clap.parseParam("-a, --aa ") catch unreachable,
148 clap.parseParam("-b, --bb ") catch unreachable, 152 clap.parseParam("-b, --bb ") catch unreachable,
149 clap.parseParam("-c, --cc <V>") catch unreachable, 153 clap.parseParam("-c, --cc <V>") catch unreachable,
@@ -160,7 +164,7 @@ test "clap.comptime.ComptimeClap" {
160 "-a", "-c", "0", "something", "-d", "a", "--dd", "b", 164 "-a", "-c", "0", "something", "-d", "a", "--dd", "b",
161 }, 165 },
162 }; 166 };
163 var args = try Clap.parse(&fb_allocator.allocator, clap.args.SliceIterator, &iter); 167 var args = try Clap.parse(&fb_allocator.allocator, &iter, null);
164 defer args.deinit(); 168 defer args.deinit();
165 169
166 testing.expect(args.flag("-a")); 170 testing.expect(args.flag("-a"));
diff --git a/clap/streaming.zig b/clap/streaming.zig
index b843bff..90c4e02 100644
--- a/clap/streaming.zig
+++ b/clap/streaming.zig
@@ -24,8 +24,8 @@ pub fn Arg(comptime Id: type) type {
24pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { 24pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
25 return struct { 25 return struct {
26 const State = union(enum) { 26 const State = union(enum) {
27 Normal, 27 normal,
28 Chaining: Chaining, 28 chaining: Chaining,
29 29
30 const Chaining = struct { 30 const Chaining = struct {
31 arg: []const u8, 31 arg: []const u8,
@@ -35,49 +35,48 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
35 35
36 params: []const clap.Param(Id), 36 params: []const clap.Param(Id),
37 iter: *ArgIterator, 37 iter: *ArgIterator,
38 state: State = State.Normal, 38 state: State = .normal,
39 39
40 /// Get the next ::Arg that matches a ::Param. 40 /// Get the next ::Arg that matches a ::Param.
41 pub fn next(parser: *@This()) !?Arg(Id) { 41 pub fn next(parser: *@This(), diag: ?*clap.Diagnostic) !?Arg(Id) {
42 const ArgInfo = struct { 42 const ArgInfo = struct {
43 const Kind = enum {
44 Long,
45 Short,
46 Positional,
47 };
48
49 arg: []const u8, 43 arg: []const u8,
50 kind: Kind, 44 kind: enum {
45 long,
46 short,
47 positional,
48 },
51 }; 49 };
52 50
53 switch (parser.state) { 51 switch (parser.state) {
54 .Normal => { 52 .normal => {
55 const full_arg = (try parser.iter.next()) orelse return null; 53 const full_arg = (try parser.iter.next()) orelse return null;
56 const arg_info = if (mem.eql(u8, full_arg, "--") or mem.eql(u8, full_arg, "-")) 54 const arg_info = if (mem.eql(u8, full_arg, "--") or mem.eql(u8, full_arg, "-"))
57 ArgInfo{ .arg = full_arg, .kind = .Positional } 55 ArgInfo{ .arg = full_arg, .kind = .positional }
58 else if (mem.startsWith(u8, full_arg, "--")) 56 else if (mem.startsWith(u8, full_arg, "--"))
59 ArgInfo{ .arg = full_arg[2..], .kind = .Long } 57 ArgInfo{ .arg = full_arg[2..], .kind = .long }
60 else if (mem.startsWith(u8, full_arg, "-")) 58 else if (mem.startsWith(u8, full_arg, "-"))
61 ArgInfo{ .arg = full_arg[1..], .kind = .Short } 59 ArgInfo{ .arg = full_arg[1..], .kind = .short }
62 else 60 else
63 ArgInfo{ .arg = full_arg, .kind = .Positional }; 61 ArgInfo{ .arg = full_arg, .kind = .positional };
64 62
65 const arg = arg_info.arg; 63 const arg = arg_info.arg;
66 const kind = arg_info.kind; 64 const kind = arg_info.kind;
67 const eql_index = mem.indexOfScalar(u8, arg, '=');
68 65
69 switch (kind) { 66 switch (kind) {
70 ArgInfo.Kind.Long => { 67 .long => {
68 const eql_index = mem.indexOfScalar(u8, arg, '=');
69 const name = if (eql_index) |i| arg[0..i] else arg;
70 const maybe_value = if (eql_index) |i| arg[i + 1 ..] else null;
71
71 for (parser.params) |*param| { 72 for (parser.params) |*param| {
72 const match = param.names.long orelse continue; 73 const match = param.names.long orelse continue;
73 const name = if (eql_index) |i| arg[0..i] else arg;
74 const maybe_value = if (eql_index) |i| arg[i + 1 ..] else null;
75 74
76 if (!mem.eql(u8, name, match)) 75 if (!mem.eql(u8, name, match))
77 continue; 76 continue;
78 if (param.takes_value == .None) { 77 if (param.takes_value == .None) {
79 if (maybe_value != null) 78 if (maybe_value != null)
80 return error.DoesntTakeValue; 79 return err(diag, param.names, error.DoesntTakeValue);
81 80
82 return Arg(Id){ .param = param }; 81 return Arg(Id){ .param = param };
83 } 82 }
@@ -86,19 +85,18 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
86 if (maybe_value) |v| 85 if (maybe_value) |v|
87 break :blk v; 86 break :blk v;
88 87
89 break :blk (try parser.iter.next()) orelse return error.MissingValue; 88 break :blk (try parser.iter.next()) orelse
89 return err(diag, param.names, error.MissingValue);
90 }; 90 };
91 91
92 return Arg(Id){ .param = param, .value = value }; 92 return Arg(Id){ .param = param, .value = value };
93 } 93 }
94 }, 94 },
95 ArgInfo.Kind.Short => { 95 .short => return try parser.chainging(.{
96 return try parser.chainging(State.Chaining{ 96 .arg = full_arg,
97 .arg = full_arg, 97 .index = full_arg.len - arg.len,
98 .index = (full_arg.len - arg.len), 98 }, diag),
99 }); 99 .positional => {
100 },
101 ArgInfo.Kind.Positional => {
102 for (parser.params) |*param| { 100 for (parser.params) |*param| {
103 if (param.names.long) |_| 101 if (param.names.long) |_|
104 continue; 102 continue;
@@ -110,13 +108,13 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
110 }, 108 },
111 } 109 }
112 110
113 return error.InvalidArgument; 111 return err(diag, .{ .long = arg }, error.InvalidArgument);
114 }, 112 },
115 .Chaining => |state| return try parser.chainging(state), 113 .chaining => |state| return try parser.chainging(state, diag),
116 } 114 }
117 } 115 }
118 116
119 fn chainging(parser: *@This(), state: State.Chaining) !?Arg(Id) { 117 fn chainging(parser: *@This(), state: State.Chaining, diag: ?*clap.Diagnostic) !?Arg(Id) {
120 const arg = state.arg; 118 const arg = state.arg;
121 const index = state.index; 119 const index = state.index;
122 const next_index = index + 1; 120 const next_index = index + 1;
@@ -129,10 +127,10 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
129 // Before we return, we have to set the new state of the clap 127 // Before we return, we have to set the new state of the clap
130 defer { 128 defer {
131 if (arg.len <= next_index or param.takes_value != .None) { 129 if (arg.len <= next_index or param.takes_value != .None) {
132 parser.state = State.Normal; 130 parser.state = .normal;
133 } else { 131 } else {
134 parser.state = State{ 132 parser.state = .{
135 .Chaining = State.Chaining{ 133 .chaining = .{
136 .arg = arg, 134 .arg = arg,
137 .index = next_index, 135 .index = next_index,
138 }, 136 },
@@ -144,7 +142,9 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
144 return Arg(Id){ .param = param }; 142 return Arg(Id){ .param = param };
145 143
146 if (arg.len <= next_index) { 144 if (arg.len <= next_index) {
147 const value = (try parser.iter.next()) orelse return error.MissingValue; 145 const value = (try parser.iter.next()) orelse
146 return err(diag, param.names, error.MissingValue);
147
148 return Arg(Id){ .param = param, .value = value }; 148 return Arg(Id){ .param = param, .value = value };
149 } 149 }
150 150
@@ -154,7 +154,13 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
154 return Arg(Id){ .param = param, .value = arg[next_index..] }; 154 return Arg(Id){ .param = param, .value = arg[next_index..] };
155 } 155 }
156 156
157 return error.InvalidArgument; 157 return err(diag, .{ .short = arg[index] }, error.InvalidArgument);
158 }
159
160 fn err(diag: ?*clap.Diagnostic, names: clap.Names, _err: var) @TypeOf(_err) {
161 if (diag) |d|
162 d.name = names;
163 return _err;
158 } 164 }
159 }; 165 };
160} 166}
@@ -167,7 +173,7 @@ fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, r
167 }; 173 };
168 174
169 for (results) |res| { 175 for (results) |res| {
170 const arg = (c.next() catch unreachable) orelse unreachable; 176 const arg = (c.next(null) catch unreachable) orelse unreachable;
171 testing.expectEqual(res.param, arg.param); 177 testing.expectEqual(res.param, arg.param);
172 const expected_value = res.value orelse { 178 const expected_value = res.value orelse {
173 testing.expectEqual(@as(@TypeOf(arg.value), null), arg.value); 179 testing.expectEqual(@as(@TypeOf(arg.value), null), arg.value);
@@ -177,7 +183,7 @@ fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, r
177 testing.expectEqualSlices(u8, expected_value, actual_value); 183 testing.expectEqualSlices(u8, expected_value, actual_value);
178 } 184 }
179 185
180 if (c.next() catch unreachable) |_| 186 if (c.next(null) catch unreachable) |_|
181 unreachable; 187 unreachable;
182} 188}
183 189
diff --git a/example/comptime-clap.zig b/example/comptime-clap.zig
index d709e48..530c7e6 100644
--- a/example/comptime-clap.zig
+++ b/example/comptime-clap.zig
@@ -16,14 +16,24 @@ pub fn main() !void {
16 .takes_value = .One, 16 .takes_value = .One,
17 }, 17 },
18 }; 18 };
19 const Clap = clap.ComptimeClap(clap.Help, clap.args.OsIterator, &params);
19 20
20 // We then initialize an argument iterator. We will use the OsIterator as it nicely 21 // We then initialize an argument iterator. We will use the OsIterator as it nicely
21 // wraps iterating over arguments the most efficient way on each os. 22 // wraps iterating over arguments the most efficient way on each os.
22 var iter = try clap.args.OsIterator.init(allocator); 23 var iter = try clap.args.OsIterator.init(allocator);
23 defer iter.deinit(); 24 defer iter.deinit();
24 25
26 // Initalize our diagnostics, which can be used for reporting useful errors.
27 // This is optional. You can also just pass `null` to `parser.next` if you
28 // don't care about the extra information `Diagnostics` provides.
29 var diag: clap.Diagnostic = undefined;
30
25 // Parse the arguments 31 // Parse the arguments
26 var args = try clap.ComptimeClap(clap.Help, &params).parse(allocator, clap.args.OsIterator, &iter); 32 var args = Clap.parse(allocator, &iter, &diag) catch |err| {
33 // Report useful error and exit
34 diag.report(std.io.getStdErr().outStream(), err) catch {};
35 return err;
36 };
27 defer args.deinit(); 37 defer args.deinit();
28 38
29 if (args.flag("--help")) 39 if (args.flag("--help"))
diff --git a/example/simple-error.zig b/example/simple-error.zig
index 2c403fc..3c62f0e 100644
--- a/example/simple-error.zig
+++ b/example/simple-error.zig
@@ -2,13 +2,11 @@ const std = @import("std");
2const clap = @import("clap"); 2const clap = @import("clap");
3 3
4pub fn main() !void { 4pub fn main() !void {
5 // First we specify what parameters our program can take.
6 // We can use `parseParam` to parse a string to a `Param(Help)`
7 const params = comptime [_]clap.Param(clap.Help){ 5 const params = comptime [_]clap.Param(clap.Help){
8 clap.parseParam("-h, --help Display this help and exit.") catch unreachable, 6 clap.parseParam("-h, --help Display this help and exit.") catch unreachable,
9 }; 7 };
10 8
11 var args = try clap.parse(clap.Help, &params, std.heap.direct_allocator); 9 var args = try clap.parse(clap.Help, &params, std.heap.direct_allocator, null);
12 defer args.deinit(); 10 defer args.deinit();
13 11
14 _ = args.flag("--helps"); 12 _ = args.flag("--helps");
diff --git a/example/simple.zig b/example/simple.zig
index adea9f9..f7b5953 100644
--- a/example/simple.zig
+++ b/example/simple.zig
@@ -15,7 +15,16 @@ pub fn main() !void {
15 }, 15 },
16 }; 16 };
17 17
18 var args = try clap.parse(clap.Help, &params, std.heap.page_allocator); 18 // Initalize our diagnostics, which can be used for reporting useful errors.
19 // This is optional. You can also just pass `null` to `parser.next` if you
20 // don't care about the extra information `Diagnostics` provides.
21 var diag: clap.Diagnostic = undefined;
22
23 var args = clap.parse(clap.Help, &params, std.heap.page_allocator, &diag) catch |err| {
24 // Report useful error and exit
25 diag.report(std.io.getStdErr().outStream(), err) catch {};
26 return err;
27 };
19 defer args.deinit(); 28 defer args.deinit();
20 29
21 if (args.flag("--help")) 30 if (args.flag("--help"))
diff --git a/example/streaming-clap.zig b/example/streaming-clap.zig
index b92a9e6..941070f 100644
--- a/example/streaming-clap.zig
+++ b/example/streaming-clap.zig
@@ -34,8 +34,17 @@ pub fn main() !void {
34 .iter = &iter, 34 .iter = &iter,
35 }; 35 };
36 36
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
37 // Because we use a streaming parser, we have to consume each argument parsed individually. 42 // Because we use a streaming parser, we have to consume each argument parsed individually.
38 while (try parser.next()) |arg| { 43 while (parser.next(&diag) catch |err| {
44 // Report useful error and exit
45 diag.report(std.io.getStdErr().outStream(), err) catch {};
46 return err;
47 }) |arg| {
39 // arg.param will point to the parameter which matched the argument. 48 // arg.param will point to the parameter which matched the argument.
40 switch (arg.param.id) { 49 switch (arg.param.id) {
41 'h' => debug.warn("Help!\n", .{}), 50 'h' => debug.warn("Help!\n", .{}),