summaryrefslogtreecommitdiff
path: root/src/index.zig
blob: 225eb9ca0aebbda5c4fe578b1248c8487efd4308 (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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
const std = @import("std");

const debug = std.debug;

pub const @"comptime" = @import("comptime.zig");
pub const args = @import("args.zig");
pub const streaming = @import("streaming.zig");

test "clap" {
    _ = @"comptime";
    _ = args;
    _ = streaming;
}

pub const ComptimeClap = @"comptime".ComptimeClap;
pub const StreamingClap = streaming.StreamingClap;

/// The names a ::Param can have.
pub const Names = struct {
    /// '-' prefix
    short: ?u8,

    /// '--' prefix
    long: ?[]const u8,

    /// Initializes a short name
    pub fn short(s: u8) Names {
        return Names{
            .short = s,
            .long = null,
        };
    }

    /// Initializes a long name
    pub fn long(l: []const u8) Names {
        return Names{
            .short = null,
            .long = l,
        };
    }

    /// Initializes a name with a prefix.
    /// ::short is set to ::name[0], and ::long is set to ::name.
    /// This function asserts that ::name.len != 0
    pub fn prefix(name: []const u8) Names {
        debug.assert(name.len != 0);

        return Names{
            .short = name[0],
            .long = name,
        };
    }
};

/// Represents a parameter for the command line.
/// Parameters come in three kinds:
///   * Short ("-a"): Should be used for the most commonly used parameters in your program.
///     * They can take a value three different ways.
///       * "-a value"
///       * "-a=value"
///       * "-avalue"
///     * They chain if they don't take values: "-abc".
///       * The last given parameter can take a value in the same way that a single parameter can:
///         * "-abc value"
///         * "-abc=value"
///         * "-abcvalue"
///   * Long ("--long-param"): Should be used for less common parameters, or when no single character
///                            can describe the paramter.
///     * They can take a value two different ways.
///       * "--long-param value"
///       * "--long-param=value"
///   * Positional: Should be used as the primary parameter of the program, like a filename or
///                 an expression to parse.
///     * Positional parameters have both names.long and names.short == null.
///     * Positional parameters must take a value.
pub fn Param(comptime Id: type) type {
    return struct {
        id: Id,
        takes_value: bool,
        names: Names,

        pub fn flag(id: Id, names: Names) @This() {
            return init(id, false, names);
        }

        pub fn option(id: Id, names: Names) @This() {
            return init(id, true, names);
        }

        pub fn positional(id: Id) @This() {
            return init(id, true, Names{ .short = null, .long = null });
        }

        pub fn init(id: Id, takes_value: bool, names: Names) @This() {
            // Assert, that if the param have no name, then it has to take
            // a value.
            debug.assert(names.long != null or
                names.short != null or
                takes_value);

            return @This(){
                .id = id,
                .takes_value = takes_value,
                .names = names,
            };
        }
    };
}