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:
| M | build.zig | | | 18 | ++++++++++++++---- |
| M | src/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();