From e00e90270102e659ac6a5f3a20353f7317091505 Mon Sep 17 00:00:00 2001 From: Meghan Date: Mon, 15 Feb 2021 15:30:26 -0800 Subject: zig.mod- add license field --- zig.mod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zig.mod b/zig.mod index c9bd69f..00c1a69 100644 --- a/zig.mod +++ b/zig.mod @@ -1,3 +1,5 @@ +id: aoe2l16htluewam6bfwvv0khsbbno8g8jd7suonifg74u7kd name: clap main: clap.zig +license: Unlicense dependencies: -- cgit v1.2.3 From 76a6d9fbe4dbfbd874072082c8593a43d2ac5b36 Mon Sep 17 00:00:00 2001 From: Komari Spaghetti Date: Thu, 8 Apr 2021 16:37:39 +0200 Subject: Add gyro.zzz --- gyro.zzz | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 gyro.zzz diff --git a/gyro.zzz b/gyro.zzz new file mode 100644 index 0000000..3853db0 --- /dev/null +++ b/gyro.zzz @@ -0,0 +1,14 @@ +pkgs: + clap: + version: 0.3.0 + license: Unlicense + description: Simple command line argument parsing library + source_url: "https://github.com/Hejsil/zig-clap" + root: clap.zig + files: + README.md + LICENSE + build.zig + clap/*.zig + example/*.zig + -- cgit v1.2.3 From aa334d8c1df252f48960e0253eb25544678a6023 Mon Sep 17 00:00:00 2001 From: Komari Spaghetti Date: Mon, 26 Apr 2021 16:23:15 +0200 Subject: Refactor Diagnostic (and others) into a ParseOption struct This allows for default arguments, which we can also extend without breaking peoples code in the future. This is a breaking change right now though. --- README.md | 26 ++++++++++++-------------- clap.zig | 36 ++++++++++++++++++++++++++---------- clap/comptime.zig | 19 ++++++++----------- clap/streaming.zig | 40 +++++++++++++++++++++------------------- example/simple-ex.zig | 14 ++++++++------ example/simple.zig | 11 +++++------ example/streaming-clap.zig | 15 +++++++-------- 7 files changed, 87 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index 3156539..ad9f026 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ into master on every `zig` release. The simplest way to use this library is to just call the `clap.parse` function. ```zig -const std = @import("std"); const clap = @import("clap"); +const std = @import("std"); const debug = std.debug; @@ -41,11 +41,10 @@ pub fn main() !void { }; // Initalize our diagnostics, which can be used for reporting useful errors. - // This is optional. You can also just pass `null` to `parser.next` if you - // don't care about the extra information `Diagnostics` provides. - var diag: clap.Diagnostic = undefined; - - var args = clap.parse(clap.Help, ¶ms, std.heap.page_allocator, &diag) catch |err| { + // This is optional. You can also pass `.{}` to `clap.parse` if you don't + // care about the extra information `Diagnostics` provides. + var diag = clap.Diagnostic{}; + var args = clap.parse(clap.Help, ¶ms, .{ .diagnostic = &diag }) catch |err| { // Report useful error and exit diag.report(std.io.getStdErr().outStream(), err) catch {}; return err; @@ -107,8 +106,8 @@ The `StreamingClap` is the base of all the other parsers. It's a streaming parse `args.Iterator` to provide it with arguments lazily. ```zig -const std = @import("std"); const clap = @import("clap"); +const std = @import("std"); const debug = std.debug; @@ -137,19 +136,18 @@ pub fn main() !void { var iter = try clap.args.OsIterator.init(allocator); defer iter.deinit(); - // Initialize our streaming parser. + // Initalize our diagnostics, which can be used for reporting useful errors. + // This is optional. You can also leave the `diagnostic` field unset if you + // don't care about the extra information `Diagnostic` provides. + var diag = clap.Diagnostic{}; var parser = clap.StreamingClap(u8, clap.args.OsIterator){ .params = ¶ms, .iter = &iter, + .diagnostic = &diag, }; - // Initalize our diagnostics, which can be used for reporting useful errors. - // This is optional. You can also just pass `null` to `parser.next` if you - // don't care about the extra information `Diagnostics` provides. - var diag: clap.Diagnostic = undefined; - // Because we use a streaming parser, we have to consume each argument parsed individually. - while (parser.next(&diag) catch |err| { + while (parser.next() catch |err| { // Report useful error and exit diag.report(std.io.getStdErr().outStream(), err) catch {}; return err; diff --git a/clap.zig b/clap.zig index 4548a48..b31cd1d 100644 --- a/clap.zig +++ b/clap.zig @@ -1,6 +1,7 @@ const std = @import("std"); const debug = std.debug; +const heap = std.heap; const io = std.io; const mem = std.mem; const testing = std.testing; @@ -307,7 +308,6 @@ pub fn Args(comptime Id: type, comptime params: []const Param(Id)) type { exe_arg: ?[]const u8, pub fn deinit(a: *@This()) void { - a.clap.deinit(); a.arena.deinit(); } @@ -329,20 +329,37 @@ pub fn Args(comptime Id: type, comptime params: []const Param(Id)) type { }; } +/// Options that can be set to customize the behavior of parsing. +pub const ParseOptions = struct { + /// The allocator used for all memory allocations. Defaults to the `heap.page_allocator`. + /// Note: You should probably override this allocator if you are calling `parseEx`. Unlike + /// `parse`, `parseEx` does not wrap the allocator so the heap allocator can be + /// quite expensive. (TODO: Can we pick a better default? For `parse`, this allocator + /// is fine, as it wraps it in an arena) + allocator: *mem.Allocator = heap.page_allocator, + diagnostic: ?*Diagnostic = null, +}; + /// Same as `parseEx` but uses the `args.OsIterator` by default. pub fn parse( comptime Id: type, comptime params: []const Param(Id), - allocator: *mem.Allocator, - diag: ?*Diagnostic, + opt: ParseOptions, ) !Args(Id, params) { - var iter = try args.OsIterator.init(allocator); - const clap = try parseEx(Id, params, allocator, &iter, diag); - return Args(Id, params){ + var iter = try args.OsIterator.init(opt.allocator); + var res = Args(Id, params){ .arena = iter.arena, - .clap = clap, .exe_arg = iter.exe_arg, + .clap = undefined, }; + + // Let's reuse the arena from the `OSIterator` since we already have + // it. + res.clap = try parseEx(Id, params, &iter, .{ + .allocator = &res.arena.allocator, + .diagnostic = opt.diagnostic, + }); + return res; } /// Parses the command line arguments passed into the program based on an @@ -350,12 +367,11 @@ pub fn parse( pub fn parseEx( comptime Id: type, comptime params: []const Param(Id), - allocator: *mem.Allocator, iter: anytype, - diag: ?*Diagnostic, + opt: ParseOptions, ) !ComptimeClap(Id, params) { const Clap = ComptimeClap(Id, params); - return try Clap.parse(allocator, iter, diag); + return try Clap.parse(iter, opt); } /// Will print a help message in the following format: diff --git a/clap/comptime.zig b/clap/comptime.zig index 8ab61cb..9bec38e 100644 --- a/clap/comptime.zig +++ b/clap/comptime.zig @@ -1,10 +1,10 @@ const clap = @import("../clap.zig"); const std = @import("std"); -const testing = std.testing; +const debug = std.debug; const heap = std.heap; const mem = std.mem; -const debug = std.debug; +const testing = std.testing; /// Deprecated: Use `parseEx` instead pub fn ComptimeClap( @@ -42,7 +42,8 @@ pub fn ComptimeClap( pos: []const []const u8, allocator: *mem.Allocator, - pub fn parse(allocator: *mem.Allocator, iter: anytype, diag: ?*clap.Diagnostic) !@This() { + pub fn parse(iter: anytype, opt: clap.ParseOptions) !@This() { + const allocator = opt.allocator; var multis = [_]std.ArrayList([]const u8){undefined} ** multi_options; for (multis) |*multi| { multi.* = std.ArrayList([]const u8).init(allocator); @@ -62,7 +63,7 @@ pub fn ComptimeClap( .params = converted_params, .iter = iter, }; - while (try stream.next(diag)) |arg| { + while (try stream.next()) |arg| { const param = arg.param; if (param.names.long == null and param.names.short == null) { try pos.append(arg.value.?); @@ -81,19 +82,17 @@ pub fn ComptimeClap( } } - for (multis) |*multi, i| { + for (multis) |*multi, i| res.multi_options[i] = multi.toOwnedSlice(); - } res.pos = pos.toOwnedSlice(); return res; } - pub fn deinit(parser: *@This()) void { + pub fn deinit(parser: @This()) void { for (parser.multi_options) |o| parser.allocator.free(o); parser.allocator.free(parser.pos); - parser.* = undefined; } pub fn flag(parser: @This(), comptime name: []const u8) bool { @@ -155,14 +154,12 @@ test "" { clap.parseParam("
") catch unreachable,
});
- var buf: [1024]u8 = undefined;
- var fb_allocator = heap.FixedBufferAllocator.init(buf[0..]);
var iter = clap.args.SliceIterator{
.args = &[_][]const u8{
"-a", "-c", "0", "something", "-d", "a", "--dd", "b",
},
};
- var args = try Clap.parse(&fb_allocator.allocator, &iter, null);
+ var args = try Clap.parse(&iter, .{ .allocator = testing.allocator });
defer args.deinit();
testing.expect(args.flag("-a"));
diff --git a/clap/streaming.zig b/clap/streaming.zig
index 11145f0..8030a67 100644
--- a/clap/streaming.zig
+++ b/clap/streaming.zig
@@ -40,12 +40,13 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
iter: *ArgIterator,
state: State = .normal,
positional: ?*const clap.Param(Id) = null,
+ diagnostic: ?*clap.Diagnostic = null,
/// Get the next Arg that matches a Param.
- pub fn next(parser: *@This(), diag: ?*clap.Diagnostic) !?Arg(Id) {
+ pub fn next(parser: *@This()) !?Arg(Id) {
switch (parser.state) {
- .normal => return try parser.normal(diag),
- .chaining => |state| return try parser.chainging(state, diag),
+ .normal => return try parser.normal(),
+ .chaining => |state| return try parser.chainging(state),
.rest_are_positional => {
const param = parser.positionalParam() orelse unreachable;
const value = (try parser.iter.next()) orelse return null;
@@ -54,7 +55,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
}
}
- fn normal(parser: *@This(), diag: ?*clap.Diagnostic) !?Arg(Id) {
+ fn normal(parser: *@This()) !?Arg(Id) {
const arg_info = (try parser.parseNextArg()) orelse return null;
const arg = arg_info.arg;
switch (arg_info.kind) {
@@ -70,7 +71,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
continue;
if (param.takes_value == .None) {
if (maybe_value != null)
- return err(diag, arg, .{ .long = name }, error.DoesntTakeValue);
+ return parser.err(arg, .{ .long = name }, error.DoesntTakeValue);
return Arg(Id){ .param = param };
}
@@ -80,18 +81,18 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
break :blk v;
break :blk (try parser.iter.next()) orelse
- return err(diag, arg, .{ .long = name }, error.MissingValue);
+ return parser.err(arg, .{ .long = name }, error.MissingValue);
};
return Arg(Id){ .param = param, .value = value };
}
- return err(diag, arg, .{ .long = name }, error.InvalidArgument);
+ return parser.err(arg, .{ .long = name }, error.InvalidArgument);
},
.short => return try parser.chainging(.{
.arg = arg,
.index = 0,
- }, diag),
+ }),
.positional => if (parser.positionalParam()) |param| {
// If we find a positional with the value `--` then we
// interpret the rest of the arguments as positional
@@ -104,12 +105,12 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
return Arg(Id){ .param = param, .value = arg };
} else {
- return err(diag, arg, .{}, error.InvalidArgument);
+ return parser.err(arg, .{}, error.InvalidArgument);
},
}
}
- fn chainging(parser: *@This(), state: State.Chaining, diag: ?*clap.Diagnostic) !?Arg(Id) {
+ fn chainging(parser: *@This(), state: State.Chaining) !?Arg(Id) {
const arg = state.arg;
const index = state.index;
const next_index = index + 1;
@@ -136,13 +137,13 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
const next_is_eql = if (next_index < arg.len) arg[next_index] == '=' else false;
if (param.takes_value == .None) {
if (next_is_eql)
- return err(diag, arg, .{ .short = short }, error.DoesntTakeValue);
+ return parser.err(arg, .{ .short = short }, error.DoesntTakeValue);
return Arg(Id){ .param = param };
}
if (arg.len <= next_index) {
const value = (try parser.iter.next()) orelse
- return err(diag, arg, .{ .short = short }, error.MissingValue);
+ return parser.err(arg, .{ .short = short }, error.MissingValue);
return Arg(Id){ .param = param, .value = value };
}
@@ -153,7 +154,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
return Arg(Id){ .param = param, .value = arg[next_index..] };
}
- return err(diag, arg, .{ .short = arg[index] }, error.InvalidArgument);
+ return parser.err(arg, .{ .short = arg[index] }, error.InvalidArgument);
}
fn positionalParam(parser: *@This()) ?*const clap.Param(Id) {
@@ -194,8 +195,8 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
return ArgInfo{ .arg = full_arg, .kind = .positional };
}
- fn err(diag: ?*clap.Diagnostic, arg: []const u8, names: clap.Names, _err: anytype) @TypeOf(_err) {
- if (diag) |d|
+ fn err(parser: @This(), arg: []const u8, names: clap.Names, _err: anytype) @TypeOf(_err) {
+ if (parser.diagnostic) |d|
d.* = .{ .arg = arg, .name = names };
return _err;
}
@@ -210,7 +211,7 @@ fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, r
};
for (results) |res| {
- const arg = (c.next(null) catch unreachable) orelse unreachable;
+ const arg = (c.next() catch unreachable) orelse unreachable;
testing.expectEqual(res.param, arg.param);
const expected_value = res.value orelse {
testing.expectEqual(@as(@TypeOf(arg.value), null), arg.value);
@@ -220,18 +221,19 @@ fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, r
testing.expectEqualSlices(u8, expected_value, actual_value);
}
- if (c.next(null) catch unreachable) |_|
+ if (c.next() catch unreachable) |_|
unreachable;
}
fn testErr(params: []const clap.Param(u8), args_strings: []const []const u8, expected: []const u8) void {
- var diag: clap.Diagnostic = undefined;
+ var diag = clap.Diagnostic{};
var iter = args.SliceIterator{ .args = args_strings };
var c = StreamingClap(u8, args.SliceIterator){
.params = params,
.iter = &iter,
+ .diagnostic = &diag,
};
- while (c.next(&diag) catch |err| {
+ while (c.next() catch |err| {
var buf: [1024]u8 = undefined;
var slice_stream = io.fixedBufferStream(&buf);
diag.report(slice_stream.outStream(), err) catch unreachable;
diff --git a/example/simple-ex.zig b/example/simple-ex.zig
index d6ecc44..f504d63 100644
--- a/example/simple-ex.zig
+++ b/example/simple-ex.zig
@@ -1,5 +1,5 @@
-const std = @import("std");
const clap = @import("clap");
+const std = @import("std");
const debug = std.debug;
@@ -21,11 +21,13 @@ pub fn main() !void {
defer iter.deinit();
// Initalize our diagnostics, which can be used for reporting useful errors.
- // This is optional. You can also just pass `null` to `parser.next` if you
- // don't care about the extra information `Diagnostics` provides.
- var diag: clap.Diagnostic = undefined;
-
- var args = clap.parseEx(clap.Help, ¶ms, allocator, &iter, &diag) catch |err| {
+ // This is optional. You can also pass `.{}` to `clap.parse` if you don't
+ // care about the extra information `Diagnostics` provides.
+ var diag = clap.Diagnostic{};
+ var args = clap.parseEx(clap.Help, ¶ms, &iter, .{
+ .allocator = allocator,
+ .diagnostic = &diag,
+ }) catch |err| {
// Report useful error and exit
diag.report(std.io.getStdErr().outStream(), err) catch {};
return err;
diff --git a/example/simple.zig b/example/simple.zig
index 270e344..392dca3 100644
--- a/example/simple.zig
+++ b/example/simple.zig
@@ -1,5 +1,5 @@
-const std = @import("std");
const clap = @import("clap");
+const std = @import("std");
const debug = std.debug;
@@ -14,11 +14,10 @@ pub fn main() !void {
};
// Initalize our diagnostics, which can be used for reporting useful errors.
- // This is optional. You can also just pass `null` to `parser.next` if you
- // don't care about the extra information `Diagnostics` provides.
- var diag: clap.Diagnostic = undefined;
-
- var args = clap.parse(clap.Help, ¶ms, std.heap.page_allocator, &diag) catch |err| {
+ // This is optional. You can also pass `.{}` to `clap.parse` if you don't
+ // care about the extra information `Diagnostics` provides.
+ var diag = clap.Diagnostic{};
+ var args = clap.parse(clap.Help, ¶ms, .{ .diagnostic = &diag }) catch |err| {
// Report useful error and exit
diag.report(std.io.getStdErr().outStream(), err) catch {};
return err;
diff --git a/example/streaming-clap.zig b/example/streaming-clap.zig
index 941070f..f8d873d 100644
--- a/example/streaming-clap.zig
+++ b/example/streaming-clap.zig
@@ -1,5 +1,5 @@
-const std = @import("std");
const clap = @import("clap");
+const std = @import("std");
const debug = std.debug;
@@ -28,19 +28,18 @@ pub fn main() !void {
var iter = try clap.args.OsIterator.init(allocator);
defer iter.deinit();
- // Initialize our streaming parser.
+ // Initalize our diagnostics, which can be used for reporting useful errors.
+ // This is optional. You can also leave the `diagnostic` field unset if you
+ // don't care about the extra information `Diagnostic` provides.
+ var diag = clap.Diagnostic{};
var parser = clap.StreamingClap(u8, clap.args.OsIterator){
.params = ¶ms,
.iter = &iter,
+ .diagnostic = &diag,
};
- // Initalize our diagnostics, which can be used for reporting useful errors.
- // This is optional. You can also just pass `null` to `parser.next` if you
- // don't care about the extra information `Diagnostics` provides.
- var diag: clap.Diagnostic = undefined;
-
// Because we use a streaming parser, we have to consume each argument parsed individually.
- while (parser.next(&diag) catch |err| {
+ while (parser.next() catch |err| {
// Report useful error and exit
diag.report(std.io.getStdErr().outStream(), err) catch {};
return err;
--
cgit v1.2.3
From 4c14bfd5188bb61d7076bc33fccbcc6a5e9dac01 Mon Sep 17 00:00:00 2001
From: Komari Spaghetti
Date: Sat, 8 May 2021 18:08:52 +0200
Subject: Modernize codebase
* Better naming for variables
* Follow naming style of enums
* Use `writer()` instead of `outStream()`
* Change many initializers to be a one liner
* Don't explicitly initialize fields to their default value
---
README.md | 38 ++++----
build.zig | 4 +-
clap.zig | 211 +++++++++++++++------------------------------
clap/comptime.zig | 20 ++---
clap/streaming.zig | 184 +++++++++++++++++----------------------
example/help.zig | 7 +-
example/simple-error.zig | 4 +-
example/simple-ex.zig | 3 +-
example/simple.zig | 3 +-
example/streaming-clap.zig | 18 ++--
example/usage.zig | 6 +-
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");
const std = @import("std");
const debug = std.debug;
+const io = std.io;
pub fn main() !void {
// First we specify what parameters our program can take.
@@ -46,7 +47,7 @@ pub fn main() !void {
var diag = clap.Diagnostic{};
var args = clap.parse(clap.Help, ¶ms, .{ .diagnostic = &diag }) catch |err| {
// Report useful error and exit
- diag.report(std.io.getStdErr().outStream(), err) catch {};
+ diag.report(io.getStdErr().writer(), err) catch {};
return err;
};
defer args.deinit();
@@ -68,15 +69,15 @@ that the strings you pass to `option`, `options` and `flag` are actually paramet
program can take:
```zig
-const std = @import("std");
const clap = @import("clap");
+const std = @import("std");
pub fn main() !void {
const params = comptime [_]clap.Param(clap.Help){
clap.parseParam("-h, --help Display this help and exit.") catch unreachable,
};
- var args = try clap.parse(clap.Help, ¶ms, std.heap.direct_allocator, null);
+ var args = try clap.parse(clap.Help, ¶ms, .{});
defer args.deinit();
_ = args.flag("--helps");
@@ -110,25 +111,23 @@ const clap = @import("clap");
const std = @import("std");
const debug = std.debug;
+const io = std.io;
pub fn main() !void {
const allocator = std.heap.page_allocator;
// First we specify what parameters our program can take.
const params = [_]clap.Param(u8){
- clap.Param(u8){
+ .{
.id = 'h',
- .names = clap.Names{ .short = 'h', .long = "help" },
+ .names = .{ .short = 'h', .long = "help" },
},
- clap.Param(u8){
+ .{
.id = 'n',
- .names = clap.Names{ .short = 'n', .long = "number" },
- .takes_value = .One,
- },
- clap.Param(u8){
- .id = 'f',
- .takes_value = .One,
+ .names = .{ .short = 'n', .long = "number" },
+ .takes_value = .one,
},
+ .{ .id = 'f', .takes_value = .one },
};
// We then initialize an argument iterator. We will use the OsIterator as it nicely
@@ -149,7 +148,7 @@ pub fn main() !void {
// Because we use a streaming parser, we have to consume each argument parsed individually.
while (parser.next() catch |err| {
// Report useful error and exit
- diag.report(std.io.getStdErr().outStream(), err) catch {};
+ diag.report(io.getStdErr().writer(), err) catch {};
return err;
}) |arg| {
// 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
program can take.
```zig
-const std = @import("std");
const clap = @import("clap");
+const std = @import("std");
pub fn main() !void {
- const stderr_file = std.io.getStdErr();
- var stderr_out_stream = stderr_file.outStream();
-
// clap.help is a function that can print a simple help message, given a
// slice of Param(Help). There is also a helpEx, which can print a
// help message for any Param, but it is more verbose to call.
try clap.help(
- stderr_out_stream,
+ std.io.getStdErr().writer(),
comptime &[_]clap.Param(clap.Help){
clap.parseParam("-h, --help Display this help and exit. ") catch unreachable,
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
of the help message.
```zig
-const std = @import("std");
const clap = @import("clap");
+const std = @import("std");
pub fn main() !void {
- const stderr = std.io.getStdErr().outStream();
-
// clap.usage is a function that can print a simple usage message, given a
// slice of Param(Help). There is also a usageEx, which can print a
// usage message for any Param, but it is more verbose to call.
try clap.usage(
- stderr,
+ std.io.getStdErr().writer(),
comptime &[_]clap.Param(clap.Help){
clap.parseParam("-h, --help Display this help and exit. ") catch unreachable,
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 @@
const builtin = @import("builtin");
const std = @import("std");
-const Mode = builtin.Mode;
const Builder = std.build.Builder;
+const Mode = builtin.Mode;
pub fn build(b: *Builder) void {
const mode = b.standardReleaseOptions();
@@ -58,7 +58,7 @@ fn readMeStep(b: *Builder) *std.build.Step {
fn make(step: *std.build.Step) anyerror!void {
@setEvalBranchQuota(10000);
const file = try std.fs.cwd().createFile("README.md", .{});
- const stream = &file.outStream();
+ const stream = file.writer();
try stream.print(@embedFile("example/README.md.template"), .{
@embedFile("example/simple.zig"),
@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 {
/// Whether a param takes no value (a flag), one value, or can be specified multiple times.
pub const Values = enum {
- None,
- One,
- Many,
+ none,
+ one,
+ many,
};
/// Represents a parameter for the command line.
@@ -56,7 +56,7 @@ pub fn Param(comptime Id: type) type {
return struct {
id: Id = Id{},
names: Names = Names{},
- takes_value: Values = .None,
+ takes_value: Values = .none,
};
}
@@ -110,8 +110,8 @@ fn parseParamRest(line: []const u8) Param(Help) {
const len = mem.indexOfScalar(u8, line, '>') orelse break :blk;
const takes_many = mem.startsWith(u8, line[len + 1 ..], "...");
const help_start = len + 1 + @as(usize, 3) * @boolToInt(takes_many);
- return Param(Help){
- .takes_value = if (takes_many) .Many else .One,
+ return .{
+ .takes_value = if (takes_many) .many else .one,
.id = .{
.msg = mem.trim(u8, line[help_start..], " \t"),
.value = line[1..len],
@@ -119,7 +119,7 @@ fn parseParamRest(line: []const u8) Param(Help) {
};
}
- return Param(Help){ .id = .{ .msg = mem.trim(u8, line, " \t") } };
+ return .{ .id = .{ .msg = mem.trim(u8, line, " \t") } };
}
fn expectParam(expect: Param(Help), actual: Param(Help)) void {
@@ -136,114 +136,60 @@ fn expectParam(expect: Param(Help), actual: Param(Help)) void {
test "parseParam" {
expectParam(Param(Help){
- .id = Help{
- .msg = "Help text",
- .value = "value",
- },
- .names = Names{
- .short = 's',
- .long = "long",
- },
- .takes_value = .One,
+ .id = .{ .msg = "Help text", .value = "value" },
+ .names = .{ .short = 's', .long = "long" },
+ .takes_value = .one,
}, try parseParam("-s, --long Positional. This should not appear in the help message.") catch unreachable,
},
);
@@ -547,10 +488,10 @@ pub fn usageFull(
valueText: fn (@TypeOf(context), Param(Id)) Error![]const u8,
) !void {
var cos = io.countingOutStream(stream);
- const cs = cos.outStream();
+ const cs = cos.writer();
for (params) |param| {
const name = param.names.short orelse continue;
- if (param.takes_value != .None)
+ if (param.takes_value != .none)
continue;
if (cos.bytes_written == 0)
@@ -562,7 +503,7 @@ pub fn usageFull(
var positional: ?Param(Id) = null;
for (params) |param| {
- if (param.takes_value == .None and param.names.short != null)
+ if (param.takes_value == .none and param.names.short != null)
continue;
const prefix = if (param.names.short) |_| "-" else "--";
@@ -578,9 +519,9 @@ pub fn usageFull(
try cs.print("[{}{}", .{ prefix, name });
switch (param.takes_value) {
- .None => {},
- .One => try cs.print(" <{}>", .{try valueText(context, param)}),
- .Many => try cs.print(" <{}>...", .{try valueText(context, param)}),
+ .none => {},
+ .one => try cs.print(" <{}>", .{try valueText(context, param)}),
+ .many => try cs.print(" <{}>...", .{try valueText(context, param)}),
}
try cs.writeByte(']');
@@ -627,7 +568,7 @@ pub fn usage(stream: anytype, params: []const Param(Help)) !void {
fn testUsage(expected: []const u8, params: []const Param(Help)) !void {
var buf: [1024]u8 = undefined;
var fbs = io.fixedBufferStream(&buf);
- try usage(fbs.outStream(), params);
+ try usage(fbs.writer(), params);
testing.expectEqualStrings(expected, fbs.getWritten());
}
@@ -650,12 +591,7 @@ test "usage" {
parseParam("--b