From 23088b800c9e4166396996de82fb1b13c8671127 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Sat, 24 Jul 2021 19:31:04 +0200 Subject: [PATCH] common: standardize on -help option Also: - Check for -help option *before* unknown options - Use common flags parsing code for riverctl - Add usage text to riverctl --- build.zig | 1 + common/flags.zig | 2 +- river/main.zig | 14 +++++------ riverctl/main.zig | 63 +++++++++++++++++++++++++++++++++------------- rivertile/main.zig | 11 ++++---- 5 files changed, 60 insertions(+), 31 deletions(-) diff --git a/build.zig b/build.zig index 8dbf0bd..48b049a 100644 --- a/build.zig +++ b/build.zig @@ -100,6 +100,7 @@ pub fn build(b: *zbs.Builder) !void { riverctl.step.dependOn(&scanner.step); riverctl.addPackage(scanner.getPkg()); + riverctl.addPackagePath("flags", "common/flags.zig"); riverctl.linkLibC(); riverctl.linkSystemLibrary("wayland-client"); diff --git a/common/flags.zig b/common/flags.zig index 0836706..4fb082c 100644 --- a/common/flags.zig +++ b/common/flags.zig @@ -85,7 +85,7 @@ pub fn parse(args: [][*:0]const u8, comptime flags: []const Flag) !ParseResult(f .arg => { arg_idx += 1; if (arg_idx == args.len) { - std.log.err("flag '" ++ flag.name ++ + std.log.err("option '" ++ flag.name ++ "' requires an argument but none was provided!", .{}); return error.MissingFlagArgument; } diff --git a/river/main.zig b/river/main.zig index 6403f18..50ea07e 100644 --- a/river/main.zig +++ b/river/main.zig @@ -40,7 +40,7 @@ pub var level: std.log.Level = switch (std.builtin.mode) { const usage: []const u8 = \\usage: river [options] \\ - \\ -h Print this help message and exit. + \\ -help Print this help message and exit. \\ -c Run `sh -c ` on startup. \\ -l Set the log level to a value from 0 to 7. \\ -version Print the version number and exit. @@ -51,7 +51,7 @@ pub fn main() anyerror!void { // This line is here because of https://github.com/ziglang/zig/issues/7807 const argv: [][*:0]const u8 = os.argv; const result = flags.parse(argv[1..], &[_]flags.Flag{ - .{ .name = "-h", .kind = .boolean }, + .{ .name = "-help", .kind = .boolean }, .{ .name = "-version", .kind = .boolean }, .{ .name = "-c", .kind = .arg }, .{ .name = "-l", .kind = .arg }, @@ -59,18 +59,18 @@ pub fn main() anyerror!void { try io.getStdErr().writeAll(usage); os.exit(1); }; + if (result.boolFlag("-help")) { + try io.getStdOut().writeAll(usage); + os.exit(0); + } if (result.args.len != 0) { std.log.err("unknown option '{s}'", .{result.args[0]}); try io.getStdErr().writeAll(usage); os.exit(1); } - if (result.boolFlag("-h")) { - try io.getStdOut().writeAll(usage); - os.exit(0); - } if (result.boolFlag("-version")) { - try io.getStdOut().writeAll(@import("build_options").version); + try io.getStdOut().writeAll(build_options.version); os.exit(0); } if (result.argFlag("-l")) |level_str| { diff --git a/riverctl/main.zig b/riverctl/main.zig index 31ca44e..3f54a2e 100644 --- a/riverctl/main.zig +++ b/riverctl/main.zig @@ -17,6 +17,7 @@ const std = @import("std"); const mem = std.mem; +const io = std.io; const os = std.os; const assert = std.debug.assert; @@ -24,6 +25,19 @@ const wayland = @import("wayland"); const wl = wayland.client.wl; const zriver = wayland.client.zriver; +const flags = @import("flags"); + +const usage = + \\usage: riverctl [options] + \\ + \\ -help Print this help message and exit. + \\ -version Print the version number and exit. + \\ + \\Complete documentation of the recognized commands may be found in + \\the riverctl(1) man page. + \\ +; + const gpa = std.heap.c_allocator; pub const Globals = struct { @@ -37,11 +51,11 @@ pub fn main() !void { return err; switch (err) { - error.RiverControlNotAdvertised => printErrorExit( + error.RiverControlNotAdvertised => fatal( \\The Wayland server does not support river-control-unstable-v1. \\Do your versions of river and riverctl match? , .{}), - error.SeatNotAdverstised => printErrorExit( + error.SeatNotAdverstised => fatal( \\The Wayland server did not advertise any seat. , .{}), else => return err, @@ -50,6 +64,24 @@ pub fn main() !void { } fn _main() !void { + // This line is here because of https://github.com/ziglang/zig/issues/7807 + const argv: [][*:0]const u8 = os.argv; + const result = flags.parse(argv[1..], &[_]flags.Flag{ + .{ .name = "-help", .kind = .boolean }, + .{ .name = "-version", .kind = .boolean }, + }) catch { + try io.getStdErr().writeAll(usage); + os.exit(1); + }; + if (result.boolFlag("-help")) { + try io.getStdOut().writeAll(usage); + os.exit(0); + } + if (result.boolFlag("-version")) { + try io.getStdOut().writeAll(@import("build_options").version); + os.exit(0); + } + const display = try wl.Display.connect(null); const registry = try display.getRegistry(); @@ -61,19 +93,9 @@ fn _main() !void { const control = globals.control orelse return error.RiverControlNotAdvertised; const seat = globals.seat orelse return error.SeatNotAdverstised; - // This next line is needed cause of https://github.com/ziglang/zig/issues/2622 - const args = os.argv; - - if (mem.eql(u8, mem.span(args[1]), "-version")) { - try std.io.getStdOut().writeAll(@import("build_options").version); - std.os.exit(0); - } - - // Skip our name, send all other args - for (args[1..]) |arg| control.addArgument(arg); + for (result.args) |arg| control.addArgument(arg); const callback = try control.runCommand(seat); - callback.setListener(?*c_void, callbackListener, null); // Loop until our callback is called and we exit. @@ -103,12 +125,19 @@ fn callbackListener(callback: *zriver.CommandCallbackV1, event: zriver.CommandCa } os.exit(0); }, - .failure => |failure| printErrorExit("Error: {s}\n", .{failure.failure_message}), + .failure => |failure| { + // A small hack to provide usage text when river reports an unknown command. + if (std.cstr.cmp(failure.failure_message, "unknown command") == 0) { + std.log.err("unknown command", .{}); + io.getStdErr().writeAll(usage) catch {}; + os.exit(1); + } + fatal("{s}", .{failure.failure_message}); + }, } } -pub fn printErrorExit(comptime format: []const u8, args: anytype) noreturn { - const stderr = std.io.getStdErr().writer(); - stderr.print("err: " ++ format ++ "\n", args) catch std.os.exit(1); +fn fatal(comptime format: []const u8, args: anytype) noreturn { + std.log.err(format, args); std.os.exit(1); } diff --git a/rivertile/main.zig b/rivertile/main.zig index 59a0f6e..2116341 100644 --- a/rivertile/main.zig +++ b/rivertile/main.zig @@ -51,7 +51,7 @@ const flags = @import("flags"); const usage = \\usage: rivertile [options] \\ - \\ -h, --help Print this help message and exit. + \\ -help Print this help message and exit. \\ -version Print the version number and exit. \\ -view-padding Set the padding around views in pixels. (Default 6) \\ -outer-padding Set the padding around the edge of the layout area in @@ -314,8 +314,7 @@ pub fn main() !void { // https://github.com/ziglang/zig/issues/7807 const argv: [][*:0]const u8 = os.argv; const result = flags.parse(argv[1..], &[_]flags.Flag{ - .{ .name = "-h", .kind = .boolean }, - .{ .name = "--help", .kind = .boolean }, + .{ .name = "-help", .kind = .boolean }, .{ .name = "-version", .kind = .boolean }, .{ .name = "-view-padding", .kind = .arg }, .{ .name = "-outer-padding", .kind = .arg }, @@ -326,12 +325,12 @@ pub fn main() !void { try std.io.getStdErr().writeAll(usage); os.exit(1); }; - if (result.args.len != 0) fatalPrintUsage("unknown option '{s}'", .{result.args[0]}); - - if (result.boolFlag("-h") or result.boolFlag("--help")) { + if (result.boolFlag("-help")) { try std.io.getStdOut().writeAll(usage); os.exit(0); } + if (result.args.len != 0) fatalPrintUsage("unknown option '{s}'", .{result.args[0]}); + if (result.boolFlag("-version")) { try std.io.getStdOut().writeAll(@import("build_options").version); os.exit(0);