feat: add per input mode init_command and deinit_command support

closes #92
This commit is contained in:
CJ van den Berg 2025-04-07 21:07:36 +02:00
parent 563eb57e44
commit 6743c99c12
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
2 changed files with 22 additions and 12 deletions

View file

@ -61,6 +61,8 @@ const Handler = struct {
.line_numbers = self.bindings.line_numbers, .line_numbers = self.bindings.line_numbers,
.cursor_shape = self.bindings.cursor_shape, .cursor_shape = self.bindings.cursor_shape,
.selection_style = self.bindings.selection_style, .selection_style = self.bindings.selection_style,
.init_command = self.bindings.init_command,
.deinit_command = self.bindings.deinit_command,
}; };
} }
pub fn deinit(self: *@This()) void { pub fn deinit(self: *@This()) void {
@ -82,8 +84,12 @@ pub const Mode = struct {
keybind_hints: *const KeybindHints, keybind_hints: *const KeybindHints,
cursor_shape: ?CursorShape = null, cursor_shape: ?CursorShape = null,
selection_style: SelectionStyle, selection_style: SelectionStyle,
init_command: ?Command = null,
deinit_command: ?Command = null,
pub fn deinit(self: *Mode) void { pub fn deinit(self: *Mode) void {
if (self.deinit_command) |deinit_|
deinit_.execute_const();
self.allocator.free(self.mode); self.allocator.free(self.mode);
self.input_handler.deinit(); self.input_handler.deinit();
if (self.event_handler) |eh| eh.deinit(); if (self.event_handler) |eh| eh.deinit();
@ -139,18 +145,10 @@ pub fn set_namespace(namespace_name: []const u8) LoadError!void {
const new_namespace = try get_or_load_namespace(namespace_name); const new_namespace = try get_or_load_namespace(namespace_name);
if (globals.current_namespace) |old_namespace| if (globals.current_namespace) |old_namespace|
if (old_namespace.deinit_command) |deinit| if (old_namespace.deinit_command) |deinit|
deinit.execute_const() catch |e| { deinit.execute_const();
const logger = log.logger("keybind");
logger.print_err("deinit_command", "ERROR: {s} {s}", .{ deinit.command, @errorName(e) });
logger.deinit();
};
globals.current_namespace = new_namespace; globals.current_namespace = new_namespace;
if (new_namespace.init_command) |init| if (new_namespace.init_command) |init|
init.execute_const() catch |e| { init.execute_const();
const logger = log.logger("keybind");
logger.print_err("init_command", "ERROR: {s} {s}", .{ init.command, @errorName(e) });
logger.deinit();
};
} }
fn get_mode_binding_set(mode_name: []const u8, insert_command: []const u8) LoadError!*const BindingSet { fn get_mode_binding_set(mode_name: []const u8, insert_command: []const u8) LoadError!*const BindingSet {
@ -267,10 +265,14 @@ const Command = struct {
try command.execute(id, .{ .args = .{ .buf = buf[0..self.args.len] } }); try command.execute(id, .{ .args = .{ .buf = buf[0..self.args.len] } });
} }
fn execute_const(self: *const @This()) !void { pub fn execute_const(self: *const @This()) void {
var buf: [2048]u8 = undefined; var buf: [2048]u8 = undefined;
@memcpy(buf[0..self.args.len], self.args); @memcpy(buf[0..self.args.len], self.args);
try command.executeName(self.command, .{ .args = .{ .buf = buf[0..self.args.len] } }); command.executeName(self.command, .{ .args = .{ .buf = buf[0..self.args.len] } }) catch |e| {
const logger = log.logger("keybind");
logger.print_err("init/deinit_command", "ERROR: {s} {s}", .{ self.command, @errorName(e) });
logger.deinit();
};
} }
fn load(allocator: std.mem.Allocator, tokens: []const std.json.Value) (parse_flow.ParseError || parse_vim.ParseError)!Command { fn load(allocator: std.mem.Allocator, tokens: []const std.json.Value) (parse_flow.ParseError || parse_vim.ParseError)!Command {
@ -373,6 +375,8 @@ const BindingSet = struct {
selection_style: SelectionStyle, selection_style: SelectionStyle,
insert_command: []const u8 = "", insert_command: []const u8 = "",
hints_map: KeybindHints = .{}, hints_map: KeybindHints = .{},
init_command: ?Command = null,
deinit_command: ?Command = null,
const KeySyntax = enum { flow, vim }; const KeySyntax = enum { flow, vim };
const OnMatchFailure = enum { insert, ignore }; const OnMatchFailure = enum { insert, ignore };
@ -391,6 +395,8 @@ const BindingSet = struct {
inherit: ?[]const u8 = null, inherit: ?[]const u8 = null,
inherits: ?[][]const u8 = null, inherits: ?[][]const u8 = null,
selection: ?SelectionStyle = null, selection: ?SelectionStyle = null,
init_command: ?[]const std.json.Value = null,
deinit_command: ?[]const std.json.Value = null,
}; };
const parsed = try std.json.parseFromValue(JsonConfig, allocator, mode_bindings, .{ const parsed = try std.json.parseFromValue(JsonConfig, allocator, mode_bindings, .{
.ignore_unknown_fields = true, .ignore_unknown_fields = true,
@ -402,6 +408,8 @@ const BindingSet = struct {
self.line_numbers = parsed.value.line_numbers; self.line_numbers = parsed.value.line_numbers;
self.cursor_shape = parsed.value.cursor; self.cursor_shape = parsed.value.cursor;
self.selection_style = parsed.value.selection orelse .normal; self.selection_style = parsed.value.selection orelse .normal;
if (parsed.value.init_command) |cmd| self.init_command = try Command.load(allocator, cmd);
if (parsed.value.deinit_command) |cmd| self.deinit_command = try Command.load(allocator, cmd);
try self.load_event(allocator, &self.press, input.event.press, parsed.value.press); try self.load_event(allocator, &self.press, input.event.press, parsed.value.press);
try self.load_event(allocator, &self.release, input.event.release, parsed.value.release); try self.load_event(allocator, &self.release, input.event.release, parsed.value.release);
if (parsed.value.inherits) |sibling_fallbacks| { if (parsed.value.inherits) |sibling_fallbacks| {

View file

@ -673,6 +673,8 @@ fn enter_input_mode(self: *Self, new_mode: Mode) command.Result {
self.input_mode_ = null; self.input_mode_ = null;
} }
self.input_mode_ = new_mode; self.input_mode_ = new_mode;
if (new_mode.init_command) |cmd|
cmd.execute_const();
} }
fn refresh_input_mode(self: *Self) command.Result { fn refresh_input_mode(self: *Self) command.Result {