lens

posix system fetch tool
git clone git://brookjeynes.dev/bjeynes/lens.git
Log | Files | Refs | README

commit b846bbe8fa359fcfaaef22b511c78a6c53da9ec7
parent 84afd1768c94adc771cf9be15fbc5a19e76c65ae
Author: brookjeynes <me@brookjeynes.dev>
Date:   Sun, 17 May 2026 18:12:30 +1000

feat: add -[h | -help] and -[v | -version]

Signed-off-by: brookjeynes <me@brookjeynes.dev>

Diffstat:
Mbuild.zig | 18++++++++++++++----
Msrc/main.zig | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 85 insertions(+), 8 deletions(-)

diff --git a/build.zig b/build.zig @@ -1,5 +1,8 @@ const std = @import("std"); +///Must match the `version` in `build.zig.zon`. +const version = std.SemanticVersion{ .major = 2, .minor = 0, .patch = 0 }; + const release_targets: []const std.Target.Query = &.{ .{ .cpu_arch = .aarch64, .os_tag = .macos }, .{ .cpu_arch = .aarch64, .os_tag = .linux }, @@ -12,6 +15,7 @@ fn createExe( exe_name: []const u8, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, + build_options: *std.Build.Module, ) !*std.Build.Step.Compile { const ziggy = b.dependency("ziggy", .{ .target = target, @@ -27,6 +31,7 @@ fn createExe( }), }); + exe.root_module.addImport("options", build_options); exe.root_module.addImport("ziggy", ziggy); return exe; @@ -36,17 +41,22 @@ pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); + const build_options = b.addOptions(); + build_options.step.name = "build options"; + build_options.addOption(std.SemanticVersion, "version", version); + const build_options_module = build_options.createModule(); + const build_all = b.option( bool, "all-targets", "Build all targets in ReleaseSafe mode.", ) orelse false; if (build_all) { - try build_targets(b); + try build_targets(b, build_options_module); return; } - const exe = try createExe(b, "lens", target, optimize); + const exe = try createExe(b, "lens", target, optimize, build_options_module); b.installArtifact(exe); const run_cmd = b.addRunArtifact(exe); @@ -59,11 +69,11 @@ pub fn build(b: *std.Build) !void { run_step.dependOn(&run_cmd.step); } -fn build_targets(b: *std.Build) !void { +fn build_targets(b: *std.Build, build_options: *std.Build.Module) !void { for (release_targets) |t| { const target = b.resolveTargetQuery(t); - const exe = try createExe(b, "lens", target, .ReleaseSafe); + const exe = try createExe(b, "lens", target, .ReleaseSafe, build_options); b.installArtifact(exe); const target_output = b.addInstallArtifact(exe, .{ diff --git a/src/main.zig b/src/main.zig @@ -1,6 +1,7 @@ const std = @import("std"); const builtin = @import("builtin"); +const options = @import("options"); const ziggy = @import("ziggy"); const environment = @import("environment.zig"); @@ -25,6 +26,20 @@ const Config = struct { widgets: []const Widgets, }; +const Options = struct { + help: bool = false, + version: bool = false, + + fn optKind(a: []const u8) enum { short, long, positional } { + if (std.mem.startsWith(u8, a, "--")) return .long; + if (std.mem.startsWith(u8, a, "-")) return .short; + return .positional; + } +}; + +const CONFIG_NAME = "config.ziggy"; +const HOME_DIR_NAME = ".lens"; +const XDG_CONFIG_HOME_DIR_NAME = "lens"; const default_config = Config{ .widgets = &[_]Widgets{ .distro, @@ -38,10 +53,16 @@ const default_config = Config{ .disk, }, }; - -const CONFIG_NAME = "config.ziggy"; -const HOME_DIR_NAME = ".lens"; -const XDG_CONFIG_HOME_DIR_NAME = "lens"; +const help_menu = + \\Usage: lens + \\ + \\a minimal posix system fetch tool + \\ + \\Flags: + \\ -h, --help Show help information and exit. + \\ -v, --version Print version information and exit. + \\ +; pub fn main(init: std.process.Init) !void { const gpa = init.gpa; @@ -51,6 +72,52 @@ pub fn main(init: std.process.Init) !void { var stdout_file_writer: std.Io.File.Writer = .init(.stdout(), io, &stdout_buffer); const stdout_writer = &stdout_file_writer.interface; + var opts = Options{}; + var args = init.minimal.args.iterate(); + _ = args.skip(); + while (args.next()) |arg| { + switch (Options.optKind(arg)) { + .short => { + const str = arg[1..]; + for (str) |b| { + switch (b) { + 'v' => opts.version = true, + 'h' => opts.help = true, + else => { + std.log.err("Invalid option: '{c}'", .{b}); + std.process.exit(1); + }, + } + } + }, + .long => { + var split = std.mem.splitScalar(u8, arg[2..], '='); + const opt = split.first(); + if (std.mem.eql(u8, opt, "version")) { + opts.version = true; + } else if (std.mem.eql(u8, opt, "help")) { + opts.help = true; + } + }, + .positional => { + std.log.err("Invalid opt: '{s}'. lens does not take positional arguments.", .{arg}); + std.process.exit(1); + }, + } + } + + if (opts.help) { + try stdout_writer.writeAll(help_menu); + try stdout_writer.flush(); + return; + } + + if (opts.version) { + try stdout_writer.print("lens v{f}\n", .{options.version}); + try stdout_writer.flush(); + return; + } + var arena = std.heap.ArenaAllocator.init(gpa); defer _ = arena.deinit(); var allocator = arena.allocator();