diff options
| author | 2019-02-10 14:47:12 +0100 | |
|---|---|---|
| committer | 2019-02-10 14:47:12 +0100 | |
| commit | 810ef3671d9c2cea5ce5524f51bf2d947a6cb5bf (patch) | |
| tree | 90b8a1fa5276d23360fb7afcfb47083eda7a53b7 | |
| parent | Updated to newest testing API (diff) | |
| parent | Removed duplicate in readme (diff) | |
| download | zig-clap-810ef3671d9c2cea5ce5524f51bf2d947a6cb5bf.tar.gz zig-clap-810ef3671d9c2cea5ce5524f51bf2d947a6cb5bf.tar.xz zig-clap-810ef3671d9c2cea5ce5524f51bf2d947a6cb5bf.zip | |
Merge branch 'master' of github.com:Hejsil/zig-clap
| -rw-r--r-- | README.md | 42 | ||||
| -rw-r--r-- | example/comptime-clap.zig | 7 | ||||
| -rw-r--r-- | example/streaming-clap.zig | 7 | ||||
| -rw-r--r-- | src/args.zig | 46 | ||||
| -rw-r--r-- | src/comptime.zig | 8 | ||||
| -rw-r--r-- | src/streaming.zig | 10 |
6 files changed, 50 insertions, 70 deletions
| @@ -15,23 +15,21 @@ A simple and easy to use command line argument parser library for Zig. | |||
| 15 | 15 | ||
| 16 | ### `StreamingClap` | 16 | ### `StreamingClap` |
| 17 | 17 | ||
| 18 | The `StreamingClap` is base of all the other parsers. It's a streaming parser that uses an | 18 | The `StreamingClap` is the base of all the other parsers. It's a streaming parser that uses an |
| 19 | `args.Iterator` to provide it with arguments lazily. | 19 | `args.Iterator` to provide it with arguments lazily. |
| 20 | 20 | ||
| 21 | ```rust | 21 | ```rust |
| 22 | const params = []clap.Param(u8){ | 22 | const params = []clap.Param(u8){ |
| 23 | clap.Param(void).flag('h', false, clap.Names.both("help")), | 23 | clap.Param(u8).flag('h', clap.Names.both("help")), |
| 24 | clap.Param(void).option('n', true, clap.Names.both("number")), | 24 | clap.Param(u8).option('n', clap.Names.both("number")), |
| 25 | clap.Param(void).positional('f'), | 25 | clap.Param(u8).positional('f'), |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | var os_iter = clap.args.OsIterator.init(allocator); | 28 | var iter = clap.args.OsIterator.init(allocator); |
| 29 | const iter = &os_iter.iter; | 29 | defer iter.deinit(); |
| 30 | defer os_iter.deinit(); | ||
| 31 | |||
| 32 | const exe = try iter.next(); | 30 | const exe = try iter.next(); |
| 33 | 31 | ||
| 34 | var parser = clap.StreamingClap(u8, clap.args.OsIterator.Error).init(params, iter); | 32 | var parser = clap.StreamingClap(u8, clap.args.OsIterator).init(params, &iter); |
| 35 | 33 | ||
| 36 | while (try parser.next()) |arg| { | 34 | while (try parser.next()) |arg| { |
| 37 | switch (arg.param.id) { | 35 | switch (arg.param.id) { |
| @@ -40,7 +38,7 @@ while (try parser.next()) |arg| { | |||
| 40 | 'f' => debug.warn("{}\n", arg.value.?), | 38 | 'f' => debug.warn("{}\n", arg.value.?), |
| 41 | else => unreachable, | 39 | else => unreachable, |
| 42 | } | 40 | } |
| 43 | } | 41 | } |
| 44 | ``` | 42 | ``` |
| 45 | 43 | ||
| 46 | ### `ComptimeClap` | 44 | ### `ComptimeClap` |
| @@ -50,18 +48,16 @@ them available through three functions (`flag`, `option`, `positionals`). | |||
| 50 | 48 | ||
| 51 | ```rust | 49 | ```rust |
| 52 | const params = comptime []clap.Param(void){ | 50 | const params = comptime []clap.Param(void){ |
| 53 | clap.Param(void).flag({}, false, clap.Names.both("help")), | 51 | clap.Param(void).flag({}, clap.Names.both("help")), |
| 54 | clap.Param(void).option({}, true, clap.Names.both("number")), | 52 | clap.Param(void).option({}, clap.Names.both("number")), |
| 55 | clap.Param(void).positional({}), | 53 | clap.Param(void).positional({}), |
| 56 | }; | 54 | }; |
| 57 | 55 | ||
| 58 | var os_iter = clap.args.OsIterator.init(allocator); | 56 | var iter = clap.args.OsIterator.init(allocator); |
| 59 | const iter = &os_iter.iter; | 57 | defer iter.deinit(); |
| 60 | defer os_iter.deinit(); | ||
| 61 | |||
| 62 | const exe = try iter.next(); | 58 | const exe = try iter.next(); |
| 63 | 59 | ||
| 64 | var args = try clap.ComptimeClap(void, params).parse(allocator, clap.args.OsIterator.Error, iter); | 60 | var args = try clap.ComptimeClap(void, params).parse(allocator, clap.args.OsIterator, &iter); |
| 65 | defer args.deinit(); | 61 | defer args.deinit(); |
| 66 | 62 | ||
| 67 | if (args.flag("--help")) | 63 | if (args.flag("--help")) |
| @@ -78,16 +74,14 @@ program can take: | |||
| 78 | 74 | ||
| 79 | ```rust | 75 | ```rust |
| 80 | const params = comptime []clap.Param(void){ | 76 | const params = comptime []clap.Param(void){ |
| 81 | clap.Param(void).init({}, false, clap.Names.both("help")), | 77 | clap.Param(void).flag({}, clap.Names.both("help")), |
| 82 | }; | 78 | }; |
| 83 | 79 | ||
| 84 | var os_iter = clap.args.OsIterator.init(allocator); | 80 | var iter = clap.args.OsIterator.init(allocator); |
| 85 | const iter = &os_iter.iter; | 81 | defer iter.deinit(); |
| 86 | defer os_iter.deinit(); | ||
| 87 | |||
| 88 | const exe = try iter.next(); | 82 | const exe = try iter.next(); |
| 89 | 83 | ||
| 90 | var args = try clap.ComptimeClap(params).parse(allocator, clap.args.OsIterator.Error, iter); | 84 | var args = try clap.ComptimeClap(void, params).parse(allocator, clap.args.OsIterator, &iter); |
| 91 | defer args.deinit(); | 85 | defer args.deinit(); |
| 92 | 86 | ||
| 93 | if (args.flag("--helps")) | 87 | if (args.flag("--helps")) |
| @@ -106,7 +100,7 @@ zig-clap/example/comptime-clap.zig:41:18: note: called from here | |||
| 106 | ^ | 100 | ^ |
| 107 | ``` | 101 | ``` |
| 108 | 102 | ||
| 109 | Ofc, this limits you to use only parameters that are comptime known. | 103 | Ofc, this limits you to parameters that are comptime known. |
| 110 | 104 | ||
| 111 | ### `help` | 105 | ### `help` |
| 112 | 106 | ||
diff --git a/example/comptime-clap.zig b/example/comptime-clap.zig index 00c2a97..8d2d8a8 100644 --- a/example/comptime-clap.zig +++ b/example/comptime-clap.zig | |||
| @@ -27,15 +27,14 @@ pub fn main() !void { | |||
| 27 | 27 | ||
| 28 | // We then initialize an argument iterator. We will use the OsIterator as it nicely | 28 | // We then initialize an argument iterator. We will use the OsIterator as it nicely |
| 29 | // wraps iterating over arguments the most efficient way on each os. | 29 | // wraps iterating over arguments the most efficient way on each os. |
| 30 | var os_iter = clap.args.OsIterator.init(allocator); | 30 | var iter = clap.args.OsIterator.init(allocator); |
| 31 | const iter = &os_iter.iter; | 31 | defer iter.deinit(); |
| 32 | defer os_iter.deinit(); | ||
| 33 | 32 | ||
| 34 | // Consume the exe arg. | 33 | // Consume the exe arg. |
| 35 | const exe = try iter.next(); | 34 | const exe = try iter.next(); |
| 36 | 35 | ||
| 37 | // Finally we can parse the arguments | 36 | // Finally we can parse the arguments |
| 38 | var args = try clap.ComptimeClap([]const u8, params).parse(allocator, clap.args.OsIterator.Error, iter); | 37 | var args = try clap.ComptimeClap([]const u8, params).parse(allocator, clap.args.OsIterator, &iter); |
| 39 | defer args.deinit(); | 38 | defer args.deinit(); |
| 40 | 39 | ||
| 41 | // clap.help is a function that can print a simple help message, given a | 40 | // clap.help is a function that can print a simple help message, given a |
diff --git a/example/streaming-clap.zig b/example/streaming-clap.zig index 77d05e2..aad3e71 100644 --- a/example/streaming-clap.zig +++ b/example/streaming-clap.zig | |||
| @@ -17,15 +17,14 @@ pub fn main() !void { | |||
| 17 | 17 | ||
| 18 | // We then initialize an argument iterator. We will use the OsIterator as it nicely | 18 | // We then initialize an argument iterator. We will use the OsIterator as it nicely |
| 19 | // wraps iterating over arguments the most efficient way on each os. | 19 | // wraps iterating over arguments the most efficient way on each os. |
| 20 | var os_iter = clap.args.OsIterator.init(allocator); | 20 | var iter = clap.args.OsIterator.init(allocator); |
| 21 | const iter = &os_iter.iter; | 21 | defer iter.deinit(); |
| 22 | defer os_iter.deinit(); | ||
| 23 | 22 | ||
| 24 | // Consume the exe arg. | 23 | // Consume the exe arg. |
| 25 | const exe = try iter.next(); | 24 | const exe = try iter.next(); |
| 26 | 25 | ||
| 27 | // Finally we initialize our streaming parser. | 26 | // Finally we initialize our streaming parser. |
| 28 | var parser = clap.StreamingClap(u8, clap.args.OsIterator.Error).init(params, iter); | 27 | var parser = clap.StreamingClap(u8, clap.args.OsIterator).init(params, &iter); |
| 29 | 28 | ||
| 30 | // Because we use a streaming parser, we have to consume each argument parsed individually. | 29 | // Because we use a streaming parser, we have to consume each argument parsed individually. |
| 31 | while (try parser.next()) |arg| { | 30 | while (try parser.next()) |arg| { |
diff --git a/src/args.zig b/src/args.zig index 304596c..8706ebc 100644 --- a/src/args.zig +++ b/src/args.zig | |||
| @@ -6,51 +6,42 @@ const heap = std.heap; | |||
| 6 | const mem = std.mem; | 6 | const mem = std.mem; |
| 7 | const os = std.os; | 7 | const os = std.os; |
| 8 | 8 | ||
| 9 | /// A interface for iterating over command line arguments | 9 | /// An example of what methods should be implemented on an arg iterator. |
| 10 | pub fn Iterator(comptime E: type) type { | 10 | pub const ExampleArgIterator = struct { |
| 11 | return struct { | 11 | const Error = error{}; |
| 12 | const Self = @This(); | ||
| 13 | const Error = E; | ||
| 14 | |||
| 15 | nextFn: fn (iter: *Self) Error!?[]const u8, | ||
| 16 | 12 | ||
| 17 | pub fn next(iter: *Self) Error!?[]const u8 { | 13 | pub fn next(iter: *ExampleArgIterator) Error!?[]const u8 { |
| 18 | return iter.nextFn(iter); | 14 | return "2"; |
| 19 | } | 15 | } |
| 20 | }; | 16 | }; |
| 21 | } | ||
| 22 | 17 | ||
| 23 | /// An ::ArgIterator, which iterates over a slice of arguments. | 18 | /// An argument iterator which iterates over a slice of arguments. |
| 24 | /// This implementation does not allocate. | 19 | /// This implementation does not allocate. |
| 25 | pub const SliceIterator = struct { | 20 | pub const SliceIterator = struct { |
| 26 | const Error = error{}; | 21 | const Error = error{}; |
| 27 | 22 | ||
| 28 | args: []const []const u8, | 23 | args: []const []const u8, |
| 29 | index: usize, | 24 | index: usize, |
| 30 | iter: Iterator(Error), | ||
| 31 | 25 | ||
| 32 | pub fn init(args: []const []const u8) SliceIterator { | 26 | pub fn init(args: []const []const u8) SliceIterator { |
| 33 | return SliceIterator{ | 27 | return SliceIterator{ |
| 34 | .args = args, | 28 | .args = args, |
| 35 | .index = 0, | 29 | .index = 0, |
| 36 | .iter = Iterator(Error){ .nextFn = nextFn }, | ||
| 37 | }; | 30 | }; |
| 38 | } | 31 | } |
| 39 | 32 | ||
| 40 | fn nextFn(iter: *Iterator(Error)) Error!?[]const u8 { | 33 | pub fn next(iter: *SliceIterator) Error!?[]const u8 { |
| 41 | const self = @fieldParentPtr(SliceIterator, "iter", iter); | 34 | if (iter.args.len <= iter.index) |
| 42 | if (self.args.len <= self.index) | ||
| 43 | return null; | 35 | return null; |
| 44 | 36 | ||
| 45 | defer self.index += 1; | 37 | defer iter.index += 1; |
| 46 | return self.args[self.index]; | 38 | return iter.args[iter.index]; |
| 47 | } | 39 | } |
| 48 | }; | 40 | }; |
| 49 | 41 | ||
| 50 | test "clap.args.SliceIterator" { | 42 | test "clap.args.SliceIterator" { |
| 51 | const args = [][]const u8{ "A", "BB", "CCC" }; | 43 | const args = [][]const u8{ "A", "BB", "CCC" }; |
| 52 | var slice_iter = SliceIterator.init(args); | 44 | var iter = SliceIterator.init(args); |
| 53 | const iter = &slice_iter.iter; | ||
| 54 | 45 | ||
| 55 | for (args) |a| { | 46 | for (args) |a| { |
| 56 | const b = try iter.next(); | 47 | const b = try iter.next(); |
| @@ -58,20 +49,18 @@ test "clap.args.SliceIterator" { | |||
| 58 | } | 49 | } |
| 59 | } | 50 | } |
| 60 | 51 | ||
| 61 | /// An ::ArgIterator, which wraps the ArgIterator in ::std. | 52 | /// An argument iterator which wraps the ArgIterator in ::std. |
| 62 | /// On windows, this iterator allocates. | 53 | /// On windows, this iterator allocates. |
| 63 | pub const OsIterator = struct { | 54 | pub const OsIterator = struct { |
| 64 | const Error = os.ArgIterator.NextError; | 55 | const Error = os.ArgIterator.NextError; |
| 65 | 56 | ||
| 66 | arena: heap.ArenaAllocator, | 57 | arena: heap.ArenaAllocator, |
| 67 | args: os.ArgIterator, | 58 | args: os.ArgIterator, |
| 68 | iter: Iterator(Error), | ||
| 69 | 59 | ||
| 70 | pub fn init(allocator: *mem.Allocator) OsIterator { | 60 | pub fn init(allocator: *mem.Allocator) OsIterator { |
| 71 | return OsIterator{ | 61 | return OsIterator{ |
| 72 | .arena = heap.ArenaAllocator.init(allocator), | 62 | .arena = heap.ArenaAllocator.init(allocator), |
| 73 | .args = os.args(), | 63 | .args = os.args(), |
| 74 | .iter = Iterator(Error){ .nextFn = nextFn }, | ||
| 75 | }; | 64 | }; |
| 76 | } | 65 | } |
| 77 | 66 | ||
| @@ -79,12 +68,11 @@ pub const OsIterator = struct { | |||
| 79 | iter.arena.deinit(); | 68 | iter.arena.deinit(); |
| 80 | } | 69 | } |
| 81 | 70 | ||
| 82 | fn nextFn(iter: *Iterator(Error)) Error!?[]const u8 { | 71 | pub fn next(iter: *OsIterator) Error!?[]const u8 { |
| 83 | const self = @fieldParentPtr(OsIterator, "iter", iter); | ||
| 84 | if (builtin.os == builtin.Os.windows) { | 72 | if (builtin.os == builtin.Os.windows) { |
| 85 | return try self.args.next(&self.arena.allocator) orelse return null; | 73 | return try iter.args.next(&iter.arena.allocator) orelse return null; |
| 86 | } else { | 74 | } else { |
| 87 | return self.args.nextPosix(); | 75 | return iter.args.nextPosix(); |
| 88 | } | 76 | } |
| 89 | } | 77 | } |
| 90 | }; | 78 | }; |
diff --git a/src/comptime.zig b/src/comptime.zig index 5339da3..b9021de 100644 --- a/src/comptime.zig +++ b/src/comptime.zig | |||
| @@ -34,7 +34,7 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) | |||
| 34 | pos: []const []const u8, | 34 | pos: []const []const u8, |
| 35 | allocator: *mem.Allocator, | 35 | allocator: *mem.Allocator, |
| 36 | 36 | ||
| 37 | pub fn parse(allocator: *mem.Allocator, comptime ArgError: type, iter: *clap.args.Iterator(ArgError)) !@This() { | 37 | pub fn parse(allocator: *mem.Allocator, comptime ArgIter: type, iter: *ArgIter) !@This() { |
| 38 | var pos = std.ArrayList([]const u8).init(allocator); | 38 | var pos = std.ArrayList([]const u8).init(allocator); |
| 39 | var res = @This(){ | 39 | var res = @This(){ |
| 40 | .options = []?[]const u8{null} ** options, | 40 | .options = []?[]const u8{null} ** options, |
| @@ -43,7 +43,7 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) | |||
| 43 | .allocator = allocator, | 43 | .allocator = allocator, |
| 44 | }; | 44 | }; |
| 45 | 45 | ||
| 46 | var stream = clap.StreamingClap(usize, ArgError).init(converted_params, iter); | 46 | var stream = clap.StreamingClap(usize, ArgIter).init(converted_params, iter); |
| 47 | while (try stream.next()) |arg| { | 47 | while (try stream.next()) |arg| { |
| 48 | const param = arg.param; | 48 | const param = arg.param; |
| 49 | if (param.names.long == null and param.names.short == null) { | 49 | if (param.names.long == null and param.names.short == null) { |
| @@ -124,10 +124,10 @@ test "clap.comptime.ComptimeClap" { | |||
| 124 | 124 | ||
| 125 | var buf: [1024]u8 = undefined; | 125 | var buf: [1024]u8 = undefined; |
| 126 | var fb_allocator = heap.FixedBufferAllocator.init(buf[0..]); | 126 | var fb_allocator = heap.FixedBufferAllocator.init(buf[0..]); |
| 127 | var arg_iter = clap.args.SliceIterator.init([][]const u8{ | 127 | var iter = clap.args.SliceIterator.init([][]const u8{ |
| 128 | "-a", "-c", "0", "something", | 128 | "-a", "-c", "0", "something", |
| 129 | }); | 129 | }); |
| 130 | var args = try Clap.parse(&fb_allocator.allocator, clap.args.SliceIterator.Error, &arg_iter.iter); | 130 | var args = try Clap.parse(&fb_allocator.allocator, clap.args.SliceIterator, &iter); |
| 131 | defer args.deinit(); | 131 | defer args.deinit(); |
| 132 | 132 | ||
| 133 | testing.expect(args.flag("-a")); | 133 | testing.expect(args.flag("-a")); |
diff --git a/src/streaming.zig b/src/streaming.zig index cc5da79..7bdc71f 100644 --- a/src/streaming.zig +++ b/src/streaming.zig | |||
| @@ -28,7 +28,7 @@ pub fn Arg(comptime Id: type) type { | |||
| 28 | /// A command line argument parser which, given an ::ArgIterator, will parse arguments according | 28 | /// A command line argument parser which, given an ::ArgIterator, will parse arguments according |
| 29 | /// to the ::params. ::StreamingClap parses in an iterating manner, so you have to use a loop together with | 29 | /// to the ::params. ::StreamingClap parses in an iterating manner, so you have to use a loop together with |
| 30 | /// ::StreamingClap.next to parse all the arguments of your program. | 30 | /// ::StreamingClap.next to parse all the arguments of your program. |
| 31 | pub fn StreamingClap(comptime Id: type, comptime ArgError: type) type { | 31 | pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { |
| 32 | return struct { | 32 | return struct { |
| 33 | const State = union(enum) { | 33 | const State = union(enum) { |
| 34 | Normal, | 34 | Normal, |
| @@ -41,10 +41,10 @@ pub fn StreamingClap(comptime Id: type, comptime ArgError: type) type { | |||
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | params: []const clap.Param(Id), | 43 | params: []const clap.Param(Id), |
| 44 | iter: *args.Iterator(ArgError), | 44 | iter: *ArgIterator, |
| 45 | state: State, | 45 | state: State, |
| 46 | 46 | ||
| 47 | pub fn init(params: []const clap.Param(Id), iter: *args.Iterator(ArgError)) @This() { | 47 | pub fn init(params: []const clap.Param(Id), iter: *ArgIterator) @This() { |
| 48 | var res = @This(){ | 48 | var res = @This(){ |
| 49 | .params = params, | 49 | .params = params, |
| 50 | .iter = iter, | 50 | .iter = iter, |
| @@ -189,8 +189,8 @@ pub fn StreamingClap(comptime Id: type, comptime ArgError: type) type { | |||
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, results: []const Arg(u8)) void { | 191 | fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, results: []const Arg(u8)) void { |
| 192 | var arg_iter = args.SliceIterator.init(args_strings); | 192 | var iter = args.SliceIterator.init(args_strings); |
| 193 | var c = StreamingClap(u8, args.SliceIterator.Error).init(params, &arg_iter.iter); | 193 | var c = StreamingClap(u8, args.SliceIterator).init(params, &iter); |
| 194 | 194 | ||
| 195 | for (results) |res| { | 195 | for (results) |res| { |
| 196 | const arg = (c.next() catch unreachable) orelse unreachable; | 196 | const arg = (c.next() catch unreachable) orelse unreachable; |