1
0
Fork 0

Comment more of the code, fix and use comptimeColour more.

This commit is contained in:
namedkitten 2020-07-17 20:16:46 +01:00
parent 7203cf1904
commit fa00747fca
9 changed files with 128 additions and 50 deletions

View file

@ -9,6 +9,7 @@ pub fn build(b: *Builder) void {
"disable_colour", "disable_colour",
"no colour", "no colour",
) orelse false; ) orelse false;
exe.addBuildOption(bool, "disable_colour", disable_colour); exe.addBuildOption(bool, "disable_colour", disable_colour);
const terminal_version = b.option( const terminal_version = b.option(
bool, bool,
@ -22,6 +23,14 @@ pub fn build(b: *Builder) void {
"use debug allocator for testing", "use debug allocator for testing",
) orelse false; ) orelse false;
exe.addBuildOption(bool, "debug_allocator", debug_allocator); 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.strip = true;
exe.addPackage(.{ exe.addPackage(.{

View file

@ -15,6 +15,7 @@ pub const Bar = struct {
out_file: std.fs.File, out_file: std.fs.File,
pub fn start(self: *Bar) !void { pub fn start(self: *Bar) !void {
self.running = true; 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"); if (!terminal_version) try self.out_file.writer().writeAll("{\"version\": 1,\"click_events\": true}\n[\n");
for (self.widgets) |w| { for (self.widgets) |w| {
try self.infos.append(try self.dupe_info(w.initial_info())); 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(w, Widget.start);
} }
var thread = try std.Thread.spawn(self, Bar.process); var thread = try std.Thread.spawn(self, Bar.process);
// TODO: wait for kill signal to kill bar instead of waiting for thread.
thread.wait(); thread.wait();
self.running = false; self.running = false;
// Wait for most widgets to stop.
std.time.sleep(1000 * std.time.ns_per_ms); std.time.sleep(1000 * std.time.ns_per_ms);
for (self.infos.items) |info| { for (self.infos.items) |info| {
try self.free_info(info); try self.free_info(info);
@ -34,6 +37,7 @@ pub const Bar = struct {
} }
inline fn print_i3bar_infos(self: *Bar) !void { inline fn print_i3bar_infos(self: *Bar) !void {
// Serialize all bar items and put on stdout.
try self.out_file.writer().writeAll("["); try self.out_file.writer().writeAll("[");
for (self.infos.items) |info, i| { for (self.infos.items) |info, i| {
try std.json.stringify(info, .{}, self.out_file.writer()); 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 { inline fn print_terminal_infos(self: *Bar) !void {
// For terminal we just need to directly print.
for (self.infos.items) |info, i| { for (self.infos.items) |info, i| {
try self.out_file.writer().writeAll(info.full_text); try self.out_file.writer().writeAll(info.full_text);
if (i < self.infos.items.len - 1) { if (i < self.infos.items.len - 1) {
@ -68,35 +73,50 @@ pub const Bar = struct {
} }
inline fn terminal_input_process(self: *Bar) !void { 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"); try self.out_file.writer().writeAll("\u{001b}[?1000;1006;1015h");
var termios = try os.tcgetattr(0); var termios = try os.tcgetattr(0);
// Set terminal to raw mode so that all input goes directly into stdin.
termios.iflag &= ~@as( termios.iflag &= ~@as(
os.tcflag_t, os.tcflag_t,
os.IGNBRK | os.BRKINT | os.PARMRK | os.ISTRIP | os.IGNBRK | os.BRKINT | os.PARMRK | os.ISTRIP |
os.INLCR | os.IGNCR | os.ICRNL | os.IXON, 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 |= ~@as(os.tcflag_t, (os.ECHO | os.ICANON));
termios.lflag &= os.ISIG; termios.lflag &= os.ISIG;
// Set terminal attributes.
// TODO: reset on bar end.
try os.tcsetattr(0, .FLUSH, termios); try os.tcsetattr(0, .FLUSH, termios);
while (true) { while (true) {
var line_buffer: [128]u8 = undefined; 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); const line_opt = try std.io.getStdIn().inStream().readUntilDelimiterOrEof(&line_buffer, 0x1b);
if (line_opt) |l| { 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; if (l.len < 2) continue;
var it = std.mem.tokenize(l, ";"); 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(); _ = 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().?; 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; if (y[y.len - 1] == 'm') continue;
var xe: u64 = 0; var current_info_line_length: u64 = 0;
for (self.infos.items) |infoItem, index| { 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; var isEscape: bool = false;
for (infoItem.full_text) |char| { for (infoItem.full_text) |char| {
// Skip all of the escape codes.
if (char == 0x1b) { if (char == 0x1b) {
isEscape = true; isEscape = true;
continue; continue;
@ -108,18 +128,20 @@ pub const Bar = struct {
isEscape = false; isEscape = false;
continue; 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| { for (self.widgets) |w| {
if (std.mem.eql(u8, w.name(), infoItem.name)) { if (std.mem.eql(u8, w.name(), infoItem.name)) {
w.mouse_event(.{ .button = .LeftClick }) catch {}; w.mouse_event(.{ .button = .LeftClick }) catch {};
} }
} }
//std.debug.print("Info Item Clicky{}\n", .{infoItem.name});
break; 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| { if (line_opt) |l| {
var line = l; var line = l;
if (std.mem.eql(u8, line, "[")) continue; 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; 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]; if (line[0] == ',') line = line[1..line.len];
const parseOptions = std.json.ParseOptions{ .allocator = allocator }; const parseOptions = std.json.ParseOptions{ .allocator = allocator };
const data = try std.json.parse(MouseEvent, &std.json.TokenStream.init(line), parseOptions); 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| { for (self.widgets) |w| {
if (std.mem.eql(u8, w.name(), data.name)) { if (std.mem.eql(u8, w.name(), data.name)) {
w.mouse_event(data) catch {}; 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); std.json.parseFree(MouseEvent, data, parseOptions);
} }
} }
} }
fn process(self: *Bar) !void { 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) { if (debug_allocator) {
std.time.sleep(std.time.ns_per_ms * 2000 * 5); std.time.sleep(std.time.ns_per_ms * 2000 * 5);
if (true) return; if (true) return;
} }
// TODO: log errors.
if (terminal_version) { if (terminal_version) {
self.terminal_input_process() catch {}; self.terminal_input_process() catch {};
} else { } else {
@ -162,8 +198,11 @@ pub const Bar = struct {
} }
} }
pub fn keep_running(self: *Bar) bool { pub fn keep_running(self: *Bar) bool {
// TODO: maybe rename this function to something more descriptive?
return self.running; return self.running;
} }
/// This frees the name and text fields of a Info struct.
fn free_info(self: *Bar, info: Info) !void { fn free_info(self: *Bar, info: Info) !void {
self.allocator.free(info.name); self.allocator.free(info.name);
self.allocator.free(info.full_text); self.allocator.free(info.full_text);
@ -180,10 +219,10 @@ pub const Bar = struct {
return Info{ return Info{
.name = new_name, .name = new_name,
.full_text = new_text, .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 { pub fn add(self: *Bar, info: Info) !void {
const lock = self.items_mutex.acquire(); const lock = self.items_mutex.acquire();
defer lock.release(); 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{ return Bar{
.allocator = allocator, .allocator = allocator,
.widgets = undefined, .widgets = undefined,

View file

@ -28,6 +28,7 @@ const TerminalYellowColour = "\u{001b}[33m";
const TerminalGreenColour = "\u{001b}[32m"; const TerminalGreenColour = "\u{001b}[32m";
const TerminalPurpleColour = "\u{001b}[35m"; 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 { pub fn comptimeColour(comptime clr: []const u8, comptime str: []const u8) []const u8 {
if (disable_colour) return str; 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>"; return "<span color=\"" ++ clr ++ "\">" ++ str ++ "</span>";
} }
} else { } else {
var colourText: []const u8 = ""; comptime var colourText: []const u8 = "";
if (eql(u8, clr, "text")) { if (eql(u8, clr, "text")) {
colourText = if (!terminal_version) TextColour else TerminalTextColour; colourText = if (!terminal_version) TextColour else TerminalTextColour;
} else if (eql(u8, clr, "dark")) { } 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; colourText = if (!terminal_version) GreenColour else TerminalGreenColour;
} else if (eql(u8, clr, "purple")) { } else if (eql(u8, clr, "purple")) {
colourText = if (!terminal_version) PurpleColour else TerminalPurpleColour; colourText = if (!terminal_version) PurpleColour else TerminalPurpleColour;
} else { }
@compileError("colour not found"); if (colourText.len == 0) {
unreachable;
} }
return comptimeColour(colourText, str); 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 { pub fn colour(alloc: *std.mem.Allocator, clr: []const u8, str: []const u8) ![]const u8 {
if (disable_colour) return str; if (disable_colour) return str;

View file

@ -18,19 +18,20 @@ pub fn main() !void {
var allocator: *std.mem.Allocator = undefined; var allocator: *std.mem.Allocator = undefined;
var dbgAlloc: *DebugAllocator = undefined; var dbgAlloc: *DebugAllocator = undefined;
if (debug_allocator) { if (debug_allocator) {
// Warning that DebugAllocator can get a little crashy.
dbgAlloc = &DebugAllocator.init(std.heap.page_allocator, 8192 * 8192); dbgAlloc = &DebugAllocator.init(std.heap.page_allocator, 8192 * 8192);
allocator = &dbgAlloc.allocator; allocator = &dbgAlloc.allocator;
} else { } else {
allocator = std.heap.page_allocator; allocator = std.heap.page_allocator;
} }
var bar = barImpl.InitBar(allocator); var bar = barImpl.initBar(allocator);
var br = Bar.init(&bar); var br = Bar.init(&bar);
const widgets = [_]*Widget{ const widgets = [_]*Widget{
//&Widget.init(&textWidget.New("owo", "potato")), // 4KiB //&Widget.init(&textWidget.New("owo", "potato")), // 4KiB
//&Widget.init(&textWidget.New("uwu", "tomato")), // 4KiB //&Widget.init(&textWidget.New("uwu", "tomato")), // 4KiB
&Widget.init(&memoryWidget.New(&br)), // 4.08KiB &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(&batteryWidget.New(allocator, &br)), // 12.11KiB
&Widget.init(&timeWidget.New(allocator, &br)), // 32.46KiB &Widget.init(&timeWidget.New(allocator, &br)), // 32.46KiB
}; };

View file

@ -1,6 +1,8 @@
const std = @import("std"); const std = @import("std");
const testing = std.testing; 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( pub fn LoopingCounter(
comptime max_number: comptime_int, comptime max_number: comptime_int,
) type { ) type {
@ -24,6 +26,7 @@ pub fn LoopingCounter(
}; };
} }
// Woot we actually have some god damn tests in here.
test "looping test" { test "looping test" {
var lc = LoopingCounter(3).init(); var lc = LoopingCounter(3).init();
testing.expect(lc.get() == 0); testing.expect(lc.get() == 0);

View file

@ -5,6 +5,7 @@ const fs = std.fs;
const cwd = fs.cwd; const cwd = fs.cwd;
const colour = @import("../../formatting/colour.zig").colour; const colour = @import("../../formatting/colour.zig").colour;
const MouseEvent = @import("../../types/mouseevent.zig"); const MouseEvent = @import("../../types/mouseevent.zig");
const comptimeColour = @import("../../formatting/colour.zig").comptimeColour;
pub const PowerPaths = struct { pub const PowerPaths = struct {
status_path: []const u8 = "", status_path: []const u8 = "",
@ -14,7 +15,9 @@ pub const PowerPaths = struct {
voltage_now_path: []const u8 = "", 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 buffer: [std.math.log10(std.math.maxInt(u64)) + 2]u8 = undefined;
var file = fs.cwd().openFile(path, .{}) catch return 0; var file = fs.cwd().openFile(path, .{}) catch return 0;
defer file.close(); 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; 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 buffer: [128]u8 = undefined;
var file = try fs.cwd().openFile(path, .{}); var file = try fs.cwd().openFile(path, .{});
defer file.close(); defer file.close();
@ -47,6 +50,7 @@ pub const BatteryWidget = struct {
pub fn mouse_event(self: *BatteryWidget, event: MouseEvent) void {} 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 { pub fn get_power_paths(self: *BatteryWidget, provided_allocator: *std.mem.Allocator) anyerror!PowerPaths {
var arena = std.heap.ArenaAllocator.init(provided_allocator); var arena = std.heap.ArenaAllocator.init(provided_allocator);
defer arena.deinit(); defer arena.deinit();
@ -106,8 +110,8 @@ pub const BatteryWidget = struct {
var sign: []const u8 = "?"; var sign: []const u8 = "?";
var power_colour: []const u8 = "#ffffff"; var power_colour: []const u8 = "#ffffff";
const capacity = @intToFloat(f64, read_file_to_unsigned_int64(pp.capacity_path)); const capacity = @intToFloat(f64, readFileToUnsignedInt64(pp.capacity_path));
const status = try read_file(pp.status_path); const status = try readFile(pp.status_path);
if (capacity > 80) { if (capacity > 80) {
power_colour = "green"; power_colour = "green";
@ -120,22 +124,22 @@ pub const BatteryWidget = struct {
} }
if (std.mem.eql(u8, status, "Charging")) { if (std.mem.eql(u8, status, "Charging")) {
descriptor = try colour(allocator, "green", "(C)"); descriptor = comptimeColour("green", "(C)");
sign = "+"; sign = "+";
} else if (std.mem.eql(u8, status, "Discharging")) { } else if (std.mem.eql(u8, status, "Discharging")) {
descriptor = try colour(allocator, power_colour, "(D)"); descriptor = try colour(allocator, power_colour, "(D)");
sign = "-"; sign = "-";
} else if (std.mem.eql(u8, status, "Unknown")) { } else if (std.mem.eql(u8, status, "Unknown")) {
descriptor = try colour(allocator, "yellow", "(U)"); descriptor = comptimeColour("yellow", "(U)");
sign = "?"; sign = "?";
} }
if (pp.power_now_path.len != 0) { 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; can_get_watts = true;
} else if (pp.current_now_path.len != 0 and pp.voltage_now_path.len != 0) { } 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 current_now = @intToFloat(f64, readFileToUnsignedInt64(pp.current_now_path)) / 1000000;
const voltage_now = @intToFloat(f64, read_file_to_unsigned_int64(pp.voltage_now_path)) / 1000000; const voltage_now = @intToFloat(f64, readFileToUnsignedInt64(pp.voltage_now_path)) / 1000000;
if (current_now == 0 or voltage_now == 0) { if (current_now == 0 or voltage_now == 0) {
can_get_watts = false; can_get_watts = false;
} else { } else {
@ -151,10 +155,10 @@ pub const BatteryWidget = struct {
} }
var bat_info = try std.fmt.allocPrint(allocator, "{} {} {}{}{}", .{ var bat_info = try std.fmt.allocPrint(allocator, "{} {} {}{}{}", .{
colour(allocator, "accentlight", "bat"), comptimeColour("accentlight", "bat"),
descriptor, descriptor,
colour(allocator, power_colour, try std.fmt.allocPrint(allocator, "{d:.2}", .{capacity})), colour(allocator, power_colour, try std.fmt.allocPrint(allocator, "{d:.2}", .{capacity})),
colour(allocator, "accentdark", "%"), comptimeColour("accentdark", "%"),
watts_info, watts_info,
}); });

View file

@ -2,7 +2,7 @@ const std = @import("std");
const Info = @import("../../types/info.zig"); const Info = @import("../../types/info.zig");
const Bar = @import("../../types/bar.zig").Bar; const Bar = @import("../../types/bar.zig").Bar;
const colour = @import("../../formatting/colour.zig").colour; 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 MouseEvent = @import("../../types/mouseevent.zig");
const LoopingCounter = @import("../../types/loopingcounter.zig").LoopingCounter; const LoopingCounter = @import("../../types/loopingcounter.zig").LoopingCounter;
@ -35,7 +35,7 @@ fn formatMemoryPercent(allocator: *std.mem.Allocator, percent: f64) ![]const u8
} else { } else {
percentColour = "green"; 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); return colour(allocator, percentColour, percentString);
} }
@ -122,49 +122,51 @@ pub const MemoryWidget = struct {
var allocator = &fba.allocator; var allocator = &fba.allocator;
const memInfo = try fetchTotalMemory(); const memInfo = try fetchTotalMemory();
var text: []const u8 = " "; var text: []const u8 = " ";
// And this is why I love the looping counter.
if (self.lc.get() == 0) { if (self.lc.get() == 0) {
text = try std.fmt.allocPrint(allocator, "{} {}", .{ 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), formatMemoryPercent(allocator, (@intToFloat(f64, memInfo.memTotal - memInfo.memFree - memInfo.buffers - memInfo.cached) / @intToFloat(f64, memInfo.memTotal)) * 100),
}); });
} else if (self.lc.get() == 1) { } else if (self.lc.get() == 1) {
text = try std.fmt.allocPrint(allocator, "{} {}", .{ 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), formatMemoryPercent(allocator, (@intToFloat(f64, memInfo.swapTotal - memInfo.swapFree) / @intToFloat(f64, memInfo.swapTotal)) * 100),
}); });
} else if (self.lc.get() == 2) { } else if (self.lc.get() == 2) {
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{ text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
colour(allocator, "accentlight", "mem free"), comptimeColour("accentlight", "mem free"),
kibibytesToMegabytes(memInfo.memFree), kibibytesToMegabytes(memInfo.memFree),
}); });
} else if (self.lc.get() == 3) { } else if (self.lc.get() == 3) {
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{ text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
colour(allocator, "accentlight", "swap free"), comptimeColour("accentlight", "swap free"),
kibibytesToMegabytes(memInfo.swapFree), kibibytesToMegabytes(memInfo.swapFree),
}); });
} else if (self.lc.get() == 4) { } else if (self.lc.get() == 4) {
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{ 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), kibibytesToMegabytes(memInfo.memTotal - memInfo.memFree - memInfo.buffers - memInfo.cached),
}); });
} else if (self.lc.get() == 5) { } else if (self.lc.get() == 5) {
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{ text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
colour(allocator, "accentlight", "swap used"), comptimeColour("accentlight", "swap used"),
kibibytesToMegabytes(memInfo.swapTotal - memInfo.swapFree), kibibytesToMegabytes(memInfo.swapTotal - memInfo.swapFree),
}); });
} else if (self.lc.get() == 6) { } else if (self.lc.get() == 6) {
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{ text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
colour(allocator, "accentlight", "mem cache"), comptimeColour("accentlight", "mem cache"),
kibibytesToMegabytes(memInfo.cached), kibibytesToMegabytes(memInfo.cached),
}); });
} else if (self.lc.get() == 7) { } else if (self.lc.get() == 7) {
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{ text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
colour(allocator, "accentlight", "swap cache"), comptimeColour("accentlight", "swap cache"),
kibibytesToMegabytes(memInfo.swapCached), kibibytesToMegabytes(memInfo.swapCached),
}); });
} else if (self.lc.get() == 8) { } else if (self.lc.get() == 8) {
text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{ text = try std.fmt.allocPrint(allocator, "{} {d:0<2} MB", .{
colour(allocator, "accentlight", "mem buf"), comptimeColour("accentlight", "mem buf"),
kibibytesToMegabytes(memInfo.buffers), kibibytesToMegabytes(memInfo.buffers),
}); });
} }

View file

@ -4,6 +4,7 @@ const Bar = @import("../../types/bar.zig").Bar;
const time = @import("time"); const time = @import("time");
const colour = @import("../../formatting/colour.zig").colour; const colour = @import("../../formatting/colour.zig").colour;
const MouseEvent = @import("../../types/mouseevent.zig"); const MouseEvent = @import("../../types/mouseevent.zig");
const comptimeColour = @import("../../formatting/colour.zig").comptimeColour;
pub const TimeWidget = struct { pub const TimeWidget = struct {
bar: *Bar, bar: *Bar,
@ -23,6 +24,8 @@ pub const TimeWidget = struct {
pub fn mouse_event(self: *TimeWidget, event: MouseEvent) void {} pub fn mouse_event(self: *TimeWidget, event: MouseEvent) void {}
pub fn start(self: *TimeWidget) anyerror!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()) { while (self.bar.keep_running()) {
var arena = std.heap.ArenaAllocator.init(self.allocator); var arena = std.heap.ArenaAllocator.init(self.allocator);
defer arena.deinit(); defer arena.deinit();
@ -45,9 +48,9 @@ pub const TimeWidget = struct {
var timeStr = try std.fmt.allocPrint(allocator, "{}{}{}{}{}{}", .{ var timeStr = try std.fmt.allocPrint(allocator, "{}{}{}{}{}{}", .{
colour(allocator, "red", try std.fmt.allocPrint(allocator, "{d:0<2}", .{@intCast(u7, hour)})), 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, "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, "yellow", try std.fmt.allocPrint(allocator, "{d:0<2}", .{@intCast(u7, clock.sec)})),
colour(allocator, "accentdark", end), colour(allocator, "accentdark", end),
}); });
@ -69,14 +72,14 @@ pub const TimeWidget = struct {
var h = try std.fmt.allocPrint(allocator, "{} {} {}{} {} {} {} {} {} {}", .{ var h = try std.fmt.allocPrint(allocator, "{} {} {}{} {} {} {} {} {} {}", .{
colour(allocator, "green", now.weekday().string()), 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, "yellow", try std.fmt.allocPrint(allocator, "{}", .{date.day})),
colour(allocator, "accentmedium", suffix), colour(allocator, "accentmedium", suffix),
colour(allocator, "purple", "of"), comptimeColour("purple", "of"),
colour(allocator, "red", date.month.string()), 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, "accentlight", try std.fmt.allocPrint(allocator, "{}", .{date.year})),
colour(allocator, "purple", "at"), comptimeColour("purple", "at"),
timeStr, timeStr,
}); });

View file

@ -5,6 +5,8 @@ const hzzp = @import("hzzp");
const Info = @import("../../types/info.zig"); const Info = @import("../../types/info.zig");
const Bar = @import("../../types/bar.zig").Bar; const Bar = @import("../../types/bar.zig").Bar;
const colour = @import("../../formatting/colour.zig").colour; const colour = @import("../../formatting/colour.zig").colour;
const comptimeColour = @import("../../formatting/colour.zig").comptimeColour;
const DebugAllocator = @import("../../debug_allocator.zig"); const DebugAllocator = @import("../../debug_allocator.zig");
const MouseEvent = @import("../../types/mouseevent.zig"); const MouseEvent = @import("../../types/mouseevent.zig");
@ -60,6 +62,8 @@ pub const WeatherWidget = struct {
var main: []const u8 = ""; var main: []const u8 = "";
var message: []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| { while (try client.readEvent()) |event| {
switch (event) { switch (event) {
.chunk => |chunk| { .chunk => |chunk| {
@ -93,7 +97,8 @@ pub const WeatherWidget = struct {
message = str; message = str;
} }
if (isNextCode) { 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; isNextCode = false;
code = try std.fmt.parseInt(i16, str, 10); code = try std.fmt.parseInt(i16, str, 10);
} }
@ -125,7 +130,6 @@ pub const WeatherWidget = struct {
var arenacator = &arena.allocator; var arenacator = &arena.allocator;
if (self.get_weather_info(arenacator)) |i| { if (self.get_weather_info(arenacator)) |i| {
inf = i; inf = i;
//std.debug.print("{}", .{i});
} else |err| switch (err) { } else |err| switch (err) {
error.TemporaryNameServerFailure => { error.TemporaryNameServerFailure => {
try self.bar.add(Info{ try self.bar.add(Info{
@ -169,6 +173,11 @@ pub const WeatherWidget = struct {
var temp = inf.temp; var temp = inf.temp;
var main = inf.main; 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"; var tempColour: []const u8 = "green";
if (temp >= 20) { if (temp >= 20) {
tempColour = "red"; tempColour = "red";
@ -183,10 +192,10 @@ pub const WeatherWidget = struct {
var i = Info{ var i = Info{
.name = self.name, .name = self.name,
.full_text = try std.fmt.allocPrint(arenacator, "{} {}{}{} {}", .{ .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, tempColour, try std.fmt.allocPrint(arenacator, "{}", .{temp})),
colour(arenacator, "accentlight", "°"), comptimeColour("accentlight", "°"),
colour(arenacator, "accentdark", "C"), comptimeColour("accentdark", "C"),
colour(arenacator, "green", main), colour(arenacator, "green", main),
}), }),
.markup = "pango", .markup = "pango",
@ -207,6 +216,9 @@ pub inline fn New(allocator: *std.mem.Allocator, bar: *Bar, comptime location: [
.allocator = allocator, .allocator = allocator,
.bar = bar, .bar = bar,
.name = "weather " ++ location, .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", .weather_api_url = "/data/2.5/weather?q=" ++ location ++ "&appid=dcea3595afe693d1c17846141f58ea10&units=metric",
}; };
} }