From 8e2d4d7d1ce3ae54fb0220edcdd31135ac4ddb23 Mon Sep 17 00:00:00 2001 From: jiacai2050 Date: Sun, 11 Aug 2024 20:33:07 +0800 Subject: [PATCH] fix ci --- docs/content/docs/modules/simargs.org | 28 +++++++++------- examples/simargs-demo.zig | 4 +++ src/bin/loc.zig | 4 +-- src/bin/repeat.zig | 4 +-- src/bin/tree.zig | 4 +-- src/mod/simargs.zig | 47 +++++++++++++++++---------- 6 files changed, 57 insertions(+), 34 deletions(-) diff --git a/docs/content/docs/modules/simargs.org b/docs/content/docs/modules/simargs.org index 3a45612..3e51776 100644 --- a/docs/content/docs/modules/simargs.org +++ b/docs/content/docs/modules/simargs.org @@ -1,6 +1,6 @@ #+TITLE: Simargs #+DATE: 2023-10-21T12:04:40+0800 -#+LASTMOD: 2023-10-22T19:30:17+0800 +#+LASTMOD: 2024-08-11T20:30:59+0800 #+WEIGTH: 1 * Simargs @@ -12,26 +12,28 @@ A simple, opinionated, struct-based argument parser in Zig, taking full advantag - =Enum= - Optional fields and fields with default value mean they are optional arguments - Use =comptime= as possible as I can -- Provide =print_help()= out of the box +- Provide =printHelp()= out of the box +- Support sub commands * Usage See [[https://github.com/jiacai2050/zigcli/blob/main/examples/simargs-demo.zig][simargs-demo.zig]]. #+begin_src bash :results verbatim :exports both # Run demo -zig build && ./zig-out/bin/simargs-demo -o /tmp/a.out --user-agent Firefox hello world 2>&1 +zig build run-simargs-demo -- -o /tmp/a.out --user-agent Firefox sub1 --a 123 hello world 2>&1 #+end_src #+RESULTS: #+begin_example ------------------------------Program------------------------------ -./zig-out/bin/simargs-demo +/Users/jiacai/gh/zigcli/.zig-cache/o/bd8a4fb104779110e787d579f1d9c6f0/simargs-demo ------------------------------Arguments------------------------------ verbose: null -user-agent: demo.main__struct_1677.main__struct_1677__enum_1777.Firefox +user-agent: simargs-demo.main__struct_1700.main__struct_1700__enum_1707.Firefox timeout: 30 output: /tmp/a.out help: false +__commands__: simargs-demo.main__struct_1700.main__struct_1700__union_1708{ .sub1 = simargs-demo.main__struct_1700.main__struct_1700__union_1708.main__struct_1700__union_1708__struct_1710{ .a = 123, .help = false } } ------------------------------Positionals------------------------------ 1: hello @@ -39,14 +41,18 @@ user-agent: demo.main__struct_1677.main__struct_1677__enum_1777.Firefox ------------------------------print_help------------------------------ USAGE: - ./zig-out/bin/demo [OPTIONS] [--] [file] + /Users/jiacai/gh/zigcli/.zig-cache/o/bd8a4fb104779110e787d579f1d9c6f0/simargs-demo [OPTIONS] [COMMANDS] + + COMMANDS: + sub1 Subcommand 1 + sub2 Subcommand 2 OPTIONS: - -v, --verbose Make the operation more talkative - -A, --user-agent STRING (valid: Chrome|Firefox|Safari)(default: Firefox) - --timeout INTEGER Max time this request can cost(default: 30) - -o, --output STRING Write to file instead of stdout(required) - -h, --help + -v, --verbose Make the operation more talkative + -A, --user-agent STRING (valid: Chrome|Firefox|Safari)(default: Firefox) + --timeout INTEGER Max time this request can cost(default: 30) + -o, --output STRING Write to file instead of stdout(required) + -h, --help #+end_example * Acknowledgment diff --git a/examples/simargs-demo.zig b/examples/simargs-demo.zig index 59e9cbc..1e2f02d 100644 --- a/examples/simargs-demo.zig +++ b/examples/simargs-demo.zig @@ -19,12 +19,16 @@ pub fn main() !void { output: []const u8, help: bool = false, + // This special field define sub_commands, + // Each union item is a config struct, which is similar with top-level config struct. __commands__: union(enum) { sub1: struct { a: u64, + help: bool = false, }, sub2: struct { name: []const u8 }, + // Define help message for sub commands. pub const __messages__ = .{ .sub1 = "Subcommand 1", .sub2 = "Subcommand 2", diff --git a/src/bin/loc.zig b/src/bin/loc.zig index 2861f14..c3619c1 100644 --- a/src/bin/loc.zig +++ b/src/bin/loc.zig @@ -206,10 +206,10 @@ pub fn main() !void { }, "[file or directory]", util.get_build_info()); defer opt.deinit(); - const file_or_dir = if (opt.positional_args.items.len == 0) + const file_or_dir = if (opt.positional_args.len == 0) "." else - opt.positional_args.items[0]; + opt.positional_args[0]; var loc_map = LocMap{}; const dir = fs.cwd().openDir(file_or_dir, .{ .iterate = true }) catch |err| switch (err) { diff --git a/src/bin/repeat.zig b/src/bin/repeat.zig index bc143cc..c70f34e 100644 --- a/src/bin/repeat.zig +++ b/src/bin/repeat.zig @@ -35,9 +35,9 @@ pub fn main() !void { }, "command", util.get_build_info()); defer opt.deinit(); - const argv = if (opt.positional_args.items.len == 0) { + const argv = if (opt.positional_args.len == 0) { return error.NoCommand; - } else opt.positional_args.items; + } else opt.positional_args; var keep_running = true; var i: usize = 0; diff --git a/src/bin/tree.zig b/src/bin/tree.zig index d773919..bd687ee 100644 --- a/src/bin/tree.zig +++ b/src/bin/tree.zig @@ -88,10 +88,10 @@ pub fn main() anyerror!void { ); defer opt.deinit(); - const root_dir = if (opt.positional_args.items.len == 0) + const root_dir = if (opt.positional_args.len == 0) "." else - opt.positional_args.items[0]; + opt.positional_args[0]; var writer = std.io.bufferedWriter(std.io.getStdOut().writer()); _ = try writer.write(root_dir); diff --git a/src/mod/simargs.zig b/src/mod/simargs.zig index 67c14ea..2243f7e 100644 --- a/src/mod/simargs.zig +++ b/src/mod/simargs.zig @@ -151,7 +151,7 @@ fn NonOptionType(comptime opt_type: type) type { }; } -const HelpMessage = struct { +const MessageHelper = struct { allocator: std.mem.Allocator, program: []const u8, arg_prompt: ?[]const u8, @@ -160,11 +160,11 @@ const HelpMessage = struct { allocator: std.mem.Allocator, program: []const u8, arg_prompt: ?[]const u8, - ) HelpMessage { + ) MessageHelper { return .{ .allocator = allocator, .program = program, .arg_prompt = arg_prompt }; } - fn print_default(comptime f: std.builtin.Type.StructField, writer: anytype) !void { + fn printDefault(comptime f: std.builtin.Type.StructField, writer: anytype) !void { if (f.default_value == null) { if (@typeInfo(f.type) != .Optional) { try writer.writeAll("(required)"); @@ -201,8 +201,9 @@ const HelpMessage = struct { } pub fn printHelp( - self: HelpMessage, + self: MessageHelper, comptime T: type, + sub_cmd_name: ?[]const u8, writer: anytype, ) !void { const fields = comptime buildOptionFields(T); @@ -229,8 +230,12 @@ const HelpMessage = struct { defer arena.deinit(); const aa = arena.allocator(); const header = try std.fmt.allocPrint(aa, header_tmpl, .{ - self.program, - if (sub_cmds) |cmds| blk: { + if (sub_cmd_name) |cmd| blk: { + break :blk try std.fmt.allocPrint(aa, "{s} {s}", .{ self.program, cmd }); + } else self.program, + + if (sub_cmds) |cmds| + blk: { var lst = std.ArrayList([]const u8).init(aa); try lst.append("[COMMANDS]\n\n COMMANDS:"); for (cmds) |cmd| { @@ -238,7 +243,10 @@ const HelpMessage = struct { } break :blk try std.mem.join(aa, "\n", lst.items); } else if (self.arg_prompt) |p| - try std.fmt.allocPrint(aa, "[--] {s}", .{p}) + if (sub_cmd_name == null) + try std.fmt.allocPrint(aa, "[--] {s}", .{p}) + else + "" else "", }); @@ -287,7 +295,7 @@ const HelpMessage = struct { try writer.writeAll(")"); } - try HelpMessage.print_default( + try MessageHelper.printDefault( f, writer, ); @@ -322,7 +330,7 @@ fn StructArguments( } pub fn printHelp(self: Self, writer: anytype) !void { - try HelpMessage.init(self.allocator, self.program, arg_prompt).printHelp(T, writer); + try MessageHelper.init(self.allocator, self.program, arg_prompt).printHelp(T, null, writer); } }; } @@ -522,9 +530,8 @@ fn OptionParser( comptime Args: type, input_args: [][:0]u8, arg_idx: *usize, - allocator: std.mem.Allocator, - program: []const u8, - comptime arg_prompt: ?[]const u8, + msg_helper: MessageHelper, + sub_cmd_name: ?[]const u8, ) !Args { var args: Args = undefined; var parser = CommandParser(Args){}; @@ -613,7 +620,7 @@ fn OptionParser( if (!is_test) { if (std.mem.eql(u8, opt.long_name, "help")) { const stdout = std.io.getStdOut(); - HelpMessage.init(allocator, program, arg_prompt).printHelp(Args, stdout.writer()) catch @panic("OOM"); + msg_helper.printHelp(Args, sub_cmd_name, stdout.writer()) catch @panic("OOM"); std.process.exit(0); } else if (std.mem.eql(u8, opt.long_name, "version")) { // if (version) |v| { @@ -634,7 +641,13 @@ fn OptionParser( if (std.mem.eql(u8, fld.name, arg)) { inline for (std.meta.fields(@TypeOf(args.__commands__))) |union_fld| { if (comptime std.mem.eql(u8, union_fld.name, fld.name)) { - const value = try Self.parseCommand(union_fld.type, input_args, arg_idx, allocator, program, arg_prompt); + const value = try Self.parseCommand( + union_fld.type, + input_args, + arg_idx, + msg_helper, + fld.name, + ); args.__commands__ = @unionInit(@TypeOf(args.__commands__), fld.name, value); sub_cmd_set = true; break :outer; @@ -693,13 +706,13 @@ fn OptionParser( const parse_args = input_args[1..]; var arg_idx: usize = 0; + const msg_helper = MessageHelper.init(self.allocator, input_args[0], arg_prompt); const parsed = try Self.parseCommand( T, parse_args, &arg_idx, - self.allocator, - input_args[0], - arg_prompt, + msg_helper, + null, ); var result = StructArguments(T, arg_prompt){ .program = input_args[0],