git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit60418daf325fc4bb344223680a99f663266eb78f
parentd38c3d9451
authorIsaac Freund <[email protected]>
date2021-07-24 19:31
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 <command>  Run `sh -c <command>` on startup.
     \\  -l <level>    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] <command>
+    \\
+    \\  -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);