summaryrefslogtreecommitdiff
path: root/example
diff options
context:
space:
mode:
authorGravatar Jimmi Holst Christensen2024-10-24 17:40:56 +0200
committerGravatar Jimmi Holst Christensen2024-10-24 17:40:56 +0200
commit9de3cd86063d9476be0b7690d69c20f315d271b0 (patch)
tree0faafb2b82ddd85ddc824332310be23660c5867c /example
parentfeat: Support multiple positionals of different types (diff)
downloadzig-clap-9de3cd86063d9476be0b7690d69c20f315d271b0.tar.gz
zig-clap-9de3cd86063d9476be0b7690d69c20f315d271b0.tar.xz
zig-clap-9de3cd86063d9476be0b7690d69c20f315d271b0.zip
docs: Add subcommand examplesubcommand-example
Diffstat (limited to 'example')
-rw-r--r--example/README.md.template11
-rw-r--r--example/subcommands.zig96
2 files changed, 106 insertions, 1 deletions
diff --git a/example/README.md.template b/example/README.md.template
index d234dcd..bcd3774 100644
--- a/example/README.md.template
+++ b/example/README.md.template
@@ -63,7 +63,7 @@ The result will contain an `args` field and a `positionals` field. `args` will h
63for each none positional parameter of your program. The name of the field will be the longest 63for each none positional parameter of your program. The name of the field will be the longest
64name of the parameter. `positionals` be a tuple with one field for each positional parameter. 64name of the parameter. `positionals` be a tuple with one field for each positional parameter.
65 65
66The fields in `args` and `psotionals` are typed. The type is based on the name of the value the 66The fields in `args` and `postionals` are typed. The type is based on the name of the value the
67parameter takes. Since `--number` takes a `usize` the field `res.args.number` has the type `usize`. 67parameter takes. Since `--number` takes a `usize` the field `res.args.number` has the type `usize`.
68 68
69Note that this is only the case because `clap.parsers.default` has a field called `usize` which 69Note that this is only the case because `clap.parsers.default` has a field called `usize` which
@@ -74,6 +74,15 @@ contains a parser that returns `usize`. You can pass in something other than
74{s} 74{s}
75``` 75```
76 76
77### Subcommands
78
79There is an option for `clap.parse` and `clap.parseEx` called `terminating_positional`. It allows
80for users of `clap` to implement subcommands in their cli application:
81
82```zig
83{s}
84```
85
77### `streaming.Clap` 86### `streaming.Clap`
78 87
79The `streaming.Clap` is the base of all the other parsers. It's a streaming parser that uses an 88The `streaming.Clap` is the base of all the other parsers. It's a streaming parser that uses an
diff --git a/example/subcommands.zig b/example/subcommands.zig
new file mode 100644
index 0000000..531a4d6
--- /dev/null
+++ b/example/subcommands.zig
@@ -0,0 +1,96 @@
1// These are our subcommands
2const SubCommands = enum {
3 help,
4 math,
5};
6
7const main_parsers = .{
8 .command = clap.parsers.enumeration(SubCommands),
9};
10
11// The parameters for main. Parameters for the subcommands are specified further down
12const main_params = clap.parseParamsComptime(
13 \\-h, --help Display this help and exit.
14 \\<command>
15 \\
16);
17
18// To pass around arguments returned by clap, `clap.Result` and `clap.ResultEx` can be used to
19// get the return type of `clap.parse` and `clap.parseEx`
20const MainArgs = clap.ResultEx(clap.Help, &main_params, main_parsers);
21
22pub fn main() !void {
23 var gpa_state = std.heap.GeneralPurposeAllocator(.{}){};
24 const gpa = gpa_state.allocator();
25 defer _ = gpa_state.deinit();
26
27 var iter = try std.process.ArgIterator.initWithAllocator(gpa);
28 defer iter.deinit();
29
30 _ = iter.next();
31
32 var diag = clap.Diagnostic{};
33 var res = clap.parseEx(clap.Help, &main_params, main_parsers, &iter, .{
34 .diagnostic = &diag,
35 .allocator = gpa,
36
37 // Terminate the parsing of arguments after parsing the first positional (0 is passed here
38 // because parsed positionals are, like slices and arrays, indexed starting at 0).
39 //
40 // This will terminate the parsing after parsing the subcommand enum and leave `iter` not
41 // fully consumed. It can then be reused to parse the arguments for subcommands
42 .terminating_positional = 0,
43 }) catch |err| {
44 diag.report(std.io.getStdErr().writer(), err) catch {};
45 return err;
46 };
47 defer res.deinit();
48
49 if (res.args.help != 0)
50 std.debug.print("--help\n", .{});
51
52 const command = res.positionals[0] orelse return error.MissingCommand;
53 switch (command) {
54 .help => std.debug.print("--help\n", .{}),
55 .math => try mathMain(gpa, &iter, res),
56 }
57}
58
59fn mathMain(gpa: std.mem.Allocator, iter: *std.process.ArgIterator, main_args: MainArgs) !void {
60 // The parent arguments are not used it, but there are cases where it might be useful, so the
61 // example shows how to pass the arguments around.
62 _ = main_args;
63
64 // The parameters for the subcommand
65 const params = comptime clap.parseParamsComptime(
66 \\-h, --help Display this help and exit.
67 \\-a, --add Add the two numbers
68 \\-s, --sub Subtract the two numbers
69 \\<isize>
70 \\<isize>
71 \\
72 );
73
74 // Here we pass the partially parsed argument iterator
75 var diag = clap.Diagnostic{};
76 var res = clap.parseEx(clap.Help, &params, clap.parsers.default, iter, .{
77 .diagnostic = &diag,
78 .allocator = gpa,
79 }) catch |err| {
80 diag.report(std.io.getStdErr().writer(), err) catch {};
81 return err;
82 };
83 defer res.deinit();
84
85 const a = res.positionals[0] orelse return error.MissingArg1;
86 const b = res.positionals[1] orelse return error.MissingArg1;
87 if (res.args.help != 0)
88 std.debug.print("--help\n", .{});
89 if (res.args.add != 0)
90 std.debug.print("added: {}\n", .{a + b});
91 if (res.args.sub != 0)
92 std.debug.print("subtracted: {}\n", .{a - b});
93}
94
95const clap = @import("clap");
96const std = @import("std");