statusbar/src/main.zig
2024-03-18 12:32:14 -06:00

168 lines
5.8 KiB
Zig

const std = @import("std");
const io = std.io;
const heap = std.heap;
const json = std.json;
const battery = @import("modules/battery.zig");
const calendar = @import("modules/calendar.zig");
const display = @import("modules/display.zig");
const uptime = @import("modules/uptime.zig");
const volume = @import("modules/volume.zig");
const memory = @import("modules/memory.zig");
const loadavg = @import("modules/loadavg.zig");
const Module = @import("module.zig");
const bg_left_color = Color{ .r = 0, .g = 0, .b = 0 };
const bg_right_color = Color{ .r = 0.2, .g = 0.2, .b = 0.2 };
pub fn main() !void {
var arena = heap.ArenaAllocator.init(heap.page_allocator);
defer arena.deinit();
const stdout_file = std.io.getStdOut().writer();
var bw = std.io.bufferedWriter(stdout_file);
const stdout = bw.writer();
try stdout.print("{{\"version\":1}}\n[\n", .{});
try bw.flush();
var modules = [_]Module{
uptime.init(arena.allocator()).module,
loadavg.init(arena.allocator()).module,
memory.init(arena.allocator()).module,
volume.init(arena.allocator()).module,
display.init(arena.allocator()).module,
battery.init(arena.allocator()).module,
calendar.init(arena.allocator()).module,
};
while (true) {
// const start_time = std.time.milliTimestamp();
try stdout.print("[", .{});
const modules_len = 1 / @as(f32, @floatFromInt(modules.len));
var bg = Color{ .r = 0.0, .g = 0.0, .b = 0.0 };
for (modules, 0..) |module, idx| {
// const module_start_time = std.time.nanoTimestamp();
var output = module.getJson() catch {
const output = Module.JSON{
.full_text = " [error] ",
.background = try bg.getString(arena.allocator()),
.color = try bg.add(Color{ .r = 1, .g = 0.3, .b = 0.3 }).getString(arena.allocator()),
.separator = false,
.separator_block_width = 0,
};
try json.stringify(output, .{ .emit_null_optional_fields = false }, stdout);
try stdout.print(",", .{});
const progress = @as(f32, @floatFromInt(idx + 1)) * modules_len;
bg = bg_left_color.mix(bg_right_color, progress);
continue;
};
output.full_text = try std.fmt.allocPrint(arena.allocator(), " {s} ", .{output.full_text});
output.background = try bg.getString(arena.allocator());
var color = bg.add(Color{ .r = 0.6, .g = 0.6, .b = 0.6 });
if (output.color == null) output.color = try color.getString(arena.allocator());
output.separator = false;
output.separator_block_width = 0;
try json.stringify(output, .{ .emit_null_optional_fields = false }, stdout);
try stdout.print(",", .{});
const progress = @as(f32, @floatFromInt(idx + 1)) * modules_len;
// std.debug.print("\n{d}\n", .{progress});
bg = bg_left_color.mix(bg_right_color, progress);
// const module_end_time = std.time.nanoTimestamp();
// std.debug.print("\nmodule {d}: finished in {d}ns", .{ idx, module_end_time - module_start_time });
}
try stdout.print("],\n", .{});
// std.debug.print("\n", .{});
try bw.flush();
_ = arena.reset(.retain_capacity);
// const end_time = std.time.milliTimestamp();
// std.debug.print("\nFinished in {d}ms", .{end_time - start_time});
std.time.sleep(1000_000_000);
}
}
pub const Color = struct {
r: f32,
g: f32,
b: f32,
pub fn init(string: []const u8) !Color {
var r = try std.fmt.parseInt(u8, string[1..2], 16);
var g = try std.fmt.parseInt(u8, string[3..4], 16);
var b = try std.fmt.parseInt(u8, string[5..6], 16);
return .{
.r = @as(f32, @floatFromInt(r)) / 255,
.g = @as(f32, @floatFromInt(g)) / 255,
.b = @as(f32, @floatFromInt(b)) / 255,
};
}
pub fn getString(self: *const Color, allocator: std.mem.Allocator) ![]const u8 {
const v = self.getVector();
const x = @max(VecRGB{ 0.0, 0.0, 0.0 }, @min(v, VecRGB{ 1.0, 1.0, 1.0 }));
const y = x * VecRGB{ 255.0, 255.0, 255.0 };
const r = @as(u8, @intFromFloat(y[0]));
const g = @as(u8, @intFromFloat(y[1]));
const b = @as(u8, @intFromFloat(y[2]));
return try std.fmt.allocPrint(allocator, "#{s}{s}{s}", .{
std.fmt.fmtSliceHexLower(&[_]u8{r}),
std.fmt.fmtSliceHexLower(&[_]u8{g}),
std.fmt.fmtSliceHexLower(&[_]u8{b}),
});
}
pub fn add(a: *const Color, b: Color) Color {
const va = a.getVector();
const vb = b.getVector();
return Color.fromVector(va + vb);
}
pub fn mix(a: *const Color, b: Color, t: f32) Color {
const va = a.getVector();
const vb = b.getVector();
const vt = VecRGB{ t, t, t };
return Color.fromVector(@mulAdd(VecRGB, vb - va, vt, va));
}
fn getVector(self: *const Color) VecRGB {
return VecRGB{
self.r,
self.g,
self.b,
};
}
fn fromVector(v: VecRGB) Color {
return .{
.r = v[0],
.g = v[1],
.b = v[2],
};
}
pub const VecRGB = @Vector(3, f32);
};
pub fn getBgColor(idx: usize, override: ?[]const u8) []const u8 {
if (override) |o| return o;
return switch (idx % 2) {
0 => "#002b36",
1 => "#0e1b15",
else => "#002b36",
};
}
pub fn getFgColor(idx: usize, override: ?[]const u8) []const u8 {
if (override) |o| return o;
return switch (idx % 2) {
// 0 => "#93a1a1",
// 1 => "#d6c2d6",
else => "#",
};
}