Fix insert mode hack + fix bugs

Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
AnErrupTion
2026-03-17 23:58:06 +01:00
parent acac884cfe
commit 9c50297059
9 changed files with 129 additions and 65 deletions

View File

@@ -172,7 +172,6 @@ pub fn runEventLoop(
layers: [][]Widget,
active_widget: Widget,
inactivity_delay: u16,
insert_mode: *bool,
position_widgets_fn: *const fn (*anyopaque) anyerror!void,
inactivity_event_fn: ?*const fn (*anyopaque) anyerror!void,
context: *anyopaque,
@@ -221,7 +220,7 @@ pub fn runEventLoop(
// Reset cursor
const current_widget = self.getActiveWidget();
current_widget.handle(null, insert_mode.*) catch |err| {
current_widget.handle(null) catch |err| {
shared_error.writeError(error.SetCursorFailed);
try self.log_file.err(
"tui",
@@ -303,7 +302,7 @@ pub fn runEventLoop(
const current_widget = self.getActiveWidget();
for (keys.items) |key| {
current_widget.handle(key, insert_mode.*) catch |err| {
current_widget.handle(key) catch |err| {
shared_error.writeError(error.CurrentWidgetHandlingFailed);
try self.log_file.err(
"tui",
@@ -441,6 +440,17 @@ pub fn simulateKeybind(self: *TerminalBuffer, keybind: []const u8) !bool {
);
}
const current_widget = self.getActiveWidget();
if (current_widget.keybinds) |keybinds| {
if (keybinds.get(key)) |binding| {
return try @call(
.auto,
binding.callback,
.{binding.context},
);
}
}
return true;
}

View File

@@ -8,7 +8,7 @@ const VTable = struct {
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, insert_mode: bool) 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,
};
@@ -26,7 +26,7 @@ pub fn init(
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, insert_mode: bool) 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);
@@ -71,13 +71,13 @@ pub fn init(
);
}
pub fn handleImpl(ptr: *anyopaque, maybe_key: ?keyboard.Key, insert_mode: bool) !void {
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, insert_mode },
.{ impl, maybe_key },
);
}
@@ -156,14 +156,14 @@ pub fn update(self: *Widget, ctx: *anyopaque) !void {
}
}
pub fn handle(self: *Widget, maybe_key: ?keyboard.Key, insert_mode: bool) !void {
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, insert_mode },
.{ impl, maybe_key },
);
}
}

View File

@@ -67,7 +67,7 @@ pub fn widget(self: *CenteredBox) Widget {
null,
null,
draw,
null,
update,
null,
null,
);

View File

