mirror of
https://github.com/fairyglade/ly.git
synced 2026-05-06 15:20:36 +00:00
## What are the changes about? Adds customizable commands and labels to ly. Solves https://codeberg.org/fairyglade/ly/issues/905. Since Ly doesn't use INI headers. I use them exclusively for declarations of custom commands and labels. ### Commands Bind a keybind to a command, and add a hint to the HUD. Useful for use cases like display brightness, switching between GPUs, etc. Supports localization in the `name` field only. ex: where `lang = es`: `$brightness_up` => `bajar brillo` Declared in config.ini with the following: ```ini [cmd:F8] name = custom command 2 cmd = touch /tmp/ly.gaming ``` ### Labels Add a label to the HUD. As specified in #905. The text of the label corresponds to the output of the command specified in `[lbl:NAME]`. Only shows the first line of the output. Declared in config.ini with the following: ```ini [lbl:kernel] cmd = uname -srn refresh = 0 ``` Example to add to the config.ini: ```ini # Declare a command with the F8 binding. [cmd:F8] #The name of the command to show up in Ly. name = custom command cmd = touch /tmp/ly.gaming # Declare a label with an ID. This ID should be unique across all labels. [lbl:kernel] cmd = uname -srn # In frames, the time to re-run the command and update the label. If 0, only run once- do not refresh. refresh = 0 # Once you're done setting up labels and commands, add an empty header # below to continue configurating the rest of Ly. # Put other settings not belonging to custom commands/labels below here. [] ``` ## Pre-requisites - [x] I have tested & confirmed the changes work locally  Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/945 Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org> Co-authored-by: RadsammyT <radsammyt@gmail.com> Co-committed-by: RadsammyT <radsammyt@gmail.com>
187 lines
5.1 KiB
Zig
187 lines
5.1 KiB
Zig
const Widget = @This();
|
|
|
|
const keyboard = @import("keyboard.zig");
|
|
const TerminalBuffer = @import("TerminalBuffer.zig");
|
|
|
|
const VTable = struct {
|
|
deinit_fn: ?*const fn (ptr: *anyopaque) void,
|
|
realloc_fn: ?*const fn (ptr: *anyopaque) anyerror!void,
|
|
draw_fn: *const fn (ptr: *anyopaque) void,
|
|
update_fn: ?*const fn (ptr: *anyopaque, ctx: *anyopaque) anyerror!void,
|
|
handle_fn: ?*const fn (ptr: *anyopaque, maybe_key: ?keyboard.Key) anyerror!void,
|
|
calculate_timeout_fn: ?*const fn (ptr: *anyopaque, ctx: *anyopaque) anyerror!?usize,
|
|
};
|
|
|
|
pub var idCounter: u64 = 0;
|
|
|
|
id: u64,
|
|
display_name: []const u8,
|
|
keybinds: ?TerminalBuffer.KeybindMap,
|
|
pointer: *anyopaque,
|
|
vtable: VTable,
|
|
|
|
pub fn init(
|
|
display_name: []const u8,
|
|
keybinds: ?TerminalBuffer.KeybindMap,
|
|
pointer: anytype,
|
|
comptime deinit_fn: ?fn (ptr: @TypeOf(pointer)) void,
|
|
comptime realloc_fn: ?fn (ptr: @TypeOf(pointer)) anyerror!void,
|
|
comptime draw_fn: fn (ptr: @TypeOf(pointer)) void,
|
|
comptime update_fn: ?fn (ptr: @TypeOf(pointer), ctx: *anyopaque) anyerror!void,
|
|
comptime handle_fn: ?fn (ptr: @TypeOf(pointer), maybe_key: ?keyboard.Key) anyerror!void,
|
|
comptime calculate_timeout_fn: ?fn (ptr: @TypeOf(pointer), ctx: *anyopaque) anyerror!?usize,
|
|
) Widget {
|
|
const Pointer = @TypeOf(pointer);
|
|
const Impl = struct {
|
|
pub fn deinitImpl(ptr: *anyopaque) void {
|
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
|
|
|
return @call(
|
|
.always_inline,
|
|
deinit_fn.?,
|
|
.{impl},
|
|
);
|
|
}
|
|
|
|
pub fn reallocImpl(ptr: *anyopaque) !void {
|
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
|
|
|
return @call(
|
|
.always_inline,
|
|
realloc_fn.?,
|
|
.{impl},
|
|
);
|
|
}
|
|
|
|
pub fn drawImpl(ptr: *anyopaque) void {
|
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
|
|
|
return @call(
|
|
.always_inline,
|
|
draw_fn,
|
|
.{impl},
|
|
);
|
|
}
|
|
|
|
pub fn updateImpl(ptr: *anyopaque, ctx: *anyopaque) !void {
|
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
|
|
|
return @call(
|
|
.always_inline,
|
|
update_fn.?,
|
|
.{ impl, ctx },
|
|
);
|
|
}
|
|
|
|
pub fn handleImpl(ptr: *anyopaque, maybe_key: ?keyboard.Key) !void {
|
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
|
|
|
return @call(
|
|
.always_inline,
|
|
handle_fn.?,
|
|
.{ impl, maybe_key },
|
|
);
|
|
}
|
|
|
|
pub fn calculateTimeoutImpl(ptr: *anyopaque, ctx: *anyopaque) !?usize {
|
|
const impl: Pointer = @ptrCast(@alignCast(ptr));
|
|
|
|
return @call(
|
|
.always_inline,
|
|
calculate_timeout_fn.?,
|
|
.{ impl, ctx },
|
|
);
|
|
}
|
|
|
|
const vtable = VTable{
|
|
.deinit_fn = if (deinit_fn != null) deinitImpl else null,
|
|
.realloc_fn = if (realloc_fn != null) reallocImpl else null,
|
|
.draw_fn = drawImpl,
|
|
.update_fn = if (update_fn != null) updateImpl else null,
|
|
.handle_fn = if (handle_fn != null) handleImpl else null,
|
|
.calculate_timeout_fn = if (calculate_timeout_fn != null) calculateTimeoutImpl else null,
|
|
};
|
|
};
|
|
|
|
idCounter += 1;
|
|
return .{
|
|
.id = idCounter,
|
|
.display_name = display_name,
|
|
.keybinds = keybinds,
|
|
.pointer = pointer,
|
|
.vtable = Impl.vtable,
|
|
};
|
|
}
|
|
|
|
pub fn deinit(self: *Widget) void {
|
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
|
|
|
if (self.vtable.deinit_fn) |deinit_fn| {
|
|
return @call(
|
|
.auto,
|
|
deinit_fn,
|
|
.{impl},
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn realloc(self: *Widget) !void {
|
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
|
|
|
if (self.vtable.realloc_fn) |realloc_fn| {
|
|
return @call(
|
|
.auto,
|
|
realloc_fn,
|
|
.{impl},
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn draw(self: *Widget) void {
|
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
|
|
|
@call(
|
|
.auto,
|
|
self.vtable.draw_fn,
|
|
.{impl},
|
|
);
|
|
}
|
|
|
|
pub fn update(self: *Widget, ctx: *anyopaque) !void {
|
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
|
|
|
if (self.vtable.update_fn) |update_fn| {
|
|
return @call(
|
|
.auto,
|
|
update_fn,
|
|
.{ impl, ctx },
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn handle(self: *Widget, maybe_key: ?keyboard.Key) !void {
|
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
|
|
|
if (self.vtable.handle_fn) |handle_fn| {
|
|
return @call(
|
|
.auto,
|
|
handle_fn,
|
|
.{ impl, maybe_key },
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn calculateTimeout(self: *Widget, ctx: *anyopaque) !?usize {
|
|
const impl: @TypeOf(self.pointer) = @ptrCast(@alignCast(self.pointer));
|
|
|
|
if (self.vtable.calculate_timeout_fn) |calculate_timeout_fn| {
|
|
return @call(
|
|
.auto,
|
|
calculate_timeout_fn,
|
|
.{ impl, ctx },
|
|
);
|
|
}
|
|
|
|
return null;
|
|
}
|