summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Komari Spaghetti2021-05-26 21:06:10 +0200
committerGravatar Komari Spaghetti2021-05-26 21:06:10 +0200
commitc7d83fcce1739271e399260b50c5f68aa03c5908 (patch)
treef859d081955e5c8c3bc329008837d351606ec19c
parentMerge branch 'master' into zig-master (diff)
downloadzig-clap-c7d83fcce1739271e399260b50c5f68aa03c5908.tar.gz
zig-clap-c7d83fcce1739271e399260b50c5f68aa03c5908.tar.xz
zig-clap-c7d83fcce1739271e399260b50c5f68aa03c5908.zip
Update to latest zig in preperation for 0.8.0
-rw-r--r--.gitignore1
-rw-r--r--README.md16
-rw-r--r--build.zig18
-rw-r--r--clap.zig128
-rw-r--r--clap/args.zig86
-rw-r--r--clap/comptime.zig70
-rw-r--r--clap/streaming.zig66
-rw-r--r--example/README.md.template10
-rw-r--r--example/help.zig2
-rw-r--r--example/simple-ex.zig10
-rw-r--r--example/simple.zig6
-rw-r--r--example/streaming-clap.zig10
-rw-r--r--example/usage.zig2
13 files changed, 211 insertions, 214 deletions
diff --git a/.gitignore b/.gitignore
index 2040c29..4c82b07 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
1zig-cache 1zig-cache
2zig-out
diff --git a/README.md b/README.md
index 398a088..4576ace 100644
--- a/README.md
+++ b/README.md
@@ -55,11 +55,11 @@ pub fn main() !void {
55 if (args.flag("--help")) 55 if (args.flag("--help"))
56 debug.warn("--help\n", .{}); 56 debug.warn("--help\n", .{});
57 if (args.option("--number")) |n| 57 if (args.option("--number")) |n|
58 debug.warn("--number = {}\n", .{n}); 58 debug.warn("--number = {s}\n", .{n});
59 for (args.options("--string")) |s| 59 for (args.options("--string")) |s|
60 debug.warn("--string = {}\n", .{s}); 60 debug.warn("--string = {s}\n", .{s});
61 for (args.positionals()) |pos| 61 for (args.positionals()) |pos|
62 debug.warn("{}\n", .{pos}); 62 debug.warn("{s}\n", .{pos});
63} 63}
64 64
65``` 65```
@@ -154,12 +154,12 @@ pub fn main() !void {
154 // arg.param will point to the parameter which matched the argument. 154 // arg.param will point to the parameter which matched the argument.
155 switch (arg.param.id) { 155 switch (arg.param.id) {
156 'h' => debug.warn("Help!\n", .{}), 156 'h' => debug.warn("Help!\n", .{}),
157 'n' => debug.warn("--number = {}\n", .{arg.value.?}), 157 'n' => debug.warn("--number = {s}\n", .{arg.value.?}),
158 158
159 // arg.value == null, if arg.param.takes_value == false. 159 // arg.value == null, if arg.param.takes_value == .none.
160 // Otherwise, arg.value is the value passed with the argument, such as "-a=10" 160 // Otherwise, arg.value is the value passed with the argument, such as "-a=10"
161 // or "-a 10". 161 // or "-a 10".
162 'f' => debug.warn("{}\n", .{arg.value.?}), 162 'f' => debug.warn("{s}\n", .{arg.value.?}),
163 else => unreachable, 163 else => unreachable,
164 } 164 }
165 } 165 }
@@ -185,7 +185,7 @@ pub fn main() !void {
185 // help message for any Param, but it is more verbose to call. 185 // help message for any Param, but it is more verbose to call.
186 try clap.help( 186 try clap.help(
187 std.io.getStdErr().writer(), 187 std.io.getStdErr().writer(),
188 comptime &[_]clap.Param(clap.Help){ 188 comptime &.{
189 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, 189 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable,
190 clap.parseParam("-v, --version Output version information and exit.") catch unreachable, 190 clap.parseParam("-v, --version Output version information and exit.") catch unreachable,
191 }, 191 },
@@ -223,7 +223,7 @@ pub fn main() !void {
223 // usage message for any Param, but it is more verbose to call. 223 // usage message for any Param, but it is more verbose to call.
224 try clap.usage( 224 try clap.usage(
225 std.io.getStdErr().writer(), 225 std.io.getStdErr().writer(),
226 comptime &[_]clap.Param(clap.Help){ 226 comptime &.{
227 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, 227 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable,
228 clap.parseParam("-v, --version Output version information and exit.") catch unreachable, 228 clap.parseParam("-v, --version Output version information and exit.") catch unreachable,
229 clap.parseParam(" --value <N> Output version information and exit.") catch unreachable, 229 clap.parseParam(" --value <N> Output version information and exit.") catch unreachable,
diff --git a/build.zig b/build.zig
index bef10be..5cbc731 100644
--- a/build.zig
+++ b/build.zig
@@ -1,4 +1,3 @@
1const builtin = @import("builtin");
2const std = @import("std"); 1const std = @import("std");
3 2
4const Builder = std.build.Builder; 3const Builder = std.build.Builder;
@@ -9,13 +8,13 @@ pub fn build(b: *Builder) void {
9 const target = b.standardTargetOptions(.{}); 8 const target = b.standardTargetOptions(.{});
10 9
11 const test_all_step = b.step("test", "Run all tests in all modes."); 10 const test_all_step = b.step("test", "Run all tests in all modes.");
12 inline for ([_]Mode{ Mode.Debug, Mode.ReleaseFast, Mode.ReleaseSafe, Mode.ReleaseSmall }) |test_mode| { 11 inline for (@typeInfo(std.builtin.Mode).Enum.fields) |field| {
13 const mode_str = comptime modeToString(test_mode); 12 const test_mode = @field(std.builtin.Mode, field.name);
13 const mode_str = @tagName(test_mode);
14 14
15 const tests = b.addTest("clap.zig"); 15 const tests = b.addTest("clap.zig");
16 tests.setBuildMode(test_mode); 16 tests.setBuildMode(test_mode);
17 tests.setTarget(target); 17 tests.setTarget(target);
18 tests.setNamePrefix(mode_str ++ " ");
19 18
20 const test_step = b.step("test-" ++ mode_str, "Run all tests in " ++ mode_str ++ "."); 19 const test_step = b.step("test-" ++ mode_str, "Run all tests in " ++ mode_str ++ ".");
21 test_step.dependOn(&tests.step); 20 test_step.dependOn(&tests.step);
@@ -23,7 +22,7 @@ pub fn build(b: *Builder) void {
23 } 22 }
24 23
25 const example_step = b.step("examples", "Build examples"); 24 const example_step = b.step("examples", "Build examples");
26 inline for ([_][]const u8{ 25 inline for (.{
27 "simple", 26 "simple",
28 "simple-ex", 27 "simple-ex",
29 //"simple-error", 28 //"simple-error",
@@ -70,12 +69,3 @@ fn readMeStep(b: *Builder) *std.build.Step {
70 }.make); 69 }.make);
71 return s; 70 return s;
72} 71}
73
74fn modeToString(mode: Mode) []const u8 {
75 return switch (mode) {
76 Mode.Debug => "debug",
77 Mode.ReleaseFast => "release-fast",
78 Mode.ReleaseSafe => "release-safe",
79 Mode.ReleaseSmall => "release-small",
80 };
81}
diff --git a/clap.zig b/clap.zig
index 8d721fa..ee713a7 100644
--- a/clap.zig
+++ b/clap.zig
@@ -122,81 +122,81 @@ fn parseParamRest(line: []const u8) Param(Help) {
122 return .{ .id = .{ .msg = mem.trim(u8, line, " \t") } }; 122 return .{ .id = .{ .msg = mem.trim(u8, line, " \t") } };
123} 123}
124 124
125fn expectParam(expect: Param(Help), actual: Param(Help)) void { 125fn expectParam(expect: Param(Help), actual: Param(Help)) !void {
126 testing.expectEqualStrings(expect.id.msg, actual.id.msg); 126 try testing.expectEqualStrings(expect.id.msg, actual.id.msg);
127 testing.expectEqualStrings(expect.id.value, actual.id.value); 127 try testing.expectEqualStrings(expect.id.value, actual.id.value);
128 testing.expectEqual(expect.names.short, actual.names.short); 128 try testing.expectEqual(expect.names.short, actual.names.short);
129 testing.expectEqual(expect.takes_value, actual.takes_value); 129 try testing.expectEqual(expect.takes_value, actual.takes_value);
130 if (expect.names.long) |long| { 130 if (expect.names.long) |long| {
131 testing.expectEqualStrings(long, actual.names.long.?); 131 try testing.expectEqualStrings(long, actual.names.long.?);
132 } else { 132 } else {
133 testing.expectEqual(@as(?[]const u8, null), actual.names.long); 133 try testing.expectEqual(@as(?[]const u8, null), actual.names.long);
134 } 134 }
135} 135}
136 136
137test "parseParam" { 137test "parseParam" {
138 expectParam(Param(Help){ 138 try expectParam(Param(Help){
139 .id = .{ .msg = "Help text", .value = "value" }, 139 .id = .{ .msg = "Help text", .value = "value" },
140 .names = .{ .short = 's', .long = "long" }, 140 .names = .{ .short = 's', .long = "long" },
141 .takes_value = .one, 141 .takes_value = .one,
142 }, try parseParam("-s, --long <value> Help text")); 142 }, try parseParam("-s, --long <value> Help text"));
143 143
144 expectParam(Param(Help){ 144 try expectParam(Param(Help){
145 .id = .{ .msg = "Help text", .value = "value" }, 145 .id = .{ .msg = "Help text", .value = "value" },
146 .names = .{ .short = 's', .long = "long" }, 146 .names = .{ .short = 's', .long = "long" },
147 .takes_value = .many, 147 .takes_value = .many,
148 }, try parseParam("-s, --long <value>... Help text")); 148 }, try parseParam("-s, --long <value>... Help text"));
149 149
150 expectParam(Param(Help){ 150 try expectParam(Param(Help){
151 .id = .{ .msg = "Help text", .value = "value" }, 151 .id = .{ .msg = "Help text", .value = "value" },
152 .names = .{ .long = "long" }, 152 .names = .{ .long = "long" },
153 .takes_value = .one, 153 .takes_value = .one,
154 }, try parseParam("--long <value> Help text")); 154 }, try parseParam("--long <value> Help text"));
155 155
156 expectParam(Param(Help){ 156 try expectParam(Param(Help){
157 .id = .{ .msg = "Help text", .value = "value" }, 157 .id = .{ .msg = "Help text", .value = "value" },
158 .names = .{ .short = 's' }, 158 .names = .{ .short = 's' },
159 .takes_value = .one, 159 .takes_value = .one,
160 }, try parseParam("-s <value> Help text")); 160 }, try parseParam("-s <value> Help text"));
161 161
162 expectParam(Param(Help){ 162 try expectParam(Param(Help){
163 .id = .{ .msg = "Help text" }, 163 .id = .{ .msg = "Help text" },
164 .names = .{ .short = 's', .long = "long" }, 164 .names = .{ .short = 's', .long = "long" },
165 }, try parseParam("-s, --long Help text")); 165 }, try parseParam("-s, --long Help text"));
166 166
167 expectParam(Param(Help){ 167 try expectParam(Param(Help){
168 .id = .{ .msg = "Help text" }, 168 .id = .{ .msg = "Help text" },
169 .names = .{ .short = 's' }, 169 .names = .{ .short = 's' },
170 }, try parseParam("-s Help text")); 170 }, try parseParam("-s Help text"));
171 171
172 expectParam(Param(Help){ 172 try expectParam(Param(Help){
173 .id = .{ .msg = "Help text" }, 173 .id = .{ .msg = "Help text" },
174 .names = .{ .long = "long" }, 174 .names = .{ .long = "long" },
175 }, try parseParam("--long Help text")); 175 }, try parseParam("--long Help text"));
176 176
177 expectParam(Param(Help){ 177 try expectParam(Param(Help){
178 .id = .{ .msg = "Help text", .value = "A | B" }, 178 .id = .{ .msg = "Help text", .value = "A | B" },
179 .names = .{ .long = "long" }, 179 .names = .{ .long = "long" },
180 .takes_value = .one, 180 .takes_value = .one,
181 }, try parseParam("--long <A | B> Help text")); 181 }, try parseParam("--long <A | B> Help text"));
182 182
183 expectParam(Param(Help){ 183 try expectParam(Param(Help){
184 .id = .{ .msg = "Help text", .value = "A" }, 184 .id = .{ .msg = "Help text", .value = "A" },
185 .names = .{}, 185 .names = .{},
186 .takes_value = .one, 186 .takes_value = .one,
187 }, try parseParam("<A> Help text")); 187 }, try parseParam("<A> Help text"));
188 188
189 expectParam(Param(Help){ 189 try expectParam(Param(Help){
190 .id = .{ .msg = "Help text", .value = "A" }, 190 .id = .{ .msg = "Help text", .value = "A" },
191 .names = .{}, 191 .names = .{},
192 .takes_value = .many, 192 .takes_value = .many,
193 }, try parseParam("<A>... Help text")); 193 }, try parseParam("<A>... Help text"));
194 194
195 testing.expectError(error.TrailingComma, parseParam("--long, Help")); 195 try testing.expectError(error.TrailingComma, parseParam("--long, Help"));
196 testing.expectError(error.TrailingComma, parseParam("-s, Help")); 196 try testing.expectError(error.TrailingComma, parseParam("-s, Help"));
197 testing.expectError(error.InvalidShortParam, parseParam("-ss Help")); 197 try testing.expectError(error.InvalidShortParam, parseParam("-ss Help"));
198 testing.expectError(error.InvalidShortParam, parseParam("-ss <value> Help")); 198 try testing.expectError(error.InvalidShortParam, parseParam("-ss <value> Help"));
199 testing.expectError(error.InvalidShortParam, parseParam("- Help")); 199 try testing.expectError(error.InvalidShortParam, parseParam("- Help"));
200} 200}
201 201
202/// Optional diagnostics used for reporting useful errors 202/// Optional diagnostics used for reporting useful errors
@@ -227,24 +227,24 @@ pub const Diagnostic = struct {
227 } 227 }
228}; 228};
229 229
230fn testDiag(diag: Diagnostic, err: anyerror, expected: []const u8) void { 230fn testDiag(diag: Diagnostic, err: anyerror, expected: []const u8) !void {
231 var buf: [1024]u8 = undefined; 231 var buf: [1024]u8 = undefined;
232 var slice_stream = io.fixedBufferStream(&buf); 232 var slice_stream = io.fixedBufferStream(&buf);
233 diag.report(slice_stream.writer(), err) catch unreachable; 233 diag.report(slice_stream.writer(), err) catch unreachable;
234 testing.expectEqualStrings(expected, slice_stream.getWritten()); 234 try testing.expectEqualStrings(expected, slice_stream.getWritten());
235} 235}
236 236
237test "Diagnostic.report" { 237test "Diagnostic.report" {
238 testDiag(.{ .arg = "c" }, error.InvalidArgument, "Invalid argument 'c'\n"); 238 try testDiag(.{ .arg = "c" }, error.InvalidArgument, "Invalid argument 'c'\n");
239 testDiag(.{ .name = .{ .long = "cc" } }, error.InvalidArgument, "Invalid argument '--cc'\n"); 239 try testDiag(.{ .name = .{ .long = "cc" } }, error.InvalidArgument, "Invalid argument '--cc'\n");
240 testDiag(.{ .name = .{ .short = 'c' } }, error.DoesntTakeValue, "The argument '-c' does not take a value\n"); 240 try testDiag(.{ .name = .{ .short = 'c' } }, error.DoesntTakeValue, "The argument '-c' does not take a value\n");
241 testDiag(.{ .name = .{ .long = "cc" } }, error.DoesntTakeValue, "The argument '--cc' does not take a value\n"); 241 try testDiag(.{ .name = .{ .long = "cc" } }, error.DoesntTakeValue, "The argument '--cc' does not take a value\n");
242 testDiag(.{ .name = .{ .short = 'c' } }, error.MissingValue, "The argument '-c' requires a value but none was supplied\n"); 242 try testDiag(.{ .name = .{ .short = 'c' } }, error.MissingValue, "The argument '-c' requires a value but none was supplied\n");
243 testDiag(.{ .name = .{ .long = "cc" } }, error.MissingValue, "The argument '--cc' requires a value but none was supplied\n"); 243 try testDiag(.{ .name = .{ .long = "cc" } }, error.MissingValue, "The argument '--cc' requires a value but none was supplied\n");
244 testDiag(.{ .name = .{ .short = 'c' } }, error.InvalidArgument, "Invalid argument '-c'\n"); 244 try testDiag(.{ .name = .{ .short = 'c' } }, error.InvalidArgument, "Invalid argument '-c'\n");
245 testDiag(.{ .name = .{ .long = "cc" } }, error.InvalidArgument, "Invalid argument '--cc'\n"); 245 try testDiag(.{ .name = .{ .long = "cc" } }, error.InvalidArgument, "Invalid argument '--cc'\n");
246 testDiag(.{ .name = .{ .short = 'c' } }, error.SomethingElse, "Error while parsing arguments: SomethingElse\n"); 246 try testDiag(.{ .name = .{ .short = 'c' } }, error.SomethingElse, "Error while parsing arguments: SomethingElse\n");
247 testDiag(.{ .name = .{ .long = "cc" } }, error.SomethingElse, "Error while parsing arguments: SomethingElse\n"); 247 try testDiag(.{ .name = .{ .long = "cc" } }, error.SomethingElse, "Error while parsing arguments: SomethingElse\n");
248} 248}
249 249
250pub fn Args(comptime Id: type, comptime params: []const Param(Id)) type { 250pub fn Args(comptime Id: type, comptime params: []const Param(Id)) type {
@@ -338,7 +338,7 @@ pub fn helpFull(
338 const max_spacing = blk: { 338 const max_spacing = blk: {
339 var res: usize = 0; 339 var res: usize = 0;
340 for (params) |param| { 340 for (params) |param| {
341 var cs = io.countingOutStream(io.null_writer); 341 var cs = io.countingWriter(io.null_writer);
342 try printParam(cs.writer(), Id, param, Error, context, valueText); 342 try printParam(cs.writer(), Id, param, Error, context, valueText);
343 if (res < cs.bytes_written) 343 if (res < cs.bytes_written)
344 res = @intCast(usize, cs.bytes_written); 344 res = @intCast(usize, cs.bytes_written);
@@ -355,7 +355,7 @@ pub fn helpFull(
355 try stream.print("\t", .{}); 355 try stream.print("\t", .{});
356 try printParam(cs.writer(), Id, param, Error, context, valueText); 356 try printParam(cs.writer(), Id, param, Error, context, valueText);
357 try stream.writeByteNTimes(' ', max_spacing - @intCast(usize, cs.bytes_written)); 357 try stream.writeByteNTimes(' ', max_spacing - @intCast(usize, cs.bytes_written));
358 try stream.print("\t{}\n", .{try helpText(context, param)}); 358 try stream.print("\t{s}\n", .{try helpText(context, param)});
359 } 359 }
360} 360}
361 361
@@ -450,7 +450,7 @@ test "clap.help" {
450 @setEvalBranchQuota(10000); 450 @setEvalBranchQuota(10000);
451 try help( 451 try help(
452 slice_stream.writer(), 452 slice_stream.writer(),
453 comptime &[_]Param(Help){ 453 comptime &.{
454 parseParam("-a Short flag.") catch unreachable, 454 parseParam("-a Short flag.") catch unreachable,
455 parseParam("-b <V1> Short option.") catch unreachable, 455 parseParam("-b <V1> Short option.") catch unreachable,
456 parseParam("--aa Long flag.") catch unreachable, 456 parseParam("--aa Long flag.") catch unreachable,
@@ -471,7 +471,7 @@ test "clap.help" {
471 "\t-d, --dd <V3> \tBoth option.\n" ++ 471 "\t-d, --dd <V3> \tBoth option.\n" ++
472 "\t-d, --dd <V3>...\tBoth repeated option.\n"; 472 "\t-d, --dd <V3>...\tBoth repeated option.\n";
473 473
474 testing.expectEqualStrings(expected, slice_stream.getWritten()); 474 try testing.expectEqualStrings(expected, slice_stream.getWritten());
475} 475}
476 476
477/// Will print a usage message in the following format: 477/// Will print a usage message in the following format:
@@ -569,40 +569,40 @@ fn testUsage(expected: []const u8, params: []const Param(Help)) !void {
569 var buf: [1024]u8 = undefined; 569 var buf: [1024]u8 = undefined;
570 var fbs = io.fixedBufferStream(&buf); 570 var fbs = io.fixedBufferStream(&buf);
571 try usage(fbs.writer(), params); 571 try usage(fbs.writer(), params);
572 testing.expectEqualStrings(expected, fbs.getWritten()); 572 try testing.expectEqualStrings(expected, fbs.getWritten());
573} 573}
574 574
575test "usage" { 575test "usage" {
576 @setEvalBranchQuota(100000); 576 @setEvalBranchQuota(100000);
577 try testUsage("[-ab]", comptime &[_]Param(Help){ 577 try testUsage("[-ab]", &.{
578 parseParam("-a") catch unreachable, 578 try parseParam("-a"),
579 parseParam("-b") catch unreachable, 579 try parseParam("-b"),
580 }); 580 });
581 try testUsage("[-a <value>] [-b <v>]", comptime &[_]Param(Help){ 581 try testUsage("[-a <value>] [-b <v>]", &.{
582 parseParam("-a <value>") catch unreachable, 582 try parseParam("-a <value>"),
583 parseParam("-b <v>") catch unreachable, 583 try parseParam("-b <v>"),
584 }); 584 });
585 try testUsage("[--a] [--b]", comptime &[_]Param(Help){ 585 try testUsage("[--a] [--b]", &.{
586 parseParam("--a") catch unreachable, 586 try parseParam("--a"),
587 parseParam("--b") catch unreachable, 587 try parseParam("--b"),
588 }); 588 });
589 try testUsage("[--a <value>] [--b <v>]", comptime &[_]Param(Help){ 589 try testUsage("[--a <value>] [--b <v>]", &.{
590 parseParam("--a <value>") catch unreachable, 590 try parseParam("--a <value>"),
591 parseParam("--b <v>") catch unreachable, 591 try parseParam("--b <v>"),
592 }); 592 });
593 try testUsage("<file>", comptime &[_]Param(Help){ 593 try testUsage("<file>", &.{
594 parseParam("<file>") catch unreachable, 594 try parseParam("<file>"),
595 }); 595 });
596 try testUsage("[-ab] [-c <value>] [-d <v>] [--e] [--f] [--g <value>] [--h <v>] [-i <v>...] <file>", comptime &[_]Param(Help){ 596 try testUsage("[-ab] [-c <value>] [-d <v>] [--e] [--f] [--g <value>] [--h <v>] [-i <v>...] <file>", &.{
597 parseParam("-a") catch unreachable, 597 try parseParam("-a"),
598 parseParam("-b") catch unreachable, 598 try parseParam("-b"),
599 parseParam("-c <value>") catch unreachable, 599 try parseParam("-c <value>"),
600 parseParam("-d <v>") catch unreachable, 600 try parseParam("-d <v>"),
601 parseParam("--e") catch unreachable, 601 try parseParam("--e"),
602 parseParam("--f") catch unreachable, 602 try parseParam("--f"),
603 parseParam("--g <value>") catch unreachable, 603 try parseParam("--g <value>"),
604 parseParam("--h <v>") catch unreachable, 604 try parseParam("--h <v>"),
605 parseParam("-i <v>...") catch unreachable, 605 try parseParam("-i <v>..."),
606 parseParam("<file>") catch unreachable, 606 try parseParam("<file>"),
607 }); 607 });
608} 608}
diff --git a/clap/args.zig b/clap/args.zig
index f9ad218..555e8ab 100644
--- a/clap/args.zig
+++ b/clap/args.zig
@@ -34,8 +34,8 @@ pub const SliceIterator = struct {
34}; 34};
35 35
36test "SliceIterator" { 36test "SliceIterator" {
37 const args = &[_][]const u8{ "A", "BB", "CCC" }; 37 const args = [_][]const u8{ "A", "BB", "CCC" };
38 var iter = SliceIterator{ .args = args }; 38 var iter = SliceIterator{ .args = &args };
39 39
40 for (args) |a| { 40 for (args) |a| {
41 const b = try iter.next(); 41 const b = try iter.next();
@@ -266,76 +266,76 @@ pub const ShellIterator = struct {
266 } 266 }
267}; 267};
268 268
269fn testShellIteratorOk(str: []const u8, allocations: usize, expect: []const []const u8) void { 269fn testShellIteratorOk(str: []const u8, allocations: usize, expect: []const []const u8) !void {
270 var allocator = testing.FailingAllocator.init(testing.allocator, allocations); 270 var allocator = testing.FailingAllocator.init(testing.allocator, allocations);
271 var it = ShellIterator.init(&allocator.allocator, str); 271 var it = ShellIterator.init(&allocator.allocator, str);
272 defer it.deinit(); 272 defer it.deinit();
273 273
274 for (expect) |e| { 274 for (expect) |e| {
275 if (it.next()) |actual| { 275 if (it.next()) |actual| {
276 testing.expect(actual != null); 276 try testing.expect(actual != null);
277 testing.expectEqualStrings(e, actual.?); 277 try testing.expectEqualStrings(e, actual.?);
278 } else |err| testing.expectEqual(@as(anyerror![]const u8, e), err); 278 } else |err| try testing.expectEqual(@as(anyerror![]const u8, e), err);
279 } 279 }
280 280
281 if (it.next()) |actual| { 281 if (it.next()) |actual| {
282 testing.expectEqual(@as(?[]const u8, null), actual); 282 try testing.expectEqual(@as(?[]const u8, null), actual);
283 testing.expectEqual(allocations, allocator.allocations); 283 try testing.expectEqual(allocations, allocator.allocations);
284 } else |err| testing.expectEqual(@as(anyerror!void, {}), err); 284 } else |err| try testing.expectEqual(@as(anyerror!void, {}), err);
285} 285}
286 286
287fn testShellIteratorErr(str: []const u8, expect: anyerror) void { 287fn testShellIteratorErr(str: []const u8, expect: anyerror) !void {
288 var it = ShellIterator.init(testing.allocator, str); 288 var it = ShellIterator.init(testing.allocator, str);
289 defer it.deinit(); 289 defer it.deinit();
290 290
291 while (it.next() catch |err| { 291 while (it.next() catch |err| {
292 testing.expectError(expect, @as(anyerror!void, err)); 292 try testing.expectError(expect, @as(anyerror!void, err));
293 return; 293 return;
294 }) |_| {} 294 }) |_| {}
295 295
296 testing.expectError(expect, @as(anyerror!void, {})); 296 try testing.expectError(expect, @as(anyerror!void, {}));
297} 297}
298 298
299test "ShellIterator" { 299test "ShellIterator" {
300 testShellIteratorOk("a", 0, &[_][]const u8{"a"}); 300 try testShellIteratorOk("a", 0, &.{"a"});
301 testShellIteratorOk("'a'", 0, &[_][]const u8{"a"}); 301 try testShellIteratorOk("'a'", 0, &.{"a"});
302 testShellIteratorOk("\"a\"", 0, &[_][]const u8{"a"}); 302 try testShellIteratorOk("\"a\"", 0, &.{"a"});
303 testShellIteratorOk("a b", 0, &[_][]const u8{ "a", "b" }); 303 try testShellIteratorOk("a b", 0, &.{ "a", "b" });
304 testShellIteratorOk("'a' b", 0, &[_][]const u8{ "a", "b" }); 304 try testShellIteratorOk("'a' b", 0, &.{ "a", "b" });
305 testShellIteratorOk("\"a\" b", 0, &[_][]const u8{ "a", "b" }); 305 try testShellIteratorOk("\"a\" b", 0, &.{ "a", "b" });
306 testShellIteratorOk("a 'b'", 0, &[_][]const u8{ "a", "b" }); 306 try testShellIteratorOk("a 'b'", 0, &.{ "a", "b" });
307 testShellIteratorOk("a \"b\"", 0, &[_][]const u8{ "a", "b" }); 307 try testShellIteratorOk("a \"b\"", 0, &.{ "a", "b" });
308 testShellIteratorOk("'a b'", 0, &[_][]const u8{"a b"}); 308 try testShellIteratorOk("'a b'", 0, &.{"a b"});
309 testShellIteratorOk("\"a b\"", 0, &[_][]const u8{"a b"}); 309 try testShellIteratorOk("\"a b\"", 0, &.{"a b"});
310 testShellIteratorOk("\"a\"\"b\"", 1, &[_][]const u8{"ab"}); 310 try testShellIteratorOk("\"a\"\"b\"", 1, &.{"ab"});
311 testShellIteratorOk("'a''b'", 1, &[_][]const u8{"ab"}); 311 try testShellIteratorOk("'a''b'", 1, &.{"ab"});
312 testShellIteratorOk("'a'b", 1, &[_][]const u8{"ab"}); 312 try testShellIteratorOk("'a'b", 1, &.{"ab"});
313 testShellIteratorOk("a'b'", 1, &[_][]const u8{"ab"}); 313 try testShellIteratorOk("a'b'", 1, &.{"ab"});
314 testShellIteratorOk("a\\ b", 1, &[_][]const u8{"a b"}); 314 try testShellIteratorOk("a\\ b", 1, &.{"a b"});
315 testShellIteratorOk("\"a\\ b\"", 1, &[_][]const u8{"a b"}); 315 try testShellIteratorOk("\"a\\ b\"", 1, &.{"a b"});
316 testShellIteratorOk("'a\\ b'", 0, &[_][]const u8{"a\\ b"}); 316 try testShellIteratorOk("'a\\ b'", 0, &.{"a\\ b"});
317 testShellIteratorOk(" a b ", 0, &[_][]const u8{ "a", "b" }); 317 try testShellIteratorOk(" a b ", 0, &.{ "a", "b" });
318 testShellIteratorOk("\\ \\ ", 0, &[_][]const u8{ " ", " " }); 318 try testShellIteratorOk("\\ \\ ", 0, &.{ " ", " " });
319 319
320 testShellIteratorOk( 320 try testShellIteratorOk(
321 \\printf 'run\nuninstall\n' 321 \\printf 'run\nuninstall\n'
322 , 0, &[_][]const u8{ "printf", "run\\nuninstall\\n" }); 322 , 0, &.{ "printf", "run\\nuninstall\\n" });
323 testShellIteratorOk( 323 try testShellIteratorOk(
324 \\setsid -f steam "steam://$action/$id" 324 \\setsid -f steam "steam://$action/$id"
325 , 0, &[_][]const u8{ "setsid", "-f", "steam", "steam://$action/$id" }); 325 , 0, &.{ "setsid", "-f", "steam", "steam://$action/$id" });
326 testShellIteratorOk( 326 try testShellIteratorOk(
327 \\xargs -I% rg --no-heading --no-line-number --only-matching 327 \\xargs -I% rg --no-heading --no-line-number --only-matching
328 \\ --case-sensitive --multiline --text --byte-offset '(?-u)%' $@ 328 \\ --case-sensitive --multiline --text --byte-offset '(?-u)%' $@
329 \\ 329 \\
330 , 0, &[_][]const u8{ 330 , 0, &.{
331 "xargs", "-I%", "rg", "--no-heading", 331 "xargs", "-I%", "rg", "--no-heading",
332 "--no-line-number", "--only-matching", "--case-sensitive", "--multiline", 332 "--no-line-number", "--only-matching", "--case-sensitive", "--multiline",
333 "--text", "--byte-offset", "(?-u)%", "$@", 333 "--text", "--byte-offset", "(?-u)%", "$@",
334 }); 334 });
335 335
336 testShellIteratorErr("'a", error.QuoteNotClosed); 336 try testShellIteratorErr("'a", error.QuoteNotClosed);
337 testShellIteratorErr("'a\\", error.QuoteNotClosed); 337 try testShellIteratorErr("'a\\", error.QuoteNotClosed);
338 testShellIteratorErr("\"a", error.QuoteNotClosed); 338 try testShellIteratorErr("\"a", error.QuoteNotClosed);
339 testShellIteratorErr("\"a\\", error.QuoteNotClosed); 339 try testShellIteratorErr("\"a\\", error.QuoteNotClosed);
340 testShellIteratorErr("a\\", error.DanglingEscape); 340 try testShellIteratorErr("a\\", error.DanglingEscape);
341} 341}
diff --git a/clap/comptime.zig b/clap/comptime.zig
index 122ff16..7808f52 100644
--- a/clap/comptime.zig
+++ b/clap/comptime.zig
@@ -14,7 +14,7 @@ pub fn ComptimeClap(
14 var flags: usize = 0; 14 var flags: usize = 0;
15 var single_options: usize = 0; 15 var single_options: usize = 0;
16 var multi_options: usize = 0; 16 var multi_options: usize = 0;
17 var converted_params: []const clap.Param(usize) = &[_]clap.Param(usize){}; 17 var converted_params: []const clap.Param(usize) = &.{};
18 for (params) |param| { 18 for (params) |param| {
19 var index: usize = 0; 19 var index: usize = 0;
20 if (param.names.long != null or param.names.short != null) { 20 if (param.names.long != null or param.names.short != null) {
@@ -27,18 +27,18 @@ pub fn ComptimeClap(
27 ptr.* += 1; 27 ptr.* += 1;
28 } 28 }
29 29
30 const converted = clap.Param(usize){ 30 converted_params = converted_params ++ [_]clap.Param(usize){.{
31 .id = index, 31 .id = index,
32 .names = param.names, 32 .names = param.names,
33 .takes_value = param.takes_value, 33 .takes_value = param.takes_value,
34 }; 34 }};
35 converted_params = converted_params ++ [_]clap.Param(usize){converted};
36 } 35 }
37 36
38 return struct { 37 return struct {
39 single_options: [single_options]?[]const u8,
40 multi_options: [multi_options][]const []const u8, 38 multi_options: [multi_options][]const []const u8,
41 flags: [flags]bool, 39 single_options: [single_options][]const u8,
40 single_options_is_set: std.PackedIntArray(u1, single_options),
41 flags: std.PackedIntArray(u1, flags),
42 pos: []const []const u8, 42 pos: []const []const u8,
43 allocator: *mem.Allocator, 43 allocator: *mem.Allocator,
44 44
@@ -52,9 +52,12 @@ pub fn ComptimeClap(
52 var pos = std.ArrayList([]const u8).init(allocator); 52 var pos = std.ArrayList([]const u8).init(allocator);
53 53
54 var res = @This(){ 54 var res = @This(){
55 .single_options = [_]?[]const u8{null} ** single_options, 55 .multi_options = .{undefined} ** multi_options,
56 .multi_options = [_][]const []const u8{undefined} ** multi_options, 56 .single_options = .{undefined} ** single_options,
57 .flags = [_]bool{false} ** flags, 57 .single_options_is_set = std.PackedIntArray(u1, single_options).init(
58 .{0} ** single_options,
59 ),
60 .flags = std.PackedIntArray(u1, flags).init(.{0} ** flags),
58 .pos = undefined, 61 .pos = undefined,
59 .allocator = allocator, 62 .allocator = allocator,
60 }; 63 };
@@ -69,16 +72,18 @@ pub fn ComptimeClap(
69 try pos.append(arg.value.?); 72 try pos.append(arg.value.?);
70 } else if (param.takes_value == .one) { 73 } else if (param.takes_value == .one) {
71 debug.assert(res.single_options.len != 0); 74 debug.assert(res.single_options.len != 0);
72 if (res.single_options.len != 0) 75 if (res.single_options.len != 0) {
73 res.single_options[param.id] = arg.value.?; 76 res.single_options[param.id] = arg.value.?;
77 res.single_options_is_set.set(param.id, 1);
78 }
74 } else if (param.takes_value == .many) { 79 } else if (param.takes_value == .many) {
75 debug.assert(multis.len != 0); 80 debug.assert(multis.len != 0);
76 if (multis.len != 0) 81 if (multis.len != 0)
77 try multis[param.id].append(arg.value.?); 82 try multis[param.id].append(arg.value.?);
78 } else { 83 } else {
79 debug.assert(res.flags.len != 0); 84 debug.assert(res.flags.len() != 0);
80 if (res.flags.len != 0) 85 if (res.flags.len() != 0)
81 res.flags[param.id] = true; 86 res.flags.set(param.id, 1);
82 } 87 }
83 } 88 }
84 89
@@ -100,7 +105,7 @@ pub fn ComptimeClap(
100 if (param.takes_value != .none) 105 if (param.takes_value != .none)
101 @compileError(name ++ " is an option and not a flag."); 106 @compileError(name ++ " is an option and not a flag.");
102 107
103 return parser.flags[param.id]; 108 return parser.flags.get(param.id) != 0;
104 } 109 }
105 110
106 pub fn option(parser: @This(), comptime name: []const u8) ?[]const u8 { 111 pub fn option(parser: @This(), comptime name: []const u8) ?[]const u8 {
@@ -109,6 +114,8 @@ pub fn ComptimeClap(
109 @compileError(name ++ " is a flag and not an option."); 114 @compileError(name ++ " is a flag and not an option.");
110 if (param.takes_value == .many) 115 if (param.takes_value == .many)
111 @compileError(name ++ " takes many options, not one."); 116 @compileError(name ++ " takes many options, not one.");
117 if (parser.single_options_is_set.get(param.id) == 0)
118 return null;
112 return parser.single_options[param.id]; 119 return parser.single_options[param.id];
113 } 120 }
114 121
@@ -146,30 +153,37 @@ pub fn ComptimeClap(
146} 153}
147 154
148test "" { 155test "" {
149 const Clap = ComptimeClap(clap.Help, comptime &[_]clap.Param(clap.Help){ 156 const Clap = ComptimeClap(clap.Help, comptime &.{
150 clap.parseParam("-a, --aa ") catch unreachable, 157 clap.parseParam("-a, --aa") catch unreachable,
151 clap.parseParam("-b, --bb ") catch unreachable, 158 clap.parseParam("-b, --bb") catch unreachable,
152 clap.parseParam("-c, --cc <V>") catch unreachable, 159 clap.parseParam("-c, --cc <V>") catch unreachable,
153 clap.parseParam("-d, --dd <V>...") catch unreachable, 160 clap.parseParam("-d, --dd <V>...") catch unreachable,
154 clap.parseParam("<P>") catch unreachable, 161 clap.parseParam("<P>") catch unreachable,
155 }); 162 });
156 163
157 var iter = clap.args.SliceIterator{ 164 var iter = clap.args.SliceIterator{
158 .args = &[_][]const u8{ 165 .args = &.{
159 "-a", "-c", "0", "something", "-d", "a", "--dd", "b", 166 "-a", "-c", "0", "something", "-d", "a", "--dd", "b",
160 }, 167 },
161 }; 168 };
162 var args = try Clap.parse(&iter, .{ .allocator = testing.allocator }); 169 var args = try Clap.parse(&iter, .{ .allocator = testing.allocator });
163 defer args.deinit(); 170 defer args.deinit();
164 171
165 testing.expect(args.flag("-a")); 172 try testing.expect(args.flag("-a"));
166 testing.expect(args.flag("--aa")); 173 try testing.expect(args.flag("--aa"));
167 testing.expect(!args.flag("-b")); 174 try testing.expect(!args.flag("-b"));
168 testing.expect(!args.flag("--bb")); 175 try testing.expect(!args.flag("--bb"));
169 testing.expectEqualStrings("0", args.option("-c").?); 176 try testing.expectEqualStrings("0", args.option("-c").?);
170 testing.expectEqualStrings("0", args.option("--cc").?); 177 try testing.expectEqualStrings("0", args.option("--cc").?);
171 testing.expectEqual(@as(usize, 1), args.positionals().len); 178 try testing.expectEqual(@as(usize, 1), args.positionals().len);
172 testing.expectEqualStrings("something", args.positionals()[0]); 179 try testing.expectEqualStrings("something", args.positionals()[0]);
173 testing.expectEqualSlices([]const u8, &[_][]const u8{ "a", "b" }, args.options("-d")); 180 try testing.expectEqualSlices([]const u8, &.{ "a", "b" }, args.options("-d"));
174 testing.expectEqualSlices([]const u8, &[_][]const u8{ "a", "b" }, args.options("--dd")); 181 try testing.expectEqualSlices([]const u8, &.{ "a", "b" }, args.options("--dd"));
182}
183
184test "empty" {
185 const Clap = ComptimeClap(clap.Help, comptime &.{});
186 var iter = clap.args.SliceIterator{ .args = &.{} };
187 var args = try Clap.parse(&iter, .{ .allocator = testing.allocator });
188 defer args.deinit();
175} 189}
diff --git a/clap/streaming.zig b/clap/streaming.zig
index a2a0ca8..e2f1311 100644
--- a/clap/streaming.zig
+++ b/clap/streaming.zig
@@ -203,7 +203,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
203 }; 203 };
204} 204}
205 205
206fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, results: []const Arg(u8)) void { 206fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, results: []const Arg(u8)) !void {
207 var iter = args.SliceIterator{ .args = args_strings }; 207 var iter = args.SliceIterator{ .args = args_strings };
208 var c = StreamingClap(u8, args.SliceIterator){ 208 var c = StreamingClap(u8, args.SliceIterator){
209 .params = params, 209 .params = params,
@@ -211,22 +211,22 @@ fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, r
211 }; 211 };
212 212
213 for (results) |res| { 213 for (results) |res| {
214 const arg = (c.next() catch unreachable) orelse unreachable; 214 const arg = (try c.next()) orelse return error.TestFailed;
215 testing.expectEqual(res.param, arg.param); 215 try testing.expectEqual(res.param, arg.param);
216 const expected_value = res.value orelse { 216 const expected_value = res.value orelse {
217 testing.expectEqual(@as(@TypeOf(arg.value), null), arg.value); 217 try testing.expectEqual(@as(@TypeOf(arg.value), null), arg.value);
218 continue; 218 continue;
219 }; 219 };
220 const actual_value = arg.value orelse unreachable; 220 const actual_value = arg.value orelse return error.TestFailed;
221 testing.expectEqualSlices(u8, expected_value, actual_value); 221 try testing.expectEqualSlices(u8, expected_value, actual_value);
222 } 222 }
223 223
224 if (c.next() catch unreachable) |_| 224 if (try c.next()) |_|
225 unreachable; 225 return error.TestFailed;
226} 226}
227 227
228fn 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 {
229 var diag = clap.Diagnostic{}; 229 var diag: clap.Diagnostic = undefined;
230 var iter = args.SliceIterator{ .args = args_strings }; 230 var iter = args.SliceIterator{ .args = args_strings };
231 var c = StreamingClap(u8, args.SliceIterator){ 231 var c = StreamingClap(u8, args.SliceIterator){
232 .params = params, 232 .params = params,
@@ -236,12 +236,12 @@ fn testErr(params: []const clap.Param(u8), args_strings: []const []const u8, exp
236 while (c.next() catch |err| { 236 while (c.next() catch |err| {
237 var buf: [1024]u8 = undefined; 237 var buf: [1024]u8 = undefined;
238 var fbs = io.fixedBufferStream(&buf); 238 var fbs = io.fixedBufferStream(&buf);
239 diag.report(fbs.writer(), err) catch unreachable; 239 diag.report(fbs.writer(), err) catch return error.TestFailed;
240 testing.expectEqualStrings(expected, fbs.getWritten()); 240 try testing.expectEqualStrings(expected, fbs.getWritten());
241 return; 241 return;
242 }) |_| {} 242 }) |_| {}
243 243
244 testing.expect(false); 244 try testing.expect(false);
245} 245}
246 246
247test "short params" { 247test "short params" {
@@ -265,14 +265,14 @@ test "short params" {
265 const c = &params[2]; 265 const c = &params[2];
266 const d = &params[3]; 266 const d = &params[3];
267 267
268 testNoErr( 268 try testNoErr(
269 &params, 269 &params,
270 &[_][]const u8{ 270 &.{
271 "-a", "-b", "-ab", "-ba", 271 "-a", "-b", "-ab", "-ba",
272 "-c", "0", "-c=0", "-ac", 272 "-c", "0", "-c=0", "-ac",
273 "0", "-ac=0", "-d=0", 273 "0", "-ac=0", "-d=0",
274 }, 274 },
275 &[_]Arg(u8){ 275 &.{
276 .{ .param = a }, 276 .{ .param = a },
277 .{ .param = b }, 277 .{ .param = b },
278 .{ .param = a }, 278 .{ .param = a },
@@ -311,14 +311,14 @@ test "long params" {
311 const cc = &params[2]; 311 const cc = &params[2];
312 const dd = &params[3]; 312 const dd = &params[3];
313 313
314 testNoErr( 314 try testNoErr(
315 &params, 315 &params,
316 &[_][]const u8{ 316 &.{
317 "--aa", "--bb", 317 "--aa", "--bb",
318 "--cc", "0", 318 "--cc", "0",
319 "--cc=0", "--dd=0", 319 "--cc=0", "--dd=0",
320 }, 320 },
321 &[_]Arg(u8){ 321 &.{
322 .{ .param = aa }, 322 .{ .param = aa },
323 .{ .param = bb }, 323 .{ .param = bb },
324 .{ .param = cc, .value = "0" }, 324 .{ .param = cc, .value = "0" },
@@ -334,10 +334,10 @@ test "positional params" {
334 .takes_value = .one, 334 .takes_value = .one,
335 }}; 335 }};
336 336
337 testNoErr( 337 try testNoErr(
338 &params, 338 &params,
339 &[_][]const u8{ "aa", "bb" }, 339 &.{ "aa", "bb" },
340 &[_]Arg(u8){ 340 &.{
341 .{ .param = &params[0], .value = "aa" }, 341 .{ .param = &params[0], .value = "aa" },
342 .{ .param = &params[0], .value = "bb" }, 342 .{ .param = &params[0], .value = "bb" },
343 }, 343 },
@@ -367,16 +367,16 @@ test "all params" {
367 const cc = &params[2]; 367 const cc = &params[2];
368 const positional = &params[3]; 368 const positional = &params[3];
369 369
370 testNoErr( 370 try testNoErr(
371 &params, 371 &params,
372 &[_][]const u8{ 372 &.{
373 "-a", "-b", "-ab", "-ba", 373 "-a", "-b", "-ab", "-ba",
374 "-c", "0", "-c=0", "-ac", 374 "-c", "0", "-c=0", "-ac",
375 "0", "-ac=0", "--aa", "--bb", 375 "0", "-ac=0", "--aa", "--bb",
376 "--cc", "0", "--cc=0", "something", 376 "--cc", "0", "--cc=0", "something",
377 "-", "--", "--cc=0", "-a", 377 "-", "--", "--cc=0", "-a",
378 }, 378 },
379 &[_]Arg(u8){ 379 &.{
380 .{ .param = aa }, 380 .{ .param = aa },
381 .{ .param = bb }, 381 .{ .param = bb },
382 .{ .param = aa }, 382 .{ .param = aa },
@@ -413,12 +413,12 @@ test "errors" {
413 .takes_value = .one, 413 .takes_value = .one,
414 }, 414 },
415 }; 415 };
416 testErr(&params, &[_][]const u8{"q"}, "Invalid argument 'q'\n"); 416 try testErr(&params, &.{"q"}, "Invalid argument 'q'\n");
417 testErr(&params, &[_][]const u8{"-q"}, "Invalid argument '-q'\n"); 417 try testErr(&params, &.{"-q"}, "Invalid argument '-q'\n");
418 testErr(&params, &[_][]const u8{"--q"}, "Invalid argument '--q'\n"); 418 try testErr(&params, &.{"--q"}, "Invalid argument '--q'\n");
419 testErr(&params, &[_][]const u8{"--q=1"}, "Invalid argument '--q'\n"); 419 try testErr(&params, &.{"--q=1"}, "Invalid argument '--q'\n");
420 testErr(&params, &[_][]const u8{"-a=1"}, "The argument '-a' does not take a value\n"); 420 try testErr(&params, &.{"-a=1"}, "The argument '-a' does not take a value\n");
421 testErr(&params, &[_][]const u8{"--aa=1"}, "The argument '--aa' does not take a value\n"); 421 try testErr(&params, &.{"--aa=1"}, "The argument '--aa' does not take a value\n");
422 testErr(&params, &[_][]const u8{"-c"}, "The argument '-c' requires a value but none was supplied\n"); 422 try testErr(&params, &.{"-c"}, "The argument '-c' requires a value but none was supplied\n");
423 testErr(&params, &[_][]const u8{"--cc"}, "The argument '--cc' requires a value but none was supplied\n"); 423 try testErr(&params, &.{"--cc"}, "The argument '--cc' requires a value but none was supplied\n");
424} 424}
diff --git a/example/README.md.template b/example/README.md.template
index 530cea4..74a2f1d 100644
--- a/example/README.md.template
+++ b/example/README.md.template
@@ -25,7 +25,7 @@ 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
28{} 28{s}
29``` 29```
30 30
31The data structure returned has lookup speed on par with array access (`arr[i]`) and validates 31The data structure returned has lookup speed on par with array access (`arr[i]`) and validates
@@ -33,7 +33,7 @@ that the strings you pass to `option`, `options` and `flag` are actually paramet
33program can take: 33program can take:
34 34
35```zig 35```zig
36{} 36{s}
37``` 37```
38 38
39``` 39```
@@ -58,7 +58,7 @@ The `StreamingClap` is the base of all the other parsers. It's a streaming parse
58`args.Iterator` to provide it with arguments lazily. 58`args.Iterator` to provide it with arguments lazily.
59 59
60```zig 60```zig
61{} 61{s}
62``` 62```
63 63
64Currently, this parse is the only parser that allow an array of `Param` tha 64Currently, this parse is the only parser that allow an array of `Param` tha
@@ -70,7 +70,7 @@ The `help`, `helpEx` and `helpFull` are functions for printing a simple list of
70program can take. 70program can take.
71 71
72```zig 72```zig
73{} 73{s}
74``` 74```
75 75
76``` 76```
@@ -93,7 +93,7 @@ The `usage`, `usageEx` and `usageFull` are functions for printing a small abbrev
93of the help message. 93of the help message.
94 94
95```zig 95```zig
96{} 96{s}
97``` 97```
98 98
99``` 99```
diff --git a/example/help.zig b/example/help.zig
index 3cf9e42..d90373a 100644
--- a/example/help.zig
+++ b/example/help.zig
@@ -7,7 +7,7 @@ pub fn main() !void {
7 // help message for any Param, but it is more verbose to call. 7 // help message for any Param, but it is more verbose to call.
8 try clap.help( 8 try clap.help(
9 std.io.getStdErr().writer(), 9 std.io.getStdErr().writer(),
10 comptime &[_]clap.Param(clap.Help){ 10 comptime &.{
11 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, 11 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable,
12 clap.parseParam("-v, --version Output version information and exit.") catch unreachable, 12 clap.parseParam("-v, --version Output version information and exit.") catch unreachable,
13 }, 13 },
diff --git a/example/simple-ex.zig b/example/simple-ex.zig
index 88598aa..838b9c2 100644
--- a/example/simple-ex.zig
+++ b/example/simple-ex.zig
@@ -30,11 +30,7 @@ pub fn main() !void {
30 .diagnostic = &diag, 30 .diagnostic = &diag,
31 }) catch |err| { 31 }) catch |err| {
32 // Report useful error and exit 32 // Report useful error and exit
33<<<<<<< HEAD
34 diag.report(std.io.getStdErr().writer(), err) catch {};
35=======
36 diag.report(io.getStdErr().writer(), err) catch {}; 33 diag.report(io.getStdErr().writer(), err) catch {};
37>>>>>>> master
38 return err; 34 return err;
39 }; 35 };
40 defer args.deinit(); 36 defer args.deinit();
@@ -42,9 +38,9 @@ pub fn main() !void {
42 if (args.flag("--help")) 38 if (args.flag("--help"))
43 debug.warn("--help\n", .{}); 39 debug.warn("--help\n", .{});
44 if (args.option("--number")) |n| 40 if (args.option("--number")) |n|
45 debug.warn("--number = {}\n", .{n}); 41 debug.warn("--number = {s}\n", .{n});
46 for (args.options("--string")) |s| 42 for (args.options("--string")) |s|
47 debug.warn("--string = {}\n", .{s}); 43 debug.warn("--string = {s}\n", .{s});
48 for (args.positionals()) |pos| 44 for (args.positionals()) |pos|
49 debug.warn("{}\n", .{pos}); 45 debug.warn("{s}\n", .{pos});
50} 46}
diff --git a/example/simple.zig b/example/simple.zig
index 69473fa..78a963c 100644
--- a/example/simple.zig
+++ b/example/simple.zig
@@ -28,9 +28,9 @@ pub fn main() !void {
28 if (args.flag("--help")) 28 if (args.flag("--help"))
29 debug.warn("--help\n", .{}); 29 debug.warn("--help\n", .{});
30 if (args.option("--number")) |n| 30 if (args.option("--number")) |n|
31 debug.warn("--number = {}\n", .{n}); 31 debug.warn("--number = {s}\n", .{n});
32 for (args.options("--string")) |s| 32 for (args.options("--string")) |s|
33 debug.warn("--string = {}\n", .{s}); 33 debug.warn("--string = {s}\n", .{s});
34 for (args.positionals()) |pos| 34 for (args.positionals()) |pos|
35 debug.warn("{}\n", .{pos}); 35 debug.warn("{s}\n", .{pos});
36} 36}
diff --git a/example/streaming-clap.zig b/example/streaming-clap.zig
index 32d44c4..5f7f219 100644
--- a/example/streaming-clap.zig
+++ b/example/streaming-clap.zig
@@ -39,22 +39,18 @@ pub fn main() !void {
39 // Because we use a streaming parser, we have to consume each argument parsed individually. 39 // Because we use a streaming parser, we have to consume each argument parsed individually.
40 while (parser.next() catch |err| { 40 while (parser.next() catch |err| {
41 // Report useful error and exit 41 // Report useful error and exit
42<<<<<<< HEAD
43 diag.report(std.io.getStdErr().writer(), err) catch {};
44=======
45 diag.report(io.getStdErr().writer(), err) catch {}; 42 diag.report(io.getStdErr().writer(), err) catch {};
46>>>>>>> master
47 return err; 43 return err;
48 }) |arg| { 44 }) |arg| {
49 // arg.param will point to the parameter which matched the argument. 45 // arg.param will point to the parameter which matched the argument.
50 switch (arg.param.id) { 46 switch (arg.param.id) {
51 'h' => debug.warn("Help!\n", .{}), 47 'h' => debug.warn("Help!\n", .{}),
52 'n' => debug.warn("--number = {}\n", .{arg.value.?}), 48 'n' => debug.warn("--number = {s}\n", .{arg.value.?}),
53 49
54 // arg.value == null, if arg.param.takes_value == false. 50 // arg.value == null, if arg.param.takes_value == .none.
55 // Otherwise, arg.value is the value passed with the argument, such as "-a=10" 51 // Otherwise, arg.value is the value passed with the argument, such as "-a=10"
56 // or "-a 10". 52 // or "-a 10".
57 'f' => debug.warn("{}\n", .{arg.value.?}), 53 'f' => debug.warn("{s}\n", .{arg.value.?}),
58 else => unreachable, 54 else => unreachable,
59 } 55 }
60 } 56 }
diff --git a/example/usage.zig b/example/usage.zig
index e044f1d..7956570 100644
--- a/example/usage.zig
+++ b/example/usage.zig
@@ -7,7 +7,7 @@ pub fn main() !void {
7 // usage message for any Param, but it is more verbose to call. 7 // usage message for any Param, but it is more verbose to call.
8 try clap.usage( 8 try clap.usage(
9 std.io.getStdErr().writer(), 9 std.io.getStdErr().writer(),
10 comptime &[_]clap.Param(clap.Help){ 10 comptime &.{
11 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, 11 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable,
12 clap.parseParam("-v, --version Output version information and exit.") catch unreachable, 12 clap.parseParam("-v, --version Output version information and exit.") catch unreachable,
13 clap.parseParam(" --value <N> Output version information and exit.") catch unreachable, 13 clap.parseParam(" --value <N> Output version information and exit.") catch unreachable,