summaryrefslogtreecommitdiff
path: root/clap/streaming.zig
diff options
context:
space:
mode:
Diffstat (limited to 'clap/streaming.zig')
-rw-r--r--clap/streaming.zig40
1 files changed, 21 insertions, 19 deletions
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 {
40 iter: *ArgIterator, 40 iter: *ArgIterator,
41 state: State = .normal, 41 state: State = .normal,
42 positional: ?*const clap.Param(Id) = null, 42 positional: ?*const clap.Param(Id) = null,
43 diagnostic: ?*clap.Diagnostic = null,
43 44
44 /// Get the next Arg that matches a Param. 45 /// Get the next Arg that matches a Param.
45 pub fn next(parser: *@This(), diag: ?*clap.Diagnostic) !?Arg(Id) { 46 pub fn next(parser: *@This()) !?Arg(Id) {
46 switch (parser.state) { 47 switch (parser.state) {
47 .normal => return try parser.normal(diag), 48 .normal => return try parser.normal(),
48 .chaining => |state| return try parser.chainging(state, diag), 49 .chaining => |state| return try parser.chainging(state),
49 .rest_are_positional => { 50 .rest_are_positional => {
50 const param = parser.positionalParam() orelse unreachable; 51 const param = parser.positionalParam() orelse unreachable;
51 const value = (try parser.iter.next()) orelse return null; 52 const value = (try parser.iter.next()) orelse return null;
@@ -54,7 +55,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
54 } 55 }
55 } 56 }
56 57
57 fn normal(parser: *@This(), diag: ?*clap.Diagnostic) !?Arg(Id) { 58 fn normal(parser: *@This()) !?Arg(Id) {
58 const arg_info = (try parser.parseNextArg()) orelse return null; 59 const arg_info = (try parser.parseNextArg()) orelse return null;
59 const arg = arg_info.arg; 60 const arg = arg_info.arg;
60 switch (arg_info.kind) { 61 switch (arg_info.kind) {
@@ -70,7 +71,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
70 continue; 71 continue;
71 if (param.takes_value == .None) { 72 if (param.takes_value == .None) {
72 if (maybe_value != null) 73 if (maybe_value != null)
73 return err(diag, arg, .{ .long = name }, error.DoesntTakeValue); 74 return parser.err(arg, .{ .long = name }, error.DoesntTakeValue);
74 75
75 return Arg(Id){ .param = param }; 76 return Arg(Id){ .param = param };
76 } 77 }
@@ -80,18 +81,18 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
80 break :blk v; 81 break :blk v;
81 82
82 break :blk (try parser.iter.next()) orelse 83 break :blk (try parser.iter.next()) orelse
83 return err(diag, arg, .{ .long = name }, error.MissingValue); 84 return parser.err(arg, .{ .long = name }, error.MissingValue);
84 }; 85 };
85 86
86 return Arg(Id){ .param = param, .value = value }; 87 return Arg(Id){ .param = param, .value = value };
87 } 88 }
88 89
89 return err(diag, arg, .{ .long = name }, error.InvalidArgument); 90 return parser.err(arg, .{ .long = name }, error.InvalidArgument);
90 }, 91 },
91 .short => return try parser.chainging(.{ 92 .short => return try parser.chainging(.{
92 .arg = arg, 93 .arg = arg,
93 .index = 0, 94 .index = 0,
94 }, diag), 95 }),
95 .positional => if (parser.positionalParam()) |param| { 96 .positional => if (parser.positionalParam()) |param| {
96 // If we find a positional with the value `--` then we 97 // If we find a positional with the value `--` then we
97 // interpret the rest of the arguments as positional 98 // interpret the rest of the arguments as positional
@@ -104,12 +105,12 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
104 105
105 return Arg(Id){ .param = param, .value = arg }; 106 return Arg(Id){ .param = param, .value = arg };
106 } else { 107 } else {
107 return err(diag, arg, .{}, error.InvalidArgument); 108 return parser.err(arg, .{}, error.InvalidArgument);
108 }, 109 },
109 } 110 }
110 } 111 }
111 112
112 fn chainging(parser: *@This(), state: State.Chaining, diag: ?*clap.Diagnostic) !?Arg(Id) { 113 fn chainging(parser: *@This(), state: State.Chaining) !?Arg(Id) {
113 const arg = state.arg; 114 const arg = state.arg;
114 const index = state.index; 115 const index = state.index;
115 const next_index = index + 1; 116 const next_index = index + 1;
@@ -136,13 +137,13 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
136 const next_is_eql = if (next_index < arg.len) arg[next_index] == '=' else false; 137 const next_is_eql = if (next_index < arg.len) arg[next_index] == '=' else false;
137 if (param.takes_value == .None) { 138 if (param.takes_value == .None) {
138 if (next_is_eql) 139 if (next_is_eql)
139 return err(diag, arg, .{ .short = short }, error.DoesntTakeValue); 140 return parser.err(arg, .{ .short = short }, error.DoesntTakeValue);
140 return Arg(Id){ .param = param }; 141 return Arg(Id){ .param = param };
141 } 142 }
142 143
143 if (arg.len <= next_index) { 144 if (arg.len <= next_index) {
144 const value = (try parser.iter.next()) orelse 145 const value = (try parser.iter.next()) orelse
145 return err(diag, arg, .{ .short = short }, error.MissingValue); 146 return parser.err(arg, .{ .short = short }, error.MissingValue);
146 147
147 return Arg(Id){ .param = param, .value = value }; 148 return Arg(Id){ .param = param, .value = value };
148 } 149 }
@@ -153,7 +154,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
153 return Arg(Id){ .param = param, .value = arg[next_index..] }; 154 return Arg(Id){ .param = param, .value = arg[next_index..] };
154 } 155 }
155 156
156 return err(diag, arg, .{ .short = arg[index] }, error.InvalidArgument); 157 return parser.err(arg, .{ .short = arg[index] }, error.InvalidArgument);
157 } 158 }
158 159
159 fn positionalParam(parser: *@This()) ?*const clap.Param(Id) { 160 fn positionalParam(parser: *@This()) ?*const clap.Param(Id) {
@@ -194,8 +195,8 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
194 return ArgInfo{ .arg = full_arg, .kind = .positional }; 195 return ArgInfo{ .arg = full_arg, .kind = .positional };
195 } 196 }
196 197
197 fn err(diag: ?*clap.Diagnostic, arg: []const u8, names: clap.Names, _err: anytype) @TypeOf(_err) { 198 fn err(parser: @This(), arg: []const u8, names: clap.Names, _err: anytype) @TypeOf(_err) {
198 if (diag) |d| 199 if (parser.diagnostic) |d|
199 d.* = .{ .arg = arg, .name = names }; 200 d.* = .{ .arg = arg, .name = names };
200 return _err; 201 return _err;
201 } 202 }
@@ -210,7 +211,7 @@ fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, r
210 }; 211 };
211 212
212 for (results) |res| { 213 for (results) |res| {
213 const arg = (c.next(null) catch unreachable) orelse unreachable; 214 const arg = (c.next() catch unreachable) orelse unreachable;
214 testing.expectEqual(res.param, arg.param); 215 testing.expectEqual(res.param, arg.param);
215 const expected_value = res.value orelse { 216 const expected_value = res.value orelse {
216 testing.expectEqual(@as(@TypeOf(arg.value), null), arg.value); 217 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
220 testing.expectEqualSlices(u8, expected_value, actual_value); 221 testing.expectEqualSlices(u8, expected_value, actual_value);
221 } 222 }
222 223
223 if (c.next(null) catch unreachable) |_| 224 if (c.next() catch unreachable) |_|
224 unreachable; 225 unreachable;
225} 226}
226 227
227fn testErr(params: []const clap.Param(u8), args_strings: []const []const u8, expected: []const u8) void { 228fn testErr(params: []const clap.Param(u8), args_strings: []const []const u8, expected: []const u8) void {
228 var diag: clap.Diagnostic = undefined; 229 var diag = clap.Diagnostic{};
229 var iter = args.SliceIterator{ .args = args_strings }; 230 var iter = args.SliceIterator{ .args = args_strings };
230 var c = StreamingClap(u8, args.SliceIterator){ 231 var c = StreamingClap(u8, args.SliceIterator){
231 .params = params, 232 .params = params,
232 .iter = &iter, 233 .iter = &iter,
234 .diagnostic = &diag,
233 }; 235 };
234 while (c.next(&diag) catch |err| { 236 while (c.next() catch |err| {
235 var buf: [1024]u8 = undefined; 237 var buf: [1024]u8 = undefined;
236 var slice_stream = io.fixedBufferStream(&buf); 238 var slice_stream = io.fixedBufferStream(&buf);
237 diag.report(slice_stream.outStream(), err) catch unreachable; 239 diag.report(slice_stream.outStream(), err) catch unreachable;