refactor(cli): consolidate terminal and color utilities into io.zig

Consolidate overlapping utilities:
- colors.zig (35 lines) → re-exports from io.zig
- terminal.zig (36 lines) → re-exports from io.zig
- io.zig now contains all terminal, color, and I/O utilities

Benefits:
- Single source of truth for terminal/color logic
- Reduced file count (25 → 23 utils)
- Easier maintenance with all I/O in one place

Build passes successfully.
This commit is contained in:
Jeremie Fraeys 2026-03-04 21:05:37 -05:00
parent 7a6d454174
commit 87cefea9ae
No known key found for this signature in database
3 changed files with 94 additions and 67 deletions

View file

@ -1,34 +1,12 @@
// Minimal color codes for CLI - no formatting, just basic ANSI
const std = @import("std");
const terminal = @import("terminal.zig");
/// Re-exports from io.zig for backward compatibility
/// Use @import("io.zig") directly for new code
const io = @import("io.zig");
pub const reset = "\x1b[0m";
pub const red = "\x1b[31m";
pub const green = "\x1b[32m";
pub const yellow = "\x1b[33m";
pub const blue = "\x1b[34m";
pub const bold = "\x1b[1m";
/// Check if colors should be used based on: flag > NO_COLOR > CLICOLOR_FORCE > TTY
pub fn shouldUseColor(force_flag: ?bool) bool {
// Flag takes precedence
if (force_flag) |forced| return forced;
// Check NO_COLOR (any value disables colors)
if (std.process.getEnvVarOwned(std.heap.page_allocator, "NO_COLOR")) |_| {
return false;
} else |_| {}
// Check CLICOLOR_FORCE (any value enables colors)
if (std.process.getEnvVarOwned(std.heap.page_allocator, "CLICOLOR_FORCE")) |_| {
return true;
} else |_| {}
// Default: color if TTY
return terminal.isTTY();
}
// Legacy function - uses auto-detection
pub fn shouldUseColorAuto() bool {
return shouldUseColor(null);
}
pub const reset = io.reset;
pub const red = io.red;
pub const green = io.green;
pub const yellow = io.yellow;
pub const blue = io.blue;
pub const bold = io.bold;
pub const shouldUseColor = io.shouldUseColor;
pub const shouldUseColorAuto = io.shouldUseColorAuto;

View file

@ -1,5 +1,80 @@
const std = @import("std");
// ============================================================================
// Terminal Detection and Utilities
// ============================================================================
/// Check if stdout is a TTY
pub fn isTTY() bool {
return std.posix.isatty(std.posix.STDOUT_FILENO);
}
/// Get terminal width from COLUMNS env var
pub fn getWidth() ?usize {
const allocator = std.heap.page_allocator;
if (std.process.getEnvVarOwned(allocator, "COLUMNS")) |cols| {
defer allocator.free(cols);
return std.fmt.parseInt(usize, cols, 10) catch null;
} else |_| {}
return null;
}
/// Get user's preferred pager from PAGER env var
pub fn getPager() ?[]const u8 {
const allocator = std.heap.page_allocator;
return std.process.getEnvVarOwned(allocator, "PAGER") catch null;
}
/// Table formatting mode
pub const TableMode = enum { truncate, wrap, auto };
/// Get table formatting mode from env var
pub fn getTableMode() TableMode {
const allocator = std.heap.page_allocator;
const mode_str = std.process.getEnvVarOwned(allocator, "ML_TABLE_MODE") catch return .truncate;
defer allocator.free(mode_str);
if (std.mem.eql(u8, mode_str, "wrap")) return .wrap;
if (std.mem.eql(u8, mode_str, "auto")) return .auto;
return .truncate;
}
// ============================================================================
// ANSI Color Codes
// ============================================================================
pub const reset = "\x1b[0m";
pub const red = "\x1b[31m";
pub const green = "\x1b[32m";
pub const yellow = "\x1b[33m";
pub const blue = "\x1b[34m";
pub const bold = "\x1b[1m";
/// Check if colors should be used based on: flag > NO_COLOR > CLICOLOR_FORCE > TTY
pub fn shouldUseColor(force_flag: ?bool) bool {
// Flag takes precedence
if (force_flag) |forced| return forced;
// Check NO_COLOR (any value disables colors)
if (std.process.getEnvVarOwned(std.heap.page_allocator, "NO_COLOR")) |_| {
return false;
} else |_| {}
// Check CLICOLOR_FORCE (any value enables colors)
if (std.process.getEnvVarOwned(std.heap.page_allocator, "CLICOLOR_FORCE")) |_| {
return true;
} else |_| {}
// Default: color if TTY
return isTTY();
}
/// Legacy function - uses auto-detection
pub const shouldUseColorAuto = shouldUseColor;
// ============================================================================
// stdout/stderr Writers
// ============================================================================
fn writeAllFd(fd: std.posix.fd_t, data: []const u8) std.Io.Writer.Error!void {
var off: usize = 0;
while (off < data.len) {

View file

@ -1,35 +1,9 @@
const std = @import("std");
/// Re-exports from io.zig for backward compatibility
/// Use @import("io.zig") directly for new code
const io = @import("io.zig");
/// Check if stdout is a TTY
pub fn isTTY() bool {
return std.posix.isatty(std.posix.STDOUT_FILENO);
}
/// Get terminal width from COLUMNS env var
pub fn getWidth() ?usize {
const allocator = std.heap.page_allocator;
if (std.process.getEnvVarOwned(allocator, "COLUMNS")) |cols| {
defer allocator.free(cols);
return std.fmt.parseInt(usize, cols, 10) catch null;
} else |_| {}
return null;
}
/// Table formatting mode
pub const TableMode = enum { truncate, wrap, auto };
/// Get table formatting mode from env var
pub fn getTableMode() TableMode {
const allocator = std.heap.page_allocator;
const mode_str = std.process.getEnvVarOwned(allocator, "ML_TABLE_MODE") catch return .truncate;
defer allocator.free(mode_str);
if (std.mem.eql(u8, mode_str, "wrap")) return .wrap;
if (std.mem.eql(u8, mode_str, "auto")) return .auto;
return .truncate;
}
/// Get user's preferred pager from PAGER env var
pub fn getPager() ?[]const u8 {
const allocator = std.heap.page_allocator;
return std.process.getEnvVarOwned(allocator, "PAGER") catch null;
}
pub const isTTY = io.isTTY;
pub const getWidth = io.getWidth;
pub const getPager = io.getPager;
pub const TableMode = io.TableMode;
pub const getTableMode = io.getTableMode;