diff options
| author | 2020-11-10 18:31:35 +0100 | |
|---|---|---|
| committer | 2020-11-10 18:33:15 +0100 | |
| commit | 5efa886662ea22ce9f9b0166c5132d2234102bb7 (patch) | |
| tree | b67b9e95c1751b2f97eff6667bbdd14c0bc54c63 | |
| parent | Improve Diagnostic error message reporting (diff) | |
| download | zig-clap-5efa886662ea22ce9f9b0166c5132d2234102bb7.tar.gz zig-clap-5efa886662ea22ce9f9b0166c5132d2234102bb7.tar.xz zig-clap-5efa886662ea22ce9f9b0166c5132d2234102bb7.zip | |
Better parseParam
| -rw-r--r-- | README.md | 8 | ||||
| -rw-r--r-- | clap.zig | 332 | ||||
| -rw-r--r-- | clap/comptime.zig | 4 | ||||
| -rw-r--r-- | clap/streaming.zig | 10 | ||||
| -rw-r--r-- | example/comptime-clap.zig | 4 | ||||
| -rw-r--r-- | example/simple.zig | 4 |
6 files changed, 150 insertions, 212 deletions
| @@ -37,9 +37,7 @@ pub fn main() !void { | |||
| 37 | clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, | 37 | clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, |
| 38 | clap.parseParam("-n, --number <NUM> An option parameter, which takes a value.") catch unreachable, | 38 | clap.parseParam("-n, --number <NUM> An option parameter, which takes a value.") catch unreachable, |
| 39 | clap.parseParam("-s, --string <STR>... An option parameter which can be specified multiple times.") catch unreachable, | 39 | clap.parseParam("-s, --string <STR>... An option parameter which can be specified multiple times.") catch unreachable, |
| 40 | clap.Param(clap.Help){ | 40 | clap.parseParam("<POS>...") catch unreachable, |
| 41 | .takes_value = .One, | ||
| 42 | }, | ||
| 43 | }; | 41 | }; |
| 44 | 42 | ||
| 45 | // Initalize our diagnostics, which can be used for reporting useful errors. | 43 | // Initalize our diagnostics, which can be used for reporting useful errors. |
| @@ -121,9 +119,7 @@ pub fn main() !void { | |||
| 121 | clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, | 119 | clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, |
| 122 | clap.parseParam("-n, --number <NUM> An option parameter, which takes a value.") catch unreachable, | 120 | clap.parseParam("-n, --number <NUM> An option parameter, which takes a value.") catch unreachable, |
| 123 | clap.parseParam("-s, --string <STR>... An option parameter which can be specified multiple times.") catch unreachable, | 121 | clap.parseParam("-s, --string <STR>... An option parameter which can be specified multiple times.") catch unreachable, |
| 124 | clap.Param(clap.Help){ | 122 | clap.parseParam("<POS>...") catch unreachable, |
| 125 | .takes_value = .One, | ||
| 126 | }, | ||
| 127 | }; | 123 | }; |
| 128 | const Clap = clap.ComptimeClap(clap.Help, clap.args.OsIterator, ¶ms); | 124 | const Clap = clap.ComptimeClap(clap.Help, clap.args.OsIterator, ¶ms); |
| 129 | 125 | ||
| @@ -8,9 +8,7 @@ const testing = std.testing; | |||
| 8 | pub const args = @import("clap/args.zig"); | 8 | pub const args = @import("clap/args.zig"); |
| 9 | 9 | ||
| 10 | test "clap" { | 10 | test "clap" { |
| 11 | _ = args; | 11 | testing.refAllDecls(@This()); |
| 12 | _ = ComptimeClap; | ||
| 13 | _ = StreamingClap; | ||
| 14 | } | 12 | } |
| 15 | 13 | ||
| 16 | pub const ComptimeClap = @import("clap/comptime.zig").ComptimeClap; | 14 | pub const ComptimeClap = @import("clap/comptime.zig").ComptimeClap; |
| @@ -64,229 +62,196 @@ pub fn Param(comptime Id: type) type { | |||
| 64 | /// Takes a string and parses it to a Param(Help). | 62 | /// Takes a string and parses it to a Param(Help). |
| 65 | /// This is the reverse of 'help' but for at single parameter only. | 63 | /// This is the reverse of 'help' but for at single parameter only. |
| 66 | pub fn parseParam(line: []const u8) !Param(Help) { | 64 | pub fn parseParam(line: []const u8) !Param(Help) { |
| 67 | var z: usize = 0; | 65 | var found_comma = false; |
| 68 | var res = Param(Help){ | ||
| 69 | .id = Help{ | ||
| 70 | // For testing, i want to be able to easily compare slices just by pointer, | ||
| 71 | // so I slice by a runtime value here, so that zig does not optimize this | ||
| 72 | // out. Maybe I should write the test better, geeh. | ||
| 73 | .msg = line[z..z], | ||
| 74 | .value = line[z..z], | ||
| 75 | }, | ||
| 76 | }; | ||
| 77 | |||
| 78 | var it = mem.tokenize(line, " \t"); | 66 | var it = mem.tokenize(line, " \t"); |
| 79 | var param_str = it.next() orelse return error.NoParamFound; | 67 | var param_str = it.next() orelse return error.NoParamFound; |
| 80 | if (!mem.startsWith(u8, param_str, "--") and mem.startsWith(u8, param_str, "-")) { | 68 | |
| 81 | const found_comma = param_str[param_str.len - 1] == ','; | 69 | const short_name = if (!mem.startsWith(u8, param_str, "--") and |
| 70 | mem.startsWith(u8, param_str, "-")) | ||
| 71 | blk: { | ||
| 72 | found_comma = param_str[param_str.len - 1] == ','; | ||
| 82 | if (found_comma) | 73 | if (found_comma) |
| 83 | param_str = param_str[0 .. param_str.len - 1]; | 74 | param_str = param_str[0 .. param_str.len - 1]; |
| 84 | 75 | ||
| 85 | if (param_str.len != 2) | 76 | if (param_str.len != 2) |
| 86 | return error.InvalidShortParam; | 77 | return error.InvalidShortParam; |
| 87 | 78 | ||
| 88 | res.names.short = param_str[1]; | 79 | const short_name = param_str[1]; |
| 89 | if (!found_comma) { | 80 | if (!found_comma) { |
| 90 | var help_msg = it.rest(); | 81 | var res = parseParamRest(it.rest()); |
| 91 | if (it.next()) |next| blk: { | 82 | res.names.short = short_name; |
| 92 | if (mem.startsWith(u8, next, "<")) { | ||
| 93 | const start = mem.indexOfScalar(u8, help_msg, '<').? + 1; | ||
| 94 | const len = mem.indexOfScalar(u8, help_msg[start..], '>') orelse break :blk; | ||
| 95 | res.id.value = help_msg[start..][0..len]; | ||
| 96 | if (mem.startsWith(u8, help_msg[start + len + 1 ..], "...")) { | ||
| 97 | res.takes_value = .Many; | ||
| 98 | help_msg = help_msg[start + len + 1 + 3 ..]; | ||
| 99 | } else { | ||
| 100 | res.takes_value = .One; | ||
| 101 | help_msg = help_msg[start + len + 1 ..]; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | res.id.msg = mem.trim(u8, help_msg, " \t"); | ||
| 107 | return res; | 83 | return res; |
| 108 | } | 84 | } |
| 109 | 85 | ||
| 110 | param_str = it.next() orelse return error.NoParamFound; | 86 | param_str = it.next() orelse return error.NoParamFound; |
| 111 | } | 87 | break :blk short_name; |
| 112 | 88 | } else null; | |
| 113 | if (mem.startsWith(u8, param_str, "--")) { | ||
| 114 | res.names.long = param_str[2..]; | ||
| 115 | 89 | ||
| 90 | const long_name = if (mem.startsWith(u8, param_str, "--")) blk: { | ||
| 116 | if (param_str[param_str.len - 1] == ',') | 91 | if (param_str[param_str.len - 1] == ',') |
| 117 | return error.TrailingComma; | 92 | return error.TrailingComma; |
| 118 | 93 | ||
| 119 | var help_msg = it.rest(); | 94 | break :blk param_str[2..]; |
| 120 | if (it.next()) |next| blk: { | 95 | } else if (found_comma) { |
| 121 | if (mem.startsWith(u8, next, "<")) { | 96 | return error.TrailingComma; |
| 122 | const start = mem.indexOfScalar(u8, help_msg, '<').? + 1; | 97 | } else if (short_name == null) { |
| 123 | const len = mem.indexOfScalar(u8, help_msg[start..], '>') orelse break :blk; | 98 | return parseParamRest(mem.trimLeft(u8, line, " \t")); |
| 124 | res.id.value = help_msg[start..][0..len]; | 99 | } else null; |
| 125 | if (mem.startsWith(u8, help_msg[start + len + 1 ..], "...")) { | 100 | |
| 126 | res.takes_value = .Many; | 101 | var res = parseParamRest(it.rest()); |
| 127 | help_msg = help_msg[start + len + 1 + 3 ..]; | 102 | res.names.long = param_str[2..]; |
| 128 | } else { | 103 | res.names.short = short_name; |
| 129 | res.takes_value = .One; | 104 | return res; |
| 130 | help_msg = help_msg[start + len + 1 ..]; | 105 | } |
| 131 | } | ||
| 132 | } | ||
| 133 | } | ||
| 134 | 106 | ||
| 135 | res.id.msg = mem.trim(u8, help_msg, " \t"); | 107 | fn parseParamRest(line: []const u8) Param(Help) { |
| 136 | return res; | 108 | if (mem.startsWith(u8, line, "<")) blk: { |
| 109 | const len = mem.indexOfScalar(u8, line, '>') orelse break :blk; | ||
| 110 | const takes_many = mem.startsWith(u8, line[len + 1 ..], "..."); | ||
| 111 | const help_start = len + 1 + @as(usize, 3) * @boolToInt(takes_many); | ||
| 112 | return Param(Help){ | ||
| 113 | .takes_value = if (takes_many) .Many else .One, | ||
| 114 | .id = .{ | ||
| 115 | .msg = mem.trim(u8, line[help_start..], " \t"), | ||
| 116 | .value = line[1..len], | ||
| 117 | }, | ||
| 118 | }; | ||
| 137 | } | 119 | } |
| 138 | 120 | ||
| 139 | return error.NoParamFound; | 121 | return Param(Help){ .id = .{ .msg = mem.trim(u8, line, " \t") } }; |
| 122 | } | ||
| 123 | |||
| 124 | fn expectParam(expect: Param(Help), actual: Param(Help)) void { | ||
| 125 | testing.expectEqualStrings(expect.id.msg, actual.id.msg); | ||
| 126 | testing.expectEqualStrings(expect.id.value, actual.id.value); | ||
| 127 | testing.expectEqual(expect.names.short, actual.names.short); | ||
| 128 | testing.expectEqual(expect.takes_value, actual.takes_value); | ||
| 129 | if (expect.names.long) |long| { | ||
| 130 | testing.expectEqualStrings(long, actual.names.long.?); | ||
| 131 | } else { | ||
| 132 | testing.expectEqual(@as(?[]const u8, null), actual.names.long); | ||
| 133 | } | ||
| 140 | } | 134 | } |
| 141 | 135 | ||
| 142 | test "parseParam" { | 136 | test "parseParam" { |
| 143 | var z: usize = 0; | 137 | expectParam(Param(Help){ |
| 144 | var text: []const u8 = "-s, --long <value> Help text"; | ||
| 145 | testing.expectEqual(Param(Help){ | ||
| 146 | .id = Help{ | 138 | .id = Help{ |
| 147 | .msg = find(text, "Help text"), | 139 | .msg = "Help text", |
| 148 | .value = find(text, "value"), | 140 | .value = "value", |
| 149 | }, | 141 | }, |
| 150 | .names = Names{ | 142 | .names = Names{ |
| 151 | .short = 's', | 143 | .short = 's', |
| 152 | .long = find(text, "long"), | 144 | .long = "long", |
| 153 | }, | 145 | }, |
| 154 | .takes_value = .One, | 146 | .takes_value = .One, |
| 155 | }, try parseParam(text)); | 147 | }, try parseParam("-s, --long <value> Help text")); |
| 156 | 148 | expectParam(Param(Help){ | |
| 157 | text = "-s, --long <value>... Help text"; | ||
| 158 | testing.expectEqual(Param(Help){ | ||
| 159 | .id = Help{ | 149 | .id = Help{ |
| 160 | .msg = find(text, "Help text"), | 150 | .msg = "Help text", |
| 161 | .value = find(text, "value"), | 151 | .value = "value", |
| 162 | }, | 152 | }, |
| 163 | .names = Names{ | 153 | .names = Names{ |
| 164 | .short = 's', | 154 | .short = 's', |
| 165 | .long = find(text, "long"), | 155 | .long = "long", |
| 166 | }, | 156 | }, |
| 167 | .takes_value = .Many, | 157 | .takes_value = .Many, |
| 168 | }, try parseParam(text)); | 158 | }, try parseParam("-s, --long <value>... Help text")); |
| 169 | 159 | expectParam(Param(Help){ | |
| 170 | text = "--long <value> Help text"; | ||
| 171 | testing.expectEqual(Param(Help){ | ||
| 172 | .id = Help{ | 160 | .id = Help{ |
| 173 | .msg = find(text, "Help text"), | 161 | .msg = "Help text", |
| 174 | .value = find(text, "value"), | 162 | .value = "value", |
| 175 | }, | 163 | }, |
| 176 | .names = Names{ | 164 | .names = Names{ |
| 177 | .short = null, | 165 | .short = null, |
| 178 | .long = find(text, "long"), | 166 | .long = "long", |
| 179 | }, | 167 | }, |
| 180 | .takes_value = .One, | 168 | .takes_value = .One, |
| 181 | }, try parseParam(text)); | 169 | }, try parseParam("--long <value> Help text")); |
| 182 | 170 | expectParam(Param(Help){ | |
| 183 | text = "-s <value> Help text"; | ||
| 184 | testing.expectEqual(Param(Help){ | ||
| 185 | .id = Help{ | 171 | .id = Help{ |
| 186 | .msg = find(text, "Help text"), | 172 | .msg = "Help text", |
| 187 | .value = find(text, "value"), | 173 | .value = "value", |
| 188 | }, | 174 | }, |
| 189 | .names = Names{ | 175 | .names = Names{ |
| 190 | .short = 's', | 176 | .short = 's', |
| 191 | .long = null, | 177 | .long = null, |
| 192 | }, | 178 | }, |
| 193 | .takes_value = .One, | 179 | .takes_value = .One, |
| 194 | }, try parseParam(text)); | 180 | }, try parseParam("-s <value> Help text")); |
| 195 | 181 | expectParam(Param(Help){ | |
| 196 | text = "-s, --long Help text"; | ||
| 197 | testing.expectEqual(Param(Help){ | ||
| 198 | .id = Help{ | 182 | .id = Help{ |
| 199 | .msg = find(text, "Help text"), | 183 | .msg = "Help text", |
| 200 | .value = text[z..z], | 184 | .value = "", |
| 201 | }, | 185 | }, |
| 202 | .names = Names{ | 186 | .names = Names{ |
| 203 | .short = 's', | 187 | .short = 's', |
| 204 | .long = find(text, "long"), | 188 | .long = "long", |
| 205 | }, | 189 | }, |
| 206 | .takes_value = .None, | 190 | .takes_value = .None, |
| 207 | }, try parseParam(text)); | 191 | }, try parseParam("-s, --long Help text")); |
| 208 | 192 | expectParam(Param(Help){ | |
| 209 | text = "-s Help text"; | ||
| 210 | testing.expectEqual(Param(Help){ | ||
| 211 | .id = Help{ | 193 | .id = Help{ |
| 212 | .msg = find(text, "Help text"), | 194 | .msg = "Help text", |
| 213 | .value = text[z..z], | 195 | .value = "", |
| 214 | }, | 196 | }, |
| 215 | .names = Names{ | 197 | .names = Names{ |
| 216 | .short = 's', | 198 | .short = 's', |
| 217 | .long = null, | 199 | .long = null, |
| 218 | }, | 200 | }, |
| 219 | .takes_value = .None, | 201 | .takes_value = .None, |
| 220 | }, try parseParam(text)); | 202 | }, try parseParam("-s Help text")); |
| 221 | 203 | expectParam(Param(Help){ | |
| 222 | text = "--long Help text"; | ||
| 223 | testing.expectEqual(Param(Help){ | ||
| 224 | .id = Help{ | 204 | .id = Help{ |
| 225 | .msg = find(text, "Help text"), | 205 | .msg = "Help text", |
| 226 | .value = text[z..z], | 206 | .value = "", |
| 227 | }, | 207 | }, |
| 228 | .names = Names{ | 208 | .names = Names{ |
| 229 | .short = null, | 209 | .short = null, |
| 230 | .long = find(text, "long"), | 210 | .long = "long", |
| 231 | }, | 211 | }, |
| 232 | .takes_value = .None, | 212 | .takes_value = .None, |
| 233 | }, try parseParam(text)); | 213 | }, try parseParam("--long Help text")); |
| 234 | 214 | expectParam(Param(Help){ | |
| 235 | text = "--long <A | B> Help text"; | ||
| 236 | testing.expectEqual(Param(Help){ | ||
| 237 | .id = Help{ | 215 | .id = Help{ |
| 238 | .msg = find(text, "Help text"), | 216 | .msg = "Help text", |
| 239 | .value = find(text, "A | B"), | 217 | .value = "A | B", |
| 240 | }, | 218 | }, |
| 241 | .names = Names{ | 219 | .names = Names{ |
| 242 | .short = null, | 220 | .short = null, |
| 243 | .long = find(text, "long"), | 221 | .long = "long", |
| 244 | }, | 222 | }, |
| 245 | .takes_value = .One, | 223 | .takes_value = .One, |
| 246 | }, try parseParam(text)); | 224 | }, try parseParam("--long <A | B> Help text")); |
| 225 | expectParam(Param(Help){ | ||
| 226 | .id = Help{ | ||
| 227 | .msg = "Help text", | ||
| 228 | .value = "A", | ||
| 229 | }, | ||
| 230 | .names = Names{ | ||
| 231 | .short = null, | ||
| 232 | .long = null, | ||
| 233 | }, | ||
| 234 | .takes_value = .One, | ||
| 235 | }, try parseParam("<A> Help text")); | ||
| 236 | expectParam(Param(Help){ | ||
| 237 | .id = Help{ | ||
| 238 | .msg = "Help text", | ||
| 239 | .value = "A", | ||
| 240 | }, | ||
| 241 | .names = Names{ | ||
| 242 | .short = null, | ||
| 243 | .long = null, | ||
| 244 | }, | ||
| 245 | .takes_value = .Many, | ||
| 246 | }, try parseParam("<A>... Help text")); | ||
| 247 | 247 | ||
| 248 | testing.expectError(error.NoParamFound, parseParam("Help")); | ||
| 249 | testing.expectError(error.TrailingComma, parseParam("--long, Help")); | 248 | testing.expectError(error.TrailingComma, parseParam("--long, Help")); |
| 250 | testing.expectError(error.NoParamFound, parseParam("-s, Help")); | 249 | testing.expectError(error.TrailingComma, parseParam("-s, Help")); |
| 251 | testing.expectError(error.InvalidShortParam, parseParam("-ss Help")); | 250 | testing.expectError(error.InvalidShortParam, parseParam("-ss Help")); |
| 252 | testing.expectError(error.InvalidShortParam, parseParam("-ss <value> Help")); | 251 | testing.expectError(error.InvalidShortParam, parseParam("-ss <value> Help")); |
| 253 | testing.expectError(error.InvalidShortParam, parseParam("- Help")); | 252 | testing.expectError(error.InvalidShortParam, parseParam("- Help")); |
| 254 | } | 253 | } |
| 255 | 254 | ||
| 256 | fn find(str: []const u8, f: []const u8) []const u8 { | ||
| 257 | const i = mem.indexOf(u8, str, f).?; | ||
| 258 | return str[i..][0..f.len]; | ||
| 259 | } | ||
| 260 | |||
| 261 | pub fn Args(comptime Id: type, comptime params: []const Param(Id)) type { | ||
| 262 | return struct { | ||
| 263 | arena: std.heap.ArenaAllocator, | ||
| 264 | clap: ComptimeClap(Id, args.OsIterator, params), | ||
| 265 | exe_arg: ?[]const u8, | ||
| 266 | |||
| 267 | pub fn deinit(a: *@This()) void { | ||
| 268 | a.clap.deinit(); | ||
| 269 | a.arena.deinit(); | ||
| 270 | } | ||
| 271 | |||
| 272 | pub fn flag(a: @This(), comptime name: []const u8) bool { | ||
| 273 | return a.clap.flag(name); | ||
| 274 | } | ||
| 275 | |||
| 276 | pub fn option(a: @This(), comptime name: []const u8) ?[]const u8 { | ||
| 277 | return a.clap.option(name); | ||
| 278 | } | ||
| 279 | |||
| 280 | pub fn options(a: @This(), comptime name: []const u8) []const []const u8 { | ||
| 281 | return a.clap.options(name); | ||
| 282 | } | ||
| 283 | |||
| 284 | pub fn positionals(a: @This()) []const []const u8 { | ||
| 285 | return a.clap.positionals(); | ||
| 286 | } | ||
| 287 | }; | ||
| 288 | } | ||
| 289 | |||
| 290 | /// Optional diagnostics used for reporting useful errors | 255 | /// Optional diagnostics used for reporting useful errors |
| 291 | pub const Diagnostic = struct { | 256 | pub const Diagnostic = struct { |
| 292 | arg: []const u8 = "", | 257 | arg: []const u8 = "", |
| @@ -319,15 +284,7 @@ fn testDiag(diag: Diagnostic, err: anyerror, expected: []const u8) void { | |||
| 319 | var buf: [1024]u8 = undefined; | 284 | var buf: [1024]u8 = undefined; |
| 320 | var slice_stream = io.fixedBufferStream(&buf); | 285 | var slice_stream = io.fixedBufferStream(&buf); |
| 321 | diag.report(slice_stream.outStream(), err) catch unreachable; | 286 | diag.report(slice_stream.outStream(), err) catch unreachable; |
| 322 | 287 | testing.expectEqualStrings(expected, slice_stream.getWritten()); | |
| 323 | const actual = slice_stream.getWritten(); | ||
| 324 | if (!mem.eql(u8, actual, expected)) { | ||
| 325 | debug.warn("\n============ Expected ============\n", .{}); | ||
| 326 | debug.warn("{}", .{expected}); | ||
| 327 | debug.warn("============= Actual =============\n", .{}); | ||
| 328 | debug.warn("{}", .{actual}); | ||
| 329 | testing.expect(false); | ||
| 330 | } | ||
| 331 | } | 288 | } |
| 332 | 289 | ||
| 333 | test "Diagnostic.report" { | 290 | test "Diagnostic.report" { |
| @@ -343,6 +300,35 @@ test "Diagnostic.report" { | |||
| 343 | testDiag(.{ .name = .{ .long = "cc" } }, error.SomethingElse, "Error while parsing arguments: SomethingElse\n"); | 300 | testDiag(.{ .name = .{ .long = "cc" } }, error.SomethingElse, "Error while parsing arguments: SomethingElse\n"); |
| 344 | } | 301 | } |
| 345 | 302 | ||
| 303 | pub fn Args(comptime Id: type, comptime params: []const Param(Id)) type { | ||
| 304 | return struct { | ||
| 305 | arena: std.heap.ArenaAllocator, | ||
| 306 | clap: ComptimeClap(Id, args.OsIterator, params), | ||
| 307 | exe_arg: ?[]const u8, | ||
| 308 | |||
| 309 | pub fn deinit(a: *@This()) void { | ||
| 310 | a.clap.deinit(); | ||
| 311 | a.arena.deinit(); | ||
| 312 | } | ||
| 313 | |||
| 314 | pub fn flag(a: @This(), comptime name: []const u8) bool { | ||
| 315 | return a.clap.flag(name); | ||
| 316 | } | ||
| 317 | |||
| 318 | pub fn option(a: @This(), comptime name: []const u8) ?[]const u8 { | ||
| 319 | return a.clap.option(name); | ||
| 320 | } | ||
| 321 | |||
| 322 | pub fn options(a: @This(), comptime name: []const u8) []const []const u8 { | ||
| 323 | return a.clap.options(name); | ||
| 324 | } | ||
| 325 | |||
| 326 | pub fn positionals(a: @This()) []const []const u8 { | ||
| 327 | return a.clap.positionals(); | ||
| 328 | } | ||
| 329 | }; | ||
| 330 | } | ||
| 331 | |||
| 346 | /// Parses the command line arguments passed into the program based on an | 332 | /// Parses the command line arguments passed into the program based on an |
| 347 | /// array of `Param`s. | 333 | /// array of `Param`s. |
| 348 | pub fn parse( | 334 | pub fn parse( |
| @@ -422,6 +408,7 @@ fn printParam( | |||
| 422 | 408 | ||
| 423 | try stream.print("--{}", .{l}); | 409 | try stream.print("--{}", .{l}); |
| 424 | } | 410 | } |
| 411 | |||
| 425 | switch (param.takes_value) { | 412 | switch (param.takes_value) { |
| 426 | .None => {}, | 413 | .None => {}, |
| 427 | .One => try stream.print(" <{}>", .{valueText(context, param)}), | 414 | .One => try stream.print(" <{}>", .{valueText(context, param)}), |
| @@ -516,22 +503,7 @@ test "clap.help" { | |||
| 516 | "\t-d, --dd <V3> \tBoth option.\n" ++ | 503 | "\t-d, --dd <V3> \tBoth option.\n" ++ |
| 517 | "\t-d, --dd <V3>...\tBoth repeated option.\n"; | 504 | "\t-d, --dd <V3>...\tBoth repeated option.\n"; |
| 518 | 505 | ||
| 519 | const actual = slice_stream.getWritten(); | 506 | testing.expectEqualStrings(expected, slice_stream.getWritten()); |
| 520 | if (!mem.eql(u8, actual, expected)) { | ||
| 521 | debug.warn("\n============ Expected ============\n", .{}); | ||
| 522 | debug.warn("{}", .{expected}); | ||
| 523 | debug.warn("============= Actual =============\n", .{}); | ||
| 524 | debug.warn("{}", .{actual}); | ||
| 525 | |||
| 526 | var buffer: [1024 * 2]u8 = undefined; | ||
| 527 | var fba = std.heap.FixedBufferAllocator.init(&buffer); | ||
| 528 | |||
| 529 | debug.warn("============ Expected (escaped) ============\n", .{}); | ||
| 530 | debug.warn("{x}\n", .{expected}); | ||
| 531 | debug.warn("============ Actual (escaped) ============\n", .{}); | ||
| 532 | debug.warn("{x}\n", .{actual}); | ||
| 533 | testing.expect(false); | ||
| 534 | } | ||
| 535 | } | 507 | } |
| 536 | 508 | ||
| 537 | /// Will print a usage message in the following format: | 509 | /// Will print a usage message in the following format: |
| @@ -629,23 +601,7 @@ fn testUsage(expected: []const u8, params: []const Param(Help)) !void { | |||
| 629 | var buf: [1024]u8 = undefined; | 601 | var buf: [1024]u8 = undefined; |
| 630 | var fbs = io.fixedBufferStream(&buf); | 602 | var fbs = io.fixedBufferStream(&buf); |
| 631 | try usage(fbs.outStream(), params); | 603 | try usage(fbs.outStream(), params); |
| 632 | 604 | testing.expectEqualStrings(expected, fbs.getWritten()); | |
| 633 | const actual = fbs.getWritten(); | ||
| 634 | if (!mem.eql(u8, actual, expected)) { | ||
| 635 | debug.warn("\n============ Expected ============\n", .{}); | ||
| 636 | debug.warn("{}\n", .{expected}); | ||
| 637 | debug.warn("============= Actual =============\n", .{}); | ||
| 638 | debug.warn("{}\n", .{actual}); | ||
| 639 | |||
| 640 | var buffer: [1024 * 2]u8 = undefined; | ||
| 641 | var fba = std.heap.FixedBufferAllocator.init(&buffer); | ||
| 642 | |||
| 643 | debug.warn("============ Expected (escaped) ============\n", .{}); | ||
| 644 | debug.warn("{x}\n", .{expected}); | ||
| 645 | debug.warn("============ Actual (escaped) ============\n", .{}); | ||
| 646 | debug.warn("{x}\n", .{actual}); | ||
| 647 | testing.expect(false); | ||
| 648 | } | ||
| 649 | } | 605 | } |
| 650 | 606 | ||
| 651 | test "usage" { | 607 | test "usage" { |
diff --git a/clap/comptime.zig b/clap/comptime.zig index df5547a..9ead41a 100644 --- a/clap/comptime.zig +++ b/clap/comptime.zig | |||
| @@ -152,9 +152,7 @@ test "" { | |||
| 152 | clap.parseParam("-b, --bb ") catch unreachable, | 152 | clap.parseParam("-b, --bb ") catch unreachable, |
| 153 | clap.parseParam("-c, --cc <V>") catch unreachable, | 153 | clap.parseParam("-c, --cc <V>") catch unreachable, |
| 154 | clap.parseParam("-d, --dd <V>...") catch unreachable, | 154 | clap.parseParam("-d, --dd <V>...") catch unreachable, |
| 155 | clap.Param(clap.Help){ | 155 | clap.parseParam("<P>") catch unreachable, |
| 156 | .takes_value = .One, | ||
| 157 | }, | ||
| 158 | }); | 156 | }); |
| 159 | 157 | ||
| 160 | var buf: [1024]u8 = undefined; | 158 | var buf: [1024]u8 = undefined; |
diff --git a/clap/streaming.zig b/clap/streaming.zig index 8ab01f6..e0b808e 100644 --- a/clap/streaming.zig +++ b/clap/streaming.zig | |||
| @@ -208,15 +208,7 @@ fn testErr(params: []const clap.Param(u8), args_strings: []const []const u8, exp | |||
| 208 | var buf: [1024]u8 = undefined; | 208 | var buf: [1024]u8 = undefined; |
| 209 | var slice_stream = io.fixedBufferStream(&buf); | 209 | var slice_stream = io.fixedBufferStream(&buf); |
| 210 | diag.report(slice_stream.outStream(), err) catch unreachable; | 210 | diag.report(slice_stream.outStream(), err) catch unreachable; |
| 211 | 211 | testing.expectEqualStrings(expected, slice_stream.getWritten()); | |
| 212 | const actual = slice_stream.getWritten(); | ||
| 213 | if (!mem.eql(u8, actual, expected)) { | ||
| 214 | debug.warn("\n============ Expected ============\n", .{}); | ||
| 215 | debug.warn("{}", .{expected}); | ||
| 216 | debug.warn("============= Actual =============\n", .{}); | ||
| 217 | debug.warn("{}", .{actual}); | ||
| 218 | testing.expect(false); | ||
| 219 | } | ||
| 220 | return; | 212 | return; |
| 221 | }) |_| {} | 213 | }) |_| {} |
| 222 | 214 | ||
diff --git a/example/comptime-clap.zig b/example/comptime-clap.zig index 530c7e6..e5d02ff 100644 --- a/example/comptime-clap.zig +++ b/example/comptime-clap.zig | |||
| @@ -12,9 +12,7 @@ pub fn main() !void { | |||
| 12 | clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, | 12 | clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, |
| 13 | clap.parseParam("-n, --number <NUM> An option parameter, which takes a value.") catch unreachable, | 13 | clap.parseParam("-n, --number <NUM> An option parameter, which takes a value.") catch unreachable, |
| 14 | clap.parseParam("-s, --string <STR>... An option parameter which can be specified multiple times.") catch unreachable, | 14 | clap.parseParam("-s, --string <STR>... An option parameter which can be specified multiple times.") catch unreachable, |
| 15 | clap.Param(clap.Help){ | 15 | clap.parseParam("<POS>...") catch unreachable, |
| 16 | .takes_value = .One, | ||
| 17 | }, | ||
| 18 | }; | 16 | }; |
| 19 | const Clap = clap.ComptimeClap(clap.Help, clap.args.OsIterator, ¶ms); | 17 | const Clap = clap.ComptimeClap(clap.Help, clap.args.OsIterator, ¶ms); |
| 20 | 18 | ||
diff --git a/example/simple.zig b/example/simple.zig index f7b5953..270e344 100644 --- a/example/simple.zig +++ b/example/simple.zig | |||
| @@ -10,9 +10,7 @@ pub fn main() !void { | |||
| 10 | clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, | 10 | clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, |
| 11 | clap.parseParam("-n, --number <NUM> An option parameter, which takes a value.") catch unreachable, | 11 | clap.parseParam("-n, --number <NUM> An option parameter, which takes a value.") catch unreachable, |
| 12 | clap.parseParam("-s, --string <STR>... An option parameter which can be specified multiple times.") catch unreachable, | 12 | clap.parseParam("-s, --string <STR>... An option parameter which can be specified multiple times.") catch unreachable, |
| 13 | clap.Param(clap.Help){ | 13 | clap.parseParam("<POS>...") catch unreachable, |
| 14 | .takes_value = .One, | ||
| 15 | }, | ||
| 16 | }; | 14 | }; |
| 17 | 15 | ||
| 18 | // Initalize our diagnostics, which can be used for reporting useful errors. | 16 | // Initalize our diagnostics, which can be used for reporting useful errors. |