summaryrefslogtreecommitdiff
path: root/src/subcommand.zig
blob: 8fde170db5ff360894fb9dd448681e85494b40c9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
const clap = @import("clap");
const std = @import("std");
const zup = @import("root");

const ArgIterator = std.process.ArgIterator;
const Config = zup.Config;

const parsers = .{
    .COMMAND = clap.parsers.string,
    .NAME = clap.parsers.string,
};

pub fn SubCommand(comptime template: type) type {
    return struct {
        pub const base = template;

        const params = clap.parseParamsComptime(
            \\-H, --help  Display this help and exit
            \\-V, --version  Display the version of Zup and exit
            \\
        ++ template.params);

        pub fn help(name: []const u8) !void {
            const writer = std.io.getStdErr().writer();
            try writer.print("USAGE: zup {s} ", .{name});
            try clap.usage(writer, clap.Help, &params);
            try writer.writeAll("\n\n");
            try clap.help(writer, clap.Help, &params, .{
                .description_on_new_line = false,
                .description_indent = 0,
                .indent = 2,
                .max_width = 120,
                .spacing_between_parameters = 0,
            });
            try writer.writeAll("\n" ++ template.description ++ "\n");
        }

        pub fn main(name: []const u8, config: Config, args: *ArgIterator) !void {
            const allocator = config.allocator;

            var diag = clap.Diagnostic{};
            var res = clap.parseEx(clap.Help, &params, parsers, args, .{
                .allocator = allocator,
                .diagnostic = &diag,
            }) catch |err| {
                diag.report(std.io.getStdErr().writer(), err) catch {};
                try help(name);
                return err;
            };
            defer res.deinit();

            if (res.args.help != 0) {
                return help(name);
            }

            if (res.args.version != 0) {
                return zup.printVersion();
            }

            if (res.positionals.len < template.min_args or res.positionals.len > template.max_args) {
                try help(name);
                return error.ArgError;
            }

            return template.main(@TypeOf(res), config, res);
        }
    };
}