From f3eb797336c1bbdae391657ef6ac54e4015b5fde Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Sun, 6 Oct 2019 17:20:56 +0200 Subject: fmt, mv src/ clap/ and run fmt on build --- src/args.zig | 71 ----------- src/comptime.zig | 143 ---------------------- src/streaming.zig | 348 ------------------------------------------------------ 3 files changed, 562 deletions(-) delete mode 100644 src/args.zig delete mode 100644 src/comptime.zig delete mode 100644 src/streaming.zig (limited to 'src') diff --git a/src/args.zig b/src/args.zig deleted file mode 100644 index 4234ada..0000000 --- a/src/args.zig +++ /dev/null @@ -1,71 +0,0 @@ -const builtin = @import("builtin"); -const std = @import("std"); - -const debug = std.debug; -const heap = std.heap; -const mem = std.mem; -const process = std.process; - -/// An example of what methods should be implemented on an arg iterator. -pub const ExampleArgIterator = struct { - const Error = error{}; - - pub fn next(iter: *ExampleArgIterator) Error!?[]const u8 { - return "2"; - } -}; - -/// An argument iterator which iterates over a slice of arguments. -/// This implementation does not allocate. -pub const SliceIterator = struct { - const Error = error{}; - - args: []const []const u8, - index: usize = 0, - - pub fn next(iter: *SliceIterator) Error!?[]const u8 { - if (iter.args.len <= iter.index) - return null; - - defer iter.index += 1; - return iter.args[iter.index]; - } -}; - -test "clap.args.SliceIterator" { - const args = [_][]const u8{ "A", "BB", "CCC" }; - var iter = SliceIterator{ .args = args }; - - for (args) |a| { - const b = try iter.next(); - debug.assert(mem.eql(u8, a, b.?)); - } -} - -/// An argument iterator which wraps the ArgIterator in ::std. -/// On windows, this iterator allocates. -pub const OsIterator = struct { - const Error = process.ArgIterator.NextError; - - arena: heap.ArenaAllocator, - args: process.ArgIterator, - - pub fn init(allocator: *mem.Allocator) OsIterator { - return OsIterator{ - .arena = heap.ArenaAllocator.init(allocator), - .args = process.args(), - }; - } - - pub fn deinit(iter: *OsIterator) void { - iter.arena.deinit(); - } - - pub fn next(iter: *OsIterator) Error!?[]const u8 { - if (builtin.os == builtin.Os.windows) { - return try iter.args.next(&iter.arena.allocator) orelse return null; - } else { - return iter.args.nextPosix(); - } - } -}; diff --git a/src/comptime.zig b/src/comptime.zig deleted file mode 100644 index f5c2762..0000000 --- a/src/comptime.zig +++ /dev/null @@ -1,143 +0,0 @@ -const clap = @import("../clap.zig"); -const std = @import("std"); - -const testing = std.testing; -const heap = std.heap; -const mem = std.mem; -const debug = std.debug; - -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){}; - for (params) |param| { - var index: usize = 0; - if (param.names.long != null or param.names.short != null) { - const ptr = if (param.takes_value) &options else &flags; - index = ptr.*; - ptr.* += 1; - } - - 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 { - options: [options]?[]const u8, - flags: [flags]bool, - pos: []const []const u8, - allocator: *mem.Allocator, - - 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, - .pos = undefined, - .allocator = allocator, - }; - - 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) { - try pos.append(arg.value.?); - } else if (param.takes_value) { - // If we don't have any optional parameters, then this code should - // never be reached. - debug.assert(res.options.len != 0); - - // Hack: Utilize Zigs lazy analyzis to avoid a compiler error - if (res.options.len != 0) - res.options[param.id] = arg.value.?; - } else { - debug.assert(res.flags.len != 0); - if (res.flags.len != 0) - res.flags[param.id] = true; - } - } - - res.pos = pos.toOwnedSlice(); - return res; - } - - pub fn deinit(parser: *@This()) void { - parser.allocator.free(parser.pos); - parser.* = undefined; - } - - pub fn flag(parser: @This(), comptime name: []const u8) bool { - const param = comptime findParam(name); - if (param.takes_value) - @compileError(name ++ " is an option and not a flag."); - - return parser.flags[param.id]; - } - - pub fn option(parser: @This(), comptime name: []const u8) ?[]const u8 { - const param = comptime findParam(name); - if (!param.takes_value) - @compileError(name ++ " is a flag and not an option."); - - return parser.options[param.id]; - } - - pub fn positionals(parser: @This()) []const []const u8 { - return parser.pos; - } - - fn findParam(comptime name: []const u8) clap.Param(usize) { - comptime { - for (converted_params) |param| { - if (param.names.short) |s| { - if (mem.eql(u8, name, "-" ++ [_]u8{s})) - return param; - } - if (param.names.long) |l| { - if (mem.eql(u8, name, "--" ++ l)) - return param; - } - } - - @compileError(name ++ " is not a parameter."); - } - } - }; -} - -test "clap.comptime.ComptimeClap" { - const Clap = ComptimeClap(clap.Help, comptime [_]clap.Param(clap.Help){ - clap.parseParam("-a, --aa ") catch unreachable, - clap.parseParam("-b, --bb ") catch unreachable, - clap.parseParam("-c, --cc ") catch unreachable, - clap.Param(clap.Help){ - .takes_value = true, - }, - }); - - var buf: [1024]u8 = undefined; - var fb_allocator = heap.FixedBufferAllocator.init(buf[0..]); - 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(); - - testing.expect(args.flag("-a")); - testing.expect(args.flag("--aa")); - testing.expect(!args.flag("-b")); - testing.expect(!args.flag("--bb")); - testing.expectEqualSlices(u8, "0", args.option("-c").?); - testing.expectEqualSlices(u8, "0", args.option("--cc").?); - testing.expectEqual(usize(1), args.positionals().len); - testing.expectEqualSlices(u8, "something", args.positionals()[0]); -} diff --git a/src/streaming.zig b/src/streaming.zig deleted file mode 100644 index b5c3498..0000000 --- a/src/streaming.zig +++ /dev/null @@ -1,348 +0,0 @@ -const builtin = @import("builtin"); -const clap = @import("../clap.zig"); -const std = @import("std"); - -const args = clap.args; -const testing = std.testing; -const heap = std.heap; -const mem = std.mem; -const os = std.os; - -/// The result returned from ::StreamingClap.next -pub fn Arg(comptime Id: type) type { - return struct { - const Self = @This(); - - param: *const clap.Param(Id), - value: ?[]const u8 = null, - }; -} - -/// A command line argument parser which, given an ::ArgIterator, will parse arguments according -/// to the ::params. ::StreamingClap parses in an iterating manner, so you have to use a loop together with -/// ::StreamingClap.next to parse all the arguments of your program. -pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type { - return struct { - const State = union(enum) { - Normal, - Chaining: Chaining, - - const Chaining = struct { - arg: []const u8, - index: usize, - }; - }; - - params: []const clap.Param(Id), - iter: *ArgIterator, - state: State = State.Normal, - - /// Get the next ::Arg that matches a ::Param. - pub fn next(parser: *@This()) !?Arg(Id) { - const ArgInfo = struct { - const Kind = enum { - Long, - Short, - Positional, - }; - - arg: []const u8, - kind: Kind, - }; - - switch (parser.state) { - .Normal => { - const full_arg = (try parser.iter.next()) orelse return null; - const arg_info = if (mem.eql(u8, full_arg, "--") or mem.eql(u8, full_arg, "-")) - ArgInfo{ .arg = full_arg, .kind = .Positional } - else if (mem.startsWith(u8, full_arg, "--")) - ArgInfo{ .arg = full_arg[2..], .kind = .Long } - else if (mem.startsWith(u8, full_arg, "-")) - ArgInfo{ .arg = full_arg[1..], .kind = .Short } - else - ArgInfo{ .arg = full_arg, .kind = .Positional }; - - const arg = arg_info.arg; - const kind = arg_info.kind; - const eql_index = mem.indexOfScalar(u8, arg, '='); - - switch (kind) { - ArgInfo.Kind.Long => { - for (parser.params) |*param| { - const match = param.names.long orelse continue; - const name = if (eql_index) |i| arg[0..i] else arg; - const maybe_value = if (eql_index) |i| arg[i + 1 ..] else null; - - if (!mem.eql(u8, name, match)) - continue; - if (!param.takes_value) { - if (maybe_value != null) - return error.DoesntTakeValue; - - return Arg(Id){ .param = param }; - } - - const value = blk: { - if (maybe_value) |v| - break :blk v; - - break :blk (try parser.iter.next()) orelse return error.MissingValue; - }; - - return Arg(Id){ .param = param, .value = value }; - } - }, - ArgInfo.Kind.Short => { - return try parser.chainging(State.Chaining{ - .arg = full_arg, - .index = (full_arg.len - arg.len), - }); - }, - ArgInfo.Kind.Positional => { - for (parser.params) |*param| { - if (param.names.long) |_| - continue; - if (param.names.short) |_| - continue; - - return Arg(Id){ .param = param, .value = arg }; - } - }, - } - - return error.InvalidArgument; - }, - .Chaining => |state| return try parser.chainging(state), - } - } - - fn chainging(parser: *@This(), state: State.Chaining) !?Arg(Id) { - const arg = state.arg; - const index = state.index; - const next_index = index + 1; - - for (parser.params) |*param| { - const short = param.names.short orelse continue; - if (short != arg[index]) - continue; - - // Before we return, we have to set the new state of the clap - defer { - if (arg.len <= next_index or param.takes_value) { - parser.state = State.Normal; - } else { - parser.state = State{ - .Chaining = State.Chaining{ - .arg = arg, - .index = next_index, - }, - }; - } - } - - if (!param.takes_value) - return Arg(Id){ .param = param }; - - if (arg.len <= next_index) { - const value = (try parser.iter.next()) orelse return error.MissingValue; - return Arg(Id){ .param = param, .value = value }; - } - - if (arg[next_index] == '=') - return Arg(Id){ .param = param, .value = arg[next_index + 1 ..] }; - - return Arg(Id){ .param = param, .value = arg[next_index..] }; - } - - return error.InvalidArgument; - } - }; -} - -fn testNoErr(params: []const clap.Param(u8), args_strings: []const []const u8, results: []const Arg(u8)) void { - 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; - testing.expectEqual(res.param, arg.param); - const expected_value = res.value orelse { - testing.expectEqual(@typeOf(arg.value)(null), arg.value); - continue; - }; - const actual_value = arg.value orelse unreachable; - testing.expectEqualSlices(u8, expected_value, actual_value); - } - - if (c.next() catch unreachable) |_| - unreachable; -} - -test "clap.streaming.StreamingClap: short params" { - 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]; - const b = ¶ms[1]; - const c = ¶ms[2]; - - testNoErr( - params, - [_][]const u8{ - "-a", "-b", "-ab", "-ba", - "-c", "0", "-c=0", "-ac", - "0", "-ac=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){ - .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]; - const bb = ¶ms[1]; - const cc = ¶ms[2]; - - testNoErr( - params, - [_][]const u8{ - "--aa", "--bb", - "--cc", "0", - "--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){ - .id = 0, - .takes_value = true, - }}; - - testNoErr( - params, - [_][]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){ - .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]; - const bb = ¶ms[1]; - const cc = ¶ms[2]; - const positional = ¶ms[3]; - - testNoErr( - params, - [_][]const u8{ - "-a", "-b", "-ab", "-ba", - "-c", "0", "-c=0", "-ac", - "0", "-ac=0", "--aa", "--bb", - "--cc", "0", "--cc=0", "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" }, - Arg(u8){ .param = positional, .value = "--" }, - Arg(u8){ .param = positional, .value = "-" }, - }, - ); -} -- cgit v1.2.3