diff options
Diffstat (limited to '')
| -rw-r--r-- | core.zig | 312 | ||||
| -rw-r--r-- | index.zig | 14 |
2 files changed, 179 insertions, 147 deletions
| @@ -6,6 +6,67 @@ const heap = std.heap; | |||
| 6 | const mem = std.mem; | 6 | const mem = std.mem; |
| 7 | const debug = std.debug; | 7 | const debug = std.debug; |
| 8 | 8 | ||
| 9 | /// The names a ::Param can have. | ||
| 10 | pub const Names = struct { | ||
| 11 | /// No prefix | ||
| 12 | bare: ?[]const u8, | ||
| 13 | |||
| 14 | /// '-' prefix | ||
| 15 | short: ?u8, | ||
| 16 | |||
| 17 | /// '--' prefix | ||
| 18 | long: ?[]const u8, | ||
| 19 | |||
| 20 | /// Initializes no names | ||
| 21 | pub fn none() Names { | ||
| 22 | return Names{ | ||
| 23 | .bare = null, | ||
| 24 | .short = null, | ||
| 25 | .long = null, | ||
| 26 | }; | ||
| 27 | } | ||
| 28 | |||
| 29 | /// Initializes a bare name | ||
| 30 | pub fn bare(b: []const u8) Names { | ||
| 31 | return Names{ | ||
| 32 | .bare = b, | ||
| 33 | .short = null, | ||
| 34 | .long = null, | ||
| 35 | }; | ||
| 36 | } | ||
| 37 | |||
| 38 | /// Initializes a short name | ||
| 39 | pub fn short(s: u8) Names { | ||
| 40 | return Names{ | ||
| 41 | .bare = null, | ||
| 42 | .short = s, | ||
| 43 | .long = null, | ||
| 44 | }; | ||
| 45 | } | ||
| 46 | |||
| 47 | /// Initializes a long name | ||
| 48 | pub fn long(l: []const u8) Names { | ||
| 49 | return Names{ | ||
| 50 | .bare = null, | ||
| 51 | .short = null, | ||
| 52 | .long = l, | ||
| 53 | }; | ||
| 54 | } | ||
| 55 | |||
| 56 | /// Initializes a name with a prefix. | ||
| 57 | /// ::short is set to ::name[0], and ::long is set to ::name. | ||
| 58 | /// This function asserts that ::name.len != 0 | ||
| 59 | pub fn prefix(name: []const u8) Names { | ||
| 60 | debug.assert(name.len != 0); | ||
| 61 | |||
| 62 | return Names{ | ||
| 63 | .bare = null, | ||
| 64 | .short = name[0], | ||
| 65 | .long = name, | ||
| 66 | }; | ||
| 67 | } | ||
| 68 | }; | ||
| 69 | |||
| 9 | /// Represents a parameter for the command line. | 70 | /// Represents a parameter for the command line. |
| 10 | /// Parameters come in three kinds: | 71 | /// Parameters come in three kinds: |
| 11 | /// * Short ("-a"): Should be used for the most commonly used parameters in your program. | 72 | /// * Short ("-a"): Should be used for the most commonly used parameters in your program. |
| @@ -19,96 +80,50 @@ const debug = std.debug; | |||
| 19 | /// * "-abc=value" | 80 | /// * "-abc=value" |
| 20 | /// * "-abcvalue" | 81 | /// * "-abcvalue" |
| 21 | /// * Long ("--long-param"): Should be used for less common parameters, or when no single character | 82 | /// * Long ("--long-param"): Should be used for less common parameters, or when no single character |
| 22 | /// can describe the paramter. | 83 | /// can describe the paramter. |
| 23 | /// * They can take a value two different ways. | 84 | /// * They can take a value two different ways. |
| 24 | /// * "--long-param value" | 85 | /// * "--long-param value" |
| 25 | /// * "--long-param=value" | 86 | /// * "--long-param=value" |
| 26 | /// * Command ("command"): Should be used as for sub-commands and other keywords. | 87 | /// * Bare ("bare"): Should be used as for sub-commands and other keywords. |
| 27 | /// * They can take a value two different ways. | 88 | /// * They can take a value two different ways. |
| 28 | /// * "command value" | 89 | /// * "command value" |
| 29 | /// * "command=value" | 90 | /// * "command=value" |
| 30 | /// * Value ("value"): Should be used as the primary parameter of the program, like a filename or | 91 | /// * Value ("value"): Should be used as the primary parameter of the program, like a filename or |
| 31 | /// an expression to parse. | 92 | /// an expression to parse. |
| 93 | /// * Value parameters must take a value. | ||
| 32 | pub fn Param(comptime Id: type) type { | 94 | pub fn Param(comptime Id: type) type { |
| 33 | return struct { | 95 | return struct { |
| 34 | const Self = this; | 96 | const Self = this; |
| 35 | 97 | ||
| 36 | id: Id, | 98 | id: Id, |
| 37 | command: ?[]const u8, | ||
| 38 | short: ?u8, | ||
| 39 | long: ?[]const u8, | ||
| 40 | takes_value: bool, | 99 | takes_value: bool, |
| 100 | names: Names, | ||
| 101 | |||
| 102 | pub fn init(id: Id, takes_value: bool, names: &const Names) Self { | ||
| 103 | // Assert, that if the param have no name, then it has to take | ||
| 104 | // a value. | ||
| 105 | debug.assert( | ||
| 106 | names.bare != null or | ||
| 107 | names.long != null or | ||
| 108 | names.short != null or | ||
| 109 | takes_value | ||
| 110 | ); | ||
| 41 | 111 | ||
| 42 | pub fn short(id: Id, s: u8, takes_value: bool) Self { | ||
| 43 | return Self{ | ||
| 44 | .id = id, | ||
| 45 | .command = null, | ||
| 46 | .short = s, | ||
| 47 | .long = null, | ||
| 48 | .takes_value = takes_value, | ||
| 49 | }; | ||
| 50 | } | ||
| 51 | |||
| 52 | pub fn long(id: Id, l: []const u8, takes_value: bool) Self { | ||
| 53 | return Self{ | ||
| 54 | .id = id, | ||
| 55 | .command = null, | ||
| 56 | .short = null, | ||
| 57 | .long = l, | ||
| 58 | .takes_value = takes_value, | ||
| 59 | }; | ||
| 60 | } | ||
| 61 | |||
| 62 | pub fn command(id: Id, c: []const u8, takes_value: bool) Self { | ||
| 63 | return Self{ | 112 | return Self{ |
| 64 | .id = id, | 113 | .id = id, |
| 65 | .command = c, | ||
| 66 | .short = null, | ||
| 67 | .long = null, | ||
| 68 | .takes_value = takes_value, | 114 | .takes_value = takes_value, |
| 115 | .names = names.*, | ||
| 69 | }; | 116 | }; |
| 70 | } | 117 | } |
| 71 | |||
| 72 | pub fn value(id: Id) Self { | ||
| 73 | return Self{ | ||
| 74 | .id = id, | ||
| 75 | .command = null, | ||
| 76 | .short = null, | ||
| 77 | .long = null, | ||
| 78 | .takes_value = true, | ||
| 79 | }; | ||
| 80 | } | ||
| 81 | |||
| 82 | /// Initialize a ::Param. | ||
| 83 | /// If ::name.len == 0, then it's a value parameter: "value". | ||
| 84 | /// If ::name.len == 1, then it's a short parameter: "-s". | ||
| 85 | /// If ::name.len > 1, then it's a long parameter: "--long". | ||
| 86 | pub fn smart(id: Id, name: []const u8, takes_value: bool) Self { | ||
| 87 | return Self{ | ||
| 88 | .id = id, | ||
| 89 | .command = null, | ||
| 90 | .short = if (name.len == 1) name[0] else null, | ||
| 91 | .long = if (name.len > 1) name else null, | ||
| 92 | .takes_value = takes_value, | ||
| 93 | }; | ||
| 94 | } | ||
| 95 | |||
| 96 | pub fn with(param: &const Self, comptime field_name: []const u8, v: var) Self { | ||
| 97 | var res = param.*; | ||
| 98 | @field(res, field_name) = v; | ||
| 99 | return res; | ||
| 100 | } | ||
| 101 | }; | 118 | }; |
| 102 | } | 119 | } |
| 103 | 120 | ||
| 121 | /// The result returned from ::Clap.next | ||
| 104 | pub fn Arg(comptime Id: type) type { | 122 | pub fn Arg(comptime Id: type) type { |
| 105 | return struct { | 123 | return struct { |
| 106 | const Self = this; | 124 | const Self = this; |
| 107 | 125 | ||
| 108 | id: Id, | 126 | id: Id, |
| 109 | |||
| 110 | /// ::Iterator owns ::value. On windows, this means that when you call ::Iterator.deinit | ||
| 111 | /// ::value is freed. | ||
| 112 | value: ?[]const u8, | 127 | value: ?[]const u8, |
| 113 | 128 | ||
| 114 | pub fn init(id: Id, value: ?[]const u8) Self { | 129 | pub fn init(id: Id, value: ?[]const u8) Self { |
| @@ -120,6 +135,7 @@ pub fn Arg(comptime Id: type) type { | |||
| 120 | }; | 135 | }; |
| 121 | } | 136 | } |
| 122 | 137 | ||
| 138 | /// A interface for iterating over command line arguments | ||
| 123 | pub const ArgIterator = struct { | 139 | pub const ArgIterator = struct { |
| 124 | const Error = error{OutOfMemory}; | 140 | const Error = error{OutOfMemory}; |
| 125 | 141 | ||
| @@ -130,6 +146,8 @@ pub const ArgIterator = struct { | |||
| 130 | } | 146 | } |
| 131 | }; | 147 | }; |
| 132 | 148 | ||
| 149 | /// An ::ArgIterator, which iterates over a slice of arguments. | ||
| 150 | /// This implementation does not allocate. | ||
| 133 | pub const ArgSliceIterator = struct { | 151 | pub const ArgSliceIterator = struct { |
| 134 | args: []const []const u8, | 152 | args: []const []const u8, |
| 135 | index: usize, | 153 | index: usize, |
| @@ -155,6 +173,8 @@ pub const ArgSliceIterator = struct { | |||
| 155 | } | 173 | } |
| 156 | }; | 174 | }; |
| 157 | 175 | ||
| 176 | /// An ::ArgIterator, which wraps the ArgIterator in ::std. | ||
| 177 | /// On windows, this iterator allocates. | ||
| 158 | pub const OsArgIterator = struct { | 178 | pub const OsArgIterator = struct { |
| 159 | args: os.ArgIterator, | 179 | args: os.ArgIterator, |
| 160 | iter: ArgIterator, | 180 | iter: ArgIterator, |
| @@ -178,8 +198,10 @@ pub const OsArgIterator = struct { | |||
| 178 | } | 198 | } |
| 179 | }; | 199 | }; |
| 180 | 200 | ||
| 181 | /// A ::CustomIterator with a default Windows buffer size. | 201 | /// A command line argument parser which, given an ::ArgIterator, will parse arguments according |
| 182 | pub fn Iterator(comptime Id: type) type { | 202 | /// to the ::params. ::Clap parses in an iterating manner, so you have to use a loop together with |
| 203 | /// ::Clap.next to parse all the arguments of your program. | ||
| 204 | pub fn Clap(comptime Id: type) type { | ||
| 183 | return struct { | 205 | return struct { |
| 184 | const Self = this; | 206 | const Self = this; |
| 185 | 207 | ||
| @@ -190,7 +212,6 @@ pub fn Iterator(comptime Id: type) type { | |||
| 190 | const Chaining = struct { | 212 | const Chaining = struct { |
| 191 | arg: []const u8, | 213 | arg: []const u8, |
| 192 | index: usize, | 214 | index: usize, |
| 193 | param: &const Param(Id), | ||
| 194 | }; | 215 | }; |
| 195 | }; | 216 | }; |
| 196 | 217 | ||
| @@ -217,7 +238,7 @@ pub fn Iterator(comptime Id: type) type { | |||
| 217 | /// Get the next ::Arg that matches a ::Param. | 238 | /// Get the next ::Arg that matches a ::Param. |
| 218 | pub fn next(iter: &Self) !?Arg(Id) { | 239 | pub fn next(iter: &Self) !?Arg(Id) { |
| 219 | const ArgInfo = struct { | 240 | const ArgInfo = struct { |
| 220 | const Kind = enum { Long, Short, Command }; | 241 | const Kind = enum { Long, Short, Bare }; |
| 221 | 242 | ||
| 222 | arg: []const u8, | 243 | arg: []const u8, |
| 223 | kind: Kind, | 244 | kind: Kind, |
| @@ -228,7 +249,7 @@ pub fn Iterator(comptime Id: type) type { | |||
| 228 | const full_arg = (try iter.innerNext()) ?? return null; | 249 | const full_arg = (try iter.innerNext()) ?? return null; |
| 229 | const arg_info = blk: { | 250 | const arg_info = blk: { |
| 230 | var arg = full_arg; | 251 | var arg = full_arg; |
| 231 | var kind = ArgInfo.Kind.Command; | 252 | var kind = ArgInfo.Kind.Bare; |
| 232 | 253 | ||
| 233 | if (mem.startsWith(u8, arg, "--")) { | 254 | if (mem.startsWith(u8, arg, "--")) { |
| 234 | arg = arg[2..]; | 255 | arg = arg[2..]; |
| @@ -248,13 +269,13 @@ pub fn Iterator(comptime Id: type) type { | |||
| 248 | const kind = arg_info.kind; | 269 | const kind = arg_info.kind; |
| 249 | const eql_index = mem.indexOfScalar(u8, arg, '='); | 270 | const eql_index = mem.indexOfScalar(u8, arg, '='); |
| 250 | 271 | ||
| 251 | for (iter.params) |*param| { | 272 | switch (kind) { |
| 252 | switch (kind) { | 273 | ArgInfo.Kind.Bare, |
| 253 | ArgInfo.Kind.Command, | 274 | ArgInfo.Kind.Long => { |
| 254 | ArgInfo.Kind.Long => { | 275 | for (iter.params) |*param| { |
| 255 | const match = switch (kind) { | 276 | const match = switch (kind) { |
| 256 | ArgInfo.Kind.Command => param.command ?? continue, | 277 | ArgInfo.Kind.Bare => param.names.bare ?? continue, |
| 257 | ArgInfo.Kind.Long => param.long ?? continue, | 278 | ArgInfo.Kind.Long => param.names.long ?? continue, |
| 258 | else => unreachable, | 279 | else => unreachable, |
| 259 | }; | 280 | }; |
| 260 | const name = if (eql_index) |i| arg[0..i] else arg; | 281 | const name = if (eql_index) |i| arg[0..i] else arg; |
| @@ -277,27 +298,22 @@ pub fn Iterator(comptime Id: type) type { | |||
| 277 | }; | 298 | }; |
| 278 | 299 | ||
| 279 | return Arg(Id).init(param.id, value); | 300 | return Arg(Id).init(param.id, value); |
| 280 | }, | 301 | } |
| 281 | ArgInfo.Kind.Short => { | 302 | }, |
| 282 | const short = param.short ?? continue; | 303 | ArgInfo.Kind.Short => { |
| 283 | if (short != arg[0]) | 304 | return try iter.chainging(State.Chaining { |
| 284 | continue; | 305 | .arg = full_arg, |
| 285 | 306 | .index = (full_arg.len - arg.len), | |
| 286 | return try iter.chainging(State.Chaining { | 307 | }); |
| 287 | .arg = full_arg, | 308 | }, |
| 288 | .index = (full_arg.len - arg.len) + 1, | ||
| 289 | .param = param, | ||
| 290 | }); | ||
| 291 | }, | ||
| 292 | } | ||
| 293 | } | 309 | } |
| 294 | 310 | ||
| 295 | // We do a final pass to look for value parameters matches | 311 | // We do a final pass to look for value parameters matches |
| 296 | if (kind == ArgInfo.Kind.Command) { | 312 | if (kind == ArgInfo.Kind.Bare) { |
| 297 | for (iter.params) |*param| { | 313 | for (iter.params) |*param| { |
| 298 | if (param.short) |_| continue; | 314 | if (param.names.bare) |_| continue; |
| 299 | if (param.long) |_| continue; | 315 | if (param.names.short) |_| continue; |
| 300 | if (param.command) |_| continue; | 316 | if (param.names.long) |_| continue; |
| 301 | 317 | ||
| 302 | return Arg(Id).init(param.id, arg); | 318 | return Arg(Id).init(param.id, arg); |
| 303 | } | 319 | } |
| @@ -312,42 +328,40 @@ pub fn Iterator(comptime Id: type) type { | |||
| 312 | fn chainging(iter: &Self, state: &const State.Chaining) !?Arg(Id) { | 328 | fn chainging(iter: &Self, state: &const State.Chaining) !?Arg(Id) { |
| 313 | const arg = state.arg; | 329 | const arg = state.arg; |
| 314 | const index = state.index; | 330 | const index = state.index; |
| 315 | const curr_param = state.param; | 331 | const next_index = index + 1; |
| 316 | |||
| 317 | if (curr_param.takes_value) { | ||
| 318 | iter.state = State.Normal; | ||
| 319 | 332 | ||
| 320 | if (arg.len <= index) { | 333 | for (iter.params) |param| { |
| 321 | const value = (try iter.innerNext()) ?? return error.MissingValue; | 334 | const short = param.names.short ?? continue; |
| 322 | return Arg(Id).init(curr_param.id, value); | 335 | if (short != arg[index]) |
| 323 | } | 336 | continue; |
| 324 | 337 | ||
| 325 | if (arg[index] == '=') { | 338 | // Before we return, we have to set the new state of the iterator |
| 326 | return Arg(Id).init(curr_param.id, arg[index + 1..]); | 339 | defer { |
| 340 | if (arg.len <= next_index or param.takes_value) { | ||
| 341 | iter.state = State.Normal; | ||
| 342 | } else { | ||
| 343 | iter.state = State { .Chaining = State.Chaining { | ||
| 344 | .arg = arg, | ||
| 345 | .index = next_index, | ||
| 346 | }}; | ||
| 347 | } | ||
| 327 | } | 348 | } |
| 328 | 349 | ||
| 329 | return Arg(Id).init(curr_param.id, arg[index..]); | 350 | if (!param.takes_value) |
| 330 | } | 351 | return Arg(Id).init(param.id, null); |
| 331 | 352 | ||
| 332 | if (arg.len <= index) { | 353 | if (arg.len <= next_index) { |
| 333 | iter.state = State.Normal; | 354 | const value = (try iter.innerNext()) ?? return error.MissingValue; |
| 334 | return Arg(Id).init(curr_param.id, null); | 355 | return Arg(Id).init(param.id, value); |
| 335 | } | 356 | } |
| 336 | 357 | ||
| 337 | for (iter.params) |*param| { | 358 | if (arg[next_index] == '=') { |
| 338 | const short = param.short ?? continue; | 359 | return Arg(Id).init(param.id, arg[next_index + 1..]); |
| 339 | if (short != arg[index]) | 360 | } |
| 340 | continue; | ||
| 341 | 361 | ||
| 342 | iter.state = State { .Chaining = State.Chaining { | 362 | return Arg(Id).init(param.id, arg[next_index..]); |
| 343 | .arg = arg, | ||
| 344 | .index = index + 1, | ||
| 345 | .param = param, | ||
| 346 | }}; | ||
| 347 | return Arg(Id).init(curr_param.id, null); | ||
| 348 | } | 363 | } |
| 349 | 364 | ||
| 350 | // This actually returns an error for the next argument. | ||
| 351 | return error.InvalidArgument; | 365 | return error.InvalidArgument; |
| 352 | } | 366 | } |
| 353 | 367 | ||
| @@ -359,7 +373,7 @@ pub fn Iterator(comptime Id: type) type { | |||
| 359 | 373 | ||
| 360 | fn testNoErr(params: []const Param(u8), args: []const []const u8, ids: []const u8, values: []const ?[]const u8) void { | 374 | fn testNoErr(params: []const Param(u8), args: []const []const u8, ids: []const u8, values: []const ?[]const u8) void { |
| 361 | var arg_iter = ArgSliceIterator.init(args); | 375 | var arg_iter = ArgSliceIterator.init(args); |
| 362 | var iter = Iterator(u8).init(params, &arg_iter.iter, debug.global_allocator); | 376 | var iter = Clap(u8).init(params, &arg_iter.iter, debug.global_allocator); |
| 363 | 377 | ||
| 364 | var i: usize = 0; | 378 | var i: usize = 0; |
| 365 | while (iter.next() catch unreachable) |arg| : (i += 1) { | 379 | while (iter.next() catch unreachable) |arg| : (i += 1) { |
| @@ -376,9 +390,9 @@ fn testNoErr(params: []const Param(u8), args: []const []const u8, ids: []const u | |||
| 376 | 390 | ||
| 377 | test "clap.core: short" { | 391 | test "clap.core: short" { |
| 378 | const params = []Param(u8) { | 392 | const params = []Param(u8) { |
| 379 | Param(u8).smart(0, "a", false), | 393 | Param(u8).init(0, false, Names.short('a')), |
| 380 | Param(u8).smart(1, "b", false), | 394 | Param(u8).init(1, false, Names.short('b')), |
| 381 | Param(u8).smart(2, "c", true), | 395 | Param(u8).init(2, true, Names.short('c')), |
| 382 | }; | 396 | }; |
| 383 | 397 | ||
| 384 | testNoErr(params, [][]const u8 { "-a" }, []u8{0}, []?[]const u8{null}); | 398 | testNoErr(params, [][]const u8 { "-a" }, []u8{0}, []?[]const u8{null}); |
| @@ -394,9 +408,9 @@ test "clap.core: short" { | |||
| 394 | 408 | ||
| 395 | test "clap.core: long" { | 409 | test "clap.core: long" { |
| 396 | const params = []Param(u8) { | 410 | const params = []Param(u8) { |
| 397 | Param(u8).smart(0, "aa", false), | 411 | Param(u8).init(0, false, Names.long("aa")), |
| 398 | Param(u8).smart(1, "bb", false), | 412 | Param(u8).init(1, false, Names.long("bb")), |
| 399 | Param(u8).smart(2, "cc", true), | 413 | Param(u8).init(2, true, Names.long("cc")), |
| 400 | }; | 414 | }; |
| 401 | 415 | ||
| 402 | testNoErr(params, [][]const u8 { "--aa" }, []u8{0}, []?[]const u8{null}); | 416 | testNoErr(params, [][]const u8 { "--aa" }, []u8{0}, []?[]const u8{null}); |
| @@ -405,11 +419,11 @@ test "clap.core: long" { | |||
| 405 | testNoErr(params, [][]const u8 { "--cc", "100" }, []u8{2}, []?[]const u8{"100"}); | 419 | testNoErr(params, [][]const u8 { "--cc", "100" }, []u8{2}, []?[]const u8{"100"}); |
| 406 | } | 420 | } |
| 407 | 421 | ||
| 408 | test "clap.core: command" { | 422 | test "clap.core: bare" { |
| 409 | const params = []Param(u8) { | 423 | const params = []Param(u8) { |
| 410 | Param(u8).command(0, "aa", false), | 424 | Param(u8).init(0, false, Names.bare("aa")), |
| 411 | Param(u8).command(1, "bb", false), | 425 | Param(u8).init(1, false, Names.bare("bb")), |
| 412 | Param(u8).command(2, "cc", true), | 426 | Param(u8).init(2, true, Names.bare("cc")), |
| 413 | }; | 427 | }; |
| 414 | 428 | ||
| 415 | testNoErr(params, [][]const u8 { "aa" }, []u8{0}, []?[]const u8{null}); | 429 | testNoErr(params, [][]const u8 { "aa" }, []u8{0}, []?[]const u8{null}); |
| @@ -418,9 +432,9 @@ test "clap.core: command" { | |||
| 418 | testNoErr(params, [][]const u8 { "cc", "100" }, []u8{2}, []?[]const u8{"100"}); | 432 | testNoErr(params, [][]const u8 { "cc", "100" }, []u8{2}, []?[]const u8{"100"}); |
| 419 | } | 433 | } |
| 420 | 434 | ||
| 421 | test "clap.core: value" { | 435 | test "clap.core: none" { |
| 422 | const params = []Param(u8) { | 436 | const params = []Param(u8) { |
| 423 | Param(u8).value(0), | 437 | Param(u8).init(0, true, Names.none()), |
| 424 | }; | 438 | }; |
| 425 | 439 | ||
| 426 | testNoErr(params, [][]const u8 { "aa" }, []u8{0}, []?[]const u8{"aa"}); | 440 | testNoErr(params, [][]const u8 { "aa" }, []u8{0}, []?[]const u8{"aa"}); |
| @@ -428,16 +442,34 @@ test "clap.core: value" { | |||
| 428 | 442 | ||
| 429 | test "clap.core: all" { | 443 | test "clap.core: all" { |
| 430 | const params = []Param(u8) { | 444 | const params = []Param(u8) { |
| 431 | Param(u8).short(0, 'a', false) | 445 | Param(u8).init( |
| 432 | .with("long", "aa"[0..]) | 446 | 0, |
| 433 | .with("command", "aa"[0..]), | 447 | false, |
| 434 | Param(u8).short(1, 'b', false) | 448 | Names{ |
| 435 | .with("long", "bb"[0..]) | 449 | .bare = "aa", |
| 436 | .with("command", "bb"[0..]), | 450 | .short = 'a', |
| 437 | Param(u8).short(2, 'c', true) | 451 | .long = "aa", |
| 438 | .with("long", "cc"[0..]) | 452 | } |
| 439 | .with("command", "cc"[0..]), | 453 | ), |
| 440 | Param(u8).value(3), | 454 | Param(u8).init( |
| 455 | 1, | ||
| 456 | false, | ||
| 457 | Names{ | ||
| 458 | .bare = "bb", | ||
| 459 | .short = 'b', | ||
| 460 | .long = "bb", | ||
| 461 | } | ||
| 462 | ), | ||
| 463 | Param(u8).init( | ||
| 464 | 2, | ||
| 465 | true, | ||
| 466 | Names{ | ||
| 467 | .bare = "cc", | ||
| 468 | .short = 'c', | ||
| 469 | .long = "cc", | ||
| 470 | } | ||
| 471 | ), | ||
| 472 | Param(u8).init(3, true, Names.none()), | ||
| 441 | }; | 473 | }; |
| 442 | 474 | ||
| 443 | testNoErr(params, [][]const u8 { "-a" }, []u8{0}, []?[]const u8{null}); | 475 | testNoErr(params, [][]const u8 { "-a" }, []u8{0}, []?[]const u8{null}); |
| @@ -128,10 +128,12 @@ pub const Command = struct { | |||
| 128 | const id = i; | 128 | const id = i; |
| 129 | res[id] = core.Param(usize) { | 129 | res[id] = core.Param(usize) { |
| 130 | .id = id, | 130 | .id = id, |
| 131 | .command = null, | ||
| 132 | .short = p.short, | ||
| 133 | .long = p.long, | ||
| 134 | .takes_value = p.takes_value != null, | 131 | .takes_value = p.takes_value != null, |
| 132 | .names = core.Names{ | ||
| 133 | .bare = null, | ||
| 134 | .short = p.short, | ||
| 135 | .long = p.long, | ||
| 136 | }, | ||
| 135 | }; | 137 | }; |
| 136 | } | 138 | } |
| 137 | 139 | ||
| @@ -139,10 +141,8 @@ pub const Command = struct { | |||
| 139 | const id = i + command.params.len; | 141 | const id = i + command.params.len; |
| 140 | res[id] = core.Param(usize) { | 142 | res[id] = core.Param(usize) { |
| 141 | .id = id, | 143 | .id = id, |
| 142 | .command = c.name, | ||
| 143 | .short = null, | ||
| 144 | .long = null, | ||
| 145 | .takes_value = false, | 144 | .takes_value = false, |
| 145 | .names = core.Names.bare(c.name), | ||
| 146 | }; | 146 | }; |
| 147 | } | 147 | } |
| 148 | 148 | ||
| @@ -159,7 +159,7 @@ pub const Command = struct { | |||
| 159 | }; | 159 | }; |
| 160 | 160 | ||
| 161 | var pos: usize = 0; | 161 | var pos: usize = 0; |
| 162 | var iter = core.Iterator(usize).init(core_params, arg_iter, allocator); | 162 | var iter = core.Clap(usize).init(core_params, arg_iter, allocator); |
| 163 | defer iter.deinit(); | 163 | defer iter.deinit(); |
| 164 | 164 | ||
| 165 | arg_loop: | 165 | arg_loop: |