diff options
| author | 2024-10-24 17:40:56 +0200 | |
|---|---|---|
| committer | 2024-10-24 17:45:01 +0200 | |
| commit | 281090c23ca631d8811d7ccb2a0dcdf4ef72a7b1 (patch) | |
| tree | 0faafb2b82ddd85ddc824332310be23660c5867c /README.md | |
| parent | feat: Support multiple positionals of different types (diff) | |
| download | zig-clap-281090c23ca631d8811d7ccb2a0dcdf4ef72a7b1.tar.gz zig-clap-281090c23ca631d8811d7ccb2a0dcdf4ef72a7b1.tar.xz zig-clap-281090c23ca631d8811d7ccb2a0dcdf4ef72a7b1.zip | |
docs: Add subcommand example
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 107 |
1 files changed, 106 insertions, 1 deletions
| @@ -103,7 +103,7 @@ The result will contain an `args` field and a `positionals` field. `args` will h | |||
| 103 | for each none positional parameter of your program. The name of the field will be the longest | 103 | for each none positional parameter of your program. The name of the field will be the longest |
| 104 | name of the parameter. `positionals` be a tuple with one field for each positional parameter. | 104 | name of the parameter. `positionals` be a tuple with one field for each positional parameter. |
| 105 | 105 | ||
| 106 | The fields in `args` and `psotionals` are typed. The type is based on the name of the value the | 106 | The fields in `args` and `postionals` are typed. The type is based on the name of the value the |
| 107 | parameter takes. Since `--number` takes a `usize` the field `res.args.number` has the type `usize`. | 107 | parameter takes. Since `--number` takes a `usize` the field `res.args.number` has the type `usize`. |
| 108 | 108 | ||
| 109 | Note that this is only the case because `clap.parsers.default` has a field called `usize` which | 109 | Note that this is only the case because `clap.parsers.default` has a field called `usize` which |
| @@ -166,6 +166,111 @@ const std = @import("std"); | |||
| 166 | 166 | ||
| 167 | ``` | 167 | ``` |
| 168 | 168 | ||
| 169 | ### Subcommands | ||
| 170 | |||
| 171 | There is an option for `clap.parse` and `clap.parseEx` called `terminating_positional`. It allows | ||
| 172 | for users of `clap` to implement subcommands in their cli application: | ||
| 173 | |||
| 174 | ```zig | ||
| 175 | // These are our subcommands | ||
| 176 | const SubCommands = enum { | ||
| 177 | help, | ||
| 178 | math, | ||
| 179 | }; | ||
| 180 | |||
| 181 | const main_parsers = .{ | ||
| 182 | .command = clap.parsers.enumeration(SubCommands), | ||
| 183 | }; | ||
| 184 | |||
| 185 | // The parameters for main. Parameters for the subcommands are specified further down | ||
| 186 | const main_params = clap.parseParamsComptime( | ||
| 187 | \\-h, --help Display this help and exit. | ||
| 188 | \\<command> | ||
| 189 | \\ | ||
| 190 | ); | ||
| 191 | |||
| 192 | // To pass around arguments returned by clap, `clap.Result` and `clap.ResultEx` can be used to | ||
| 193 | // get the return type of `clap.parse` and `clap.parseEx` | ||
| 194 | const MainArgs = clap.ResultEx(clap.Help, &main_params, main_parsers); | ||
| 195 | |||
| 196 | pub fn main() !void { | ||
| 197 | var gpa_state = std.heap.GeneralPurposeAllocator(.{}){}; | ||
| 198 | const gpa = gpa_state.allocator(); | ||
| 199 | defer _ = gpa_state.deinit(); | ||
| 200 | |||
| 201 | var iter = try std.process.ArgIterator.initWithAllocator(gpa); | ||
| 202 | defer iter.deinit(); | ||
| 203 | |||
| 204 | _ = iter.next(); | ||
| 205 | |||
| 206 | var diag = clap.Diagnostic{}; | ||
| 207 | var res = clap.parseEx(clap.Help, &main_params, main_parsers, &iter, .{ | ||
| 208 | .diagnostic = &diag, | ||
| 209 | .allocator = gpa, | ||
| 210 | |||
| 211 | // Terminate the parsing of arguments after parsing the first positional (0 is passed here | ||
| 212 | // because parsed positionals are, like slices and arrays, indexed starting at 0). | ||
| 213 | // | ||
| 214 | // This will terminate the parsing after parsing the subcommand enum and leave `iter` not | ||
| 215 | // fully consumed. It can then be reused to parse the arguments for subcommands | ||
| 216 | .terminating_positional = 0, | ||
| 217 | }) catch |err| { | ||
| 218 | diag.report(std.io.getStdErr().writer(), err) catch {}; | ||
| 219 | return err; | ||
| 220 | }; | ||
| 221 | defer res.deinit(); | ||
| 222 | |||
| 223 | if (res.args.help != 0) | ||
| 224 | std.debug.print("--help\n", .{}); | ||
| 225 | |||
| 226 | const command = res.positionals[0] orelse return error.MissingCommand; | ||
| 227 | switch (command) { | ||
| 228 | .help => std.debug.print("--help\n", .{}), | ||
| 229 | .math => try mathMain(gpa, &iter, res), | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | fn mathMain(gpa: std.mem.Allocator, iter: *std.process.ArgIterator, main_args: MainArgs) !void { | ||
| 234 | // The parent arguments are not used it, but there are cases where it might be useful, so the | ||
| 235 | // example shows how to pass the arguments around. | ||
| 236 | _ = main_args; | ||
| 237 | |||
| 238 | // The parameters for the subcommand | ||
| 239 | const params = comptime clap.parseParamsComptime( | ||
| 240 | \\-h, --help Display this help and exit. | ||
| 241 | \\-a, --add Add the two numbers | ||
| 242 | \\-s, --sub Subtract the two numbers | ||
| 243 | \\<isize> | ||
| 244 | \\<isize> | ||
| 245 | \\ | ||
| 246 | ); | ||
| 247 | |||
| 248 | // Here we pass the partially parsed argument iterator | ||
| 249 | var diag = clap.Diagnostic{}; | ||
| 250 | var res = clap.parseEx(clap.Help, ¶ms, clap.parsers.default, iter, .{ | ||
| 251 | .diagnostic = &diag, | ||
| 252 | .allocator = gpa, | ||
| 253 | }) catch |err| { | ||
| 254 | diag.report(std.io.getStdErr().writer(), err) catch {}; | ||
| 255 | return err; | ||
| 256 | }; | ||
| 257 | defer res.deinit(); | ||
| 258 | |||
| 259 | const a = res.positionals[0] orelse return error.MissingArg1; | ||
| 260 | const b = res.positionals[1] orelse return error.MissingArg1; | ||
| 261 | if (res.args.help != 0) | ||
| 262 | std.debug.print("--help\n", .{}); | ||
| 263 | if (res.args.add != 0) | ||
| 264 | std.debug.print("added: {}\n", .{a + b}); | ||
| 265 | if (res.args.sub != 0) | ||
| 266 | std.debug.print("subtracted: {}\n", .{a - b}); | ||
| 267 | } | ||
| 268 | |||
| 269 | const clap = @import("clap"); | ||
| 270 | const std = @import("std"); | ||
| 271 | |||
| 272 | ``` | ||
| 273 | |||
| 169 | ### `streaming.Clap` | 274 | ### `streaming.Clap` |
| 170 | 275 | ||
| 171 | The `streaming.Clap` is the base of all the other parsers. It's a streaming parser that uses an | 276 | The `streaming.Clap` is the base of all the other parsers. It's a streaming parser that uses an |