Compare commits

..

2 commits

Author SHA1 Message Date
d9ab0fd5af
feat: add support in keybind module for looking up key sequence prefix matches
This is the initial part of some sort of which-key like function.
2025-11-28 16:11:41 +01:00
d5eb4d8bd3
fix: avoid setting the terminal background color until we know what the system color scheme is
This was in the hope that it might fix kitty's behavior with
enable_terminal_color_scheme enabled. Unfortunately it makes no
difference to kitty (kitty stops sending color scheme updates). I
am commiting these changes anyway as it seems a little cleaner to
avoid setting the background color twice on startup.
2025-11-28 15:20:50 +01:00
3 changed files with 41 additions and 2 deletions

View file

@ -71,13 +71,15 @@ const Handler = struct {
opts.insert_command opts.insert_command
else else
"insert_chars"; "insert_chars";
const bindings = try get_mode_binding_set(mode_name, insert_command);
self.* = .{ self.* = .{
.allocator = allocator, .allocator = allocator,
.bindings = try get_mode_binding_set(mode_name, insert_command), .bindings = bindings,
}; };
return .{ return .{
.allocator = allocator, .allocator = allocator,
.input_handler = EventHandler.to_owned(self), .input_handler = EventHandler.to_owned(self),
.bindings = bindings,
.keybind_hints = self.bindings.hints(), .keybind_hints = self.bindings.hints(),
.mode = try allocator.dupe(u8, mode_name), .mode = try allocator.dupe(u8, mode_name),
.name = self.bindings.name, .name = self.bindings.name,
@ -127,6 +129,7 @@ pub const Mode = struct {
mode: []const u8, mode: []const u8,
name: []const u8 = "", name: []const u8 = "",
line_numbers: LineNumbers = .inherit, line_numbers: LineNumbers = .inherit,
bindings: *const BindingSet,
keybind_hints: *const KeybindHints, keybind_hints: *const KeybindHints,
cursor_shape: ?CursorShape = null, cursor_shape: ?CursorShape = null,
init_command: ?Command = null, init_command: ?Command = null,
@ -168,6 +171,11 @@ pub const Mode = struct {
self.deinit_command = null; self.deinit_command = null;
self.initialized = false; self.initialized = false;
} }
pub fn current_key_event_sequence_bindings(self: *const Mode, allocator: std.mem.Allocator) error{OutOfMemory}![]const Binding {
if (globals.current_sequence.items.len == 0) return &.{};
return self.bindings.get_matches_for_key_event_sequence(allocator, globals.current_sequence.items);
}
}; };
const NamespaceMap = std.StringHashMapUnmanaged(Namespace); const NamespaceMap = std.StringHashMapUnmanaged(Namespace);
@ -760,6 +768,18 @@ const BindingSet = struct {
globals.current_sequence.clearRetainingCapacity(); globals.current_sequence.clearRetainingCapacity();
} }
} }
/// Retreive bindings that will match a key event sequence
pub fn get_matches_for_key_event_sequence(self: *const @This(), allocator: std.mem.Allocator, sequence: []const KeyEvent) error{OutOfMemory}![]const Binding {
var matches: std.ArrayListUnmanaged(Binding) = .{};
for (self.press.items) |*binding| switch (binding.match(sequence)) {
.matched, .match_possible => {
(try matches.addOne(allocator)).* = binding.*;
},
.match_impossible => {},
};
return matches.toOwnedSlice(allocator);
}
}; };
pub const LineNumbers = enum { pub const LineNumbers = enum {

View file

@ -385,6 +385,8 @@ pub fn process_renderer_event(self: *Self, msg: []const u8) Error!void {
self.queries_done = true; self.queries_done = true;
self.vx.enableDetectedFeatures(self.tty.writer()) catch |e| self.logger.err("enable features", e); self.vx.enableDetectedFeatures(self.tty.writer()) catch |e| self.logger.err("enable features", e);
self.vx.setMouseMode(self.tty.writer(), true) catch return error.TtyWriteError; self.vx.setMouseMode(self.tty.writer(), true) catch return error.TtyWriteError;
self.logger.print("capability queries complete", .{});
if (self.dispatch_event) |f| f(self.handler_ctx, try self.fmtmsg(.{"capability_detection_complete"}));
}, },
.cap_kitty_keyboard => { .cap_kitty_keyboard => {
self.logger.print("kitty keyboard capability detected", .{}); self.logger.print("kitty keyboard capability detected", .{});

View file

@ -207,7 +207,6 @@ fn init(allocator: Allocator) InitError!*Self {
} }
self.mainview_ = try MainView.create(allocator); self.mainview_ = try MainView.create(allocator);
resize(); resize();
self.set_terminal_style(self.current_theme());
try save_config(); try save_config();
try self.init_input_namespace(); try self.init_input_namespace();
if (tp.env.get().is("restore-session")) { if (tp.env.get().is("restore-session")) {
@ -298,6 +297,15 @@ fn handle_input_idle(self: *Self) void {
var buf: [32]u8 = undefined; var buf: [32]u8 = undefined;
const m = tp.message.fmtbuf(&buf, .{"input_idle"}) catch return; const m = tp.message.fmtbuf(&buf, .{"input_idle"}) catch return;
_ = self.send_widgets(tp.self_pid(), m) catch return; _ = self.send_widgets(tp.self_pid(), m) catch return;
if (self.input_mode_) |mode| {
const bindings = mode.current_key_event_sequence_bindings(self.allocator) catch return;
defer self.allocator.free(bindings);
for (bindings) |binding|
self.logger.print(" {f} => {s}", .{
keybind.key_event_sequence_fmt(binding.key_events),
binding.commands[0].command,
});
}
} }
fn update_input_idle_timer(self: *Self) void { fn update_input_idle_timer(self: *Self) void {
@ -516,15 +524,23 @@ fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) !void {
} }
if (try m.match(.{ "color_scheme", "dark" })) { if (try m.match(.{ "color_scheme", "dark" })) {
self.logger.print("system color scheme event: dark", .{});
self.set_color_scheme(.dark); self.set_color_scheme(.dark);
return; return;
} }
if (try m.match(.{ "color_scheme", "light" })) { if (try m.match(.{ "color_scheme", "light" })) {
self.logger.print("system color scheme event: light", .{});
self.set_color_scheme(.light); self.set_color_scheme(.light);
return; return;
} }
if (try m.match(.{"capability_detection_complete"})) {
if (!self.rdr_.vx.caps.color_scheme_updates)
self.set_terminal_style(self.current_theme());
return;
}
return tp.unexpected(m); return tp.unexpected(m);
} }
@ -1769,6 +1785,7 @@ pub const fallbacks: []const FallBack = &[_]FallBack{
}; };
fn set_terminal_style(self: *Self, theme_: *const Widget.Theme) void { fn set_terminal_style(self: *Self, theme_: *const Widget.Theme) void {
self.logger.print("set terminal style {s}", .{theme_.name});
self.rdr_.set_terminal_cursor_color(theme_.editor_cursor.bg.?); self.rdr_.set_terminal_cursor_color(theme_.editor_cursor.bg.?);
if (self.rdr_.vx.caps.multi_cursor) if (self.rdr_.vx.caps.multi_cursor)
self.rdr_.set_terminal_secondary_cursor_color(theme_.editor_cursor_secondary.bg orelse theme_.editor_cursor.bg.?); self.rdr_.set_terminal_secondary_cursor_color(theme_.editor_cursor_secondary.bg orelse theme_.editor_cursor.bg.?);