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/streaming.zig | 348 ------------------------------------------------------ 1 file changed, 348 deletions(-) delete mode 100644 src/streaming.zig (limited to 'src/streaming.zig') 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