Comment more of the code, fix and use comptimeColour more.
This commit is contained in:
parent
7203cf1904
commit
fa00747fca
|
@ -9,6 +9,7 @@ pub fn build(b: *Builder) void {
|
|||
"disable_colour",
|
||||
"no colour",
|
||||
) orelse false;
|
||||
|
||||
exe.addBuildOption(bool, "disable_colour", disable_colour);
|
||||
const terminal_version = b.option(
|
||||
bool,
|
||||
|
@ -22,6 +23,14 @@ pub fn build(b: *Builder) void {
|
|||
"use debug allocator for testing",
|
||||
) orelse false;
|
||||
exe.addBuildOption(bool, "debug_allocator", debug_allocator);
|
||||
const weather_location = b.option(
|
||||
[]const u8,
|
||||
"weather_location",
|
||||
"weather_location",
|
||||
) orelse "\"\"";
|
||||
exe.addBuildOption([]const u8, "weather_location", weather_location);
|
||||
|
||||
|
||||
|
||||
//exe.strip = true;
|
||||
exe.addPackage(.{
|
||||
|
|
|
@ -15,6 +15,7 @@ pub const Bar = struct {
|
|||
out_file: std.fs.File,
|
||||
pub fn start(self: *Bar) !void {
|
||||
self.running = true;
|
||||
// i3bar/swaybar requires starting with this to get click events.
|
||||
if (!terminal_version) try self.out_file.writer().writeAll("{\"version\": 1,\"click_events\": true}\n[\n");
|
||||
for (self.widgets) |w| {
|
||||
try self.infos.append(try self.dupe_info(w.initial_info()));
|
||||
|
@ -24,8 +25,10 @@ pub const Bar = struct {
|
|||
var thread = try std.Thread.spawn(w, Widget.start);
|
||||
}
|
||||
var thread = try std.Thread.spawn(self, Bar.process);
|
||||
// TODO: wait for kill signal to kill bar instead of waiting for thread.
|
||||
thread.wait();
|
||||
self.running = false;
|
||||
// Wait for most widgets to stop.
|
||||
std.time.sleep(1000 * std.time.ns_per_ms);
|
||||
for (self.infos.items) |info| {
|
||||
try self.free_info(info);
|
||||
|
@ -34,6 +37,7 @@ pub const Bar = struct {
|
|||
}
|
||||
|
||||
inline fn print_i3bar_infos(self: *Bar) !void {
|
||||
// Serialize all bar items and put on stdout.
|
||||
try self.out_file.writer().writeAll("[");
|
||||
for (self.infos.items) |info, i| {
|
||||
try std.json.stringify(info, .{}, self.out_file.writer());
|
||||
|
@ -46,6 +50,7 @@ pub const Bar = struct {
|
|||
}
|
||||
|
||||
inline fn print_terminal_infos(self: *Bar) !void {
|
||||
// For terminal we just need to directly print.
|
||||
for (self.infos.items) |info, i| {
|
||||
try self.out_file.writer().writeAll(info.full_text);
|
||||
if (i < self.infos.items.len - 1) {
|
||||
|
@ -68,35 +73,50 @@ pub const Bar = struct {
|
|||
}
|
||||
|
||||
inline fn terminal_input_process(self: *Bar) !void {
|
||||
// TODO: make work on other OSes other than xterm compatable terminals.
|
||||
|
||||
// Write to stdout that we want to recieve all terminal click events.
|
||||
try self.out_file.writer().writeAll("\u{001b}[?1000;1006;1015h");
|
||||
|
||||
var termios = try os.tcgetattr(0);
|
||||
// Set terminal to raw mode so that all input goes directly into stdin.
|
||||
termios.iflag &= ~@as(
|
||||
os.tcflag_t,
|
||||
os.IGNBRK | os.BRKINT | os.PARMRK | os.ISTRIP |
|
||||
os.INLCR | os.IGNCR | os.ICRNL | os.IXON,
|
||||
);
|
||||
// Disable echo so that you don't see mouse events in terminal.
|
||||
termios.lflag |= ~@as(os.tcflag_t, (os.ECHO | os.ICANON));
|
||||
termios.lflag &= os.ISIG;
|
||||
|
||||
// Set terminal attributes.
|
||||
// TODO: reset on bar end.
|
||||
try os.tcsetattr(0, .FLUSH, termios);
|
||||
|
||||
while (true) {
|
||||
var line_buffer: [128]u8 = undefined;
|
||||
|
||||
// 0x1b is the ESC key which is used for sending and recieving events to xterm terminals.
|
||||
const line_opt = try std.io.getStdIn().inStream().readUntilDelimiterOrEof(&line_buffer, 0x1b);
|
||||
if (line_opt) |l| {
|
||||
// I honestly have no idea what this does but I assume that it checks
|
||||
// that this is the right event?
|
||||
if (l.len < 2) continue;
|
||||
var it = std.mem.tokenize(l, ";");
|
||||
// First number is just the mouse event, skip processing it for now.
|
||||
// TODO: map mouse click and scroll events to the right enum value.
|
||||
_ = it.next();
|
||||
const n = try std.fmt.parseInt(u64, it.next().?, 10);
|
||||
const click_x_position = try std.fmt.parseInt(u64, it.next().?, 10);
|
||||
var y = it.next().?;
|
||||
// This makes it so it only works on the end of a click not the start
|
||||
// preventing a single click pressing the button twice.
|
||||
if (y[y.len - 1] == 'm') continue;
|
||||
|
||||
var xe: u64 = 0;
|
||||
var current_info_line_length: u64 = 0;
|
||||
for (self.infos.items) |infoItem, index| {
|
||||
// Because the terminal output contains colour codes, we need to strip them.
|
||||
// To do this we only count the number of characters that are actually printed.
|
||||
var isEscape: bool = false;
|
||||
for (infoItem.full_text) |char| {
|
||||
// Skip all of the escape codes.
|
||||
if (char == 0x1b) {
|
||||
isEscape = true;
|
||||
continue;
|
||||
|
@ -108,18 +128,20 @@ pub const Bar = struct {
|
|||
isEscape = false;
|
||||
continue;
|
||||
}
|
||||
xe = xe + 1;
|
||||
// If we get here, it is the start of some amount of actual printed characters.
|
||||
current_info_line_length = current_info_line_length + 1;
|
||||
}
|
||||
if (n <= xe) {
|
||||
// Get the first widget that the click is in.
|
||||
if (click_x_position <= current_info_line_length) {
|
||||
for (self.widgets) |w| {
|
||||
if (std.mem.eql(u8, w.name(), infoItem.name)) {
|
||||
w.mouse_event(.{ .button = .LeftClick }) catch {};
|
||||
}
|
||||
}
|
||||
//std.debug.print("Info Item Clicky{}\n", .{infoItem.name});
|
||||
break;
|
||||
}
|
||||
xe = xe + 1;
|
||||
// Compensate for the | seporator on the terminal.
|
||||
current_info_line_length = current_info_line_length + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,26 +157,40 @@ pub const Bar = struct {
|
|||
if (line_opt) |l| {
|
||||
var line = l;
|
||||
if (std.mem.eql(u8, line, "[")) continue;
|
||||
// Prevention from crashing when running via `zig build run` when pressing enter key.
|
||||
if (line.len == 0) continue;
|
||||
// Why do you even do this i3bar?
|
||||
// Why cant you just send one single {} without a comma at start.
|
||||
// This is stupid and I don't get it, maybe if you were streaming the data
|
||||
// instead of looping and getting it, maybe then it would make more sense?
|
||||
// Anyway this just strips off the prefix of ',' so I can parse the json.
|
||||
if (line[0] == ',') line = line[1..line.len];
|
||||
const parseOptions = std.json.ParseOptions{ .allocator = allocator };
|
||||
const data = try std.json.parse(MouseEvent, &std.json.TokenStream.init(line), parseOptions);
|
||||
// TODO: maybe make a function for getting the widget or widget index by name?
|
||||
// We do use this patern a lot in this code.
|
||||
for (self.widgets) |w| {
|
||||
if (std.mem.eql(u8, w.name(), data.name)) {
|
||||
w.mouse_event(data) catch {};
|
||||
}
|
||||
}
|
||||
// If mouse_event needs to store the event for after the call is finished,
|
||||
// it should do it by itself, this just keeps the lifetime of the event to bare minimum.
|
||||
// Free the memory allocated by the MouseEvent struct.
|
||||
std.json.parseFree(MouseEvent, data, parseOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process(self: *Bar) !void {
|
||||
// Right now this is what we do for the debug allocator for testing memory usage.
|
||||
// If it the best code? Heck no but until we can gracefully ^C the program
|
||||
// this is the best we can do.
|
||||
if (debug_allocator) {
|
||||
std.time.sleep(std.time.ns_per_ms * 2000 * 5);
|
||||
if (true) return;
|
||||
}
|
||||
|
||||
// TODO: log errors.
|
||||
if (terminal_version) {
|
||||
self.terminal_input_process() catch {};
|
||||
} else {
|
||||
|
@ -162,8 +198,11 @@ pub const Bar = struct {
|
|||
}
|
||||
}
|
||||
pub fn keep_running(self: *Bar) bool {
|
||||
// TODO: maybe rename this function to something more descriptive?
|
||||
return self.running;
|
||||
}
|
||||
|
||||
/// This frees the name and text fields of a Info struct.
|
||||
fn free_info(self: *Bar, info: Info) !void {
|
||||
self.allocator.free(info.name);
|
||||
self.allocator.free(info.full_text);
|
||||
|
@ -180,10 +219,10 @@ pub const Bar = struct {
|
|||
return Info{
|
||||
.name = new_name,
|
||||
.full_text = new_text,
|
||||
.markup = "pango",
|
||||
.markup = "pango", // setting markup to pango all the time seems OK for perf, no reason not to.
|
||||
};
|
||||
}
|
||||
|
||||
/// Add a Info to the bar.
|
||||
pub fn add(self: *Bar, info: Info) !void {
|
||||
const lock = self.items_mutex.acquire();
|
||||
defer lock.release();
|
||||
|
@ -202,7 +241,7 @@ pub const Bar = struct {
|
|||
}
|
||||
};
|
||||
|
||||
pub fn InitBar(allocator: *std.mem.Allocator) Bar {
|
||||
pub fn initBar(allocator: *std.mem.Allocator) Bar {
|
||||
return Bar{
|
||||
.allocator = allocator,
|
||||
.widgets = undefined,
|
||||
|
|
|
@ -28,6 +28,7 @@ const TerminalYellowColour = "\u{001b}[33m";
|
|||
const TerminalGreenColour = "\u{001b}[32m";
|
||||
const TerminalPurpleColour = "\u{001b}[35m";
|
||||
|
||||
/// This colours a string but at comptime.
|
||||
pub fn comptimeColour(comptime clr: []const u8, comptime str: []const u8) []const u8 {
|
||||
if (disable_colour) return str;
|
||||
|
||||
|
@ -38,7 +39,7 @@ pub fn comptimeColour(comptime clr: []const u8, comptime str: []const u8) []cons
|
|||
return "<span color=\"" ++ clr ++ "\">" ++ str ++ "</span>";
|
||||
}
|
||||
} else {
|
||||
var colourText: []const u8 = "";
|
||||
comptime var colourText: []const u8 = "";
|
||||
if (eql(u8, clr, "text")) {
|
||||
colourText = if (!terminal_version) TextColour else TerminalTextColour;
|
||||
} else if (eql(u8, clr, "dark")) {
|
||||
|
@ -61,13 +62,17 @@ pub fn comptimeColour(comptime clr: []const u8, comptime str: []const u8) []cons
|
|||
colourText = if (!terminal_version) GreenColour else TerminalGreenColour;
|
||||
} else if (eql(u8, clr, "purple")) {
|
||||
colourText = if (!terminal_version) PurpleColour else TerminalPurpleColour;
|
||||
} else {
|
||||
@compileError("colour not found");
|
||||
}
|
||||
if (colourText.len == 0) {
|
||||
unreachable;
|
||||
}
|
||||
return comptimeColour(colourText, str);
|
||||
}
|
||||
}
|
||||
|
||||
/// This colours a dynamic string at runtime.
|
||||
/// It may make more than one allocation,
|
||||
/// so put it on a ArenaAllocator so you can free what else it allocates.
|
||||
pub fn colour(alloc: *std.mem.Allocator, clr: []const u8, str: []const u8) ![]const u8 {
|
||||
if (disable_colour) return str;
|
||||
|
||||
|
|
|
@ -18,19 +18,20 @@ pub fn main() !void {
|
|||
var allocator: *std.mem.Allocator = undefined;
|
||||
var dbgAlloc: *DebugAllocator = undefined;
|
||||
if (debug_allocator) {
|
||||
// Warning that DebugAllocator can get a little crashy.
|
||||
dbgAlloc = &DebugAllocator.init(std.heap.page_allocator, 8192 * 8192);
|
||||
allocator = &dbgAlloc.allocator;
|
||||
} else {
|
||||
allocator = std.heap.page_allocator;
|
||||
}
|
||||
var bar = barImpl.InitBar(allocator);
|
||||
var bar = barImpl.initBar(allocator);
|
||||
var br = Bar.init(&bar);
|
||||
|
||||
const widgets = [_]*Widget{
|
||||
//&Widget.init(&textWidget.New("owo", "potato")), // 4KiB
|
||||
//&Widget.init(&textWidget.New("uwu", "tomato")), // 4KiB
|
||||
&Widget.init(&memoryWidget.New(&br)), // 4.08KiB
|
||||
&Widget.init(&weatherWidget.New(allocator, &br, "Stockholm")), // 16.16KiB
|
||||
&Widget.init(&weatherWidget.New(allocator, &br, @import("build_options").weather_location)), // 16.16KiB
|
||||
&Widget.init(&batteryWidget.New(allocator, &br)), // 12.11KiB
|
||||
&Widget.init(&timeWidget.New(allocator, &br)), // 32.46KiB
|
||||
};
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
|
||||
/// A LoopingCounter is *extremely* helpful when making clickable widgets
|
||||
/// that have different data to show and loops around.
|
||||
pub fn LoopingCounter(
|
||||
comptime max_number: comptime_int,
|
||||
) type {
|
||||
|
@ -24,6 +26,7 @@ pub fn LoopingCounter(
|
|||
};
|
||||
}
|
||||
|
||||
// Woot we actually have some god damn tests in here.
|
||||
test "looping test" {
|
||||
var lc = LoopingCounter(3).init();
|
||||
testing.expect(lc.get() == 0);
|
||||
|
|
|
@ -5,6 +5,7 @@ const fs = std.fs;
|
|||
const cwd = fs.cwd;
|
||||
const colour = @import("../../formatting/colour.zig").colour;
|
||||
const MouseEvent = @import("../../types/mouseevent.zig");
|
||||
const comptimeColour = @import("../../formatting/colour.zig").comptimeColour;
|
||||
|
||||
pub const PowerPaths = struct {
|
||||
status_path: []const u8 = "",
|
||||
|
@ -14,7 +15,9 @@ pub const PowerPaths = struct {
|
|||
voltage_now_path: []const u8 = "",
|
||||
};
|
||||
|
||||
pub fn read_file_to_unsigned_int64(path: []const u8) u64 {
|
||||
pub fn readFileToUnsignedInt64(path: []const u8) u64 {
|
||||
// Calculate the max length of a u64 encoded as a string at comptime
|
||||
// adding 1 for newline and 1 for good luck.
|
||||
var buffer: [std.math.log10(std.math.maxInt(u64)) + 2]u8 = undefined;
|
||||
var file = fs.cwd().openFile(path, .{}) catch return 0;
|
||||
defer file.close();
|
||||
|
@ -22,7 +25,7 @@ pub fn read_file_to_unsigned_int64(path: []const u8) u64 {
|
|||
return std.fmt.parseInt(u64, buffer[0 .. siz - 1], 10) catch return 0;
|
||||
}
|
||||
|
||||
pub fn read_file(path: []const u8) ![]const u8 {
|
||||
pub fn readFile(path: []const u8) ![]const u8 {
|
||||
var buffer: [128]u8 = undefined;
|
||||
var file = try fs.cwd().openFile(path, .{});
|
||||
defer file.close();
|
||||
|
@ -47,6 +50,7 @@ pub const BatteryWidget = struct {
|
|||
|
||||
pub fn mouse_event(self: *BatteryWidget, event: MouseEvent) void {}
|
||||
|
||||
// Find all the paths for power info.
|
||||
pub fn get_power_paths(self: *BatteryWidget, provided_allocator: *std.mem.Allocator) anyerror!PowerPaths {
|
||||
var arena = std.heap.ArenaAllocator.init(provided_allocator);
|
||||
defer arena.deinit();
|
||||
|
@ -106,8 +110,8 @@ pub const BatteryWidget = struct {
|
|||
var sign: []const u8 = "?";
|
||||
var power_colour: []const u8 = "#ffffff";
|
||||
|
||||
const capacity = @intToFloat(f64, read_file_to_unsigned_int64(pp.capacity_path));
|
||||
const status = try read_file(pp.status_path);
|
||||
const capacity = @intToFloat(f64, readFileToUnsignedInt64(pp.capacity_path));
|
||||
const status = try readFile(pp.status_path);
|
||||
|
||||
if (capacity > 80) {
|
||||
power_colour = "green";
|
||||
|
@ -120,22 +124,22 @@ pub const BatteryWidget = struct {
|
|||
}
|
||||
|
||||
if (std.mem.eql(u8, status, "Charging")) {
|
||||
descriptor = try colour(allocator, "green", "(C)");
|
||||
descriptor = comptimeColour("green", "(C)");
|
||||
sign = "+";
|
||||
} else if (std.mem.eql(u8, status, "Discharging")) {
|
||||
descriptor = try colour(allocator, power_colour, "(D)");
|
||||
sign = "-";
|
||||
} else if (std.mem.eql(u8, status, "Unknown")) {
|
||||
descriptor = try colour(allocator, "yellow", "(U)");
|
||||
descriptor = comptimeColour("yellow", "(U)");
|
||||
sign = "?";
|
||||
}
|
||||
|
||||
if (pp.power_now_path.len != 0) {
|
||||
watts = @intToFloat(f64, read_file_to_unsigned_int64(pp.power_now_path)) / 1000000;
|
||||
watts = @intToFloat(f64, readFileToUnsignedInt64(pp.power_now_path)) / 1000000;
|
||||
can_get_watts = true;
|
||||
} else if (pp.current_now_path.len != 0 and pp.voltage_now_path.len != 0) {
|
||||
const current_now = @intToFloat(f64, read_file_to_unsigned_int64(pp.current_now_path)) / 1000000;
|
||||
const voltage_now = @intToFloat(f64, read_file_to_unsigned_int64(pp.voltage_now_path)) / 1000000;
|
||||
const current_now = @intToFloat(f64, readFileToUnsignedInt64(pp.current_now_path)) / 1000000;
|
||||
const voltage_now = @intToFloat(f64, readFileToUnsignedInt64(pp.voltage_now_path)) / 1000000;
|
||||
if (current_now == 0 or voltage_now == 0) {
|
||||
can_get_watts = false;
|
||||
} else {
|
||||
|
@ -151,10 +155,10 @@ pub const BatteryWidget = struct {
|
|||
}
|
||||
|
||||
var bat_info = try std.fmt.allocPrint(allocator, "{} {} {}{}{}", .{
|
||||
colour(allocator, "accentlight", "bat"),
|
||||
comptimeColour("accentlight", "bat"),
|
||||
descriptor,
|
||||
colour(allocator, power_colour, try std.fmt.allocPrint(allocator, "{d:.2}", .{capacity})),
|
||||
colour(allocator, "accentdark", "%"),
|
||||
comptimeColour("accentdark", "%"),
|
||||
watts_info,
|
||||
});
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ const std = @import("std");
|
|||
const Info = @import("../../types/info.zig");
|
||||
const Bar = @import("../../types/bar.zig").Bar;
|
||||
const colour = @import("../../formatting/colour.zig").colour;
|
||||
const comptimeColour = @import("../../formatting/colour.zig").colour;
|
||||
const comptimeColour = @import("../../formatting/colour.zig").comptimeColour;
|
||||
const MouseEvent = @import("../../types/mouseevent.zig");
|
||||
const LoopingCounter = @import("../../types/loopingcounter.zig").LoopingCounter;
|
||||
|
||||
|
@ -35,7 +35,7 @@ fn formatMemoryPercent(allocator: *std.mem.Allocator, percent: f64) ![]const u8
|
|||
} else {
|
||||
percentColour = "green";
|
||||
}
|
||||
const percentString = try std.fmt.allocPrint(allocator, "{d:.3}{}", .{ percent, comptimeColour(allocator, "accentdark", "%") });
|
||||
const percentString = try std.fmt.allocPrint(allocator, "{d:.3}{}", .{ percent, comptimeColour("accentdark", "%") });
|
||||
|
||||
return colour(allocator, percentColour, percentString);
|
||||
}
|
||||
|
@ -122,49 +122,51 @@ pub const MemoryWidget = struct {
|
|||
var allocator = &fba.allocator;
|
||||
const memInfo = try fetchTotalMemory();
|
||||
var text: []const u8 = " ";
|
||||
|
||||
// And this is why I love the looping counter.
|
||||
if (self.lc.get() == 0) {
|
||||
text = try std.fmt.allocPrint(allocator, "{} {}", .{
|
||||
colour(allocator, "accentlight", "mem"),
|
||||
comptimeColour("accentlight", "mem"),
|
||||
formatMemoryPercent(allocator, (@intToFloat(f64, memInfo.memTotal - memInfo.memFree - memInfo.buffers - memInfo.cached) / @intToFloat(f64, memInfo.memTotal)) * 100),
|
||||
});
|
||||
} else if (self.lc.get() == 1) {
|
||||
text = try std.fmt.allocPrint(allocator, "{} {}", .{
|
||||
colour(allocator, "accentlight", "swap"),
|
||||
comptimeColour("accentlight", "swap"),
|
||||
formatMemoryPercent(allocator, (@intToFloat(f64, memInfo.swapTotal - memInfo.swapFree) / @intToFloat(f64, memInfo.swapTotal)) * 100),
|
||||
});
|
||||
} else if (self.lc.get() == 2) {
|
||||
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
|
||||
colour(allocator, "accentlight", "mem free"),
|
||||
comptimeColour("accentlight", "mem free"),
|
||||
kibibytesToMegabytes(memInfo.memFree),
|
||||
});
|
||||
} else if (self.lc.get() == 3) {
|
||||
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
|
||||
colour(allocator, "accentlight", "swap free"),
|
||||
comptimeColour("accentlight", "swap free"),
|
||||
kibibytesToMegabytes(memInfo.swapFree),
|
||||
});
|
||||
} else if (self.lc.get() == 4) {
|
||||
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
|
||||
colour(allocator, "accentlight", "mem used"),
|
||||
comptimeColour("accentlight", "mem used"),
|
||||
kibibytesToMegabytes(memInfo.memTotal - memInfo.memFree - memInfo.buffers - memInfo.cached),
|
||||
});
|
||||
} else if (self.lc.get() == 5) {
|
||||
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
|
||||
colour(allocator, "accentlight", "swap used"),
|
||||
comptimeColour("accentlight", "swap used"),
|
||||
kibibytesToMegabytes(memInfo.swapTotal - memInfo.swapFree),
|
||||
});
|
||||
} else if (self.lc.get() == 6) {
|
||||
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
|
||||
colour(allocator, "accentlight", "mem cache"),
|
||||
comptimeColour("accentlight", "mem cache"),
|
||||
kibibytesToMegabytes(memInfo.cached),
|
||||
});
|
||||
} else if (self.lc.get() == 7) {
|
||||
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
|
||||
colour(allocator, "accentlight", "swap cache"),
|
||||
comptimeColour("accentlight", "swap cache"),
|
||||
kibibytesToMegabytes(memInfo.swapCached),
|
||||
});
|
||||
} else if (self.lc.get() == 8) {
|
||||
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
|
||||
colour(allocator, "accentlight", "mem buf"),
|
||||
comptimeColour("accentlight", "mem buf"),
|
||||
kibibytesToMegabytes(memInfo.buffers),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ const Bar = @import("../../types/bar.zig").Bar;
|
|||
const time = @import("time");
|
||||
const colour = @import("../../formatting/colour.zig").colour;
|
||||
const MouseEvent = @import("../../types/mouseevent.zig");
|
||||
const comptimeColour = @import("../../formatting/colour.zig").comptimeColour;
|
||||
|
||||
pub const TimeWidget = struct {
|
||||
bar: *Bar,
|
||||
|
@ -23,6 +24,8 @@ pub const TimeWidget = struct {
|
|||
pub fn mouse_event(self: *TimeWidget, event: MouseEvent) void {}
|
||||
|
||||
pub fn start(self: *TimeWidget) anyerror!void {
|
||||
// TODO: find a god damn decent time library thats better than this bullshit.
|
||||
|
||||
while (self.bar.keep_running()) {
|
||||
var arena = std.heap.ArenaAllocator.init(self.allocator);
|
||||
defer arena.deinit();
|
||||
|
@ -45,9 +48,9 @@ pub const TimeWidget = struct {
|
|||
|
||||
var timeStr = try std.fmt.allocPrint(allocator, "{}{}{}{}{}{}", .{
|
||||
colour(allocator, "red", try std.fmt.allocPrint(allocator, "{d:0<2}", .{@intCast(u7, hour)})),
|
||||
colour(allocator, "accentlight", ":"),
|
||||
comptimeColour("accentlight", ":"),
|
||||
colour(allocator, "orange", try std.fmt.allocPrint(allocator, "{d:0<2}", .{@intCast(u7, clock.min)})),
|
||||
colour(allocator, "accentmedium", ":"),
|
||||
comptimeColour("accentmedium", ":"),
|
||||
colour(allocator, "yellow", try std.fmt.allocPrint(allocator, "{d:0<2}", .{@intCast(u7, clock.sec)})),
|
||||
colour(allocator, "accentdark", end),
|
||||
});
|
||||
|
@ -69,14 +72,14 @@ pub const TimeWidget = struct {
|
|||
|
||||
var h = try std.fmt.allocPrint(allocator, "{} {} {}{} {} {} {} {} {} {}", .{
|
||||
colour(allocator, "green", now.weekday().string()),
|
||||
colour(allocator, "purple", "the"),
|
||||
comptimeColour("purple", "the"),
|
||||
colour(allocator, "yellow", try std.fmt.allocPrint(allocator, "{}", .{date.day})),
|
||||
colour(allocator, "accentmedium", suffix),
|
||||
colour(allocator, "purple", "of"),
|
||||
comptimeColour("purple", "of"),
|
||||
colour(allocator, "red", date.month.string()),
|
||||
colour(allocator, "purple", "in"),
|
||||
comptimeColour("purple", "in"),
|
||||
colour(allocator, "accentlight", try std.fmt.allocPrint(allocator, "{}", .{date.year})),
|
||||
colour(allocator, "purple", "at"),
|
||||
comptimeColour("purple", "at"),
|
||||
timeStr,
|
||||
});
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ const hzzp = @import("hzzp");
|
|||
const Info = @import("../../types/info.zig");
|
||||
const Bar = @import("../../types/bar.zig").Bar;
|
||||
const colour = @import("../../formatting/colour.zig").colour;
|
||||
const comptimeColour = @import("../../formatting/colour.zig").comptimeColour;
|
||||
|
||||
const DebugAllocator = @import("../../debug_allocator.zig");
|
||||
const MouseEvent = @import("../../types/mouseevent.zig");
|
||||
|
||||
|
@ -60,6 +62,8 @@ pub const WeatherWidget = struct {
|
|||
var main: []const u8 = "";
|
||||
var message: []const u8 = "";
|
||||
|
||||
|
||||
// This parser is clunky, it may be worth a rewrite but it seems like it optimizes decently.
|
||||
while (try client.readEvent()) |event| {
|
||||
switch (event) {
|
||||
.chunk => |chunk| {
|
||||
|
@ -93,7 +97,8 @@ pub const WeatherWidget = struct {
|
|||
message = str;
|
||||
}
|
||||
if (isNextCode) {
|
||||
// why the fuck would you make code both a string and a int are you wanting me to question my sanity???
|
||||
// Why the fuck would you make code both a string and a int.
|
||||
// Are you wanting me to question my sanity???
|
||||
isNextCode = false;
|
||||
code = try std.fmt.parseInt(i16, str, 10);
|
||||
}
|
||||
|
@ -125,7 +130,6 @@ pub const WeatherWidget = struct {
|
|||
var arenacator = &arena.allocator;
|
||||
if (self.get_weather_info(arenacator)) |i| {
|
||||
inf = i;
|
||||
//std.debug.print("{}", .{i});
|
||||
} else |err| switch (err) {
|
||||
error.TemporaryNameServerFailure => {
|
||||
try self.bar.add(Info{
|
||||
|
@ -169,6 +173,11 @@ pub const WeatherWidget = struct {
|
|||
var temp = inf.temp;
|
||||
var main = inf.main;
|
||||
|
||||
|
||||
// Please note that these are *my* personal temp preferences.
|
||||
// TODO: it may be worth making a way for the user to change this with a function on init.
|
||||
// If you happen to read this and you plan on inviting me round your house one day,
|
||||
// then feel free to set your A/C to a optimal temp as shown below.
|
||||
var tempColour: []const u8 = "green";
|
||||
if (temp >= 20) {
|
||||
tempColour = "red";
|
||||
|
@ -183,10 +192,10 @@ pub const WeatherWidget = struct {
|
|||
var i = Info{
|
||||
.name = self.name,
|
||||
.full_text = try std.fmt.allocPrint(arenacator, "{} {}{}{} {}", .{
|
||||
colour(arenacator, "accentlight", "weather"),
|
||||
comptimeColour("accentlight", "weather"),
|
||||
colour(arenacator, tempColour, try std.fmt.allocPrint(arenacator, "{}", .{temp})),
|
||||
colour(arenacator, "accentlight", "°"),
|
||||
colour(arenacator, "accentdark", "C"),
|
||||
comptimeColour("accentlight", "°"),
|
||||
comptimeColour("accentdark", "C"),
|
||||
colour(arenacator, "green", main),
|
||||
}),
|
||||
.markup = "pango",
|
||||
|
@ -207,6 +216,9 @@ pub inline fn New(allocator: *std.mem.Allocator, bar: *Bar, comptime location: [
|
|||
.allocator = allocator,
|
||||
.bar = bar,
|
||||
.name = "weather " ++ location,
|
||||
// Yeah I know I'm leaking a token here.
|
||||
// So what? It ain't my token.
|
||||
// It was the first result on github code search for "openweathermap appid"
|
||||
.weather_api_url = "/data/2.5/weather?q=" ++ location ++ "&appid=dcea3595afe693d1c17846141f58ea10&units=metric",
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue