1
0
Fork 0
This commit is contained in:
namedkitten 2020-07-24 17:02:47 +01:00
parent 321105ecbd
commit bfcd22b329
6 changed files with 57 additions and 44 deletions

View file

@ -110,6 +110,16 @@ pub const Bar = struct {
} }
} }
fn dispatch_click_event(self: *Bar, name: []const u8, event: MouseEvent) !void {
std.log.debug(.bar, "Dispatch! {} {}\n", .{ name, event });
for (self.widgets) |w| {
if (std.mem.eql(u8, w.name(), name)) {
try w.mouse_event(event);
}
}
}
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. // TODO: make work on other OSes other than xterm compatable terminals.
@ -150,16 +160,17 @@ pub const Bar = struct {
if (y == null) { if (y == null) {
continue; continue;
} }
const click_x_position = try std.fmt.parseInt(u64, x.?, 10); const click_x_position = try std.fmt.parseInt(u16, x.?, 10);
// This makes it so it only works on the end of a click not the start // This makes it so it only works on the end of a click not the start
// preventing a single click pressing the button twice. // preventing a single click pressing the button twice.
if (y.?[y.?.len - 1] == 'm') continue; if (y.?[y.?.len - 1] == 'm') continue;
var current_info_line_length: u64 = 0; var current_info_line_length: u16 = 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. // 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. // To do this we only count the number of characters that are actually printed.
var isEscape: bool = false; var isEscape: bool = false;
const previous_length = current_info_line_length;
for (infoItem.full_text) |char| { for (infoItem.full_text) |char| {
// Skip all of the escape codes. // Skip all of the escape codes.
if (char == 0x1b) { if (char == 0x1b) {
@ -177,12 +188,8 @@ pub const Bar = struct {
current_info_line_length = current_info_line_length + 1; current_info_line_length = current_info_line_length + 1;
} }
// Get the first widget that the click is in. // Get the first widget that the click is in.
if (click_x_position <= current_info_line_length) { if (click_x_position <= current_info_line_length) {
for (self.widgets) |w| { self.dispatch_click_event(infoItem.name, .{ .button = .LeftClick, .x = click_x_position, .y=0,.scale=1, .height=1, .relative_x = click_x_position - previous_length}) catch {};
if (std.mem.eql(u8, w.name(), infoItem.name)) {
w.mouse_event(.{ .button = .LeftClick }) catch {};
}
}
break; break;
} }
// Compensate for the | seporator on the terminal. // Compensate for the | seporator on the terminal.
@ -195,9 +202,6 @@ pub const Bar = struct {
inline fn i3bar_input_process(self: *Bar) !void { inline fn i3bar_input_process(self: *Bar) !void {
var line_buffer: [512]u8 = undefined; var line_buffer: [512]u8 = undefined;
while (self.running) { while (self.running) {
var arena = std.heap.ArenaAllocator.init(self.allocator);
defer arena.deinit();
var allocator = &arena.allocator;
const line_opt = try std.io.getStdIn().inStream().readUntilDelimiterOrEof(&line_buffer, '\n'); const line_opt = try std.io.getStdIn().inStream().readUntilDelimiterOrEof(&line_buffer, '\n');
if (line_opt) |l| { if (line_opt) |l| {
var line = l; var line = l;
@ -210,16 +214,11 @@ pub const Bar = struct {
// instead of looping and getting it, maybe then it would make more sense? // 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. // 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 = self.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);
defer std.json.parseFree(MouseEvent, data, parseOptions); defer std.json.parseFree(MouseEvent, data, 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. self.dispatch_click_event(data.name, data) catch {};
for (self.widgets) |w| {
if (std.mem.eql(u8, w.name(), data.name)) {
try w.mouse_event(data);
}
}
// If mouse_event needs to store the event for after the call is finished, // 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. // 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. // Free the memory allocated by the MouseEvent struct.

View file

@ -66,8 +66,7 @@ pub fn main() !void {
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(&networkWidget.New(allocator, &br)), // 4.08KiB &Widget.init(&networkWidget.New(allocator, &br)), // 24.01KiB
&Widget.init(&cpuWidget.New(&br)), // 4.08KiB &Widget.init(&cpuWidget.New(&br)), // 4.08KiB
&Widget.init(&memoryWidget.New(&br)), // 4.08KiB &Widget.init(&memoryWidget.New(&br)), // 4.08KiB
&Widget.init(&weatherWidget.New(allocator, &br, @import("build_options").weather_location)), // 16.16KiB &Widget.init(&weatherWidget.New(allocator, &br, @import("build_options").weather_location)), // 16.16KiB

View file

@ -17,7 +17,6 @@ fn formatCPUPercent(allocator: *std.mem.Allocator, percent: f64) ![]const u8 {
percentColour = "green"; percentColour = "green";
} }
const percentString = try std.fmt.allocPrint(allocator, "{d:0<2.2}" ++ comptimeColour("accentdark", "%"), .{percent}); const percentString = try std.fmt.allocPrint(allocator, "{d:0<2.2}" ++ comptimeColour("accentdark", "%"), .{percent});
return colour(allocator, percentColour, percentString); return colour(allocator, percentColour, percentString);
} }

View file

@ -41,6 +41,7 @@ fn formatMemoryPercent(allocator: *std.mem.Allocator, percent: f64) ![]const u8
percentColour = "green"; percentColour = "green";
} }
const percentString = try std.fmt.allocPrint(allocator, "{d:.2}" ++ comptimeColour("accentdark", "%"), .{percent}); const percentString = try std.fmt.allocPrint(allocator, "{d:.2}" ++ comptimeColour("accentdark", "%"), .{percent});
defer allocator.free(percentString);
return colour(allocator, percentColour, percentString); return colour(allocator, percentColour, percentString);
} }

View file

@ -47,10 +47,17 @@ fn networkStatusToColour(s: NetworkStatus) []const u8 {
pub const NetworkInfo = struct { pub const NetworkInfo = struct {
network_type: NetworkType = .WiFi, network_type: NetworkType = .WiFi,
network_status: NetworkStatus = .Connected, network_status: NetworkStatus = .Connected,
network_info: [32]u8 = [32]u8{ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, network_info: []const u8,
network_info_len: usize,
}; };
inline fn freeString(allocator: *std.mem.Allocator, string: []const u8) void {
allocator.free(string);
}
inline fn dupeString(allocator: *std.mem.Allocator, string: []const u8) ![]const u8 {
return try allocator.dupe(u8, string);
}
pub const NetworkWidget = struct { pub const NetworkWidget = struct {
bar: *Bar, bar: *Bar,
allocator: *std.mem.Allocator, allocator: *std.mem.Allocator,
@ -87,14 +94,15 @@ pub const NetworkWidget = struct {
pub fn update_network_infos(self: *NetworkWidget) anyerror!void { pub fn update_network_infos(self: *NetworkWidget) anyerror!void {
const lock = self.update_mutex.acquire(); const lock = self.update_mutex.acquire();
defer lock.release(); defer lock.release();
self.network_infos.shrink(0); for (self.network_infos.items) |info| {
freeString(self.allocator, info.network_info);
}
self.num_interfaces = 0; self.num_interfaces = 0;
var arena = std.heap.ArenaAllocator.init(self.allocator); var proc = try std.ChildProcess.init(&[_][]const u8{ "nmcli", "-f", "common", "-c", "no", "d" }, self.allocator);
defer arena.deinit(); defer { _ = proc.kill() catch {}; proc.deinit(); }
var allocator = &arena.allocator;
var proc = try std.ChildProcess.init(&[_][]const u8{ "nmcli", "-f", "common", "-c", "no", "d" }, allocator);
proc.stdout_behavior = .Pipe; proc.stdout_behavior = .Pipe;
try proc.spawn(); try proc.spawn();
var i: u8 = 0;
if (proc.stdout) |stdout| { if (proc.stdout) |stdout| {
var line_buffer: [128]u8 = undefined; var line_buffer: [128]u8 = undefined;
// Skip header. // Skip header.
@ -107,45 +115,52 @@ pub const NetworkWidget = struct {
const status = it.next(); const status = it.next();
const description = it.next(); const description = it.next();
if (connection_type) |t| if (!(eql(u8, t, "wifi") or eql(u8, t, "ethernet"))) continue; if (connection_type) |t| if (!(eql(u8, t, "wifi") or eql(u8, t, "ethernet"))) continue;
var net_info = NetworkInfo{ try self.network_infos.resize(i+1);
self.network_infos.items[i] = NetworkInfo{
.network_type = toNetworkType(connection_type.?), .network_type = toNetworkType(connection_type.?),
.network_status = toNetworkStatus(status.?), .network_status = toNetworkStatus(status.?),
.network_info_len = description.?.len, .network_info = try dupeString(self.allocator, description.?),
}; };
std.mem.copy(u8, net_info.network_info[0..description.?.len], description.?[0..description.?.len]); //try self.network_infos.append(net_info);
try self.network_infos.append(net_info);
self.num_interfaces += 1; self.num_interfaces += 1;
i += 1;
} }
} }
} }
pub fn update_bar(self: *NetworkWidget) anyerror!void { pub fn update_bar(self: *NetworkWidget) anyerror!void {
var arena = std.heap.ArenaAllocator.init(self.allocator); var buffer: [512]u8 = undefined;
defer arena.deinit(); var fba = std.heap.FixedBufferAllocator.init(&buffer);
var allocator = &arena.allocator; var allocator = &fba.allocator;
for (self.network_infos.items) |info, i| { for (self.network_infos.items) |info, i| {
if (i != self.current_interface) continue; if (i != self.current_interface) continue;
//std.log.debug(.network, "item! {} {}\n", .{ info, i }); //std.log.debug(.network, "item! {} {}\n", .{ info, i });
const inner_text = try std.fmt.allocPrint(allocator, "{} {}", .{ @tagName(info.network_type), info.network_info });
const full_text = try colour(allocator, networkStatusToColour(info.network_status), inner_text);
defer allocator.free(full_text);
allocator.free(inner_text);
try self.bar.add(Info{ try self.bar.add(Info{
.name = "network", .name = "network",
.full_text = try colour(allocator, networkStatusToColour(info.network_status), try std.fmt.allocPrint(allocator, "{} {}", .{ @tagName(info.network_type), info.network_info[0..info.network_info_len] })), .full_text = full_text,
.markup = "pango", .markup = "pango",
}); });
} }
} }
pub fn start(self: *NetworkWidget) anyerror!void { pub fn start(self: *NetworkWidget) anyerror!void {
var arena = std.heap.ArenaAllocator.init(self.allocator); self.network_infos = std.ArrayList(NetworkInfo).init(self.allocator);
defer arena.deinit(); defer self.network_infos.deinit();
var allocator = &arena.allocator;
self.network_infos = std.ArrayList(NetworkInfo).init(allocator);
while (self.bar.keep_running()) { while (self.bar.keep_running()) {
try self.update_network_infos(); try self.update_network_infos();
try self.update_bar(); try self.update_bar();
std.time.sleep(std.time.ns_per_s); std.time.sleep(std.time.ns_per_s);
} }
const lock = self.update_mutex.acquire();
defer lock.release();
for (self.network_infos.items) |info| {
freeString(self.allocator, info.network_info);
}
} }
}; };

View file

@ -25,12 +25,12 @@ pub const TimeWidget = struct {
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. // 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); var arena = std.heap.ArenaAllocator.init(self.allocator);
defer arena.deinit(); defer arena.deinit();
var allocator = &arena.allocator; var allocator = &arena.allocator;
var local = time.Location.getLocal(allocator); var local = time.Location.getLocal(allocator);
var now = time.now(&local); while (self.bar.keep_running()) {
var now = time.now(&local);
var date = now.date(); var date = now.date();
var clock = now.clock(); var clock = now.clock();