summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--README.md38
-rw-r--r--build.zig4
-rw-r--r--clap.zig211
-rw-r--r--clap/comptime.zig20
-rw-r--r--clap/streaming.zig184
-rw-r--r--example/help.zig7
-rw-r--r--example/simple-error.zig4
-rw-r--r--example/simple-ex.zig3
-rw-r--r--example/simple.zig3
-rw-r--r--example/streaming-clap.zig18
-rw-r--r--example/usage.zig6
11 files changed, 194 insertions, 304 deletions
diff --git a/README.md b/README.md
index ad9f026..398a088 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,7 @@ const clap = @import("clap");
29const std = @import("std"); 29const std = @import("std");
30 30
31const debug = std.debug; 31const debug = std.debug;
32const io = std.io;
32 33
33pub fn main() !void { 34pub fn main() !void {
34 // First we specify what parameters our program can take. 35 // First we specify what parameters our program can take.
@@ -46,7 +47,7 @@ pub fn main() !void {
46 var diag = clap.Diagnostic{}; 47 var diag = clap.Diagnostic{};
47 var args = clap.parse(clap.Help, &params, .{ .diagnostic = &diag }) catch |err| { 48 var args = clap.parse(clap.Help, &params, .{ .diagnostic = &diag }) catch |err| {
48 // Report useful error and exit 49 // Report useful error and exit
49 diag.report(std.io.getStdErr().outStream(), err) catch {}; 50 diag.report(io.getStdErr().writer(), err) catch {};
50 return err; 51 return err;
51 }; 52 };
52 defer args.deinit(); 53 defer args.deinit();
@@ -68,15 +69,15 @@ that the strings you pass to `option`, `options` and `flag` are actually paramet
68program can take: 69program can take:
69 70
70```zig 71```zig
71const std = @import("std");
72const clap = @import("clap"); 72const clap = @import("clap");
73const std = @import("std");
73 74
74pub fn main() !void { 75pub fn main() !void {
75 const params = comptime [_]clap.Param(clap.Help){ 76 const params = comptime [_]clap.Param(clap.Help){
76 clap.parseParam("-h, --help Display this help and exit.") catch unreachable, 77 clap.parseParam("-h, --help Display this help and exit.") catch unreachable,
77 }; 78 };
78 79
79 var args = try clap.parse(clap.Help, &params, std.heap.direct_allocator, null); 80 var args = try clap.parse(clap.Help, &params, .{});
80 defer args.deinit(); 81 defer args.deinit();
81 82
82 _ = args.flag("--helps"); 83 _ = args.flag("--helps");
@@ -110,25 +111,23 @@ const clap = @import("clap");
110const std = @import("std"); 111const std = @import("std");
111 112
112const debug = std.debug; 113const debug = std.debug;
114const io = std.io;
113 115
114pub fn main() !void { 116pub fn main() !void {
115 const allocator = std.heap.page_allocator; 117 const allocator = std.heap.page_allocator;
116 118
117 // First we specify what parameters our program can take. 119 // First we specify what parameters our program can take.
118 const params = [_]clap.Param(u8){ 120 const params = [_]clap.Param(u8){
119 clap.Param(u8){ 121 .{
120 .id = 'h', 122 .id = 'h',
121 .names = clap.Names{ .short = 'h', .long = "help" }, 123 .names = .{ .short = 'h', .long = "help" },
122 }, 124 },
123 clap.Param(u8){ 125 .{
124 .id = 'n', 126 .id = 'n',
125 .names = clap.Names{ .short = 'n', .long = "number" }, 127 .names = .{ .short = 'n', .long = "number" },
126 .takes_value = .One, 128 .takes_value = .one,
127 },
128 clap.Param(u8){
129 .id = 'f',
130 .takes_value = .One,
131 }, 129 },
130 .{ .id = 'f', .takes_value = .one },
132 }; 131 };
133 132
134 // We then initialize an argument iterator. We will use the OsIterator as it nicely 133 // We then initialize an argument iterator. We will use the OsIterator as it nicely
@@ -149,7 +148,7 @@ pub fn main() !void {
149 // Because we use a streaming parser, we have to consume each argument parsed individually. 148 // Because we use a streaming parser, we have to consume each argument parsed individually.
150 while (parser.next() catch |err| { 149 while (parser.next() catch |err| {
151 // Report useful error and exit 150 // Report useful error and exit
152 diag.report(std.io.getStdErr().outStream(), err) catch {}; 151 diag.report(io.getStdErr().writer(), err) catch {};
153 return err; 152 return err;
154 }) |arg| { 153 }) |arg| {
155 // arg.param will point to the parameter which matched the argument. 154 // arg.param will point to the parameter which matched the argument.
@@ -177,18 +176,15 @@ The `help`, `helpEx` and `helpFull` are functions for printing a simple list of
177program can take. 176program can take.
178 177
179```zig 178```zig
180const std = @import("std");
181const clap = @import("clap"); 179const clap = @import("clap");
180const std = @import("std");
182 181
183pub fn main() !void { 182pub fn main() !void {
184 const stderr_file = std.io.getStdErr();
185 var stderr_out_stream = stderr_file.outStream();
186
187 // clap.help is a function that can print a simple help message, given a 183 // clap.help is a function that can print a simple help message, given a
188 // slice of Param(Help). There is also a helpEx, which can print a 184 // slice of Param(Help). There is also a helpEx, which can print a
189 // 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.
190 try clap.help( 186 try clap.help(
191 stderr_out_stream, 187 std.io.getStdErr().writer(),
192 comptime &[_]clap.Param(clap.Help){ 188 comptime &[_]clap.Param(clap.Help){
193 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, 189 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable,
194 clap.parseParam("-v, --version Output version information and exit.") catch unreachable, 190 clap.parseParam("-v, --version Output version information and exit.") catch unreachable,
@@ -218,17 +214,15 @@ The `usage`, `usageEx` and `usageFull` are functions for printing a small abbrev
218of the help message. 214of the help message.
219 215
220```zig 216```zig
221const std = @import("std");
222const clap = @import("clap"); 217const clap = @import("clap");
218const std = @import("std");
223 219
224pub fn main() !void { 220pub fn main() !void {
225 const stderr = std.io.getStdErr().outStream();
226
227 // clap.usage is a function that can print a simple usage message, given a 221 // clap.usage is a function that can print a simple usage message, given a
228 // slice of Param(Help). There is also a usageEx, which can print a 222 // slice of Param(Help). There is also a usageEx, which can print a
229 // 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.
230 try clap.usage( 224 try clap.usage(
231 stderr, 225 std.io.getStdErr().writer(),
232 comptime &[_]clap.Param(clap.Help){ 226 comptime &[_]clap.Param(clap.Help){
233 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, 227 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable,
234 clap.parseParam("-v, --version Output version information and exit.") catch unreachable, 228 clap.parseParam("-v, --version Output version information and exit.") catch unreachable,
diff --git a/build.zig b/build.zig
index ef67a5f..bef10be 100644
--- a/build.zig
+++ b/build.zig
@@ -1,8 +1,8 @@
1const builtin = @import("builtin"); 1const builtin = @import("builtin");
2const std = @import("std"); 2const std = @import("std");
3 3
4const Mode = builtin.Mode;
5const Builder = std.build.Builder; 4const Builder = std.build.Builder;
5const Mode = builtin.Mode;
6 6
7pub fn build(b: *Builder) void { 7pub fn build(b: *Builder) void {
8 const mode = b.standardReleaseOptions(); 8 const mode = b.standardReleaseOptions();
@@ -58,7 +58,7 @@ fn readMeStep(b: *Builder) *std.build.Step {
58 fn make(step: *std.build.Step) anyerror!void { 58 fn make(step: *std.build.Step) anyerror!void {
59 @setEvalBranchQuota(10000); 59 @setEvalBranchQuota(10000);
60 const file = try std.fs.cwd().createFile("README.md", .{}); 60 const file = try std.fs.cwd().createFile("README.md", .{});
61 const stream = &file.outStream(); 61 const stream = file.writer();
62 try stream.print(@embedFile("example/README.md.template"), .{ 62 try stream.print(@embedFile("example/README.md.template"), .{
63 @embedFile("example/simple.zig"), 63 @embedFile("example/simple.zig"),
64 @embedFile("example/simple-error.zig"), 64 @embedFile("example/simple-error.zig"),
diff --git a/clap.zig b/clap.zig
index b31cd1d..49d0670 100644
--- a/clap.zig
+++ b/clap.zig
@@ -26,9 +26,9 @@ pub const Names = struct {
26 26
27/// Whether a param takes no value (a flag), one value, or can be specified multiple times. 27/// Whether a param takes no value (a flag), one value, or can be specified multiple times.
28pub const Values = enum { 28pub const Values = enum {
29 None, 29 none,
30 One, 30 one,
31 Many, 31 many,
32}; 32};
33 33
34/// Represents a parameter for the command line. 34/// Represents a parameter for the command line.
@@ -56,7 +56,7 @@ pub fn Param(comptime Id: type) type {
56 return struct { 56 return struct {
57 id: Id = Id{}, 57 id: Id = Id{},
58 names: Names = Names{}, 58 names: Names = Names{},
59 takes_value: Values = .None, 59 takes_value: Values = .none,
60 }; 60 };
61} 61}
62 62
@@ -110,8 +110,8 @@ fn parseParamRest(line: []const u8) Param(Help) {
110 const len = mem.indexOfScalar(u8, line, '>') orelse break :blk; 110 const len = mem.indexOfScalar(u8, line, '>') orelse break :blk;
111 const takes_many = mem.startsWith(u8, line[len + 1 ..], "..."); 111 const takes_many = mem.startsWith(u8, line[len + 1 ..], "...");
112 const help_start = len + 1 + @as(usize, 3) * @boolToInt(takes_many); 112 const help_start = len + 1 + @as(usize, 3) * @boolToInt(takes_many);
113 return Param(Help){ 113 return .{
114 .takes_value = if (takes_many) .Many else .One, 114 .takes_value = if (takes_many) .many else .one,
115 .id = .{ 115 .id = .{
116 .msg = mem.trim(u8, line[help_start..], " \t"), 116 .msg = mem.trim(u8, line[help_start..], " \t"),
117 .value = line[1..len], 117 .value = line[1..len],
@@ -119,7 +119,7 @@ fn parseParamRest(line: []const u8) Param(Help) {
119 }; 119 };
120 } 120 }
121 121
122 return Param(Help){ .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 {
@@ -136,114 +136,60 @@ fn expectParam(expect: Param(Help), actual: Param(Help)) void {
136 136
137test "parseParam" { 137test "parseParam" {
138 expectParam(Param(Help){ 138 expectParam(Param(Help){
139 .id = Help{ 139 .id = .{ .msg = "Help text", .value = "value" },
140 .msg = "Help text", 140 .names = .{ .short = 's', .long = "long" },
141 .value = "value", 141 .takes_value = .one,
142 },
143 .names = Names{
144 .short = 's',
145 .long = "long",
146 },
147 .takes_value = .One,
148 }, try parseParam("-s, --long <value> Help text")); 142 }, try parseParam("-s, --long <value> Help text"));
143
149 expectParam(Param(Help){ 144 expectParam(Param(Help){
150 .id = Help{ 145 .id = .{ .msg = "Help text", .value = "value" },
151 .msg = "Help text", 146 .names = .{ .short = 's', .long = "long" },
152 .value = "value", 147 .takes_value = .many,
153 },
154 .names = Names{
155 .short = 's',
156 .long = "long",
157 },
158 .takes_value = .Many,
159 }, try parseParam("-s, --long <value>... Help text")); 148 }, try parseParam("-s, --long <value>... Help text"));
149
160 expectParam(Param(Help){ 150 expectParam(Param(Help){
161 .id = Help{ 151 .id = .{ .msg = "Help text", .value = "value" },
162 .msg = "Help text", 152 .names = .{ .long = "long" },
163 .value = "value", 153 .takes_value = .one,
164 },
165 .names = Names{
166 .short = null,
167 .long = "long",
168 },
169 .takes_value = .One,
170 }, try parseParam("--long <value> Help text")); 154 }, try parseParam("--long <value> Help text"));
155
171 expectParam(Param(Help){ 156 expectParam(Param(Help){
172 .id = Help{ 157 .id = .{ .msg = "Help text", .value = "value" },
173 .msg = "Help text", 158 .names = .{ .short = 's' },
174 .value = "value", 159 .takes_value = .one,
175 },
176 .names = Names{
177 .short = 's',
178 .long = null,
179 },
180 .takes_value = .One,
181 }, try parseParam("-s <value> Help text")); 160 }, try parseParam("-s <value> Help text"));
161
182 expectParam(Param(Help){ 162 expectParam(Param(Help){
183 .id = Help{ 163 .id = .{ .msg = "Help text" },
184 .msg = "Help text", 164 .names = .{ .short = 's', .long = "long" },
185 .value = "",
186 },
187 .names = Names{
188 .short = 's',
189 .long = "long",
190 },
191 .takes_value = .None,
192 }, try parseParam("-s, --long Help text")); 165 }, try parseParam("-s, --long Help text"));
166
193 expectParam(Param(Help){ 167 expectParam(Param(Help){
194 .id = Help{ 168 .id = .{ .msg = "Help text" },
195 .msg = "Help text", 169 .names = .{ .short = 's' },
196 .value = "",
197 },
198 .names = Names{
199 .short = 's',
200 .long = null,
201 },
202 .takes_value = .None,
203 }, try parseParam("-s Help text")); 170 }, try parseParam("-s Help text"));
171
204 expectParam(Param(Help){ 172 expectParam(Param(Help){
205 .id = Help{ 173 .id = .{ .msg = "Help text" },
206 .msg = "Help text", 174 .names = .{ .long = "long" },
207 .value = "",
208 },
209 .names = Names{
210 .short = null,
211 .long = "long",
212 },
213 .takes_value = .None,
214 }, try parseParam("--long Help text")); 175 }, try parseParam("--long Help text"));
176
215 expectParam(Param(Help){ 177 expectParam(Param(Help){
216 .id = Help{ 178 .id = .{ .msg = "Help text", .value = "A | B" },
217 .msg = "Help text", 179 .names = .{ .long = "long" },
218 .value = "A | B", 180 .takes_value = .one,
219 },
220 .names = Names{
221 .short = null,
222 .long = "long",
223 },
224 .takes_value = .One,
225 }, try parseParam("--long <A | B> Help text")); 181 }, try parseParam("--long <A | B> Help text"));
182
226 expectParam(Param(Help){ 183 expectParam(Param(Help){
227 .id = Help{ 184 .id = .{ .msg = "Help text", .value = "A" },
228 .msg = "Help text", 185 .names = .{},
229 .value = "A", 186 .takes_value = .one,
230 },
231 .names = Names{
232 .short = null,
233 .long = null,
234 },
235 .takes_value = .One,
236 }, try parseParam("<A> Help text")); 187 }, try parseParam("<A> Help text"));
188
237 expectParam(Param(Help){ 189 expectParam(Param(Help){
238 .id = Help{ 190 .id = .{ .msg = "Help text", .value = "A" },
239 .msg = "Help text", 191 .names = .{},
240 .value = "A", 192 .takes_value = .many,
241 },
242 .names = Names{
243 .short = null,
244 .long = null,
245 },
246 .takes_value = .Many,
247 }, try parseParam("<A>... Help text")); 193 }, try parseParam("<A>... Help text"));
248 194
249 testing.expectError(error.TrailingComma, parseParam("--long, Help")); 195 testing.expectError(error.TrailingComma, parseParam("--long, Help"));
@@ -284,7 +230,7 @@ pub const Diagnostic = struct {
284fn testDiag(diag: Diagnostic, err: anyerror, expected: []const u8) void { 230fn testDiag(diag: Diagnostic, err: anyerror, expected: []const u8) void {
285 var buf: [1024]u8 = undefined; 231 var buf: [1024]u8 = undefined;
286 var slice_stream = io.fixedBufferStream(&buf); 232 var slice_stream = io.fixedBufferStream(&buf);
287 diag.report(slice_stream.outStream(), err) catch unreachable; 233 diag.report(slice_stream.writer(), err) catch unreachable;
288 testing.expectEqualStrings(expected, slice_stream.getWritten()); 234 testing.expectEqualStrings(expected, slice_stream.getWritten());
289} 235}
290 236
@@ -392,10 +338,10 @@ pub fn helpFull(
392 const max_spacing = blk: { 338 const max_spacing = blk: {
393 var res: usize = 0; 339 var res: usize = 0;
394 for (params) |param| { 340 for (params) |param| {
395 var counting_stream = io.countingOutStream(io.null_out_stream); 341 var cs = io.countingOutStream(io.null_out_stream);
396 try printParam(counting_stream.outStream(), Id, param, Error, context, valueText); 342 try printParam(cs.writer(), Id, param, Error, context, valueText);
397 if (res < counting_stream.bytes_written) 343 if (res < cs.bytes_written)
398 res = @intCast(usize, counting_stream.bytes_written); 344 res = @intCast(usize, cs.bytes_written);
399 } 345 }
400 346
401 break :blk res; 347 break :blk res;
@@ -405,10 +351,10 @@ pub fn helpFull(
405 if (param.names.short == null and param.names.long == null) 351 if (param.names.short == null and param.names.long == null)
406 continue; 352 continue;
407 353
408 var counting_stream = io.countingOutStream(stream); 354 var cs = io.countingOutStream(stream);
409 try stream.print("\t", .{}); 355 try stream.print("\t", .{});
410 try printParam(counting_stream.outStream(), Id, param, Error, context, valueText); 356 try printParam(cs.writer(), Id, param, Error, context, valueText);
411 try stream.writeByteNTimes(' ', max_spacing - @intCast(usize, counting_stream.bytes_written)); 357 try stream.writeByteNTimes(' ', max_spacing - @intCast(usize, cs.bytes_written));
412 try stream.print("\t{}\n", .{try helpText(context, param)}); 358 try stream.print("\t{}\n", .{try helpText(context, param)});
413 } 359 }
414} 360}
@@ -437,9 +383,9 @@ fn printParam(
437 } 383 }
438 384
439 switch (param.takes_value) { 385 switch (param.takes_value) {
440 .None => {}, 386 .none => {},
441 .One => try stream.print(" <{}>", .{valueText(context, param)}), 387 .one => try stream.print(" <{}>", .{valueText(context, param)}),
442 .Many => try stream.print(" <{}>...", .{valueText(context, param)}), 388 .many => try stream.print(" <{}>...", .{valueText(context, param)}),
443 } 389 }
444} 390}
445 391
@@ -503,21 +449,16 @@ test "clap.help" {
503 449
504 @setEvalBranchQuota(10000); 450 @setEvalBranchQuota(10000);
505 try help( 451 try help(
506 slice_stream.outStream(), 452 slice_stream.writer(),
507 comptime &[_]Param(Help){ 453 comptime &[_]Param(Help){
508 parseParam("-a Short flag. ") catch unreachable, 454 parseParam("-a Short flag.") catch unreachable,
509 parseParam("-b <V1> Short option.") catch unreachable, 455 parseParam("-b <V1> Short option.") catch unreachable,
510 parseParam("--aa Long flag. ") catch unreachable, 456 parseParam("--aa Long flag.") catch unreachable,
511 parseParam("--bb <V2> Long option. ") catch unreachable, 457 parseParam("--bb <V2> Long option.") catch unreachable,
512 parseParam("-c, --cc Both flag. ") catch unreachable, 458 parseParam("-c, --cc Both flag.") catch unreachable,
513 parseParam("-d, --dd <V3> Both option. ") catch unreachable, 459 parseParam("-d, --dd <V3> Both option.") catch unreachable,
514 parseParam("-d, --dd <V3>... Both repeated option. ") catch unreachable, 460 parseParam("-d, --dd <V3>... Both repeated option.") catch unreachable,
515 Param(Help){ 461 parseParam("<P> Positional. This should not appear in the help message.") catch unreachable,
516 .id = Help{
517 .msg = "Positional. This should not appear in the help message.",
518 },
519 .takes_value = .One,
520 },
521 }, 462 },
522 ); 463 );
523 464
@@ -547,10 +488,10 @@ pub fn usageFull(
547 valueText: fn (@TypeOf(context), Param(Id)) Error![]const u8, 488 valueText: fn (@TypeOf(context), Param(Id)) Error![]const u8,
548) !void { 489) !void {
549 var cos = io.countingOutStream(stream); 490 var cos = io.countingOutStream(stream);
550 const cs = cos.outStream(); 491 const cs = cos.writer();
551 for (params) |param| { 492 for (params) |param| {
552 const name = param.names.short orelse continue; 493 const name = param.names.short orelse continue;
553 if (param.takes_value != .None) 494 if (param.takes_value != .none)
554 continue; 495 continue;
555 496
556 if (cos.bytes_written == 0) 497 if (cos.bytes_written == 0)
@@ -562,7 +503,7 @@ pub fn usageFull(
562 503
563 var positional: ?Param(Id) = null; 504 var positional: ?Param(Id) = null;
564 for (params) |param| { 505 for (params) |param| {
565 if (param.takes_value == .None and param.names.short != null) 506 if (param.takes_value == .none and param.names.short != null)
566 continue; 507 continue;
567 508
568 const prefix = if (param.names.short) |_| "-" else "--"; 509 const prefix = if (param.names.short) |_| "-" else "--";
@@ -578,9 +519,9 @@ pub fn usageFull(
578 519
579 try cs.print("[{}{}", .{ prefix, name }); 520 try cs.print("[{}{}", .{ prefix, name });
580 switch (param.takes_value) { 521 switch (param.takes_value) {
581 .None => {}, 522 .none => {},
582 .One => try cs.print(" <{}>", .{try valueText(context, param)}), 523 .one => try cs.print(" <{}>", .{try valueText(context, param)}),
583 .Many => try cs.print(" <{}>...", .{try valueText(context, param)}), 524 .many => try cs.print(" <{}>...", .{try valueText(context, param)}),
584 } 525 }
585 526
586 try cs.writeByte(']'); 527 try cs.writeByte(']');
@@ -627,7 +568,7 @@ pub fn usage(stream: anytype, params: []const Param(Help)) !void {
627fn testUsage(expected: []const u8, params: []const Param(Help)) !void { 568fn testUsage(expected: []const u8, params: []const Param(Help)) !void {
628 var buf: [1024]u8 = undefined; 569 var buf: [1024]u8 = undefined;
629 var fbs = io.fixedBufferStream(&buf); 570 var fbs = io.fixedBufferStream(&buf);
630 try usage(fbs.outStream(), params); 571 try usage(fbs.writer(), params);
631 testing.expectEqualStrings(expected, fbs.getWritten()); 572 testing.expectEqualStrings(expected, fbs.getWritten());
632} 573}
633 574
@@ -650,12 +591,7 @@ test "usage" {
650 parseParam("--b <v>") catch unreachable, 591 parseParam("--b <v>") catch unreachable,
651 }); 592 });
652 try testUsage("<file>", comptime &[_]Param(Help){ 593 try testUsage("<file>", comptime &[_]Param(Help){
653 Param(Help){ 594 parseParam("<file>") catch unreachable,
654 .id = Help{
655 .value = "file",
656 },
657 .takes_value = .One,
658 },
659 }); 595 });
660 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>", comptime &[_]Param(Help){
661 parseParam("-a") catch unreachable, 597 parseParam("-a") catch unreachable,
@@ -667,11 +603,6 @@ test "usage" {
667 parseParam("--g <value>") catch unreachable, 603 parseParam("--g <value>") catch unreachable,
668 parseParam("--h <v>") catch unreachable, 604 parseParam("--h <v>") catch unreachable,
669 parseParam("-i <v>...") catch unreachable, 605 parseParam("-i <v>...") catch unreachable,
670 Param(Help){ 606 parseParam("<file>") catch unreachable,
671 .id = Help{
672 .value = "file",
673 },
674 .takes_value = .One,
675 },
676 }); 607 });
677} 608}
diff --git a/clap/comptime.zig b/clap/comptime.zig
index 9bec38e..122ff16 100644
--- a/clap/comptime.zig
+++ b/clap/comptime.zig
@@ -19,9 +19,9 @@ pub fn ComptimeClap(
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) {
21 const ptr = switch (param.takes_value) { 21 const ptr = switch (param.takes_value) {
22 .None => &flags, 22 .none => &flags,
23 .One => &single_options, 23 .one => &single_options,
24 .Many => &multi_options, 24 .many => &multi_options,
25 }; 25 };
26 index = ptr.*; 26 index = ptr.*;
27 ptr.* += 1; 27 ptr.* += 1;
@@ -67,11 +67,11 @@ pub fn ComptimeClap(
67 const param = arg.param; 67 const param = arg.param;
68 if (param.names.long == null and param.names.short == null) { 68 if (param.names.long == null and param.names.short == null) {
69 try pos.append(arg.value.?); 69 try pos.append(arg.value.?);
70 } else if (param.takes_value == .One) { 70 } else if (param.takes_value == .one) {
71 debug.assert(res.single_options.len != 0); 71 debug.assert(res.single_options.len != 0);
72 if (res.single_options.len != 0) 72 if (res.single_options.len != 0)
73 res.single_options[param.id] = arg.value.?; 73 res.single_options[param.id] = arg.value.?;
74 } else if (param.takes_value == .Many) { 74 } else if (param.takes_value == .many) {
75 debug.assert(multis.len != 0); 75 debug.assert(multis.len != 0);
76 if (multis.len != 0) 76 if (multis.len != 0)
77 try multis[param.id].append(arg.value.?); 77 try multis[param.id].append(arg.value.?);
@@ -97,7 +97,7 @@ pub fn ComptimeClap(
97 97
98 pub fn flag(parser: @This(), comptime name: []const u8) bool { 98 pub fn flag(parser: @This(), comptime name: []const u8) bool {
99 const param = comptime findParam(name); 99 const param = comptime findParam(name);
100 if (param.takes_value != .None) 100 if (param.takes_value != .none)
101 @compileError(name ++ " is an option and not a flag."); 101 @compileError(name ++ " is an option and not a flag.");
102 102
103 return parser.flags[param.id]; 103 return parser.flags[param.id];
@@ -105,18 +105,18 @@ pub fn ComptimeClap(
105 105
106 pub fn option(parser: @This(), comptime name: []const u8) ?[]const u8 { 106 pub fn option(parser: @This(), comptime name: []const u8) ?[]const u8 {
107 const param = comptime findParam(name); 107 const param = comptime findParam(name);
108 if (param.takes_value == .None) 108 if (param.takes_value == .none)
109 @compileError(name ++ " is a flag and not an option."); 109 @compileError(name ++ " is a flag and not an option.");
110 if (param.takes_value == .Many) 110 if (param.takes_value == .many)
111 @compileError(name ++ " takes many options, not one."); 111 @compileError(name ++ " takes many options, not one.");
112 return parser.single_options[param.id]; 112 return parser.single_options[param.id];
113 } 113 }
114 114
115 pub fn options(parser: @This(), comptime name: []const u8) []const []const u8 { 115 pub fn options(parser: @This(), comptime name: []const u8) []const []const u8 {
116 const param = comptime findParam(name); 116 const param = comptime findParam(name);
117 if (param.takes_value == .None) 117 if (param.takes_value == .none)
118 @compileError(name ++ " is a flag and not an option."); 118 @compileError(name ++ " is a flag and not an option.");
119 if (param.takes_value == .One) 119 if (param.takes_value == .one)
120 @compileError(name ++ " takes one option, not multiple."); 120 @compileError(name ++ " takes one option, not multiple.");
121 121
122 return parser.multi_options[param.id]; 122 return parser.multi_options[param.id];
diff --git a/clap/streaming.zig b/clap/streaming.zig
index 8030a67..a2a0ca8 100644
--- a/clap/streaming.zig
+++ b/clap/streaming.zig
@@ -69,7 +69,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
69 69
70 if (!mem.eql(u8, name, match)) 70 if (!mem.eql(u8, name, match))
71 continue; 71 continue;
72 if (param.takes_value == .None) { 72 if (param.takes_value == .none) {
73 if (maybe_value != null) 73 if (maybe_value != null)
74 return parser.err(arg, .{ .long = name }, error.DoesntTakeValue); 74 return parser.err(arg, .{ .long = name }, error.DoesntTakeValue);
75 75
@@ -122,7 +122,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
122 122
123 // Before we return, we have to set the new state of the clap 123 // Before we return, we have to set the new state of the clap
124 defer { 124 defer {
125 if (arg.len <= next_index or param.takes_value != .None) { 125 if (arg.len <= next_index or param.takes_value != .none) {
126 parser.state = .normal; 126 parser.state = .normal;
127 } else { 127 } else {
128 parser.state = .{ 128 parser.state = .{
@@ -135,7 +135,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
135 } 135 }
136 136
137 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;
138 if (param.takes_value == .None) { 138 if (param.takes_value == .none) {
139 if (next_is_eql) 139 if (next_is_eql)
140 return parser.err(arg, .{ .short = short }, error.DoesntTakeValue); 140 return parser.err(arg, .{ .short = short }, error.DoesntTakeValue);
141 return Arg(Id){ .param = param }; 141 return Arg(Id){ .param = param };
@@ -235,9 +235,9 @@ fn testErr(params: []const clap.Param(u8), args_strings: []const []const u8, exp
235 }; 235 };
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 slice_stream = io.fixedBufferStream(&buf); 238 var fbs = io.fixedBufferStream(&buf);
239 diag.report(slice_stream.outStream(), err) catch unreachable; 239 diag.report(fbs.writer(), err) catch unreachable;
240 testing.expectEqualStrings(expected, slice_stream.getWritten()); 240 testing.expectEqualStrings(expected, fbs.getWritten());
241 return; 241 return;
242 }) |_| {} 242 }) |_| {}
243 243
@@ -246,23 +246,17 @@ fn testErr(params: []const clap.Param(u8), args_strings: []const []const u8, exp
246 246
247test "short params" { 247test "short params" {
248 const params = [_]clap.Param(u8){ 248 const params = [_]clap.Param(u8){
249 clap.Param(u8){ 249 .{ .id = 0, .names = .{ .short = 'a' } },
250 .id = 0, 250 .{ .id = 1, .names = .{ .short = 'b' } },
251 .names = clap.Names{ .short = 'a' }, 251 .{
252 },
253 clap.Param(u8){
254 .id = 1,
255 .names = clap.Names{ .short = 'b' },
256 },
257 clap.Param(u8){
258 .id = 2, 252 .id = 2,
259 .names = clap.Names{ .short = 'c' }, 253 .names = .{ .short = 'c' },
260 .takes_value = .One, 254 .takes_value = .one,
261 }, 255 },
262 clap.Param(u8){ 256 .{
263 .id = 3, 257 .id = 3,
264 .names = clap.Names{ .short = 'd' }, 258 .names = .{ .short = 'd' },
265 .takes_value = .Many, 259 .takes_value = .many,
266 }, 260 },
267 }; 261 };
268 262
@@ -279,42 +273,36 @@ test "short params" {
279 "0", "-ac=0", "-d=0", 273 "0", "-ac=0", "-d=0",
280 }, 274 },
281 &[_]Arg(u8){ 275 &[_]Arg(u8){
282 Arg(u8){ .param = a }, 276 .{ .param = a },
283 Arg(u8){ .param = b }, 277 .{ .param = b },
284 Arg(u8){ .param = a }, 278 .{ .param = a },
285 Arg(u8){ .param = b }, 279 .{ .param = b },
286 Arg(u8){ .param = b }, 280 .{ .param = b },
287 Arg(u8){ .param = a }, 281 .{ .param = a },
288 Arg(u8){ .param = c, .value = "0" }, 282 .{ .param = c, .value = "0" },
289 Arg(u8){ .param = c, .value = "0" }, 283 .{ .param = c, .value = "0" },
290 Arg(u8){ .param = a }, 284 .{ .param = a },
291 Arg(u8){ .param = c, .value = "0" }, 285 .{ .param = c, .value = "0" },
292 Arg(u8){ .param = a }, 286 .{ .param = a },
293 Arg(u8){ .param = c, .value = "0" }, 287 .{ .param = c, .value = "0" },
294 Arg(u8){ .param = d, .value = "0" }, 288 .{ .param = d, .value = "0" },
295 }, 289 },
296 ); 290 );
297} 291}
298 292
299test "long params" { 293test "long params" {
300 const params = [_]clap.Param(u8){ 294 const params = [_]clap.Param(u8){
301 clap.Param(u8){ 295 .{ .id = 0, .names = .{ .long = "aa" } },
302 .id = 0, 296 .{ .id = 1, .names = .{ .long = "bb" } },
303 .names = clap.Names{ .long = "aa" }, 297 .{
304 },
305 clap.Param(u8){
306 .id = 1,
307 .names = clap.Names{ .long = "bb" },
308 },
309 clap.Param(u8){
310 .id = 2, 298 .id = 2,
311 .names = clap.Names{ .long = "cc" }, 299 .names = .{ .long = "cc" },
312 .takes_value = .One, 300 .takes_value = .one,
313 }, 301 },
314 clap.Param(u8){ 302 .{
315 .id = 3, 303 .id = 3,
316 .names = clap.Names{ .long = "dd" }, 304 .names = .{ .long = "dd" },
317 .takes_value = .Many, 305 .takes_value = .many,
318 }, 306 },
319 }; 307 };
320 308
@@ -331,59 +319,47 @@ test "long params" {
331 "--cc=0", "--dd=0", 319 "--cc=0", "--dd=0",
332 }, 320 },
333 &[_]Arg(u8){ 321 &[_]Arg(u8){
334 Arg(u8){ .param = aa }, 322 .{ .param = aa },
335 Arg(u8){ .param = bb }, 323 .{ .param = bb },
336 Arg(u8){ .param = cc, .value = "0" }, 324 .{ .param = cc, .value = "0" },
337 Arg(u8){ .param = cc, .value = "0" }, 325 .{ .param = cc, .value = "0" },
338 Arg(u8){ .param = dd, .value = "0" }, 326 .{ .param = dd, .value = "0" },
339 }, 327 },
340 ); 328 );
341} 329}
342 330
343test "positional params" { 331test "positional params" {
344 const params = [_]clap.Param(u8){clap.Param(u8){ 332 const params = [_]clap.Param(u8){.{
345 .id = 0, 333 .id = 0,
346 .takes_value = .One, 334 .takes_value = .one,
347 }}; 335 }};
348 336
349 testNoErr( 337 testNoErr(
350 &params, 338 &params,
351 &[_][]const u8{ "aa", "bb" }, 339 &[_][]const u8{ "aa", "bb" },
352 &[_]Arg(u8){ 340 &[_]Arg(u8){
353 Arg(u8){ .param = &params[0], .value = "aa" }, 341 .{ .param = &params[0], .value = "aa" },
354 Arg(u8){ .param = &params[0], .value = "bb" }, 342 .{ .param = &params[0], .value = "bb" },
355 }, 343 },
356 ); 344 );
357} 345}
358 346
359test "all params" { 347test "all params" {
360 const params = [_]clap.Param(u8){ 348 const params = [_]clap.Param(u8){
361 clap.Param(u8){ 349 .{
362 .id = 0, 350 .id = 0,
363 .names = clap.Names{ 351 .names = .{ .short = 'a', .long = "aa" },
364 .short = 'a',
365 .long = "aa",
366 },
367 }, 352 },
368 clap.Param(u8){ 353 .{
369 .id = 1, 354 .id = 1,
370 .names = clap.Names{ 355 .names = .{ .short = 'b', .long = "bb" },
371 .short = 'b',
372 .long = "bb",
373 },
374 }, 356 },
375 clap.Param(u8){ 357 .{
376 .id = 2, 358 .id = 2,
377 .names = clap.Names{ 359 .names = .{ .short = 'c', .long = "cc" },
378 .short = 'c', 360 .takes_value = .one,
379 .long = "cc",
380 },
381 .takes_value = .One,
382 },
383 clap.Param(u8){
384 .id = 3,
385 .takes_value = .One,
386 }, 361 },
362 .{ .id = 3, .takes_value = .one },
387 }; 363 };
388 364
389 const aa = &params[0]; 365 const aa = &params[0];
@@ -401,46 +377,40 @@ test "all params" {
401 "-", "--", "--cc=0", "-a", 377 "-", "--", "--cc=0", "-a",
402 }, 378 },
403 &[_]Arg(u8){ 379 &[_]Arg(u8){
404 Arg(u8){ .param = aa }, 380 .{ .param = aa },
405 Arg(u8){ .param = bb }, 381 .{ .param = bb },
406 Arg(u8){ .param = aa }, 382 .{ .param = aa },
407 Arg(u8){ .param = bb }, 383 .{ .param = bb },
408 Arg(u8){ .param = bb }, 384 .{ .param = bb },
409 Arg(u8){ .param = aa }, 385 .{ .param = aa },
410 Arg(u8){ .param = cc, .value = "0" }, 386 .{ .param = cc, .value = "0" },
411 Arg(u8){ .param = cc, .value = "0" }, 387 .{ .param = cc, .value = "0" },
412 Arg(u8){ .param = aa }, 388 .{ .param = aa },
413 Arg(u8){ .param = cc, .value = "0" }, 389 .{ .param = cc, .value = "0" },
414 Arg(u8){ .param = aa }, 390 .{ .param = aa },
415 Arg(u8){ .param = cc, .value = "0" }, 391 .{ .param = cc, .value = "0" },
416 Arg(u8){ .param = aa }, 392 .{ .param = aa },
417 Arg(u8){ .param = bb }, 393 .{ .param = bb },
418 Arg(u8){ .param = cc, .value = "0" }, 394 .{ .param = cc, .value = "0" },
419 Arg(u8){ .param = cc, .value = "0" }, 395 .{ .param = cc, .value = "0" },
420 Arg(u8){ .param = positional, .value = "something" }, 396 .{ .param = positional, .value = "something" },
421 Arg(u8){ .param = positional, .value = "-" }, 397 .{ .param = positional, .value = "-" },
422 Arg(u8){ .param = positional, .value = "--cc=0" }, 398 .{ .param = positional, .value = "--cc=0" },
423 Arg(u8){ .param = positional, .value = "-a" }, 399 .{ .param = positional, .value = "-a" },
424 }, 400 },
425 ); 401 );
426} 402}
427 403
428test "errors" { 404test "errors" {
429 const params = [_]clap.Param(u8){ 405 const params = [_]clap.Param(u8){
430 clap.Param(u8){ 406 .{
431 .id = 0, 407 .id = 0,
432 .names = clap.Names{ 408 .names = .{ .short = 'a', .long = "aa" },
433 .short = 'a',
434 .long = "aa",
435 },
436 }, 409 },
437 clap.Param(u8){ 410 .{
438 .id = 1, 411 .id = 1,
439 .names = clap.Names{ 412 .names = .{ .short = 'c', .long = "cc" },
440 .short = 'c', 413 .takes_value = .one,
441 .long = "cc",
442 },
443 .takes_value = .One,
444 }, 414 },
445 }; 415 };
446 testErr(&params, &[_][]const u8{"q"}, "Invalid argument 'q'\n"); 416 testErr(&params, &[_][]const u8{"q"}, "Invalid argument 'q'\n");
diff --git a/example/help.zig b/example/help.zig
index 2775177..3cf9e42 100644
--- a/example/help.zig
+++ b/example/help.zig
@@ -1,15 +1,12 @@
1const std = @import("std");
2const clap = @import("clap"); 1const clap = @import("clap");
2const std = @import("std");
3 3
4pub fn main() !void { 4pub fn main() !void {
5 const stderr_file = std.io.getStdErr();
6 var stderr_out_stream = stderr_file.outStream();
7
8 // clap.help is a function that can print a simple help message, given a 5 // clap.help is a function that can print a simple help message, given a
9 // slice of Param(Help). There is also a helpEx, which can print a 6 // slice of Param(Help). There is also a helpEx, which can print a
10 // 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.
11 try clap.help( 8 try clap.help(
12 stderr_out_stream, 9 std.io.getStdErr().writer(),
13 comptime &[_]clap.Param(clap.Help){ 10 comptime &[_]clap.Param(clap.Help){
14 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, 11 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable,
15 clap.parseParam("-v, --version Output version information and exit.") catch unreachable, 12 clap.parseParam("-v, --version Output version information and exit.") catch unreachable,
diff --git a/example/simple-error.zig b/example/simple-error.zig
index 3c62f0e..c04a9c6 100644
--- a/example/simple-error.zig
+++ b/example/simple-error.zig
@@ -1,12 +1,12 @@
1const std = @import("std");
2const clap = @import("clap"); 1const clap = @import("clap");
2const std = @import("std");
3 3
4pub fn main() !void { 4pub fn main() !void {
5 const params = comptime [_]clap.Param(clap.Help){ 5 const params = comptime [_]clap.Param(clap.Help){
6 clap.parseParam("-h, --help Display this help and exit.") catch unreachable, 6 clap.parseParam("-h, --help Display this help and exit.") catch unreachable,
7 }; 7 };
8 8
9 var args = try clap.parse(clap.Help, &params, std.heap.direct_allocator, null); 9 var args = try clap.parse(clap.Help, &params, .{});
10 defer args.deinit(); 10 defer args.deinit();
11 11
12 _ = args.flag("--helps"); 12 _ = args.flag("--helps");
diff --git a/example/simple-ex.zig b/example/simple-ex.zig
index f504d63..f08751b 100644
--- a/example/simple-ex.zig
+++ b/example/simple-ex.zig
@@ -2,6 +2,7 @@ const clap = @import("clap");
2const std = @import("std"); 2const std = @import("std");
3 3
4const debug = std.debug; 4const debug = std.debug;
5const io = std.io;
5 6
6pub fn main() !void { 7pub fn main() !void {
7 const allocator = std.heap.page_allocator; 8 const allocator = std.heap.page_allocator;
@@ -29,7 +30,7 @@ pub fn main() !void {
29 .diagnostic = &diag, 30 .diagnostic = &diag,
30 }) catch |err| { 31 }) catch |err| {
31 // Report useful error and exit 32 // Report useful error and exit
32 diag.report(std.io.getStdErr().outStream(), err) catch {}; 33 diag.report(io.getStdErr().writer(), err) catch {};
33 return err; 34 return err;
34 }; 35 };
35 defer args.deinit(); 36 defer args.deinit();
diff --git a/example/simple.zig b/example/simple.zig
index 392dca3..69473fa 100644
--- a/example/simple.zig
+++ b/example/simple.zig
@@ -2,6 +2,7 @@ const clap = @import("clap");
2const std = @import("std"); 2const std = @import("std");
3 3
4const debug = std.debug; 4const debug = std.debug;
5const io = std.io;
5 6
6pub fn main() !void { 7pub fn main() !void {
7 // First we specify what parameters our program can take. 8 // First we specify what parameters our program can take.
@@ -19,7 +20,7 @@ pub fn main() !void {
19 var diag = clap.Diagnostic{}; 20 var diag = clap.Diagnostic{};
20 var args = clap.parse(clap.Help, &params, .{ .diagnostic = &diag }) catch |err| { 21 var args = clap.parse(clap.Help, &params, .{ .diagnostic = &diag }) catch |err| {
21 // Report useful error and exit 22 // Report useful error and exit
22 diag.report(std.io.getStdErr().outStream(), err) catch {}; 23 diag.report(io.getStdErr().writer(), err) catch {};
23 return err; 24 return err;
24 }; 25 };
25 defer args.deinit(); 26 defer args.deinit();
diff --git a/example/streaming-clap.zig b/example/streaming-clap.zig
index f8d873d..41efd1f 100644
--- a/example/streaming-clap.zig
+++ b/example/streaming-clap.zig
@@ -2,25 +2,23 @@ const clap = @import("clap");
2const std = @import("std"); 2const std = @import("std");
3 3
4const debug = std.debug; 4const debug = std.debug;
5const io = std.io;
5 6
6pub fn main() !void { 7pub fn main() !void {
7 const allocator = std.heap.page_allocator; 8 const allocator = std.heap.page_allocator;
8 9
9 // First we specify what parameters our program can take. 10 // First we specify what parameters our program can take.
10 const params = [_]clap.Param(u8){ 11 const params = [_]clap.Param(u8){
11 clap.Param(u8){ 12 .{
12 .id = 'h', 13 .id = 'h',
13 .names = clap.Names{ .short = 'h', .long = "help" }, 14 .names = .{ .short = 'h', .long = "help" },
14 }, 15 },
15 clap.Param(u8){ 16 .{
16 .id = 'n', 17 .id = 'n',
17 .names = clap.Names{ .short = 'n', .long = "number" }, 18 .names = .{ .short = 'n', .long = "number" },
18 .takes_value = .One, 19 .takes_value = .one,
19 },
20 clap.Param(u8){
21 .id = 'f',
22 .takes_value = .One,
23 }, 20 },
21 .{ .id = 'f', .takes_value = .one },
24 }; 22 };
25 23
26 // We then initialize an argument iterator. We will use the OsIterator as it nicely 24 // We then initialize an argument iterator. We will use the OsIterator as it nicely
@@ -41,7 +39,7 @@ pub fn main() !void {
41 // 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.
42 while (parser.next() catch |err| { 40 while (parser.next() catch |err| {
43 // Report useful error and exit 41 // Report useful error and exit
44 diag.report(std.io.getStdErr().outStream(), err) catch {}; 42 diag.report(io.getStdErr().writer(), err) catch {};
45 return err; 43 return err;
46 }) |arg| { 44 }) |arg| {
47 // arg.param will point to the parameter which matched the argument. 45 // arg.param will point to the parameter which matched the argument.
diff --git a/example/usage.zig b/example/usage.zig
index 25e1a34..e044f1d 100644
--- a/example/usage.zig
+++ b/example/usage.zig
@@ -1,14 +1,12 @@
1const std = @import("std");
2const clap = @import("clap"); 1const clap = @import("clap");
2const std = @import("std");
3 3
4pub fn main() !void { 4pub fn main() !void {
5 const stderr = std.io.getStdErr().outStream();
6
7 // clap.usage is a function that can print a simple usage message, given a 5 // clap.usage is a function that can print a simple usage message, given a
8 // slice of Param(Help). There is also a usageEx, which can print a 6 // slice of Param(Help). There is also a usageEx, which can print a
9 // 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.
10 try clap.usage( 8 try clap.usage(
11 stderr, 9 std.io.getStdErr().writer(),
12 comptime &[_]clap.Param(clap.Help){ 10 comptime &[_]clap.Param(clap.Help){
13 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, 11 clap.parseParam("-h, --help Display this help and exit. ") catch unreachable,
14 clap.parseParam("-v, --version Output version information and exit.") catch unreachable, 12 clap.parseParam("-v, --version Output version information and exit.") catch unreachable,