diff --git a/build.zig b/build.zig index 5cd077d..2efe78e 100644 --- a/build.zig +++ b/build.zig @@ -6,7 +6,6 @@ pub fn build(b: *std.Build) void { const tracy_enabled = b.option(bool, "enable_tracy", "Enable tracy client library (default: no)") orelse false; const use_tree_sitter = b.option(bool, "use_tree_sitter", "Enable tree-sitter (default: yes)") orelse true; const strip = b.option(bool, "strip", "Disable debug information (default: no)"); - const dynamic_keybind = b.option(bool, "dynamic_keybind", "Build with dynamic keybinding support (default: no) (EXPERIMENTAL)") orelse false; const use_llvm = b.option(bool, "use_llvm", "Enable llvm backend (default: none)"); const pie = b.option(bool, "pie", "Produce an executable with position independent code (default: none)"); @@ -24,7 +23,6 @@ pub fn build(b: *std.Build) void { tracy_enabled, use_tree_sitter, strip, - dynamic_keybind, use_llvm, pie, ); @@ -39,7 +37,6 @@ fn build_development( tracy_enabled: bool, use_tree_sitter: bool, strip: ?bool, - dynamic_keybind: bool, use_llvm: ?bool, pie: ?bool, ) void { @@ -58,7 +55,6 @@ fn build_development( tracy_enabled, use_tree_sitter, strip orelse false, - dynamic_keybind, use_llvm, pie, ); @@ -73,7 +69,6 @@ fn build_release( tracy_enabled: bool, use_tree_sitter: bool, strip: ?bool, - dynamic_keybind: bool, use_llvm: ?bool, pie: ?bool, ) void { @@ -113,7 +108,6 @@ fn build_release( tracy_enabled, use_tree_sitter, strip orelse true, - dynamic_keybind, use_llvm, pie, ); @@ -132,7 +126,6 @@ pub fn build_exe( tracy_enabled: bool, use_tree_sitter: bool, strip: bool, - dynamic_keybind: bool, use_llvm: ?bool, pie: ?bool, ) void { @@ -140,7 +133,6 @@ pub fn build_exe( options.addOption(bool, "enable_tracy", tracy_enabled); options.addOption(bool, "use_tree_sitter", use_tree_sitter); options.addOption(bool, "strip", strip); - options.addOption(bool, "dynamic_keybind", dynamic_keybind); const options_mod = options.createModule(); @@ -286,18 +278,8 @@ pub fn build_exe( }, }); - const keybind_static_mod = b.createModule(.{ - .root_source_file = b.path("src/keybind/static/keybind.zig"), - .imports = &.{ - .{ .name = "cbor", .module = cbor_mod }, - .{ .name = "command", .module = command_mod }, - .{ .name = "EventHandler", .module = EventHandler_mod }, - .{ .name = "input", .module = input_mod }, - .{ .name = "thespian", .module = thespian_mod }, - }, - }); - const keybind_dynamic_mod = b.createModule(.{ - .root_source_file = b.path("src/keybind/dynamic/keybind.zig"), + const keybind_mod = b.createModule(.{ + .root_source_file = b.path("src/keybind/keybind.zig"), .imports = &.{ .{ .name = "cbor", .module = cbor_mod }, .{ .name = "command", .module = command_mod }, @@ -307,11 +289,10 @@ pub fn build_exe( .{ .name = "log", .module = log_mod }, }, }); - const keybind_mod = if (dynamic_keybind) keybind_dynamic_mod else keybind_static_mod; const keybind_test_run_cmd = blk: { const tests = b.addTest(.{ - .root_source_file = b.path("src/keybind/dynamic/keybind.zig"), + .root_source_file = b.path("src/keybind/keybind.zig"), .target = target, .optimize = optimize, }); diff --git a/src/keybind/dynamic/keybind.zig b/src/keybind/keybind.zig similarity index 100% rename from src/keybind/dynamic/keybind.zig rename to src/keybind/keybind.zig diff --git a/src/keybind/dynamic/keybindings.json b/src/keybind/keybindings.json similarity index 100% rename from src/keybind/dynamic/keybindings.json rename to src/keybind/keybindings.json diff --git a/src/keybind/dynamic/parse_flow.zig b/src/keybind/parse_flow.zig similarity index 100% rename from src/keybind/dynamic/parse_flow.zig rename to src/keybind/parse_flow.zig diff --git a/src/keybind/dynamic/parse_vim.zig b/src/keybind/parse_vim.zig similarity index 100% rename from src/keybind/dynamic/parse_vim.zig rename to src/keybind/parse_vim.zig diff --git a/src/keybind/static/input/flow.zig b/src/keybind/static/input/flow.zig deleted file mode 100644 index fafe566..0000000 --- a/src/keybind/static/input/flow.zig +++ /dev/null @@ -1,413 +0,0 @@ -const std = @import("std"); -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); -const keybind = @import("../keybind.zig"); - -const Self = @This(); -const input_buffer_size = 1024; - -allocator: std.mem.Allocator, -input: std.ArrayList(u8), -last_cmd: []const u8 = "", -leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null, - -pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler { - const self: *Self = try allocator.create(Self); - self.* = .{ - .allocator = allocator, - .input = try std.ArrayList(u8).initCapacity(allocator, input_buffer_size), - }; - return EventHandler.to_owned(self); -} - -pub fn deinit(self: *Self) void { - self.input.deinit(); - self.allocator.destroy(self); -} - -pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var egc: input.Key = undefined; - var modifiers: input.Mods = undefined; - var text: []const u8 = undefined; - - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) { - self.map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{"F"})) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) { - self.paste_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace()); - } - return false; -} - -pub fn add_keybind() void {} - -fn map_event(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - return switch (event) { - input.event.press => self.map_press(keypress, egc, modifiers), - input.event.repeat => self.map_press(keypress, egc, modifiers), - input.event.release => self.map_release(keypress, egc, modifiers), - else => {}, - }; -} - -fn map_press(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - if (self.leader) |_| return self.map_follower(keynormal, modifiers); - switch (keypress) { - input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}), - else => {}, - } - return switch (modifiers) { - input.mod.ctrl => switch (keynormal) { - 'E' => self.cmd("open_recent", .{}), - 'R' => self.cmd("open_recent_project", .{}), - 'J' => self.cmd("toggle_panel", .{}), - 'Z' => self.cmd("undo", .{}), - 'Y' => self.cmd("redo", .{}), - 'Q' => self.cmd("quit", .{}), - 'O' => self.cmd("open_file", .{}), - 'W' => self.cmd("close_file", .{}), - 'S' => self.cmd("save_file", .{}), - 'L' => self.cmd("scroll_view_center_cycle", .{}), - 'N' => self.cmd("goto_next_match", .{}), - 'P' => self.cmd("goto_prev_match", .{}), - 'B' => self.cmd("move_to_char", command.fmt(.{false})), - 'T' => self.cmd("move_to_char", command.fmt(.{true})), - 'X' => self.cmd("cut", .{}), - 'C' => self.cmd("copy", .{}), - 'V' => self.cmd("system_paste", .{}), - 'U' => self.cmd("pop_cursor", .{}), - 'K' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'F' => self.cmd("find", .{}), - 'G' => self.cmd("goto", .{}), - 'D' => self.cmd("add_cursor_next_match", .{}), - 'A' => self.cmd("select_all", .{}), - 'I' => self.insert_bytes("\t"), - '/' => self.cmd("toggle_comment", .{}), - input.key.enter => self.cmd("smart_insert_line_after", .{}), - input.key.space => self.cmd("completion", .{}), - input.key.end => self.cmd("move_buffer_end", .{}), - input.key.home => self.cmd("move_buffer_begin", .{}), - input.key.up => self.cmd("move_scroll_up", .{}), - input.key.down => self.cmd("move_scroll_down", .{}), - input.key.page_up => self.cmd("move_scroll_page_up", .{}), - input.key.page_down => self.cmd("move_scroll_page_down", .{}), - input.key.left => self.cmd("move_word_left", .{}), - input.key.right => self.cmd("move_word_right", .{}), - input.key.backspace => self.cmd("delete_word_left", .{}), - input.key.delete => self.cmd("delete_word_right", .{}), - input.key.f5 => self.cmd("toggle_inspector_view", .{}), - input.key.f10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34 - input.key.f12 => self.cmd("goto_implementation", .{}), - else => {}, - }, - input.mod.ctrl | input.mod.shift => switch (keynormal) { - 'S' => self.cmd("save_as", .{}), - 'P' => self.cmd("open_command_palette", .{}), - 'D' => self.cmd("dupe_down", .{}), - 'Z' => self.cmd("redo", .{}), - 'Q' => self.cmd("quit_without_saving", .{}), - 'W' => self.cmd("close_file_without_saving", .{}), - 'F' => self.cmd("find_in_files", .{}), - 'L' => self.cmd_async("add_cursor_all_matches"), - 'I' => self.cmd_async("toggle_inspector_view"), - 'M' => self.cmd("show_diagnostics", .{}), - input.key.enter => self.cmd("smart_insert_line_before", .{}), - input.key.end => self.cmd("select_buffer_end", .{}), - input.key.home => self.cmd("select_buffer_begin", .{}), - input.key.up => self.cmd("select_scroll_up", .{}), - input.key.down => self.cmd("select_scroll_down", .{}), - input.key.left => self.cmd("select_word_left", .{}), - input.key.right => self.cmd("select_word_right", .{}), - input.key.space => self.cmd("selections_reverse", .{}), - else => {}, - }, - input.mod.alt => switch (keynormal) { - 'O' => self.cmd("open_previous_file", .{}), - 'J' => self.cmd("join_next_line", .{}), - 'N' => self.cmd("goto_next_file_or_diagnostic", .{}), - 'P' => self.cmd("goto_prev_file_or_diagnostic", .{}), - 'U' => self.cmd("to_upper", .{}), - 'L' => self.cmd("to_lower", .{}), - 'C' => self.cmd("switch_case", .{}), - 'I' => self.cmd("toggle_inputview", .{}), - 'B' => self.cmd("move_word_left", .{}), - 'F' => self.cmd("move_word_right", .{}), - 'S' => self.cmd("filter", command.fmt(.{"sort"})), - 'V' => self.cmd("paste", .{}), - 'X' => self.cmd("open_command_palette", .{}), - input.key.left => self.cmd("jump_back", .{}), - input.key.right => self.cmd("jump_forward", .{}), - input.key.up => self.cmd("pull_up", .{}), - input.key.down => self.cmd("pull_down", .{}), - input.key.enter => self.cmd("insert_line", .{}), - input.key.f10 => self.cmd("gutter_mode_next", .{}), // aka F58 - input.key.f12 => self.cmd("goto_declaration", .{}), - else => {}, - }, - input.mod.alt | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - 'D' => self.cmd("dupe_up", .{}), - // 'B' => self.cmd("select_word_left", .{}), - // 'F' => self.cmd("select_word_right", .{}), - 'F' => self.cmd("format", .{}), - 'S' => self.cmd("filter", command.fmt(.{ "sort", "-u" })), - 'V' => self.cmd("paste", .{}), - 'I' => self.cmd("add_cursors_to_line_ends", .{}), - input.key.left => self.cmd("shrink_selection", .{}), - input.key.right => self.cmd("expand_selection", .{}), - input.key.home => self.cmd("move_scroll_left", .{}), - input.key.end => self.cmd("move_scroll_right", .{}), - input.key.up => self.cmd("add_cursor_up", .{}), - input.key.down => self.cmd("add_cursor_down", .{}), - input.key.f12 => self.cmd("goto_type_definition", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - input.key.f3 => self.cmd("goto_prev_match", .{}), - input.key.f10 => self.cmd("toggle_syntax_highlighting", .{}), - input.key.f12 => self.cmd("references", .{}), - input.key.left => self.cmd("select_left", .{}), - input.key.right => self.cmd("select_right", .{}), - input.key.up => self.cmd("select_up", .{}), - input.key.down => self.cmd("select_down", .{}), - input.key.home => self.cmd("smart_select_begin", .{}), - input.key.end => self.cmd("select_end", .{}), - input.key.page_up => self.cmd("select_page_up", .{}), - input.key.page_down => self.cmd("select_page_down", .{}), - input.key.enter => self.cmd("smart_insert_line_before", .{}), - input.key.backspace => self.cmd("delete_backward", .{}), - input.key.tab => self.cmd("unindent", .{}), - else => if (!input.is_non_input_key(keypress)) - self.insert_code_point(egc) - else {}, - }, - 0 => switch (keypress) { - input.key.f2 => self.cmd("toggle_input_mode", .{}), - input.key.f3 => self.cmd("goto_next_match", .{}), - input.key.f15 => self.cmd("goto_prev_match", .{}), // S-F3 - input.key.f5 => self.cmd("toggle_inspector_view", .{}), // C-F5 - input.key.f6 => self.cmd("dump_current_line_tree", .{}), - input.key.f7 => self.cmd("dump_current_line", .{}), - input.key.f9 => self.cmd("theme_prev", .{}), - input.key.f10 => self.cmd("theme_next", .{}), - input.key.f11 => self.cmd("toggle_panel", .{}), - input.key.f12 => self.cmd("goto_definition", .{}), - input.key.f34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10 - input.key.escape => self.cmd("cancel", .{}), - input.key.enter => self.cmd("smart_insert_line", .{}), - input.key.delete => self.cmd("delete_forward", .{}), - input.key.backspace => self.cmd("delete_backward", .{}), - input.key.left => self.cmd("move_left", .{}), - input.key.right => self.cmd("move_right", .{}), - input.key.up => self.cmd("move_up", .{}), - input.key.down => self.cmd("move_down", .{}), - input.key.home => self.cmd("smart_move_begin", .{}), - input.key.end => self.cmd("move_end", .{}), - input.key.page_up => self.cmd("move_page_up", .{}), - input.key.page_down => self.cmd("move_page_down", .{}), - input.key.tab => self.cmd("indent", .{}), - else => if (!input.is_non_input_key(keypress)) - self.insert_code_point(egc) - else {}, - }, - else => {}, - }; -} - -fn map_follower(self: *Self, keypress: input.Key, modifiers: input.Mods) !void { - defer self.leader = null; - const ldr = if (self.leader) |leader| leader else return; - return switch (ldr.modifiers) { - input.mod.ctrl => switch (ldr.keypress) { - 'K' => switch (modifiers) { - input.mod.ctrl => switch (keypress) { - 'U' => self.cmd("delete_to_begin", .{}), - 'K' => self.cmd("delete_to_end", .{}), - 'D' => self.cmd("move_cursor_next_match", .{}), - 'T' => self.cmd("change_theme", .{}), - 'I' => self.cmd("hover", .{}), - else => {}, - }, - else => {}, - }, - else => {}, - }, - else => {}, - }; -} - -fn map_release(self: *Self, keypress: input.Key, _: u32, _: u32) !void { - return switch (keypress) { - input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}), - else => {}, - }; -} - -fn insert_code_point(self: *Self, c: u32) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - var buf: [6]u8 = undefined; - const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf); - try self.input.appendSlice(buf[0..bytes]); -} - -fn insert_bytes(self: *Self, bytes: []const u8) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - try self.input.appendSlice(bytes); -} - -fn paste_bytes(self: *Self, bytes: []const u8) !void { - try self.flush_input(); - try command.executeName("paste", command.fmt(.{bytes})); -} - -var insert_chars_id: ?command.ID = null; - -fn flush_input(self: *Self) !void { - if (self.input.items.len > 0) { - defer self.input.clearRetainingCapacity(); - const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse { - return tp.exit_error(error.InputTargetNotFound, null); - }; - try command.execute(id, command.fmt(.{self.input.items})); - self.last_cmd = "insert_chars"; - } -} - -fn cmd(self: *Self, name_: []const u8, ctx: command.Context) tp.result { - try self.flush_input(); - self.last_cmd = name_; - try command.executeName(name_, ctx); -} - -fn cmd_async(self: *Self, name_: []const u8) tp.result { - self.last_cmd = name_; - return tp.self_pid().send(.{ "cmd", name_ }); -} - -pub const hints = keybind.KeybindHints.initComptime(.{ - .{ "add_cursor_all_matches", "C-S-l" }, - .{ "add_cursor_down", "S-A-down" }, - .{ "add_cursor_next_match", "C-d" }, - .{ "add_cursors_to_line_ends", "S-A-i" }, - .{ "add_cursor_up", "S-A-up" }, - .{ "cancel", "esc" }, - .{ "change_theme", "C-k C-t" }, - .{ "close_file", "C-w" }, - .{ "close_file_without_saving", "C-S-w" }, - .{ "copy", "C-c" }, - .{ "cut", "C-x" }, - .{ "delete_backward", "backspace" }, - .{ "delete_forward", "del" }, - .{ "delete_to_begin", "C-k C-u" }, - .{ "delete_to_end", "C-k C-k" }, - .{ "delete_word_left", "C-backspace" }, - .{ "delete_word_right", "C-del" }, - .{ "dump_current_line", "F7" }, - .{ "dump_current_line_tree", "F6" }, - .{ "dupe_down", "C-S-d" }, - .{ "dupe_up", "S-A-d" }, - .{ "enable_fast_scroll", "hold Ctrl" }, - .{ "enable_jump_mode", "hold Alt" }, - .{ "expand_selection", "S-A-right" }, - .{ "filter", "A-s" }, // self.cmd("filter", command.fmt(.{"sort"})), - // .{ "filter", "S-A-s" }, // self.cmd("filter", command.fmt(.{ "sort", "-u" })), - .{ "find", "C-f" }, - .{ "find_in_files", "C-S-f" }, - .{ "format", "S-A-f" }, - .{ "goto", "C-g" }, - .{ "goto_declaration", "A-F12" }, - .{ "goto_definition", "F12" }, - .{ "goto_implementation", "C-F12" }, - .{ "goto_next_file_or_diagnostic", "A-n" }, - .{ "goto_next_match", "C-n, F3" }, - .{ "goto_prev_file_or_diagnostic", "A-p" }, - .{ "goto_prev_match", "C-p, S-F3" }, - .{ "goto_type_definition", "A-S-F12" }, - .{ "gutter_mode_next", "A-F10" }, - .{ "indent", "tab" }, - .{ "insert_line", "A-enter" }, - .{ "join_next_line", "A-j" }, - .{ "jump_back", "A-left" }, - .{ "jump_forward", "A-right" }, - .{ "move_buffer_begin", "C-home" }, - .{ "move_buffer_end", "C-end" }, - .{ "move_cursor_next_match", "C-k C-d" }, - .{ "move_down", "down" }, - .{ "move_end", "end" }, - .{ "move_left", "left" }, - .{ "move_page_down", "pgdn" }, - .{ "move_page_up", "pgup" }, - .{ "move_right", "right" }, - .{ "move_scroll_down", "C-down" }, - .{ "move_scroll_left", "S-A-home" }, - .{ "move_scroll_page_down", "C-pgdn" }, - .{ "move_scroll_page_up", "C-pgup" }, - .{ "move_scroll_right", "S-A-end" }, - .{ "move_scroll_up", "C-up" }, - .{ "move_to_char", "C-b, C-t" }, // true/false - .{ "move_up", "up" }, - .{ "move_word_left", "C-left, A-b" }, - .{ "move_word_right", "C-right, A-f" }, - .{ "open_command_palette", "C-S-p, S-A-p, A-x" }, - .{ "open_file", "C-o" }, - .{ "open_previous_file", "A-o" }, - .{ "open_recent", "C-e" }, - .{ "open_recent_project", "C-r" }, - .{ "paste", "A-v" }, - .{ "pop_cursor", "C-u" }, - .{ "pull_down", "A-down" }, - .{ "pull_up", "A-up" }, - .{ "quit", "C-q" }, - .{ "quit_without_saving", "C-S-q" }, - .{ "redo", "C-S-z, C-y" }, - .{ "references", "S-F12" }, - .{ "save_as", "C-S-s" }, - .{ "save_file", "C-s" }, - .{ "scroll_view_center_cycle", "C-l" }, - .{ "select_all", "C-a" }, - .{ "select_buffer_begin", "C-S-home" }, - .{ "select_buffer_end", "C-S-end" }, - .{ "select_down", "S-down" }, - .{ "select_end", "S-end" }, - .{ "selections_reverse", "C-S-space" }, - .{ "select_left", "S-left" }, - .{ "select_page_down", "S-pgdn" }, - .{ "select_page_up", "S-pgup" }, - .{ "select_right", "S-right" }, - .{ "select_scroll_down", "C-S-down" }, - .{ "select_scroll_up", "C-S-up" }, - .{ "select_up", "S-up" }, - .{ "select_word_left", "C-S-left" }, - .{ "select_word_right", "C-S-right" }, - .{ "show_diagnostics", "C-S-m" }, - .{ "shrink_selection", "S-A-left" }, - .{ "smart_insert_line_after", "C-enter" }, - .{ "smart_insert_line_before", "S-enter, C-S-enter" }, - .{ "smart_insert_line", "enter" }, - .{ "smart_move_begin", "home" }, - .{ "smart_select_begin", "S-home" }, - .{ "system_paste", "C-v" }, - .{ "theme_next", "F10" }, - .{ "theme_prev", "F9" }, - .{ "toggle_comment", "C-/" }, - .{ "toggle_input_mode", "F2" }, - .{ "toggle_inputview", "A-i" }, - .{ "toggle_inspector_view", "F5, C-F5, C-S-i" }, - .{ "toggle_panel", "C-j, F11" }, - .{ "toggle_whitespace_mode", "C-F10" }, - .{ "toggle_syntax_highlighting", "S-F10" }, - .{ "to_lower", "A-l" }, - .{ "to_upper", "A-u" }, - .{ "undo", "C-z" }, - .{ "unindent", "S-tab" }, -}); diff --git a/src/keybind/static/input/helix/insert.zig b/src/keybind/static/input/helix/insert.zig deleted file mode 100644 index c1fa36f..0000000 --- a/src/keybind/static/input/helix/insert.zig +++ /dev/null @@ -1,314 +0,0 @@ -const std = @import("std"); -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); -const keybind = @import("../../keybind.zig"); - -const Self = @This(); -const input_buffer_size = 1024; - -allocator: std.mem.Allocator, -input: std.ArrayList(u8), -last_cmd: []const u8 = "", -leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null, -commands: Commands = undefined, - -pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler { - const self: *Self = try allocator.create(Self); - self.* = .{ - .allocator = allocator, - .input = try std.ArrayList(u8).initCapacity(allocator, input_buffer_size), - }; - try self.commands.init(self); - return EventHandler.to_owned(self); -} - -pub fn deinit(self: *Self) void { - self.commands.deinit(); - self.input.deinit(); - self.allocator.destroy(self); -} - -pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var egc: input.Key = undefined; - var modifiers: input.Mods = undefined; - var text: []const u8 = undefined; - - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) { - self.mapEvent(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{"F"})) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace()); - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } - return false; -} - -pub fn add_keybind() void {} - -fn mapEvent(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - return switch (event) { - input.event.press => self.map_press(keypress, egc, modifiers), - input.event.repeat => self.map_press(keypress, egc, modifiers), - input.event.release => self.map_release(keypress), - else => {}, - }; -} - -fn map_press(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - if (self.leader) |_| return self.map_follower(keynormal, modifiers); - switch (keypress) { - input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}), - else => {}, - } - return switch (modifiers) { - input.mod.ctrl => switch (keynormal) { - 'E' => self.cmd("open_recent", .{}), - 'U' => self.cmd("move_scroll_page_up", .{}), - 'D' => self.cmd("move_scroll_page_down", .{}), - 'J' => self.cmd("toggle_panel", .{}), - 'Z' => self.cmd("undo", .{}), - 'Y' => self.cmd("redo", .{}), - 'Q' => self.cmd("quit", .{}), - 'W' => self.cmd("close_file", .{}), - 'S' => self.cmd("save_file", .{}), - 'L' => self.cmd("scroll_view_center_cycle", .{}), - 'N' => self.cmd("goto_next_match", .{}), - 'P' => self.cmd("goto_prev_match", .{}), - 'B' => self.cmd("move_to_char", command.fmt(.{false})), - 'T' => self.cmd("move_to_char", command.fmt(.{true})), - 'X' => self.cmd("cut", .{}), - 'C' => self.cmd("enter_mode", command.fmt(.{"helix/normal"})), - 'V' => self.cmd("system_paste", .{}), - 'K' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'F' => self.cmd("find", .{}), - 'G' => self.cmd("goto", .{}), - 'O' => self.cmd("run_ls", .{}), - 'A' => self.cmd("select_all", .{}), - 'I' => self.insert_bytes("\t"), - '/' => self.cmd("toggle_comment", .{}), - input.key.enter => self.cmd("smart_insert_line_after", .{}), - input.key.space => self.cmd("selections_reverse", .{}), - input.key.end => self.cmd("move_buffer_end", .{}), - input.key.home => self.cmd("move_buffer_begin", .{}), - input.key.up => self.cmd("move_scroll_up", .{}), - input.key.down => self.cmd("move_scroll_down", .{}), - input.key.page_up => self.cmd("move_scroll_page_up", .{}), - input.key.page_down => self.cmd("move_scroll_page_down", .{}), - input.key.left => self.cmd("move_word_left", .{}), - input.key.right => self.cmd("move_word_right", .{}), - input.key.backspace => self.cmd("delete_word_left", .{}), - input.key.delete => self.cmd("delete_word_right", .{}), - input.key.f5 => self.cmd("toggle_inspector_view", .{}), - input.key.f10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34 - else => {}, - }, - input.mod.ctrl | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - 'D' => self.cmd("dupe_down", .{}), - 'Z' => self.cmd("redo", .{}), - 'Q' => self.cmd("quit_without_saving", .{}), - 'W' => self.cmd("close_file_without_saving", .{}), - 'F' => self.cmd("find_in_files", .{}), - 'L' => self.cmd_async("add_cursor_all_matches"), - 'I' => self.cmd_async("toggle_inspector_view"), - input.key.enter => self.cmd("smart_insert_line_before", .{}), - input.key.end => self.cmd("select_buffer_end", .{}), - input.key.home => self.cmd("select_buffer_begin", .{}), - input.key.up => self.cmd("select_scroll_up", .{}), - input.key.down => self.cmd("select_scroll_down", .{}), - input.key.left => self.cmd("select_word_left", .{}), - input.key.right => self.cmd("select_word_right", .{}), - else => {}, - }, - input.mod.alt => switch (keynormal) { - 'J' => self.cmd("join_next_line", .{}), - 'N' => self.cmd("goto_next_match", .{}), - 'P' => self.cmd("goto_prev_match", .{}), - 'U' => self.cmd("to_upper", .{}), - 'L' => self.cmd("to_lower", .{}), - 'I' => self.cmd("toggle_inputview", .{}), - 'B' => self.cmd("move_word_left", .{}), - 'F' => self.cmd("move_word_right", .{}), - 'S' => self.cmd("filter", command.fmt(.{"sort"})), - 'V' => self.cmd("paste", .{}), - input.key.left => self.cmd("jump_back", .{}), - input.key.right => self.cmd("jump_forward", .{}), - input.key.up => self.cmd("pull_up", .{}), - input.key.down => self.cmd("pull_down", .{}), - input.key.enter => self.cmd("insert_line", .{}), - input.key.f10 => self.cmd("gutter_mode_next", .{}), // aka F58 - else => {}, - }, - input.mod.alt | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - 'D' => self.cmd("dupe_up", .{}), - 'F' => self.cmd("filter", command.fmt(.{ "zig", "fmt", "--stdin" })), - 'S' => self.cmd("filter", command.fmt(.{ "sort", "-u" })), - 'V' => self.cmd("paste", .{}), - 'I' => self.cmd("add_cursors_to_line_ends", .{}), - input.key.left => self.cmd("move_scroll_left", .{}), - input.key.right => self.cmd("move_scroll_right", .{}), - input.key.up => self.cmd("add_cursor_up", .{}), - input.key.down => self.cmd("add_cursor_down", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - input.key.f3 => self.cmd("goto_prev_match", .{}), - input.key.left => self.cmd("select_left", .{}), - input.key.right => self.cmd("select_right", .{}), - input.key.up => self.cmd("select_up", .{}), - input.key.down => self.cmd("select_down", .{}), - input.key.home => self.cmd("smart_select_begin", .{}), - input.key.end => self.cmd("select_end", .{}), - input.key.page_up => self.cmd("select_page_up", .{}), - input.key.page_down => self.cmd("select_page_down", .{}), - input.key.enter => self.cmd("smart_insert_line_before", .{}), - input.key.backspace => self.cmd("delete_backward", .{}), - input.key.tab => self.cmd("unindent", .{}), - else => if (!input.is_non_input_key(keypress)) - self.insert_code_point(egc) - else {}, - }, - 0 => switch (keypress) { - input.key.f2 => self.cmd("toggle_input_mode", .{}), - input.key.f3 => self.cmd("goto_next_match", .{}), - input.key.f15 => self.cmd("goto_prev_match", .{}), // S-F3 - input.key.f5 => self.cmd("toggle_inspector_view", .{}), // C-F5 - input.key.f6 => self.cmd("dump_current_line_tree", .{}), - input.key.f7 => self.cmd("dump_current_line", .{}), - input.key.f9 => self.cmd("theme_prev", .{}), - input.key.f10 => self.cmd("theme_next", .{}), - input.key.f11 => self.cmd("toggle_panel", .{}), - input.key.f12 => self.cmd("goto_definition", .{}), - input.key.f34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10 - input.key.escape => self.cmd("enter_mode", command.fmt(.{"helix/normal"})), - input.key.enter => self.cmd("smart_insert_line", .{}), - input.key.delete => self.cmd("delete_forward", .{}), - input.key.backspace => self.cmd("delete_backward", .{}), - input.key.left => self.cmd("move_left", .{}), - input.key.right => self.cmd("move_right", .{}), - input.key.up => self.cmd("move_up", .{}), - input.key.down => self.cmd("move_down", .{}), - input.key.home => self.cmd("smart_move_begin", .{}), - input.key.end => self.cmd("move_end", .{}), - input.key.page_up => self.cmd("move_page_up", .{}), - input.key.page_down => self.cmd("move_page_down", .{}), - input.key.tab => self.cmd("indent", .{}), - else => if (!input.is_non_input_key(keypress)) - self.insert_code_point(egc) - else {}, - }, - else => {}, - }; -} - -fn map_follower(self: *Self, keypress: input.Key, modifiers: input.Mods) !void { - defer self.leader = null; - const ldr = if (self.leader) |leader| leader else return; - return switch (ldr.modifiers) { - input.mod.ctrl => switch (ldr.keypress) { - 'K' => switch (modifiers) { - input.mod.ctrl => switch (keypress) { - 'U' => self.cmd("delete_to_begin", .{}), - 'K' => self.cmd("delete_to_end", .{}), - 'D' => self.cmd("move_cursor_next_match", .{}), - 'T' => self.cmd("change_theme", .{}), - else => {}, - }, - else => {}, - }, - else => {}, - }, - else => {}, - }; -} - -fn map_release(self: *Self, keypress: input.Key) !void { - return switch (keypress) { - input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}), - else => {}, - }; -} - -fn insert_code_point(self: *Self, c: u32) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - var buf: [6]u8 = undefined; - const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf); - try self.input.appendSlice(buf[0..bytes]); -} - -fn insert_bytes(self: *Self, bytes: []const u8) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - try self.input.appendSlice(bytes); -} - -var insert_chars_id: ?command.ID = null; - -fn flush_input(self: *Self) !void { - if (self.input.items.len > 0) { - defer self.input.clearRetainingCapacity(); - const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse { - return tp.exit_error(error.InputTargetNotFound, null); - }; - try command.execute(id, command.fmt(.{self.input.items})); - self.last_cmd = "insert_chars"; - } -} - -fn cmd(self: *Self, name_: []const u8, ctx: command.Context) tp.result { - try self.flush_input(); - self.last_cmd = name_; - try command.executeName(name_, ctx); -} - -fn cmd_async(self: *Self, name_: []const u8) tp.result { - self.last_cmd = name_; - return tp.self_pid().send(.{ "cmd", name_ }); -} - -pub const hints = keybind.KeybindHints.initComptime(.{}); - -const Commands = command.Collection(cmds_); -const cmds_ = struct { - pub const Target = Self; - const Ctx = command.Context; - const Result = command.Result; - - pub fn w(self: *Self, _: Ctx) Result { - try self.cmd("save_file", .{}); - } - pub const w_meta = .{ .description = "w (write file)" }; - - pub fn q(self: *Self, _: Ctx) Result { - try self.cmd("quit", .{}); - } - pub const q_meta = .{ .description = "q (quit)" }; - - pub fn @"q!"(self: *Self, _: Ctx) Result { - try self.cmd("quit_without_saving", .{}); - } - pub const @"q!_meta" = .{ .description = "q! (quit without saving)" }; - - pub fn wq(self: *Self, _: Ctx) Result { - try self.cmd("save_file", .{}); - try self.cmd("quit", .{}); - } - pub const wq_meta = .{ .description = "wq (write file and quit)" }; - - pub fn @"wq!"(self: *Self, _: Ctx) Result { - self.cmd("save_file", .{}) catch {}; - try self.cmd("quit_without_saving", .{}); - } - pub const @"wq!_meta" = .{ .description = "wq! (write file and quit without saving)" }; -}; diff --git a/src/keybind/static/input/helix/normal.zig b/src/keybind/static/input/helix/normal.zig deleted file mode 100644 index b3ae253..0000000 --- a/src/keybind/static/input/helix/normal.zig +++ /dev/null @@ -1,669 +0,0 @@ -const std = @import("std"); -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); -const keybind = @import("../../keybind.zig"); - -const Self = @This(); -const input_buffer_size = 1024; - -allocator: std.mem.Allocator, -input: std.ArrayList(u8), -last_cmd: []const u8 = "", -leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null, -count: usize = 0, -commands: Commands = undefined, - -pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler { - const self: *Self = try allocator.create(Self); - self.* = .{ - .allocator = allocator, - .input = try std.ArrayList(u8).initCapacity(allocator, input_buffer_size), - }; - try self.commands.init(self); - return EventHandler.to_owned(self); -} - -pub fn deinit(self: *Self) void { - self.commands.deinit(); - self.input.deinit(); - self.allocator.destroy(self); -} - -pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var egc: input.Key = undefined; - var modifiers: input.Mods = undefined; - var text: []const u8 = undefined; - - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) { - self.map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{"F"})) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace()); - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } - return false; -} - -pub fn add_keybind() void {} - -fn map_event(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - return switch (event) { - input.event.press => self.map_press(keypress, egc, modifiers), - input.event.repeat => self.map_press(keypress, egc, modifiers), - input.event.release => self.map_release(keypress), - else => {}, - }; -} - -fn map_press(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - if (self.count > 0 and modifiers == 0 and '0' <= keypress and keypress <= '9') return self.add_count(keypress - '0'); - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers); - switch (keypress) { - input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}), - else => {}, - } - return switch (modifiers) { - input.mod.ctrl => switch (keynormal) { - 'B' => self.cmd("move_scroll_page_up", .{}), - 'F' => self.cmd("move_scroll_page_down", .{}), - 'U' => self.cmd("page_cursor_half_up", .{}), - 'D' => self.cmd("page_cursor_half_down", .{}), - - 'C' => self.cmd("toggle_comment", .{}), - - 'I' => self.cmd("jump_forward", .{}), - 'O' => self.cmd("jump_back", .{}), - 'S' => self.cmd("save_selection", .{}), - 'W' => self.leader = .{ .keypress = keynormal, .modifiers = 0 }, - - 'A' => self.cmd("increment", .{}), - 'X' => self.cmd("decrement", .{}), - else => {}, - }, - input.mod.ctrl | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - '6' => self.cmd("open_previous_file", .{}), - else => {}, - }, - input.mod.alt => switch (keynormal) { - '.' => self.cmd("repeat_last_motion", .{}), - - '`' => self.cmd("switch_to_uppercase", .{}), - - 'D' => self.cmd("delete_backward", .{}), - 'C' => { - try self.cmd("delete_backward", .{}); - try self.cmd("enter_mode", command.fmt(.{"helix/insert"})); - }, - - 'S' => self.cmd("split_selection_on_newline", .{}), - '-' => self.cmd("merge_selections", .{}), - '_' => self.cmd("merge_consecutive_selections", .{}), - - ';' => self.cmd("flip_selections", .{}), - 'O', input.key.up => self.cmd("expand_selection", .{}), - 'I', input.key.down => self.cmd("shrink_selection", .{}), - 'P', input.key.left => self.cmd("select_prev_sibling", .{}), - 'N', input.key.right => self.cmd("select_next_sibling", .{}), - - 'E' => self.cmd("move_parent_node_end", .{}), - 'B' => self.cmd("move_parent_node_start", .{}), - 'A' => self.cmd("select_all_siblings", .{}), - - 'X' => self.cmd("shrink_to_line_bounds", .{}), - - 'U' => self.cmd("undo", .{}), - - ',' => self.cmd("remove_primary_selection", .{}), - else => {}, - }, - input.mod.alt | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - - 'C' => self.cmd("copy_selection_on_next_line", .{}), - - 'I', input.key.down => self.cmd("select_all_children", .{}), - - 'U' => self.cmd("redo", .{}), - - 'j' => self.cmd("join_selections_space", .{}), - - '(' => self.cmd("rotate_selection_contents_backward", .{}), - ')' => self.cmd("rotate_selection_contents_forward", .{}), - - '\\' => self.cmd("shell_pipe_to", .{}), - '1' => self.cmd("shell_append_output", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - '`' => self.cmd("switch_case", .{}), - - 't' => self.cmd("till_prev_char", .{}), - 'f' => self.cmd("find_prev_char", .{}), - 'r' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - - 'w' => self.cmd_count("move_next_long_word_start", .{}), - 'b' => self.cmd_count("move_prev_long_word_start", .{}), - 'e' => self.cmd_count("move_next_long_word_end", .{}), - - 'g' => if (self.count == 0) - self.cmd("move_buffer_end", .{}) - else { - const count = self.count; - try self.cmd("move_buffer_begin", .{}); - self.count = count - 1; - if (self.count > 0) - try self.cmd_count("move_down", .{}); - }, - - 'i' => self.seq(.{ "smart_move_begin", "enter_mode" }, command.fmt(.{"helix/insert"})), - 'a' => self.seq(.{ "move_end", "enter_mode" }, command.fmt(.{"helix/insert"})), - - 'o' => self.seq(.{ "smart_insert_line_before", "enter_mode" }, command.fmt(.{"helix/insert"})), - - 'c' => self.cmd("copy_selection_on_next_line", .{}), - - 's' => self.cmd("split_selection", .{}), - - 'x' => self.cmd_count("extend_to_line_bounds", .{}), - - '/' => self.cmd("rfind", .{}), - - 'n' => self.cmd("goto_prev_match", .{}), - '8' => self.cmd("search_selection", .{}), - - 'u' => self.cmd("redo", .{}), - - 'p' => self.cmd("paste", .{}), - - 'q' => self.cmd("replay_macro", .{}), - - '.' => self.cmd("indent", .{}), - ',' => self.cmd("unindent", .{}), - - 'j' => self.cmd("join_selections", .{}), - - ';' => self.cmd("open_command_palette", .{}), - - '7' => self.cmd("align_selections", .{}), - '-' => self.cmd("trim_selections", .{}), - - '9' => self.cmd("rotate_selections_backward", .{}), - '0' => self.cmd("rotate_selections_forward", .{}), - - '\'' => self.cmd("select_register", .{}), - '\\' => self.cmd("shell_pipe", .{}), - '1' => self.cmd("shell_insert_output", .{}), - '4' => self.cmd("shell_keep_pipe", .{}), - else => {}, - }, - 0 => switch (keypress) { - input.key.f2 => self.cmd("toggle_input_mode", .{}), - 'h', input.key.left => self.cmd_count("move_left", .{}), - 'j', input.key.down => self.cmd_count("move_down", .{}), - 'k', input.key.up => self.cmd_count("move_up", .{}), - 'l', input.key.right => self.cmd_count("move_right", .{}), - - 't' => self.cmd("find_till_char", .{}), - 'f' => self.cmd("find_next_char", .{}), - 'r' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - - '`' => self.cmd("switch_to_lowercase", .{}), - - input.key.home => self.cmd("move_begin", .{}), - input.key.end => self.cmd("move_end", .{}), - - 'w' => self.cmd_count("move_next_word_start", .{}), - 'b' => self.cmd_count("move_prev_word_start", .{}), - 'e' => self.cmd_count("move_next_word_end", .{}), - - 'v' => self.cmd("enter_mode", command.fmt(.{"helix/select"})), - 'g' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - - 'i' => self.cmd("enter_mode", command.fmt(.{"helix/insert"})), - 'a' => self.seq(.{ "move_right", "enter_mode" }, command.fmt(.{"helix/insert"})), // TODO: keep selection - 'o' => self.seq(.{ "smart_insert_line_after", "enter_mode" }, command.fmt(.{"helix/insert"})), - - 'd' => self.cmd("cut", .{}), - 'c' => { - try self.cmd("cut", .{}); - try self.cmd("enter_mode", command.fmt(.{"helix/insert"})); - }, - - 's' => self.cmd("select_regex", .{}), - ';' => self.cmd("collapse_selections", .{}), - - 'x' => self.cmd_count("extend_line_below", .{}), - - 'm' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - '[' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - ']' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - - '/' => self.cmd("find", .{}), - 'n' => self.cmd("goto_next_match", .{}), - 'u' => self.cmd("undo", .{}), - - 'y' => self.cmd("copy", .{}), - 'p' => self.cmd("paste_after", .{}), - - 'q' => self.cmd("record_macro", .{}), - - '=' => self.cmd("format_selections", .{}), - - ',' => self.cmd("keep_primary_selection", .{}), - - input.key.escape => self.cmd("cancel", .{}), - - input.key.page_up => self.cmd("move_scroll_page_up", .{}), - input.key.page_down => self.cmd("move_scroll_page_down", .{}), - - ' ' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'z' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - - '1' => self.add_count(1), - '2' => self.add_count(2), - '3' => self.add_count(3), - '4' => self.add_count(4), - '5' => self.add_count(5), - '6' => self.add_count(6), - '7' => self.add_count(7), - '8' => self.add_count(8), - '9' => self.add_count(9), - else => {}, - }, - else => {}, - }; -} - -fn mapFollower(self: *Self, keypress: input.Key, _: u32, modifiers: input.Mods) !void { - if (keypress == input.key.left_control or - keypress == input.key.right_control or - keypress == input.key.left_alt or - keypress == input.key.right_alt or - keypress == input.key.left_shift or - keypress == input.key.right_shift or - keypress == input.key.left_super or - keypress == input.key.right_super) return; - - defer self.leader = null; - const ldr = if (self.leader) |leader| leader else return; - return switch (ldr.modifiers) { - 0 => switch (ldr.keypress) { - 'G' => switch (modifiers) { - 0 => switch (keypress) { - 'G' => self.cmd("move_buffer_begin", .{}), - 'E' => self.cmd("move_buffer_end", .{}), - 'F' => self.cmd("goto_file", .{}), - 'H' => self.cmd("move_begin", .{}), - 'L' => self.cmd("move_end", .{}), - 'S' => self.cmd("smart_move_begin", .{}), - 'D' => self.cmd("goto_definition", .{}), - 'Y' => self.cmd("goto_type_definition", .{}), - 'R' => self.cmd("goto_reference", .{}), - 'I' => self.cmd("goto_implementation", .{}), - 'T' => self.cmd("goto_window_top", .{}), - 'C' => self.cmd("goto_window_center", .{}), - 'B' => self.cmd("goto_window_bottom", .{}), - 'A' => self.cmd("goto_last_accessed_file", .{}), - 'M' => self.cmd("goto_last_modified_file", .{}), - 'N' => self.cmd("goto_next_buffer", .{}), - 'P' => self.cmd("goto_previous_buffer", .{}), - 'K' => self.cmd("goto_previous_buffer", .{}), - '.' => self.cmd("goto_last_modification", .{}), - 'W' => self.cmd("goto_word", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - 'D' => self.cmd("goto_declaration", .{}), - else => {}, - }, - else => {}, - }, - 'M' => { - try switch (modifiers) { - 0 => switch (keypress) { - 'M' => self.cmd("match_brackets", .{}), - 'S' => self.cmd("surround_add", .{}), - 'R' => self.cmd("surround_replace", .{}), - 'D' => self.cmd("surround_delete", .{}), - 'A' => self.cmd("select_textobject_around", .{}), - 'I' => self.cmd("select_textobject_inner", .{}), - else => {}, - }, - else => {}, - }; - }, - '[' => { - try switch (modifiers) { - input.mod.shift => switch (keypress) { - 'D' => self.cmd("goto_first_diag", .{}), - 'G' => self.cmd("goto_first_change", .{}), - 'T' => self.cmd("goto_prev_test", .{}), - else => {}, - }, - 0 => switch (keypress) { - 'D' => self.cmd("goto_prev_diagnostic", .{}), - 'G' => self.cmd("goto_prev_change", .{}), - 'F' => self.cmd("goto_prev_function", .{}), - 'T' => self.cmd("goto_prev_class", .{}), - 'A' => self.cmd("goto_prev_parameter", .{}), - 'C' => self.cmd("goto_prev_comment", .{}), - 'E' => self.cmd("goto_prev_entry", .{}), - 'P' => self.cmd("goto_prev_paragraph", .{}), - ' ' => self.cmd("add_newline_above", .{}), - else => {}, - }, - else => {}, - }; - }, - ']' => { - try switch (modifiers) { - input.mod.shift => switch (keypress) { - 'D' => self.cmd("goto_last_diag", .{}), - 'G' => self.cmd("goto_last_change", .{}), - 'T' => self.cmd("goto_next_test", .{}), - else => {}, - }, - 0 => switch (keypress) { - 'D' => self.cmd("goto_next_diagnostic", .{}), - 'G' => self.cmd("goto_next_change", .{}), - 'F' => self.cmd("goto_next_function", .{}), - 'T' => self.cmd("goto_next_class", .{}), - 'A' => self.cmd("goto_next_parameter", .{}), - 'C' => self.cmd("goto_next_comment", .{}), - 'E' => self.cmd("goto_next_entry", .{}), - 'P' => self.cmd("goto_next_paragraph", .{}), - ' ' => self.cmd("add_newline_below", .{}), - else => {}, - }, - else => {}, - }; - }, - 'W' => switch (modifiers) { - // way too much stuff if someone wants they can implement it - input.mod.shift => switch (keypress) { - else => {}, - }, - 0 => switch (keypress) { - else => {}, - }, - else => {}, - }, - ' ' => switch (modifiers) { - input.mod.shift => switch (keypress) { - 'F' => self.cmd("file_picker_in_current_directory", .{}), - 'S' => self.cmd("workspace_symbol_picker", .{}), - 'D' => self.cmd("workspace_diagnostics_picker", .{}), - 'P' => self.cmd("system_paste", .{}), - 'R' => self.cmd("replace_selections_with_clipboard", .{}), - '/' => self.cmd("open_command_palette", .{}), - else => {}, - }, - 0 => switch (keypress) { - 'F' => self.cmd("file_picker", .{}), - 'B' => self.cmd("buffer_picker", .{}), - 'J' => self.cmd("jumplist_picker", .{}), - 'S' => self.cmd("symbol_picker", .{}), - 'D' => self.cmd("diagnostics_picker", .{}), - 'A' => self.cmd("code_action", .{}), - 'W' => self.leader = .{ .keypress = keypress, .modifiers = modifiers }, - '\'' => self.cmd("last_picker", .{}), - 'Y' => self.cmd("copy", .{}), - 'P' => self.cmd("system_paste_after", .{}), - '/' => self.cmd("find_in_file", .{}), - 'K' => self.cmd("hover", .{}), - 'R' => self.cmd("rename_symbol", .{}), - 'H' => self.cmd("select_references_to_symbol_under_cursor", .{}), - 'C' => self.cmd("toggle_comment", .{}), - else => {}, - }, - else => {}, - }, - else => {}, - }, - else => {}, - }; -} - -fn map_release(self: *Self, keypress: input.Key) !void { - return switch (keypress) { - input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}), - else => {}, - }; -} - -fn add_count(self: *Self, value: usize) void { - if (self.count > 0) self.count *= 10; - self.count += value; -} - -fn insert_code_point(self: *Self, c: u32) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - var buf: [6]u8 = undefined; - const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf); - try self.input.appendSlice(buf[0..bytes]); -} - -fn insert_bytes(self: *Self, bytes: []const u8) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - try self.input.appendSlice(bytes); -} - -var insert_chars_id: ?command.ID = null; - -fn flush_input(self: *Self) !void { - if (self.input.items.len > 0) { - defer self.input.clearRetainingCapacity(); - const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse { - return tp.exit_error(error.InputTargetNotFound, null); - }; - try command.execute(id, command.fmt(.{self.input.items})); - self.last_cmd = "insert_chars"; - } -} - -fn cmd(self: *Self, name_: []const u8, ctx: command.Context) tp.result { - self.count = 0; - try self.flush_input(); - self.last_cmd = name_; - try command.executeName(name_, ctx); -} - -fn cmd_count(self: *Self, name_: []const u8, ctx: command.Context) tp.result { - var count = if (self.count == 0) 1 else self.count; - self.count = 0; - try self.flush_input(); - self.last_cmd = name_; - while (count > 0) : (count -= 1) - try command.executeName(name_, ctx); -} - -fn cmd_async(self: *Self, name_: []const u8) tp.result { - self.last_cmd = name_; - return tp.self_pid().send(.{ "cmd", name_ }); -} - -fn seq(self: *Self, cmds: anytype, ctx: command.Context) tp.result { - const cmds_type_info = @typeInfo(@TypeOf(cmds)); - if (cmds_type_info != .Struct) @compileError("expected tuple argument"); - const fields_info = cmds_type_info.Struct.fields; - inline for (fields_info) |field_info| - try self.cmd(@field(cmds, field_info.name), ctx); -} - -fn seq_count(self: *Self, cmds: anytype, ctx: command.Context) tp.result { - var count = if (self.count == 0) 1 else self.count; - self.count = 0; - const cmds_type_info = @typeInfo(@TypeOf(cmds)); - if (cmds_type_info != .Struct) @compileError("expected tuple argument"); - const fields_info = cmds_type_info.Struct.fields; - while (count > 0) : (count -= 1) - inline for (fields_info) |field_info| - try self.cmd(@field(cmds, field_info.name), ctx); -} - -pub const hints = keybind.KeybindHints.initComptime(.{ - .{ "add_cursor_all_matches", "C-S-l" }, - .{ "add_cursor_down", "S-A-down" }, - .{ "add_cursor_next_match", "C-d" }, - .{ "add_cursors_to_line_ends", "S-A-i" }, - .{ "add_cursor_up", "S-A-up" }, - .{ "cancel", "esc" }, - .{ "close_file", "C-w" }, - .{ "close_file_without_saving", "C-S-w" }, - .{ "copy", "C-c" }, - .{ "cut", "C-x" }, - .{ "delete_backward", "backspace" }, - .{ "delete_forward", "del, x" }, - .{ "delete_to_begin", "C-k C-u" }, - .{ "delete_to_end", "C-k C-k, d $" }, - .{ "delete_word_left", "C-backspace" }, - .{ "delete_word_right", "C-del" }, - .{ "dump_current_line", "F7" }, - .{ "dump_current_line_tree", "F6" }, - .{ "dupe_down", "C-S-d" }, - .{ "dupe_up", "S-A-d" }, - .{ "enable_fast_scroll", "hold Ctrl" }, - .{ "enable_jump_mode", "hold Alt" }, - .{ "find_in_files", "C-S-f" }, - .{ "find", "C-f, /" }, - .{ "goto", "C-g" }, - .{ "move_to_char", "C-b, C-t" }, // true/false - .{ "open_file", "C-o" }, - .{ "filter", "A-s" }, // self.cmd("filter", command.fmt(.{"sort"})), - // .{ "filter", "S-A-s" }, // self.cmd("filter", command.fmt(.{ "sort", "-u" })), - .{ "format", "S-A-f" }, - .{ "goto_definition", "F12, g d" }, - .{ "goto_declaration", "g D" }, - .{ "goto_implementation", "g i" }, - .{ "goto_type_definition", "g y" }, - .{ "goto_next_file_or_diagnostic", "A-n" }, - .{ "goto_next_match", "C-n, F3, n" }, - .{ "goto_prev_file_or_diagnostic", "A-p" }, - .{ "goto_prev_match", "C-p, S-F3, N" }, - .{ "gutter_mode_next", "A-F10" }, - .{ "indent", "tab" }, - .{ "insert_line", "A-enter" }, - .{ "join_next_line", "A-j" }, - .{ "jump_back", "A-left" }, - .{ "jump_forward", "A-right" }, - .{ "move_begin", "0" }, - .{ "move_buffer_begin", "C-home, g g" }, - .{ "move_buffer_end", "C-end, G" }, - .{ "move_cursor_next_match", "C-k C-d" }, - .{ "move_down", "down, j" }, - .{ "move_end", "end, $, S-4" }, - .{ "move_left", "left" }, - .{ "move_left_vim", "h" }, - .{ "move_page_down", "pgdn" }, - .{ "move_page_up", "pgup" }, - .{ "move_right", "right" }, - .{ "move_right_vim", "l, space" }, - .{ "move_scroll_down", "C-down" }, - .{ "move_scroll_left", "S-A-left" }, - .{ "move_scroll_page_down", "C-pgdn" }, - .{ "move_scroll_page_up", "C-pgup" }, - .{ "move_scroll_right", "S-A-right" }, - .{ "move_scroll_up", "C-up" }, - .{ "move_up", "up, k" }, - .{ "move_word_left", "C-left, A-b, b" }, - .{ "move_word_right", "C-right, A-f, e" }, - .{ "move_word_right_vim", "w" }, - .{ "open_command_palette", "Space ?, C-S-p, :, S-;, S-A-p" }, - .{ "open_previous_file", "C-^" }, - .{ "open_recent", "C-e" }, - .{ "paste", "A-v, p" }, - .{ "pop_cursor", "C-u" }, - .{ "pull_down", "A-down" }, - .{ "pull_up", "A-up" }, - .{ "quit", "C-q" }, - .{ "quit_without_saving", "C-S-q" }, - .{ "redo", "C-S-z, C-y" }, - .{ "save_file", "C-s" }, - .{ "scroll_view_center_cycle", "C-l, z z" }, - .{ "select_all", "C-a" }, - .{ "select_buffer_begin", "C-S-home" }, - .{ "select_buffer_end", "C-S-end" }, - .{ "select_down", "S-down" }, - .{ "select_end", "S-end" }, - .{ "selections_reverse", "C-space" }, - .{ "select_left", "S-left" }, - .{ "select_page_down", "S-pgdn" }, - .{ "select_page_up", "S-pgup" }, - .{ "select_right", "S-right" }, - .{ "select_scroll_down", "C-S-down" }, - .{ "select_scroll_up", "C-S-up" }, - .{ "change_theme", "C-k C-t" }, - .{ "select_up", "S-up" }, - .{ "select_word_left", "C-S-left" }, - .{ "select_word_right", "C-S-right" }, - .{ "smart_insert_line_after", "C-enter, o" }, - .{ "smart_insert_line_before", "S-enter, C-S-enter, O" }, - .{ "smart_insert_line", "enter" }, - .{ "smart_move_begin", "home" }, - .{ "smart_select_begin", "S-home" }, - .{ "system_paste", "C-v" }, - .{ "theme_next", "F10" }, - .{ "theme_prev", "F9" }, - .{ "toggle_comment", "C-/" }, - .{ "toggle_input_mode", "F2" }, - .{ "toggle_inputview", "A-i" }, - .{ "toggle_inspector_view", "F5, C-F5, C-S-i" }, - .{ "toggle_panel", "C-j, F11" }, - .{ "toggle_whitespace_mode", "C-F10" }, - .{ "to_lower", "A-l" }, - .{ "to_upper", "A-u" }, - .{ "undo", "C-z" }, - .{ "undo", "u" }, - .{ "unindent", "S-tab" }, -}); - -const Commands = command.Collection(cmds_); -const cmds_ = struct { - pub const Target = Self; - const Ctx = command.Context; - const Result = command.Result; - - pub fn w(self: *Self, _: Ctx) Result { - try self.cmd("save_file", .{}); - } - pub const w_meta = .{ .description = "w (write file)" }; - - pub fn q(self: *Self, _: Ctx) Result { - try self.cmd("quit", .{}); - } - pub const q_meta = .{ .description = "q (quit)" }; - - pub fn @"q!"(self: *Self, _: Ctx) Result { - try self.cmd("quit_without_saving", .{}); - } - pub const @"q!_meta" = .{ .description = "q! (quit without saving)" }; - - pub fn wq(self: *Self, _: Ctx) Result { - try self.cmd("save_file", .{}); - try self.cmd("quit", .{}); - } - pub const wq_meta = .{ .description = "wq (write file and quit)" }; - - pub fn o(self: *Self, _: Ctx) Result { - try self.cmd("open_file", .{}); - } - pub const o_meta = .{ .description = "o (open file)" }; - - pub fn @"wq!"(self: *Self, _: Ctx) Result { - self.cmd("save_file", .{}) catch {}; - try self.cmd("quit_without_saving", .{}); - } - pub const @"wq!_meta" = .{ .description = "wq! (write file and quit without saving)" }; -}; diff --git a/src/keybind/static/input/helix/select.zig b/src/keybind/static/input/helix/select.zig deleted file mode 100644 index 2d968ca..0000000 --- a/src/keybind/static/input/helix/select.zig +++ /dev/null @@ -1,669 +0,0 @@ -const std = @import("std"); -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); -const keybind = @import("../../keybind.zig"); - -const Self = @This(); -const input_buffer_size = 1024; - -allocator: std.mem.Allocator, -input: std.ArrayList(u8), -last_cmd: []const u8 = "", -leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null, -count: usize = 0, -commands: Commands = undefined, - -pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler { - const self: *Self = try allocator.create(Self); - self.* = .{ - .allocator = allocator, - .input = try std.ArrayList(u8).initCapacity(allocator, input_buffer_size), - }; - try self.commands.init(self); - return EventHandler.to_owned(self); -} - -pub fn deinit(self: *Self) void { - self.commands.deinit(); - self.input.deinit(); - self.allocator.destroy(self); -} - -pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var egc: input.Key = undefined; - var modifiers: input.Mods = undefined; - var text: []const u8 = undefined; - - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) { - self.map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{"F"})) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace()); - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } - return false; -} - -pub fn add_keybind() void {} - -fn map_event(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - return switch (event) { - input.event.press => self.map_press(keypress, egc, modifiers), - input.event.repeat => self.map_press(keypress, egc, modifiers), - input.event.release => self.map_release(keypress), - else => {}, - }; -} - -fn map_press(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - if (self.count > 0 and modifiers == 0 and '0' <= keypress and keypress <= '9') return self.add_count(keypress - '0'); - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers); - switch (keypress) { - input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}), - else => {}, - } - return switch (modifiers) { - input.mod.ctrl => switch (keynormal) { - 'B' => self.cmd("move_scroll_page_up", .{}), - 'F' => self.cmd("move_scroll_page_down", .{}), - 'U' => self.cmd("page_cursor_half_up", .{}), - 'D' => self.cmd("page_cursor_half_down", .{}), - - 'C' => self.cmd("toggle_comment", .{}), - - 'I' => self.cmd("jump_forward", .{}), - 'O' => self.cmd("jump_back", .{}), - 'S' => self.cmd("save_selection", .{}), - 'W' => self.leader = .{ .keypress = keynormal, .modifiers = 0 }, - - 'A' => self.cmd("increment", .{}), - 'X' => self.cmd("decrement", .{}), - else => {}, - }, - input.mod.ctrl | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - '6' => self.cmd("open_previous_file", .{}), - else => {}, - }, - input.mod.alt => switch (keynormal) { - '.' => self.cmd("repeat_last_motion", .{}), - - '`' => self.cmd("switch_to_uppercase", .{}), - - 'D' => self.cmd("delete_backward", .{}), - 'C' => { - try self.cmd("delete_backward", .{}); - try self.cmd("enter_mode", command.fmt(.{"helix/insert"})); - }, - - 'S' => self.cmd("split_selection_on_newline", .{}), - '-' => self.cmd("merge_selections", .{}), - '_' => self.cmd("merge_consecutive_selections", .{}), - - ';' => self.cmd("flip_selections", .{}), - 'O', input.key.up => self.cmd("expand_selection", .{}), - 'I', input.key.down => self.cmd("shrink_selection", .{}), - 'P', input.key.left => self.cmd("select_prev_sibling", .{}), - 'N', input.key.right => self.cmd("select_next_sibling", .{}), - - 'E' => self.cmd("extend_parent_node_end", .{}), - 'B' => self.cmd("extend_parent_node_start", .{}), - 'A' => self.cmd("select_all_siblings", .{}), - - 'X' => self.cmd("shrink_to_line_bounds", .{}), - - 'U' => self.cmd("undo", .{}), - - ',' => self.cmd("remove_primary_selection", .{}), - else => {}, - }, - input.mod.alt | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - - 'C' => self.cmd("copy_selection_on_next_line", .{}), - - 'I', input.key.down => self.cmd("select_all_children", .{}), - - 'U' => self.cmd("redo", .{}), - - 'j' => self.cmd("join_selections_space", .{}), - - '(' => self.cmd("rotate_selection_contents_backward", .{}), - ')' => self.cmd("rotate_selection_contents_forward", .{}), - - '\\' => self.cmd("shell_pipe_to", .{}), - '1' => self.cmd("shell_append_output", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - '`' => self.cmd("switch_case", .{}), - - 't' => self.cmd("extend_till_prev_char", .{}), - 'f' => self.cmd("extend_prev_char", .{}), - 'r' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - - 'w' => self.cmd_count("extend_next_long_word_start", .{}), - 'b' => self.cmd_count("extend_prev_long_word_start", .{}), - 'e' => self.cmd_count("extend_next_long_word_end", .{}), - - 'g' => if (self.count == 0) - self.cmd("move_buffer_end", .{}) - else { - const count = self.count; - try self.cmd("move_buffer_begin", .{}); - self.count = count - 1; - if (self.count > 0) - try self.cmd_count("move_down", .{}); - }, - - 'i' => self.seq(.{ "smart_move_begin", "enter_mode" }, command.fmt(.{"helix/insert"})), - 'a' => self.seq(.{ "move_end", "enter_mode" }, command.fmt(.{"helix/insert"})), - - 'o' => self.seq(.{ "smart_insert_line_before", "enter_mode" }, command.fmt(.{"helix/insert"})), - - 'c' => self.cmd("copy_selection_on_next_line", .{}), - - 's' => self.cmd("split_selection", .{}), - - 'x' => self.cmd_count("extend_to_line_bounds", .{}), - - '/' => self.cmd("rfind", .{}), - - 'n' => self.cmd("extend_search_next", .{}), - '8' => self.cmd("extend_search_prev", .{}), - - 'u' => self.cmd("redo", .{}), - - 'p' => self.cmd("paste", .{}), - - 'q' => self.cmd("replay_macro", .{}), - - '.' => self.cmd("indent", .{}), - ',' => self.cmd("unindent", .{}), - - 'j' => self.cmd("join_selections", .{}), - - ';' => self.cmd("open_command_palette", .{}), - - '7' => self.cmd("align_selections", .{}), - '-' => self.cmd("trim_selections", .{}), - - '9' => self.cmd("rotate_selections_backward", .{}), - '0' => self.cmd("rotate_selections_forward", .{}), - - '\'' => self.cmd("select_register", .{}), - '\\' => self.cmd("shell_pipe", .{}), - '1' => self.cmd("shell_insert_output", .{}), - '4' => self.cmd("shell_keep_pipe", .{}), - else => {}, - }, - 0 => switch (keypress) { - input.key.f2 => self.cmd("toggle_input_mode", .{}), - 'h', input.key.left => self.cmd_count("select_left", .{}), - 'j', input.key.down => self.cmd_count("select_down", .{}), - 'k', input.key.up => self.cmd_count("select_up", .{}), - 'l', input.key.right => self.cmd_count("select_right", .{}), - - 't' => self.cmd("extend_till_char", .{}), - 'f' => self.cmd("extend_next_char", .{}), - 'r' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - - '`' => self.cmd("switch_to_lowercase", .{}), - - input.key.home => self.cmd("extend_to_line_start", .{}), - input.key.end => self.cmd("extend_to_line_end", .{}), - - 'w' => self.cmd_count("extend_next_word_start", .{}), - 'b' => self.cmd_count("extend_pre_word_start", .{}), - 'e' => self.cmd_count("extend_next_word_end", .{}), - - 'v' => self.cmd("enter_mode", command.fmt(.{"helix/normal"})), - 'g' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - - 'i' => self.cmd("enter_mode", command.fmt(.{"helix/insert"})), - 'a' => self.seq(.{ "move_right", "enter_mode" }, command.fmt(.{"helix/insert"})), // TODO: keep selection - 'o' => self.seq(.{ "smart_insert_line_after", "enter_mode" }, command.fmt(.{"helix/insert"})), - - 'd' => self.cmd("cut", .{}), - 'c' => { - try self.cmd("cut", .{}); - try self.cmd("enter_mode", command.fmt(.{"helix/insert"})); - }, - - 's' => self.cmd("select_regex", .{}), - ';' => self.cmd("collapse_selections", .{}), - - 'x' => self.cmd_count("extend_line_below", .{}), - - 'm' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - '[' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - ']' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - - '/' => self.cmd("find", .{}), - 'n' => self.cmd("goto_next_match", .{}), - 'u' => self.cmd("undo", .{}), - - 'y' => self.cmd("copy", .{}), - 'p' => self.cmd("paste_after", .{}), - - 'q' => self.cmd("record_macro", .{}), - - '=' => self.cmd("format_selections", .{}), - - ',' => self.cmd("keep_primary_selection", .{}), - - input.key.escape => self.cmd("enter_mode", command.fmt(.{"helix/normal"})), - - input.key.page_up => self.cmd("move_scroll_page_up", .{}), - input.key.page_down => self.cmd("move_scroll_page_down", .{}), - - ' ' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'z' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - - '1' => self.add_count(1), - '2' => self.add_count(2), - '3' => self.add_count(3), - '4' => self.add_count(4), - '5' => self.add_count(5), - '6' => self.add_count(6), - '7' => self.add_count(7), - '8' => self.add_count(8), - '9' => self.add_count(9), - else => {}, - }, - else => {}, - }; -} - -fn mapFollower(self: *Self, keypress: input.Key, _: u32, modifiers: input.Mods) !void { - if (keypress == input.key.left_control or - keypress == input.key.right_control or - keypress == input.key.left_alt or - keypress == input.key.right_alt or - keypress == input.key.left_shift or - keypress == input.key.right_shift or - keypress == input.key.left_super or - keypress == input.key.right_super) return; - - defer self.leader = null; - const ldr = if (self.leader) |leader| leader else return; - return switch (ldr.modifiers) { - 0 => switch (ldr.keypress) { - 'G' => switch (modifiers) { - 0 => switch (keypress) { - 'G' => self.cmd("move_buffer_begin", .{}), - 'E' => self.cmd("move_buffer_end", .{}), - 'F' => self.cmd("goto_file", .{}), - 'H' => self.cmd("move_begin", .{}), - 'L' => self.cmd("move_end", .{}), - 'S' => self.cmd("smart_move_begin", .{}), - 'D' => self.cmd("goto_definition", .{}), - 'Y' => self.cmd("goto_type_definition", .{}), - 'R' => self.cmd("goto_reference", .{}), - 'I' => self.cmd("goto_implementation", .{}), - 'T' => self.cmd("goto_window_top", .{}), - 'C' => self.cmd("goto_window_center", .{}), - 'B' => self.cmd("goto_window_bottom", .{}), - 'A' => self.cmd("goto_last_accessed_file", .{}), - 'M' => self.cmd("goto_last_modified_file", .{}), - 'N' => self.cmd("goto_next_buffer", .{}), - 'P' => self.cmd("goto_previous_buffer", .{}), - 'K' => self.cmd("goto_previous_buffer", .{}), - '.' => self.cmd("goto_last_modification", .{}), - 'W' => self.cmd("goto_word", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - 'D' => self.cmd("goto_declaration", .{}), - else => {}, - }, - else => {}, - }, - 'M' => { - try switch (modifiers) { - 0 => switch (keypress) { - 'M' => self.cmd("match_brackets", .{}), - 'S' => self.cmd("surround_add", .{}), - 'R' => self.cmd("surround_replace", .{}), - 'D' => self.cmd("surround_delete", .{}), - 'A' => self.cmd("select_textobject_around", .{}), - 'I' => self.cmd("select_textobject_inner", .{}), - else => {}, - }, - else => {}, - }; - }, - '[' => { - try switch (modifiers) { - input.mod.shift => switch (keypress) { - 'D' => self.cmd("goto_first_diag", .{}), - 'G' => self.cmd("goto_first_change", .{}), - 'T' => self.cmd("goto_prev_test", .{}), - else => {}, - }, - 0 => switch (keypress) { - 'D' => self.cmd("goto_prev_diagnostic", .{}), - 'G' => self.cmd("goto_prev_change", .{}), - 'F' => self.cmd("goto_prev_function", .{}), - 'T' => self.cmd("goto_prev_class", .{}), - 'A' => self.cmd("goto_prev_parameter", .{}), - 'C' => self.cmd("goto_prev_comment", .{}), - 'E' => self.cmd("goto_prev_entry", .{}), - 'P' => self.cmd("goto_prev_paragraph", .{}), - ' ' => self.cmd("add_newline_above", .{}), - else => {}, - }, - else => {}, - }; - }, - ']' => { - try switch (modifiers) { - input.mod.shift => switch (keypress) { - 'D' => self.cmd("goto_last_diag", .{}), - 'G' => self.cmd("goto_last_change", .{}), - 'T' => self.cmd("goto_next_test", .{}), - else => {}, - }, - 0 => switch (keypress) { - 'D' => self.cmd("goto_next_diagnostic", .{}), - 'G' => self.cmd("goto_next_change", .{}), - 'F' => self.cmd("goto_next_function", .{}), - 'T' => self.cmd("goto_next_class", .{}), - 'A' => self.cmd("goto_next_parameter", .{}), - 'C' => self.cmd("goto_next_comment", .{}), - 'E' => self.cmd("goto_next_entry", .{}), - 'P' => self.cmd("goto_next_paragraph", .{}), - ' ' => self.cmd("add_newline_below", .{}), - else => {}, - }, - else => {}, - }; - }, - 'W' => switch (modifiers) { - // way too much stuff if someone wants they can implement it - input.mod.shift => switch (keypress) { - else => {}, - }, - 0 => switch (keypress) { - else => {}, - }, - else => {}, - }, - ' ' => switch (modifiers) { - input.mod.shift => switch (keypress) { - 'F' => self.cmd("file_picker_in_current_directory", .{}), - 'S' => self.cmd("workspace_symbol_picker", .{}), - 'D' => self.cmd("workspace_diagnostics_picker", .{}), - 'P' => self.cmd("system_paste", .{}), - 'R' => self.cmd("replace_selections_with_clipboard", .{}), - '/' => self.cmd("open_command_palette", .{}), - else => {}, - }, - 0 => switch (keypress) { - 'F' => self.cmd("file_picker", .{}), - 'B' => self.cmd("buffer_picker", .{}), - 'J' => self.cmd("jumplist_picker", .{}), - 'S' => self.cmd("symbol_picker", .{}), - 'D' => self.cmd("diagnostics_picker", .{}), - 'A' => self.cmd("code_action", .{}), - 'W' => self.leader = .{ .keypress = keypress, .modifiers = modifiers }, - '\'' => self.cmd("last_picker", .{}), - 'Y' => self.cmd("copy", .{}), - 'P' => self.cmd("system_paste_after", .{}), - '/' => self.cmd("find_in_file", .{}), - 'K' => self.cmd("hover", .{}), - 'R' => self.cmd("rename_symbol", .{}), - 'H' => self.cmd("select_references_to_symbol_under_cursor", .{}), - 'C' => self.cmd("toggle_comment", .{}), - else => {}, - }, - else => {}, - }, - else => {}, - }, - else => {}, - }; -} - -fn map_release(self: *Self, keypress: input.Key) !void { - return switch (keypress) { - input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}), - else => {}, - }; -} - -fn add_count(self: *Self, value: usize) void { - if (self.count > 0) self.count *= 10; - self.count += value; -} - -fn insert_code_point(self: *Self, c: u32) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - var buf: [6]u8 = undefined; - const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf); - try self.input.appendSlice(buf[0..bytes]); -} - -fn insert_bytes(self: *Self, bytes: []const u8) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - try self.input.appendSlice(bytes); -} - -var insert_chars_id: ?command.ID = null; - -fn flush_input(self: *Self) !void { - if (self.input.items.len > 0) { - defer self.input.clearRetainingCapacity(); - const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse { - return tp.exit_error(error.InputTargetNotFound, null); - }; - try command.execute(id, command.fmt(.{self.input.items})); - self.last_cmd = "insert_chars"; - } -} - -fn cmd(self: *Self, name_: []const u8, ctx: command.Context) tp.result { - self.count = 0; - try self.flush_input(); - self.last_cmd = name_; - try command.executeName(name_, ctx); -} - -fn cmd_count(self: *Self, name_: []const u8, ctx: command.Context) tp.result { - var count = if (self.count == 0) 1 else self.count; - self.count = 0; - try self.flush_input(); - self.last_cmd = name_; - while (count > 0) : (count -= 1) - try command.executeName(name_, ctx); -} - -fn cmd_async(self: *Self, name_: []const u8) tp.result { - self.last_cmd = name_; - return tp.self_pid().send(.{ "cmd", name_ }); -} - -fn seq(self: *Self, cmds: anytype, ctx: command.Context) tp.result { - const cmds_type_info = @typeInfo(@TypeOf(cmds)); - if (cmds_type_info != .Struct) @compileError("expected tuple argument"); - const fields_info = cmds_type_info.Struct.fields; - inline for (fields_info) |field_info| - try self.cmd(@field(cmds, field_info.name), ctx); -} - -fn seq_count(self: *Self, cmds: anytype, ctx: command.Context) tp.result { - var count = if (self.count == 0) 1 else self.count; - self.count = 0; - const cmds_type_info = @typeInfo(@TypeOf(cmds)); - if (cmds_type_info != .Struct) @compileError("expected tuple argument"); - const fields_info = cmds_type_info.Struct.fields; - while (count > 0) : (count -= 1) - inline for (fields_info) |field_info| - try self.cmd(@field(cmds, field_info.name), ctx); -} - -pub const hints = keybind.KeybindHints.initComptime(.{ - .{ "add_cursor_all_matches", "C-S-l" }, - .{ "add_cursor_down", "S-A-down" }, - .{ "add_cursor_next_match", "C-d" }, - .{ "add_cursors_to_line_ends", "S-A-i" }, - .{ "add_cursor_up", "S-A-up" }, - .{ "cancel", "esc" }, - .{ "close_file", "C-w" }, - .{ "close_file_without_saving", "C-S-w" }, - .{ "copy", "C-c" }, - .{ "cut", "C-x" }, - .{ "delete_backward", "backspace" }, - .{ "delete_forward", "del, x" }, - .{ "delete_to_begin", "C-k C-u" }, - .{ "delete_to_end", "C-k C-k, d $" }, - .{ "delete_word_left", "C-backspace" }, - .{ "delete_word_right", "C-del" }, - .{ "dump_current_line", "F7" }, - .{ "dump_current_line_tree", "F6" }, - .{ "dupe_down", "C-S-d" }, - .{ "dupe_up", "S-A-d" }, - .{ "enable_fast_scroll", "hold Ctrl" }, - .{ "enable_jump_mode", "hold Alt" }, - .{ "find_in_files", "C-S-f" }, - .{ "find", "C-f, /" }, - .{ "goto", "C-g" }, - .{ "move_to_char", "C-b, C-t" }, // true/false - .{ "open_file", "C-o" }, - .{ "filter", "A-s" }, // self.cmd("filter", command.fmt(.{"sort"})), - // .{ "filter", "S-A-s" }, // self.cmd("filter", command.fmt(.{ "sort", "-u" })), - .{ "format", "S-A-f" }, - .{ "goto_definition", "F12, g d" }, - .{ "goto_declaration", "g D" }, - .{ "goto_implementation", "g i" }, - .{ "goto_type_definition", "g y" }, - .{ "goto_next_file_or_diagnostic", "A-n" }, - .{ "goto_next_match", "C-n, F3, n" }, - .{ "goto_prev_file_or_diagnostic", "A-p" }, - .{ "goto_prev_match", "C-p, S-F3, N" }, - .{ "gutter_mode_next", "A-F10" }, - .{ "indent", "tab" }, - .{ "insert_line", "A-enter" }, - .{ "join_next_line", "A-j" }, - .{ "jump_back", "A-left" }, - .{ "jump_forward", "A-right" }, - .{ "move_begin", "0" }, - .{ "move_buffer_begin", "C-home, g g" }, - .{ "move_buffer_end", "C-end, G" }, - .{ "move_cursor_next_match", "C-k C-d" }, - .{ "move_down", "down, j" }, - .{ "move_end", "end, $, S-4" }, - .{ "move_left", "left" }, - .{ "move_left_vim", "h" }, - .{ "move_page_down", "pgdn" }, - .{ "move_page_up", "pgup" }, - .{ "move_right", "right" }, - .{ "move_right_vim", "l, space" }, - .{ "move_scroll_down", "C-down" }, - .{ "move_scroll_left", "S-A-left" }, - .{ "move_scroll_page_down", "C-pgdn" }, - .{ "move_scroll_page_up", "C-pgup" }, - .{ "move_scroll_right", "S-A-right" }, - .{ "move_scroll_up", "C-up" }, - .{ "move_up", "up, k" }, - .{ "move_word_left", "C-left, A-b, b" }, - .{ "move_word_right", "C-right, A-f, e" }, - .{ "move_word_right_vim", "w" }, - .{ "open_command_palette", "Space ?, C-S-p, :, S-;, S-A-p" }, - .{ "open_previous_file", "C-^" }, - .{ "open_recent", "C-e" }, - .{ "paste", "A-v, p" }, - .{ "pop_cursor", "C-u" }, - .{ "pull_down", "A-down" }, - .{ "pull_up", "A-up" }, - .{ "quit", "C-q" }, - .{ "quit_without_saving", "C-S-q" }, - .{ "redo", "C-S-z, C-y" }, - .{ "save_file", "C-s" }, - .{ "scroll_view_center_cycle", "C-l, z z" }, - .{ "select_all", "C-a" }, - .{ "select_buffer_begin", "C-S-home" }, - .{ "select_buffer_end", "C-S-end" }, - .{ "select_down", "S-down" }, - .{ "select_end", "S-end" }, - .{ "selections_reverse", "C-space" }, - .{ "select_left", "S-left" }, - .{ "select_page_down", "S-pgdn" }, - .{ "select_page_up", "S-pgup" }, - .{ "select_right", "S-right" }, - .{ "select_scroll_down", "C-S-down" }, - .{ "select_scroll_up", "C-S-up" }, - .{ "change_theme", "C-k C-t" }, - .{ "select_up", "S-up" }, - .{ "select_word_left", "C-S-left" }, - .{ "select_word_right", "C-S-right" }, - .{ "smart_insert_line_after", "C-enter, o" }, - .{ "smart_insert_line_before", "S-enter, C-S-enter, O" }, - .{ "smart_insert_line", "enter" }, - .{ "smart_move_begin", "home" }, - .{ "smart_select_begin", "S-home" }, - .{ "system_paste", "C-v" }, - .{ "theme_next", "F10" }, - .{ "theme_prev", "F9" }, - .{ "toggle_comment", "C-/" }, - .{ "toggle_input_mode", "F2" }, - .{ "toggle_inputview", "A-i" }, - .{ "toggle_inspector_view", "F5, C-F5, C-S-i" }, - .{ "toggle_panel", "C-j, F11" }, - .{ "toggle_whitespace_mode", "C-F10" }, - .{ "to_lower", "A-l" }, - .{ "to_upper", "A-u" }, - .{ "undo", "C-z" }, - .{ "undo", "u" }, - .{ "unindent", "S-tab" }, -}); - -const Commands = command.Collection(cmds_); -const cmds_ = struct { - pub const Target = Self; - const Ctx = command.Context; - const Result = command.Result; - - pub fn w(self: *Self, _: Ctx) Result { - try self.cmd("save_file", .{}); - } - pub const w_meta = .{ .description = "w (write file)" }; - - pub fn q(self: *Self, _: Ctx) Result { - try self.cmd("quit", .{}); - } - pub const q_meta = .{ .description = "q (quit)" }; - - pub fn @"q!"(self: *Self, _: Ctx) Result { - try self.cmd("quit_without_saving", .{}); - } - pub const @"q!_meta" = .{ .description = "q! (quit without saving)" }; - - pub fn wq(self: *Self, _: Ctx) Result { - try self.cmd("save_file", .{}); - try self.cmd("quit", .{}); - } - pub const wq_meta = .{ .description = "wq (write file and quit)" }; - - pub fn o(self: *Self, _: Ctx) Result { - try self.cmd("open_file", .{}); - } - pub const o_meta = .{ .description = "o (open file)" }; - - pub fn @"wq!"(self: *Self, _: Ctx) Result { - self.cmd("save_file", .{}) catch {}; - try self.cmd("quit_without_saving", .{}); - } - pub const @"wq!_meta" = .{ .description = "wq! (write file and quit without saving)" }; -}; diff --git a/src/keybind/static/input/home.zig b/src/keybind/static/input/home.zig deleted file mode 100644 index 649c78a..0000000 --- a/src/keybind/static/input/home.zig +++ /dev/null @@ -1,173 +0,0 @@ -const std = @import("std"); -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); -const keybind = @import("../keybind.zig"); - -const Self = @This(); - -allocator: std.mem.Allocator, -f: usize = 0, -leader: ?struct { keypress: u32, modifiers: u32 } = null, - -pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler { - const self: *Self = try allocator.create(Self); - self.* = .{ - .allocator = allocator, - }; - return EventHandler.to_owned(self); -} - -pub fn deinit(self: *Self) void { - self.allocator.destroy(self); -} - -pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var modifiers: input.Mods = undefined; - - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.any, tp.string, tp.extract(&modifiers) })) { - try self.map_event(event, keypress, modifiers); - } - return false; -} - -fn map_event(self: *Self, event: u32, keypress: u32, modifiers: u32) tp.result { - return switch (event) { - input.event.press => self.mapPress(keypress, modifiers), - input.event.repeat => self.mapPress(keypress, modifiers), - else => {}, - }; -} - -fn mapPress(self: *Self, keypress: u32, modifiers: u32) tp.result { - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - if (self.leader) |_| return self.mapFollower(keynormal, modifiers); - return switch (modifiers) { - input.mod.ctrl => switch (keynormal) { - 'F' => self.sheeran(), - 'J' => self.cmd("toggle_panel", .{}), - 'Q' => self.cmd("quit", .{}), - 'W' => self.cmd("quit", .{}), - 'O' => self.cmd("open_file", .{}), - 'E' => self.cmd("open_recent", .{}), - 'R' => self.cmd("open_recent_project", .{}), - 'P' => self.cmd("open_command_palette", .{}), - '/' => self.cmd("open_help", .{}), - 'K' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - else => {}, - }, - input.mod.ctrl | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - 'Q' => self.cmd("quit_without_saving", .{}), - 'R' => self.cmd("restart", .{}), - 'F' => self.cmd("find_in_files", .{}), - 'L' => self.cmd_async("toggle_panel"), - '/' => self.cmd("open_help", .{}), - else => {}, - }, - input.mod.alt | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - else => {}, - }, - input.mod.alt => switch (keynormal) { - 'N' => self.cmd("goto_next_file_or_diagnostic", .{}), - 'P' => self.cmd("goto_prev_file_or_diagnostic", .{}), - 'L' => self.cmd("toggle_panel", .{}), - 'I' => self.cmd("toggle_inputview", .{}), - 'X' => self.cmd("open_command_palette", .{}), - input.key.left => self.cmd("jump_back", .{}), - input.key.right => self.cmd("jump_forward", .{}), - else => {}, - }, - 0 => switch (keypress) { - input.key.f2 => self.cmd("toggle_input_mode", .{}), - 'h' => self.cmd("open_help", .{}), - 'o' => self.cmd("open_file", .{}), - 'e' => self.cmd("open_recent", .{}), - 'r' => self.cmd("open_recent_project", .{}), - 'p' => self.cmd("open_command_palette", .{}), - 'c' => self.cmd("open_config", .{}), - 't' => self.cmd("change_theme", .{}), - 'q' => self.cmd("quit", .{}), - - input.key.f1 => self.cmd("open_help", .{}), - input.key.f6 => self.cmd("open_config", .{}), - input.key.f9 => self.cmd("theme_prev", .{}), - input.key.f10 => self.cmd("theme_next", .{}), - input.key.f11 => self.cmd("toggle_panel", .{}), - input.key.f12 => self.cmd("toggle_inputview", .{}), - input.key.up => self.cmd("home_menu_up", .{}), - input.key.down => self.cmd("home_menu_down", .{}), - input.key.enter => self.cmd("home_menu_activate", .{}), - else => {}, - }, - else => {}, - }; -} - -fn mapFollower(self: *Self, keypress: u32, modifiers: u32) !void { - defer self.leader = null; - const ldr = if (self.leader) |leader| leader else return; - return switch (ldr.modifiers) { - input.mod.ctrl => switch (ldr.keypress) { - 'K' => switch (modifiers) { - input.mod.ctrl => switch (keypress) { - 'T' => self.cmd("change_theme", .{}), - else => {}, - }, - else => {}, - }, - else => {}, - }, - else => {}, - }; -} - -fn cmd(_: *Self, name_: []const u8, ctx: command.Context) tp.result { - try command.executeName(name_, ctx); -} - -fn msg(_: *Self, text: []const u8) tp.result { - return tp.self_pid().send(.{ "log", "home", text }); -} - -fn cmd_async(_: *Self, name_: []const u8) tp.result { - return tp.self_pid().send(.{ "cmd", name_ }); -} - -fn sheeran(self: *Self) void { - self.f += 1; - if (self.f >= 5) { - self.f = 0; - self.cmd("home_sheeran", .{}) catch {}; - } -} - -pub const hints = keybind.KeybindHints.initComptime(.{ - .{ "find_in_files", "C-S-f" }, - .{ "open_file", "o, C-o" }, - .{ "open_recent", "e, C-e" }, - .{ "open_recent_project", "r, C-r" }, - .{ "open_command_palette", "p, C-S-p, S-A-p, A-x" }, - .{ "home_menu_activate", "enter" }, - .{ "home_menu_down", "down" }, - .{ "home_menu_up", "up" }, - .{ "jump_back", "A-left" }, - .{ "jump_forward", "A-right" }, - .{ "open_config", "c, F6" }, - .{ "open_help", "h, F1, C-/, C-S-/" }, - .{ "quit", "q, C-q, C-w" }, - .{ "quit_without_saving", "C-S-q" }, - .{ "restart", "C-S-r" }, - .{ "change_theme", "t, C-k C-t" }, - .{ "theme_next", "F10" }, - .{ "theme_prev", "F9" }, - .{ "toggle_input_mode", "F2" }, - .{ "toggle_inputview", "F12, A-i" }, - .{ "toggle_panel", "F11, C-j, A-l, C-S-l" }, - .{ "goto_next_file_or_diagnostic", "A-n" }, - .{ "goto_prev_file_or_diagnostic", "A-p" }, -}); diff --git a/src/keybind/static/input/vim/insert.zig b/src/keybind/static/input/vim/insert.zig deleted file mode 100644 index 1061abb..0000000 --- a/src/keybind/static/input/vim/insert.zig +++ /dev/null @@ -1,365 +0,0 @@ -const std = @import("std"); -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); -const keybind = @import("../../keybind.zig"); - -const Self = @This(); -const input_buffer_size = 1024; - -allocator: std.mem.Allocator, -input: std.ArrayList(u8), -last_cmd: []const u8 = "", -leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null, -commands: Commands = undefined, -last_key: KeyPressEvent = .{}, -enable_chording: bool, - -pub const KeyPressEvent = struct { - keypress: input.Key = 0, - modifiers: input.Mods = std.math.maxInt(input.Mods), - egc: input.Key = 0, - timestamp_ms: i64 = 0, -}; - -pub fn create(allocator: std.mem.Allocator, opts: anytype) !EventHandler { - const self: *Self = try allocator.create(Self); - self.* = .{ - .allocator = allocator, - .input = try std.ArrayList(u8).initCapacity(allocator, input_buffer_size), - .enable_chording = opts.enable_chording, - }; - try self.commands.init(self); - return EventHandler.to_owned(self); -} - -pub fn deinit(self: *Self) void { - self.commands.deinit(); - self.input.deinit(); - self.allocator.destroy(self); -} - -pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var egc: input.Key = undefined; - var modifiers: input.Mods = undefined; - var text: []const u8 = undefined; - - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) { - self.map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{"F"})) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace()); - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } - return false; -} - -pub fn add_keybind() void {} - -fn map_event(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - return switch (event) { - input.event.press => self.map_press(keypress, egc, modifiers), - input.event.repeat => self.map_press(keypress, egc, modifiers), - input.event.release => self.map_release(keypress), - else => {}, - }; -} - -fn map_press(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - if (self.leader) |_| return self.map_follower(keynormal, egc, modifiers); - switch (keypress) { - input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}), - else => {}, - } - - if (self.enable_chording) { - - //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("undo", .{}); - 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("undo", .{}); - 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("undo", .{}); - 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("undo", .{}); - 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) { - input.mod.ctrl => switch (keynormal) { - 'E' => self.cmd("open_recent", .{}), - 'U' => self.cmd("move_scroll_page_up", .{}), - 'D' => self.cmd("move_scroll_page_down", .{}), - 'J' => self.cmd("toggle_panel", .{}), - 'Z' => self.cmd("undo", .{}), - 'Y' => self.cmd("redo", .{}), - 'Q' => self.cmd("quit", .{}), - 'W' => self.cmd("close_file", .{}), - 'S' => self.cmd("save_file", .{}), - 'L' => self.cmd("scroll_view_center_cycle", .{}), - 'N' => self.cmd("goto_next_match", .{}), - 'P' => self.cmd("goto_prev_match", .{}), - 'B' => self.cmd("move_to_char", command.fmt(.{false})), - 'T' => self.cmd("move_to_char", command.fmt(.{true})), - 'X' => self.cmd("cut", .{}), - 'C' => self.cmd("enter_mode", command.fmt(.{"vim/normal"})), - 'V' => self.cmd("system_paste", .{}), - 'K' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'F' => self.cmd("find", .{}), - 'G' => self.cmd("goto", .{}), - 'O' => self.cmd("run_ls", .{}), - 'A' => self.cmd("select_all", .{}), - 'I' => self.insert_bytes("\t"), - '/' => self.cmd("toggle_comment", .{}), - input.key.enter => self.cmd("smart_insert_line_after", .{}), - input.key.space => self.cmd("selections_reverse", .{}), - input.key.end => self.cmd("move_buffer_end", .{}), - input.key.home => self.cmd("move_buffer_begin", .{}), - input.key.up => self.cmd("move_scroll_up", .{}), - input.key.down => self.cmd("move_scroll_down", .{}), - input.key.page_up => self.cmd("move_scroll_page_up", .{}), - input.key.page_down => self.cmd("move_scroll_page_down", .{}), - input.key.left => self.cmd("move_word_left", .{}), - input.key.right => self.cmd("move_word_right", .{}), - input.key.backspace => self.cmd("delete_word_left", .{}), - input.key.delete => self.cmd("delete_word_right", .{}), - input.key.f5 => self.cmd("toggle_inspector_view", .{}), - input.key.f10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34 - else => {}, - }, - input.mod.ctrl | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - 'D' => self.cmd("dupe_down", .{}), - 'Z' => self.cmd("redo", .{}), - 'Q' => self.cmd("quit_without_saving", .{}), - 'W' => self.cmd("close_file_without_saving", .{}), - 'F' => self.cmd("find_in_files", .{}), - 'L' => self.cmd_async("add_cursor_all_matches"), - 'I' => self.cmd_async("toggle_inspector_view"), - input.key.enter => self.cmd("smart_insert_line_before", .{}), - input.key.end => self.cmd("select_buffer_end", .{}), - input.key.home => self.cmd("select_buffer_begin", .{}), - input.key.up => self.cmd("select_scroll_up", .{}), - input.key.down => self.cmd("select_scroll_down", .{}), - input.key.left => self.cmd("select_word_left", .{}), - input.key.right => self.cmd("select_word_right", .{}), - else => {}, - }, - input.mod.alt => switch (keynormal) { - 'J' => self.cmd("join_next_line", .{}), - 'N' => self.cmd("goto_next_match", .{}), - 'P' => self.cmd("goto_prev_match", .{}), - 'U' => self.cmd("to_upper", .{}), - 'L' => self.cmd("to_lower", .{}), - 'I' => self.cmd("toggle_inputview", .{}), - 'B' => self.cmd("move_word_left", .{}), - 'F' => self.cmd("move_word_right", .{}), - 'S' => self.cmd("filter", command.fmt(.{"sort"})), - 'V' => self.cmd("paste", .{}), - input.key.left => self.cmd("jump_back", .{}), - input.key.right => self.cmd("jump_forward", .{}), - input.key.up => self.cmd("pull_up", .{}), - input.key.down => self.cmd("pull_down", .{}), - input.key.enter => self.cmd("insert_line", .{}), - input.key.f10 => self.cmd("gutter_mode_next", .{}), // aka F58 - else => {}, - }, - input.mod.alt | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - 'D' => self.cmd("dupe_up", .{}), - 'F' => self.cmd("filter", command.fmt(.{ "zig", "fmt", "--stdin" })), - 'S' => self.cmd("filter", command.fmt(.{ "sort", "-u" })), - 'V' => self.cmd("paste", .{}), - 'I' => self.cmd("add_cursors_to_line_ends", .{}), - input.key.left => self.cmd("move_scroll_left", .{}), - input.key.right => self.cmd("move_scroll_right", .{}), - input.key.up => self.cmd("add_cursor_up", .{}), - input.key.down => self.cmd("add_cursor_down", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - input.key.f3 => self.cmd("goto_prev_match", .{}), - input.key.f10 => self.cmd("toggle_syntax_highlighting", .{}), - input.key.left => self.cmd("select_left", .{}), - input.key.right => self.cmd("select_right", .{}), - input.key.up => self.cmd("select_up", .{}), - input.key.down => self.cmd("select_down", .{}), - input.key.home => self.cmd("smart_select_begin", .{}), - input.key.end => self.cmd("select_end", .{}), - input.key.page_up => self.cmd("select_page_up", .{}), - input.key.page_down => self.cmd("select_page_down", .{}), - input.key.enter => self.cmd("smart_insert_line_before", .{}), - input.key.backspace => self.cmd("delete_backward", .{}), - input.key.tab => self.cmd("unindent", .{}), - else => if (!input.is_non_input_key(keypress)) - self.insert_code_point(egc) - else {}, - }, - 0 => switch (keypress) { - input.key.f2 => self.cmd("toggle_input_mode", .{}), - input.key.f3 => self.cmd("goto_next_match", .{}), - input.key.f15 => self.cmd("goto_prev_match", .{}), // S-F3 - input.key.f5 => self.cmd("toggle_inspector_view", .{}), // C-F5 - input.key.f6 => self.cmd("dump_current_line_tree", .{}), - input.key.f7 => self.cmd("dump_current_line", .{}), - input.key.f9 => self.cmd("theme_prev", .{}), - input.key.f10 => self.cmd("theme_next", .{}), - input.key.f11 => self.cmd("toggle_panel", .{}), - input.key.f12 => self.cmd("goto_definition", .{}), - input.key.f34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10 - input.key.escape => self.cmd("enter_mode", command.fmt(.{"vim/normal"})), - input.key.enter => self.cmd("smart_insert_line", .{}), - input.key.delete => self.cmd("delete_forward", .{}), - input.key.backspace => self.cmd("delete_backward", .{}), - input.key.left => self.cmd("move_left", .{}), - input.key.right => self.cmd("move_right", .{}), - input.key.up => self.cmd("move_up", .{}), - input.key.down => self.cmd("move_down", .{}), - input.key.home => self.cmd("smart_move_begin", .{}), - input.key.end => self.cmd("move_end", .{}), - input.key.page_up => self.cmd("move_page_up", .{}), - input.key.page_down => self.cmd("move_page_down", .{}), - input.key.tab => self.cmd("indent", .{}), - else => if (!input.is_non_input_key(keypress)) - self.insert_code_point(egc) - else {}, - }, - else => {}, - }; -} - -fn map_follower(self: *Self, keypress: input.Key, _: u32, modifiers: input.Mods) !void { - defer self.leader = null; - const ldr = if (self.leader) |leader| leader else return; - return switch (ldr.modifiers) { - input.mod.ctrl => switch (ldr.keypress) { - 'K' => switch (modifiers) { - input.mod.ctrl => switch (keypress) { - 'U' => self.cmd("delete_to_begin", .{}), - 'K' => self.cmd("delete_to_end", .{}), - 'D' => self.cmd("move_cursor_next_match", .{}), - 'T' => self.cmd("change_theme", .{}), - else => {}, - }, - else => {}, - }, - else => {}, - }, - else => {}, - }; -} - -fn map_release(self: *Self, keypress: input.Key) !void { - return switch (keypress) { - input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}), - else => {}, - }; -} - -fn insert_code_point(self: *Self, c: u32) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - var buf: [6]u8 = undefined; - const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf); - try self.input.appendSlice(buf[0..bytes]); -} - -fn insert_bytes(self: *Self, bytes: []const u8) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - try self.input.appendSlice(bytes); -} - -var insert_chars_id: ?command.ID = null; - -fn flush_input(self: *Self) !void { - if (self.input.items.len > 0) { - defer self.input.clearRetainingCapacity(); - const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse { - return tp.exit_error(error.InputTargetNotFound, null); - }; - try command.execute(id, command.fmt(.{self.input.items})); - self.last_cmd = "insert_chars"; - } -} - -fn cmd(self: *Self, name_: []const u8, ctx: command.Context) tp.result { - try self.flush_input(); - self.last_cmd = name_; - try command.executeName(name_, ctx); -} - -fn cmd_async(self: *Self, name_: []const u8) tp.result { - self.last_cmd = name_; - return tp.self_pid().send(.{ "cmd", name_ }); -} - -pub const hints = keybind.KeybindHints.initComptime(.{}); - -const Commands = command.Collection(cmds_); -const cmds_ = struct { - pub const Target = Self; - const Ctx = command.Context; - const Result = command.Result; - - pub fn w(self: *Self, _: Ctx) Result { - try self.cmd("save_file", .{}); - } - pub const w_meta = .{ .description = "w (write file)" }; - - pub fn q(self: *Self, _: Ctx) Result { - try self.cmd("quit", .{}); - } - pub const q_meta = .{ .description = "q (quit)" }; - - pub fn @"q!"(self: *Self, _: Ctx) Result { - try self.cmd("quit_without_saving", .{}); - } - pub const @"q!_meta" = .{ .description = "q! (quit without saving)" }; - - pub fn wq(self: *Self, _: Ctx) Result { - try self.cmd("save_file", .{}); - try self.cmd("quit", .{}); - } - pub const wq_meta = .{ .description = "wq (write file and quit)" }; - - pub fn @"wq!"(self: *Self, _: Ctx) Result { - self.cmd("save_file", .{}) catch {}; - try self.cmd("quit_without_saving", .{}); - } - pub const @"wq!_meta" = .{ .description = "wq! (write file and quit without saving)" }; -}; diff --git a/src/keybind/static/input/vim/normal.zig b/src/keybind/static/input/vim/normal.zig deleted file mode 100644 index f88b3a8..0000000 --- a/src/keybind/static/input/vim/normal.zig +++ /dev/null @@ -1,630 +0,0 @@ -const std = @import("std"); -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); -const keybind = @import("../../keybind.zig"); - -const Self = @This(); -const input_buffer_size = 1024; - -allocator: std.mem.Allocator, -input: std.ArrayList(u8), -last_cmd: []const u8 = "", -leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null, -count: usize = 0, -commands: Commands = undefined, - -pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler { - const self: *Self = try allocator.create(Self); - self.* = .{ - .allocator = allocator, - .input = try std.ArrayList(u8).initCapacity(allocator, input_buffer_size), - }; - try self.commands.init(self); - return EventHandler.to_owned(self); -} - -pub fn deinit(self: *Self) void { - self.commands.deinit(); - self.input.deinit(); - self.allocator.destroy(self); -} - -pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var egc: input.Key = undefined; - var modifiers: input.Mods = undefined; - var text: []const u8 = undefined; - - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) { - self.mapEvent(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{"F"})) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace()); - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } - return false; -} - -pub fn add_keybind() void {} - -fn mapEvent(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - return switch (event) { - input.event.press => self.mapPress(keypress, egc, modifiers), - input.event.repeat => self.mapPress(keypress, egc, modifiers), - input.event.release => self.mapRelease(keypress, egc, modifiers), - else => {}, - }; -} - -fn mapPress(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - if (self.count > 0 and modifiers == 0 and '0' <= keypress and keypress <= '9') return self.add_count(keypress - '0'); - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers); - switch (keypress) { - input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}), - else => {}, - } - return switch (modifiers) { - input.mod.ctrl => switch (keynormal) { - 'E' => self.cmd("open_recent", .{}), - 'U' => self.cmd("move_scroll_page_up", .{}), - 'D' => self.cmd("move_scroll_page_down", .{}), - 'R' => self.cmd("redo", .{}), - 'O' => self.cmd("jump_back", .{}), - 'I' => self.cmd("jump_forward", .{}), - - 'J' => self.cmd("toggle_panel", .{}), - 'Z' => self.cmd("undo", .{}), - 'Y' => self.cmd("redo", .{}), - 'Q' => self.cmd("quit", .{}), - 'W' => self.cmd("close_file", .{}), - 'S' => self.cmd("save_file", .{}), - 'L' => self.cmd("scroll_view_center_cycle", .{}), - 'N' => self.cmd("goto_next_match", .{}), - 'P' => self.cmd("goto_prev_match", .{}), - 'B' => self.cmd("move_to_char", command.fmt(.{false})), - 'T' => self.cmd("move_to_char", command.fmt(.{true})), - 'X' => self.cmd("cut", .{}), - 'C' => self.cmd("copy", .{}), - 'V' => self.cmd("system_paste", .{}), - 'K' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'F' => self.cmd("find", .{}), - 'G' => self.cmd("goto", .{}), - 'A' => self.cmd("select_all", .{}), - '/' => self.cmd("toggle_comment", .{}), - input.key.enter => self.cmd("smart_insert_line_after", .{}), - input.key.space => self.cmd("selections_reverse", .{}), - input.key.end => self.cmd("move_buffer_end", .{}), - input.key.home => self.cmd("move_buffer_begin", .{}), - input.key.up => self.cmd("move_scroll_up", .{}), - input.key.down => self.cmd("move_scroll_down", .{}), - input.key.page_up => self.cmd("move_scroll_page_up", .{}), - input.key.page_down => self.cmd("move_scroll_page_down", .{}), - input.key.left => self.cmd("move_word_left", .{}), - input.key.right => self.cmd("move_word_right", .{}), - input.key.backspace => self.cmd("delete_word_left", .{}), - input.key.delete => self.cmd("delete_word_right", .{}), - input.key.f5 => self.cmd("toggle_inspector_view", .{}), - input.key.f10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34 - else => {}, - }, - input.mod.ctrl | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - 'D' => self.cmd("dupe_down", .{}), - 'Z' => self.cmd("redo", .{}), - 'Q' => self.cmd("quit_without_saving", .{}), - 'W' => self.cmd("close_file_without_saving", .{}), - 'F' => self.cmd("find_in_files", .{}), - 'L' => self.cmd_async("add_cursor_all_matches"), - 'I' => self.cmd_async("toggle_inspector_view"), - '6' => self.cmd("open_previous_file", .{}), - input.key.enter => self.cmd("smart_insert_line_before", .{}), - input.key.end => self.cmd("select_buffer_end", .{}), - input.key.home => self.cmd("select_buffer_begin", .{}), - input.key.up => self.cmd("select_scroll_up", .{}), - input.key.down => self.cmd("select_scroll_down", .{}), - input.key.left => self.cmd("select_word_left", .{}), - input.key.right => self.cmd("select_word_right", .{}), - else => {}, - }, - input.mod.alt => switch (keynormal) { - 'J' => self.cmd("join_next_line", .{}), - 'N' => self.cmd("goto_next_match", .{}), - 'P' => self.cmd("goto_prev_match", .{}), - 'U' => self.cmd("to_upper", .{}), - 'L' => self.cmd("to_lower", .{}), - 'I' => self.cmd("toggle_inputview", .{}), - 'B' => self.cmd("move_word_left", .{}), - 'F' => self.cmd("move_word_right", .{}), - 'S' => self.cmd("filter", command.fmt(.{"sort"})), - 'V' => self.cmd("paste", .{}), - input.key.left => self.cmd("jump_back", .{}), - input.key.right => self.cmd("jump_forward", .{}), - input.key.up => self.cmd("pull_up", .{}), - input.key.down => self.cmd("pull_down", .{}), - input.key.enter => self.cmd("insert_line", .{}), - input.key.f10 => self.cmd("gutter_mode_next", .{}), // aka F58 - else => {}, - }, - input.mod.alt | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - 'D' => self.cmd("dupe_up", .{}), - 'F' => self.cmd("filter", command.fmt(.{ "zig", "fmt", "--stdin" })), - 'S' => self.cmd("filter", command.fmt(.{ "sort", "-u" })), - 'V' => self.cmd("paste", .{}), - 'I' => self.cmd("add_cursors_to_line_ends", .{}), - input.key.left => self.cmd("move_scroll_left", .{}), - input.key.right => self.cmd("move_scroll_right", .{}), - input.key.up => self.cmd("add_cursor_up", .{}), - input.key.down => self.cmd("add_cursor_down", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - input.key.f3 => self.cmd("goto_prev_match", .{}), - input.key.f10 => self.cmd("toggle_syntax_highlighting", .{}), - input.key.left => self.cmd("select_left", .{}), - input.key.right => self.cmd("select_right", .{}), - input.key.up => self.cmd("select_up", .{}), - input.key.down => self.cmd("select_down", .{}), - input.key.home => self.cmd("smart_select_begin", .{}), - input.key.end => self.cmd("select_end", .{}), - input.key.page_up => self.cmd("select_page_up", .{}), - input.key.page_down => self.cmd("select_page_down", .{}), - input.key.enter => self.cmd("smart_insert_line_before", .{}), - input.key.backspace => self.cmd("delete_backward", .{}), - input.key.tab => self.cmd("unindent", .{}), - - ';' => self.cmd("open_command_palette", .{}), - 'n' => self.cmd("goto_prev_match", .{}), - 'a' => self.seq(.{ "move_end", "enter_mode" }, command.fmt(.{"vim/insert"})), - 'i' => self.seq(.{ "smart_move_begin", "enter_mode" }, command.fmt(.{"vim/insert"})), - '4' => self.cmd("move_end", .{}), - 'g' => if (self.count == 0) - self.cmd("move_buffer_end", .{}) - else { - const count = self.count; - try self.cmd("move_buffer_begin", .{}); - self.count = count - 1; - if (self.count > 0) - try self.cmd_count("move_down", .{}); - }, - - 'o' => self.seq(.{ "smart_insert_line_before", "enter_mode" }, command.fmt(.{"vim/insert"})), - 'k' => self.cmd("hover", .{}), - - '`' => self.cmd("switch_case", .{}), - else => {}, - }, - 0 => switch (keypress) { - input.key.f2 => self.cmd("toggle_input_mode", .{}), - input.key.f3 => self.cmd("goto_next_match", .{}), - input.key.f15 => self.cmd("goto_prev_match", .{}), // S-F3 - input.key.f5 => self.cmd("toggle_inspector_view", .{}), // C-F5 - input.key.f6 => self.cmd("dump_current_line_tree", .{}), - input.key.f7 => self.cmd("dump_current_line", .{}), - input.key.f9 => self.cmd("theme_prev", .{}), - input.key.f10 => self.cmd("theme_next", .{}), - input.key.f11 => self.cmd("toggle_panel", .{}), - input.key.f12 => self.cmd("goto_definition", .{}), - input.key.f34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10 - input.key.escape => self.cmd("cancel", .{}), - input.key.enter => self.cmd("smart_insert_line", .{}), - input.key.delete => self.cmd("delete_forward", .{}), - input.key.backspace => self.cmd("delete_backward", .{}), - - ':' => self.cmd("open_command_palette", .{}), - 'i' => self.cmd("enter_mode", command.fmt(.{"vim/insert"})), - 'a' => self.seq(.{ "move_right", "enter_mode" }, command.fmt(.{"vim/insert"})), - 'v' => self.cmd("enter_mode", command.fmt(.{"vim/visual"})), - - '/' => self.cmd("find", .{}), - 'n' => self.cmd("goto_next_match", .{}), - - 'h' => self.cmd_count("move_left_vim", .{}), - 'j' => self.cmd_count("move_down", .{}), - 'k' => self.cmd_count("move_up", .{}), - 'l' => self.cmd_count("move_right_vim", .{}), - ' ' => self.cmd_count("move_right_vim", .{}), - - 'b' => self.cmd_count("move_word_left", .{}), - 'w' => self.cmd_count("move_word_right_vim", .{}), - 'e' => self.cmd_count("move_word_right", .{}), - - '$' => self.cmd_count("move_end", .{}), - '0' => self.cmd_count("move_begin", .{}), - - '1' => self.add_count(1), - '2' => self.add_count(2), - '3' => self.add_count(3), - '4' => self.add_count(4), - '5' => self.add_count(5), - '6' => self.add_count(6), - '7' => self.add_count(7), - '8' => self.add_count(8), - '9' => self.add_count(9), - - 'x' => self.cmd_count("delete_forward", .{}), - 'u' => self.cmd("undo", .{}), - - 'd' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'r' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'c' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'z' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'g' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'y' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - - 'p' => self.cmd("paste", .{}), - 'o' => self.seq(.{ "smart_insert_line_after", "enter_mode" }, command.fmt(.{"vim/insert"})), - - input.key.left => self.cmd("move_left_vim", .{}), - input.key.right => self.cmd("move_right_vim", .{}), - input.key.up => self.cmd("move_up", .{}), - input.key.down => self.cmd("move_down", .{}), - input.key.home => self.cmd("smart_move_begin", .{}), - input.key.end => self.cmd("move_end", .{}), - input.key.page_up => self.cmd("move_page_up", .{}), - input.key.page_down => self.cmd("move_page_down", .{}), - input.key.tab => self.cmd("indent", .{}), - else => {}, - }, - else => {}, - }; -} - -fn mapFollower(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - if (keypress == input.key.left_control or - keypress == input.key.right_control or - keypress == input.key.left_alt or - keypress == input.key.right_alt or - keypress == input.key.left_shift or - keypress == input.key.right_shift or - keypress == input.key.left_super or - keypress == input.key.right_super) return; - - defer self.leader = null; - const ldr = if (self.leader) |leader| leader else return; - return switch (ldr.modifiers) { - input.mod.ctrl => switch (ldr.keypress) { - 'K' => switch (modifiers) { - input.mod.ctrl => switch (keypress) { - 'U' => self.cmd("delete_to_begin", .{}), - 'K' => self.cmd("delete_to_end", .{}), - 'D' => self.cmd("move_cursor_next_match", .{}), - 'T' => self.cmd("change_theme", .{}), - 'I' => self.cmd("hover", .{}), - else => {}, - }, - else => {}, - }, - else => {}, - }, - 0 => switch (ldr.keypress) { - 'C' => { - try switch (modifiers) { - input.mod.shift => switch (egc) { - '$' => self.cmd("delete_to_end", .{}), - else => {}, - }, - 0 => switch (keypress) { - 'W', 'E' => self.seq_count(.{ "select_word_right", "cut" }, .{}), - else => {}, - }, - else => switch (egc) { - '$' => self.cmd("delete_to_end", .{}), - else => {}, - }, - }; - if (ldr.keypress == 'C') - try self.cmd("enter_mode", command.fmt(.{"vim/insert"})); - }, - 'D' => { - try switch (modifiers) { - input.mod.shift => switch (egc) { - '$' => self.cmd("delete_to_end", .{}), - else => {}, - }, - 0 => switch (keypress) { - 'D' => self.seq_count(.{ "move_begin", "select_end", "select_right", "cut" }, .{}), - 'W' => self.seq_count(.{ "select_word_right", "select_word_right", "select_word_left", "cut" }, .{}), - 'E' => self.seq_count(.{ "select_word_right", "cut" }, .{}), - else => {}, - }, - else => switch (egc) { - '$' => self.cmd("delete_to_end", .{}), - else => {}, - }, - }; - if (ldr.keypress == 'C') - try self.cmd("enter_mode", command.fmt(.{"vim/insert"})); - }, - 'R' => switch (modifiers) { - input.mod.shift, 0 => if (!input.is_non_input_key(keypress)) { - var count = self.count; - try self.cmd_count("delete_forward", .{}); - while (count > 0) : (count -= 1) - try self.insert_code_point(egc); - }, - else => {}, - }, - 'Z' => switch (modifiers) { - 0 => switch (keypress) { - 'Z' => self.cmd("scroll_view_center_cycle", .{}), - else => {}, - }, - else => {}, - }, - 'G' => switch (modifiers) { - 0 => switch (keypress) { - 'G' => self.cmd("move_buffer_begin", .{}), - 'D' => self.cmd("goto_definition", .{}), - 'I' => self.cmd("goto_implementation", .{}), - 'Y' => self.cmd("goto_type_definition", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - 'D' => self.cmd("goto_declaration", .{}), - else => {}, - }, - else => {}, - }, - 'Y' => { - try switch (modifiers) { - input.mod.shift => switch (keypress) { - '4' => self.seq(.{ "select_to_end", "copy" }, .{}), - else => {}, - }, - 0 => switch (keypress) { - 'Y' => self.seq_count(.{ "move_begin", "select_end", "select_right", "copy" }, .{}), - 'W' => self.seq_count(.{ "select_word_right", "select_word_right", "select_word_left", "copy" }, .{}), - 'E' => self.seq_count(.{ "select_word_right", "copy" }, .{}), - else => {}, - }, - else => switch (egc) { - '$' => self.seq(.{ "select_to_end", "copy" }, .{}), - else => {}, - }, - }; - if (ldr.keypress == 'C') - try self.cmd("enter_mode", command.fmt(.{"vim/insert"})); - }, - else => {}, - }, - else => {}, - }; -} - -fn mapRelease(self: *Self, keypress: input.Key, _: u32, _: u32) !void { - return switch (keypress) { - input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}), - else => {}, - }; -} - -fn add_count(self: *Self, value: usize) void { - if (self.count > 0) self.count *= 10; - self.count += value; -} - -fn insert_code_point(self: *Self, c: u32) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - var buf: [6]u8 = undefined; - const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf); - try self.input.appendSlice(buf[0..bytes]); -} - -fn insert_bytes(self: *Self, bytes: []const u8) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - try self.input.appendSlice(bytes); -} - -var insert_chars_id: ?command.ID = null; - -fn flush_input(self: *Self) !void { - if (self.input.items.len > 0) { - defer self.input.clearRetainingCapacity(); - const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse { - return tp.exit_error(error.InputTargetNotFound, null); - }; - try command.execute(id, command.fmt(.{self.input.items})); - self.last_cmd = "insert_chars"; - } -} - -fn cmd(self: *Self, name_: []const u8, ctx: command.Context) tp.result { - self.count = 0; - try self.flush_input(); - self.last_cmd = name_; - try command.executeName(name_, ctx); -} - -fn cmd_count(self: *Self, name_: []const u8, ctx: command.Context) tp.result { - var count = if (self.count == 0) 1 else self.count; - self.count = 0; - try self.flush_input(); - self.last_cmd = name_; - while (count > 0) : (count -= 1) - try command.executeName(name_, ctx); -} - -fn cmd_async(self: *Self, name_: []const u8) tp.result { - self.last_cmd = name_; - return tp.self_pid().send(.{ "cmd", name_ }); -} - -fn seq(self: *Self, cmds: anytype, ctx: command.Context) tp.result { - const cmds_type_info = @typeInfo(@TypeOf(cmds)); - if (cmds_type_info != .Struct) @compileError("expected tuple argument"); - const fields_info = cmds_type_info.Struct.fields; - inline for (fields_info) |field_info| - try self.cmd(@field(cmds, field_info.name), ctx); -} - -fn seq_count(self: *Self, cmds: anytype, ctx: command.Context) tp.result { - var count = if (self.count == 0) 1 else self.count; - self.count = 0; - const cmds_type_info = @typeInfo(@TypeOf(cmds)); - if (cmds_type_info != .Struct) @compileError("expected tuple argument"); - const fields_info = cmds_type_info.Struct.fields; - while (count > 0) : (count -= 1) - inline for (fields_info) |field_info| - try self.cmd(@field(cmds, field_info.name), ctx); -} - -pub const hints = keybind.KeybindHints.initComptime(.{ - .{ "add_cursor_all_matches", "C-S-l" }, - .{ "add_cursor_down", "S-A-down" }, - .{ "add_cursor_next_match", "C-d" }, - .{ "add_cursors_to_line_ends", "S-A-i" }, - .{ "add_cursor_up", "S-A-up" }, - .{ "cancel", "esc" }, - .{ "close_file", "C-w" }, - .{ "close_file_without_saving", "C-S-w" }, - .{ "copy", "C-c" }, - .{ "cut", "C-x" }, - .{ "delete_backward", "backspace" }, - .{ "delete_forward", "del, x" }, - .{ "delete_to_begin", "C-k C-u" }, - .{ "delete_to_end", "C-k C-k, d $" }, - .{ "delete_word_left", "C-backspace" }, - .{ "delete_word_right", "C-del" }, - .{ "dump_current_line", "F7" }, - .{ "dump_current_line_tree", "F6" }, - .{ "dupe_down", "C-S-d" }, - .{ "dupe_up", "S-A-d" }, - .{ "enable_fast_scroll", "hold Ctrl" }, - .{ "enable_jump_mode", "hold Alt" }, - .{ "find_in_files", "C-S-f" }, - .{ "find", "C-f, /" }, - .{ "goto", "C-g" }, - .{ "move_to_char", "C-b, C-t" }, // true/false - .{ "open_file", "C-o" }, - .{ "filter", "A-s" }, // self.cmd("filter", command.fmt(.{"sort"})), - // .{ "filter", "S-A-s" }, // self.cmd("filter", command.fmt(.{ "sort", "-u" })), - .{ "format", "S-A-f" }, - .{ "goto_definition", "F12, g d" }, - .{ "goto_declaration", "g D" }, - .{ "goto_implementation", "g i" }, - .{ "goto_type_definition", "g y" }, - .{ "goto_next_file_or_diagnostic", "A-n" }, - .{ "goto_next_match", "C-n, F3, n" }, - .{ "goto_prev_file_or_diagnostic", "A-p" }, - .{ "goto_prev_match", "C-p, S-F3, N" }, - .{ "gutter_mode_next", "A-F10" }, - .{ "indent", "tab" }, - .{ "insert_line", "A-enter" }, - .{ "join_next_line", "A-j" }, - .{ "jump_back", "A-left" }, - .{ "jump_forward", "A-right" }, - .{ "move_begin", "0" }, - .{ "move_buffer_begin", "C-home, g g" }, - .{ "move_buffer_end", "C-end, G" }, - .{ "move_cursor_next_match", "C-k C-d" }, - .{ "move_down", "down, j" }, - .{ "move_end", "end, $, S-4" }, - .{ "move_left", "left" }, - .{ "move_left_vim", "h" }, - .{ "move_page_down", "pgdn" }, - .{ "move_page_up", "pgup" }, - .{ "move_right", "right" }, - .{ "move_right_vim", "l, space" }, - .{ "move_scroll_down", "C-down" }, - .{ "move_scroll_left", "S-A-left" }, - .{ "move_scroll_page_down", "C-pgdn" }, - .{ "move_scroll_page_up", "C-pgup" }, - .{ "move_scroll_right", "S-A-right" }, - .{ "move_scroll_up", "C-up" }, - .{ "move_up", "up, k" }, - .{ "move_word_left", "C-left, A-b, b" }, - .{ "move_word_right", "C-right, A-f, e" }, - .{ "move_word_right_vim", "w" }, - .{ "open_command_palette", "C-S-p, :, S-;, S-A-p" }, - .{ "open_previous_file", "C-^" }, - .{ "open_recent", "C-e" }, - .{ "paste", "A-v, p" }, - .{ "pop_cursor", "C-u" }, - .{ "pull_down", "A-down" }, - .{ "pull_up", "A-up" }, - .{ "quit", "C-q" }, - .{ "quit_without_saving", "C-S-q" }, - .{ "redo", "C-S-z, C-y" }, - .{ "save_file", "C-s" }, - .{ "scroll_view_center_cycle", "C-l, z z" }, - .{ "select_all", "C-a" }, - .{ "select_buffer_begin", "C-S-home" }, - .{ "select_buffer_end", "C-S-end" }, - .{ "select_down", "S-down" }, - .{ "select_end", "S-end" }, - .{ "selections_reverse", "C-space" }, - .{ "select_left", "S-left" }, - .{ "select_page_down", "S-pgdn" }, - .{ "select_page_up", "S-pgup" }, - .{ "select_right", "S-right" }, - .{ "select_scroll_down", "C-S-down" }, - .{ "select_scroll_up", "C-S-up" }, - .{ "change_theme", "C-k C-t" }, - .{ "select_up", "S-up" }, - .{ "select_word_left", "C-S-left" }, - .{ "select_word_right", "C-S-right" }, - .{ "smart_insert_line_after", "C-enter, o" }, - .{ "smart_insert_line_before", "S-enter, C-S-enter, O" }, - .{ "smart_insert_line", "enter" }, - .{ "smart_move_begin", "home" }, - .{ "smart_select_begin", "S-home" }, - .{ "system_paste", "C-v" }, - .{ "theme_next", "F10" }, - .{ "theme_prev", "F9" }, - .{ "toggle_comment", "C-/" }, - .{ "toggle_input_mode", "F2" }, - .{ "toggle_inputview", "A-i" }, - .{ "toggle_inspector_view", "F5, C-F5, C-S-i" }, - .{ "toggle_panel", "C-j, F11" }, - .{ "toggle_whitespace_mode", "C-F10" }, - .{ "toggle_syntax_highlighting", "S-F10" }, - .{ "to_lower", "A-l" }, - .{ "to_upper", "A-u" }, - .{ "undo", "C-z" }, - .{ "undo", "u" }, - .{ "unindent", "S-tab" }, -}); - -const Commands = command.Collection(cmds_); -const cmds_ = struct { - pub const Target = Self; - const Ctx = command.Context; - const Result = command.Result; - - pub fn w(self: *Self, _: Ctx) Result { - try self.cmd("save_file", .{}); - } - pub const w_meta = .{ .description = "w (write file)" }; - - pub fn q(self: *Self, _: Ctx) Result { - try self.cmd("quit", .{}); - } - pub const q_meta = .{ .description = "q (quit)" }; - - pub fn @"q!"(self: *Self, _: Ctx) Result { - try self.cmd("quit_without_saving", .{}); - } - pub const @"q!_meta" = .{ .description = "q! (quit without saving)" }; - - pub fn wq(self: *Self, _: Ctx) Result { - try self.cmd("save_file", command.fmt(.{ "then", .{ "quit", .{} } })); - } - pub const wq_meta = .{ .description = "wq (write file and quit)" }; - - pub fn @"wq!"(self: *Self, _: Ctx) Result { - self.cmd("save_file", .{}) catch {}; - try self.cmd("quit_without_saving", .{}); - } - pub const @"wq!_meta" = .{ .description = "wq! (write file and quit without saving)" }; -}; diff --git a/src/keybind/static/input/vim/visual.zig b/src/keybind/static/input/vim/visual.zig deleted file mode 100644 index 3d494a6..0000000 --- a/src/keybind/static/input/vim/visual.zig +++ /dev/null @@ -1,579 +0,0 @@ -const std = @import("std"); -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); -const keybind = @import("../../keybind.zig"); - -const Self = @This(); -const input_buffer_size = 1024; - -allocator: std.mem.Allocator, -input: std.ArrayList(u8), -last_cmd: []const u8 = "", -leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null, -count: usize = 0, -commands: Commands = undefined, - -pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler { - const self: *Self = try allocator.create(Self); - self.* = .{ - .allocator = allocator, - .input = try std.ArrayList(u8).initCapacity(allocator, input_buffer_size), - }; - try self.commands.init(self); - return EventHandler.to_owned(self); -} - -pub fn deinit(self: *Self) void { - self.commands.deinit(); - self.input.deinit(); - self.allocator.destroy(self); -} - -pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var egc: input.Key = undefined; - var modifiers: input.Mods = undefined; - var text: []const u8 = undefined; - - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) { - self.map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{"F"})) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) { - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - self.insert_bytes(text) catch |e| return tp.exit_error(e, @errorReturnTrace()); - self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace()); - } - return false; -} - -pub fn add_keybind() void {} - -fn map_event(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - return switch (event) { - input.event.press => self.map_press(keypress, egc, modifiers), - input.event.repeat => self.map_press(keypress, egc, modifiers), - input.event.release => self.map_release(keypress), - else => {}, - }; -} - -fn map_press(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - if (self.count > 0 and modifiers == 0 and '0' <= keypress and keypress <= '9') return self.add_count(keypress - '0'); - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers); - switch (keypress) { - input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}), - else => {}, - } - return switch (modifiers) { - input.mod.ctrl => switch (keynormal) { - 'E' => self.cmd("open_recent", .{}), - 'U' => self.cmd("move_scroll_page_up", .{}), - 'D' => self.cmd("move_scroll_page_down", .{}), - 'R' => self.cmd("redo", .{}), - 'O' => self.cmd("jump_back", .{}), - 'I' => self.cmd("jump_forward", .{}), - - 'J' => self.cmd("toggle_panel", .{}), - 'Z' => self.cmd("undo", .{}), - 'Y' => self.cmd("redo", .{}), - 'Q' => self.cmd("quit", .{}), - 'W' => self.cmd("close_file", .{}), - 'S' => self.cmd("save_file", .{}), - 'L' => self.cmd("scroll_view_center_cycle", .{}), - 'N' => self.cmd("goto_next_match", .{}), - 'P' => self.cmd("goto_prev_match", .{}), - 'B' => self.cmd("move_to_char", command.fmt(.{false})), - 'T' => self.cmd("move_to_char", command.fmt(.{true})), - 'X' => self.cmd("cut", .{}), - 'C' => self.cmd("copy", .{}), - 'V' => self.cmd("system_paste", .{}), - 'K' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'F' => self.cmd("find", .{}), - 'G' => self.cmd("goto", .{}), - 'A' => self.cmd("select_all", .{}), - '/' => self.cmd("toggle_comment", .{}), - input.key.enter => self.cmd("smart_insert_line_after", .{}), - input.key.space => self.cmd("selections_reverse", .{}), - input.key.end => self.cmd("select_buffer_end", .{}), - input.key.home => self.cmd("select_buffer_begin", .{}), - input.key.up => self.cmd("select_scroll_up", .{}), - input.key.down => self.cmd("select_scroll_down", .{}), - input.key.page_up => self.cmd("select_scroll_page_up", .{}), - input.key.page_down => self.cmd("select_scroll_page_down", .{}), - input.key.left => self.cmd("select_word_left", .{}), - input.key.right => self.cmd("select_word_right", .{}), - input.key.backspace => self.cmd("delete_word_left", .{}), - input.key.delete => self.cmd("delete_word_right", .{}), - input.key.f5 => self.cmd("toggle_inspector_view", .{}), - input.key.f10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34 - else => {}, - }, - input.mod.ctrl | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - 'D' => self.cmd("dupe_down", .{}), - 'Z' => self.cmd("redo", .{}), - 'Q' => self.cmd("quit_without_saving", .{}), - 'W' => self.cmd("close_file_without_saving", .{}), - 'F' => self.cmd("find_in_files", .{}), - 'L' => self.cmd_async("add_cursor_all_matches"), - 'I' => self.cmd_async("toggle_inspector_view"), - '6' => self.cmd("open_previous_file", .{}), - input.key.enter => self.cmd("smart_insert_line_before", .{}), - input.key.end => self.cmd("select_buffer_end", .{}), - input.key.home => self.cmd("select_buffer_begin", .{}), - input.key.up => self.cmd("select_scroll_up", .{}), - input.key.down => self.cmd("select_scroll_down", .{}), - input.key.left => self.cmd("select_word_left", .{}), - input.key.right => self.cmd("select_word_right", .{}), - else => {}, - }, - input.mod.alt => switch (keynormal) { - 'J' => self.cmd("join_next_line", .{}), - 'N' => self.cmd("goto_next_match", .{}), - 'P' => self.cmd("goto_prev_match", .{}), - 'U' => self.cmd("to_upper", .{}), - 'L' => self.cmd("to_lower", .{}), - 'I' => self.cmd("toggle_inputview", .{}), - 'B' => self.cmd("select_word_left", .{}), - 'F' => self.cmd("select_word_right", .{}), - 'S' => self.cmd("filter", command.fmt(.{"sort"})), - 'V' => self.cmd("paste", .{}), - input.key.left => self.cmd("jump_back", .{}), - input.key.right => self.cmd("jump_forward", .{}), - input.key.up => self.cmd("pull_up", .{}), - input.key.down => self.cmd("pull_down", .{}), - input.key.enter => self.cmd("insert_line", .{}), - input.key.f10 => self.cmd("gutter_mode_next", .{}), // aka F58 - else => {}, - }, - input.mod.alt | input.mod.shift => switch (keynormal) { - 'P' => self.cmd("open_command_palette", .{}), - 'D' => self.cmd("dupe_up", .{}), - 'F' => self.cmd("filter", command.fmt(.{ "zig", "fmt", "--stdin" })), - 'S' => self.cmd("filter", command.fmt(.{ "sort", "-u" })), - 'V' => self.cmd("paste", .{}), - 'I' => self.cmd("add_cursors_to_line_ends", .{}), - input.key.left => self.cmd("move_scroll_left", .{}), - input.key.right => self.cmd("move_scroll_right", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - input.key.f3 => self.cmd("goto_prev_match", .{}), - input.key.f10 => self.cmd("toggle_syntax_highlighting", .{}), - input.key.left => self.cmd("select_left", .{}), - input.key.right => self.cmd("select_right", .{}), - input.key.up => self.cmd("select_up", .{}), - input.key.down => self.cmd("select_down", .{}), - input.key.home => self.cmd("smart_select_begin", .{}), - input.key.end => self.cmd("select_end", .{}), - input.key.page_up => self.cmd("select_page_up", .{}), - input.key.page_down => self.cmd("select_page_down", .{}), - input.key.enter => self.cmd("smart_insert_line_before", .{}), - input.key.backspace => self.cmd("delete_backward", .{}), - input.key.tab => self.cmd("unindent", .{}), - - ';' => self.cmd("open_command_palette", .{}), - 'n' => self.cmd("goto_prev_match", .{}), - 'a' => self.seq(.{ "move_end", "enter_mode" }, command.fmt(.{"vim/insert"})), - '4' => self.cmd("select_end", .{}), - 'g' => if (self.count == 0) - self.cmd("move_buffer_end", .{}) - else { - const count = self.count; - try self.cmd("move_buffer_begin", .{}); - self.count = count - 1; - if (self.count > 0) - try self.cmd_count("move_down", .{}); - }, - - 'o' => self.seq(.{ "smart_insert_line_before", "enter_mode" }, command.fmt(.{"vim/insert"})), - - '`' => self.cmd("switch_case", .{}), - else => {}, - }, - 0 => switch (keypress) { - input.key.f2 => self.cmd("toggle_input_mode", .{}), - input.key.f3 => self.cmd("goto_next_match", .{}), - input.key.f15 => self.cmd("goto_prev_match", .{}), // S-F3 - input.key.f5 => self.cmd("toggle_inspector_view", .{}), // C-F5 - input.key.f6 => self.cmd("dump_current_line_tree", .{}), - input.key.f7 => self.cmd("dump_current_line", .{}), - input.key.f9 => self.cmd("theme_prev", .{}), - input.key.f10 => self.cmd("theme_next", .{}), - input.key.f11 => self.cmd("toggle_panel", .{}), - input.key.f12 => self.cmd("goto_definition", .{}), - input.key.f34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10 - input.key.escape => self.seq(.{ "cancel", "enter_mode" }, command.fmt(.{"vim/normal"})), - input.key.enter => self.cmd("smart_insert_line", .{}), - input.key.delete => self.cmd("delete_forward", .{}), - input.key.backspace => self.cmd("delete_backward", .{}), - - ':' => self.cmd("open_command_palette", .{}), - 'i' => self.cmd("enter_mode", command.fmt(.{"vim/insert"})), - 'a' => self.seq(.{ "move_right", "enter_mode" }, command.fmt(.{"vim/insert"})), - 'v' => self.cmd("enter_mode", command.fmt(.{"vim/visual"})), - - '/' => self.cmd("find", .{}), - 'n' => self.cmd("goto_next_match", .{}), - - 'h' => self.cmd_count("select_left", .{}), - 'j' => self.cmd_count("select_down", .{}), - 'k' => self.cmd_count("select_up", .{}), - 'l' => self.cmd_count("select_right", .{}), - ' ' => self.cmd_count("select_right", .{}), - - 'b' => self.cmd_count("select_word_left", .{}), - 'w' => self.cmd_count("select_word_right_vim", .{}), - 'e' => self.cmd_count("select_word_right", .{}), - - '$' => self.cmd_count("select_end", .{}), - '0' => self.cmd_count("select_begin", .{}), - - '1' => self.add_count(1), - '2' => self.add_count(2), - '3' => self.add_count(3), - '4' => self.add_count(4), - '5' => self.add_count(5), - '6' => self.add_count(6), - '7' => self.add_count(7), - '8' => self.add_count(8), - '9' => self.add_count(9), - - 'u' => self.cmd("undo", .{}), - - 'd' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'r' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'c' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'z' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - 'g' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers }, - - 'x' => self.cmd("cut", .{}), - 'y' => self.cmd("copy", .{}), - 'p' => self.cmd("paste", .{}), - 'o' => self.seq(.{ "insert_line_after", "enter_mode" }, command.fmt(.{"vim/insert"})), - - input.key.left => self.cmd("select_left", .{}), - input.key.right => self.cmd("select_right", .{}), - input.key.up => self.cmd("select_up", .{}), - input.key.down => self.cmd("select_down", .{}), - input.key.home => self.cmd("smart_select_begin", .{}), - input.key.end => self.cmd("select_end", .{}), - input.key.page_up => self.cmd("select_page_up", .{}), - input.key.page_down => self.cmd("select_page_down", .{}), - input.key.tab => self.cmd("indent", .{}), - else => {}, - }, - else => {}, - }; -} - -fn mapFollower(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - if (keypress == input.key.left_control or - keypress == input.key.right_control or - keypress == input.key.left_alt or - keypress == input.key.right_alt or - keypress == input.key.left_shift or - keypress == input.key.right_shift or - keypress == input.key.left_super or - keypress == input.key.right_super) return; - - defer self.leader = null; - const ldr = if (self.leader) |leader| leader else return; - return switch (ldr.modifiers) { - input.mod.ctrl => switch (ldr.keypress) { - 'K' => switch (modifiers) { - input.mod.ctrl => switch (keypress) { - 'U' => self.cmd("delete_to_begin", .{}), - 'K' => self.cmd("delete_to_end", .{}), - 'D' => self.cmd("move_cursor_next_match", .{}), - 'T' => self.cmd("change_theme", .{}), - 'I' => self.cmd("hover", .{}), - else => {}, - }, - else => {}, - }, - else => {}, - }, - 0 => switch (ldr.keypress) { - 'D', 'C' => { - try switch (modifiers) { - input.mod.shift => switch (keypress) { - '4' => self.cmd("delete_to_end", .{}), - else => {}, - }, - 0 => switch (keypress) { - 'D' => self.seq_count(.{ "move_begin", "select_end", "select_right", "cut" }, .{}), - 'W' => self.seq_count(.{ "select_word_right", "select_word_right", "select_word_left", "cut" }, .{}), - 'E' => self.seq_count(.{ "select_word_right", "cut" }, .{}), - else => {}, - }, - else => switch (egc) { - '$' => self.cmd("delete_to_end", .{}), - else => {}, - }, - }; - if (ldr.keypress == 'C') - try self.cmd("enter_mode", command.fmt(.{"vim/insert"})); - }, - 'R' => switch (modifiers) { - input.mod.shift, 0 => if (!input.is_non_input_key(keypress)) { - var count = self.count; - try self.cmd_count("delete_forward", .{}); - while (count > 0) : (count -= 1) - try self.insert_code_point(egc); - }, - else => {}, - }, - 'Z' => switch (modifiers) { - 0 => switch (keypress) { - 'Z' => self.cmd("scroll_view_center_cycle", .{}), - else => {}, - }, - else => {}, - }, - 'G' => switch (modifiers) { - 0 => switch (keypress) { - 'G' => self.cmd("move_buffer_begin", .{}), - else => {}, - }, - else => {}, - }, - else => {}, - }, - else => {}, - }; -} - -fn map_release(self: *Self, keypress: input.Key) !void { - return switch (keypress) { - input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}), - else => {}, - }; -} - -fn add_count(self: *Self, value: usize) void { - if (self.count > 0) self.count *= 10; - self.count += value; -} - -fn insert_code_point(self: *Self, c: u32) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - var buf: [6]u8 = undefined; - const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf); - try self.input.appendSlice(buf[0..bytes]); -} - -fn insert_bytes(self: *Self, bytes: []const u8) !void { - if (self.input.items.len + 4 > input_buffer_size) - try self.flush_input(); - try self.input.appendSlice(bytes); -} - -var insert_chars_id: ?command.ID = null; - -fn flush_input(self: *Self) !void { - if (self.input.items.len > 0) { - defer self.input.clearRetainingCapacity(); - const id = insert_chars_id orelse command.get_id_cache("insert_chars", &insert_chars_id) orelse { - return tp.exit_error(error.InputTargetNotFound, null); - }; - try command.execute(id, command.fmt(.{self.input.items})); - self.last_cmd = "insert_chars"; - } -} - -fn cmd(self: *Self, name_: []const u8, ctx: command.Context) tp.result { - self.count = 0; - try self.flush_input(); - self.last_cmd = name_; - try command.executeName(name_, ctx); -} - -fn cmd_count(self: *Self, name_: []const u8, ctx: command.Context) tp.result { - var count = if (self.count == 0) 1 else self.count; - self.count = 0; - try self.flush_input(); - self.last_cmd = name_; - while (count > 0) : (count -= 1) - try command.executeName(name_, ctx); -} - -fn cmd_async(self: *Self, name_: []const u8) tp.result { - self.last_cmd = name_; - return tp.self_pid().send(.{ "cmd", name_ }); -} - -fn seq(self: *Self, cmds: anytype, ctx: command.Context) tp.result { - const cmds_type_info = @typeInfo(@TypeOf(cmds)); - if (cmds_type_info != .Struct) @compileError("expected tuple argument"); - const fields_info = cmds_type_info.Struct.fields; - inline for (fields_info) |field_info| - try self.cmd(@field(cmds, field_info.name), ctx); -} - -fn seq_count(self: *Self, cmds: anytype, ctx: command.Context) tp.result { - var count = if (self.count == 0) 1 else self.count; - self.count = 0; - const cmds_type_info = @typeInfo(@TypeOf(cmds)); - if (cmds_type_info != .Struct) @compileError("expected tuple argument"); - const fields_info = cmds_type_info.Struct.fields; - while (count > 0) : (count -= 1) - inline for (fields_info) |field_info| - try self.cmd(@field(cmds, field_info.name), ctx); -} - -pub const hints = keybind.KeybindHints.initComptime(.{ - .{ "add_cursor_all_matches", "C-S-l" }, - .{ "add_cursor_down", "S-A-down" }, - .{ "add_cursor_next_match", "C-d" }, - .{ "add_cursors_to_line_ends", "S-A-i" }, - .{ "add_cursor_up", "S-A-up" }, - .{ "cancel", "esc" }, - .{ "close_file", "C-w" }, - .{ "close_file_without_saving", "C-S-w" }, - .{ "copy", "C-c" }, - .{ "cut", "C-x" }, - .{ "delete_backward", "backspace" }, - .{ "delete_forward", "del, x" }, - .{ "delete_to_begin", "C-k C-u" }, - .{ "delete_to_end", "C-k C-k, d $" }, - .{ "delete_word_left", "C-backspace" }, - .{ "delete_word_right", "C-del" }, - .{ "dump_current_line", "F7" }, - .{ "dump_current_line_tree", "F6" }, - .{ "dupe_down", "C-S-d" }, - .{ "dupe_up", "S-A-d" }, - .{ "enable_fast_scroll", "hold Ctrl" }, - .{ "enable_jump_mode", "hold Alt" }, - .{ "find_in_files", "C-S-f" }, - .{ "find", "C-f, /" }, - .{ "goto", "C-g" }, - .{ "move_to_char", "C-b, C-t" }, // true/false - .{ "open_previous_file", "C-^" }, - .{ "open_file", "C-o" }, - .{ "filter", "A-s" }, // self.cmd("filter", command.fmt(.{"sort"})), - // .{ "filter", "S-A-s" }, // self.cmd("filter", command.fmt(.{ "sort", "-u" })), - .{ "format", "S-A-f" }, - .{ "goto_definition", "F12" }, - .{ "goto_next_file_or_diagnostic", "A-n" }, - .{ "goto_next_match", "C-n, F3, n" }, - .{ "goto_prev_file_or_diagnostic", "A-p" }, - .{ "goto_prev_match", "C-p, S-F3, N" }, - .{ "gutter_mode_next", "A-F10" }, - .{ "indent", "tab" }, - .{ "insert_line", "A-enter" }, - .{ "join_next_line", "A-j" }, - .{ "jump_back", "A-left" }, - .{ "jump_forward", "A-right" }, - .{ "move_begin", "0" }, - .{ "move_buffer_begin", "C-home, g g" }, - .{ "move_buffer_end", "C-end, G" }, - .{ "move_cursor_next_match", "C-k C-d" }, - .{ "move_down", "down, j" }, - .{ "move_end", "end, $, S-4" }, - .{ "move_left", "left" }, - .{ "move_left_vim", "h" }, - .{ "move_page_down", "pgdn" }, - .{ "move_page_up", "pgup" }, - .{ "move_right", "right" }, - .{ "move_right_vim", "l, space" }, - .{ "move_scroll_down", "C-down" }, - .{ "move_scroll_left", "S-A-left" }, - .{ "move_scroll_page_down", "C-pgdn" }, - .{ "move_scroll_page_up", "C-pgup" }, - .{ "move_scroll_right", "S-A-right" }, - .{ "move_scroll_up", "C-up" }, - .{ "move_up", "up, k" }, - .{ "move_word_left", "C-left, A-b, b" }, - .{ "move_word_right", "C-right, A-f, e" }, - .{ "move_word_right_vim", "w" }, - .{ "open_command_palette", "C-S-p, :, S-;, S-A-p" }, - .{ "open_recent", "C-e" }, - .{ "paste", "A-v, p" }, - .{ "pop_cursor", "C-u" }, - .{ "pull_down", "A-down" }, - .{ "pull_up", "A-up" }, - .{ "quit", "C-q" }, - .{ "quit_without_saving", "C-S-q" }, - .{ "redo", "C-S-z, C-y" }, - .{ "save_file", "C-s" }, - .{ "scroll_view_center_cycle", "C-l, z z" }, - .{ "select_all", "C-a" }, - .{ "select_buffer_begin", "C-S-home" }, - .{ "select_buffer_end", "C-S-end" }, - .{ "select_down", "S-down" }, - .{ "select_end", "S-end" }, - .{ "selections_reverse", "C-space" }, - .{ "select_left", "S-left" }, - .{ "select_page_down", "S-pgdn" }, - .{ "select_page_up", "S-pgup" }, - .{ "select_right", "S-right" }, - .{ "select_scroll_down", "C-S-down" }, - .{ "select_scroll_up", "C-S-up" }, - .{ "change_theme", "C-k C-t" }, - .{ "select_up", "S-up" }, - .{ "select_word_left", "C-S-left" }, - .{ "select_word_right", "C-S-right" }, - .{ "smart_insert_line_after", "C-enter, o" }, - .{ "smart_insert_line_before", "S-enter, C-S-enter, O" }, - .{ "smart_insert_line", "enter" }, - .{ "smart_move_begin", "home" }, - .{ "smart_select_begin", "S-home" }, - .{ "system_paste", "C-v" }, - .{ "theme_next", "F10" }, - .{ "theme_prev", "F9" }, - .{ "toggle_comment", "C-/" }, - .{ "toggle_input_mode", "F2" }, - .{ "toggle_inputview", "A-i" }, - .{ "toggle_inspector_view", "F5, C-F5, C-S-i" }, - .{ "toggle_panel", "C-j, F11" }, - .{ "toggle_whitespace_mode", "C-F10" }, - .{ "toggle_syntax_highlighting", "S-F10" }, - .{ "to_lower", "A-l" }, - .{ "to_upper", "A-u" }, - .{ "undo", "C-z" }, - .{ "undo", "u" }, - .{ "unindent", "S-tab" }, -}); - -const Commands = command.Collection(cmds_); -const cmds_ = struct { - pub const Target = Self; - const Ctx = command.Context; - const Result = command.Result; - - pub fn w(self: *Self, _: Ctx) Result { - try self.cmd("save_file", .{}); - } - pub const w_meta = .{ .description = "w (write file)" }; - - pub fn q(self: *Self, _: Ctx) Result { - try self.cmd("quit", .{}); - } - pub const q_meta = .{ .description = "q (quit)" }; - - pub fn @"q!"(self: *Self, _: Ctx) Result { - try self.cmd("quit_without_saving", .{}); - } - pub const @"q!_meta" = .{ .description = "q! (quit without saving)" }; - - pub fn wq(self: *Self, _: Ctx) Result { - try self.cmd("save_file", .{}); - try self.cmd("quit", .{}); - } - pub const wq_meta = .{ .description = "wq (write file and quit)" }; - - pub fn @"wq!"(self: *Self, _: Ctx) Result { - self.cmd("save_file", .{}) catch {}; - try self.cmd("quit_without_saving", .{}); - } - pub const @"wq!_meta" = .{ .description = "wq! (write file and quit without saving)" }; -}; diff --git a/src/keybind/static/keybind.zig b/src/keybind/static/keybind.zig deleted file mode 100644 index d828521..0000000 --- a/src/keybind/static/keybind.zig +++ /dev/null @@ -1,56 +0,0 @@ -pub const mode = struct { - pub const input = struct { - pub const flow = @import("input/flow.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 helix = struct { - pub const normal = @import("input/helix/normal.zig"); - pub const insert = @import("input/helix/insert.zig"); - pub const visual = @import("input/helix/select.zig"); - }; - }; - pub const overlay = struct { - pub const palette = @import("overlay/palette.zig"); - }; - pub const mini = struct { - pub const goto = @import("mini/goto.zig"); - pub const move_to_char = @import("mini/move_to_char.zig"); - pub const file_browser = @import("mini/file_browser.zig"); - pub const find_in_files = @import("mini/find_in_files.zig"); - pub const find = @import("mini/find.zig"); - }; -}; - -pub const Mode = struct { - input_handler: EventHandler, - event_handler: ?EventHandler = null, - - name: []const u8 = "", - line_numbers: enum { absolute, relative } = .absolute, - keybind_hints: ?*const KeybindHints = null, - cursor_shape: CursorShape = .block, - - pub fn deinit(self: *Mode) void { - self.input_handler.deinit(); - if (self.event_handler) |eh| eh.deinit(); - } -}; - -pub const KeybindHints = std.static_string_map.StaticStringMap([]const u8); - -pub const CursorShape = enum { - default, - block_blink, - block, - underline_blink, - underline, - beam_blink, - beam, -}; - -const EventHandler = @import("EventHandler"); -const std = @import("std"); diff --git a/src/keybind/static/mini/file_browser.zig b/src/keybind/static/mini/file_browser.zig deleted file mode 100644 index f86525c..0000000 --- a/src/keybind/static/mini/file_browser.zig +++ /dev/null @@ -1,74 +0,0 @@ -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); - -pub fn create(_: @import("std").mem.Allocator, _: anytype) !EventHandler { - return EventHandler.static(@This()); -} - -pub fn receive(_: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var egc: input.Key = undefined; - var modifiers: input.Mods = undefined; - - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) { - map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace()); - } - return false; -} - -fn map_event(event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - switch (event) { - input.event.press => try map_press(keypress, egc, modifiers), - input.event.repeat => try map_press(keypress, egc, modifiers), - else => {}, - } -} - -fn map_press(keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - return switch (modifiers) { - input.mod.ctrl => switch (keynormal) { - 'Q' => command.executeName("quit", .{}), - 'V' => command.executeName("system_paste", .{}), - 'U' => command.executeName("mini_mode_reset", .{}), - 'G' => command.executeName("mini_mode_cancel", .{}), - 'C' => command.executeName("mini_mode_cancel", .{}), - 'L' => command.executeName("scroll_view_center_cycle", .{}), - 'I' => command.executeName("mini_mode_insert_bytes", command.fmt(.{"\t"})), - input.key.space => command.executeName("mini_mode_cancel", .{}), - input.key.backspace => command.executeName("mini_mode_delete_to_previous_path_segment", .{}), - else => {}, - }, - input.mod.alt => switch (keynormal) { - 'V' => command.executeName("system_paste", .{}), - else => {}, - }, - input.mod.alt | input.mod.shift => switch (keynormal) { - 'V' => command.executeName("system_paste", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - input.key.tab => command.executeName("mini_mode_reverse_complete_file", .{}), - else => if (!input.is_non_input_key(keypress)) - command.executeName("mini_mode_insert_code_point", command.fmt(.{egc})) - else {}, - }, - 0 => switch (keypress) { - input.key.up => command.executeName("mini_mode_reverse_complete_file", .{}), - input.key.down => command.executeName("mini_mode_try_complete_file", .{}), - input.key.right => command.executeName("mini_mode_try_complete_file_forward", .{}), - input.key.left => command.executeName("mini_mode_delete_to_previous_path_segment", .{}), - input.key.tab => command.executeName("mini_mode_try_complete_file", .{}), - input.key.escape => command.executeName("mini_mode_cancel", .{}), - input.key.enter => command.executeName("mini_mode_select", .{}), - input.key.backspace => command.executeName("mini_mode_delete_backwards", .{}), - else => if (!input.is_non_input_key(keypress)) - command.executeName("mini_mode_insert_code_point", command.fmt(.{egc})) - else {}, - }, - else => {}, - }; -} diff --git a/src/keybind/static/mini/find.zig b/src/keybind/static/mini/find.zig deleted file mode 100644 index 9db7a09..0000000 --- a/src/keybind/static/mini/find.zig +++ /dev/null @@ -1,84 +0,0 @@ -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); - -pub fn create(_: @import("std").mem.Allocator, _: anytype) !EventHandler { - return EventHandler.static(@This()); -} - -pub fn receive(_: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var egc: input.Key = undefined; - var modifiers: input.Mods = undefined; - - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) { - map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace()); - } - return false; -} - -fn map_event(event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - switch (event) { - input.event.press => try map_press(keypress, egc, modifiers), - input.event.repeat => try map_press(keypress, egc, modifiers), - else => {}, - } -} - -fn map_press(keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - return switch (modifiers) { - input.mod.ctrl => switch (keynormal) { - 'Q' => command.executeName("quit", .{}), - 'V' => command.executeName("system_paste", .{}), - 'U' => command.executeName("mini_mode_reset", .{}), - 'G' => command.executeName("mini_mode_cancel", .{}), - 'C' => command.executeName("mini_mode_cancel", .{}), - 'L' => command.executeName("scroll_view_center_cycle", .{}), - 'F' => command.executeName("goto_next_match", .{}), - 'N' => command.executeName("goto_next_match", .{}), - 'P' => command.executeName("goto_prev_match", .{}), - 'I' => command.executeName("mini_mode_insert_bytes", command.fmt(.{"\t"})), - input.key.space => command.executeName("mini_mode_cancel", .{}), - input.key.enter => command.executeName("mini_mode_insert_bytes", command.fmt(.{"\n"})), - input.key.backspace => command.executeName("mini_mode_reset", .{}), - else => {}, - }, - input.mod.alt => switch (keynormal) { - 'V' => command.executeName("system_paste", .{}), - 'N' => command.executeName("goto_next_match", .{}), - 'P' => command.executeName("goto_prev_match", .{}), - else => {}, - }, - input.mod.alt | input.mod.shift => switch (keynormal) { - 'V' => command.executeName("system_paste", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - input.key.enter => command.executeName("goto_prev_match", .{}), - input.key.f3 => command.executeName("goto_prev_match", .{}), - else => if (!input.is_non_input_key(keypress)) - command.executeName("mini_mode_insert_code_point", command.fmt(.{egc})) - else {}, - }, - 0 => switch (keypress) { - input.key.up => command.executeName("mini_mode_history_prev", .{}), - input.key.down => command.executeName("mini_mode_history_next", .{}), - input.key.f3 => command.executeName("goto_next_match", .{}), - input.key.f15 => command.executeName("goto_prev_match", .{}), - input.key.f9 => command.executeName("theme_prev", .{}), - input.key.f10 => command.executeName("theme_next", .{}), - input.key.escape => command.executeName("mini_mode_cancel", .{}), - input.key.enter => command.executeName("mini_mode_select", .{}), - input.key.backspace => command.executeName("mini_mode_delete_backwards", .{}), - input.key.left_control, input.key.right_control => command.executeName("enable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => command.executeName("enable_fast_scroll", .{}), - else => if (!input.is_non_input_key(keypress)) - command.executeName("mini_mode_insert_code_point", command.fmt(.{egc})) - else {}, - }, - else => {}, - }; -} diff --git a/src/keybind/static/mini/find_in_files.zig b/src/keybind/static/mini/find_in_files.zig deleted file mode 100644 index b3ac04f..0000000 --- a/src/keybind/static/mini/find_in_files.zig +++ /dev/null @@ -1,93 +0,0 @@ -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); - -pub fn create(_: @import("std").mem.Allocator, _: anytype) !EventHandler { - return EventHandler.static(@This()); -} - -pub fn receive(_: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var egc: input.Key = undefined; - var modifiers: input.Mods = undefined; - - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) { - map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace()); - } - return false; -} - -fn map_event(event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - switch (event) { - input.event.press => try map_press(keypress, egc, modifiers), - input.event.repeat => try map_press(keypress, egc, modifiers), - input.event.release => try map_release(keypress, egc, modifiers), - else => {}, - } -} - -fn map_press(keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - return switch (modifiers) { - input.mod.ctrl => switch (keynormal) { - 'Q' => command.executeName("quit", .{}), - 'V' => command.executeName("system_paste", .{}), - 'U' => command.executeName("mini_mode_reset", .{}), - 'G' => command.executeName("exit_mini_mode", .{}), - 'C' => command.executeName("exit_mini_mode", .{}), - 'L' => command.executeName("scroll_view_center_cycle", .{}), - 'F' => command.executeName("goto_next_match", .{}), - 'N' => command.executeName("goto_next_match", .{}), - 'P' => command.executeName("goto_prev_match", .{}), - 'I' => command.executeName("mini_mode_insert_bytes", command.fmt(.{"\t"})), - input.key.space => command.executeName("exit_mini_mode", .{}), - input.key.enter => command.executeName("mini_mode_insert_bytes", command.fmt(.{"\n"})), - input.key.backspace => command.executeName("mini_mode_reset", .{}), - else => {}, - }, - input.mod.alt => switch (keynormal) { - 'V' => command.executeName("system_paste", .{}), - 'N' => command.executeName("goto_next_file", .{}), - 'P' => command.executeName("goto_prev_file", .{}), - else => {}, - }, - input.mod.alt | input.mod.shift => switch (keynormal) { - 'V' => command.executeName("system_paste", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - input.key.enter => command.executeName("goto_prev_match", .{}), - input.key.f3 => command.executeName("goto_prev_match", .{}), - else => if (!input.is_non_input_key(keypress)) - command.executeName("mini_mode_insert_code_point", command.fmt(.{egc})) - else {}, - }, - 0 => switch (keypress) { - input.key.up => command.executeName("select_prev_file", .{}), - input.key.down => command.executeName("select_next_file", .{}), - input.key.f3 => command.executeName("goto_next_match", .{}), - input.key.f15 => command.executeName("goto_prev_match", .{}), - input.key.f9 => command.executeName("theme_prev", .{}), - input.key.f10 => command.executeName("theme_next", .{}), - input.key.escape => command.executeName("exit_mini_mode", .{}), - input.key.enter => command.executeName("mini_mode_select", .{}), - input.key.backspace => command.executeName("mini_mode_delete_backwards", .{}), - input.key.left_control, input.key.right_control => command.executeName("enable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => command.executeName("enable_fast_scroll", .{}), - else => if (!input.is_non_input_key(keypress)) - command.executeName("mini_mode_insert_code_point", command.fmt(.{egc})) - else {}, - }, - else => {}, - }; -} - -fn map_release(keypress: input.Key, _: input.Key, _: input.Mods) !void { - return switch (keypress) { - input.key.left_control, input.key.right_control => command.executeName("disable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => command.executeName("disable_fast_scroll", .{}), - else => {}, - }; -} diff --git a/src/keybind/static/mini/goto.zig b/src/keybind/static/mini/goto.zig deleted file mode 100644 index 26f4a1f..0000000 --- a/src/keybind/static/mini/goto.zig +++ /dev/null @@ -1,59 +0,0 @@ -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); - -pub fn create(_: @import("std").mem.Allocator, _: anytype) !EventHandler { - return EventHandler.static(@This()); -} - -pub fn receive(_: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var modifiers: input.Mods = undefined; - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.any, tp.string, tp.extract(&modifiers) })) - try map_event(event, keypress, modifiers); - return false; -} - -fn map_event(event: input.Event, keypress: input.Key, modifiers: input.Mods) tp.result { - switch (event) { - input.event.press => try map_press(keypress, modifiers), - input.event.repeat => try map_press(keypress, modifiers), - input.event.release => try map_release(keypress), - else => {}, - } -} - -fn map_press(keypress: input.Key, modifiers: input.Mods) tp.result { - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - return switch (modifiers) { - input.mod.ctrl => switch (keynormal) { - 'Q' => command.executeName("quit", .{}), - 'U' => command.executeName("mini_mode_reset", .{}), - 'G' => command.executeName("mini_mode_cancel", .{}), - 'C' => command.executeName("mini_mode_cancel", .{}), - 'L' => command.executeName("scroll_view_center_cycle", .{}), - input.key.space => command.executeName("mini_mode_cancel", .{}), - else => {}, - }, - 0 => switch (keypress) { - input.key.left_control, input.key.right_control => command.executeName("enable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => command.executeName("enable_fast_scroll", .{}), - input.key.escape => command.executeName("mini_mode_cancel", .{}), - input.key.enter => command.executeName("exit_mini_mode", .{}), - input.key.backspace => command.executeName("mini_mode_delete_backwards", .{}), - '0'...'9' => command.executeName("mini_mode_insert_code_point", command.fmt(.{keypress})), - else => {}, - }, - else => {}, - }; -} - -fn map_release(keypress: input.Key) tp.result { - return switch (keypress) { - input.key.left_control, input.key.right_control => command.executeName("disable_fast_scroll", .{}), - input.key.left_alt, input.key.right_alt => command.executeName("disable_fast_scroll", .{}), - else => {}, - }; -} diff --git a/src/keybind/static/mini/move_to_char.zig b/src/keybind/static/mini/move_to_char.zig deleted file mode 100644 index 443c871..0000000 --- a/src/keybind/static/mini/move_to_char.zig +++ /dev/null @@ -1,50 +0,0 @@ -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); - -pub fn create(_: @import("std").mem.Allocator, _: anytype) !EventHandler { - return EventHandler.static(@This()); -} - -pub fn receive(_: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var egc: input.Key = undefined; - var modifiers: input.Mods = undefined; - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) - try map_event(event, keypress, egc, modifiers); - return false; -} - -fn map_event(event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) tp.result { - switch (event) { - input.event.press => try map_press(keypress, egc, modifiers), - else => {}, - } -} - -fn map_press(keypress: input.Key, egc: input.Key, modifiers: input.Mods) tp.result { - switch (keypress) { - input.key.left_super, input.key.right_super => return, - input.key.left_shift, input.key.right_shift => return, - input.key.left_control, input.key.right_control => return, - input.key.left_alt, input.key.right_alt => return, - else => {}, - } - return switch (modifiers) { - input.mod.shift => if (!input.is_non_input_key(keypress)) - command.executeName("mini_mode_insert_code_point", command.fmt(.{egc})) - else - command.executeName("mini_mode_cancel", .{}), - 0 => switch (keypress) { - input.key.escape => command.executeName("mini_mode_cancel", .{}), - input.key.enter => command.executeName("mini_mode_cancel", .{}), - else => if (!input.is_non_input_key(keypress)) - command.executeName("mini_mode_insert_code_point", command.fmt(.{egc})) - else - command.executeName("mini_mode_cancel", .{}), - }, - else => command.executeName("mini_mode_cancel", .{}), - }; -} diff --git a/src/keybind/static/overlay/palette.zig b/src/keybind/static/overlay/palette.zig deleted file mode 100644 index 8a6ef69..0000000 --- a/src/keybind/static/overlay/palette.zig +++ /dev/null @@ -1,105 +0,0 @@ -const tp = @import("thespian"); -const input = @import("input"); -const command = @import("command"); -const EventHandler = @import("EventHandler"); - -pub fn create(_: @import("std").mem.Allocator, _: anytype) !EventHandler { - return EventHandler.static(@This()); -} - -pub fn receive(_: tp.pid_ref, m: tp.message) error{Exit}!bool { - var event: input.Event = undefined; - var keypress: input.Key = undefined; - var egc: input.Key = undefined; - var modifiers: input.Mods = undefined; - - if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) { - map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace()); - } - return false; -} - -fn map_event(event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - return switch (event) { - input.event.press => map_press(keypress, egc, modifiers), - input.event.repeat => map_press(keypress, egc, modifiers), - input.event.release => map_release(keypress), - else => {}, - }; -} - -fn map_press(keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void { - const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress; - return switch (modifiers) { - input.mod.ctrl => switch (keynormal) { - 'J' => command.executeName("toggle_panel", .{}), - 'Q' => command.executeName("quit", .{}), - 'W' => command.executeName("close_file", .{}), - 'P' => command.executeName("palette_menu_up", .{}), - 'N' => command.executeName("palette_menu_down", .{}), - 'E' => command.executeName("palette_menu_down", .{}), // open recent repeat key - 'R' => command.executeName("palette_menu_down", .{}), // open recent project repeat key - 'T' => command.executeName("palette_menu_down", .{}), // select theme repeat key - 'V' => command.executeName("system_paste", .{}), - 'C' => command.executeName("palette_menu_cancel", .{}), - 'G' => command.executeName("palette_menu_cancel", .{}), - input.key.escape => command.executeName("palette_menu_cancel", .{}), - input.key.up => command.executeName("palette_menu_up", .{}), - input.key.down => command.executeName("palette_menu_down", .{}), - input.key.page_up => command.executeName("palette_menu_pageup", .{}), - input.key.page_down => command.executeName("palette_menu_pagedown", .{}), - input.key.enter => command.executeName("palette_menu_activate", .{}), - input.key.backspace => command.executeName("overlay_delete_word_left", .{}), - else => {}, - }, - input.mod.ctrl | input.mod.shift => switch (keynormal) { - 'E' => command.executeName("palette_menu_up", .{}), // open recent repeat key - 'R' => command.executeName("palette_menu_up", .{}), // open recent project repeat key - 'P' => command.executeName("palette_menu_down", .{}), // command palette repeat key - 'Q' => command.executeName("quit_without_saving", .{}), - 'W' => command.executeName("close_file_without_saving", .{}), - 'L' => command.executeName("overlay_toggle_panel", .{}), - 'I' => command.executeName("overlay_toggle_inputview", .{}), - else => {}, - }, - input.mod.alt | input.mod.shift => switch (keynormal) { - 'P' => command.executeName("palette_menu_down", .{}), - else => {}, - }, - input.mod.alt => switch (keynormal) { - 'P' => command.executeName("palette_menu_up", .{}), - 'L' => command.executeName("toggle_panel", .{}), - 'I' => command.executeName("toggle_inputview", .{}), - else => {}, - }, - input.mod.shift => switch (keypress) { - else => if (!input.is_non_input_key(keypress)) - command.executeName("overlay_insert_code_point", command.fmt(.{egc})) - else {}, - }, - 0 => switch (keypress) { - input.key.f9 => command.executeName("theme_prev", .{}), - input.key.f10 => command.executeName("theme_next", .{}), - input.key.f11 => command.executeName("toggle_panel", .{}), - input.key.f12 => command.executeName("toggle_inputview", .{}), - input.key.escape => command.executeName("palette_menu_cancel", .{}), - input.key.up => command.executeName("palette_menu_up", .{}), - input.key.down => command.executeName("palette_menu_down", .{}), - input.key.page_up => command.executeName("palette_menu_pageup", .{}), - input.key.page_down => command.executeName("palette_menu_pagedown", .{}), - input.key.enter => command.executeName("palette_menu_activate", .{}), - input.key.backspace => command.executeName("overlay_delete_backwards", .{}), - else => if (!input.is_non_input_key(keypress)) - command.executeName("overlay_insert_code_point", command.fmt(.{egc})) - else {}, - }, - else => {}, - }; -} - -fn map_release(keypress: input.Key) !void { - return switch (keypress) { - input.key.left_control, input.key.right_control => command.executeName("overlay_release_control", .{}), - else => {}, - }; -}