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",
|
"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(.{
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue