From 1a1d96c3a34510e2c3e494e508ee74de3e2eecf0 Mon Sep 17 00:00:00 2001 From: utox39 Date: Wed, 28 May 2025 17:33:10 +0200 Subject: [PATCH 1/8] feat: add conversion of a hex color to rgb --- src/ascii.zig | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/ascii.zig b/src/ascii.zig index cab84a3..9ef63f7 100644 --- a/src/ascii.zig +++ b/src/ascii.zig @@ -12,6 +12,58 @@ pub const White = "\x1b[37m"; pub fn selectAscii() void {} +inline fn parseHexChar(c: u8) !u8 { + return switch (c) { + '0'...'9' => c - '0', + 'a'...'f' => c - 'a' + 10, + 'A'...'F' => c - 'A' + 10, + else => error.InvalidHexChar, + }; +} + +fn parseHexByte(s: []const u8) !u8 { + if (s.len != 2) return error.InvalidHexByteLength; + + const hi = try parseHexChar(s[0]); + const lo = try parseHexChar(s[1]); + + // Example: ff + // hi = 0b00001111 (15) + // lo = 0b00001111 (15) + // + // hi << 4 -> 0b11110000 (240) + // + // (hi << 4) | lo -> 0b11110000 | 0b00001111 + // => 0b11111111 (255) + + return (hi << 4) | lo; +} + +/// Converts a hex color to rgb +pub fn hexColorToRgb(color: []const u8) !struct { r: u8, g: u8, b: u8 } { + if (color.len < 6 or color.len > 7) return error.InvalidHexColorLength; + + var start: usize = 0; + + if (color[0] == '#') start = 1; + + return .{ + .r = try parseHexByte(color[start .. start + 2]), + .g = try parseHexByte(color[start + 2 .. start + 4]), + .b = try parseHexByte(color[start + 4 ..]), + }; +} + +test "parse #ffffff" { + const result = try hexColorToRgb("#ffffff"); + try std.testing.expect((result.r == 255) and (result.g == 255) and (result.b == 255)); +} + +test "parse ffffff" { + const result = try hexColorToRgb("ffffff"); + try std.testing.expect((result.r == 255) and (result.g == 255) and (result.b == 255)); +} + pub fn printAscii(allocator: std.mem.Allocator, sys_info_list: std.ArrayList([]u8)) !void { const stdout_file = std.io.getStdOut().writer(); var bw = std.io.bufferedWriter(stdout_file); From 0019045acb8db0958b7190aa7df4152c84d14494 Mon Sep 17 00:00:00 2001 From: utox39 Date: Wed, 28 May 2025 17:35:13 +0200 Subject: [PATCH 2/8] feat: add user configuration logic --- src/config.zig | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/config.zig diff --git a/src/config.zig b/src/config.zig new file mode 100644 index 0000000..9f80ff4 --- /dev/null +++ b/src/config.zig @@ -0,0 +1,65 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const ascii = @import("ascii.zig"); + +pub const Module = struct { + type: []u8, + key: []u8, + key_color: []u8, +}; + +pub const Config = struct { + modules: []Module, +}; + +pub const ModuleType = enum { + os, + kernel, + uptime, + packages, + shell, + cpu, + gpu, + ram, + swap, + disk, + terminal, + locale, + net, +}; + +pub fn getModulesTypes(allocator: std.mem.Allocator, config: ?std.json.Parsed(Config)) !std.ArrayList(ModuleType) { + var modules_list = std.ArrayList(ModuleType).init(allocator); + + if (config) |c| { + for (c.value.modules) |module| { + const module_enum = std.meta.stringToEnum(ModuleType, module.type); + if (module_enum) |m| { + try modules_list.append(m); + } else { + return error.InvalidModule; + } + } + } + + return modules_list; +} + +pub fn readConfigFile(allocator: std.mem.Allocator) !?std.json.Parsed(Config) { + const home = try std.process.getEnvVarOwned(allocator, "HOME"); + defer allocator.free(home); + + const config_abs_path = try std.mem.concat(allocator, u8, &.{ home, "/.config/zigfetch/config.json" }); + defer allocator.free(config_abs_path); + + const file = std.fs.openFileAbsolute(config_abs_path, .{ .mode = .read_only }) catch |err| switch (err) { + error.FileNotFound => return null, + else => return err, + }; + defer file.close(); + + const data = try file.readToEndAlloc(allocator, std.math.maxInt(usize)); + defer allocator.free(data); + + return try std.json.parseFromSlice(Config, allocator, data, .{ .allocate = .alloc_always }); +} From ff90b826d5113f9b9d4ce7b59d66e359083736af Mon Sep 17 00:00:00 2001 From: utox39 Date: Wed, 28 May 2025 17:35:36 +0200 Subject: [PATCH 3/8] feat: add formatters for user configuration --- src/formatters.zig | 210 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 src/formatters.zig diff --git a/src/formatters.zig b/src/formatters.zig new file mode 100644 index 0000000..6880b95 --- /dev/null +++ b/src/formatters.zig @@ -0,0 +1,210 @@ +const builtin = @import("builtin"); +const std = @import("std"); +const ascii = @import("ascii.zig"); +const detection = @import("detection.zig").os_module; + +pub const formatters = [_]*const fn (allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) anyerror![]u8{ + &getFormattedOsInfo, + &getFormattedKernelInfo, + &getFormattedUptimeInfo, + &getFormattedPackagesInfo, + &getFormattedShellInfo, + &getFormattedCpuInfo, + &getFormattedGpuInfo, + &getFormattedRamInfo, + &getFormattedSwapInfo, + &getFormattedDiskInfo, + &getFormattedTerminalNameInfo, + &getFormattedLocaleInfo, +}; + +pub const default_formatters = [_]*const fn (allocator: std.mem.Allocator) anyerror![]u8{ + &getDefaultFormattedOsInfo, + &getDefaultFormattedKernelInfo, + &getDefaultFormattedUptimeInfo, + &getDefaultFormattedPackagesInfo, + &getDefaultFormattedShellInfo, + &getDefaultFormattedCpuInfo, + &getDefaultFormattedGpuInfo, + &getDefaultFormattedRamInfo, + &getDefaultFormattedSwapInfo, + &getDefaultFormattedDiskInfo, + &getDefaultFormattedTerminalNameInfo, + &getDefaultFormattedLocaleInfo, +}; + +pub fn getDefaultFormattedKernelInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedKernelInfo(allocator, "Kernel", ascii.Yellow); +} + +pub fn getFormattedKernelInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 { + const kernel_info = try detection.system.getKernelInfo(allocator); + defer allocator.free(kernel_info.kernel_name); + defer allocator.free(kernel_info.kernel_release); + + var buf: [1024]u8 = undefined; + + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, try kernel_info.toStr(&buf) }); +} + +pub fn getDefaultFormattedOsInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedOsInfo(allocator, "OS", ascii.Yellow); +} + +pub fn getFormattedOsInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 { + const os_info = try detection.system.getOsInfo(allocator); + defer allocator.free(os_info); + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, os_info }); +} + +pub fn getDefaultFormattedLocaleInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedLocaleInfo(allocator, "Locale", ascii.Yellow); +} + +pub fn getFormattedLocaleInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 { + const locale = try detection.system.getLocale(allocator); + defer allocator.free(locale); + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, locale }); +} + +pub fn getDefaultFormattedUptimeInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedUptimeInfo(allocator, "Uptime", ascii.Yellow); +} + +pub fn getFormattedUptimeInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 { + const uptime = try detection.system.getSystemUptime(); + var buf: [1024]u8 = undefined; + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, try uptime.toStr(&buf) }); +} + +pub fn getDefaultFormattedPackagesInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedPackagesInfo(allocator, "Packages", ascii.Yellow); +} + +pub fn getFormattedPackagesInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 { + if (builtin.os.tag == .macos) { + const packages_info = try detection.packages.getPackagesInfo(allocator); + defer allocator.free(packages_info); + return try std.fmt.allocPrint(allocator, "{s}{s}:{s}{s}", .{ key_color, key, ascii.Reset, packages_info }); + } else if (builtin.os.tag == .linux) { + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} WIP", .{ key_color, key, ascii.Reset }); + } +} + +pub fn getDefaultFormattedShellInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedShellInfo(allocator, "Shell", ascii.Yellow); +} + +pub fn getFormattedShellInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 { + const shell = try detection.user.getShell(allocator); + defer allocator.free(shell); + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, shell[0..(shell.len - 1)] }); +} + +pub fn getDefaultFormattedCpuInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedCpuInfo(allocator, "Cpu", ascii.Yellow); +} + +pub fn getFormattedCpuInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 { + const cpu_info = try detection.hardware.getCpuInfo(allocator); + defer allocator.free(cpu_info.cpu_name); + + var buf: [1024]u8 = undefined; + + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, try cpu_info.toStr(&buf) }); +} + +pub fn getDefaultFormattedGpuInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedGpuInfo(allocator, "Gpu", ascii.Yellow); +} + +pub fn getFormattedGpuInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 { + if (builtin.os.tag == .macos) { + const gpu_info = try detection.hardware.getGpuInfo(allocator); + defer allocator.free(gpu_info.gpu_name); + + var buf: [1024]u8 = undefined; + + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, try gpu_info.toStr(&buf) }); + } else if (builtin.os.tag == .linux) { + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} WIP", .{ key_color, key, ascii.Reset }); + } +} + +pub fn getDefaultFormattedRamInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedRamInfo(allocator, "Ram", ascii.Yellow); +} + +pub fn getFormattedRamInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 { + var ram_info = detection.hardware.RamInfo{ + .ram_size = 0.0, + .ram_usage = 0.0, + .ram_usage_percentage = 0, + }; + if (builtin.os.tag == .macos) { + ram_info = try detection.hardware.getRamInfo(); + } else if (builtin.os.tag == .linux) { + ram_info = try detection.hardware.getRamInfo(allocator); + } + + var buf: [1024]u8 = undefined; + + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, try ram_info.toStr(&buf) }); +} + +pub fn getDefaultFormattedSwapInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedSwapInfo(allocator, "Swap", ascii.Yellow); +} + +pub fn getFormattedSwapInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 { + var buf: [1024]u8 = undefined; + const swap_info = if (builtin.os.tag == .macos) try detection.hardware.getSwapInfo() else if (builtin.os.tag == .linux) try detection.hardware.getSwapInfo(allocator); + if (swap_info) |s| { + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, try s.toStr(&buf) }); + } else { + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} Disabled", .{ key_color, key, ascii.Reset }); + } +} + +pub fn getDefaultFormattedDiskInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedDiskInfo(allocator, "Disk", ascii.Yellow); +} + +pub fn getFormattedDiskInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 { + const disk_info = try detection.hardware.getDiskSize("/"); + + var buf: [1024]u8 = undefined; + + return try std.fmt.allocPrint(allocator, "{s}{s}{s} {s}", .{ key_color, key, ascii.Reset, try disk_info.toStr(&buf) }); +} + +pub fn getDefaultFormattedTerminalNameInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedTerminalNameInfo(allocator, "Terminal", ascii.Yellow); +} + +pub fn getFormattedTerminalNameInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) ![]u8 { + const terminal_name = try detection.user.getTerminalName(allocator); + defer allocator.free(terminal_name); + return try std.fmt.allocPrint(allocator, "{s}{s}:{s} {s}", .{ key_color, key, ascii.Reset, terminal_name }); +} + +pub fn getDefaultFormattedNetInfo(allocator: std.mem.Allocator) ![]u8 { + return try getFormattedNetInfo(allocator, "Local IP", ascii.Yellow); +} + +pub fn getFormattedNetInfo(allocator: std.mem.Allocator, key: []const u8, key_color: []const u8) !std.ArrayList([]u8) { + var formatted_net_info_list = std.ArrayList([]u8).init(allocator); + + var buf: [1024]u8 = undefined; + + var net_info_list = try detection.network.getNetInfo(allocator); + for (net_info_list.items) |n| { + try formatted_net_info_list.append(try std.fmt.allocPrint(allocator, "{s}{s} {s}{s}", .{ key_color, key, ascii.Reset, try n.toStr(&buf) })); + allocator.free(n.interface_name); + allocator.free(n.ipv4_addr); + @memset(&buf, 0); + } + net_info_list.deinit(); + + return formatted_net_info_list; +} From e56de0a70fb33cc6c37d4618c46a08baae71ecc4 Mon Sep 17 00:00:00 2001 From: utox39 Date: Wed, 28 May 2025 17:37:12 +0200 Subject: [PATCH 4/8] chore: add default configuration --- config.json | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 config.json diff --git a/config.json b/config.json new file mode 100644 index 0000000..832629f --- /dev/null +++ b/config.json @@ -0,0 +1,69 @@ +{ + "modules": [ + { + "type": "os", + "key": "OS", + "key_color": "#f5c543" + }, + { + "type": "kernel", + "key": "Kernel", + "key_color": "#f5c543" + }, + { + "type": "uptime", + "key": "Uptime", + "key_color": "#f5c543" + }, + { + "type": "packages", + "key": "Packages", + "key_color": "#f5c543" + }, + { + "type": "shell", + "key": "Shell", + "key_color": "#f5c543" + }, + { + "type": "cpu", + "key": "Cpu", + "key_color": "#f5c543" + }, + { + "type": "gpu", + "key": "Gpu", + "key_color": "#f5c543" + }, + { + "type": "ram", + "key": "Ram", + "key_color": "#f5c543" + }, + { + "type": "swap", + "key": "Swap", + "key_color": "#f5c543" + }, + { + "type": "disk", + "key": "Disk", + "key_color": "#f5c543" + }, + { + "type": "net", + "key": "Local IP", + "key_color": "#f5c543" + }, + { + "type": "terminal", + "key": "Terminal", + "key_color": "#f5c543" + }, + { + "type": "locale", + "key": "Locale", + "key_color": "#f5c543" + } + ] +} From d497f2e4b5bed4a80c3a495c3f539026de284ae2 Mon Sep 17 00:00:00 2001 From: utox39 Date: Wed, 28 May 2025 17:39:03 +0200 Subject: [PATCH 5/8] feat: add user configuration logic --- src/main.zig | 101 +++++++++++++-------------------------------------- 1 file changed, 26 insertions(+), 75 deletions(-) diff --git a/src/main.zig b/src/main.zig index 0cab76d..da1e36e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,6 +2,8 @@ const std = @import("std"); const builtin = @import("builtin"); const detection = @import("detection.zig").os_module; const ascii = @import("ascii.zig"); +const config = @import("config.zig"); +const formatters = @import("formatters.zig"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; @@ -17,19 +19,22 @@ pub fn main() !void { } } - var buf1: [1024]u8 = undefined; - var buf2: [1024]u8 = undefined; + const conf = try config.readConfigFile(allocator); + defer if (conf) |c| c.deinit(); + + const modules_types = try config.getModulesTypes(allocator, conf); + defer modules_types.deinit(); const username = try detection.user.getUsername(allocator); const hostname = try detection.system.getHostname(allocator); - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}{s}{s}@{s}{s}{s}", .{ + try sys_info_list.append(try std.fmt.allocPrint(allocator, "{s}{s}{s}@{s}{s}{s}", .{ ascii.Yellow, username, ascii.Reset, ascii.Magenta, hostname, ascii.Reset, - }))); + })); allocator.free(hostname); allocator.free(username); @@ -37,82 +42,28 @@ pub fn main() !void { @memset(separtor_buffer, '-'); try sys_info_list.append(separtor_buffer); - const kernel_info = try detection.system.getKernelInfo(allocator); - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Kernel:{s} {s}", .{ ascii.Yellow, ascii.Reset, try kernel_info.toStr(&buf2) }))); - allocator.free(kernel_info.kernel_name); - allocator.free(kernel_info.kernel_release); + if (modules_types.items.len == 0) { + inline for (0..formatters.formatters.len) |i| { + try sys_info_list.append(try formatters.default_formatters[i](allocator)); + } + } else if (conf) |c| { + for (modules_types.items, c.value.modules) |module_type, module| { + var buf: [32]u8 = undefined; + const rgb = try ascii.hexColorToRgb(module.key_color); + const key_color = try std.fmt.bufPrint(&buf, "\x1b[38;2;{d};{d};{d}m", .{ rgb.r, rgb.g, rgb.b }); - const os_info = try detection.system.getOsInfo(allocator); - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}OS:{s} {s}", .{ ascii.Yellow, ascii.Reset, os_info }))); - allocator.free(os_info); + if (module_type == config.ModuleType.net) { + var formatted_net_info_list = try formatters.getFormattedNetInfo(allocator, module.key, key_color); + defer formatted_net_info_list.deinit(); - const locale = try detection.system.getLocale(allocator); - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Locale:{s} {s}", .{ ascii.Yellow, ascii.Reset, locale }))); - allocator.free(locale); + try sys_info_list.appendSlice(formatted_net_info_list.items); - const uptime = try detection.system.getSystemUptime(); - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Uptime:{s} {s}", .{ ascii.Yellow, ascii.Reset, try uptime.toStr(&buf2) }))); + continue; + } - if (builtin.os.tag == .macos) { - const packages_info = try detection.packages.getPackagesInfo(allocator); - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Packages:{s}{s}", .{ ascii.Yellow, ascii.Reset, packages_info }))); - allocator.free(packages_info); - } else if (builtin.os.tag == .linux) { - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Packages:{s} WIP", .{ ascii.Yellow, ascii.Reset }))); + try sys_info_list.append(try formatters.formatters[@intFromEnum(module_type)](allocator, module.key, key_color)); + } } - const shell = try detection.user.getShell(allocator); - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Shell:{s} {s}", .{ ascii.Yellow, ascii.Reset, shell[0..(shell.len - 1)] }))); - allocator.free(shell); - - const cpu_info = try detection.hardware.getCpuInfo(allocator); - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Cpu:{s} {s}", .{ ascii.Yellow, ascii.Reset, try cpu_info.toStr(&buf2) }))); - allocator.free(cpu_info.cpu_name); - - if (builtin.os.tag == .macos) { - const gpu_info = try detection.hardware.getGpuInfo(allocator); - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Gpu:{s} {s}", .{ ascii.Yellow, ascii.Reset, try gpu_info.toStr(&buf2) }))); - allocator.free(gpu_info.gpu_name); - } else if (builtin.os.tag == .linux) { - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Gpu:{s} WIP", .{ ascii.Yellow, ascii.Reset }))); - } - - var ram_info = detection.hardware.RamInfo{ - .ram_size = 0.0, - .ram_usage = 0.0, - .ram_usage_percentage = 0, - }; - if (builtin.os.tag == .macos) { - ram_info = try detection.hardware.getRamInfo(); - } else if (builtin.os.tag == .linux) { - ram_info = try detection.hardware.getRamInfo(allocator); - } - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Ram:{s} {s}", .{ ascii.Yellow, ascii.Reset, try ram_info.toStr(&buf2) }))); - - const swap_info = if (builtin.os.tag == .macos) try detection.hardware.getSwapInfo() else if (builtin.os.tag == .linux) try detection.hardware.getSwapInfo(allocator); - if (swap_info) |s| { - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Swap:{s} {s}", .{ ascii.Yellow, ascii.Reset, try s.toStr(&buf2) }))); - } else { - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Swap:{s} Disabled", .{ ascii.Yellow, ascii.Reset }))); - } - - const disk_info = try detection.hardware.getDiskSize("/"); - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Disk{s} {s}", .{ ascii.Yellow, ascii.Reset, try disk_info.toStr(&buf2) }))); - - const terminal_name = try detection.user.getTerminalName(allocator); - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Terminal:{s} {s}", .{ ascii.Yellow, ascii.Reset, terminal_name }))); - allocator.free(terminal_name); - - const net_info_list = try detection.network.getNetInfo(allocator); - for (net_info_list.items) |n| { - try sys_info_list.append(try allocator.dupe(u8, try std.fmt.bufPrint(&buf1, "{s}Local IP {s}{s}", .{ ascii.Yellow, ascii.Reset, try n.toStr(&buf2) }))); - allocator.free(n.interface_name); - allocator.free(n.ipv4_addr); - } - net_info_list.deinit(); - - @memset(&buf1, 0); - @memset(&buf2, 0); - try ascii.printAscii(allocator, sys_info_list); } From 801d15afc8bc5b4cdc842c6cf5fc7d86477a94a3 Mon Sep 17 00:00:00 2001 From: utox39 Date: Wed, 28 May 2025 17:39:19 +0200 Subject: [PATCH 6/8] docs(README): update README --- README.md | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b77b96e..3d2b336 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,13 @@ # Zigfetch +- [Description](#description) +- [Requirements](#requirements) +- [Installation](#installation) +- [Usage](#usage) + - [Configuration](#configuration) +- [Roadtrip](#roadtrip) +- [Contributing](#contributing) + ## Description Zigfetch is a minimal [neofetch](https://github.com/dylanaraps/neofetch)/[fastfetch](https://github.com/fastfetch-cli/fastfetch) like system information tool @@ -21,7 +29,7 @@ $ cd path/to/zigfetch $ zig build -Doptimize=ReleaseSafe # Then move it somewhere in your $PATH. Here is an example: -$ mv ./zig-out/zigfetch ~/bin +$ mv ./zig-out/zigfetch ~/bin/ ``` ## Usage @@ -30,12 +38,36 @@ $ mv ./zig-out/zigfetch ~/bin $ zigfetch ``` +### Configuration + +> [!IMPORTANT] +> Currently, Zig does not have a built-in library for JSON validation via JSON schema, so it is very important to follow the pattern shown in the default configuration file ([config.json]()) to avoid errors + +- Create the config folder + +```console +$ mkdir -p ~/.config/zigfetch +``` + +- Create the config file + +```console +$ cd ~/.config/zigfetch +$ touch config.json +``` + +- Or copy the default config (preferred way) + +```console +$ cp /path/to/zigfetch/config.json ~/.config/zigfetch/config.json +``` + ## Roadtrip - [ ] Add ASCII art for each operating system and Linux distro - [ ] Add GPU info for Linux - [ ] Add packages info for Linux -- [ ] Add user customization +- [x] Add user customization ## Contributing If you would like to contribute to this project just create a pull request which I will try to review as soon as possible. From c81e9f7886125712f0234b24f5c8facd494a8c13 Mon Sep 17 00:00:00 2001 From: utox39 Date: Wed, 28 May 2025 17:40:02 +0200 Subject: [PATCH 7/8] build: bump version to 0.4.0 --- build.zig.zon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.zig.zon b/build.zig.zon index 975d7f5..f207ef6 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -10,7 +10,7 @@ // This is a [Semantic Version](https://semver.org/). // In a future version of Zig it will be used for package deduplication. - .version = "0.3.1", + .version = "0.4.0", // Together with name, this represents a globally unique package // identifier. This field is generated by the Zig toolchain when the From bf721c1671472848ee0b28d9a44484d4e1a06362 Mon Sep 17 00:00:00 2001 From: utox39 Date: Wed, 28 May 2025 17:46:03 +0200 Subject: [PATCH 8/8] docs(README): update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d2b336..4b5115d 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ $ zigfetch ### Configuration > [!IMPORTANT] -> Currently, Zig does not have a built-in library for JSON validation via JSON schema, so it is very important to follow the pattern shown in the default configuration file ([config.json]()) to avoid errors +> Currently, Zig does not have a built-in library for JSON validation via JSON schema, so it is very important to follow the pattern shown in the default configuration file ([config.json](https://github.com/utox39/zigfetch/blob/feat/user-config/config.json)) to avoid errors - Create the config folder