river: use common CLI arg parsing code
This makes river's main() function quite a bit cleaner.
This commit is contained in:
		| @ -116,6 +116,7 @@ pub fn build(b: *zbs.Builder) !void { | ||||
|  | ||||
|         rivertile.step.dependOn(&scanner.step); | ||||
|         rivertile.addPackage(scanner.getPkg()); | ||||
|         rivertile.addPackagePath("args", "common/args.zig"); | ||||
|         rivertile.linkLibC(); | ||||
|         rivertile.linkSystemLibrary("wayland-client"); | ||||
|  | ||||
| @ -208,6 +209,8 @@ fn addServerDeps(exe: *zbs.LibExeObjStep, scanner: *ScanProtocolsStep) void { | ||||
|     exe.addPackage(wlroots); | ||||
|     exe.linkSystemLibrary("wlroots"); | ||||
|  | ||||
|     exe.addPackagePath("args", "common/args.zig"); | ||||
|  | ||||
|     // TODO: remove when zig issue #131 is implemented | ||||
|     scanner.addCSource(exe); | ||||
| } | ||||
|  | ||||
| @ -113,14 +113,14 @@ pub fn Args(comptime num_positionals: comptime_int, comptime flag_defs: []const | ||||
|             for (self.flags) |flag| { | ||||
|                 if (cstr.cmp(flag.name, flag_name) == 0) return flag.value.boolean; | ||||
|             } | ||||
|             unreachable; | ||||
|             unreachable; // Invalid flag_name | ||||
|         } | ||||
| 
 | ||||
|         pub fn argFlag(self: Self, flag_name: [*:0]const u8) ?[*:0]const u8 { | ||||
|             for (self.flags) |flag| { | ||||
|                 if (cstr.cmp(flag.name, flag_name) == 0) return flag.value.arg; | ||||
|             } | ||||
|             unreachable; | ||||
|             unreachable; // Invalid flag_name | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| @ -15,12 +15,14 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
|  | ||||
| const build_options = @import("build_options"); | ||||
| const std = @import("std"); | ||||
| const fs = std.fs; | ||||
| const io = std.io; | ||||
| const os = std.os; | ||||
| const wlr = @import("wlroots"); | ||||
|  | ||||
| const build_options = @import("build_options"); | ||||
| const Args = @import("args").Args; | ||||
| const FlagDef = @import("args").FlagDef; | ||||
|  | ||||
| const c = @import("c.zig"); | ||||
| const util = @import("util.zig"); | ||||
| @ -47,43 +49,35 @@ const usage: []const u8 = | ||||
| ; | ||||
|  | ||||
| pub fn main() anyerror!void { | ||||
|     var startup_command: ?[:0]const u8 = null; | ||||
|     { | ||||
|         var it = std.process.args(); | ||||
|         // Skip our name | ||||
|         _ = it.nextPosix(); | ||||
|         while (it.nextPosix()) |arg| { | ||||
|             if (std.mem.eql(u8, arg, "-h")) { | ||||
|                 const stdout = std.io.getStdOut().writer(); | ||||
|                 try stdout.print(usage, .{}); | ||||
|                 os.exit(0); | ||||
|             } else if (std.mem.eql(u8, arg, "-c")) { | ||||
|                 if (it.nextPosix()) |command| { | ||||
|                     // If the user used '-c' multiple times the variable | ||||
|                     // already holds a path and needs to be freed. | ||||
|                     if (startup_command) |cmd| util.gpa.free(cmd); | ||||
|                     startup_command = try util.gpa.dupeZ(u8, command); | ||||
|                 } else { | ||||
|                     printErrorExit("Error: flag '-c' requires exactly one argument", .{}); | ||||
|                 } | ||||
|             } else if (std.mem.eql(u8, arg, "-l")) { | ||||
|                 if (it.nextPosix()) |level_str| { | ||||
|                     const log_level = std.fmt.parseInt(u3, level_str, 10) catch | ||||
|                         printErrorExit("Error: invalid log level '{s}'", .{level_str}); | ||||
|                     level = @intToEnum(std.log.Level, log_level); | ||||
|                 } else { | ||||
|                     printErrorExit("Error: flag '-l' requires exactly one argument", .{}); | ||||
|                 } | ||||
|             } else if (std.mem.eql(u8, arg, "-version")) { | ||||
|                 try std.io.getStdOut().writeAll(build_options.version); | ||||
|                 os.exit(0); | ||||
|             } else { | ||||
|                 const stderr = std.io.getStdErr().writer(); | ||||
|                 try stderr.print(usage, .{}); | ||||
|                 os.exit(1); | ||||
|             } | ||||
|         } | ||||
|     // This line is here because of https://github.com/ziglang/zig/issues/7807 | ||||
|     const argv: [][*:0]const u8 = os.argv; | ||||
|     const args = Args(0, &[_]FlagDef{ | ||||
|         .{ .name = "-h", .kind = .boolean }, | ||||
|         .{ .name = "-version", .kind = .boolean }, | ||||
|         .{ .name = "-c", .kind = .arg }, | ||||
|         .{ .name = "-l", .kind = .arg }, | ||||
|     }).parse(argv[1..]); | ||||
|  | ||||
|     if (args.boolFlag("-h")) { | ||||
|         try io.getStdOut().writeAll(usage); | ||||
|         os.exit(0); | ||||
|     } | ||||
|     if (args.boolFlag("-version")) { | ||||
|         try io.getStdOut().writeAll(@import("build_options").version); | ||||
|         os.exit(0); | ||||
|     } | ||||
|     if (args.argFlag("-l")) |level_str| { | ||||
|         const log_level = std.fmt.parseInt(u3, std.mem.span(level_str), 10) catch | ||||
|             fatal("Error: invalid log level '{s}'", .{level_str}); | ||||
|         level = @intToEnum(std.log.Level, log_level); | ||||
|     } | ||||
|     const startup_command = blk: { | ||||
|         if (args.argFlag("-c")) |command| { | ||||
|             break :blk try util.gpa.dupeZ(u8, std.mem.span(command)); | ||||
|         } else { | ||||
|             break :blk try defaultInitPath(); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     wlr.log.init(switch (level) { | ||||
|         .debug => .debug, | ||||
| @ -91,8 +85,6 @@ pub fn main() anyerror!void { | ||||
|         .warn, .err, .crit, .alert, .emerg => .err, | ||||
|     }); | ||||
|  | ||||
|     if (startup_command == null) startup_command = try defaultInitPath(); | ||||
|  | ||||
|     std.log.info("initializing server", .{}); | ||||
|     try server.init(); | ||||
|     defer server.deinit(); | ||||
| @ -125,9 +117,8 @@ pub fn main() anyerror!void { | ||||
|     std.log.info("shutting down", .{}); | ||||
| } | ||||
|  | ||||
| fn printErrorExit(comptime format: []const u8, args: anytype) noreturn { | ||||
|     const stderr = std.io.getStdErr().writer(); | ||||
|     stderr.print(format ++ "\n", args) catch os.exit(1); | ||||
| pub fn fatal(comptime format: []const u8, args: anytype) noreturn { | ||||
|     io.getStdErr().writer().print(format ++ "\n", args) catch {}; | ||||
|     os.exit(1); | ||||
| } | ||||
|  | ||||
| @ -160,7 +151,7 @@ pub fn log( | ||||
|     if (@enumToInt(message_level) <= @enumToInt(level)) { | ||||
|         // Don't store/log messages in release small mode to save space | ||||
|         if (std.builtin.mode != .ReleaseSmall) { | ||||
|             const stderr = std.io.getStdErr().writer(); | ||||
|             const stderr = io.getStdErr().writer(); | ||||
|             stderr.print(@tagName(message_level) ++ ": (" ++ @tagName(scope) ++ ") " ++ | ||||
|                 format ++ "\n", args) catch return; | ||||
|         } | ||||
|  | ||||
| @ -45,8 +45,8 @@ const wayland = @import("wayland"); | ||||
| const wl = wayland.client.wl; | ||||
| const river = wayland.client.river; | ||||
|  | ||||
| const Args = @import("args.zig").Args; | ||||
| const FlagDef = @import("args.zig").FlagDef; | ||||
| const Args = @import("args").Args; | ||||
| const FlagDef = @import("args").FlagDef; | ||||
|  | ||||
| const usage = | ||||
|     \\Usage: rivertile [options] | ||||
|  | ||||
		Reference in New Issue
	
	Block a user