mirror of
https://github.com/fairyglade/ly.git
synced 2026-03-21 22:43:38 +00:00
Add support for local keybinds
Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
@@ -15,8 +15,8 @@ const Widget = @import("Widget.zig");
|
||||
|
||||
const TerminalBuffer = @This();
|
||||
|
||||
const KeybindCallbackFn = *const fn (*anyopaque) anyerror!bool;
|
||||
const KeybindMap = std.AutoHashMap(keyboard.Key, struct {
|
||||
pub const KeybindCallbackFn = *const fn (*anyopaque) anyerror!bool;
|
||||
pub const KeybindMap = std.AutoHashMap(keyboard.Key, struct {
|
||||
callback: KeybindCallbackFn,
|
||||
context: *anyopaque,
|
||||
});
|
||||
@@ -177,14 +177,14 @@ pub fn runEventLoop(
|
||||
inactivity_event_fn: ?*const fn (*anyopaque) anyerror!void,
|
||||
context: *anyopaque,
|
||||
) !void {
|
||||
try self.registerKeybind("Ctrl+K", &moveCursorUp, self);
|
||||
try self.registerKeybind("Up", &moveCursorUp, self);
|
||||
try self.registerGlobalKeybind("Ctrl+K", &moveCursorUp, self);
|
||||
try self.registerGlobalKeybind("Up", &moveCursorUp, self);
|
||||
|
||||
try self.registerKeybind("Ctrl+J", &moveCursorDown, self);
|
||||
try self.registerKeybind("Down", &moveCursorDown, self);
|
||||
try self.registerGlobalKeybind("Ctrl+J", &moveCursorDown, self);
|
||||
try self.registerGlobalKeybind("Down", &moveCursorDown, self);
|
||||
|
||||
try self.registerKeybind("Tab", &wrapCursor, self);
|
||||
try self.registerKeybind("Shift+Tab", &wrapCursorReverse, self);
|
||||
try self.registerGlobalKeybind("Tab", &wrapCursor, self);
|
||||
try self.registerGlobalKeybind("Shift+Tab", &wrapCursorReverse, self);
|
||||
|
||||
defer self.handlable_widgets.deinit(allocator);
|
||||
|
||||
@@ -402,13 +402,14 @@ pub fn reclaim(self: TerminalBuffer) !void {
|
||||
|
||||
pub fn registerKeybind(
|
||||
self: *TerminalBuffer,
|
||||
keybinds: *KeybindMap,
|
||||
keybind: []const u8,
|
||||
callback: KeybindCallbackFn,
|
||||
context: *anyopaque,
|
||||
) !void {
|
||||
const key = try self.parseKeybind(keybind);
|
||||
|
||||
self.keybinds.put(key, .{
|
||||
keybinds.put(key, .{
|
||||
.callback = callback,
|
||||
.context = context,
|
||||
}) catch |err| {
|
||||
@@ -420,6 +421,15 @@ pub fn registerKeybind(
|
||||
};
|
||||
}
|
||||
|
||||
pub fn registerGlobalKeybind(
|
||||
self: *TerminalBuffer,
|
||||
keybind: []const u8,
|
||||
callback: KeybindCallbackFn,
|
||||
context: *anyopaque,
|
||||
) !void {
|
||||
try self.registerKeybind(&self.keybinds, keybind, callback, context);
|
||||
}
|
||||
|
||||
pub fn simulateKeybind(self: *TerminalBuffer, keybind: []const u8) !bool {
|
||||
const key = try self.parseKeybind(keybind);
|
||||
|
||||
@@ -552,6 +562,24 @@ fn handleKeybind(
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
const current_widget = self.getActiveWidget();
|
||||
if (current_widget.keybinds) |keybinds| {
|
||||
if (keybinds.get(key)) |binding| {
|
||||
const passthrough_event = try @call(
|
||||
.auto,
|
||||
binding.callback,
|
||||
.{binding.context},
|
||||
);
|
||||
|
||||
if (!passthrough_event) {
|
||||
keys.deinit(allocator);
|
||||
return null;
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
|
||||
@@ -14,11 +14,13 @@ const VTable = struct {
|
||||
|
||||
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,
|
||||
@@ -102,6 +104,7 @@ pub fn init(
|
||||
return .{
|
||||
.id = @intFromPtr(Impl.vtable.draw_fn),
|
||||
.display_name = display_name,
|
||||
.keybinds = keybinds,
|
||||
.pointer = pointer,
|
||||
.vtable = Impl.vtable,
|
||||
};
|
||||
|
||||
@@ -88,6 +88,7 @@ pub fn deinit(self: *BigLabel) void {
|
||||
pub fn widget(self: *BigLabel) Widget {
|
||||
return Widget.init(
|
||||
"BigLabel",
|
||||
null,
|
||||
self,
|
||||
deinit,
|
||||
null,
|
||||
|
||||
@@ -62,6 +62,7 @@ pub fn init(
|
||||
pub fn widget(self: *CenteredBox) Widget {
|
||||
return Widget.init(
|
||||
"CenteredBox",
|
||||
null,
|
||||
self,
|
||||
null,
|
||||
null,
|
||||
|
||||
@@ -46,6 +46,7 @@ pub fn deinit(self: *Label) void {
|
||||
pub fn widget(self: *Label) Widget {
|
||||
return Widget.init(
|
||||
"Label",
|
||||
null,
|
||||
self,
|
||||
deinit,
|
||||
null,
|
||||
|
||||
@@ -23,6 +23,7 @@ masked: bool,
|
||||
maybe_mask: ?u32,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
keybinds: TerminalBuffer.KeybindMap,
|
||||
|
||||
pub fn init(
|
||||
allocator: Allocator,
|
||||
@@ -32,8 +33,9 @@ pub fn init(
|
||||
width: usize,
|
||||
fg: u32,
|
||||
bg: u32,
|
||||
) Text {
|
||||
return .{
|
||||
) !*Text {
|
||||
var self = try allocator.create(Text);
|
||||
self.* = Text{
|
||||
.allocator = allocator,
|
||||
.buffer = buffer,
|
||||
.text = .empty,
|
||||
@@ -47,16 +49,24 @@ pub fn init(
|
||||
.maybe_mask = maybe_mask,
|
||||
.fg = fg,
|
||||
.bg = bg,
|
||||
.keybinds = .init(allocator),
|
||||
};
|
||||
|
||||
try buffer.registerKeybind(&self.keybinds, "Ctrl+U", &clearTextEntry, self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Text) void {
|
||||
self.text.deinit(self.allocator);
|
||||
self.keybinds.deinit();
|
||||
self.allocator.destroy(self);
|
||||
}
|
||||
|
||||
pub fn widget(self: *Text) Widget {
|
||||
return Widget.init(
|
||||
"Text",
|
||||
self.keybinds,
|
||||
self,
|
||||
deinit,
|
||||
null,
|
||||
@@ -208,3 +218,11 @@ fn write(self: *Text, char: u8) !void {
|
||||
self.end += 1;
|
||||
self.goRight();
|
||||
}
|
||||
|
||||
fn clearTextEntry(ptr: *anyopaque) !bool {
|
||||
var self: *Text = @ptrCast(@alignCast(ptr));
|
||||
|
||||
self.clear();
|
||||
self.buffer.drawNextFrame(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user