summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jimmi Holst Christensen2024-10-22 17:46:47 +0200
committerGravatar Jimmi Holst Christensen2024-10-22 17:48:34 +0200
commite73b56aa4bcb7e53144ef96ee978f2a19b32669d (patch)
tree0ab5e3d426e25d2ad9d2e0cd0015fc010d9ea182
parentfeat: Add `terminating_positional` to `clap.ParseOptions` (diff)
downloadzig-clap-e73b56aa4bcb7e53144ef96ee978f2a19b32669d.tar.gz
zig-clap-e73b56aa4bcb7e53144ef96ee978f2a19b32669d.tar.xz
zig-clap-e73b56aa4bcb7e53144ef96ee978f2a19b32669d.zip
refactor: Always access using full namespace
This is my new preferred style of programming Zig :)
Diffstat (limited to '')
-rw-r--r--README.md77
-rw-r--r--build.zig4
-rw-r--r--clap.zig183
-rw-r--r--clap/args.zig15
-rw-r--r--clap/codepoint_counting_writer.zig7
-rw-r--r--clap/parsers.zig55
-rw-r--r--clap/streaming.zig95
-rw-r--r--example/help.zig8
-rw-r--r--example/simple-ex.zig22
-rw-r--r--example/simple.zig19
-rw-r--r--example/streaming-clap.zig22
-rw-r--r--example/usage.zig6
12 files changed, 232 insertions, 281 deletions
diff --git a/README.md b/README.md
index bc38b58..c6e14e9 100644
--- a/README.md
+++ b/README.md
@@ -56,12 +56,6 @@ Note that Zig autodoc is in beta; the website may be broken or incomplete.
56The simplest way to use this library is to just call the `clap.parse` function. 56The simplest way to use this library is to just call the `clap.parse` function.
57 57
58```zig 58```zig
59const clap = @import("clap");
60const std = @import("std");
61
62const debug = std.debug;
63const io = std.io;
64
65pub fn main() !void { 59pub fn main() !void {
66 var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 60 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
67 defer _ = gpa.deinit(); 61 defer _ = gpa.deinit();
@@ -85,21 +79,24 @@ pub fn main() !void {
85 .allocator = gpa.allocator(), 79 .allocator = gpa.allocator(),
86 }) catch |err| { 80 }) catch |err| {
87 // Report useful error and exit 81 // Report useful error and exit
88 diag.report(io.getStdErr().writer(), err) catch {}; 82 diag.report(std.io.getStdErr().writer(), err) catch {};
89 return err; 83 return err;
90 }; 84 };
91 defer res.deinit(); 85 defer res.deinit();
92 86
93 if (res.args.help != 0) 87 if (res.args.help != 0)
94 debug.print("--help\n", .{}); 88 std.debug.print("--help\n", .{});
95 if (res.args.number) |n| 89 if (res.args.number) |n|
96 debug.print("--number = {}\n", .{n}); 90 std.debug.print("--number = {}\n", .{n});
97 for (res.args.string) |s| 91 for (res.args.string) |s|
98 debug.print("--string = {s}\n", .{s}); 92 std.debug.print("--string = {s}\n", .{s});
99 for (res.positionals) |pos| 93 for (res.positionals) |pos|
100 debug.print("{s}\n", .{pos}); 94 std.debug.print("{s}\n", .{pos});
101} 95}
102 96
97const clap = @import("clap");
98const std = @import("std");
99
103``` 100```
104 101
105The result will contain an `args` field and a `positionals` field. `args` will have one field 102The result will contain an `args` field and a `positionals` field. `args` will have one field
@@ -114,13 +111,6 @@ contains a parser that returns `usize`. You can pass in something other than
114`clap.parsers.default` if you want some other mapping. 111`clap.parsers.default` if you want some other mapping.
115 112
116```zig 113```zig
117const clap = @import("clap");
118const std = @import("std");
119
120const debug = std.debug;
121const io = std.io;
122const process = std.process;
123
124pub fn main() !void { 114pub fn main() !void {
125 var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 115 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
126 defer _ = gpa.deinit(); 116 defer _ = gpa.deinit();
@@ -154,23 +144,26 @@ pub fn main() !void {
154 // allowed. 144 // allowed.
155 .assignment_separators = "=:", 145 .assignment_separators = "=:",
156 }) catch |err| { 146 }) catch |err| {
157 diag.report(io.getStdErr().writer(), err) catch {}; 147 diag.report(std.io.getStdErr().writer(), err) catch {};
158 return err; 148 return err;
159 }; 149 };
160 defer res.deinit(); 150 defer res.deinit();
161 151
162 if (res.args.help != 0) 152 if (res.args.help != 0)
163 debug.print("--help\n", .{}); 153 std.debug.print("--help\n", .{});
164 if (res.args.number) |n| 154 if (res.args.number) |n|
165 debug.print("--number = {}\n", .{n}); 155 std.debug.print("--number = {}\n", .{n});
166 if (res.args.answer) |a| 156 if (res.args.answer) |a|
167 debug.print("--answer = {s}\n", .{@tagName(a)}); 157 std.debug.print("--answer = {s}\n", .{@tagName(a)});
168 for (res.args.string) |s| 158 for (res.args.string) |s|
169 debug.print("--string = {s}\n", .{s}); 159 std.debug.print("--string = {s}\n", .{s});
170 for (res.positionals) |pos| 160 for (res.positionals) |pos|
171 debug.print("{s}\n", .{pos}); 161 std.debug.print("{s}\n", .{pos});
172} 162}
173 163
164const clap = @import("clap");
165const std = @import("std");
166
174``` 167```
175 168
176### `streaming.Clap` 169### `streaming.Clap`
@@ -179,13 +172,6 @@ The `streaming.Clap` is the base of all the other parsers. It's a streaming pars
179`args.Iterator` to provide it with arguments lazily. 172`args.Iterator` to provide it with arguments lazily.
180 173
181```zig 174```zig
182const clap = @import("clap");
183const std = @import("std");
184
185const debug = std.debug;
186const io = std.io;
187const process = std.process;
188
189pub fn main() !void { 175pub fn main() !void {
190 const allocator = std.heap.page_allocator; 176 const allocator = std.heap.page_allocator;
191 177
@@ -203,7 +189,7 @@ pub fn main() !void {
203 .{ .id = 'f', .takes_value = .one }, 189 .{ .id = 'f', .takes_value = .one },
204 }; 190 };
205 191
206 var iter = try process.ArgIterator.initWithAllocator(allocator); 192 var iter = try std.process.ArgIterator.initWithAllocator(allocator);
207 defer iter.deinit(); 193 defer iter.deinit();
208 194
209 // Skip exe argument 195 // Skip exe argument
@@ -213,7 +199,7 @@ pub fn main() !void {
213 // This is optional. You can also leave the `diagnostic` field unset if you 199 // This is optional. You can also leave the `diagnostic` field unset if you
214 // don't care about the extra information `Diagnostic` provides. 200 // don't care about the extra information `Diagnostic` provides.
215 var diag = clap.Diagnostic{}; 201 var diag = clap.Diagnostic{};
216 var parser = clap.streaming.Clap(u8, process.ArgIterator){ 202 var parser = clap.streaming.Clap(u8, std.process.ArgIterator){
217 .params = &params, 203 .params = &params,
218 .iter = &iter, 204 .iter = &iter,
219 .diagnostic = &diag, 205 .diagnostic = &diag,
@@ -222,23 +208,26 @@ pub fn main() !void {
222 // Because we use a streaming parser, we have to consume each argument parsed individually. 208 // Because we use a streaming parser, we have to consume each argument parsed individually.
223 while (parser.next() catch |err| { 209 while (parser.next() catch |err| {
224 // Report useful error and exit 210 // Report useful error and exit
225 diag.report(io.getStdErr().writer(), err) catch {}; 211 diag.report(std.io.getStdErr().writer(), err) catch {};
226 return err; 212 return err;
227 }) |arg| { 213 }) |arg| {
228 // arg.param will point to the parameter which matched the argument. 214 // arg.param will point to the parameter which matched the argument.
229 switch (arg.param.id) { 215 switch (arg.param.id) {
230 'h' => debug.print("Help!\n", .{}), 216 'h' => std.debug.print("Help!\n", .{}),
231 'n' => debug.print("--number = {s}\n", .{arg.value.?}), 217 'n' => std.debug.print("--number = {s}\n", .{arg.value.?}),
232 218
233 // arg.value == null, if arg.param.takes_value == .none. 219 // arg.value == null, if arg.param.takes_value == .none.
234 // Otherwise, arg.value is the value passed with the argument, such as "-a=10" 220 // Otherwise, arg.value is the value passed with the argument, such as "-a=10"
235 // or "-a 10". 221 // or "-a 10".
236 'f' => debug.print("{s}\n", .{arg.value.?}), 222 'f' => std.debug.print("{s}\n", .{arg.value.?}),
237 else => unreachable, 223 else => unreachable,
238 } 224 }
239 } 225 }
240} 226}
241 227
228const clap = @import("clap");
229const std = @import("std");
230
242``` 231```
243 232
244Currently, this parser is the only parser that allows an array of `Param` that 233Currently, this parser is the only parser that allows an array of `Param` that
@@ -252,9 +241,6 @@ in the output. `HelpOptions` is passed to `help` to control how the help message
252printed. 241printed.
253 242
254```zig 243```zig
255const clap = @import("clap");
256const std = @import("std");
257
258pub fn main() !void { 244pub fn main() !void {
259 var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 245 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
260 defer _ = gpa.deinit(); 246 defer _ = gpa.deinit();
@@ -271,13 +257,16 @@ pub fn main() !void {
271 defer res.deinit(); 257 defer res.deinit();
272 258
273 // `clap.help` is a function that can print a simple help message. It can print any `Param` 259 // `clap.help` is a function that can print a simple help message. It can print any `Param`
274 // where `Id` has a `describtion` and `value` method (`Param(Help)` is one such parameter). 260 // where `Id` has a `description` and `value` method (`Param(Help)` is one such parameter).
275 // The last argument contains options as to how `help` should print those parameters. Using 261 // The last argument contains options as to how `help` should print those parameters. Using
276 // `.{}` means the default options. 262 // `.{}` means the default options.
277 if (res.args.help != 0) 263 if (res.args.help != 0)
278 return clap.help(std.io.getStdErr().writer(), clap.Help, &params, .{}); 264 return clap.help(std.io.getStdErr().writer(), clap.Help, &params, .{});
279} 265}
280 266
267const clap = @import("clap");
268const std = @import("std");
269
281``` 270```
282 271
283``` 272```
@@ -295,9 +284,6 @@ The `usage` prints a small abbreviated version of the help message. It expects t
295to have a `value` method so it can provide that in the output. 284to have a `value` method so it can provide that in the output.
296 285
297```zig 286```zig
298const clap = @import("clap");
299const std = @import("std");
300
301pub fn main() !void { 287pub fn main() !void {
302 var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 288 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
303 defer _ = gpa.deinit(); 289 defer _ = gpa.deinit();
@@ -320,6 +306,9 @@ pub fn main() !void {
320 return clap.usage(std.io.getStdErr().writer(), clap.Help, &params); 306 return clap.usage(std.io.getStdErr().writer(), clap.Help, &params);
321} 307}
322 308
309const clap = @import("clap");
310const std = @import("std");
311
323``` 312```
324 313
325``` 314```
diff --git a/build.zig b/build.zig
index 9035675..b4a8e91 100644
--- a/build.zig
+++ b/build.zig
@@ -1,5 +1,3 @@
1const std = @import("std");
2
3pub fn build(b: *std.Build) void { 1pub fn build(b: *std.Build) void {
4 const clap_mod = b.addModule("clap", .{ .root_source_file = b.path("clap.zig") }); 2 const clap_mod = b.addModule("clap", .{ .root_source_file = b.path("clap.zig") });
5 3
@@ -80,3 +78,5 @@ fn readMeStep(b: *std.Build) *std.Build.Step {
80 }); 78 });
81 return s; 79 return s;
82} 80}
81
82const std = @import("std");
diff --git a/clap.zig b/clap.zig
index f7eb5d0..21590a2 100644
--- a/clap.zig
+++ b/clap.zig
@@ -1,24 +1,3 @@
1const std = @import("std");
2
3const builtin = std.builtin;
4const debug = std.debug;
5const heap = std.heap;
6const io = std.io;
7const math = std.math;
8const mem = std.mem;
9const meta = std.meta;
10const process = std.process;
11const testing = std.testing;
12
13pub const args = @import("clap/args.zig");
14pub const parsers = @import("clap/parsers.zig");
15pub const streaming = @import("clap/streaming.zig");
16pub const ccw = @import("clap/codepoint_counting_writer.zig");
17
18test "clap" {
19 testing.refAllDecls(@This());
20}
21
22pub const default_assignment_separators = "="; 1pub const default_assignment_separators = "=";
23 2
24/// The names a `Param` can have. 3/// The names a `Param` can have.
@@ -97,14 +76,14 @@ pub fn Param(comptime Id: type) type {
97 76
98/// Takes a string and parses it into many Param(Help). Returned is a newly allocated slice 77/// Takes a string and parses it into many Param(Help). Returned is a newly allocated slice
99/// containing all the parsed params. The caller is responsible for freeing the slice. 78/// containing all the parsed params. The caller is responsible for freeing the slice.
100pub fn parseParams(allocator: mem.Allocator, str: []const u8) ![]Param(Help) { 79pub fn parseParams(allocator: std.mem.Allocator, str: []const u8) ![]Param(Help) {
101 var end: usize = undefined; 80 var end: usize = undefined;
102 return parseParamsEx(allocator, str, &end); 81 return parseParamsEx(allocator, str, &end);
103} 82}
104 83
105/// Takes a string and parses it into many Param(Help). Returned is a newly allocated slice 84/// Takes a string and parses it into many Param(Help). Returned is a newly allocated slice
106/// containing all the parsed params. The caller is responsible for freeing the slice. 85/// containing all the parsed params. The caller is responsible for freeing the slice.
107pub fn parseParamsEx(allocator: mem.Allocator, str: []const u8, end: *usize) ![]Param(Help) { 86pub fn parseParamsEx(allocator: std.mem.Allocator, str: []const u8, end: *usize) ![]Param(Help) {
108 var list = std.ArrayList(Param(Help)).init(allocator); 87 var list = std.ArrayList(Param(Help)).init(allocator);
109 errdefer list.deinit(); 88 errdefer list.deinit();
110 89
@@ -135,11 +114,11 @@ fn countParams(str: []const u8) usize {
135 @setEvalBranchQuota(std.math.maxInt(u32)); 114 @setEvalBranchQuota(std.math.maxInt(u32));
136 115
137 var res: usize = 0; 116 var res: usize = 0;
138 var it = mem.splitScalar(u8, str, '\n'); 117 var it = std.mem.splitScalar(u8, str, '\n');
139 while (it.next()) |line| { 118 while (it.next()) |line| {
140 const trimmed = mem.trimLeft(u8, line, " \t"); 119 const trimmed = std.mem.trimLeft(u8, line, " \t");
141 if (mem.startsWith(u8, trimmed, "-") or 120 if (std.mem.startsWith(u8, trimmed, "-") or
142 mem.startsWith(u8, trimmed, "<")) 121 std.mem.startsWith(u8, trimmed, "<"))
143 { 122 {
144 res += 1; 123 res += 1;
145 } 124 }
@@ -152,7 +131,7 @@ fn countParams(str: []const u8) usize {
152/// is returned, containing all the parameters parsed. This function will fail if the input slice 131/// is returned, containing all the parameters parsed. This function will fail if the input slice
153/// is to small. 132/// is to small.
154pub fn parseParamsIntoSlice(slice: []Param(Help), str: []const u8) ![]Param(Help) { 133pub fn parseParamsIntoSlice(slice: []Param(Help), str: []const u8) ![]Param(Help) {
155 var null_alloc = heap.FixedBufferAllocator.init(""); 134 var null_alloc = std.heap.FixedBufferAllocator.init("");
156 var list = std.ArrayList(Param(Help)){ 135 var list = std.ArrayList(Param(Help)){
157 .allocator = null_alloc.allocator(), 136 .allocator = null_alloc.allocator(),
158 .items = slice[0..0], 137 .items = slice[0..0],
@@ -167,7 +146,7 @@ pub fn parseParamsIntoSlice(slice: []Param(Help), str: []const u8) ![]Param(Help
167/// is returned, containing all the parameters parsed. This function will fail if the input slice 146/// is returned, containing all the parameters parsed. This function will fail if the input slice
168/// is to small. 147/// is to small.
169pub fn parseParamsIntoSliceEx(slice: []Param(Help), str: []const u8, end: *usize) ![]Param(Help) { 148pub fn parseParamsIntoSliceEx(slice: []Param(Help), str: []const u8, end: *usize) ![]Param(Help) {
170 var null_alloc = heap.FixedBufferAllocator.init(""); 149 var null_alloc = std.heap.FixedBufferAllocator.init("");
171 var list = std.ArrayList(Param(Help)){ 150 var list = std.ArrayList(Param(Help)){
172 .allocator = null_alloc.allocator(), 151 .allocator = null_alloc.allocator(),
173 .items = slice[0..0], 152 .items = slice[0..0],
@@ -410,7 +389,7 @@ pub fn parseParamEx(str: []const u8, end: *usize) !Param(Help) {
410 389
411fn testParseParams(str: []const u8, expected_params: []const Param(Help)) !void { 390fn testParseParams(str: []const u8, expected_params: []const Param(Help)) !void {
412 var end: usize = undefined; 391 var end: usize = undefined;
413 const actual_params = parseParamsEx(testing.allocator, str, &end) catch |err| { 392 const actual_params = parseParamsEx(std.testing.allocator, str, &end) catch |err| {
414 const loc = std.zig.findLineColumn(str, end); 393 const loc = std.zig.findLineColumn(str, end);
415 std.debug.print("error:{}:{}: Failed to parse parameter:\n{s}\n", .{ 394 std.debug.print("error:{}:{}: Failed to parse parameter:\n{s}\n", .{
416 loc.line + 1, 395 loc.line + 1,
@@ -419,22 +398,22 @@ fn testParseParams(str: []const u8, expected_params: []const Param(Help)) !void
419 }); 398 });
420 return err; 399 return err;
421 }; 400 };
422 defer testing.allocator.free(actual_params); 401 defer std.testing.allocator.free(actual_params);
423 402
424 try testing.expectEqual(expected_params.len, actual_params.len); 403 try std.testing.expectEqual(expected_params.len, actual_params.len);
425 for (expected_params, 0..) |_, i| 404 for (expected_params, 0..) |_, i|
426 try expectParam(expected_params[i], actual_params[i]); 405 try expectParam(expected_params[i], actual_params[i]);
427} 406}
428 407
429fn expectParam(expect: Param(Help), actual: Param(Help)) !void { 408fn expectParam(expect: Param(Help), actual: Param(Help)) !void {
430 try testing.expectEqualStrings(expect.id.desc, actual.id.desc); 409 try std.testing.expectEqualStrings(expect.id.desc, actual.id.desc);
431 try testing.expectEqualStrings(expect.id.val, actual.id.val); 410 try std.testing.expectEqualStrings(expect.id.val, actual.id.val);
432 try testing.expectEqual(expect.names.short, actual.names.short); 411 try std.testing.expectEqual(expect.names.short, actual.names.short);
433 try testing.expectEqual(expect.takes_value, actual.takes_value); 412 try std.testing.expectEqual(expect.takes_value, actual.takes_value);
434 if (expect.names.long) |long| { 413 if (expect.names.long) |long| {
435 try testing.expectEqualStrings(long, actual.names.long.?); 414 try std.testing.expectEqualStrings(long, actual.names.long.?);
436 } else { 415 } else {
437 try testing.expectEqual(@as(?[]const u8, null), actual.names.long); 416 try std.testing.expectEqual(@as(?[]const u8, null), actual.names.long);
438 } 417 }
439} 418}
440 419
@@ -549,11 +528,11 @@ test "parseParams" {
549 }, 528 },
550 }); 529 });
551 530
552 try testing.expectError(error.InvalidParameter, parseParam("--long, Help")); 531 try std.testing.expectError(error.InvalidParameter, parseParam("--long, Help"));
553 try testing.expectError(error.InvalidParameter, parseParam("-s, Help")); 532 try std.testing.expectError(error.InvalidParameter, parseParam("-s, Help"));
554 try testing.expectError(error.InvalidParameter, parseParam("-ss Help")); 533 try std.testing.expectError(error.InvalidParameter, parseParam("-ss Help"));
555 try testing.expectError(error.InvalidParameter, parseParam("-ss <val> Help")); 534 try std.testing.expectError(error.InvalidParameter, parseParam("-ss <val> Help"));
556 try testing.expectError(error.InvalidParameter, parseParam("- Help")); 535 try std.testing.expectError(error.InvalidParameter, parseParam("- Help"));
557} 536}
558 537
559/// Optional diagnostics used for reporting useful errors 538/// Optional diagnostics used for reporting useful errors
@@ -588,9 +567,9 @@ pub const Diagnostic = struct {
588 567
589fn testDiag(diag: Diagnostic, err: anyerror, expected: []const u8) !void { 568fn testDiag(diag: Diagnostic, err: anyerror, expected: []const u8) !void {
590 var buf: [1024]u8 = undefined; 569 var buf: [1024]u8 = undefined;
591 var slice_stream = io.fixedBufferStream(&buf); 570 var slice_stream = std.io.fixedBufferStream(&buf);
592 diag.report(slice_stream.writer(), err) catch unreachable; 571 diag.report(slice_stream.writer(), err) catch unreachable;
593 try testing.expectEqualStrings(expected, slice_stream.getWritten()); 572 try std.testing.expectEqualStrings(expected, slice_stream.getWritten());
594} 573}
595 574
596test "Diagnostic.report" { 575test "Diagnostic.report" {
@@ -644,7 +623,7 @@ test "Diagnostic.report" {
644 623
645/// Options that can be set to customize the behavior of parsing. 624/// Options that can be set to customize the behavior of parsing.
646pub const ParseOptions = struct { 625pub const ParseOptions = struct {
647 allocator: mem.Allocator, 626 allocator: std.mem.Allocator,
648 diagnostic: ?*Diagnostic = null, 627 diagnostic: ?*Diagnostic = null,
649 628
650 /// The assignment separators, which by default is `=`. This is the separator between the name 629 /// The assignment separators, which by default is `=`. This is the separator between the name
@@ -666,10 +645,10 @@ pub fn parse(
666 comptime value_parsers: anytype, 645 comptime value_parsers: anytype,
667 opt: ParseOptions, 646 opt: ParseOptions,
668) !Result(Id, params, value_parsers) { 647) !Result(Id, params, value_parsers) {
669 var arena = heap.ArenaAllocator.init(opt.allocator); 648 var arena = std.heap.ArenaAllocator.init(opt.allocator);
670 errdefer arena.deinit(); 649 errdefer arena.deinit();
671 650
672 var iter = try process.ArgIterator.initWithAllocator(arena.allocator()); 651 var iter = try std.process.ArgIterator.initWithAllocator(arena.allocator());
673 const exe_arg = iter.next(); 652 const exe_arg = iter.next();
674 653
675 const result = try parseEx(Id, params, value_parsers, &iter, .{ 654 const result = try parseEx(Id, params, value_parsers, &iter, .{
@@ -745,7 +724,7 @@ pub fn parseEx(
745 var arguments = Arguments(Id, params, value_parsers, .list){}; 724 var arguments = Arguments(Id, params, value_parsers, .list){};
746 errdefer deinitArgs(Id, params, allocator, &arguments); 725 errdefer deinitArgs(Id, params, allocator, &arguments);
747 726
748 var stream = streaming.Clap(Id, meta.Child(@TypeOf(iter))){ 727 var stream = streaming.Clap(Id, std.meta.Child(@TypeOf(iter))){
749 .params = params, 728 .params = params,
750 .iter = iter, 729 .iter = iter,
751 .diagnostic = opt.diagnostic, 730 .diagnostic = opt.diagnostic,
@@ -785,7 +764,7 @@ pub fn parseEx(
785 // We are done parsing, but our arguments are stored in lists, and not slices. Map the list 764 // We are done parsing, but our arguments are stored in lists, and not slices. Map the list
786 // fields to slices and return that. 765 // fields to slices and return that.
787 var result_args = Arguments(Id, params, value_parsers, .slice){}; 766 var result_args = Arguments(Id, params, value_parsers, .slice){};
788 inline for (meta.fields(@TypeOf(arguments))) |field| { 767 inline for (std.meta.fields(@TypeOf(arguments))) |field| {
789 if (@typeInfo(field.type) == .@"struct" and 768 if (@typeInfo(field.type) == .@"struct" and
790 @hasDecl(field.type, "toOwnedSlice")) 769 @hasDecl(field.type, "toOwnedSlice"))
791 { 770 {
@@ -812,7 +791,7 @@ pub fn ResultEx(
812 return struct { 791 return struct {
813 args: Arguments(Id, params, value_parsers, .slice), 792 args: Arguments(Id, params, value_parsers, .slice),
814 positionals: []const FindPositionalType(Id, params, value_parsers), 793 positionals: []const FindPositionalType(Id, params, value_parsers),
815 allocator: mem.Allocator, 794 allocator: std.mem.Allocator,
816 795
817 pub fn deinit(result: *@This()) void { 796 pub fn deinit(result: *@This()) void {
818 deinitArgs(Id, params, result.allocator, &result.args); 797 deinitArgs(Id, params, result.allocator, &result.args);
@@ -859,7 +838,7 @@ fn ParamType(
859fn deinitArgs( 838fn deinitArgs(
860 comptime Id: type, 839 comptime Id: type,
861 comptime params: []const Param(Id), 840 comptime params: []const Param(Id),
862 allocator: mem.Allocator, 841 allocator: std.mem.Allocator,
863 arguments: anytype, 842 arguments: anytype,
864) void { 843) void {
865 inline for (params) |param| { 844 inline for (params) |param| {
@@ -899,7 +878,7 @@ fn Arguments(
899 fields_len += 1; 878 fields_len += 1;
900 } 879 }
901 880
902 var fields: [fields_len]builtin.Type.StructField = undefined; 881 var fields: [fields_len]std.builtin.Type.StructField = undefined;
903 var i: usize = 0; 882 var i: usize = 0;
904 for (params) |param| { 883 for (params) |param| {
905 const longest = param.names.longest(); 884 const longest = param.names.longest();
@@ -946,7 +925,7 @@ test "str and u64" {
946 .args = &.{ "--num", "10", "--str", "cooley_rec_inp_ptr" }, 925 .args = &.{ "--num", "10", "--str", "cooley_rec_inp_ptr" },
947 }; 926 };
948 var res = try parseEx(Help, &params, parsers.default, &iter, .{ 927 var res = try parseEx(Help, &params, parsers.default, &iter, .{
949 .allocator = testing.allocator, 928 .allocator = std.testing.allocator,
950 }); 929 });
951 defer res.deinit(); 930 defer res.deinit();
952} 931}
@@ -961,12 +940,12 @@ test "different assignment separators" {
961 .args = &.{ "-a=0", "--aa=1", "-a:2", "--aa:3" }, 940 .args = &.{ "-a=0", "--aa=1", "-a:2", "--aa:3" },
962 }; 941 };
963 var res = try parseEx(Help, &params, parsers.default, &iter, .{ 942 var res = try parseEx(Help, &params, parsers.default, &iter, .{
964 .allocator = testing.allocator, 943 .allocator = std.testing.allocator,
965 .assignment_separators = "=:", 944 .assignment_separators = "=:",
966 }); 945 });
967 defer res.deinit(); 946 defer res.deinit();
968 947
969 try testing.expectEqualSlices(usize, &.{ 0, 1, 2, 3 }, res.args.aa); 948 try std.testing.expectEqualSlices(usize, &.{ 0, 1, 2, 3 }, res.args.aa);
970} 949}
971 950
972test "everything" { 951test "everything" {
@@ -984,18 +963,18 @@ test "everything" {
984 .args = &.{ "-a", "--aa", "-c", "0", "something", "-d", "1", "--dd", "2", "-h" }, 963 .args = &.{ "-a", "--aa", "-c", "0", "something", "-d", "1", "--dd", "2", "-h" },
985 }; 964 };
986 var res = try parseEx(Help, &params, parsers.default, &iter, .{ 965 var res = try parseEx(Help, &params, parsers.default, &iter, .{
987 .allocator = testing.allocator, 966 .allocator = std.testing.allocator,
988 }); 967 });
989 defer res.deinit(); 968 defer res.deinit();
990 969
991 try testing.expect(res.args.aa == 2); 970 try std.testing.expect(res.args.aa == 2);
992 try testing.expect(res.args.bb == 0); 971 try std.testing.expect(res.args.bb == 0);
993 try testing.expect(res.args.h == 1); 972 try std.testing.expect(res.args.h == 1);
994 try testing.expectEqualStrings("0", res.args.cc.?); 973 try std.testing.expectEqualStrings("0", res.args.cc.?);
995 try testing.expectEqual(@as(usize, 1), res.positionals.len); 974 try std.testing.expectEqual(@as(usize, 1), res.positionals.len);
996 try testing.expectEqualStrings("something", res.positionals[0]); 975 try std.testing.expectEqualStrings("something", res.positionals[0]);
997 try testing.expectEqualSlices(usize, &.{ 1, 2 }, res.args.dd); 976 try std.testing.expectEqualSlices(usize, &.{ 1, 2 }, res.args.dd);
998 try testing.expectEqual(@as(usize, 10), iter.index); 977 try std.testing.expectEqual(@as(usize, 10), iter.index);
999} 978}
1000 979
1001test "terminating positional" { 980test "terminating positional" {
@@ -1013,19 +992,19 @@ test "terminating positional" {
1013 .args = &.{ "-a", "--aa", "-c", "0", "something", "-d", "1", "--dd", "2", "-h" }, 992 .args = &.{ "-a", "--aa", "-c", "0", "something", "-d", "1", "--dd", "2", "-h" },
1014 }; 993 };
1015 var res = try parseEx(Help, &params, parsers.default, &iter, .{ 994 var res = try parseEx(Help, &params, parsers.default, &iter, .{
1016 .allocator = testing.allocator, 995 .allocator = std.testing.allocator,
1017 .terminating_positional = 0, 996 .terminating_positional = 0,
1018 }); 997 });
1019 defer res.deinit(); 998 defer res.deinit();
1020 999
1021 try testing.expect(res.args.aa == 2); 1000 try std.testing.expect(res.args.aa == 2);
1022 try testing.expect(res.args.bb == 0); 1001 try std.testing.expect(res.args.bb == 0);
1023 try testing.expect(res.args.h == 0); 1002 try std.testing.expect(res.args.h == 0);
1024 try testing.expectEqualStrings("0", res.args.cc.?); 1003 try std.testing.expectEqualStrings("0", res.args.cc.?);
1025 try testing.expectEqual(@as(usize, 1), res.positionals.len); 1004 try std.testing.expectEqual(@as(usize, 1), res.positionals.len);
1026 try testing.expectEqualStrings("something", res.positionals[0]); 1005 try std.testing.expectEqualStrings("something", res.positionals[0]);
1027 try testing.expectEqualSlices(usize, &.{}, res.args.dd); 1006 try std.testing.expectEqualSlices(usize, &.{}, res.args.dd);
1028 try testing.expectEqual(@as(usize, 5), iter.index); 1007 try std.testing.expectEqual(@as(usize, 5), iter.index);
1029} 1008}
1030 1009
1031test "overflow-safe" { 1010test "overflow-safe" {
@@ -1039,7 +1018,7 @@ test "overflow-safe" {
1039 1018
1040 // This just needs to not crash 1019 // This just needs to not crash
1041 var res = try parseEx(Help, &params, parsers.default, &iter, .{ 1020 var res = try parseEx(Help, &params, parsers.default, &iter, .{
1042 .allocator = testing.allocator, 1021 .allocator = std.testing.allocator,
1043 }); 1022 });
1044 defer res.deinit(); 1023 defer res.deinit();
1045} 1024}
@@ -1047,7 +1026,7 @@ test "overflow-safe" {
1047test "empty" { 1026test "empty" {
1048 var iter = args.SliceIterator{ .args = &.{} }; 1027 var iter = args.SliceIterator{ .args = &.{} };
1049 var res = try parseEx(u8, &[_]Param(u8){}, parsers.default, &iter, .{ 1028 var res = try parseEx(u8, &[_]Param(u8){}, parsers.default, &iter, .{
1050 .allocator = testing.allocator, 1029 .allocator = std.testing.allocator,
1051 }); 1030 });
1052 defer res.deinit(); 1031 defer res.deinit();
1053} 1032}
@@ -1060,17 +1039,17 @@ fn testErr(
1060 var diag = Diagnostic{}; 1039 var diag = Diagnostic{};
1061 var iter = args.SliceIterator{ .args = args_strings }; 1040 var iter = args.SliceIterator{ .args = args_strings };
1062 _ = parseEx(Help, params, parsers.default, &iter, .{ 1041 _ = parseEx(Help, params, parsers.default, &iter, .{
1063 .allocator = testing.allocator, 1042 .allocator = std.testing.allocator,
1064 .diagnostic = &diag, 1043 .diagnostic = &diag,
1065 }) catch |err| { 1044 }) catch |err| {
1066 var buf: [1024]u8 = undefined; 1045 var buf: [1024]u8 = undefined;
1067 var fbs = io.fixedBufferStream(&buf); 1046 var fbs = std.io.fixedBufferStream(&buf);
1068 diag.report(fbs.writer(), err) catch return error.TestFailed; 1047 diag.report(fbs.writer(), err) catch return error.TestFailed;
1069 try testing.expectEqualStrings(expected, fbs.getWritten()); 1048 try std.testing.expectEqualStrings(expected, fbs.getWritten());
1070 return; 1049 return;
1071 }; 1050 };
1072 1051
1073 try testing.expect(false); 1052 try std.testing.expect(false);
1074} 1053}
1075 1054
1076test "errors" { 1055test "errors" {
@@ -1175,7 +1154,7 @@ pub fn help(
1175 const max_spacing = blk: { 1154 const max_spacing = blk: {
1176 var res: usize = 0; 1155 var res: usize = 0;
1177 for (params) |param| { 1156 for (params) |param| {
1178 var cs = ccw.codepointCountingWriter(io.null_writer); 1157 var cs = ccw.codepointCountingWriter(std.io.null_writer);
1179 try printParam(cs.writer(), Id, param); 1158 try printParam(cs.writer(), Id, param);
1180 if (res < cs.codepoints_written) 1159 if (res < cs.codepoints_written)
1181 res = @intCast(cs.codepoints_written); 1160 res = @intCast(cs.codepoints_written);
@@ -1215,9 +1194,9 @@ pub fn help(
1215 1194
1216 var first_line = true; 1195 var first_line = true;
1217 var res: usize = std.math.maxInt(usize); 1196 var res: usize = std.math.maxInt(usize);
1218 var it = mem.tokenizeScalar(u8, description, '\n'); 1197 var it = std.mem.tokenizeScalar(u8, description, '\n');
1219 while (it.next()) |line| : (first_line = false) { 1198 while (it.next()) |line| : (first_line = false) {
1220 const trimmed = mem.trimLeft(u8, line, " "); 1199 const trimmed = std.mem.trimLeft(u8, line, " ");
1221 const indent = line.len - trimmed.len; 1200 const indent = line.len - trimmed.len;
1222 1201
1223 // If the first line has no indentation, then we ignore the indentation of the 1202 // If the first line has no indentation, then we ignore the indentation of the
@@ -1240,18 +1219,18 @@ pub fn help(
1240 }; 1219 };
1241 1220
1242 const description = param.id.description(); 1221 const description = param.id.description();
1243 var it = mem.splitScalar(u8, description, '\n'); 1222 var it = std.mem.splitScalar(u8, description, '\n');
1244 var first_line = true; 1223 var first_line = true;
1245 var non_emitted_newlines: usize = 0; 1224 var non_emitted_newlines: usize = 0;
1246 var last_line_indentation: usize = 0; 1225 var last_line_indentation: usize = 0;
1247 while (it.next()) |raw_line| : (first_line = false) { 1226 while (it.next()) |raw_line| : (first_line = false) {
1248 // First line might be special. See comment above. 1227 // First line might be special. See comment above.
1249 const indented_line = if (first_line and !mem.startsWith(u8, raw_line, " ")) 1228 const indented_line = if (first_line and !std.mem.startsWith(u8, raw_line, " "))
1250 raw_line 1229 raw_line
1251 else 1230 else
1252 raw_line[@min(min_description_indent, raw_line.len)..]; 1231 raw_line[@min(min_description_indent, raw_line.len)..];
1253 1232
1254 const line = mem.trimLeft(u8, indented_line, " "); 1233 const line = std.mem.trimLeft(u8, indented_line, " ");
1255 if (line.len == 0) { 1234 if (line.len == 0) {
1256 non_emitted_newlines += 1; 1235 non_emitted_newlines += 1;
1257 continue; 1236 continue;
@@ -1266,7 +1245,7 @@ pub fn help(
1266 const does_not_have_same_indent_as_last_line = 1245 const does_not_have_same_indent_as_last_line =
1267 line_indentation != last_line_indentation; 1246 line_indentation != last_line_indentation;
1268 1247
1269 const starts_with_control_char = mem.indexOfScalar(u8, "=*", line[0]) != null; 1248 const starts_with_control_char = std.mem.indexOfScalar(u8, "=*", line[0]) != null;
1270 1249
1271 // Either the input contains 2 or more newlines, in which case we should start 1250 // Either the input contains 2 or more newlines, in which case we should start
1272 // a new paragraph. 1251 // a new paragraph.
@@ -1286,7 +1265,7 @@ pub fn help(
1286 try description_writer.newline(); 1265 try description_writer.newline();
1287 } 1266 }
1288 1267
1289 var words = mem.tokenizeScalar(u8, line, ' '); 1268 var words = std.mem.tokenizeScalar(u8, line, ' ');
1290 while (words.next()) |word| 1269 while (words.next()) |word|
1291 try description_writer.writeWord(word); 1270 try description_writer.writeWord(word);
1292 1271
@@ -1310,7 +1289,7 @@ fn DescriptionWriter(comptime UnderlyingWriter: type) type {
1310 printed_chars: usize, 1289 printed_chars: usize,
1311 1290
1312 pub fn writeWord(writer: *@This(), word: []const u8) !void { 1291 pub fn writeWord(writer: *@This(), word: []const u8) !void {
1313 debug.assert(word.len != 0); 1292 std.debug.assert(word.len != 0);
1314 1293
1315 var first_word = writer.printed_chars <= writer.indentation; 1294 var first_word = writer.printed_chars <= writer.indentation;
1316 const chars_to_write = try std.unicode.utf8CountCodepoints(word) + @intFromBool(!first_word); 1295 const chars_to_write = try std.unicode.utf8CountCodepoints(word) + @intFromBool(!first_word);
@@ -1380,13 +1359,13 @@ fn printParam(
1380} 1359}
1381 1360
1382fn testHelp(opt: HelpOptions, str: []const u8) !void { 1361fn testHelp(opt: HelpOptions, str: []const u8) !void {
1383 const params = try parseParams(testing.allocator, str); 1362 const params = try parseParams(std.testing.allocator, str);
1384 defer testing.allocator.free(params); 1363 defer std.testing.allocator.free(params);
1385 1364
1386 var buf: [2048]u8 = undefined; 1365 var buf: [2048]u8 = undefined;
1387 var fbs = io.fixedBufferStream(&buf); 1366 var fbs = std.io.fixedBufferStream(&buf);
1388 try help(fbs.writer(), Help, params, opt); 1367 try help(fbs.writer(), Help, params, opt);
1389 try testing.expectEqualStrings(str, fbs.getWritten()); 1368 try std.testing.expectEqualStrings(str, fbs.getWritten());
1390} 1369}
1391 1370
1392test "clap.help" { 1371test "clap.help" {
@@ -1884,9 +1863,9 @@ pub fn usage(stream: anytype, comptime Id: type, params: []const Param(Id)) !voi
1884 1863
1885fn testUsage(expected: []const u8, params: []const Param(Help)) !void { 1864fn testUsage(expected: []const u8, params: []const Param(Help)) !void {
1886 var buf: [1024]u8 = undefined; 1865 var buf: [1024]u8 = undefined;
1887 var fbs = io.fixedBufferStream(&buf); 1866 var fbs = std.io.fixedBufferStream(&buf);
1888 try usage(fbs.writer(), Help, params); 1867 try usage(fbs.writer(), Help, params);
1889 try testing.expectEqualStrings(expected, fbs.getWritten()); 1868 try std.testing.expectEqualStrings(expected, fbs.getWritten());
1890} 1869}
1891 1870
1892test "usage" { 1871test "usage" {
@@ -1948,3 +1927,17 @@ test "usage" {
1948 \\ 1927 \\
1949 )); 1928 ));
1950} 1929}
1930
1931test {
1932 _ = args;
1933 _ = parsers;
1934 _ = streaming;
1935 _ = ccw;
1936}
1937
1938pub const args = @import("clap/args.zig");
1939pub const parsers = @import("clap/parsers.zig");
1940pub const streaming = @import("clap/streaming.zig");
1941pub const ccw = @import("clap/codepoint_counting_writer.zig");
1942
1943const std = @import("std");
diff --git a/clap/args.zig b/clap/args.zig
index d0aaee3..6a424e3 100644
--- a/clap/args.zig
+++ b/clap/args.zig
@@ -1,12 +1,3 @@
1const builtin = @import("builtin");
2const std = @import("std");
3
4const debug = std.debug;
5const heap = std.heap;
6const mem = std.mem;
7const process = std.process;
8const testing = std.testing;
9
10/// An example of what methods should be implemented on an arg iterator. 1/// An example of what methods should be implemented on an arg iterator.
11pub const ExampleArgIterator = struct { 2pub const ExampleArgIterator = struct {
12 pub fn next(iter: *ExampleArgIterator) ?[]const u8 { 3 pub fn next(iter: *ExampleArgIterator) ?[]const u8 {
@@ -35,7 +26,9 @@ test "SliceIterator" {
35 var iter = SliceIterator{ .args = &args }; 26 var iter = SliceIterator{ .args = &args };
36 27
37 for (args) |a| 28 for (args) |a|
38 try testing.expectEqualStrings(a, iter.next().?); 29 try std.testing.expectEqualStrings(a, iter.next().?);
39 30
40 try testing.expectEqual(@as(?[]const u8, null), iter.next()); 31 try std.testing.expectEqual(@as(?[]const u8, null), iter.next());
41} 32}
33
34const std = @import("std");
diff --git a/clap/codepoint_counting_writer.zig b/clap/codepoint_counting_writer.zig
index e6b9d1c..c445c90 100644
--- a/clap/codepoint_counting_writer.zig
+++ b/clap/codepoint_counting_writer.zig
@@ -1,7 +1,3 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const native_endian = builtin.cpu.arch.endian();
4
5/// A Writer that counts how many codepoints has been written to it. 1/// A Writer that counts how many codepoints has been written to it.
6/// Expects valid UTF-8 input, and does not validate the input. 2/// Expects valid UTF-8 input, and does not validate the input.
7pub fn CodepointCountingWriter(comptime WriterType: type) type { 3pub fn CodepointCountingWriter(comptime WriterType: type) type {
@@ -34,6 +30,7 @@ pub fn CodepointCountingWriter(comptime WriterType: type) type {
34// the number of codepoints up to that point. 30// the number of codepoints up to that point.
35// Does not validate UTF-8 beyond checking the start byte. 31// Does not validate UTF-8 beyond checking the start byte.
36fn utf8CountCodepointsAllowTruncate(s: []const u8) !struct { bytes: usize, codepoints: usize } { 32fn utf8CountCodepointsAllowTruncate(s: []const u8) !struct { bytes: usize, codepoints: usize } {
33 const native_endian = @import("builtin").cpu.arch.endian();
37 var len: usize = 0; 34 var len: usize = 0;
38 35
39 const N = @sizeOf(usize); 36 const N = @sizeOf(usize);
@@ -100,3 +97,5 @@ test "handles partial UTF-8 writes" {
100 97
101 try testing.expectEqualSlices(u8, utf8_text, fbs.getWritten()); 98 try testing.expectEqualSlices(u8, utf8_text, fbs.getWritten());
102} 99}
100
101const std = @import("std");
diff --git a/clap/parsers.zig b/clap/parsers.zig
index 8abdf57..2bf8976 100644
--- a/clap/parsers.zig
+++ b/clap/parsers.zig
@@ -1,8 +1,3 @@
1const std = @import("std");
2
3const fmt = std.fmt;
4const testing = std.testing;
5
6pub const default = .{ 1pub const default = .{
7 .string = string, 2 .string = string,
8 .str = string, 3 .str = string,
@@ -26,46 +21,46 @@ pub fn string(in: []const u8) error{}![]const u8 {
26} 21}
27 22
28test "string" { 23test "string" {
29 try testing.expectEqualStrings("aa", try string("aa")); 24 try std.testing.expectEqualStrings("aa", try string("aa"));
30} 25}
31 26
32/// A parser that uses `std.fmt.parseInt` to parse the string into an integer value. 27/// A parser that uses `std.fmt.parseInt` to parse the string into an integer value.
33/// See `std.fmt.parseInt` documentation for more information. 28/// See `std.fmt.parseInt` documentation for more information.
34pub fn int(comptime T: type, comptime base: u8) fn ([]const u8) fmt.ParseIntError!T { 29pub fn int(comptime T: type, comptime base: u8) fn ([]const u8) std.fmt.ParseIntError!T {
35 return struct { 30 return struct {
36 fn parse(in: []const u8) fmt.ParseIntError!T { 31 fn parse(in: []const u8) std.fmt.ParseIntError!T {
37 return fmt.parseInt(T, in, base); 32 return std.fmt.parseInt(T, in, base);
38 } 33 }
39 }.parse; 34 }.parse;
40} 35}
41 36
42test "int" { 37test "int" {
43 try testing.expectEqual(@as(u8, 0), try int(u8, 10)("0")); 38 try std.testing.expectEqual(@as(u8, 0), try int(u8, 10)("0"));
44 try testing.expectEqual(@as(u8, 1), try int(u8, 10)("1")); 39 try std.testing.expectEqual(@as(u8, 1), try int(u8, 10)("1"));
45 try testing.expectEqual(@as(u8, 10), try int(u8, 10)("10")); 40 try std.testing.expectEqual(@as(u8, 10), try int(u8, 10)("10"));
46 try testing.expectEqual(@as(u8, 0b10), try int(u8, 2)("10")); 41 try std.testing.expectEqual(@as(u8, 0b10), try int(u8, 2)("10"));
47 try testing.expectEqual(@as(u8, 0x10), try int(u8, 0)("0x10")); 42 try std.testing.expectEqual(@as(u8, 0x10), try int(u8, 0)("0x10"));
48 try testing.expectEqual(@as(u8, 0b10), try int(u8, 0)("0b10")); 43 try std.testing.expectEqual(@as(u8, 0b10), try int(u8, 0)("0b10"));
49 try testing.expectEqual(@as(u16, 0), try int(u16, 10)("0")); 44 try std.testing.expectEqual(@as(u16, 0), try int(u16, 10)("0"));
50 try testing.expectEqual(@as(u16, 1), try int(u16, 10)("1")); 45 try std.testing.expectEqual(@as(u16, 1), try int(u16, 10)("1"));
51 try testing.expectEqual(@as(u16, 10), try int(u16, 10)("10")); 46 try std.testing.expectEqual(@as(u16, 10), try int(u16, 10)("10"));
52 try testing.expectEqual(@as(u16, 0b10), try int(u16, 2)("10")); 47 try std.testing.expectEqual(@as(u16, 0b10), try int(u16, 2)("10"));
53 try testing.expectEqual(@as(u16, 0x10), try int(u16, 0)("0x10")); 48 try std.testing.expectEqual(@as(u16, 0x10), try int(u16, 0)("0x10"));
54 try testing.expectEqual(@as(u16, 0b10), try int(u16, 0)("0b10")); 49 try std.testing.expectEqual(@as(u16, 0b10), try int(u16, 0)("0b10"));
55} 50}
56 51
57/// A parser that uses `std.fmt.parseFloat` to parse the string into an float value. 52/// A parser that uses `std.fmt.parseFloat` to parse the string into an float value.
58/// See `std.fmt.parseFloat` documentation for more information. 53/// See `std.fmt.parseFloat` documentation for more information.
59pub fn float(comptime T: type) fn ([]const u8) fmt.ParseFloatError!T { 54pub fn float(comptime T: type) fn ([]const u8) std.fmt.ParseFloatError!T {
60 return struct { 55 return struct {
61 fn parse(in: []const u8) fmt.ParseFloatError!T { 56 fn parse(in: []const u8) std.fmt.ParseFloatError!T {
62 return fmt.parseFloat(T, in); 57 return std.fmt.parseFloat(T, in);
63 } 58 }
64 }.parse; 59 }.parse;
65} 60}
66 61
67test "float" { 62test "float" {
68 try testing.expectEqual(@as(f32, 0), try float(f32)("0")); 63 try std.testing.expectEqual(@as(f32, 0), try float(f32)("0"));
69} 64}
70 65
71pub const EnumError = error{ 66pub const EnumError = error{
@@ -85,10 +80,10 @@ pub fn enumeration(comptime T: type) fn ([]const u8) EnumError!T {
85 80
86test "enumeration" { 81test "enumeration" {
87 const E = enum { a, b, c }; 82 const E = enum { a, b, c };
88 try testing.expectEqual(E.a, try enumeration(E)("a")); 83 try std.testing.expectEqual(E.a, try enumeration(E)("a"));
89 try testing.expectEqual(E.b, try enumeration(E)("b")); 84 try std.testing.expectEqual(E.b, try enumeration(E)("b"));
90 try testing.expectEqual(E.c, try enumeration(E)("c")); 85 try std.testing.expectEqual(E.c, try enumeration(E)("c"));
91 try testing.expectError(EnumError.NameNotPartOfEnum, enumeration(E)("d")); 86 try std.testing.expectError(EnumError.NameNotPartOfEnum, enumeration(E)("d"));
92} 87}
93 88
94fn ReturnType(comptime P: type) type { 89fn ReturnType(comptime P: type) type {
@@ -98,3 +93,5 @@ fn ReturnType(comptime P: type) type {
98pub fn Result(comptime P: type) type { 93pub fn Result(comptime P: type) type {
99 return @typeInfo(ReturnType(P)).error_union.payload; 94 return @typeInfo(ReturnType(P)).error_union.payload;
100} 95}
96
97const std = @import("std");
diff --git a/clap/streaming.zig b/clap/streaming.zig
index eba84bb..4a687a2 100644
--- a/clap/streaming.zig
+++ b/clap/streaming.zig
@@ -1,15 +1,3 @@
1const builtin = @import("builtin");
2const clap = @import("../clap.zig");
3const std = @import("std");
4
5const args = clap.args;
6const debug = std.debug;
7const heap = std.heap;
8const io = std.io;
9const mem = std.mem;
10const os = std.os;
11const testing = std.testing;
12
13/// The result returned from Clap.next 1/// The result returned from Clap.next
14pub fn Arg(comptime Id: type) type { 2pub fn Arg(comptime Id: type) type {
15 return struct { 3 return struct {
@@ -71,14 +59,14 @@ pub fn Clap(comptime Id: type, comptime ArgIterator: type) type {
71 const arg = arg_info.arg; 59 const arg = arg_info.arg;
72 switch (arg_info.kind) { 60 switch (arg_info.kind) {
73 .long => { 61 .long => {
74 const eql_index = mem.indexOfAny(u8, arg, parser.assignment_separators); 62 const eql_index = std.mem.indexOfAny(u8, arg, parser.assignment_separators);
75 const name = if (eql_index) |i| arg[0..i] else arg; 63 const name = if (eql_index) |i| arg[0..i] else arg;
76 const maybe_value = if (eql_index) |i| arg[i + 1 ..] else null; 64 const maybe_value = if (eql_index) |i| arg[i + 1 ..] else null;
77 65
78 for (parser.params) |*param| { 66 for (parser.params) |*param| {
79 const match = param.names.long orelse continue; 67 const match = param.names.long orelse continue;
80 68
81 if (!mem.eql(u8, name, match)) 69 if (!std.mem.eql(u8, name, match))
82 continue; 70 continue;
83 if (param.takes_value == .none) { 71 if (param.takes_value == .none) {
84 if (maybe_value != null) 72 if (maybe_value != null)
@@ -108,7 +96,7 @@ pub fn Clap(comptime Id: type, comptime ArgIterator: type) type {
108 // If we find a positional with the value `--` then we 96 // If we find a positional with the value `--` then we
109 // interpret the rest of the arguments as positional 97 // interpret the rest of the arguments as positional
110 // arguments. 98 // arguments.
111 if (mem.eql(u8, arg, "--")) { 99 if (std.mem.eql(u8, arg, "--")) {
112 parser.state = .rest_are_positional; 100 parser.state = .rest_are_positional;
113 const value = parser.iter.next() orelse return null; 101 const value = parser.iter.next() orelse return null;
114 return Arg(Id){ .param = param, .value = value }; 102 return Arg(Id){ .param = param, .value = value };
@@ -200,11 +188,11 @@ pub fn Clap(comptime Id: type, comptime ArgIterator: type) type {
200 188
201 fn parseNextArg(parser: *@This()) !?ArgInfo { 189 fn parseNextArg(parser: *@This()) !?ArgInfo {
202 const full_arg = parser.iter.next() orelse return null; 190 const full_arg = parser.iter.next() orelse return null;
203 if (mem.eql(u8, full_arg, "--") or mem.eql(u8, full_arg, "-")) 191 if (std.mem.eql(u8, full_arg, "--") or std.mem.eql(u8, full_arg, "-"))
204 return ArgInfo{ .arg = full_arg, .kind = .positional }; 192 return ArgInfo{ .arg = full_arg, .kind = .positional };
205 if (mem.startsWith(u8, full_arg, "--")) 193 if (std.mem.startsWith(u8, full_arg, "--"))
206 return ArgInfo{ .arg = full_arg[2..], .kind = .long }; 194 return ArgInfo{ .arg = full_arg[2..], .kind = .long };
207 if (mem.startsWith(u8, full_arg, "-")) 195 if (std.mem.startsWith(u8, full_arg, "-"))
208 return ArgInfo{ .arg = full_arg[1..], .kind = .short }; 196 return ArgInfo{ .arg = full_arg[1..], .kind = .short };
209 197
210 return ArgInfo{ .arg = full_arg, .kind = .positional }; 198 return ArgInfo{ .arg = full_arg, .kind = .positional };
@@ -219,18 +207,18 @@ pub fn Clap(comptime Id: type, comptime ArgIterator: type) type {
219} 207}
220 208
221fn expectArgs( 209fn expectArgs(
222 parser: *Clap(u8, args.SliceIterator), 210 parser: *Clap(u8, clap.args.SliceIterator),
223 results: []const Arg(u8), 211 results: []const Arg(u8),
224) !void { 212) !void {
225 for (results) |res| { 213 for (results) |res| {
226 const arg = (try parser.next()) orelse return error.TestFailed; 214 const arg = (try parser.next()) orelse return error.TestFailed;
227 try testing.expectEqual(res.param, arg.param); 215 try std.testing.expectEqual(res.param, arg.param);
228 const expected_value = res.value orelse { 216 const expected_value = res.value orelse {
229 try testing.expectEqual(@as(@TypeOf(arg.value), null), arg.value); 217 try std.testing.expectEqual(@as(@TypeOf(arg.value), null), arg.value);
230 continue; 218 continue;
231 }; 219 };
232 const actual_value = arg.value orelse return error.TestFailed; 220 const actual_value = arg.value orelse return error.TestFailed;
233 try testing.expectEqualSlices(u8, expected_value, actual_value); 221 try std.testing.expectEqualSlices(u8, expected_value, actual_value);
234 } 222 }
235 223
236 if (try parser.next()) |_| 224 if (try parser.next()) |_|
@@ -238,7 +226,7 @@ fn expectArgs(
238} 226}
239 227
240fn expectError( 228fn expectError(
241 parser: *Clap(u8, args.SliceIterator), 229 parser: *Clap(u8, clap.args.SliceIterator),
242 expected: []const u8, 230 expected: []const u8,
243) !void { 231) !void {
244 var diag: clap.Diagnostic = .{}; 232 var diag: clap.Diagnostic = .{};
@@ -246,13 +234,13 @@ fn expectError(
246 234
247 while (parser.next() catch |err| { 235 while (parser.next() catch |err| {
248 var buf: [1024]u8 = undefined; 236 var buf: [1024]u8 = undefined;
249 var fbs = io.fixedBufferStream(&buf); 237 var fbs = std.io.fixedBufferStream(&buf);
250 diag.report(fbs.writer(), err) catch return error.TestFailed; 238 diag.report(fbs.writer(), err) catch return error.TestFailed;
251 try testing.expectEqualStrings(expected, fbs.getWritten()); 239 try std.testing.expectEqualStrings(expected, fbs.getWritten());
252 return; 240 return;
253 }) |_| {} 241 }) |_| {}
254 242
255 try testing.expect(false); 243 try std.testing.expect(false);
256} 244}
257 245
258test "short params" { 246test "short params" {
@@ -276,12 +264,12 @@ test "short params" {
276 const c = &params[2]; 264 const c = &params[2];
277 const d = &params[3]; 265 const d = &params[3];
278 266
279 var iter = args.SliceIterator{ .args = &.{ 267 var iter = clap.args.SliceIterator{ .args = &.{
280 "-a", "-b", "-ab", "-ba", 268 "-a", "-b", "-ab", "-ba",
281 "-c", "0", "-c=0", "-ac", 269 "-c", "0", "-c=0", "-ac",
282 "0", "-ac=0", "-d=0", 270 "0", "-ac=0", "-d=0",
283 } }; 271 } };
284 var parser = Clap(u8, args.SliceIterator){ .params = &params, .iter = &iter }; 272 var parser = Clap(u8, clap.args.SliceIterator){ .params = &params, .iter = &iter };
285 273
286 try expectArgs(&parser, &.{ 274 try expectArgs(&parser, &.{
287 .{ .param = a }, 275 .{ .param = a },
@@ -321,12 +309,12 @@ test "long params" {
321 const cc = &params[2]; 309 const cc = &params[2];
322 const dd = &params[3]; 310 const dd = &params[3];
323 311
324 var iter = args.SliceIterator{ .args = &.{ 312 var iter = clap.args.SliceIterator{ .args = &.{
325 "--aa", "--bb", 313 "--aa", "--bb",
326 "--cc", "0", 314 "--cc", "0",
327 "--cc=0", "--dd=0", 315 "--cc=0", "--dd=0",
328 } }; 316 } };
329 var parser = Clap(u8, args.SliceIterator){ .params = &params, .iter = &iter }; 317 var parser = Clap(u8, clap.args.SliceIterator){ .params = &params, .iter = &iter };
330 318
331 try expectArgs(&parser, &.{ 319 try expectArgs(&parser, &.{
332 .{ .param = aa }, 320 .{ .param = aa },
@@ -343,11 +331,11 @@ test "positional params" {
343 .takes_value = .one, 331 .takes_value = .one,
344 }}; 332 }};
345 333
346 var iter = args.SliceIterator{ .args = &.{ 334 var iter = clap.args.SliceIterator{ .args = &.{
347 "aa", 335 "aa",
348 "bb", 336 "bb",
349 } }; 337 } };
350 var parser = Clap(u8, args.SliceIterator){ .params = &params, .iter = &iter }; 338 var parser = Clap(u8, clap.args.SliceIterator){ .params = &params, .iter = &iter };
351 339
352 try expectArgs(&parser, &.{ 340 try expectArgs(&parser, &.{
353 .{ .param = &params[0], .value = "aa" }, 341 .{ .param = &params[0], .value = "aa" },
@@ -378,14 +366,14 @@ test "all params" {
378 const cc = &params[2]; 366 const cc = &params[2];
379 const positional = &params[3]; 367 const positional = &params[3];
380 368
381 var iter = args.SliceIterator{ .args = &.{ 369 var iter = clap.args.SliceIterator{ .args = &.{
382 "-a", "-b", "-ab", "-ba", 370 "-a", "-b", "-ab", "-ba",
383 "-c", "0", "-c=0", "-ac", 371 "-c", "0", "-c=0", "-ac",
384 "0", "-ac=0", "--aa", "--bb", 372 "0", "-ac=0", "--aa", "--bb",
385 "--cc", "0", "--cc=0", "something", 373 "--cc", "0", "--cc=0", "something",
386 "-", "--", "--cc=0", "-a", 374 "-", "--", "--cc=0", "-a",
387 } }; 375 } };
388 var parser = Clap(u8, args.SliceIterator){ .params = &params, .iter = &iter }; 376 var parser = Clap(u8, clap.args.SliceIterator){ .params = &params, .iter = &iter };
389 377
390 try expectArgs(&parser, &.{ 378 try expectArgs(&parser, &.{
391 .{ .param = aa }, 379 .{ .param = aa },
@@ -422,11 +410,11 @@ test "different assignment separators" {
422 410
423 const aa = &params[0]; 411 const aa = &params[0];
424 412
425 var iter = args.SliceIterator{ .args = &.{ 413 var iter = clap.args.SliceIterator{ .args = &.{
426 "-a=0", "--aa=0", 414 "-a=0", "--aa=0",
427 "-a:0", "--aa:0", 415 "-a:0", "--aa:0",
428 } }; 416 } };
429 var parser = Clap(u8, args.SliceIterator){ 417 var parser = Clap(u8, clap.args.SliceIterator){
430 .params = &params, 418 .params = &params,
431 .iter = &iter, 419 .iter = &iter,
432 .assignment_separators = "=:", 420 .assignment_separators = "=:",
@@ -453,35 +441,38 @@ test "errors" {
453 }, 441 },
454 }; 442 };
455 443
456 var iter = args.SliceIterator{ .args = &.{"q"} }; 444 var iter = clap.args.SliceIterator{ .args = &.{"q"} };
457 var parser = Clap(u8, args.SliceIterator){ .params = &params, .iter = &iter }; 445 var parser = Clap(u8, clap.args.SliceIterator){ .params = &params, .iter = &iter };
458 try expectError(&parser, "Invalid argument 'q'\n"); 446 try expectError(&parser, "Invalid argument 'q'\n");
459 447
460 iter = args.SliceIterator{ .args = &.{"-q"} }; 448 iter = clap.args.SliceIterator{ .args = &.{"-q"} };
461 parser = Clap(u8, args.SliceIterator){ .params = &params, .iter = &iter }; 449 parser = Clap(u8, clap.args.SliceIterator){ .params = &params, .iter = &iter };
462 try expectError(&parser, "Invalid argument '-q'\n"); 450 try expectError(&parser, "Invalid argument '-q'\n");
463 451
464 iter = args.SliceIterator{ .args = &.{"--q"} }; 452 iter = clap.args.SliceIterator{ .args = &.{"--q"} };
465 parser = Clap(u8, args.SliceIterator){ .params = &params, .iter = &iter }; 453 parser = Clap(u8, clap.args.SliceIterator){ .params = &params, .iter = &iter };
466 try expectError(&parser, "Invalid argument '--q'\n"); 454 try expectError(&parser, "Invalid argument '--q'\n");
467 455
468 iter = args.SliceIterator{ .args = &.{"--q=1"} }; 456 iter = clap.args.SliceIterator{ .args = &.{"--q=1"} };
469 parser = Clap(u8, args.SliceIterator){ .params = &params, .iter = &iter }; 457 parser = Clap(u8, clap.args.SliceIterator){ .params = &params, .iter = &iter };
470 try expectError(&parser, "Invalid argument '--q'\n"); 458 try expectError(&parser, "Invalid argument '--q'\n");
471 459
472 iter = args.SliceIterator{ .args = &.{"-a=1"} }; 460 iter = clap.args.SliceIterator{ .args = &.{"-a=1"} };
473 parser = Clap(u8, args.SliceIterator){ .params = &params, .iter = &iter }; 461 parser = Clap(u8, clap.args.SliceIterator){ .params = &params, .iter = &iter };
474 try expectError(&parser, "The argument '-a' does not take a value\n"); 462 try expectError(&parser, "The argument '-a' does not take a value\n");
475 463
476 iter = args.SliceIterator{ .args = &.{"--aa=1"} }; 464 iter = clap.args.SliceIterator{ .args = &.{"--aa=1"} };
477 parser = Clap(u8, args.SliceIterator){ .params = &params, .iter = &iter }; 465 parser = Clap(u8, clap.args.SliceIterator){ .params = &params, .iter = &iter };
478 try expectError(&parser, "The argument '--aa' does not take a value\n"); 466 try expectError(&parser, "The argument '--aa' does not take a value\n");
479 467
480 iter = args.SliceIterator{ .args = &.{"-c"} }; 468 iter = clap.args.SliceIterator{ .args = &.{"-c"} };
481 parser = Clap(u8, args.SliceIterator){ .params = &params, .iter = &iter }; 469 parser = Clap(u8, clap.args.SliceIterator){ .params = &params, .iter = &iter };
482 try expectError(&parser, "The argument '-c' requires a value but none was supplied\n"); 470 try expectError(&parser, "The argument '-c' requires a value but none was supplied\n");
483 471
484 iter = args.SliceIterator{ .args = &.{"--cc"} }; 472 iter = clap.args.SliceIterator{ .args = &.{"--cc"} };
485 parser = Clap(u8, args.SliceIterator){ .params = &params, .iter = &iter }; 473 parser = Clap(u8, clap.args.SliceIterator){ .params = &params, .iter = &iter };
486 try expectError(&parser, "The argument '--cc' requires a value but none was supplied\n"); 474 try expectError(&parser, "The argument '--cc' requires a value but none was supplied\n");
487} 475}
476
477const clap = @import("../clap.zig");
478const std = @import("std");
diff --git a/example/help.zig b/example/help.zig
index 2f063c5..b80ee35 100644
--- a/example/help.zig
+++ b/example/help.zig
@@ -1,6 +1,3 @@
1const clap = @import("clap");
2const std = @import("std");
3
4pub fn main() !void { 1pub fn main() !void {
5 var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 2 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
6 defer _ = gpa.deinit(); 3 defer _ = gpa.deinit();
@@ -17,9 +14,12 @@ pub fn main() !void {
17 defer res.deinit(); 14 defer res.deinit();
18 15
19 // `clap.help` is a function that can print a simple help message. It can print any `Param` 16 // `clap.help` is a function that can print a simple help message. It can print any `Param`
20 // where `Id` has a `describtion` and `value` method (`Param(Help)` is one such parameter). 17 // where `Id` has a `description` and `value` method (`Param(Help)` is one such parameter).
21 // The last argument contains options as to how `help` should print those parameters. Using 18 // The last argument contains options as to how `help` should print those parameters. Using
22 // `.{}` means the default options. 19 // `.{}` means the default options.
23 if (res.args.help != 0) 20 if (res.args.help != 0)
24 return clap.help(std.io.getStdErr().writer(), clap.Help, &params, .{}); 21 return clap.help(std.io.getStdErr().writer(), clap.Help, &params, .{});
25} 22}
23
24const clap = @import("clap");
25const std = @import("std");
diff --git a/example/simple-ex.zig b/example/simple-ex.zig
index 2943f4e..4ca9791 100644
--- a/example/simple-ex.zig
+++ b/example/simple-ex.zig
@@ -1,10 +1,3 @@
1const clap = @import("clap");
2const std = @import("std");
3
4const debug = std.debug;
5const io = std.io;
6const process = std.process;
7
8pub fn main() !void { 1pub fn main() !void {
9 var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 2 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
10 defer _ = gpa.deinit(); 3 defer _ = gpa.deinit();
@@ -38,19 +31,22 @@ pub fn main() !void {
38 // allowed. 31 // allowed.
39 .assignment_separators = "=:", 32 .assignment_separators = "=:",
40 }) catch |err| { 33 }) catch |err| {
41 diag.report(io.getStdErr().writer(), err) catch {}; 34 diag.report(std.io.getStdErr().writer(), err) catch {};
42 return err; 35 return err;
43 }; 36 };
44 defer res.deinit(); 37 defer res.deinit();
45 38
46 if (res.args.help != 0) 39 if (res.args.help != 0)
47 debug.print("--help\n", .{}); 40 std.debug.print("--help\n", .{});
48 if (res.args.number) |n| 41 if (res.args.number) |n|
49 debug.print("--number = {}\n", .{n}); 42 std.debug.print("--number = {}\n", .{n});
50 if (res.args.answer) |a| 43 if (res.args.answer) |a|
51 debug.print("--answer = {s}\n", .{@tagName(a)}); 44 std.debug.print("--answer = {s}\n", .{@tagName(a)});
52 for (res.args.string) |s| 45 for (res.args.string) |s|
53 debug.print("--string = {s}\n", .{s}); 46 std.debug.print("--string = {s}\n", .{s});
54 for (res.positionals) |pos| 47 for (res.positionals) |pos|
55 debug.print("{s}\n", .{pos}); 48 std.debug.print("{s}\n", .{pos});
56} 49}
50
51const clap = @import("clap");
52const std = @import("std");
diff --git a/example/simple.zig b/example/simple.zig
index a7207c7..7f1bfc0 100644
--- a/example/simple.zig
+++ b/example/simple.zig
@@ -1,9 +1,3 @@
1const clap = @import("clap");
2const std = @import("std");
3
4const debug = std.debug;
5const io = std.io;
6
7pub fn main() !void { 1pub fn main() !void {
8 var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 2 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
9 defer _ = gpa.deinit(); 3 defer _ = gpa.deinit();
@@ -27,17 +21,20 @@ pub fn main() !void {
27 .allocator = gpa.allocator(), 21 .allocator = gpa.allocator(),
28 }) catch |err| { 22 }) catch |err| {
29 // Report useful error and exit 23 // Report useful error and exit
30 diag.report(io.getStdErr().writer(), err) catch {}; 24 diag.report(std.io.getStdErr().writer(), err) catch {};
31 return err; 25 return err;
32 }; 26 };
33 defer res.deinit(); 27 defer res.deinit();
34 28
35 if (res.args.help != 0) 29 if (res.args.help != 0)
36 debug.print("--help\n", .{}); 30 std.debug.print("--help\n", .{});
37 if (res.args.number) |n| 31 if (res.args.number) |n|
38 debug.print("--number = {}\n", .{n}); 32 std.debug.print("--number = {}\n", .{n});
39 for (res.args.string) |s| 33 for (res.args.string) |s|
40 debug.print("--string = {s}\n", .{s}); 34 std.debug.print("--string = {s}\n", .{s});
41 for (res.positionals) |pos| 35 for (res.positionals) |pos|
42 debug.print("{s}\n", .{pos}); 36 std.debug.print("{s}\n", .{pos});
43} 37}
38
39const clap = @import("clap");
40const std = @import("std");
diff --git a/example/streaming-clap.zig b/example/streaming-clap.zig
index 9d99859..2a20bcb 100644
--- a/example/streaming-clap.zig
+++ b/example/streaming-clap.zig
@@ -1,10 +1,3 @@
1const clap = @import("clap");
2const std = @import("std");
3
4const debug = std.debug;
5const io = std.io;
6const process = std.process;
7
8pub fn main() !void { 1pub fn main() !void {
9 const allocator = std.heap.page_allocator; 2 const allocator = std.heap.page_allocator;
10 3
@@ -22,7 +15,7 @@ pub fn main() !void {
22 .{ .id = 'f', .takes_value = .one }, 15 .{ .id = 'f', .takes_value = .one },
23 }; 16 };
24 17
25 var iter = try process.ArgIterator.initWithAllocator(allocator); 18 var iter = try std.process.ArgIterator.initWithAllocator(allocator);
26 defer iter.deinit(); 19 defer iter.deinit();
27 20
28 // Skip exe argument 21 // Skip exe argument
@@ -32,7 +25,7 @@ pub fn main() !void {
32 // This is optional. You can also leave the `diagnostic` field unset if you 25 // This is optional. You can also leave the `diagnostic` field unset if you
33 // don't care about the extra information `Diagnostic` provides. 26 // don't care about the extra information `Diagnostic` provides.
34 var diag = clap.Diagnostic{}; 27 var diag = clap.Diagnostic{};
35 var parser = clap.streaming.Clap(u8, process.ArgIterator){ 28 var parser = clap.streaming.Clap(u8, std.process.ArgIterator){
36 .params = &params, 29 .params = &params,
37 .iter = &iter, 30 .iter = &iter,
38 .diagnostic = &diag, 31 .diagnostic = &diag,
@@ -41,19 +34,22 @@ pub fn main() !void {
41 // Because we use a streaming parser, we have to consume each argument parsed individually. 34 // Because we use a streaming parser, we have to consume each argument parsed individually.
42 while (parser.next() catch |err| { 35 while (parser.next() catch |err| {
43 // Report useful error and exit 36 // Report useful error and exit
44 diag.report(io.getStdErr().writer(), err) catch {}; 37 diag.report(std.io.getStdErr().writer(), err) catch {};
45 return err; 38 return err;
46 }) |arg| { 39 }) |arg| {
47 // arg.param will point to the parameter which matched the argument. 40 // arg.param will point to the parameter which matched the argument.
48 switch (arg.param.id) { 41 switch (arg.param.id) {
49 'h' => debug.print("Help!\n", .{}), 42 'h' => std.debug.print("Help!\n", .{}),
50 'n' => debug.print("--number = {s}\n", .{arg.value.?}), 43 'n' => std.debug.print("--number = {s}\n", .{arg.value.?}),
51 44
52 // arg.value == null, if arg.param.takes_value == .none. 45 // arg.value == null, if arg.param.takes_value == .none.
53 // Otherwise, arg.value is the value passed with the argument, such as "-a=10" 46 // Otherwise, arg.value is the value passed with the argument, such as "-a=10"
54 // or "-a 10". 47 // or "-a 10".
55 'f' => debug.print("{s}\n", .{arg.value.?}), 48 'f' => std.debug.print("{s}\n", .{arg.value.?}),
56 else => unreachable, 49 else => unreachable,
57 } 50 }
58 } 51 }
59} 52}
53
54const clap = @import("clap");
55const std = @import("std");
diff --git a/example/usage.zig b/example/usage.zig
index a773dd2..59ac84a 100644
--- a/example/usage.zig
+++ b/example/usage.zig
@@ -1,6 +1,3 @@
1const clap = @import("clap");
2const std = @import("std");
3
4pub fn main() !void { 1pub fn main() !void {
5 var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 2 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
6 defer _ = gpa.deinit(); 3 defer _ = gpa.deinit();
@@ -22,3 +19,6 @@ pub fn main() !void {
22 if (res.args.help != 0) 19 if (res.args.help != 0)
23 return clap.usage(std.io.getStdErr().writer(), clap.Help, &params); 20 return clap.usage(std.io.getStdErr().writer(), clap.Help, &params);
24} 21}
22
23const clap = @import("clap");
24const std = @import("std");