summaryrefslogtreecommitdiff
path: root/README.md
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 /README.md
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 'README.md')
-rw-r--r--README.md107
1 files changed, 106 insertions, 1 deletions
diff --git a/README.md b/README.md
index 3281d91..d36715c 100644
--- a/README.md
+++ b/README.md
@@ -103,7 +103,7 @@ The result will contain an `args` field and a `positionals` field. `args` will h
103for each none positional parameter of your program. The name of the field will be the longest 103for each none positional parameter of your program. The name of the field will be the longest
104name of the parameter. `positionals` be a tuple with one field for each positional parameter. 104name of the parameter. `positionals` be a tuple with one field for each positional parameter.
105 105
106The fields in `args` and `psotionals` are typed. The type is based on the name of the value the 106The fields in `args` and `postionals` are typed. The type is based on the name of the value the
107parameter takes. Since `--number` takes a `usize` the field `res.args.number` has the type `usize`. 107parameter takes. Since `--number` takes a `usize` the field `res.args.number` has the type `usize`.
108 108
109Note that this is only the case because `clap.parsers.default` has a field called `usize` which 109Note 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
171There is an option for `clap.parse` and `clap.parseEx` called `terminating_positional`. It allows
172for users of `clap` to implement subcommands in their cli application:
173
174```zig
175// These are our subcommands
176const SubCommands = enum {
177 help,
178 math,
179};
180
181const main_parsers = .{
182 .command = clap.parsers.enumeration(SubCommands),
183};
184
185// The parameters for main. Parameters for the subcommands are specified further down
186const 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`
194const MainArgs = clap.ResultEx(clap.Help, &main_params, main_parsers);
195
196pub 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
233fn 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, &params, 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
269const clap = @import("clap");
270const std = @import("std");
271
272```
273
169### `streaming.Clap` 274### `streaming.Clap`
170 275
171The `streaming.Clap` is the base of all the other parsers. It's a streaming parser that uses an 276The `streaming.Clap` is the base of all the other parsers. It's a streaming parser that uses an