diff options
| -rw-r--r-- | README.md | 54 | ||||
| -rw-r--r-- | clap.zig | 730 | ||||
| -rw-r--r-- | example/README.md.template | 4 | ||||
| -rw-r--r-- | example/help.zig | 9 | ||||
| -rw-r--r-- | example/simple-ex.zig | 15 | ||||
| -rw-r--r-- | example/simple.zig | 15 | ||||
| -rw-r--r-- | example/usage.zig | 11 |
7 files changed, 447 insertions, 391 deletions
| @@ -32,13 +32,14 @@ const io = std.io; | |||
| 32 | 32 | ||
| 33 | pub fn main() !void { | 33 | pub fn main() !void { |
| 34 | // First we specify what parameters our program can take. | 34 | // First we specify what parameters our program can take. |
| 35 | // We can use `parseParam` to parse a string to a `Param(Help)` | 35 | // We can use `parseParamsComptime` to parse a string into an array of `Param(Help)` |
| 36 | const params = comptime [_]clap.Param(clap.Help){ | 36 | const params = comptime clap.parseParamsComptime( |
| 37 | clap.parseParam("-h, --help Display this help and exit.") catch unreachable, | 37 | \\-h, --help Display this help and exit. |
| 38 | clap.parseParam("-n, --number <usize> An option parameter, which takes a value.") catch unreachable, | 38 | \\-n, --number <usize> An option parameter, which takes a value. |
| 39 | clap.parseParam("-s, --string <str>... An option parameter which can be specified multiple times.") catch unreachable, | 39 | \\-s, --string <str>... An option parameter which can be specified multiple times. |
| 40 | clap.parseParam("<str>...") catch unreachable, | 40 | \\<str>... |
| 41 | }; | 41 | \\ |
| 42 | ); | ||
| 42 | 43 | ||
| 43 | // Initalize our diagnostics, which can be used for reporting useful errors. | 44 | // Initalize our diagnostics, which can be used for reporting useful errors. |
| 44 | // This is optional. You can also pass `.{}` to `clap.parse` if you don't | 45 | // This is optional. You can also pass `.{}` to `clap.parse` if you don't |
| @@ -73,8 +74,8 @@ The fields in `args` are typed. The type is based on the name of the value the p | |||
| 73 | Since `--number` takes a `usize` the field `res.args.number` has the type `usize`. | 74 | Since `--number` takes a `usize` the field `res.args.number` has the type `usize`. |
| 74 | 75 | ||
| 75 | Note that this is only the case because `clap.parsers.default` has a field called `usize` which | 76 | Note that this is only the case because `clap.parsers.default` has a field called `usize` which |
| 76 | contains a parser that returns `usize`. You can pass in something other than `clap.parsers.default` | 77 | contains a parser that returns `usize`. You can pass in something other than |
| 77 | if you want some other mapping. | 78 | `clap.parsers.default` if you want some other mapping. |
| 78 | 79 | ||
| 79 | ```zig | 80 | ```zig |
| 80 | const clap = @import("clap"); | 81 | const clap = @import("clap"); |
| @@ -86,13 +87,14 @@ const process = std.process; | |||
| 86 | 87 | ||
| 87 | pub fn main() !void { | 88 | pub fn main() !void { |
| 88 | // First we specify what parameters our program can take. | 89 | // First we specify what parameters our program can take. |
| 89 | // We can use `parseParam` to parse a string to a `Param(Help)` | 90 | // We can use `parseParamsComptime` to parse a string into an array of `Param(Help)` |
| 90 | const params = comptime [_]clap.Param(clap.Help){ | 91 | const params = comptime clap.parseParamsComptime( |
| 91 | clap.parseParam("-h, --help Display this help and exit.") catch unreachable, | 92 | \\-h, --help Display this help and exit. |
| 92 | clap.parseParam("-n, --number <INT> An option parameter, which takes a value.") catch unreachable, | 93 | \\-n, --number <INT> An option parameter, which takes a value. |
| 93 | clap.parseParam("-s, --string <STR>... An option parameter which can be specified multiple times.") catch unreachable, | 94 | \\-s, --string <STR>... An option parameter which can be specified multiple times. |
| 94 | clap.parseParam("<FILE>...") catch unreachable, | 95 | \\<FILE>... |
| 95 | }; | 96 | \\ |
| 97 | ); | ||
| 96 | 98 | ||
| 97 | // Declare our own parsers which are used to map the argument strings to other | 99 | // Declare our own parsers which are used to map the argument strings to other |
| 98 | // types. | 100 | // types. |
| @@ -205,10 +207,11 @@ const clap = @import("clap"); | |||
| 205 | const std = @import("std"); | 207 | const std = @import("std"); |
| 206 | 208 | ||
| 207 | pub fn main() !void { | 209 | pub fn main() !void { |
| 208 | const params = comptime [_]clap.Param(clap.Help){ | 210 | const params = comptime clap.parseParamsComptime( |
| 209 | clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, | 211 | \\-h, --help Display this help and exit. |
| 210 | clap.parseParam("-v, --version Output version information and exit.") catch unreachable, | 212 | \\-v, --version Output version information and exit. |
| 211 | }; | 213 | \\ |
| 214 | ); | ||
| 212 | 215 | ||
| 213 | var res = try clap.parse(clap.Help, ¶ms, clap.parsers.default, .{}); | 216 | var res = try clap.parse(clap.Help, ¶ms, clap.parsers.default, .{}); |
| 214 | defer res.deinit(); | 217 | defer res.deinit(); |
| @@ -238,11 +241,12 @@ const clap = @import("clap"); | |||
| 238 | const std = @import("std"); | 241 | const std = @import("std"); |
| 239 | 242 | ||
| 240 | pub fn main() !void { | 243 | pub fn main() !void { |
| 241 | const params = comptime [_]clap.Param(clap.Help){ | 244 | const params = comptime clap.parseParamsComptime( |
| 242 | clap.parseParam("-h, --help Display this help and exit.") catch unreachable, | 245 | \\-h, --help Display this help and exit. |
| 243 | clap.parseParam("-v, --version Output version information and exit.") catch unreachable, | 246 | \\-v, --version Output version information and exit. |
| 244 | clap.parseParam(" --value <str> An option parameter, which takes a value.") catch unreachable, | 247 | \\ --value <str> An option parameter, which takes a value. |
| 245 | }; | 248 | \\ |
| 249 | ); | ||
| 246 | 250 | ||
| 247 | var res = try clap.parse(clap.Help, ¶ms, clap.parsers.default, .{}); | 251 | var res = try clap.parse(clap.Help, ¶ms, clap.parsers.default, .{}); |
| 248 | defer res.deinit(); | 252 | defer res.deinit(); |
| @@ -78,9 +78,76 @@ pub fn Param(comptime Id: type) type { | |||
| 78 | }; | 78 | }; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | /// Takes a string and parses it into many Param(Help). Returned is a newly allocated slice | ||
| 82 | /// containing all the parsed params. The caller is responsible for freeing the slice. | ||
| 83 | pub fn parseParams(allocator: mem.Allocator, str: []const u8) ![]Param(Help) { | ||
| 84 | var list = std.ArrayList(Param(Help)).init(allocator); | ||
| 85 | errdefer list.deinit(); | ||
| 86 | |||
| 87 | try parseParamsIntoArrayList(&list, str); | ||
| 88 | return list.toOwnedSlice(); | ||
| 89 | } | ||
| 90 | |||
| 91 | /// Takes a string and parses it into many Param(Help) at comptime. Returned is an array of | ||
| 92 | /// exactly the number of params that was parsed from `str`. A parse error becomes a compiler | ||
| 93 | /// error. | ||
| 94 | pub fn parseParamsComptime(comptime str: []const u8) [countParams(str)]Param(Help) { | ||
| 95 | var res: [countParams(str)]Param(Help) = undefined; | ||
| 96 | _ = parseParamsIntoSlice(&res, str) catch unreachable; | ||
| 97 | return res; | ||
| 98 | } | ||
| 99 | |||
| 100 | fn countParams(str: []const u8) usize { | ||
| 101 | // See parseParam for reasoning. I would like to remove it from parseParam, but people depend | ||
| 102 | // on that function to still work conveniently at comptime, so leaving it for now. | ||
| 103 | @setEvalBranchQuota(std.math.maxInt(u32)); | ||
| 104 | |||
| 105 | var res: usize = 0; | ||
| 106 | var it = mem.split(u8, str, "\n"); | ||
| 107 | while (it.next()) |line| { | ||
| 108 | const trimmed = mem.trimLeft(u8, line, " \t"); | ||
| 109 | if (mem.startsWith(u8, trimmed, "-") or | ||
| 110 | mem.startsWith(u8, trimmed, "<")) | ||
| 111 | { | ||
| 112 | res += 1; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | return res; | ||
| 117 | } | ||
| 118 | |||
| 119 | /// Takes a string and parses it into many Param(Help), which are written to `slice`. A subslice | ||
| 120 | /// is returned, containing all the parameters parsed. This function will fail if the input slice | ||
| 121 | /// is to small. | ||
| 122 | pub fn parseParamsIntoSlice(slice: []Param(Help), str: []const u8) ![]Param(Help) { | ||
| 123 | var null_alloc = heap.FixedBufferAllocator.init(""); | ||
| 124 | var list = std.ArrayList(Param(Help)){ | ||
| 125 | .allocator = null_alloc.allocator(), | ||
| 126 | .items = slice[0..0], | ||
| 127 | .capacity = slice.len, | ||
| 128 | }; | ||
| 129 | |||
| 130 | try parseParamsIntoArrayList(&list, str); | ||
| 131 | return list.items; | ||
| 132 | } | ||
| 133 | |||
| 134 | /// Takes a string and parses it into many Param(Help), which are appended onto `list`. | ||
| 135 | pub fn parseParamsIntoArrayList(list: *std.ArrayList(Param(Help)), str: []const u8) !void { | ||
| 136 | var i: usize = 0; | ||
| 137 | while (i != str.len) { | ||
| 138 | var end: usize = undefined; | ||
| 139 | try list.append(try parseParamEx(str[i..], &end)); | ||
| 140 | i += end; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | pub fn parseParam(str: []const u8) !Param(Help) { | ||
| 145 | var end: usize = undefined; | ||
| 146 | return parseParamEx(str, &end); | ||
| 147 | } | ||
| 148 | |||
| 81 | /// Takes a string and parses it to a Param(Help). | 149 | /// Takes a string and parses it to a Param(Help). |
| 82 | /// This is the reverse of 'help' but for at single parameter only. | 150 | pub fn parseParamEx(str: []const u8, end: *usize) !Param(Help) { |
| 83 | pub fn parseParam(line: []const u8) !Param(Help) { | ||
| 84 | // This function become a lot less ergonomic to use once you hit the eval branch quota. To | 151 | // This function become a lot less ergonomic to use once you hit the eval branch quota. To |
| 85 | // avoid this we pick a sane default. Sadly, the only sane default is the biggest possible | 152 | // avoid this we pick a sane default. Sadly, the only sane default is the biggest possible |
| 86 | // value. If we pick something a lot smaller and a user hits the quota after that, they have | 153 | // value. If we pick something a lot smaller and a user hits the quota after that, they have |
| @@ -120,157 +187,177 @@ pub fn parseParam(line: []const u8) !Param(Help) { | |||
| 120 | rest_of_description, | 187 | rest_of_description, |
| 121 | rest_of_description_new_line, | 188 | rest_of_description_new_line, |
| 122 | } = .start; | 189 | } = .start; |
| 123 | for (line) |c, i| switch (state) { | 190 | for (str) |c, i| { |
| 124 | .start => switch (c) { | 191 | errdefer end.* = i; |
| 125 | ' ', '\t', '\n' => {}, | 192 | |
| 126 | '-' => state = .start_of_short_name, | 193 | switch (state) { |
| 127 | '<' => state = .first_char_of_value, | 194 | .start => switch (c) { |
| 128 | else => return error.InvalidParameter, | 195 | ' ', '\t', '\n' => {}, |
| 129 | }, | 196 | '-' => state = .start_of_short_name, |
| 197 | '<' => state = .first_char_of_value, | ||
| 198 | else => return error.InvalidParameter, | ||
| 199 | }, | ||
| 130 | 200 | ||
| 131 | .start_of_short_name => switch (c) { | 201 | .start_of_short_name => switch (c) { |
| 132 | '-' => state = .first_char_of_long_name, | 202 | '-' => state = .first_char_of_long_name, |
| 133 | 'a'...'z', 'A'...'Z', '0'...'9' => { | 203 | 'a'...'z', 'A'...'Z', '0'...'9' => { |
| 134 | res.names.short = c; | 204 | res.names.short = c; |
| 135 | state = .end_of_short_name; | 205 | state = .end_of_short_name; |
| 206 | }, | ||
| 207 | else => return error.InvalidParameter, | ||
| 208 | }, | ||
| 209 | .end_of_short_name => switch (c) { | ||
| 210 | ' ', '\t' => state = .before_long_name_or_value_or_description, | ||
| 211 | '\n' => state = .before_description_new_line, | ||
| 212 | ',' => state = .before_long_name, | ||
| 213 | else => return error.InvalidParameter, | ||
| 136 | }, | 214 | }, |
| 137 | else => return error.InvalidParameter, | ||
| 138 | }, | ||
| 139 | .end_of_short_name => switch (c) { | ||
| 140 | ' ', '\t' => state = .before_long_name_or_value_or_description, | ||
| 141 | '\n' => state = .before_description_new_line, | ||
| 142 | ',' => state = .before_long_name, | ||
| 143 | else => return error.InvalidParameter, | ||
| 144 | }, | ||
| 145 | 215 | ||
| 146 | .before_long_name => switch (c) { | 216 | .before_long_name => switch (c) { |
| 147 | ' ', '\t' => {}, | 217 | ' ', '\t' => {}, |
| 148 | '-' => state = .start_of_long_name, | 218 | '-' => state = .start_of_long_name, |
| 149 | else => return error.InvalidParameter, | 219 | else => return error.InvalidParameter, |
| 150 | }, | ||
| 151 | .start_of_long_name => switch (c) { | ||
| 152 | '-' => state = .first_char_of_long_name, | ||
| 153 | else => return error.InvalidParameter, | ||
| 154 | }, | ||
| 155 | .first_char_of_long_name => switch (c) { | ||
| 156 | 'a'...'z', 'A'...'Z', '0'...'9' => { | ||
| 157 | start = i; | ||
| 158 | state = .rest_of_long_name; | ||
| 159 | }, | 220 | }, |
| 160 | else => return error.InvalidParameter, | 221 | .start_of_long_name => switch (c) { |
| 161 | }, | 222 | '-' => state = .first_char_of_long_name, |
| 162 | .rest_of_long_name => switch (c) { | 223 | else => return error.InvalidParameter, |
| 163 | 'a'...'z', 'A'...'Z', '0'...'9' => {}, | ||
| 164 | ' ', '\t' => { | ||
| 165 | res.names.long = line[start..i]; | ||
| 166 | state = .before_value_or_description; | ||
| 167 | }, | 224 | }, |
| 168 | '\n' => { | 225 | .first_char_of_long_name => switch (c) { |
| 169 | res.names.long = line[start..i]; | 226 | 'a'...'z', 'A'...'Z', '0'...'9' => { |
| 170 | state = .before_description_new_line; | 227 | start = i; |
| 228 | state = .rest_of_long_name; | ||
| 229 | }, | ||
| 230 | else => return error.InvalidParameter, | ||
| 231 | }, | ||
| 232 | .rest_of_long_name => switch (c) { | ||
| 233 | 'a'...'z', 'A'...'Z', '0'...'9' => {}, | ||
| 234 | ' ', '\t' => { | ||
| 235 | res.names.long = str[start..i]; | ||
| 236 | state = .before_value_or_description; | ||
| 237 | }, | ||
| 238 | '\n' => { | ||
| 239 | res.names.long = str[start..i]; | ||
| 240 | state = .before_description_new_line; | ||
| 241 | }, | ||
| 242 | else => return error.InvalidParameter, | ||
| 171 | }, | 243 | }, |
| 172 | else => return error.InvalidParameter, | ||
| 173 | }, | ||
| 174 | 244 | ||
| 175 | .before_long_name_or_value_or_description => switch (c) { | 245 | .before_long_name_or_value_or_description => switch (c) { |
| 176 | ' ', '\t' => {}, | 246 | ' ', '\t' => {}, |
| 177 | ',' => state = .before_long_name, | 247 | ',' => state = .before_long_name, |
| 178 | '<' => state = .first_char_of_value, | 248 | '<' => state = .first_char_of_value, |
| 179 | else => { | 249 | else => { |
| 180 | start = i; | 250 | start = i; |
| 181 | state = .rest_of_description; | 251 | state = .rest_of_description; |
| 252 | }, | ||
| 182 | }, | 253 | }, |
| 183 | }, | ||
| 184 | 254 | ||
| 185 | .before_value_or_description => switch (c) { | 255 | .before_value_or_description => switch (c) { |
| 186 | ' ', '\t' => {}, | 256 | ' ', '\t' => {}, |
| 187 | '<' => state = .first_char_of_value, | 257 | '<' => state = .first_char_of_value, |
| 188 | else => { | 258 | else => { |
| 189 | start = i; | 259 | start = i; |
| 190 | state = .rest_of_description; | 260 | state = .rest_of_description; |
| 261 | }, | ||
| 191 | }, | 262 | }, |
| 192 | }, | 263 | .first_char_of_value => switch (c) { |
| 193 | .first_char_of_value => switch (c) { | 264 | '>' => return error.InvalidParameter, |
| 194 | '>' => return error.InvalidParameter, | 265 | else => { |
| 195 | else => { | 266 | start = i; |
| 196 | start = i; | 267 | state = .rest_of_value; |
| 197 | state = .rest_of_value; | 268 | }, |
| 198 | }, | 269 | }, |
| 199 | }, | 270 | .rest_of_value => switch (c) { |
| 200 | .rest_of_value => switch (c) { | 271 | '>' => { |
| 201 | '>' => { | 272 | res.takes_value = .one; |
| 202 | res.takes_value = .one; | 273 | res.id.val = str[start..i]; |
| 203 | res.id.val = line[start..i]; | 274 | state = .end_of_one_value; |
| 204 | state = .end_of_one_value; | 275 | }, |
| 276 | else => {}, | ||
| 205 | }, | 277 | }, |
| 206 | else => {}, | 278 | .end_of_one_value => switch (c) { |
| 207 | }, | 279 | '.' => state = .second_dot_of_multi_value, |
| 208 | .end_of_one_value => switch (c) { | 280 | ' ', '\t' => state = .before_description, |
| 209 | '.' => state = .second_dot_of_multi_value, | 281 | '\n' => state = .before_description_new_line, |
| 210 | ' ', '\t' => state = .before_description, | 282 | else => { |
| 211 | '\n' => state = .before_description_new_line, | 283 | start = i; |
| 212 | else => { | 284 | state = .rest_of_description; |
| 213 | start = i; | 285 | }, |
| 214 | state = .rest_of_description; | ||
| 215 | }, | 286 | }, |
| 216 | }, | 287 | .second_dot_of_multi_value => switch (c) { |
| 217 | .second_dot_of_multi_value => switch (c) { | 288 | '.' => state = .third_dot_of_multi_value, |
| 218 | '.' => state = .third_dot_of_multi_value, | 289 | else => return error.InvalidParameter, |
| 219 | else => return error.InvalidParameter, | 290 | }, |
| 220 | }, | 291 | .third_dot_of_multi_value => switch (c) { |
| 221 | .third_dot_of_multi_value => switch (c) { | 292 | '.' => { |
| 222 | '.' => { | 293 | res.takes_value = .many; |
| 223 | res.takes_value = .many; | 294 | state = .before_description; |
| 224 | state = .before_description; | 295 | }, |
| 296 | else => return error.InvalidParameter, | ||
| 225 | }, | 297 | }, |
| 226 | else => return error.InvalidParameter, | ||
| 227 | }, | ||
| 228 | 298 | ||
| 229 | .before_description => switch (c) { | 299 | .before_description => switch (c) { |
| 230 | ' ', '\t' => {}, | 300 | ' ', '\t' => {}, |
| 231 | '\n' => state = .before_description_new_line, | 301 | '\n' => state = .before_description_new_line, |
| 232 | else => { | 302 | else => { |
| 233 | start = i; | 303 | start = i; |
| 234 | state = .rest_of_description; | 304 | state = .rest_of_description; |
| 305 | }, | ||
| 235 | }, | 306 | }, |
| 236 | }, | 307 | .before_description_new_line => switch (c) { |
| 237 | .before_description_new_line => switch (c) { | 308 | ' ', '\t', '\n' => {}, |
| 238 | ' ', '\t', '\n' => {}, | 309 | '-', '<' => { |
| 239 | '-' => break, | 310 | end.* = i; |
| 240 | else => { | 311 | break; |
| 241 | start = i; | 312 | }, |
| 242 | state = .rest_of_description; | 313 | else => { |
| 314 | start = i; | ||
| 315 | state = .rest_of_description; | ||
| 316 | }, | ||
| 243 | }, | 317 | }, |
| 244 | }, | 318 | .rest_of_description => switch (c) { |
| 245 | .rest_of_description => switch (c) { | 319 | '\n' => state = .rest_of_description_new_line, |
| 246 | '\n' => state = .rest_of_description_new_line, | 320 | else => {}, |
| 247 | else => {}, | ||
| 248 | }, | ||
| 249 | .rest_of_description_new_line => switch (c) { | ||
| 250 | ' ', '\t', '\n' => {}, | ||
| 251 | '-' => { | ||
| 252 | res.id.desc = mem.trimRight(u8, line[start..i], " \t\n\r"); | ||
| 253 | break; | ||
| 254 | }, | 321 | }, |
| 255 | else => state = .rest_of_description, | 322 | .rest_of_description_new_line => switch (c) { |
| 256 | }, | 323 | ' ', '\t', '\n' => {}, |
| 257 | } else switch (state) { | 324 | '-', '<' => { |
| 258 | .rest_of_description, .rest_of_description_new_line => { | 325 | res.id.desc = mem.trimRight(u8, str[start..i], " \t\n\r"); |
| 259 | res.id.desc = mem.trimRight(u8, line[start..], " \t\n\r"); | 326 | end.* = i; |
| 260 | }, | 327 | break; |
| 261 | .rest_of_long_name => res.names.long = line[start..], | 328 | }, |
| 262 | .end_of_short_name, | 329 | else => state = .rest_of_description, |
| 263 | .end_of_one_value, | 330 | }, |
| 264 | .before_value_or_description, | 331 | } |
| 265 | .before_description, | 332 | } else { |
| 266 | .before_description_new_line, | 333 | end.* = str.len; |
| 267 | => {}, | 334 | switch (state) { |
| 268 | else => return error.InvalidParameter, | 335 | .rest_of_description, .rest_of_description_new_line => { |
| 336 | res.id.desc = mem.trimRight(u8, str[start..], " \t\n\r"); | ||
| 337 | }, | ||
| 338 | .rest_of_long_name => res.names.long = str[start..], | ||
| 339 | .end_of_short_name, | ||
| 340 | .end_of_one_value, | ||
| 341 | .before_value_or_description, | ||
| 342 | .before_description, | ||
| 343 | .before_description_new_line, | ||
| 344 | => {}, | ||
| 345 | else => return error.InvalidParameter, | ||
| 346 | } | ||
| 269 | } | 347 | } |
| 270 | 348 | ||
| 271 | return res; | 349 | return res; |
| 272 | } | 350 | } |
| 273 | 351 | ||
| 352 | fn testParseParams(str: []const u8, expected_params: []const Param(Help)) !void { | ||
| 353 | const actual_params = try parseParams(testing.allocator, str); | ||
| 354 | defer testing.allocator.free(actual_params); | ||
| 355 | |||
| 356 | try testing.expectEqual(expected_params.len, actual_params.len); | ||
| 357 | for (expected_params) |_, i| | ||
| 358 | try expectParam(expected_params[i], actual_params[i]); | ||
| 359 | } | ||
| 360 | |||
| 274 | fn expectParam(expect: Param(Help), actual: Param(Help)) !void { | 361 | fn expectParam(expect: Param(Help), actual: Param(Help)) !void { |
| 275 | try testing.expectEqualStrings(expect.id.desc, actual.id.desc); | 362 | try testing.expectEqualStrings(expect.id.desc, actual.id.desc); |
| 276 | try testing.expectEqualStrings(expect.id.val, actual.id.val); | 363 | try testing.expectEqualStrings(expect.id.val, actual.id.val); |
| @@ -283,157 +370,112 @@ fn expectParam(expect: Param(Help), actual: Param(Help)) !void { | |||
| 283 | } | 370 | } |
| 284 | } | 371 | } |
| 285 | 372 | ||
| 286 | test "parseParam" { | 373 | test "parseParams" { |
| 287 | try expectParam(.{ | 374 | try testParseParams( |
| 288 | .id = .{}, | 375 | \\-s |
| 289 | .names = .{ .short = 's' }, | 376 | \\--str |
| 290 | }, try parseParam("-s")); | 377 | \\-s, --str |
| 291 | 378 | \\--str <str> | |
| 292 | try expectParam(.{ | 379 | \\-s, --str <str> |
| 293 | .id = .{}, | 380 | \\-s, --long <val> Help text |
| 294 | .names = .{ .long = "str" }, | 381 | \\-s, --long <val>... Help text |
| 295 | }, try parseParam("--str")); | 382 | \\--long <val> Help text |
| 296 | 383 | \\-s <val> Help text | |
| 297 | try expectParam(.{ | 384 | \\-s, --long Help text |
| 298 | .id = .{}, | 385 | \\-s Help text |
| 299 | .names = .{ .short = 's', .long = "str" }, | 386 | \\--long Help text |
| 300 | }, try parseParam("-s, --str")); | 387 | \\--long <A | B> Help text |
| 301 | 388 | \\<A> Help text | |
| 302 | try expectParam(.{ | 389 | \\<A>... Help text |
| 303 | .id = .{ .val = "str" }, | ||
| 304 | .names = .{ .long = "str" }, | ||
| 305 | .takes_value = .one, | ||
| 306 | }, try parseParam("--str <str>")); | ||
| 307 | |||
| 308 | try expectParam(.{ | ||
| 309 | .id = .{ .val = "str" }, | ||
| 310 | .names = .{ .short = 's', .long = "str" }, | ||
| 311 | .takes_value = .one, | ||
| 312 | }, try parseParam("-s, --str <str>")); | ||
| 313 | |||
| 314 | try expectParam(.{ | ||
| 315 | .id = .{ .desc = "Help text", .val = "val" }, | ||
| 316 | .names = .{ .short = 's', .long = "long" }, | ||
| 317 | .takes_value = .one, | ||
| 318 | }, try parseParam("-s, --long <val> Help text")); | ||
| 319 | |||
| 320 | try expectParam(.{ | ||
| 321 | .id = .{ .desc = "Help text", .val = "val" }, | ||
| 322 | .names = .{ .short = 's', .long = "long" }, | ||
| 323 | .takes_value = .many, | ||
| 324 | }, try parseParam("-s, --long <val>... Help text")); | ||
| 325 | |||
| 326 | try expectParam(.{ | ||
| 327 | .id = .{ .desc = "Help text", .val = "val" }, | ||
| 328 | .names = .{ .long = "long" }, | ||
| 329 | .takes_value = .one, | ||
| 330 | }, try parseParam("--long <val> Help text")); | ||
| 331 | |||
| 332 | try expectParam(.{ | ||
| 333 | .id = .{ .desc = "Help text", .val = "val" }, | ||
| 334 | .names = .{ .short = 's' }, | ||
| 335 | .takes_value = .one, | ||
| 336 | }, try parseParam("-s <val> Help text")); | ||
| 337 | |||
| 338 | try expectParam(.{ | ||
| 339 | .id = .{ .desc = "Help text" }, | ||
| 340 | .names = .{ .short = 's', .long = "long" }, | ||
| 341 | }, try parseParam("-s, --long Help text")); | ||
| 342 | |||
| 343 | try expectParam(.{ | ||
| 344 | .id = .{ .desc = "Help text" }, | ||
| 345 | .names = .{ .short = 's' }, | ||
| 346 | }, try parseParam("-s Help text")); | ||
| 347 | |||
| 348 | try expectParam(.{ | ||
| 349 | .id = .{ .desc = "Help text" }, | ||
| 350 | .names = .{ .long = "long" }, | ||
| 351 | }, try parseParam("--long Help text")); | ||
| 352 | |||
| 353 | try expectParam(.{ | ||
| 354 | .id = .{ .desc = "Help text", .val = "A | B" }, | ||
| 355 | .names = .{ .long = "long" }, | ||
| 356 | .takes_value = .one, | ||
| 357 | }, try parseParam("--long <A | B> Help text")); | ||
| 358 | |||
| 359 | try expectParam(.{ | ||
| 360 | .id = .{ .desc = "Help text", .val = "A" }, | ||
| 361 | .names = .{}, | ||
| 362 | .takes_value = .one, | ||
| 363 | }, try parseParam("<A> Help text")); | ||
| 364 | |||
| 365 | try expectParam(.{ | ||
| 366 | .id = .{ .desc = "Help text", .val = "A" }, | ||
| 367 | .names = .{}, | ||
| 368 | .takes_value = .many, | ||
| 369 | }, try parseParam("<A>... Help text")); | ||
| 370 | |||
| 371 | try expectParam(.{ | ||
| 372 | .id = .{ | ||
| 373 | .desc = | ||
| 374 | \\This is | ||
| 375 | \\ help spanning multiple | ||
| 376 | \\ lines | ||
| 377 | , | ||
| 378 | }, | ||
| 379 | .names = .{ .long = "aa" }, | ||
| 380 | .takes_value = .none, | ||
| 381 | }, try parseParam( | ||
| 382 | \\--aa This is | 390 | \\--aa This is |
| 383 | \\ help spanning multiple | 391 | \\ help spanning multiple |
| 384 | \\ lines | 392 | \\ lines |
| 385 | \\ | 393 | \\ |
| 386 | )); | ||
| 387 | |||
| 388 | try expectParam(.{ | ||
| 389 | .id = .{ .desc = "This msg should end and the newline cause of new param" }, | ||
| 390 | .names = .{ .long = "aa" }, | ||
| 391 | .takes_value = .none, | ||
| 392 | }, try parseParam( | ||
| 393 | \\--aa This msg should end and the newline cause of new param | 394 | \\--aa This msg should end and the newline cause of new param |
| 394 | \\--bb This should not end up being parsed | 395 | \\--bb This should be a new param |
| 395 | \\ | ||
| 396 | )); | ||
| 397 | |||
| 398 | try expectParam(.{ | ||
| 399 | .id = .{}, | ||
| 400 | .names = .{ .short = 'a' }, | ||
| 401 | .takes_value = .none, | ||
| 402 | }, try parseParam( | ||
| 403 | \\-a | ||
| 404 | \\--bb | ||
| 405 | \\ | ||
| 406 | )); | ||
| 407 | |||
| 408 | try expectParam(.{ | ||
| 409 | .id = .{}, | ||
| 410 | .names = .{ .long = "aa" }, | ||
| 411 | .takes_value = .none, | ||
| 412 | }, try parseParam( | ||
| 413 | \\--aa | ||
| 414 | \\--bb | ||
| 415 | \\ | 396 | \\ |
| 416 | )); | 397 | , &.{ |
| 417 | 398 | .{ .names = .{ .short = 's' } }, | |
| 418 | try expectParam(.{ | 399 | .{ .names = .{ .long = "str" } }, |
| 419 | .id = .{ .val = "q" }, | 400 | .{ .names = .{ .short = 's', .long = "str" } }, |
| 420 | .names = .{ .short = 'a' }, | 401 | .{ |
| 421 | .takes_value = .one, | 402 | .id = .{ .val = "str" }, |
| 422 | }, try parseParam( | 403 | .names = .{ .long = "str" }, |
| 423 | \\-a <q> | 404 | .takes_value = .one, |
| 424 | \\--bb | 405 | }, |
| 425 | \\ | 406 | .{ |
| 426 | )); | 407 | .id = .{ .val = "str" }, |
| 427 | 408 | .names = .{ .short = 's', .long = "str" }, | |
| 428 | try expectParam(.{ | 409 | .takes_value = .one, |
| 429 | .id = .{ .val = "q" }, | 410 | }, |
| 430 | .names = .{ .short = 'a' }, | 411 | .{ |
| 431 | .takes_value = .many, | 412 | .id = .{ .desc = "Help text", .val = "val" }, |
| 432 | }, try parseParam( | 413 | .names = .{ .short = 's', .long = "long" }, |
| 433 | \\-a <q>... | 414 | .takes_value = .one, |
| 434 | \\--bb | 415 | }, |
| 435 | \\ | 416 | .{ |
| 436 | )); | 417 | .id = .{ .desc = "Help text", .val = "val" }, |
| 418 | .names = .{ .short = 's', .long = "long" }, | ||
| 419 | .takes_value = .many, | ||
| 420 | }, | ||
| 421 | .{ | ||
| 422 | .id = .{ .desc = "Help text", .val = "val" }, | ||
| 423 | .names = .{ .long = "long" }, | ||
| 424 | .takes_value = .one, | ||
| 425 | }, | ||
| 426 | .{ | ||
| 427 | .id = .{ .desc = "Help text", .val = "val" }, | ||
| 428 | .names = .{ .short = 's' }, | ||
| 429 | .takes_value = .one, | ||
| 430 | }, | ||
| 431 | .{ | ||
| 432 | .id = .{ .desc = "Help text" }, | ||
| 433 | .names = .{ .short = 's', .long = "long" }, | ||
| 434 | }, | ||
| 435 | .{ | ||
| 436 | .id = .{ .desc = "Help text" }, | ||
| 437 | .names = .{ .short = 's' }, | ||
| 438 | }, | ||
| 439 | .{ | ||
| 440 | .id = .{ .desc = "Help text" }, | ||
| 441 | .names = .{ .long = "long" }, | ||
| 442 | }, | ||
| 443 | .{ | ||
| 444 | .id = .{ .desc = "Help text", .val = "A | B" }, | ||
| 445 | .names = .{ .long = "long" }, | ||
| 446 | .takes_value = .one, | ||
| 447 | }, | ||
| 448 | .{ | ||
| 449 | .id = .{ .desc = "Help text", .val = "A" }, | ||
| 450 | .takes_value = .one, | ||
| 451 | }, | ||
| 452 | .{ | ||
| 453 | .id = .{ .desc = "Help text", .val = "A" }, | ||
| 454 | .names = .{}, | ||
| 455 | .takes_value = .many, | ||
| 456 | }, | ||
| 457 | .{ | ||
| 458 | .id = .{ | ||
| 459 | .desc = | ||
| 460 | \\This is | ||
| 461 | \\ help spanning multiple | ||
| 462 | \\ lines | ||
| 463 | , | ||
| 464 | }, | ||
| 465 | .names = .{ .long = "aa" }, | ||
| 466 | .takes_value = .none, | ||
| 467 | }, | ||
| 468 | .{ | ||
| 469 | .id = .{ .desc = "This msg should end and the newline cause of new param" }, | ||
| 470 | .names = .{ .long = "aa" }, | ||
| 471 | .takes_value = .none, | ||
| 472 | }, | ||
| 473 | .{ | ||
| 474 | .id = .{ .desc = "This should be a new param" }, | ||
| 475 | .names = .{ .long = "bb" }, | ||
| 476 | .takes_value = .none, | ||
| 477 | }, | ||
| 478 | }); | ||
| 437 | 479 | ||
| 438 | try testing.expectError(error.InvalidParameter, parseParam("--long, Help")); | 480 | try testing.expectError(error.InvalidParameter, parseParam("--long, Help")); |
| 439 | try testing.expectError(error.InvalidParameter, parseParam("-s, Help")); | 481 | try testing.expectError(error.InvalidParameter, parseParam("-s, Help")); |
| @@ -821,33 +863,35 @@ fn Arguments( | |||
| 821 | } | 863 | } |
| 822 | 864 | ||
| 823 | test "str and u64" { | 865 | test "str and u64" { |
| 824 | const params = comptime &.{ | 866 | const params = comptime parseParamsComptime( |
| 825 | parseParam("--str <str>") catch unreachable, | 867 | \\--str <str> |
| 826 | parseParam("--num <u64>") catch unreachable, | 868 | \\--num <u64> |
| 827 | }; | 869 | \\ |
| 870 | ); | ||
| 828 | 871 | ||
| 829 | var iter = args.SliceIterator{ | 872 | var iter = args.SliceIterator{ |
| 830 | .args = &.{ "--num", "10", "--str", "cooley_rec_inp_ptr" }, | 873 | .args = &.{ "--num", "10", "--str", "cooley_rec_inp_ptr" }, |
| 831 | }; | 874 | }; |
| 832 | var res = try parseEx(Help, params, parsers.default, &iter, .{ | 875 | var res = try parseEx(Help, ¶ms, parsers.default, &iter, .{ |
| 833 | .allocator = testing.allocator, | 876 | .allocator = testing.allocator, |
| 834 | }); | 877 | }); |
| 835 | defer res.deinit(); | 878 | defer res.deinit(); |
| 836 | } | 879 | } |
| 837 | 880 | ||
| 838 | test "" { | 881 | test "" { |
| 839 | const params = comptime &.{ | 882 | const params = comptime parseParamsComptime( |
| 840 | parseParam("-a, --aa") catch unreachable, | 883 | \\-a, --aa |
| 841 | parseParam("-b, --bb") catch unreachable, | 884 | \\-b, --bb |
| 842 | parseParam("-c, --cc <str>") catch unreachable, | 885 | \\-c, --cc <str> |
| 843 | parseParam("-d, --dd <usize>...") catch unreachable, | 886 | \\-d, --dd <usize>... |
| 844 | parseParam("<str>") catch unreachable, | 887 | \\<str> |
| 845 | }; | 888 | \\ |
| 889 | ); | ||
| 846 | 890 | ||
| 847 | var iter = args.SliceIterator{ | 891 | var iter = args.SliceIterator{ |
| 848 | .args = &.{ "-a", "-c", "0", "something", "-d", "1", "--dd", "2" }, | 892 | .args = &.{ "-a", "-c", "0", "something", "-d", "1", "--dd", "2" }, |
| 849 | }; | 893 | }; |
| 850 | var res = try parseEx(Help, params, parsers.default, &iter, .{ | 894 | var res = try parseEx(Help, ¶ms, parsers.default, &iter, .{ |
| 851 | .allocator = testing.allocator, | 895 | .allocator = testing.allocator, |
| 852 | }); | 896 | }); |
| 853 | defer res.deinit(); | 897 | defer res.deinit(); |
| @@ -888,10 +932,11 @@ fn testErr( | |||
| 888 | } | 932 | } |
| 889 | 933 | ||
| 890 | test "errors" { | 934 | test "errors" { |
| 891 | const params = comptime [_]Param(Help){ | 935 | const params = comptime parseParamsComptime( |
| 892 | parseParam("-a, --aa") catch unreachable, | 936 | \\-a, --aa |
| 893 | parseParam("-c, --cc <str>") catch unreachable, | 937 | \\-c, --cc <str> |
| 894 | }; | 938 | \\ |
| 939 | ); | ||
| 895 | 940 | ||
| 896 | try testErr(¶ms, &.{"q"}, "Invalid argument 'q'\n"); | 941 | try testErr(¶ms, &.{"q"}, "Invalid argument 'q'\n"); |
| 897 | try testErr(¶ms, &.{"-q"}, "Invalid argument '-q'\n"); | 942 | try testErr(¶ms, &.{"-q"}, "Invalid argument '-q'\n"); |
| @@ -957,7 +1002,7 @@ pub fn help(stream: anytype, comptime Id: type, params: []const Param(Id)) !void | |||
| 957 | try stream.writeByteNTimes(' ', max_spacing); | 1002 | try stream.writeByteNTimes(' ', max_spacing); |
| 958 | } | 1003 | } |
| 959 | try stream.writeAll("\t"); | 1004 | try stream.writeAll("\t"); |
| 960 | try stream.writeAll(line); | 1005 | try stream.writeAll(mem.trimLeft(u8, line, " \t")); |
| 961 | try stream.writeAll("\n"); | 1006 | try stream.writeAll("\n"); |
| 962 | } | 1007 | } |
| 963 | } | 1008 | } |
| @@ -998,25 +1043,22 @@ test "clap.help" { | |||
| 998 | var buf: [1024]u8 = undefined; | 1043 | var buf: [1024]u8 = undefined; |
| 999 | var slice_stream = io.fixedBufferStream(&buf); | 1044 | var slice_stream = io.fixedBufferStream(&buf); |
| 1000 | 1045 | ||
| 1001 | @setEvalBranchQuota(10000); | 1046 | const params = comptime parseParamsComptime( |
| 1002 | try help( | 1047 | \\-a Short flag. |
| 1003 | slice_stream.writer(), | 1048 | \\-b <V1> Short option. |
| 1004 | Help, | 1049 | \\--aa Long flag. |
| 1005 | comptime &.{ | 1050 | \\--bb <V2> Long option. |
| 1006 | parseParam("-a Short flag.") catch unreachable, | 1051 | \\-c, --cc Both flag. |
| 1007 | parseParam("-b <V1> Short option.") catch unreachable, | 1052 | \\--complicate Flag with a complicated and |
| 1008 | parseParam("--aa Long flag.") catch unreachable, | 1053 | \\ very long description that |
| 1009 | parseParam("--bb <V2> Long option.") catch unreachable, | 1054 | \\ spans multiple lines. |
| 1010 | parseParam("-c, --cc Both flag.") catch unreachable, | 1055 | \\-d, --dd <V3> Both option. |
| 1011 | parseParam("--complicate Flag with a complicated and\nvery long description that\nspans multiple lines.") catch unreachable, | 1056 | \\-d, --dd <V3>... Both repeated option. |
| 1012 | parseParam("-d, --dd <V3> Both option.") catch unreachable, | 1057 | \\<P> Positional. This should not appear in the help message. |
| 1013 | parseParam("-d, --dd <V3>... Both repeated option.") catch unreachable, | 1058 | \\ |
| 1014 | parseParam( | ||
| 1015 | "<P> Positional. This should not appear in the help message.", | ||
| 1016 | ) catch unreachable, | ||
| 1017 | }, | ||
| 1018 | ); | 1059 | ); |
| 1019 | 1060 | ||
| 1061 | try help(slice_stream.writer(), Help, ¶ms); | ||
| 1020 | const expected = "" ++ | 1062 | const expected = "" ++ |
| 1021 | "\t-a \tShort flag.\n" ++ | 1063 | "\t-a \tShort flag.\n" ++ |
| 1022 | "\t-b <V1> \tShort option.\n" ++ | 1064 | "\t-b <V1> \tShort option.\n" ++ |
| @@ -1105,38 +1147,44 @@ fn testUsage(expected: []const u8, params: []const Param(Help)) !void { | |||
| 1105 | 1147 | ||
| 1106 | test "usage" { | 1148 | test "usage" { |
| 1107 | @setEvalBranchQuota(100000); | 1149 | @setEvalBranchQuota(100000); |
| 1108 | try testUsage("[-ab]", &.{ | 1150 | try testUsage("[-ab]", &comptime parseParamsComptime( |
| 1109 | try parseParam("-a"), | 1151 | \\-a |
| 1110 | try parseParam("-b"), | 1152 | \\-b |
| 1111 | }); | 1153 | \\ |
| 1112 | try testUsage("[-a <value>] [-b <v>]", &.{ | 1154 | )); |
| 1113 | try parseParam("-a <value>"), | 1155 | try testUsage("[-a <value>] [-b <v>]", &comptime parseParamsComptime( |
| 1114 | try parseParam("-b <v>"), | 1156 | \\-a <value> |
| 1115 | }); | 1157 | \\-b <v> |
| 1116 | try testUsage("[--a] [--b]", &.{ | 1158 | \\ |
| 1117 | try parseParam("--a"), | 1159 | )); |
| 1118 | try parseParam("--b"), | 1160 | try testUsage("[--a] [--b]", &comptime parseParamsComptime( |
| 1119 | }); | 1161 | \\--a |
| 1120 | try testUsage("[--a <value>] [--b <v>]", &.{ | 1162 | \\--b |
| 1121 | try parseParam("--a <value>"), | 1163 | \\ |
| 1122 | try parseParam("--b <v>"), | 1164 | )); |
| 1123 | }); | 1165 | try testUsage("[--a <value>] [--b <v>]", &comptime parseParamsComptime( |
| 1124 | try testUsage("<file>", &.{ | 1166 | \\--a <value> |
| 1125 | try parseParam("<file>"), | 1167 | \\--b <v> |
| 1126 | }); | 1168 | \\ |
| 1169 | )); | ||
| 1170 | try testUsage("<file>", &comptime parseParamsComptime( | ||
| 1171 | \\<file> | ||
| 1172 | \\ | ||
| 1173 | )); | ||
| 1127 | try testUsage( | 1174 | try testUsage( |
| 1128 | "[-ab] [-c <value>] [-d <v>] [--e] [--f] [--g <value>] [--h <v>] [-i <v>...] <file>", | 1175 | "[-ab] [-c <value>] [-d <v>] [--e] [--f] [--g <value>] [--h <v>] [-i <v>...] <file>", |
| 1129 | &.{ | 1176 | &comptime parseParamsComptime( |
| 1130 | try parseParam("-a"), | 1177 | \\-a |
| 1131 | try parseParam("-b"), | 1178 | \\-b |
| 1132 | try parseParam("-c <value>"), | 1179 | \\-c <value> |
| 1133 | try parseParam("-d <v>"), | 1180 | \\-d <v> |
| 1134 | try parseParam("--e"), | 1181 | \\--e |
| 1135 | try parseParam("--f"), | 1182 | \\--f |
| 1136 | try parseParam("--g <value>"), | 1183 | \\--g <value> |
| 1137 | try parseParam("--h <v>"), | 1184 | \\--h <v> |
| 1138 | try parseParam("-i <v>..."), | 1185 | \\-i <v>... |
| 1139 | try parseParam("<file>"), | 1186 | \\<file> |
| 1140 | }, | 1187 | \\ |
| 1188 | ), | ||
| 1141 | ); | 1189 | ); |
| 1142 | } | 1190 | } |
diff --git a/example/README.md.template b/example/README.md.template index 9fbc1cc..c19c1cd 100644 --- a/example/README.md.template +++ b/example/README.md.template | |||
| @@ -35,8 +35,8 @@ The fields in `args` are typed. The type is based on the name of the value the p | |||
| 35 | Since `--number` takes a `usize` the field `res.args.number` has the type `usize`. | 35 | Since `--number` takes a `usize` the field `res.args.number` has the type `usize`. |
| 36 | 36 | ||
| 37 | Note that this is only the case because `clap.parsers.default` has a field called `usize` which | 37 | Note that this is only the case because `clap.parsers.default` has a field called `usize` which |
| 38 | contains a parser that returns `usize`. You can pass in something other than `clap.parsers.default` | 38 | contains a parser that returns `usize`. You can pass in something other than |
| 39 | if you want some other mapping. | 39 | `clap.parsers.default` if you want some other mapping. |
| 40 | 40 | ||
| 41 | ```zig | 41 | ```zig |
| 42 | {s} | 42 | {s} |
diff --git a/example/help.zig b/example/help.zig index f3edb58..64d1709 100644 --- a/example/help.zig +++ b/example/help.zig | |||
| @@ -2,10 +2,11 @@ const clap = @import("clap"); | |||
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | 3 | ||
| 4 | pub fn main() !void { | 4 | pub fn main() !void { |
| 5 | const params = comptime [_]clap.Param(clap.Help){ | 5 | const params = comptime clap.parseParamsComptime( |
| 6 | clap.parseParam("-h, --help Display this help and exit. ") catch unreachable, | 6 | \\-h, --help Display this help and exit. |
| 7 | clap.parseParam("-v, --version Output version information and exit.") catch unreachable, | 7 | \\-v, --version Output version information and exit. |
| 8 | }; | 8 | \\ |
| 9 | ); | ||
| 9 | 10 | ||
| 10 | var res = try clap.parse(clap.Help, ¶ms, clap.parsers.default, .{}); | 11 | var res = try clap.parse(clap.Help, ¶ms, clap.parsers.default, .{}); |
| 11 | defer res.deinit(); | 12 | defer res.deinit(); |
diff --git a/example/simple-ex.zig b/example/simple-ex.zig index 6cb4c3f..d0d214d 100644 --- a/example/simple-ex.zig +++ b/example/simple-ex.zig | |||
| @@ -7,13 +7,14 @@ const process = std.process; | |||
| 7 | 7 | ||
| 8 | pub fn main() !void { | 8 | pub fn main() !void { |
| 9 | // First we specify what parameters our program can take. | 9 | // First we specify what parameters our program can take. |
| 10 | // We can use `parseParam` to parse a string to a `Param(Help)` | 10 | // We can use `parseParamsComptime` to parse a string into an array of `Param(Help)` |
| 11 | const params = comptime [_]clap.Param(clap.Help){ | 11 | const params = comptime clap.parseParamsComptime( |
| 12 | clap.parseParam("-h, --help Display this help and exit.") catch unreachable, | 12 | \\-h, --help Display this help and exit. |
| 13 | clap.parseParam("-n, --number <INT> An option parameter, which takes a value.") catch unreachable, | 13 | \\-n, --number <INT> An option parameter, which takes a value. |
| 14 | clap.parseParam("-s, --string <STR>... An option parameter which can be specified multiple times.") catch unreachable, | 14 | \\-s, --string <STR>... An option parameter which can be specified multiple times. |
| 15 | clap.parseParam("<FILE>...") catch unreachable, | 15 | \\<FILE>... |
| 16 | }; | 16 | \\ |
| 17 | ); | ||
| 17 | 18 | ||
| 18 | // Declare our own parsers which are used to map the argument strings to other | 19 | // Declare our own parsers which are used to map the argument strings to other |
| 19 | // types. | 20 | // types. |
diff --git a/example/simple.zig b/example/simple.zig index 11e975e..1ac7de5 100644 --- a/example/simple.zig +++ b/example/simple.zig | |||
| @@ -6,13 +6,14 @@ const io = std.io; | |||
| 6 | 6 | ||
| 7 | pub fn main() !void { | 7 | pub fn main() !void { |
| 8 | // First we specify what parameters our program can take. | 8 | // First we specify what parameters our program can take. |
| 9 | // We can use `parseParam` to parse a string to a `Param(Help)` | 9 | // We can use `parseParamsComptime` to parse a string into an array of `Param(Help)` |
| 10 | const params = comptime [_]clap.Param(clap.Help){ | 10 | const params = comptime clap.parseParamsComptime( |
| 11 | clap.parseParam("-h, --help Display this help and exit.") catch unreachable, | 11 | \\-h, --help Display this help and exit. |
| 12 | clap.parseParam("-n, --number <usize> An option parameter, which takes a value.") catch unreachable, | 12 | \\-n, --number <usize> An option parameter, which takes a value. |
| 13 | clap.parseParam("-s, --string <str>... An option parameter which can be specified multiple times.") catch unreachable, | 13 | \\-s, --string <str>... An option parameter which can be specified multiple times. |
| 14 | clap.parseParam("<str>...") catch unreachable, | 14 | \\<str>... |
| 15 | }; | 15 | \\ |
| 16 | ); | ||
| 16 | 17 | ||
| 17 | // Initalize our diagnostics, which can be used for reporting useful errors. | 18 | // Initalize our diagnostics, which can be used for reporting useful errors. |
| 18 | // This is optional. You can also pass `.{}` to `clap.parse` if you don't | 19 | // This is optional. You can also pass `.{}` to `clap.parse` if you don't |
diff --git a/example/usage.zig b/example/usage.zig index 20d4736..f57b07c 100644 --- a/example/usage.zig +++ b/example/usage.zig | |||
| @@ -2,11 +2,12 @@ const clap = @import("clap"); | |||
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | 3 | ||
| 4 | pub fn main() !void { | 4 | pub fn main() !void { |
| 5 | const params = comptime [_]clap.Param(clap.Help){ | 5 | const params = comptime clap.parseParamsComptime( |
| 6 | clap.parseParam("-h, --help Display this help and exit.") catch unreachable, | 6 | \\-h, --help Display this help and exit. |
| 7 | clap.parseParam("-v, --version Output version information and exit.") catch unreachable, | 7 | \\-v, --version Output version information and exit. |
| 8 | clap.parseParam(" --value <str> An option parameter, which takes a value.") catch unreachable, | 8 | \\ --value <str> An option parameter, which takes a value. |
| 9 | }; | 9 | \\ |
| 10 | ); | ||
| 10 | 11 | ||
| 11 | var res = try clap.parse(clap.Help, ¶ms, clap.parsers.default, .{}); | 12 | var res = try clap.parse(clap.Help, ¶ms, clap.parsers.default, .{}); |
| 12 | defer res.deinit(); | 13 | defer res.deinit(); |