diff options
| author | 2018-03-20 10:40:43 +0100 | |
|---|---|---|
| committer | 2018-03-20 10:40:43 +0100 | |
| commit | c362215f7433950152d56fc0f28929c72701128b (patch) | |
| tree | 3b7cabe20bc956dab12ae8cba0de2caab9b16785 | |
| parent | Updated help function to not use inline loop. (diff) | |
| download | zig-clap-c362215f7433950152d56fc0f28929c72701128b.tar.gz zig-clap-c362215f7433950152d56fc0f28929c72701128b.tar.xz zig-clap-c362215f7433950152d56fc0f28929c72701128b.zip | |
We now handle arguments "--arg=VALUE"
Diffstat (limited to '')
| -rw-r--r-- | clap.zig | 69 |
1 files changed, 48 insertions, 21 deletions
| @@ -11,7 +11,6 @@ const assert = debug.assert; | |||
| 11 | // TODO: Missing a few convinient features | 11 | // TODO: Missing a few convinient features |
| 12 | // * Short arguments that doesn't take values should probably be able to be | 12 | // * Short arguments that doesn't take values should probably be able to be |
| 13 | // chain like many linux programs: "rm -rf" | 13 | // chain like many linux programs: "rm -rf" |
| 14 | // * Handle "--something=VALUE" | ||
| 15 | pub fn Option(comptime Result: type, comptime ParseError: type) type { | 14 | pub fn Option(comptime Result: type, comptime ParseError: type) type { |
| 16 | return struct { | 15 | return struct { |
| 17 | const Self = this; | 16 | const Self = this; |
| @@ -75,7 +74,20 @@ pub fn Parser(comptime Result: type, comptime ParseError: type, comptime default | |||
| 75 | const Kind = enum { Long, Short, None }; | 74 | const Kind = enum { Long, Short, None }; |
| 76 | 75 | ||
| 77 | arg: []const u8, | 76 | arg: []const u8, |
| 78 | kind: Kind | 77 | kind: Kind, |
| 78 | after_eql: ?[]const u8, | ||
| 79 | }; | ||
| 80 | |||
| 81 | const Iterator = struct { | ||
| 82 | slice: []const []const u8, | ||
| 83 | |||
| 84 | pub fn next(it: &this) ?[]const u8 { | ||
| 85 | if (it.slice.len == 0) | ||
| 86 | return null; | ||
| 87 | |||
| 88 | defer it.slice = it.slice[1..]; | ||
| 89 | return it.slice[0]; | ||
| 90 | } | ||
| 79 | }; | 91 | }; |
| 80 | 92 | ||
| 81 | // NOTE: For now, a bitfield is used to keep track of the required arguments. | 93 | // NOTE: For now, a bitfield is used to keep track of the required arguments. |
| @@ -109,19 +121,33 @@ pub fn Parser(comptime Result: type, comptime ParseError: type, comptime default | |||
| 109 | var result = *defaults; | 121 | var result = *defaults; |
| 110 | var required = required_mask; | 122 | var required = required_mask; |
| 111 | 123 | ||
| 112 | var arg_i = usize(0); | 124 | var it = Iterator { .slice = args }; |
| 113 | while (arg_i < args.len) : (arg_i += 1) { | 125 | while (it.next()) |item| { |
| 114 | const pair = blk: { | 126 | const arg_info = blk: { |
| 115 | const tmp = args[arg_i]; | 127 | var arg = item; |
| 116 | if (mem.startsWith(u8, tmp, "--")) | 128 | var kind = Arg.Kind.None; |
| 117 | break :blk Arg { .arg = tmp[2..], .kind = Arg.Kind.Long }; | 129 | |
| 118 | if (mem.startsWith(u8, tmp, "-")) | 130 | if (mem.startsWith(u8, arg, "--")) { |
| 119 | break :blk Arg { .arg = tmp[1..], .kind = Arg.Kind.Short }; | 131 | arg = arg[2..]; |
| 132 | kind = Arg.Kind.Long; | ||
| 133 | } else if (mem.startsWith(u8, arg, "-")) { | ||
| 134 | arg = arg[1..]; | ||
| 135 | kind = Arg.Kind.Short; | ||
| 136 | } | ||
| 137 | |||
| 138 | if (kind == Arg.Kind.None) | ||
| 139 | break :blk Arg { .arg = arg, .kind = kind, .after_eql = null }; | ||
| 120 | 140 | ||
| 121 | break :blk Arg { .arg = tmp, .kind = Arg.Kind.None }; | 141 | |
| 142 | if (mem.indexOfScalar(u8, arg, '=')) |index| { | ||
| 143 | break :blk Arg { .arg = arg[0..index], .kind = kind, .after_eql = arg[index + 1..] }; | ||
| 144 | } else { | ||
| 145 | break :blk Arg { .arg = arg, .kind = kind, .after_eql = null }; | ||
| 146 | } | ||
| 122 | }; | 147 | }; |
| 123 | const arg = pair.arg; | 148 | const arg = arg_info.arg; |
| 124 | const kind = pair.kind; | 149 | const kind = arg_info.kind; |
| 150 | const after_eql = arg_info.after_eql; | ||
| 125 | 151 | ||
| 126 | success: { | 152 | success: { |
| 127 | var required_index = usize(0); | 153 | var required_index = usize(0); |
| @@ -144,10 +170,8 @@ pub fn Parser(comptime Result: type, comptime ParseError: type, comptime default | |||
| 144 | const short = option.short ?? continue; | 170 | const short = option.short ?? continue; |
| 145 | if (arg.len == 1 and arg[0] == short) { | 171 | if (arg.len == 1 and arg[0] == short) { |
| 146 | if (option.takes_value) { | 172 | if (option.takes_value) { |
| 147 | arg_i += 1; | 173 | const value = after_eql ?? it.next() ?? return error.OptionMissingValue; |
| 148 | if (args.len <= arg_i) return error.OptionMissingValue; | 174 | try option.parse(&result, value); |
| 149 | |||
| 150 | try option.parse(&result, args[arg_i]); | ||
| 151 | } else { | 175 | } else { |
| 152 | try option.parse(&result, []u8{}); | 176 | try option.parse(&result, []u8{}); |
| 153 | } | 177 | } |
| @@ -163,10 +187,8 @@ pub fn Parser(comptime Result: type, comptime ParseError: type, comptime default | |||
| 163 | const long = option.long ?? continue; | 187 | const long = option.long ?? continue; |
| 164 | if (mem.eql(u8, arg, long)) { | 188 | if (mem.eql(u8, arg, long)) { |
| 165 | if (option.takes_value) { | 189 | if (option.takes_value) { |
| 166 | arg_i += 1; | 190 | const value = after_eql ?? it.next() ?? return error.OptionMissingValue; |
| 167 | if (args.len <= arg_i) return error.OptionMissingValue; | 191 | try option.parse(&result, value); |
| 168 | |||
| 169 | try option.parse(&result, args[arg_i]); | ||
| 170 | } else { | 192 | } else { |
| 171 | try option.parse(&result, []u8{}); | 193 | try option.parse(&result, []u8{}); |
| 172 | } | 194 | } |
| @@ -285,6 +307,11 @@ test "clap.parse.Example" { | |||
| 285 | .err = null, | 307 | .err = null, |
| 286 | }, | 308 | }, |
| 287 | Case { | 309 | Case { |
| 310 | .args = [][]const u8 { "--red=100", "-g=100", "--blue=50", }, | ||
| 311 | .res = Color { .r = 100, .g = 100, .b = 50 }, | ||
| 312 | .err = null, | ||
| 313 | }, | ||
| 314 | Case { | ||
| 288 | .args = [][]const u8 { "-g", "200", "--blue", "100", "--red", "100", }, | 315 | .args = [][]const u8 { "-g", "200", "--blue", "100", "--red", "100", }, |
| 289 | .res = Color { .r = 100, .g = 200, .b = 100 }, | 316 | .res = Color { .r = 100, .g = 200, .b = 100 }, |
| 290 | .err = null, | 317 | .err = null, |