From 44ea38f25453fbf51de72505d7b3ddb0f3eec13c Mon Sep 17 00:00:00 2001 From: Jimmi HC Date: Wed, 12 Jun 2019 15:30:30 +0200 Subject: updated to newest version of zig --- src/args.zig | 13 +-- src/comptime.zig | 68 +++++++++----- src/index.zig | 276 ------------------------------------------------------ src/streaming.zig | 217 +++++++++++++++++++++++------------------- 4 files changed, 166 insertions(+), 408 deletions(-) delete mode 100644 src/index.zig (limited to 'src') diff --git a/src/args.zig b/src/args.zig index a34c14c..4234ada 100644 --- a/src/args.zig +++ b/src/args.zig @@ -21,14 +21,7 @@ pub const SliceIterator = struct { const Error = error{}; args: []const []const u8, - index: usize, - - pub fn init(args: []const []const u8) SliceIterator { - return SliceIterator{ - .args = args, - .index = 0, - }; - } + index: usize = 0, pub fn next(iter: *SliceIterator) Error!?[]const u8 { if (iter.args.len <= iter.index) @@ -40,8 +33,8 @@ pub const SliceIterator = struct { }; test "clap.args.SliceIterator" { - const args = [][]const u8{ "A", "BB", "CCC" }; - var iter = SliceIterator.init(args); + const args = [_][]const u8{ "A", "BB", "CCC" }; + var iter = SliceIterator{ .args = args }; for (args) |a| { const b = try iter.next(); diff --git a/src/comptime.zig b/src/comptime.zig index b9021de..b585598 100644 --- a/src/comptime.zig +++ b/src/comptime.zig @@ -1,4 +1,4 @@ -const clap = @import("index.zig"); +const clap = @import("../clap.zig"); const std = @import("std"); const testing = std.testing; @@ -8,7 +8,7 @@ const mem = std.mem; pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) type { var flags: usize = 0; var options: usize = 0; - var converted_params: []const clap.Param(usize) = []clap.Param(usize){}; + var converted_params: []const clap.Param(usize) = [_]clap.Param(usize){}; for (params) |param| { const index = blk: { if (param.names.long == null and param.names.short == null) @@ -24,8 +24,12 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) break :blk res; }; - const converted = clap.Param(usize).init(index, param.takes_value, param.names); - converted_params = converted_params ++ []clap.Param(usize){converted}; + const converted = clap.Param(usize){ + .id = index, + .names = param.names, + .takes_value = param.takes_value, + }; + converted_params = converted_params ++ [_]clap.Param(usize){converted}; } return struct { @@ -37,13 +41,16 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) pub fn parse(allocator: *mem.Allocator, comptime ArgIter: type, iter: *ArgIter) !@This() { var pos = std.ArrayList([]const u8).init(allocator); var res = @This(){ - .options = []?[]const u8{null} ** options, - .flags = []bool{false} ** flags, + .options = [_]?[]const u8{null} ** options, + .flags = [_]bool{false} ** flags, .pos = undefined, .allocator = allocator, }; - var stream = clap.StreamingClap(usize, ArgIter).init(converted_params, iter); + var stream = clap.StreamingClap(usize, ArgIter){ + .params = converted_params, + .iter = iter, + }; while (try stream.next()) |arg| { const param = arg.param; if (param.names.long == null and param.names.short == null) { @@ -90,7 +97,7 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) comptime { for (converted_params) |param| { if (param.names.short) |s| { - if (mem.eql(u8, name, "-" ++ []u8{s})) + if (mem.eql(u8, name, "-" ++ [_]u8{s})) return param; } if (param.names.long) |l| { @@ -106,27 +113,38 @@ pub fn ComptimeClap(comptime Id: type, comptime params: []const clap.Param(Id)) } test "clap.comptime.ComptimeClap" { - const Clap = ComptimeClap(void, comptime []clap.Param(void){ - clap.Param(void).flag({}, clap.Names{ - .short = 'a', - .long = "aa", - }), - clap.Param(void).flag({}, clap.Names{ - .short = 'b', - .long = "bb", - }), - clap.Param(void).option({}, clap.Names{ - .short = 'c', - .long = "cc", - }), - clap.Param(void).positional({}), + const Clap = ComptimeClap(void, [_]clap.Param(void){ + clap.Param(void){ + .names = clap.Names{ + .short = 'a', + .long = "aa", + } + }, + clap.Param(void){ + .names = clap.Names{ + .short = 'b', + .long = "bb", + } + }, + clap.Param(void){ + .names = clap.Names{ + .short = 'c', + .long = "cc", + }, + .takes_value = true, + }, + clap.Param(void){ + .takes_value = true, + }, }); var buf: [1024]u8 = undefined; var fb_allocator = heap.FixedBufferAllocator.init(buf[0..]); - var iter = clap.args.SliceIterator.init([][]const u8{ - "-a", "-c", "0", "something", - }); + var iter = clap.args.SliceIterator{ + .args = [_][]const u8{ + "-a", "-c", "0", "something", + }, + }; var args = try Clap.parse(&fb_allocator.allocator, clap.args.SliceIterator, &iter); defer args.deinit(); diff --git a/src/index.zig b/src/index.zig deleted file mode 100644 index 40ad849..0000000 --- a/src/index.zig +++ /dev/null @@ -1,276 +0,0 @@ -const std = @import("std"); - -const debug = std.debug; -const io = std.io; -const mem = std.mem; - -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 that is long and short, from the same string. - /// ::short is set to ::name[0], and ::long is set to ::name. - /// This function asserts that ::name.len != 0 - pub fn both(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, - }; - } - }; -} - -/// Will print a help message in the following format: -/// -s, --long=value_text help_text -/// -s, help_text -/// --long help_text -pub fn helpFull( - stream: var, - comptime Id: type, - params: []const Param(Id), - comptime Error: type, - context: var, - help_text: fn (@typeOf(context), Param(Id)) Error![]const u8, - value_text: fn (@typeOf(context), Param(Id)) Error![]const u8, -) !void { - const max_spacing = blk: { - var res: usize = 0; - for (params) |param| { - var counting_stream = io.CountingOutStream(io.NullOutStream.Error).init(io.null_out_stream); - try printParam(&counting_stream.stream, Id, param, Error, context, value_text); - if (res < counting_stream.bytes_written) - res = counting_stream.bytes_written; - } - - break :blk res; - }; - - for (params) |param| { - if (param.names.short == null and param.names.long == null) - continue; - - var counting_stream = io.CountingOutStream(@typeOf(stream.*).Error).init(stream); - try stream.print("\t"); - try printParam(&counting_stream.stream, Id, param, Error, context, value_text); - try stream.writeByteNTimes(' ', max_spacing - counting_stream.bytes_written); - try stream.print("\t{}\n", try help_text(context, param)); - } -} - -fn printParam( - stream: var, - comptime Id: type, - param: Param(Id), - comptime Error: type, - context: var, - value_text: fn (@typeOf(context), Param(Id)) Error![]const u8, -) @typeOf(stream.*).Error!void { - if (param.names.short) |s| { - try stream.print("-{c}", s); - } else { - try stream.print(" "); - } - if (param.names.long) |l| { - if (param.names.short) |_| { - try stream.print(", "); - } else { - try stream.print(" "); - } - - try stream.print("--{}", l); - } - if (param.takes_value) - try stream.print("={}", value_text(context, param)); -} - -/// A wrapper around helpFull for simple help_text and value_text functions that -/// cant return an error or take a context. -pub fn helpEx( - stream: var, - comptime Id: type, - params: []const Param(Id), - help_text: fn (Param(Id)) []const u8, - value_text: fn (Param(Id)) []const u8, -) !void { - const Context = struct { - help_text: fn (Param(Id)) []const u8, - value_text: fn (Param(Id)) []const u8, - - pub fn help(c: @This(), p: Param(Id)) error{}![]const u8 { - return c.help_text(p); - } - - pub fn value(c: @This(), p: Param(Id)) error{}![]const u8 { - return c.value_text(p); - } - }; - - return helpFull( - stream, - Id, - params, - error{}, - Context{ - .help_text = help_text, - .value_text = value_text, - }, - Context.help, - Context.value, - ); -} - -/// A wrapper around helpEx that takes a Param([]const u8) and uses the string id -/// as the help text for each paramter. -pub fn help(stream: var, params: []const Param([]const u8)) !void { - try helpEx(stream, []const u8, params, getHelpSimple, getValueSimple); -} - -fn getHelpSimple(param: Param([]const u8)) []const u8 { - return param.id; -} - -fn getValueSimple(param: Param([]const u8)) []const u8 { - return "VALUE"; -} - -test "clap.help" { - var buf: [1024]u8 = undefined; - var slice_stream = io.SliceOutStream.init(buf[0..]); - try help( - &slice_stream.stream, - []Param([]const u8){ - Param([]const u8).flag( - "Short flag.", - Names.short('a'), - ), - Param([]const u8).option( - "Short option.", - Names.short('b'), - ), - Param([]const u8).flag( - "Long flag.", - Names.long("aa"), - ), - Param([]const u8).option( - "Long option.", - Names.long("bb"), - ), - Param([]const u8).flag( - "Both flag.", - Names.both("cc"), - ), - Param([]const u8).option( - "Both option.", - Names.both("dd"), - ), - Param([]const u8).positional( - "Positional. This should not appear in the help message.", - ), - }, - ); - - const expected = "" ++ - "\t-a \tShort flag.\n" ++ - "\t-b=VALUE \tShort option.\n" ++ - "\t --aa \tLong flag.\n" ++ - "\t --bb=VALUE\tLong option.\n" ++ - "\t-c, --cc \tBoth flag.\n" ++ - "\t-d, --dd=VALUE\tBoth option.\n"; - - if (!mem.eql(u8, slice_stream.getWritten(), expected)) { - debug.warn("============ Expected ============\n"); - debug.warn("{}", expected); - debug.warn("============= Actual =============\n"); - debug.warn("{}", slice_stream.getWritten()); - return error.NoMatch; - } -} diff --git a/src/streaming.zig b/src/streaming.zig index 7bdc71f..9da120c 100644 --- a/src/streaming.zig +++ b/src/streaming.zig @@ -1,5 +1,5 @@ const builtin = @import("builtin"); -const clap = @import("index.zig"); +const clap = @import("../clap.zig"); const std = @import("std"); const args = clap.args; @@ -14,14 +14,7 @@ pub fn Arg(comptime Id: type) type { const Self = @This(); param: *const clap.Param(Id), - value: ?[]const u8, - - pub fn init(param: *const clap.Param(Id), value: ?[]const u8) Self { - return Self{ - .param = param, - .value = value, - }; - } + value: ?[]const u8 = null, }; } @@ -42,17 +35,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { params: []const clap.Param(Id), iter: *ArgIterator, - state: State, - - pub fn init(params: []const clap.Param(Id), iter: *ArgIterator) @This() { - var res = @This(){ - .params = params, - .iter = iter, - .state = State.Normal, - }; - - return res; - } + state: State = State.Normal, /// Get the next ::Arg that matches a ::Param. pub fn next(parser: *@This()) !?Arg(Id) { @@ -107,7 +90,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { if (maybe_value != null) return error.DoesntTakeValue; - return Arg(Id).init(param, null); + return Arg(Id){ .param = param }; } const value = blk: { @@ -117,7 +100,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { break :blk (try parser.iter.next()) orelse return error.MissingValue; }; - return Arg(Id).init(param, value); + return Arg(Id){ .param = param, .value = value }; } }, ArgInfo.Kind.Short => { @@ -133,7 +116,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { if (param.names.short) |_| continue; - return Arg(Id).init(param, arg); + return Arg(Id){ .param = param, .value = arg }; } }, } @@ -169,18 +152,17 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { } if (!param.takes_value) - return Arg(Id).init(param, null); + return Arg(Id){ .param = param }; if (arg.len <= next_index) { const value = (try parser.iter.next()) orelse return error.MissingValue; - return Arg(Id).init(param, value); + return Arg(Id){ .param = param, .value = value }; } - if (arg[next_index] == '=') { - return Arg(Id).init(param, arg[next_index + 1 ..]); - } + if (arg[next_index] == '=') + return Arg(Id){ .param = param, .value = arg[next_index + 1 ..] }; - return Arg(Id).init(param, arg[next_index..]); + return Arg(Id){ .param = param, .value = arg[next_index..] }; } return error.InvalidArgument; @@ -189,8 +171,11 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { } fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, results: []const Arg(u8)) void { - var iter = args.SliceIterator.init(args_strings); - var c = StreamingClap(u8, args.SliceIterator).init(params, &iter); + var iter = args.SliceIterator{ .args = args_strings }; + var c = StreamingClap(u8, args.SliceIterator){ + .params = params, + .iter = &iter + }; for (results) |res| { const arg = (c.next() catch unreachable) orelse unreachable; @@ -209,10 +194,20 @@ fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, r } test "clap.streaming.StreamingClap: short params" { - const params = []clap.Param(u8){ - clap.Param(u8).flag(0, clap.Names.short('a')), - clap.Param(u8).flag(1, clap.Names.short('b')), - clap.Param(u8).option(2, clap.Names.short('c')), + const params = [_]clap.Param(u8){ + clap.Param(u8){ + .id = 0, + .names = clap.Names{ .short = 'a' }, + }, + clap.Param(u8){ + .id = 1, + .names = clap.Names{ .short = 'b' }, + }, + clap.Param(u8){ + .id = 2, + .names = clap.Names{ .short = 'c' }, + .takes_value = true, + }, }; const a = ¶ms[0]; @@ -221,33 +216,43 @@ test "clap.streaming.StreamingClap: short params" { testNoErr( params, - [][]const u8{ + [_][]const u8{ "-a", "-b", "-ab", "-ba", "-c", "0", "-c=0", "-ac", "0", "-ac=0", }, - []const Arg(u8){ - Arg(u8).init(a, null), - Arg(u8).init(b, null), - Arg(u8).init(a, null), - Arg(u8).init(b, null), - Arg(u8).init(b, null), - Arg(u8).init(a, null), - Arg(u8).init(c, "0"), - Arg(u8).init(c, "0"), - Arg(u8).init(a, null), - Arg(u8).init(c, "0"), - Arg(u8).init(a, null), - Arg(u8).init(c, "0"), + [_]Arg(u8){ + Arg(u8){ .param = a }, + Arg(u8){ .param = b }, + Arg(u8){ .param = a }, + Arg(u8){ .param = b }, + Arg(u8){ .param = b }, + Arg(u8){ .param = a }, + Arg(u8){ .param = c, .value = "0" }, + Arg(u8){ .param = c, .value = "0" }, + Arg(u8){ .param = a }, + Arg(u8){ .param = c, .value = "0" }, + Arg(u8){ .param = a }, + Arg(u8){ .param = c, .value = "0" }, }, ); } test "clap.streaming.StreamingClap: long params" { - const params = []clap.Param(u8){ - clap.Param(u8).flag(0, clap.Names.long("aa")), - clap.Param(u8).flag(1, clap.Names.long("bb")), - clap.Param(u8).option(2, clap.Names.long("cc")), + const params = [_]clap.Param(u8){ + clap.Param(u8){ + .id = 0, + .names = clap.Names{ .long = "aa" }, + }, + clap.Param(u8){ + .id = 1, + .names = clap.Names{ .long = "bb" }, + }, + clap.Param(u8){ + .id = 2, + .names = clap.Names{ .long = "cc" }, + .takes_value = true, + }, }; const aa = ¶ms[0]; @@ -256,48 +261,66 @@ test "clap.streaming.StreamingClap: long params" { testNoErr( params, - [][]const u8{ + [_][]const u8{ "--aa", "--bb", "--cc", "0", "--cc=0", }, - []const Arg(u8){ - Arg(u8).init(aa, null), - Arg(u8).init(bb, null), - Arg(u8).init(cc, "0"), - Arg(u8).init(cc, "0"), + [_]Arg(u8){ + Arg(u8){ .param = aa }, + Arg(u8){ .param = bb }, + Arg(u8){ .param = cc, .value = "0" }, + Arg(u8){ .param = cc, .value = "0" }, }, ); } test "clap.streaming.StreamingClap: positional params" { - const params = []clap.Param(u8){clap.Param(u8).positional(0)}; + const params = [_]clap.Param(u8){ + clap.Param(u8){ + .id = 0, + .takes_value = true, + }, + }; testNoErr( params, - [][]const u8{ "aa", "bb" }, - []const Arg(u8){ - Arg(u8).init(¶ms[0], "aa"), - Arg(u8).init(¶ms[0], "bb"), + [_][]const u8{ "aa", "bb" }, + [_]Arg(u8){ + Arg(u8){ .param = ¶ms[0], .value = "aa" }, + Arg(u8){ .param = ¶ms[0], .value = "bb" }, }, ); } test "clap.streaming.StreamingClap: all params" { - const params = []clap.Param(u8){ - clap.Param(u8).flag(0, clap.Names{ - .short = 'a', - .long = "aa", - }), - clap.Param(u8).flag(1, clap.Names{ - .short = 'b', - .long = "bb", - }), - clap.Param(u8).option(2, clap.Names{ - .short = 'c', - .long = "cc", - }), - clap.Param(u8).positional(3), + const params = [_]clap.Param(u8){ + clap.Param(u8){ + .id = 0, + .names = clap.Names{ + .short = 'a', + .long = "aa", + }, + }, + clap.Param(u8){ + .id = 1, + .names = clap.Names{ + .short = 'b', + .long = "bb", + }, + }, + clap.Param(u8){ + .id = 2, + .names = clap.Names{ + .short = 'c', + .long = "cc", + }, + .takes_value = true, + }, + clap.Param(u8){ + .id = 3, + .takes_value = true, + }, }; const aa = ¶ms[0]; @@ -307,30 +330,30 @@ test "clap.streaming.StreamingClap: all params" { testNoErr( params, - [][]const u8{ + [_][]const u8{ "-a", "-b", "-ab", "-ba", "-c", "0", "-c=0", "-ac", "0", "-ac=0", "--aa", "--bb", "--cc", "0", "--cc=0", "something", }, - []const Arg(u8){ - Arg(u8).init(aa, null), - Arg(u8).init(bb, null), - Arg(u8).init(aa, null), - Arg(u8).init(bb, null), - Arg(u8).init(bb, null), - Arg(u8).init(aa, null), - Arg(u8).init(cc, "0"), - Arg(u8).init(cc, "0"), - Arg(u8).init(aa, null), - Arg(u8).init(cc, "0"), - Arg(u8).init(aa, null), - Arg(u8).init(cc, "0"), - Arg(u8).init(aa, null), - Arg(u8).init(bb, null), - Arg(u8).init(cc, "0"), - Arg(u8).init(cc, "0"), - Arg(u8).init(positional, "something"), + [_]Arg(u8){ + Arg(u8){ .param = aa }, + Arg(u8){ .param = bb }, + Arg(u8){ .param = aa }, + Arg(u8){ .param = bb }, + Arg(u8){ .param = bb }, + Arg(u8){ .param = aa }, + Arg(u8){ .param = cc, .value = "0" }, + Arg(u8){ .param = cc, .value = "0" }, + Arg(u8){ .param = aa }, + Arg(u8){ .param = cc, .value = "0" }, + Arg(u8){ .param = aa }, + Arg(u8){ .param = cc, .value = "0" }, + Arg(u8){ .param = aa }, + Arg(u8){ .param = bb }, + Arg(u8){ .param = cc, .value = "0" }, + Arg(u8){ .param = cc, .value = "0" }, + Arg(u8){ .param = positional, .value = "something" }, }, ); } -- cgit v1.2.3