summaryrefslogtreecommitdiff
path: root/src/cli/args.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli/args.zig')
-rw-r--r--src/cli/args.zig48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/cli/args.zig b/src/cli/args.zig
index 678c44b1d..d8b670852 100644
--- a/src/cli/args.zig
+++ b/src/cli/args.zig
@@ -67,6 +67,11 @@ pub fn parse(comptime T: type, alloc: Allocator, dst: *T, iter: anytype) !void {
};
while (iter.next()) |arg| {
+ // If an _inputs fields exist we keep track of the inputs.
+ if (@hasField(T, "_inputs")) {
+ try dst._inputs.append(arena_alloc, try arena_alloc.dupe(u8, arg));
+ }
+
// Do manual parsing if we have a hook for it.
if (@hasDecl(T, "parseManuallyHook")) {
if (!try dst.parseManuallyHook(arena_alloc, arg, iter)) return;
@@ -381,6 +386,30 @@ test "parse: error tracking" {
try testing.expect(!data._errors.empty());
}
+test "parse: input tracking" {
+ const testing = std.testing;
+
+ var data: struct {
+ a: []const u8 = "",
+ b: enum { one } = .one,
+
+ _arena: ?ArenaAllocator = null,
+ _errors: ErrorList = .{},
+ _inputs: std.ArrayListUnmanaged([]const u8) = .{},
+ } = .{};
+ defer if (data._arena) |arena| arena.deinit();
+
+ var iter = try std.process.ArgIteratorGeneral(.{}).init(
+ testing.allocator,
+ "--what --a=42",
+ );
+ defer iter.deinit();
+ try parse(@TypeOf(data), testing.allocator, &data, &iter);
+ try testing.expect(data._arena != null);
+ try testing.expect(data._inputs.items.len == 2);
+ try testing.expectEqualStrings("--what", data._inputs.items[0]);
+ try testing.expectEqualStrings("--a=42", data._inputs.items[1]);
+}
test "parseIntoField: ignore underscore-prefixed fields" {
const testing = std.testing;
var arena = ArenaAllocator.init(testing.allocator);
@@ -732,6 +761,25 @@ pub fn lineIterator(reader: anytype) LineIterator(@TypeOf(reader)) {
return .{ .r = reader };
}
+/// An iterator valid for arg parsing from a slice.
+pub const SliceIterator = struct {
+ const Self = @This();
+
+ slice: []const []const u8,
+ idx: usize = 0,
+
+ pub fn next(self: *Self) ?[]const u8 {
+ if (self.idx >= self.slice.len) return null;
+ defer self.idx += 1;
+ return self.slice[self.idx];
+ }
+};
+
+/// Construct a SliceIterator from a slice.
+pub fn sliceIterator(slice: []const []const u8) SliceIterator {
+ return .{ .slice = slice };
+}
+
test "LineIterator" {
const testing = std.testing;
var fbs = std.io.fixedBufferStream(