wip: fast

This commit is contained in:
Kalle Carlbark 2024-09-16 22:08:54 +02:00
parent 42db065ac5
commit f7d243b2b7
No known key found for this signature in database
7 changed files with 231 additions and 55 deletions

View file

@ -36,6 +36,8 @@ pub fn build(b: *std.Build) void {
.target = target,
.optimize = optimize,
});
macos.linkFramework("IOKit");
macos.linkFramework("CoreFoundation");
// This declares intent for the library to be installed into the standard
// location when the user invokes the "install" step (the default step when
@ -49,8 +51,10 @@ pub fn build(b: *std.Build) void {
.target = target,
.optimize = optimize,
});
exe.addIncludePath(b.path("./include"));
exe.linkFramework("IOKIT");
exe.linkFramework("CoreFoundation");
exe.linkFramework("SystemConfiguration");
exe.root_module.addImport("vaxis", vaxis);
exe.root_module.addImport("objc", objc);

View file

@ -25,7 +25,7 @@
.dependencies = .{
.vaxis = .{
.url = "https://github.com/rockorager/libvaxis/archive/refs/heads/main.tar.gz",
.hash = "12209fb0db1467d24882f4a0fca367d25d7ef7353882270ba3b76382c185332c52ae",
.hash = "12209e3e6a758023f77c35c88723209ca78f3e8f386cef27ea73ab5ea36d6f21e14f",
},
.objc = .{
.url = "https://github.com/mitchellh/zig-objc/archive/refs/heads/main.tar.gz",

BIN
src/assets/apple-white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
src/assets/freebsd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View file

@ -5,6 +5,11 @@ const c = @cImport({
@cInclude("sys/utsname.h");
@cInclude("sys/sysctl.h");
@cInclude("sys/time.h");
@cInclude("IOKit/IOKitLib.h");
@cInclude("IOKit/ps/IOPowerSources.h");
@cInclude("IOKit/ps/IOPSKeys.h");
@cInclude("CoreFoundation/CoreFoundation.h");
@cInclude("SystemConfiguration/SystemConfiguration.h");
});
const OsVersion = struct {
name: []const u8,
@ -57,6 +62,122 @@ pub fn macos_kernel_version(allocator: std.mem.Allocator) ![]const u8 {
return buf;
}
pub fn memory_info(allocator: std.mem.Allocator) ![]const u8 {
var memsize: u64 = 0;
var memsize_size: usize = @sizeOf(u64);
if (c.sysctlbyname("hw.memsize", &memsize, @as([*c]usize, &memsize_size), null, 0) < 0) {
return error.NoMemInfo;
}
const bingb: u64 = (1024 * 1024 * 1024);
const memsize_gb: u64 = @divFloor(memsize, bingb);
return try std.fmt.allocPrint(allocator, ": {d} GiB\n", .{memsize_gb});
}
// Helper function to create CFString from Zig string
fn CFStringCreateWithCStringZig(s: []const u8) *c.__CFString {
return @constCast(c.CFStringCreateWithCString(
null, // Allocator (default: null)
s.ptr, // C string pointer
c.kCFStringEncodingUTF8, // Encoding (UTF-8)
).?);
}
pub fn get_vpn_info() !void {
const infoz: []const u8 = "infoz";
const cfstringref = CFStringCreateWithCStringZig(infoz);
const prefs = c.SCPreferencesCreate(null, cfstringref, null);
if (prefs == null) {
return error.SCPreferencesCreateError;
}
const networkServices = c.SCNetworkServiceCopyAll(prefs);
if (networkServices == null) {
return error.SCNetworkServiceCopyAllError;
}
const count = c.CFArrayGetCount(networkServices);
std.debug.print("Network Services: {d}\n", .{count});
const zero: usize = 0;
for (zero..@as(c.u_long, @intCast(count))) |index| {
const long_index = @as(c_long, @intCast(index));
const service: c.SCNetworkServiceRef = @ptrCast(c.CFArrayGetValueAtIndex(networkServices, long_index));
const serviceName = c.SCNetworkServiceGetName(service);
const bufferSize = 256;
var buffer: [bufferSize]u8 = undefined;
_ = c.CFStringGetCString(serviceName, &buffer[0], bufferSize, c.kCFStringEncodingUTF8);
const service_name = std.mem.sliceTo(buffer[0..], 0);
std.debug.print("Found VPN service: {s}\n", .{service_name});
}
//const interface = c.SCNetworkServiceGetInterface(service);
// Convert CFStringRef to C string (null-terminated)
}
pub fn get_battery_info(allocator: std.mem.Allocator) ![]const u8 {
const power_sources_info: c.CFTypeRef = c.IOPSCopyPowerSourcesInfo();
if (power_sources_info == null) {
return error.NoPowerSourcesInfo;
}
const power_sources_list = c.IOPSCopyPowerSourcesList(power_sources_info);
if (power_sources_list == null) {
c.CFRelease(power_sources_info);
return error.NoPowerSourcesList;
}
const power_source = c.IOPSGetPowerSourceDescription(power_sources_info, c.CFArrayGetValueAtIndex(power_sources_list, 0)) orelse null;
if (power_source == null) {
return error.GotNoPowerSource;
}
const name: c.CFStringRef = @ptrCast(c.CFDictionaryGetValue(power_source, CFStringCreateWithCStringZig(c.kIOPSNameKey)));
const power_type: c.CFStringRef = @ptrCast(c.CFDictionaryGetValue(power_source, CFStringCreateWithCStringZig(c.kIOPSTypeKey)));
const capacity: c.CFNumberRef = @ptrCast(c.CFDictionaryGetValue(power_source, CFStringCreateWithCStringZig(c.kIOPSCurrentCapacityKey)));
const max_capacity: c.CFNumberRef = @ptrCast(c.CFDictionaryGetValue(power_source, CFStringCreateWithCStringZig(c.kIOPSMaxCapacityKey)));
const source_state: c.CFStringRef = @ptrCast(c.CFDictionaryGetValue(power_source, CFStringCreateWithCStringZig(c.kIOPSPowerSourceStateKey)));
const time_to_empty: c.CFNumberRef = @ptrCast(c.CFDictionaryGetValue(power_source, CFStringCreateWithCStringZig(c.kIOPSTimeToEmptyKey)));
var name_buffer: [256]u8 = undefined;
var power_type_buffer: [256]u8 = undefined;
var power_source_state_buffer: [256]u8 = undefined;
var maxCapacity: c.u_int32_t = 0;
var currentCapacity: c.u_int32_t = 0;
var time_to_empty_mins: c.u_int32_t = 0;
_ = c.CFNumberGetValue(capacity, c.kCFNumberIntType, &currentCapacity);
_ = c.CFNumberGetValue(max_capacity, c.kCFNumberIntType, &maxCapacity);
_ = c.CFNumberGetValue(time_to_empty, c.kCFNumberIntType, &time_to_empty_mins);
_ = c.CFStringGetCString(name, &name_buffer[0], 256, c.kCFStringEncodingUTF8);
_ = c.CFStringGetCString(power_type, &power_type_buffer[0], 256, c.kCFStringEncodingUTF8);
_ = c.CFStringGetCString(source_state, &power_source_state_buffer[0], 256, c.kCFStringEncodingUTF8);
const power_source_state = std.mem.sliceTo(power_source_state_buffer[0..], 0);
const percent = (currentCapacity * 100) / maxCapacity;
const hours = time_to_empty_mins / 60;
const minutes = time_to_empty_mins % 60;
if (std.mem.eql(u8, power_source_state, "Battery Power")) {
if (time_to_empty_mins < 0) {
return try std.fmt.allocPrint(allocator, ": {d}%, ?m left\n", .{ percent, hours, minutes });
} else {
return try std.fmt.allocPrint(allocator, ": {d}%, {d}h:{d}m left\n", .{ percent, hours, minutes });
}
} else {
return try std.fmt.allocPrint(allocator, ": {d}%, {s}\n", .{ percent, "charging" });
}
}
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;

View file

@ -1,4 +1,5 @@
const std = @import("std");
const builtin = @import("builtin");
const vaxis = @import("vaxis");
const root = @import("root.zig");
const macos = @import("macos.zig");
@ -6,6 +7,9 @@ const sys = @import("sys.zig");
const log = std.log.scoped(.main);
const apple_logo = @embedFile("assets/apple-white.png");
const freebsd = @embedFile("assets/freebsd.png");
const Event = union(enum) {
key_press: vaxis.Key,
winsize: vaxis.Winsize,
@ -32,8 +36,13 @@ pub fn main() !void {
vx.caps.unicode = .unicode;
vx.caps.kitty_graphics = true;
const os = try macos.macos_version(allocator);
defer allocator.free(os);
const battery = try macos.get_battery_info(allocator);
defer allocator.free(battery);
// _ = try macos.get_vpn_info();
// const os = try macos.macos_version(allocator);
const os = try sys.get_os_version(allocator);
defer allocator.free(os.text);
const kernel = try macos.macos_kernel_version(allocator);
defer allocator.free(kernel);
const uptime = try macos.macos_uptime(allocator);
@ -42,36 +51,43 @@ pub fn main() !void {
defer allocator.free(cpu);
const current_shell = try sys.get_shell(allocator);
defer allocator.free(current_shell);
const memory = try macos.memory_info(allocator);
defer allocator.free(memory);
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");
try tty.anyWriter().writeAll(vaxis.ctlseqs.unicode_set);
defer vx.queryTerminalSend(tty.anyWriter()) catch {};
defer tty.anyWriter().writeAll(vaxis.ctlseqs.unicode_reset) catch {};
var buf_writer = tty.bufferedWriter();
const writer = buf_writer.writer().any();
// try writer.writeAll(vaxis.ctlseqs.unicode_set);
// defer vx.queryTerminalSend(writer) catch {};
// defer writer.writeAll(vaxis.ctlseqs.unicode_reset) catch {};
// defer tty.deinit();
const winsize: vaxis.Winsize = try vaxis.Tty.getWinsize(tty.fd);
try vx.resize(allocator, tty.anyWriter(), winsize);
try vx.resize(allocator, writer, winsize);
const win = vx.window();
win.clear();
// win.hideCursor();
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";
var image: vaxis.Image = undefined;
switch (builtin.os.tag) {
.macos => {
image = try vx.loadImage(allocator, tty.anyWriter(), .{ .mem = apple_logo });
},
.freebsd => {
image = try vx.loadImage(allocator, writer, .{ .mem = freebsd });
},
else => @compileError("unsupported os"),
}
const koko = try vx.loadImage(allocator, writer, .{ .path = logo });
const dims = try koko.cellSize(win);
const dims = try image.cellSize(win);
// const cursor_row = vx.state.cursor.row;
const logo_win = win.child(.{
.y_off = 0,
.y_off = 2,
.x_off = 0,
.width = .{
.limit = dims.cols + 1,
@ -79,15 +95,8 @@ pub fn main() !void {
.height = .{
.limit = dims.rows + 1,
},
// .border = .{
// .where = .right,
// .glyphs = .single_rounded,
// .style = .{
// .fg = .{ .index = 15 },
// },
// },
});
// const logo_text_win = win.child(.{ .y_off = dims.rows });
var user_buf: [64]u8 = undefined;
const user = try sys.get_user(&user_buf);
var hostname_buf: [std.posix.HOST_NAME_MAX]u8 = undefined;
@ -96,7 +105,7 @@ pub fn main() !void {
// const logo_win = win.child(.{ .y_off = 0, .x_off = 0 });
const border_locations = vaxis.Window.BorderOptions.Locations{
.top = true,
.bottom = true,
.bottom = false,
};
const whoami_win = win.child(.{
@ -106,7 +115,7 @@ pub fn main() !void {
.y_off = 1,
.x_off = dims.cols + 1,
.width = .{ .limit = 40 },
.height = .{ .limit = 10 },
.height = .{ .limit = 16 },
.border = .{
.where = .{
.other = border_locations,
@ -118,32 +127,23 @@ pub fn main() !void {
},
});
// 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);
// var img1 = try vaxis.zigimg.Image.fromFilePath(allocator, "/Users/kc/Sync/Images/apple-white.png");
// defer img1.deinit();
// const koko = try vx.transmitImage(allocator, tty.anyWriter(), &img1, .png);
// win.hideCursor();
// win.showCursor(10, 1);
const whoami_info = [_]vaxis.Cell.Segment{
.{ .text = user, .style = .{
.fg = .{
.index = 3,
.index = 7,
},
} },
.{ .text = "@", .style = .{
.fg = .{
.index = 7,
.index = 15,
},
.bold = true,
} },
.{ .text = hostname, .style = .{
.fg = .{
.index = 5,
.index = 7,
},
} },
};
@ -157,7 +157,7 @@ pub fn main() !void {
.bold = true,
},
},
.{ .text = os },
os,
.{
.text = " Kernel",
.style = .{
@ -188,6 +188,16 @@ pub fn main() !void {
},
},
.{ .text = cpu },
.{
.text = " Memory",
.style = .{
.fg = .{
.index = 7,
},
.bold = true,
},
},
.{ .text = memory },
.{
.text = " Shell",
.style = .{
@ -208,6 +218,23 @@ pub fn main() !void {
},
},
.{ .text = current_terminal },
.{
.text = " Battery",
.style = .{
.fg = .{
.index = 7,
},
.bold = true,
},
},
.{
.text = battery,
// .style = .{
// .fg = .{
// .index = 2,
// },
// },
},
.{
.text = " ▂▂▂",
.style = .{
@ -329,20 +356,23 @@ pub fn main() !void {
},
},
.{
.text = " ▂▂▂",
.text = " ▂▂▂\n\n\n",
.style = .{
.fg = .{
.index = 15,
},
},
},
.{
.text = " ",
},
};
// const logo_text = [_]vaxis.Cell.Segment{
// .{
// .text = " hello",
// },
// };
try koko.draw(logo_win, .{});
try image.draw(logo_win, .{});
// _ = try logo_text_win.print(&logo_text, .{});
// try root.kitty_image_inline_copy(allocator, tty.anyWriter(), "/Users/kc/Sync/Images/apple-dark.png");
@ -353,7 +383,7 @@ pub fn main() !void {
// try tty.anyWriter().print("\x1b[{d}A\x1b[9999999D", .{winsize.rows});
// try tty.anyWriter().writeAll("\x1b[1J");
try vx.prettyPrint(writer);
// try logo_win.print();
// const dimensions = try koko.cellSize(win);
// const image = try vx.transmitLocalImagePath(allocator, tty.anyWriter(), "/Users/kc/Sync/Images/apple-white.png", dimensions.rows, dimensions.cols, .file, .png);
@ -362,8 +392,9 @@ pub fn main() !void {
// try image.draw(win, .{});
// try vx.render(tty.anyWriter());
// win.clear();
try vx.prettyPrint(tty.anyWriter());
try buf_writer.flush();
// try vx.queryTerminalSend(tty.anyWriter());
// Clear from cursor to beginning of the screen
@ -381,7 +412,6 @@ pub fn main() !void {
// // vaxis.Image.DrawOptions{ .clip_region = .{ .x = 0, .y = 0 } },
// };
// win.hideCursor();
// const dims = try image[0].cellSize(win);
// try vx.render(writer);

View file

@ -1,4 +1,20 @@
const std = @import("std");
const builtin = @import("builtin");
const vaxis = @import("vaxis");
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) ![]const u8 {
const shell_env = std.posix.getenv("SHELL") orelse "Unknown";
@ -14,7 +30,7 @@ pub fn get_shell(allocator: std.mem.Allocator) ![]const u8 {
} 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});
return 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(
.{
@ -27,23 +43,28 @@ pub fn get_shell(allocator: std.mem.Allocator) ![]const u8 {
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_os_version(allocator: std.mem.Allocator) !vaxis.Cell.Segment {
switch (builtin.os.tag) {
.macos => {
return .{
.text = try macos.macos_version(allocator),
};
},
else => return .{ .text = "" },
}
}
pub fn get_terminal(buf: []u8) ![]const u8 {
const term_program = std.posix.getenv("TERM_PROGRAM") orelse "Unknown";
if (std.mem.eql(u8, term_program, "ghostty")) {
return try std.fmt.bufPrint(buf, ": {s} 󰊠\n", .{term_program});
}
return try std.fmt.bufPrint(buf, ": {s}\n", .{term_program});
}