wip: colors
This commit is contained in:
parent
2d344a4efb
commit
0d1b3f5b7d
5 changed files with 347 additions and 20 deletions
|
@ -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
19
src/detect_colors.zig
Normal 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";
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
179
src/main.zig
179
src/main.zig
|
@ -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
112
src/sys.zig
Normal 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);
|
||||
}
|
Loading…
Reference in a new issue