summaryrefslogtreecommitdiff
path: root/src/comptime.zig
diff options
context:
space:
mode:
authorGravatar Jimmi Holst Christensen2018-11-14 14:06:20 +0100
committerGravatar Jimmi Holst Christensen2018-11-14 14:06:20 +0100
commitc564b168785e740c37f47da4942825b25cb8b4ec (patch)
tree880252c7a63bdc91f23ba5e13b593d4ca9ad8277 /src/comptime.zig
parentZig fmt (diff)
downloadzig-clap-c564b168785e740c37f47da4942825b25cb8b4ec.tar.gz
zig-clap-c564b168785e740c37f47da4942825b25cb8b4ec.tar.xz
zig-clap-c564b168785e740c37f47da4942825b25cb8b4ec.zip
Restructured and make StreamingClap simpler
* Also added a ComptimeClap
Diffstat (limited to 'src/comptime.zig')
-rw-r--r--src/comptime.zig142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/comptime.zig b/src/comptime.zig
new file mode 100644
index 0000000..b11dccc
--- /dev/null
+++ b/src/comptime.zig
@@ -0,0 +1,142 @@
1const clap = @import("index.zig");
2const std = @import("std");
3
4const debug = std.debug;
5const heap = std.heap;
6const mem = std.mem;
7
8pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) type {
9 var flags: usize = 0;
10 var options: usize = 0;
11 var converted_params: []const clap.Param(usize) = []clap.Param(usize){};
12 for (params) |param| {
13 const index = blk: {
14 if (param.names.long == null and param.names.short == null)
15 break :blk 0;
16 if (param.takes_value) {
17 const res = options;
18 options += 1;
19 break :blk res;
20 }
21
22 const res = flags;
23 flags += 1;
24 break :blk res;
25 };
26
27 converted_params = converted_params ++ []clap.Param(usize){
28 clap.Param(usize).init(index, param.takes_value, param.names),
29 };
30 }
31
32 return struct {
33 options: [options]?[]const u8,
34 flags: [flags]bool,
35 pos: []const []const u8,
36 allocator: *mem.Allocator,
37
38 pub fn parse(allocator: *mem.Allocator, comptime ArgError: type, iter: *clap.args.Iterator(ArgError)) !@This() {
39 var pos = std.ArrayList([]const u8).init(allocator);
40 var res = @This(){
41 .options = []?[]const u8{null} ** options,
42 .flags = []bool{false} ** flags,
43 .pos = undefined,
44 .allocator = allocator,
45 };
46
47 var stream = clap.StreamingClap(usize, ArgError).init(converted_params, iter);
48 while (try stream.next()) |arg| {
49 const param = arg.param;
50 if (param.names.long == null and param.names.short == null) {
51 try pos.append(arg.value.?);
52 } else if (param.takes_value) {
53 // We slice before access to avoid false positive access out of bound
54 // compile error.
55 res.options[0..][param.id] = arg.value.?;
56 } else {
57 res.flags[0..][param.id] = true;
58 }
59 }
60
61 res.pos = pos.toOwnedSlice();
62 return res;
63 }
64
65 pub fn deinit(parser: *@This()) void {
66 parser.allocator.free(parser.pos);
67 parser.* = undefined;
68 }
69
70 pub fn flag(parser: @This(), comptime name: []const u8) bool {
71 const param = comptime findParam(name);
72 if (param.takes_value)
73 @compileError(name ++ " is an option and not a flag.");
74
75 return parser.flags[param.id];
76 }
77
78 pub fn option(parser: @This(), comptime name: []const u8) ?[]const u8 {
79 const param = comptime findParam(name);
80 if (!param.takes_value)
81 @compileError(name ++ " is a flag and not an option.");
82
83 return parser.options[param.id];
84 }
85
86 pub fn positionals(parser: @This()) []const []const u8 {
87 return parser.pos;
88 }
89
90 fn findParam(comptime name: []const u8) clap.Param(usize) {
91 comptime {
92 for (converted_params) |param| {
93 if (param.names.short) |s| {
94 if (mem.eql(u8, name, "-" ++ []u8{s}))
95 return param;
96 }
97 if (param.names.long) |l| {
98 if (mem.eql(u8, name, "--" ++ l))
99 return param;
100 }
101 }
102
103 @compileError(name ++ " is not a parameter.");
104 }
105 }
106 };
107}
108
109test "clap.comptime.ComptimeClap" {
110 const Clap = ComptimeClap(void, comptime []clap.Param(void){
111 clap.Param(void).init({}, false, clap.Names{
112 .short = 'a',
113 .long = "aa",
114 }),
115 clap.Param(void).init({}, false, clap.Names{
116 .short = 'b',
117 .long = "bb",
118 }),
119 clap.Param(void).init({}, true, clap.Names{
120 .short = 'c',
121 .long = "cc",
122 }),
123 clap.Param(void).init({}, true, clap.Names.positional()),
124 });
125
126 var buf: [1024]u8 = undefined;
127 var fb_allocator = heap.FixedBufferAllocator.init(buf[0..]);
128 var arg_iter = clap.args.SliceIterator.init([][]const u8{
129 "-a", "-c", "0", "something",
130 });
131 var args = try Clap.parse(&fb_allocator.allocator, clap.args.SliceIterator.Error, &arg_iter.iter);
132 defer args.deinit();
133
134 debug.assert(args.flag("-a"));
135 debug.assert(args.flag("--aa"));
136 debug.assert(!args.flag("-b"));
137 debug.assert(!args.flag("--bb"));
138 debug.assert(mem.eql(u8, args.option("-c").?, "0"));
139 debug.assert(mem.eql(u8, args.option("--cc").?, "0"));
140 debug.assert(args.positionals().len == 1);
141 debug.assert(mem.eql(u8, args.positionals()[0], "something"));
142}