From 72a441a6bdeb40c423807e047496f02b4511c4a5 Mon Sep 17 00:00:00 2001 From: Manlio Perillo Date: Sat, 6 Jun 2026 17:39:42 +0200 Subject: [PATCH] Improve command line style Parse the command line following the code from the Zig compiler cli. Use the args iterator instead of slice, and use while instead of for loop. Use the new std.mem.cutPrefix instead of the custom function prefix. Move Context struct to the top. --- rivendell/elrond.zig | 47 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/rivendell/elrond.zig b/rivendell/elrond.zig index 52cf395..c49d0ab 100644 --- a/rivendell/elrond.zig +++ b/rivendell/elrond.zig @@ -21,6 +21,7 @@ const builtin = @import("builtin"); const Process = std.process; const print = std.debug.print; +const cutPrefix = std.mem.cutPrefix; const progress_filename = ".progress.txt"; @@ -102,6 +103,16 @@ pub const Exercise = struct { } }; +// Shared, read-only run context threaded through the helpers. +const Context = struct { + io: std.Io, + arena: std.mem.Allocator, + zig_exe: []const u8, + work_path: []const u8, +}; + +const Error = error{Failed}; + // Ansi colors. var use_color_escapes = false; var red_text: []const u8 = ""; @@ -138,7 +149,8 @@ pub fn main(init: std.process.Init) !void { const io = init.io; const arena = init.arena.allocator(); - const args = try init.minimal.args.toSlice(arena); + var args_it = try init.minimal.args.iterateAllocator(arena); + if (!args_it.skip()) @panic("expected self arg"); setupColors(io); @@ -150,22 +162,21 @@ pub fn main(init: std.process.Init) !void { var only_n: ?usize = null; var start_n: ?usize = null; - for (1..args.len) |n| { - const arg = args[n]; + while (args_it.next()) |arg| { if (std.mem.eql(u8, arg, "--logo")) { print("{s}{s}{s}", .{ yellow_text, logo, reset_text }); return; - } else if (prefix(arg, "--zig=")) |v| { + } else if (cutPrefix(u8, arg, "--zig=")) |v| { zig_exe = v; - } else if (prefix(arg, "--work-path=")) |v| { + } else if (cutPrefix(u8, arg, "--work-path=")) |v| { work_path = v; - } else if (prefix(arg, "--only=")) |v| { + } else if (cutPrefix(u8, arg, "--only=")) |v| { only_n = std.fmt.parseInt(usize, v, 10) catch { print("invalid --only value: {s}\n", .{v}); std.process.exit(1); }; mode = .named; - } else if (prefix(arg, "--start=")) |v| { + } else if (cutPrefix(u8, arg, "--start=")) |v| { start_n = std.fmt.parseInt(usize, v, 10) catch { print("invalid --start value: {s}\n", .{v}); std.process.exit(1); @@ -181,7 +192,12 @@ pub fn main(init: std.process.Init) !void { print("{s}", .{logo}); - const ctx: Context = .{ .io = io, .arena = arena, .zig_exe = zig_exe, .work_path = work_path }; + const ctx: Context = .{ + .io = io, + .arena = arena, + .zig_exe = zig_exe, + .work_path = work_path, + }; switch (mode) { .named => { @@ -230,21 +246,6 @@ pub fn main(init: std.process.Init) !void { } } -fn prefix(arg: []const u8, pre: []const u8) ?[]const u8 { - if (std.mem.startsWith(u8, arg, pre)) return arg[pre.len..]; - return null; -} - -// Shared, read-only run context threaded through the helpers. -const Context = struct { - io: std.Io, - arena: std.mem.Allocator, - zig_exe: []const u8, - work_path: []const u8, -}; - -const Error = error{Failed}; - // Iterates exercises from `start_index` to the end, stopping at the first failure. // Progress is written after each passed exercise. fn iterateFrom(ctx: Context, start_index: usize) Error!void {