refactor: move vim mode keybindings to keybind module

This commit is contained in:
CJ van den Berg 2024-11-12 22:20:02 +01:00
parent 4be4fe76e9
commit cf50f77abf
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
7 changed files with 72 additions and 77 deletions

View file

@ -16,7 +16,7 @@ input: std.ArrayList(u8),
last_cmd: []const u8 = "", last_cmd: []const u8 = "",
leader: ?struct { keypress: u32, modifiers: u32 } = null, leader: ?struct { keypress: u32, modifiers: u32 } = null,
pub fn create(allocator: std.mem.Allocator) !EventHandler { pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler {
const self: *Self = try allocator.create(Self); const self: *Self = try allocator.create(Self);
self.* = .{ self.* = .{
.allocator = allocator, .allocator = allocator,

View file

@ -13,7 +13,7 @@ allocator: std.mem.Allocator,
f: usize = 0, f: usize = 0,
leader: ?struct { keypress: u32, modifiers: u32 } = null, leader: ?struct { keypress: u32, modifiers: u32 } = null,
pub fn create(allocator: std.mem.Allocator) !EventHandler { pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler {
const self: *Self = try allocator.create(Self); const self: *Self = try allocator.create(Self);
self.* = .{ self.* = .{
.allocator = allocator, .allocator = allocator,

View file

@ -1,28 +1,23 @@
const tp = @import("thespian");
const std = @import("std"); const std = @import("std");
const tp = @import("thespian");
const key = @import("renderer").input.key; const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier; const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type; const event_type = @import("renderer").input.event_type;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8; const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const command = @import("command"); const command = @import("command");
const EventHandler = @import("EventHandler"); const EventHandler = @import("EventHandler");
const keybind = @import("../../keybind.zig");
const tui = @import("../../../tui.zig");
const Allocator = @import("std").mem.Allocator;
const ArrayList = @import("std").ArrayList;
const eql = @import("std").mem.eql;
const Self = @This(); const Self = @This();
const input_buffer_size = 1024; const input_buffer_size = 1024;
allocator: Allocator, allocator: std.mem.Allocator,
input: ArrayList(u8), input: std.ArrayList(u8),
last_cmd: []const u8 = "", last_cmd: []const u8 = "",
leader: ?struct { keypress: u32, modifiers: u32 } = null, leader: ?struct { keypress: u32, modifiers: u32 } = null,
commands: Commands = undefined, commands: Commands = undefined,
last_key: KeyPressEvent = .{}, last_key: KeyPressEvent = .{},
enable_chording: bool,
pub const KeyPressEvent = struct { pub const KeyPressEvent = struct {
keypress: u32 = 0, keypress: u32 = 0,
@ -31,19 +26,15 @@ pub const KeyPressEvent = struct {
timestamp_ms: i64 = 0, timestamp_ms: i64 = 0,
}; };
pub fn create(allocator: Allocator) !tui.Mode { pub fn create(allocator: std.mem.Allocator, opts: anytype) !EventHandler {
const self: *Self = try allocator.create(Self); const self: *Self = try allocator.create(Self);
self.* = .{ self.* = .{
.allocator = allocator, .allocator = allocator,
.input = try ArrayList(u8).initCapacity(allocator, input_buffer_size), .input = try std.ArrayList(u8).initCapacity(allocator, input_buffer_size),
.enable_chording = opts.enable_chording,
}; };
try self.commands.init(self); try self.commands.init(self);
return .{ return EventHandler.to_owned(self);
.input_handler = EventHandler.to_owned(self),
.name = "INSERT",
.line_numbers = if (tui.current().config.vim_insert_gutter_line_numbers_relative) .relative else .absolute,
.cursor_shape = .beam,
};
} }
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
@ -91,7 +82,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
else => {}, else => {},
} }
if (tui.current().config.vim_insert_chording_keybindings) { if (self.enable_chording) {
//reset chord if enough time has passed //reset chord if enough time has passed
const chord_time_window_ms = 750; const chord_time_window_ms = 750;
@ -337,9 +328,9 @@ fn cmd(self: *Self, name_: []const u8, ctx: command.Context) tp.result {
} }
fn cmd_cycle3(self: *Self, name1: []const u8, name2: []const u8, name3: []const u8, ctx: command.Context) tp.result { fn cmd_cycle3(self: *Self, name1: []const u8, name2: []const u8, name3: []const u8, ctx: command.Context) tp.result {
return if (eql(u8, self.last_cmd, name2)) return if (std.mem.eql(u8, self.last_cmd, name2))
self.cmd(name3, ctx) self.cmd(name3, ctx)
else if (eql(u8, self.last_cmd, name1)) else if (std.mem.eql(u8, self.last_cmd, name1))
self.cmd(name2, ctx) self.cmd(name2, ctx)
else else
self.cmd(name1, ctx); self.cmd(name1, ctx);
@ -350,6 +341,8 @@ fn cmd_async(self: *Self, name_: []const u8) tp.result {
return tp.self_pid().send(.{ "cmd", name_ }); return tp.self_pid().send(.{ "cmd", name_ });
} }
pub const hints = keybind.KeybindHints.initComptime(.{});
const Commands = command.Collection(cmds_); const Commands = command.Collection(cmds_);
const cmds_ = struct { const cmds_ = struct {
pub const Target = Self; pub const Target = Self;

View file

@ -1,42 +1,31 @@
const std = @import("std");
const tp = @import("thespian"); const tp = @import("thespian");
const key = @import("renderer").input.key; const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier; const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type; const event_type = @import("renderer").input.event_type;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8; const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const command = @import("command"); const command = @import("command");
const EventHandler = @import("EventHandler"); const EventHandler = @import("EventHandler");
const keybind = @import("../../keybind.zig");
const tui = @import("../../../tui.zig");
const Allocator = @import("std").mem.Allocator;
const ArrayList = @import("std").ArrayList;
const eql = @import("std").mem.eql;
const Self = @This(); const Self = @This();
const input_buffer_size = 1024; const input_buffer_size = 1024;
allocator: Allocator, allocator: std.mem.Allocator,
input: ArrayList(u8), input: std.ArrayList(u8),
last_cmd: []const u8 = "", last_cmd: []const u8 = "",
leader: ?struct { keypress: u32, modifiers: u32 } = null, leader: ?struct { keypress: u32, modifiers: u32 } = null,
count: usize = 0, count: usize = 0,
commands: Commands = undefined, commands: Commands = undefined,
pub fn create(allocator: Allocator) !tui.Mode { pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler {
const self: *Self = try allocator.create(Self); const self: *Self = try allocator.create(Self);
self.* = .{ self.* = .{
.allocator = allocator, .allocator = allocator,
.input = try ArrayList(u8).initCapacity(allocator, input_buffer_size), .input = try std.ArrayList(u8).initCapacity(allocator, input_buffer_size),
}; };
try self.commands.init(self); try self.commands.init(self);
return .{ return EventHandler.to_owned(self);
.input_handler = EventHandler.to_owned(self),
.name = "NORMAL",
.line_numbers = if (tui.current().config.vim_normal_gutter_line_numbers_relative) .relative else .absolute,
.keybind_hints = &hints,
.cursor_shape = .block,
};
} }
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
@ -471,9 +460,9 @@ fn cmd_count(self: *Self, name_: []const u8, ctx: command.Context) tp.result {
} }
fn cmd_cycle3(self: *Self, name1: []const u8, name2: []const u8, name3: []const u8, ctx: command.Context) tp.result { fn cmd_cycle3(self: *Self, name1: []const u8, name2: []const u8, name3: []const u8, ctx: command.Context) tp.result {
return if (eql(u8, self.last_cmd, name2)) return if (std.mem.eql(u8, self.last_cmd, name2))
self.cmd(name3, ctx) self.cmd(name3, ctx)
else if (eql(u8, self.last_cmd, name1)) else if (std.mem.eql(u8, self.last_cmd, name1))
self.cmd(name2, ctx) self.cmd(name2, ctx)
else else
self.cmd(name1, ctx); self.cmd(name1, ctx);
@ -503,7 +492,7 @@ fn seq_count(self: *Self, cmds: anytype, ctx: command.Context) tp.result {
try self.cmd(@field(cmds, field_info.name), ctx); try self.cmd(@field(cmds, field_info.name), ctx);
} }
const hints = tui.KeybindHints.initComptime(.{ pub const hints = keybind.KeybindHints.initComptime(.{
.{ "add_cursor_all_matches", "C-S-l" }, .{ "add_cursor_all_matches", "C-S-l" },
.{ "add_cursor_down", "S-A-down" }, .{ "add_cursor_down", "S-A-down" },
.{ "add_cursor_next_match", "C-d" }, .{ "add_cursor_next_match", "C-d" },

View file

@ -1,42 +1,31 @@
const std = @import("std");
const tp = @import("thespian"); const tp = @import("thespian");
const key = @import("renderer").input.key; const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier; const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type; const event_type = @import("renderer").input.event_type;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8; const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const command = @import("command"); const command = @import("command");
const EventHandler = @import("EventHandler"); const EventHandler = @import("EventHandler");
const keybind = @import("../../keybind.zig");
const tui = @import("../../../tui.zig");
const Allocator = @import("std").mem.Allocator;
const ArrayList = @import("std").ArrayList;
const eql = @import("std").mem.eql;
const Self = @This(); const Self = @This();
const input_buffer_size = 1024; const input_buffer_size = 1024;
allocator: Allocator, allocator: std.mem.Allocator,
input: ArrayList(u8), input: std.ArrayList(u8),
last_cmd: []const u8 = "", last_cmd: []const u8 = "",
leader: ?struct { keypress: u32, modifiers: u32 } = null, leader: ?struct { keypress: u32, modifiers: u32 } = null,
count: usize = 0, count: usize = 0,
commands: Commands = undefined, commands: Commands = undefined,
pub fn create(allocator: Allocator) !tui.Mode { pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler {
const self: *Self = try allocator.create(Self); const self: *Self = try allocator.create(Self);
self.* = .{ self.* = .{
.allocator = allocator, .allocator = allocator,
.input = try ArrayList(u8).initCapacity(allocator, input_buffer_size), .input = try std.ArrayList(u8).initCapacity(allocator, input_buffer_size),
}; };
try self.commands.init(self); try self.commands.init(self);
return .{ return EventHandler.to_owned(self);
.input_handler = EventHandler.to_owned(self),
.name = "VISUAL",
.line_numbers = if (tui.current().config.vim_visual_gutter_line_numbers_relative) .relative else .absolute,
.keybind_hints = &hints,
.cursor_shape = .underline,
};
} }
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
@ -422,9 +411,9 @@ fn cmd_count(self: *Self, name_: []const u8, ctx: command.Context) tp.result {
} }
fn cmd_cycle3(self: *Self, name1: []const u8, name2: []const u8, name3: []const u8, ctx: command.Context) tp.result { fn cmd_cycle3(self: *Self, name1: []const u8, name2: []const u8, name3: []const u8, ctx: command.Context) tp.result {
return if (eql(u8, self.last_cmd, name2)) return if (std.mem.eql(u8, self.last_cmd, name2))
self.cmd(name3, ctx) self.cmd(name3, ctx)
else if (eql(u8, self.last_cmd, name1)) else if (std.mem.eql(u8, self.last_cmd, name1))
self.cmd(name2, ctx) self.cmd(name2, ctx)
else else
self.cmd(name1, ctx); self.cmd(name1, ctx);
@ -454,7 +443,7 @@ fn seq_count(self: *Self, cmds: anytype, ctx: command.Context) tp.result {
try self.cmd(@field(cmds, field_info.name), ctx); try self.cmd(@field(cmds, field_info.name), ctx);
} }
const hints = tui.KeybindHints.initComptime(.{ pub const hints = keybind.KeybindHints.initComptime(.{
.{ "add_cursor_all_matches", "C-S-l" }, .{ "add_cursor_all_matches", "C-S-l" },
.{ "add_cursor_down", "S-A-down" }, .{ "add_cursor_down", "S-A-down" },
.{ "add_cursor_next_match", "C-d" }, .{ "add_cursor_next_match", "C-d" },

View file

@ -2,6 +2,11 @@ pub const mode = struct {
pub const input = struct { pub const input = struct {
pub const flow = @import("input/flow.zig"); pub const flow = @import("input/flow.zig");
pub const home = @import("input/home.zig"); pub const home = @import("input/home.zig");
pub const vim = struct {
pub const normal = @import("input/vim/normal.zig");
pub const insert = @import("input/vim/insert.zig");
pub const visual = @import("input/vim/visual.zig");
};
}; };
pub const overlay = struct { pub const overlay = struct {
pub const palette = @import("overlay/palette.zig"); pub const palette = @import("overlay/palette.zig");

View file

@ -561,11 +561,20 @@ fn enter_overlay_mode(self: *Self, mode: type) command.Result {
self.refresh_hover(); self.refresh_hover();
} }
fn static_mode(self: *Self, mode: anytype, name: []const u8) !Mode { fn static_mode(self: *Self, mode: anytype, name: []const u8, opts: anytype) !Mode {
// .line_numbers_relative = if (self.config.vim_normal_gutter_line_numbers_relative) .relative else .absolute,
return .{ return .{
.input_handler = try mode.create(self.allocator), .input_handler = try mode.create(self.allocator, opts),
.name = name, .name = name,
.keybind_hints = &mode.hints, .keybind_hints = &mode.hints,
.line_numbers = if (@hasField(@TypeOf(opts), "line_numbers_relative"))
if (opts.line_numbers_relative)
.relative
else
.absolute
else
.absolute,
.cursor_shape = if (@hasField(@TypeOf(opts), "cursor_shape")) opts.cursor_shape else .block,
}; };
} }
@ -656,11 +665,21 @@ const cmds = struct {
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{}); if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
if (self.input_mode) |*m| m.deinit(); if (self.input_mode) |*m| m.deinit();
self.input_mode = if (std.mem.eql(u8, mode, "vim/normal")) self.input_mode = if (std.mem.eql(u8, mode, "vim/normal"))
try @import("mode/input/vim/normal.zig").create(self.allocator) try self.static_mode(keybind.mode.input.vim.normal, "NORMAL", .{
.line_numbers_relative = self.config.vim_normal_gutter_line_numbers_relative,
.cursor_shape = .block,
})
else if (std.mem.eql(u8, mode, "vim/insert")) else if (std.mem.eql(u8, mode, "vim/insert"))
try @import("mode/input/vim/insert.zig").create(self.allocator) try self.static_mode(keybind.mode.input.vim.insert, "INSERT", .{
.enable_chording = self.config.vim_insert_chording_keybindings,
.line_numbers_relative = self.config.vim_insert_gutter_line_numbers_relative,
.cursor_shape = .beam,
})
else if (std.mem.eql(u8, mode, "vim/visual")) else if (std.mem.eql(u8, mode, "vim/visual"))
try @import("mode/input/vim/visual.zig").create(self.allocator) try self.static_mode(keybind.mode.input.vim.visual, "VISUAL", .{
.line_numbers_relative = self.config.vim_visual_gutter_line_numbers_relative,
.cursor_shape = .underline,
})
else if (std.mem.eql(u8, mode, "helix/normal")) else if (std.mem.eql(u8, mode, "helix/normal"))
try @import("mode/input/helix/normal.zig").create(self.allocator) try @import("mode/input/helix/normal.zig").create(self.allocator)
else if (std.mem.eql(u8, mode, "helix/insert")) else if (std.mem.eql(u8, mode, "helix/insert"))
@ -668,12 +687,12 @@ const cmds = struct {
else if (std.mem.eql(u8, mode, "helix/select")) else if (std.mem.eql(u8, mode, "helix/select"))
try @import("mode/input/helix/select.zig").create(self.allocator) try @import("mode/input/helix/select.zig").create(self.allocator)
else if (std.mem.eql(u8, mode, "flow")) else if (std.mem.eql(u8, mode, "flow"))
try self.static_mode(keybind.mode.input.flow, "flow") try self.static_mode(keybind.mode.input.flow, "flow", .{})
else if (std.mem.eql(u8, mode, "home")) else if (std.mem.eql(u8, mode, "home"))
try self.static_mode(keybind.mode.input.home, "home") try self.static_mode(keybind.mode.input.home, "home", .{})
else ret: { else ret: {
self.logger.print("unknown mode {s}", .{mode}); self.logger.print("unknown mode {s}", .{mode});
break :ret try self.static_mode(keybind.mode.input.flow, "flow"); break :ret try self.static_mode(keybind.mode.input.flow, "flow", .{});
}; };
// self.logger.print("input mode: {s}", .{(self.input_mode orelse return).description}); // self.logger.print("input mode: {s}", .{(self.input_mode orelse return).description});
} }