diff --git a/src/config.zig b/src/config.zig index 52826f1..1689908 100644 --- a/src/config.zig +++ b/src/config.zig @@ -8,6 +8,7 @@ gutter_line_numbers_relative: bool = false, vim_normal_gutter_line_numbers_relative: bool = true, vim_visual_gutter_line_numbers_relative: bool = true, vim_insert_gutter_line_numbers_relative: bool = false, +vim_insert_chording_keybindings: bool = true, enable_terminal_cursor: bool = false, enable_terminal_color_scheme: bool = builtin.os.tag != .windows, highlight_current_line: bool = true, diff --git a/src/tui/mode/input/vim/insert.zig b/src/tui/mode/input/vim/insert.zig index 4746e93..6407b68 100644 --- a/src/tui/mode/input/vim/insert.zig +++ b/src/tui/mode/input/vim/insert.zig @@ -1,4 +1,5 @@ const tp = @import("thespian"); +const std = @import("std"); const key = @import("renderer").input.key; const mod = @import("renderer").input.modifier; @@ -21,6 +22,14 @@ input: ArrayList(u8), last_cmd: []const u8 = "", leader: ?struct { keypress: u32, modifiers: u32 } = null, commands: Commands = undefined, +last_key: KeyPressEvent = .{}, + +pub const KeyPressEvent = struct { + keypress: u32 = 0, + modifiers: u32 = std.math.maxInt(u32), + egc: u32 = 0, + timestamp_ms: i64 = 0, +}; pub fn create(allocator: Allocator) !tui.Mode { const self: *Self = try allocator.create(Self); @@ -82,6 +91,46 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void { key.LALT, key.RALT => return self.cmd("enable_jump_mode", .{}), else => {}, } + + if (tui.current().config.vim_insert_chording_keybindings) { + + //reset chord if enough time has passed + const chord_time_window_ms = 750; + if (std.time.milliTimestamp() - self.last_key.timestamp_ms > chord_time_window_ms) { + self.last_key = .{}; + } + + //chording + if (self.last_key.keypress == 'j' and self.last_key.modifiers == 0 and keypress == 'k' and modifiers == 0) { + try self.cmd("delete_backward", .{}); + try self.cmd("enter_mode", command.fmt(.{"vim/normal"})); + return; + } + if (self.last_key.keypress == 'k' and self.last_key.modifiers == 0 and keypress == 'j' and modifiers == 0) { + try self.cmd("delete_backward", .{}); + try self.cmd("enter_mode", command.fmt(.{"vim/normal"})); + return; + } + if (self.last_key.keypress == 'f' and self.last_key.modifiers == 0 and keypress == 'j' and modifiers == 0) { + try self.cmd("delete_backward", .{}); + try self.cmd("enter_mode", command.fmt(.{"vim/normal"})); + return; + } + if (self.last_key.keypress == 'j' and self.last_key.modifiers == 0 and keypress == 'f' and modifiers == 0) { + try self.cmd("delete_backward", .{}); + try self.cmd("enter_mode", command.fmt(.{"vim/normal"})); + return; + } + + //record current key event + self.last_key = .{ + .keypress = keypress, + .modifiers = modifiers, + .egc = egc, + .timestamp_ms = std.time.milliTimestamp(), + }; + } + return switch (modifiers) { mod.CTRL => switch (keynormal) { 'E' => self.cmd("open_recent", .{}),