From 38d9065f4f578d63a74902f1b17cb59e8ea39e60 Mon Sep 17 00:00:00 2001 From: Emil Lerch Date: Thu, 19 Mar 2026 12:29:37 -0700 Subject: [PATCH] windows support (theoretically) --- src/config.zig | 29 +++++++++++++++++++---------- src/format.zig | 6 +++--- src/tui.zig | 6 ++++-- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/config.zig b/src/config.zig index d647f14..7a3a41d 100644 --- a/src/config.zig +++ b/src/config.zig @@ -12,11 +12,14 @@ pub const Config = struct { /// URL of a zfin-server instance for lazy cache sync (e.g. "https://zfin.lerch.org") server_url: ?[]const u8 = null, cache_dir: []const u8, + cache_dir_owned: bool = false, // true when cache_dir was allocated via path.join allocator: ?std.mem.Allocator = null, /// Raw .env file contents (keys/values in env_map point into this). env_buf: ?[]const u8 = null, /// Parsed KEY=VALUE pairs from .env file. env_map: ?EnvMap = null, + /// Strings allocated by resolve() from process environment variables. + env_owned: std.ArrayList([]const u8) = .empty, pub fn fromEnv(allocator: std.mem.Allocator) Config { var self = Config{ @@ -40,12 +43,14 @@ pub const Config = struct { const env_cache = self.resolve("ZFIN_CACHE_DIR"); self.cache_dir = env_cache orelse blk: { + self.cache_dir_owned = true; // XDG Base Directory: $XDG_CACHE_HOME/zfin, falling back to $HOME/.cache/zfin - const base = std.posix.getenv("XDG_CACHE_HOME") orelse fallback: { - const home = std.posix.getenv("HOME") orelse "/tmp"; + const xdg = self.resolve("XDG_CACHE_HOME"); + const base = xdg orelse fallback: { + const home = self.resolve("HOME") orelse "/tmp"; break :fallback std.fs.path.join(allocator, &.{ home, ".cache" }) catch @panic("OOM"); }; - const base_allocated = std.posix.getenv("XDG_CACHE_HOME") == null; + const base_allocated = xdg == null; defer if (base_allocated) allocator.free(base); break :blk std.fs.path.join(allocator, &.{ base, "zfin" }) catch @panic("OOM"); }; @@ -55,15 +60,14 @@ pub const Config = struct { pub fn deinit(self: *Config) void { if (self.allocator) |a| { - // cache_dir is allocated (via path.join) unless ZFIN_CACHE_DIR was set directly. - // Check BEFORE freeing env_map/env_buf, since resolve() reads from them. - const cache_dir_from_env = self.resolve("ZFIN_CACHE_DIR") != null; if (self.env_map) |*m| { var map = m.*; map.deinit(); } if (self.env_buf) |buf| a.free(buf); - if (!cache_dir_from_env) { + for (self.env_owned.items) |s| a.free(s); + self.env_owned.deinit(a); + if (self.cache_dir_owned) { a.free(self.cache_dir); } } @@ -77,9 +81,14 @@ pub const Config = struct { self.tiingo_key != null; } - /// Look up a key: environment variable first, then .env file fallback. - fn resolve(self: Config, key: []const u8) ?[]const u8 { - if (std.posix.getenv(key)) |v| return v; + /// Look up a key: process environment first, then .env file fallback. + fn resolve(self: *Config, key: []const u8) ?[]const u8 { + if (self.allocator) |a| { + if (std.process.getEnvVarOwned(a, key)) |v| { + self.env_owned.append(a, v) catch {}; + return v; + } else |_| {} + } if (self.env_map) |m| return m.get(key); return null; } diff --git a/src/format.zig b/src/format.zig index e8403d9..fd92545 100644 --- a/src/format.zig +++ b/src/format.zig @@ -863,11 +863,11 @@ pub fn writeBrailleAnsi( // ── ANSI color helpers (for CLI) ───────────────────────────── /// Determine whether to use ANSI color output. +/// Uses std.Io.tty.Config.detect which handles TTY detection, NO_COLOR, +/// CLICOLOR_FORCE, and Windows console API cross-platform. pub fn shouldUseColor(no_color_flag: bool) bool { if (no_color_flag) return false; - if (std.posix.getenv("NO_COLOR")) |_| return false; - // Check if stdout is a TTY - return std.posix.isatty(std.fs.File.stdout().handle); + return std.Io.tty.Config.detect(std.fs.File.stdout()) != .no_color; } /// Write an ANSI 24-bit foreground color escape. diff --git a/src/tui.zig b/src/tui.zig index 55ab2cf..6605b36 100644 --- a/src/tui.zig +++ b/src/tui.zig @@ -1778,7 +1778,8 @@ pub fn run(allocator: std.mem.Allocator, config: zfin.Config, args: []const []co } var keymap = blk: { - const home = std.posix.getenv("HOME") orelse break :blk keybinds.defaults(); + const home = std.process.getEnvVarOwned(allocator, "HOME") catch break :blk keybinds.defaults(); + defer allocator.free(home); const keys_path = std.fs.path.join(allocator, &.{ home, ".config", "zfin", "keys.srf" }) catch break :blk keybinds.defaults(); defer allocator.free(keys_path); @@ -1787,7 +1788,8 @@ pub fn run(allocator: std.mem.Allocator, config: zfin.Config, args: []const []co defer keymap.deinit(); const theme = blk: { - const home = std.posix.getenv("HOME") orelse break :blk theme_mod.default_theme; + const home = std.process.getEnvVarOwned(allocator, "HOME") catch break :blk theme_mod.default_theme; + defer allocator.free(home); const theme_path = std.fs.path.join(allocator, &.{ home, ".config", "zfin", "theme.srf" }) catch break :blk theme_mod.default_theme; defer allocator.free(theme_path);