wip: colors

This commit is contained in:
Kalle Carlbark 2024-08-26 22:38:49 +02:00
parent 2d344a4efb
commit 0d1b3f5b7d
No known key found for this signature in database
5 changed files with 347 additions and 20 deletions

View file

@ -49,6 +49,7 @@ pub fn build(b: *std.Build) void {
.target = target,
.optimize = optimize,
});
exe.addIncludePath(b.path("./include"));
exe.root_module.addImport("vaxis", vaxis);
exe.root_module.addImport("objc", objc);

19
src/detect_colors.zig Normal file
View file

@ -0,0 +1,19 @@
const std = @import("std");
pub fn detect_dark_mode() bool {
const home_directory = detect_home_directory();
var dark_mode = std.fs.cwd().createFile(home_directory ++ "/.dark-mode", .{ .exclusive = true }) catch |e|
switch (e) {
error.PathAlreadyExists => {
return true;
},
else => {},
};
defer dark_mode.close();
return false;
}
fn detect_home_directory() []const u8 {
return std.posix.getenv("HOME") orelse "/tmp";
}

View file

@ -1,7 +1,10 @@
const objc = @import("objc");
const std = @import("std");
const utsname = @cImport({
const c = @cImport({
@cInclude("sys/types.h");
@cInclude("sys/utsname.h");
@cInclude("sys/sysctl.h");
@cInclude("sys/time.h");
});
const OsVersion = struct {
name: []const u8,
@ -34,22 +37,65 @@ pub fn macos_version(allocator: std.mem.Allocator) ![]const u8 {
const koko = info.msgSend(NSOperatingSystemVersion, "operatingSystemVersion", .{});
const buf = try std.fmt.allocPrint(allocator, " OS: macOS {s} {d}.{d}.{d}\n", .{ version_to_name(koko), koko.major, koko.minor, koko.patch });
const buf = try std.fmt.allocPrint(allocator, ": macOS {s} {d}.{d}.{d}\n", .{ version_to_name(koko), koko.major, koko.minor, koko.patch });
return buf;
}
pub fn macos_kernel_version(allocator: std.mem.Allocator) ![]const u8 {
var name: utsname.struct_utsname = undefined;
var name: c.struct_utsname = undefined;
if (utsname.uname(&name) != 0) {
if (c.uname(&name) != 0) {
return error.UnameFailed;
}
const sysname = std.mem.sliceTo(name.sysname[0..], 0);
const version = std.mem.sliceTo(name.release[0..], 0);
const buf = try std.fmt.allocPrint(allocator, " Kernel: {s} {s}\n", .{ sysname, version });
const buf = try std.fmt.allocPrint(allocator, ": {s} {s}\n", .{ sysname, version });
return buf;
}
pub fn macos_cpu_info(allocator: std.mem.Allocator) ![]const u8 {
var cpu_brand: [128]u8 = undefined;
var cpu_brand_size: usize = cpu_brand.len;
var cpu_cores: c_int = 0;
var cpu_cores_size: usize = @sizeOf(c_int);
if (c.sysctlbyname("machdep.cpu.core_count", &cpu_cores, @as([*c]usize, &cpu_cores_size), null, 0) < 0) {
return error.SysctlFailed;
}
if (c.sysctlbyname("machdep.cpu.brand_string", &cpu_brand, &cpu_brand_size, null, 0) < 0) {
return error.SysctlFailed;
}
// if (c.sysctlbyname("hw.cpufrequency", &))
const buf = try std.fmt.allocPrint(allocator, ": {s} ({d} cores)\n", .{ cpu_brand[0..cpu_brand_size], cpu_cores });
return buf;
}
pub fn macos_uptime(allocator: std.mem.Allocator) ![]const u8 {
var mib: [2]c.integer_t = [_]c.integer_t{ c.CTL_KERN, c.KERN_BOOTTIME };
var boottime: c.struct_timeval = undefined;
var size: u64 = @sizeOf(c.struct_timeval);
if (c.sysctl(&mib[0], 2, &boottime, @as([*c]usize, &size), null, 0) < 0) {
return error.SysctlFailed;
}
var now: c.time_t = 0;
_ = c.time(&now);
const uptime_seconds: i64 = now - boottime.tv_sec;
const days = @divFloor(uptime_seconds, (24 * 60 * 60));
const hours = @divFloor(@rem(uptime_seconds, (24 * 60 * 60)), (60 * 60));
const minutes = @divFloor(@rem(uptime_seconds, (60 * 60)), 60);
const buf = try std.fmt.allocPrint(allocator, ": {d} days, {d} hours, {d} mins\n", .{ days, hours, minutes });
return buf;
}

View file

@ -2,6 +2,7 @@ const std = @import("std");
const vaxis = @import("vaxis");
const root = @import("root.zig");
const macos = @import("macos.zig");
const sys = @import("sys.zig");
const log = std.log.scoped(.main);
@ -35,6 +36,15 @@ pub fn main() !void {
defer allocator.free(os);
const kernel = try macos.macos_kernel_version(allocator);
defer allocator.free(kernel);
const uptime = try macos.macos_uptime(allocator);
defer allocator.free(uptime);
const cpu = try macos.macos_cpu_info(allocator);
defer allocator.free(cpu);
const current_shell = try sys.get_shell(allocator);
defer allocator.free(current_shell);
var term_buf: [64]u8 = undefined;
const current_terminal = try sys.get_terminal(&term_buf);
// try tty.anyWriter().writeAll("\x1bc");
// try tty.anyWriter().writeAll("\x1b[1;1H");
@ -49,17 +59,66 @@ pub fn main() !void {
const win = vx.window();
win.clear();
const koko = try vx.loadImage(allocator, writer, .{ .path = "/Users/kc/Sync/Images/apple-white.png" });
var logo: []const u8 = "/Users/kc/Sync/Images/apple-dark.png";
if (try is_dark_mode(allocator)) {
logo = "/Users/kc/Sync/Images/apple-white.png";
}
const koko = try vx.loadImage(allocator, writer, .{ .path = logo });
const dims = try koko.cellSize(win);
// const cursor_row = vx.state.cursor.row;
const logo_win = win.child(.{ .y_off = 0, .x_off = 0, .width = .{ .limit = dims.cols + 1 }, .height = .{ .limit = dims.rows + 1 }, .border = .{ .where = .right, .glyphs = .single_rounded, .style = .{ .fg = .{ .index = 15 } } } });
// const logo_win = win.child(.{ .y_off = 0, .x_off = 0 });
const info_win = win.child(.{ .y_off = 0, .x_off = dims.cols + 1, .width = .{ .limit = 40 }, .height = .{ .limit = 20 } });
const logo_win = win.child(.{
.y_off = 0,
.x_off = 0,
.width = .{
.limit = dims.cols + 1,
},
.height = .{
.limit = dims.rows + 1,
},
// .border = .{
// .where = .right,
// .glyphs = .single_rounded,
// .style = .{
// .fg = .{ .index = 15 },
// },
// },
});
var user_buf: [64]u8 = undefined;
const user = try sys.get_user(&user_buf);
var hostname_buf: [std.posix.HOST_NAME_MAX]u8 = undefined;
const hostname = try std.posix.gethostname(&hostname_buf);
logo_win.clear();
info_win.clear();
// const logo_win = win.child(.{ .y_off = 0, .x_off = 0 });
const border_locations = vaxis.Window.BorderOptions.Locations{
.top = true,
.bottom = true,
};
const whoami_win = win.child(.{
.x_off = dims.cols + 1,
});
const info_win = win.child(.{
.y_off = 1,
.x_off = dims.cols + 1,
.width = .{ .limit = 40 },
.height = .{ .limit = 6 },
.border = .{
.where = .{
.other = border_locations,
},
.glyphs = .single_rounded,
.style = .{
.fg = .{ .index = 15 },
},
},
});
// logo_win.clear();
// info_win.clear();
var result: vaxis.Window.PrintResult = .{ .col = 0, .row = 0, .overflow = false };
// try tty.anyWriter().writeAll(vaxis.ctlseqs.kitty_graphics_query);
@ -69,21 +128,91 @@ pub fn main() !void {
// win.hideCursor();
// win.showCursor(10, 1);
const whoami_info = [_]vaxis.Cell.Segment{
.{ .text = user, .style = .{
.fg = .{
.index = 3,
},
} },
.{ .text = "@", .style = .{
.fg = .{
.index = 7,
},
.bold = true,
} },
.{ .text = hostname, .style = .{
.fg = .{
.index = 5,
},
} },
};
const system_info = [_]vaxis.Cell.Segment{
.{
.text = " OS",
.style = .{
.fg = .{
.index = 2,
},
.bold = true,
},
},
.{ .text = os },
.{
.text = " Kernel",
.style = .{
.fg = .{
.index = 2,
},
.bold = true,
},
},
.{ .text = kernel },
// .{ .text = " Kernel: lalal\n" },
// .{ .text = " Kernel: lalal\n" },
// .{ .text = " Kernel: lalal\n" },
// .{ .text = " Kernel: lalal\n" },
// .{ .text = " Kernel: lalal\n" },
// .{ .text = " Kernel: lalal\n" },
// .{ .text = "Kernel: lalal\n" },
// .{ .text = "Kernel: lalal\n" },
.{
.text = " Uptime",
.style = .{
.fg = .{
.index = 2,
},
.bold = true,
},
},
.{ .text = uptime },
.{
.text = " CPU",
.style = .{
.fg = .{
.index = 2,
},
.bold = true,
},
},
.{ .text = cpu },
.{
.text = " Shell",
.style = .{
.fg = .{
.index = 2,
},
.bold = true,
},
},
.{ .text = current_shell },
.{
.text = " Terminal",
.style = .{
.fg = .{
.index = 2,
},
.bold = true,
},
},
.{ .text = current_terminal },
};
try koko.draw(logo_win, .{});
// try root.kitty_image_inline_copy(allocator, tty.anyWriter(), "/Users/kc/Sync/Images/apple-dark.png");
result = try whoami_win.print(&whoami_info, .{ .wrap = .word });
result = try info_win.print(&system_info, .{ .wrap = .word });
// printf '\e[%sA\e[9999999D' "${lines:-0}"
// try tty.anyWriter().print("\x1b[{d}A\x1b[9999999D", .{winsize.rows});
@ -98,7 +227,7 @@ pub fn main() !void {
// try image.draw(win, .{});
// try vx.render(tty.anyWriter());
win.clear();
// win.clear();
try buf_writer.flush();
// try vx.queryTerminalSend(tty.anyWriter());
@ -129,6 +258,26 @@ pub fn main() !void {
// std.time.sleep(10000000);
}
fn is_dark_mode(allocator: std.mem.Allocator) !bool {
const home_directory = detect_home_directory();
const dark_mode_file_path = try std.fmt.allocPrint(allocator, "{s}/.dark-mode", .{home_directory});
defer allocator.free(dark_mode_file_path);
const dark_mode = std.fs.cwd().createFile(dark_mode_file_path, .{ .exclusive = true }) catch |err|
switch (err) {
error.PathAlreadyExists => return true,
else => {
return false;
},
};
dark_mode.close();
return false;
}
fn detect_home_directory() []const u8 {
return std.posix.getenv("HOME") orelse "/tmp";
}
test "simple test" {
var list = std.ArrayList(i32).init(std.testing.allocator);
defer list.deinit(); // try commenting this out and see if zig detects the memory leak!

112
src/sys.zig Normal file
View file

@ -0,0 +1,112 @@
const std = @import("std");
pub fn get_shell(allocator: std.mem.Allocator) ![]const u8 {
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 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 try std.fmt.allocPrint(allocator, ": {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 try std.fmt.allocPrint(allocator, ": {s}\n", .{version.stdout});
}
// const version = try std.process.Child.run(.{
// .allocator = allocator,
// .argv = &.{ shell_env, &version_flag },
// });
// defer allocator.free(version.stdout);
// defer allocator.free(version.stderr);
// if (std.mem.eql(u8, "zsh", shell)) {
// std.debug.print("shell: {s}\n", .{shell});
// }
return try std.fmt.allocPrint(allocator, ": {s}\n", .{shell_env});
}
pub fn get_terminal(buf: []u8) ![]const u8 {
const term_program = std.posix.getenv("TERM_PROGRAM") orelse "Unknown";
return 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);
}