139d763aea8c

feat: Add --version flag and version output (v3.0.11)

- Recognize --version before config loading - Print version banner from output module - Verify with build/test and runtime smoke test

time
2026-05-31 12:19 UTC · 4 months ago
machine
koh2
parent
13667345d2bd
4 files VERSION+1 −1build.zig.zon+1 −1src/main.zig+16 −0src/output.zig+11 −6
VERSION+1 −1
@@ -1 +1 @@1-3.0.101+3.0.11

view file

build.zig.zon+1 −1
@@ -9,7 +9,7 @@99     .name = .nina,1010     // This is a [Semantic Version](https://semver.org/).1111     // In a future version of Zig it will be used for package deduplication.12-    .version = "3.0.10",12+    .version = "3.0.11",1313     // Together with name, this represents a globally unique package1414     // identifier. This field is generated by the Zig toolchain when the1515     // package is first created, and then *never changes*. This allows

view file

src/main.zig+16 −0
@@ -14,6 +14,7 @@1414     sub: []const u8 = "",1515     rest: []const []const u8 = &.{},1616     machine: ?[]const u8 = null,17+    version: bool = false,1718     dry: bool = false,1819     check: bool = false,1920     no_apply: bool = false,@@ -36,6 +37,11 @@3637     const argv = try startup.minimal.args.toSlice(arena);3738     const args = try parseArgs(arena, argv);3839 40+    if (args.version) {41+        output.version();42+        return;43+    }44+3945     // Help and hello work without config4046     if (args.command.len == 0 or std.mem.eql(u8, args.command, "help")) {4147         output.help();@@ -205,6 +211,8 @@205211             result.dry = true;206212         } else if (std.mem.eql(u8, a, "--check")) {207213             result.check = true;214+        } else if (std.mem.eql(u8, a, "--version")) {215+            result.version = true;208216         } else if (std.mem.eql(u8, a, "--no-apply")) {209217             result.no_apply = true;210218         } else if (std.mem.eql(u8, a, "--all")) {@@ -260,4 +268,12 @@260268     defer gpa.free(args.rest);261269     try std.testing.expectEqualStrings("service", args.command);262270     try std.testing.expectEqualStrings("list", args.sub);271+}272+273+test "parse version flag" {274+    const gpa = std.testing.allocator;275+    const argv = [_][:0]const u8{ "nina", "--version" };276+    const args = try parseArgs(gpa, &argv);277+    defer gpa.free(args.rest);278+    try std.testing.expect(args.version);263279 }

view file

src/output.zig+11 −6
@@ -2,6 +2,7 @@22 // All ANSI codes live here. No raw escape sequences elsewhere.33 const std = @import("std");44 const types = @import("types.zig");5+const nina_version = @import("version.zig");56 const Io = std.Io;67 78 // Color constants — all ANSI codes live here only@@ -459,8 +460,8 @@459460     p("{s}profile packages\n\n", .{hdr()});460461 }461462 462-pub fn profileRow(attr: []const u8, version: []const u8, description: []const u8) void {463-    p("   {s:<24}  {s:<12}  {s}\n", .{ attr, version, description });463+pub fn profileRow(attr: []const u8, pkg_version: []const u8, description: []const u8) void {464+    p("   {s:<24}  {s:<12}  {s}\n", .{ attr, pkg_version, description });464465 }465466 466467 // --- Install / Remove / Try ---@@ -484,8 +485,8 @@484485     p("\n   {s}save and close when done{s}\n\n", .{ c(DIM), c(RESET) });485486 }486487 487-pub fn installSelectPrompt(pkg: []const u8, version: []const u8) void {488-    p("{s}{s}{s}{s}  {s}\n\n", .{ hdr(), c(PINK), pkg, c(RESET), version });488+pub fn installSelectPrompt(pkg: []const u8, pkg_version: []const u8) void {489+    p("{s}{s}{s}{s}  {s}\n\n", .{ hdr(), c(PINK), pkg, c(RESET), pkg_version });489490     p("   [i] profile install    {s}instant  no rebuild{s}\n", .{ c(DIM), c(RESET) });490491     p("   [s] system install     {s}opens editor  requires apply{s}\n", .{ c(DIM), c(RESET) });491492     p("   [t] try now            {s}exits when done{s}\n\n", .{ c(DIM), c(RESET) });@@ -511,8 +512,8 @@511512     p("   {s}{s}{s}\n", .{ c(DIM), title, c(RESET) });512513 }513514 514-pub fn listPkg(name: []const u8, version: []const u8) void {515-    p("   {s}{s}{s}   {s}{s}{s}\n", .{ c(PINK), name, c(RESET), c(DIM), version, c(RESET) });515+pub fn listPkg(name: []const u8, pkg_version: []const u8) void {516+    p("   {s}{s}{s}   {s}{s}{s}\n", .{ c(PINK), name, c(RESET), c(DIM), pkg_version, c(RESET) });516517 }517518 518519 // --- Hello ---@@ -574,6 +575,10 @@574575         p("   {s:<18}  {s}{s}{s}\n", .{ cmd[0], c(DIM), cmd[1], c(RESET) });575576     }576577     p("\n   {s}flags: --on <machine>  --dry  --check  --no-apply  --last <n>  --all  --json{s}\n", .{ c(DIM), c(RESET) });578+}579+580+pub fn version() void {581+    p("{s}nina  v{s}  zig 0.16  zero dependencies\n", .{ hdr(), nina_version.VERSION });577582 }578583 579584 // --- Search (text output before TUI) ---

view file