@@ -19,6 +19,7 @@ visible_start: usize,
width: usize,
component_pos: Position,
children_pos: Position,
should_insert: bool,
masked: bool,
maybe_mask: ?u32,
fg: u32,
@@ -28,6 +29,7 @@ keybinds: TerminalBuffer.KeybindMap,
pub fn init(
allocator: Allocator,
buffer: *TerminalBuffer,
should_insert: bool,
masked: bool,
maybe_mask: ?u32,
width: usize,
@@ -45,6 +47,7 @@ pub fn init(
.width = width,
.component_pos = TerminalBuffer.START_POSITION,
.children_pos = TerminalBuffer.START_POSITION,
.should_insert = should_insert,
.masked = masked,
.maybe_mask = maybe_mask,
.fg = fg,
@@ -52,6 +55,10 @@ pub fn init(
.keybinds = .init(allocator),
};
try buffer.registerKeybind(&self.keybinds, "Left", &goLeft, self);
try buffer.registerKeybind(&self.keybinds, "Right", &goRight, self);
try buffer.registerKeybind(&self.keybinds, "Delete", &delete, self);
try buffer.registerKeybind(&self.keybinds, "Backspace", &backspace, self);
try buffer.registerKeybind(&self.keybinds, "Ctrl+U", &clearTextEntry, self);
return self;
@@ -110,17 +117,9 @@ pub fn toggleMask(self: *Text) void {
self.masked = !self.masked;
}
pub fn handle(self: *Text, maybe_key: ?keyboard.Key, insert_mode: bool) !void {
pub fn handle(self: *Text, maybe_key: ?keyboard.Key) !void {
if (maybe_key) |key| {
if (key.left or (!insert_mode and (key.h or key.backspace))) {
self.goLeft();
} else if (key.right or (!insert_mode and key.l)) {
self.goRight();
} else if (key.delete) {
self.delete();
} else if (key.backspace) {
self.backspace();
} else if (insert_mode) {
if (self.should_insert) {
const maybe_character = key.getEnabledPrintableAscii();
if (maybe_character) |character| try self.write(character);
}
@@ -181,33 +180,45 @@ fn draw(self: *Text) void {
);
}
fn goLeft(self: *Text) void {
if (self.cursor == 0) return;
fn goLeft(ptr: *anyopaque) !bool {
var self: *Text = @ptrCast(@alignCast(ptr));
if (self.cursor == 0) return false;
if (self.visible_start > 0) self.visible_start -= 1;
self.cursor -= 1;
return false;
}
fn goRight(self: *Text) void {
if (self.cursor >= self.end) return;
fn goRight(ptr: *anyopaque) !bool {
var self: *Text = @ptrCast(@alignCast(ptr));
if (self.cursor >= self.end) return false;
if (self.cursor - self.visible_start == self.width - 1) self.visible_start += 1;
self.cursor += 1;
return false;
}
fn delete(self: *Text) void {
if (self.cursor >= self.end) return;
fn delete(ptr: *anyopaque) !bool {
var self: *Text = @ptrCast(@alignCast(ptr));
if (self.cursor >= self.end or !self.should_insert) return false;
_ = self.text.orderedRemove(self.cursor);
self.end -= 1;
return false;
}
fn backspace(self: *Text) void {
if (self.cursor == 0) return;
fn backspace(ptr: *anyopaque) !bool {
const self: *Text = @ptrCast(@alignCast(ptr));
self.goLeft();
self.delete();
if (self.cursor == 0 or !self.should_insert) return false;
_ = try goLeft(ptr);
_ = try delete(ptr);
return false;
}
fn write(self: *Text, char: u8) !void {
@@ -216,12 +227,14 @@ fn write(self: *Text, char: u8) !void {
try self.text.insert(self.allocator, self.cursor, char);
self.end += 1;
self.goRight();
_ = try goRight(self);
}
fn clearTextEntry(ptr: *anyopaque) !bool {
var self: *Text = @ptrCast(@alignCast(ptr));
if (!self.should_insert) return false;
self.clear();
self.buffer.drawNextFrame(true);
return false;

View File

@@ -28,6 +28,7 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
draw_item_fn: DrawItemFn,
change_item_fn: ?ChangeItemFn,
change_item_arg: ?ChangeItemType,
keybinds: TerminalBuffer.KeybindMap,
pub fn init(
allocator: Allocator,
@@ -39,8 +40,9 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
text_in_center: bool,
fg: u32,
bg: u32,
) Self {
return .{
) !*Self {
var self = try allocator.create(Self);
self.* = .{
.allocator = allocator,
.buffer = buffer,
.list = .empty,
@@ -55,11 +57,21 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
.draw_item_fn = draw_item_fn,
.change_item_fn = change_item_fn,
.change_item_arg = change_item_arg,
.keybinds = .init(allocator),
};
try buffer.registerKeybind(&self.keybinds, "Left", &goLeft, self);
try buffer.registerKeybind(&self.keybinds, "Ctrl+H", &goLeft, self);
try buffer.registerKeybind(&self.keybinds, "Right", &goRight, self);
try buffer.registerKeybind(&self.keybinds, "Ctrl+L", &goRight, self);
return self;
}
pub fn deinit(self: *Self) void {
self.list.deinit(self.allocator);
self.keybinds.deinit();
self.allocator.destroy(self);
}
pub fn positionX(self: *Self, original_pos: Position) void {
@@ -92,15 +104,7 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
self.current = self.list.items.len - 1;
}
pub fn handle(self: *Self, maybe_key: ?keyboard.Key, insert_mode: bool) void {
if (maybe_key) |key| {
if (key.left or (key.ctrl and key.h) or (!insert_mode and key.h)) {
self.goLeft();
} else if (key.right or (key.ctrl and key.l) or (!insert_mode and key.l)) {
self.goRight();
}
}
pub fn handle(self: *Self, _: ?keyboard.Key) void {
TerminalBuffer.setCursor(
self.component_pos.x + self.cursor + 2,
self.component_pos.y,
@@ -132,7 +136,9 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
);
}
fn goLeft(self: *Self) void {
fn goLeft(ptr: *anyopaque) !bool {
var self: *Self = @ptrCast(@alignCast(ptr));
self.current = if (self.current == 0) self.list.items.len - 1 else self.current - 1;
if (self.change_item_fn) |change_item_fn| {
@@ -142,9 +148,13 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
.{ self.list.items[self.current], self.change_item_arg },
);
}
return false;
}
fn goRight(self: *Self) void {
fn goRight(ptr: *anyopaque) !bool {
var self: *Self = @ptrCast(@alignCast(ptr));
self.current = if (self.current == self.list.items.len - 1) 0 else self.current + 1;
if (self.change_item_fn) |change_item_fn| {
@@ -154,6 +164,8 @@ pub fn CyclableLabel(comptime ItemType: type, comptime ChangeItemType: type) typ
.{ self.list.items[self.current], self.change_item_arg },
);
}
return false;
}
};
}