const std = @import("std"); const builtin = @import("builtin"); const vaxis = @import("vaxis"); const linux = @import("linux.zig"); const macos = @import("macos.zig"); const OSVersion = struct { name: []const u8, major: []u64, minor: []u64, patch: []u64, }; const Shell = struct { name: []const u8, version: []const u8, }; pub fn get_shell(allocator: std.mem.Allocator) !vaxis.Cell.Segment { const shell_env = std.posix.getenv("SHELL") orelse "Unknown"; var shell_path = std.mem.splitBackwards(u8, shell_env, "/"); var buf: [64]u8 = undefined; const filename = shell_path.first(); if (std.mem.eql(u8, filename, "zsh")) { const zsh_version = try get_zsh_version(allocator, &buf, shell_env); // defer allocator.free(zsh_version); return .{ .text = try std.fmt.allocPrint( allocator, ": {s} {s}\n", .{ filename, zsh_version, }, ), }; } else if (std.mem.eql(u8, filename, "bash")) { const bash_version = try get_bash_version(allocator, &buf, shell_env); return .{ .text = try std.fmt.allocPrint( allocator, ": bash {s}\n", .{bash_version}, ), }; } else if (std.mem.eql(u8, filename, "bash")) { const version = try std.process.Child.run( .{ .allocator = allocator, .argv = &.{ shell_env, "--version" }, }, ); defer allocator.free(version.stdout); defer allocator.free(version.stderr); return .{ .text = try std.fmt.allocPrint( allocator, ": {s}\n", .{version.stdout}, ), }; } return .{ .text = try std.fmt.allocPrint(allocator, ": {s}\n", .{shell_env}), }; } pub fn get_kernel_version(buf: []u8) !vaxis.Cell.Segment { switch (builtin.os.tag) { .macos => { return .{ .text = try macos.get_kernel_version(buf), }; }, else => return .{ .text = try std.fmt.bufPrint(buf, "unknown", .{}) }, } } pub fn get_uptime(buf: []u8) !vaxis.Cell.Segment { switch (builtin.os.tag) { .macos => { return .{ .text = try macos.get_uptime(buf), }; }, else => return .{ .text = try std.fmt.bufPrint(buf, "unknown", .{}) }, } } pub fn get_cpu_info(buf: []u8) !vaxis.Cell.Segment { switch (builtin.os.tag) { .macos => { return .{ .text = try macos.get_cpu_info(buf), }; }, else => return .{ .text = try std.fmt.bufPrint(buf, "unknown", .{}) }, } } pub fn get_mem_info(buf: []u8) !vaxis.Cell.Segment { switch (builtin.os.tag) { .macos => { return .{ .text = try macos.get_mem_info(buf), }; }, else => return .{ .text = try std.fmt.bufPrint(buf, "unknown", .{}) }, } } pub fn get_battery(buf: []u8) !vaxis.Cell.Segment { switch (builtin.os.tag) { .macos => { return .{ .text = try macos.get_battery_info(buf), }; }, else => return .{ .text = "unknown" }, } } pub fn get_os_version(buf: []u8) !vaxis.Cell.Segment { switch (builtin.os.tag) { .macos => { return .{ .text = try macos.macos_version(buf), }; }, .linux => { return .{ .text = try std.fmt.bufPrint(buf, "{s} {s}", .{ try linux.kernel_version(), try linux.distribution() }), }; }, .freebsd => { return .{ .text = try std.fmt.bufPrint(buf, "not implemented", .{}), }; }, else => return .{ .text = try std.fmt.bufPrint(buf, "unknown", .{}) }, } } pub fn get_terminal(buf: []u8) !vaxis.Cell.Segment { const term_program = std.posix.getenv("TERM_PROGRAM") orelse "Unknown"; if (std.mem.eql(u8, term_program, "ghostty")) { return .{ .text = try std.fmt.bufPrint(buf, ": {s} 󰊠\n", .{term_program}), }; } return .{ .text = try std.fmt.bufPrint(buf, ": {s}\n", .{term_program}), }; } fn get_zsh_version(allocator: std.mem.Allocator, buf: []u8, zsh_path: []const u8) ![]const u8 { const zsh_version = try std.fmt.bufPrint(buf, "Unknown", .{}); const version_string = std.process.Child.run( .{ .allocator = allocator, .argv = &.{ zsh_path, "--version" }, }, ) catch { return zsh_version; }; defer allocator.free(version_string.stdout); defer allocator.free(version_string.stderr); var version = std.mem.split(u8, version_string.stdout, " "); _ = version.first(); return try std.fmt.bufPrint(buf, "{s}", .{version.next() orelse "Uknown"}); // return try std.fmt.allocPrint(allocator, "{s}", .{version.next() orelse "Unknown"}); } fn get_bash_version(allocator: std.mem.Allocator, buf: []u8, bash_path: []const u8) ![]const u8 { const version_string = try std.process.Child.run( .{ .allocator = allocator, .argv = &.{ bash_path, "--version" }, }, ); defer allocator.free(version_string.stdout); defer allocator.free(version_string.stderr); var split_lines = std.mem.split(u8, version_string.stdout, "\n"); var version_line = std.mem.split(u8, split_lines.first(), " "); var i: usize = 0; while (version_line.next()) |word| { std.debug.print("version_line: {s}", .{word}); if (i == 3) { return try std.fmt.bufPrint(buf, "{s}", .{word}); } i += 1; } return try std.fmt.bufPrint(buf, "Unknown", .{}); } pub fn get_user(buf: []u8) ![]const u8 { const user = std.posix.getenv("USER") orelse "Unknown"; return try std.fmt.bufPrint(buf, "{s}", .{user}); } pub fn get_hostname(buf: *[std.posix.HOST_NAME_MAX]u8) ![]const u8 { const hostname = try std.posix.gethostname(&buf); return try std.fmt.bufPrint(buf, hostname, .{}); } test "get_bash_version" { var buf: [8]u8 = undefined; const bash_version = try get_bash_version(std.testing.allocator, &buf, "/run/current-system/sw/bin/bash"); try std.testing.expectEqualSlices(u8, "5.2.32(1)-release", bash_version); }