feat: add keybind hints to command palette

This commit is contained in:
CJ van den Berg 2024-06-20 22:26:09 +02:00
parent 3ea039f41c
commit d4019d00b2
10 changed files with 422 additions and 139 deletions

View file

@ -111,7 +111,7 @@ fn menu_action_open_file(_: **Menu.State(*Self), _: *Button.State(*Menu.State(*S
}
fn menu_action_open_recent_file(_: **Menu.State(*Self), _: *Button.State(*Menu.State(*Self))) void {
command.executeName("enter_overlay_mode", command.fmt(.{"open_recent"})) catch {};
command.executeName("open_recent", .{}) catch {};
}
fn menu_action_open_recent_project(_: **Menu.State(*Self), _: *Button.State(*Menu.State(*Self))) void {
@ -119,7 +119,7 @@ fn menu_action_open_recent_project(_: **Menu.State(*Self), _: *Button.State(*Men
}
fn menu_action_show_commands(_: **Menu.State(*Self), _: *Button.State(*Menu.State(*Self))) void {
command.executeName("enter_overlay_mode", command.fmt(.{"command_palette"})) catch {};
command.executeName("open_command_palette", .{}) catch {};
}
fn menu_action_open_config(_: **Menu.State(*Self), _: *Button.State(*Menu.State(*Self))) void {

View file

@ -33,6 +33,7 @@ pub fn create(a: Allocator) !tui.Mode {
.handler = EventHandler.to_owned(self),
.name = root.application_logo ++ root.application_name,
.description = "default",
.keybind_hints = &hints,
};
}
@ -79,7 +80,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
}
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
'E' => self.cmd("enter_overlay_mode", command.fmt(.{"open_recent"})),
'E' => self.cmd("open_recent", .{}),
'J' => self.cmd("toggle_logview", .{}),
'Z' => self.cmd("undo", .{}),
'Y' => self.cmd("redo", .{}),
@ -120,7 +121,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
'P' => self.cmd("enter_overlay_mode", command.fmt(.{"command_palette"})),
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_down", .{}),
'Z' => self.cmd("redo", .{}),
'Q' => self.cmd("quit_without_saving", .{}),
@ -129,7 +130,6 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
'F' => self.cmd("enter_find_in_files_mode", .{}),
'L' => self.cmd_async("add_cursor_all_matches"),
'I' => self.cmd_async("toggle_inspector_view"),
'/' => self.cmd("log_widgets", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.END => self.cmd("select_buffer_end", .{}),
key.HOME => self.cmd("select_buffer_begin", .{}),
@ -302,3 +302,112 @@ fn cmd_async(self: *Self, name_: []const u8) tp.result {
self.last_cmd = name_;
return tp.self_pid().send(.{ "cmd", name_ });
}
const hints = tui.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" },
.{ "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" },
.{ "enter_find_in_files_mode", "C-S-f" },
.{ "enter_find_mode", "C-f" },
.{ "enter_goto_mode", "C-g" },
.{ "enter_move_to_char_mode", "C-b, C-t" }, // true/false
.{ "enter_open_file_mode", "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_diagnostic", "A-n" },
.{ "goto_next_match", "C-n, F3" },
.{ "goto_prev_diagnostic", "A-p" },
.{ "goto_prev_match", "C-p, S-F3" },
.{ "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-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" },
.{ "move_word_left", "C-left, A-b" },
.{ "move_word_right", "C-right, A-f" },
.{ "open_command_palette", "C-S-p" },
.{ "open_recent", "C-e" },
.{ "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" },
.{ "restart", "C-S-r" },
.{ "save_file", "C-s" },
.{ "scroll_view_bottom", "C-l" },
.{ "scroll_view_center", "C-l" },
.{ "scroll_view_top", "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-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" },
.{ "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_logview", "C-j, F11" },
.{ "toggle_whitespace", "C-F10" },
.{ "to_lower", "A-l" },
.{ "to_upper", "A-u" },
.{ "undo", "C-z" },
.{ "unindent", "S-tab" },
});

View file

@ -24,6 +24,7 @@ pub fn create(a: std.mem.Allocator) !tui.Mode {
.handler = EventHandler.to_owned(self),
.name = root.application_logo ++ root.application_name,
.description = "home",
.keybind_hints = &hints,
};
}
@ -59,13 +60,13 @@ fn mapPress(self: *Self, keypress: u32, modifiers: u32) tp.result {
'Q' => self.cmd("quit", .{}),
'W' => self.cmd("quit", .{}),
'O' => self.cmd("enter_open_file_mode", .{}),
'E' => self.cmd("enter_overlay_mode", command.fmt(.{"open_recent"})),
'P' => self.cmd("enter_overlay_mode", command.fmt(.{"command_palette"})),
'E' => self.cmd("open_recent", .{}),
'P' => self.cmd("open_command_palette", .{}),
'/' => self.cmd("open_help", .{}),
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
'P' => self.cmd("enter_overlay_mode", command.fmt(.{"command_palette"})),
'P' => self.cmd("open_command_palette", .{}),
'Q' => self.cmd("quit_without_saving", .{}),
'R' => self.cmd("restart", .{}),
'F' => self.cmd("enter_find_in_files_mode", .{}),
@ -84,9 +85,9 @@ fn mapPress(self: *Self, keypress: u32, modifiers: u32) tp.result {
0 => switch (keypress) {
'h' => self.cmd("open_help", .{}),
'o' => self.cmd("enter_open_file_mode", .{}),
'e' => self.cmd("enter_overlay_mode", command.fmt(.{"open_recent"})),
'e' => self.cmd("open_recent", .{}),
'r' => self.msg("open recent project not implemented"),
'p' => self.cmd("enter_overlay_mode", command.fmt(.{"command_palette"})),
'p' => self.cmd("open_command_palette", .{}),
'c' => self.cmd("open_config", .{}),
'q' => self.cmd("quit", .{}),
@ -124,3 +125,25 @@ fn sheeran(self: *Self) void {
self.cmd("home_sheeran", .{}) catch {};
}
}
const hints = tui.KeybindHints.initComptime(.{
.{ "enter_find_in_files_mode", "C-S-f" },
.{ "enter_open_file_mode", "o, C-o" },
.{ "open_recent", "e, C-e" },
.{ "open_command_palette", "p, C-S-p" },
.{ "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", "C-/, C-S-/" },
.{ "open_help", "h, F1" },
.{ "quit", "q, C-q, C-w" },
.{ "quit_without_saving", "C-S-q" },
.{ "restart", "C-S-r" },
.{ "theme_next", "F10" },
.{ "theme_prev", "F9" },
.{ "toggle_inputview", "F12, A-i, C-S-i" },
.{ "toggle_logview", "F11, C-j, A-l, C-S-l" },
});

View file

@ -82,7 +82,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
}
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
'E' => self.cmd("enter_overlay_mode", command.fmt(.{"open_recent"})),
'E' => self.cmd("open_recent", .{}),
'U' => self.cmd("move_scroll_page_up", .{}),
'D' => self.cmd("move_scroll_page_down", .{}),
'J' => self.cmd("toggle_logview", .{}),
@ -123,7 +123,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
'P' => self.cmd("enter_overlay_mode", command.fmt(.{"command_palette"})),
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_down", .{}),
'Z' => self.cmd("redo", .{}),
'Q' => self.cmd("quit_without_saving", .{}),
@ -132,7 +132,6 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
'F' => self.cmd("enter_find_in_files_mode", .{}),
'L' => self.cmd_async("add_cursor_all_matches"),
'I' => self.cmd_async("toggle_inspector_view"),
'/' => self.cmd("log_widgets", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.END => self.cmd("select_buffer_end", .{}),
key.HOME => self.cmd("select_buffer_begin", .{}),

View file

@ -35,6 +35,7 @@ pub fn create(a: Allocator) !tui.Mode {
.name = root.application_logo ++ "NORMAL",
.description = "vim",
.line_numbers = if (tui.current().config.vim_normal_gutter_line_numbers_relative) .relative else .absolute,
.keybind_hints = &hints,
};
}
@ -74,6 +75,7 @@ fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) t
}
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
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) {
@ -83,7 +85,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
}
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
'E' => self.cmd("enter_overlay_mode", command.fmt(.{"open_recent"})),
'E' => self.cmd("open_recent", .{}),
'U' => self.cmd("move_scroll_page_up", .{}),
'D' => self.cmd("move_scroll_page_down", .{}),
'R' => self.cmd("redo", .{}),
@ -126,7 +128,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
'P' => self.cmd("enter_overlay_mode", command.fmt(.{"command_palette"})),
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_down", .{}),
'Z' => self.cmd("redo", .{}),
'Q' => self.cmd("quit_without_saving", .{}),
@ -135,7 +137,6 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
'F' => self.cmd("enter_find_in_files_mode", .{}),
'L' => self.cmd_async("add_cursor_all_matches"),
'I' => self.cmd_async("toggle_inspector_view"),
'/' => self.cmd("log_widgets", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.END => self.cmd("select_buffer_end", .{}),
key.HOME => self.cmd("select_buffer_begin", .{}),
@ -166,8 +167,6 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
},
mod.ALT | mod.SHIFT => switch (keynormal) {
'D' => self.cmd("dupe_up", .{}),
// 'B' => self.cmd("select_word_left", .{}),
// 'F' => self.cmd("select_word_right", .{}),
'F' => self.cmd("filter", command.fmt(.{ "zig", "fmt", "--stdin" })),
'S' => self.cmd("filter", command.fmt(.{ "sort", "-u" })),
'V' => self.cmd("paste", .{}),
@ -192,11 +191,11 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
key.BACKSPACE => self.cmd("delete_backward", .{}),
key.TAB => self.cmd("unindent", .{}),
';' => self.cmd("enter_overlay_mode", command.fmt(.{"command_palette"})),
'N' => self.cmd("goto_prev_match", .{}),
'A' => self.seq(.{ "move_end", "enter_mode" }, command.fmt(.{"vim/insert"})),
';' => 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("move_end", .{}),
'G' => if (self.count == 0)
'g' => if (self.count == 0)
self.cmd("move_buffer_end", .{})
else {
const count = self.count;
@ -206,7 +205,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
try self.cmd_count("move_down", .{});
},
'O' => self.seq(.{ "smart_insert_line_before", "enter_mode" }, command.fmt(.{"vim/insert"})),
'o' => self.seq(.{ "smart_insert_line_before", "enter_mode" }, command.fmt(.{"vim/insert"})),
else => {},
},
@ -228,7 +227,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
key.DEL => self.cmd("delete_forward", .{}),
key.BACKSPACE => self.cmd("delete_backward", .{}),
':' => self.cmd("enter_overlay_mode", command.fmt(.{"command_palette"})),
':' => 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"})),
@ -297,49 +296,6 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
keypress == key.LSUPER or
keypress == key.RSUPER) return;
switch (modifiers) {
0 => switch (keypress) {
'1' => {
self.add_count(1);
return;
},
'2' => {
self.add_count(2);
return;
},
'3' => {
self.add_count(3);
return;
},
'4' => {
self.add_count(4);
return;
},
'5' => {
self.add_count(5);
return;
},
'6' => {
self.add_count(6);
return;
},
'7' => {
self.add_count(7);
return;
},
'8' => {
self.add_count(8);
return;
},
'9' => {
self.add_count(9);
return;
},
else => {},
},
else => {},
}
defer self.leader = null;
const ldr = if (self.leader) |leader| leader else return;
return switch (ldr.modifiers) {
@ -531,3 +487,117 @@ fn seq_count(self: *Self, cmds: anytype, ctx: command.Context) tp.result {
inline for (fields_info) |field_info|
try self.cmd(@field(cmds, field_info.name), ctx);
}
const hints = tui.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" },
.{ "enter_find_in_files_mode", "C-S-f" },
.{ "enter_find_mode", "C-f, /" },
.{ "enter_goto_mode", "C-g" },
.{ "enter_move_to_char_mode", "C-b, C-t" }, // true/false
.{ "enter_open_file_mode", "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_diagnostic", "A-n" },
.{ "goto_next_match", "C-n, F3, n" },
.{ "goto_prev_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-;" },
.{ "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" },
.{ "restart", "C-S-r" },
.{ "save_file", "C-s" },
.{ "scroll_view_bottom", "C-l, z z" },
.{ "scroll_view_center", "C-l, z z" },
.{ "scroll_view_top", "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" },
.{ "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_logview", "C-j, F11" },
.{ "toggle_whitespace", "C-F10" },
.{ "to_lower", "A-l" },
.{ "to_upper", "A-u" },
.{ "undo", "C-z" },
.{ "undo", "u" },
.{ "unindent", "S-tab" },
});

View file

@ -35,6 +35,7 @@ pub fn create(a: Allocator) !tui.Mode {
.name = root.application_logo ++ "VISUAL",
.description = "vim",
.line_numbers = if (tui.current().config.vim_visual_gutter_line_numbers_relative) .relative else .absolute,
.keybind_hints = &hints,
};
}
@ -74,6 +75,7 @@ fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) t
}
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
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) {
@ -83,7 +85,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
}
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
'E' => self.cmd("enter_overlay_mode", command.fmt(.{"open_recent"})),
'E' => self.cmd("open_recent", .{}),
'U' => self.cmd("move_scroll_page_up", .{}),
'D' => self.cmd("move_scroll_page_down", .{}),
'R' => self.cmd("redo", .{}),
@ -126,7 +128,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
'P' => self.cmd("enter_overlay_mode", command.fmt(.{"command_palette"})),
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_down", .{}),
'Z' => self.cmd("redo", .{}),
'Q' => self.cmd("quit_without_saving", .{}),
@ -135,7 +137,6 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
'F' => self.cmd("enter_find_in_files_mode", .{}),
'L' => self.cmd_async("add_cursor_all_matches"),
'I' => self.cmd_async("toggle_inspector_view"),
'/' => self.cmd("log_widgets", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.END => self.cmd("select_buffer_end", .{}),
key.HOME => self.cmd("select_buffer_begin", .{}),
@ -188,11 +189,11 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
key.BACKSPACE => self.cmd("delete_backward", .{}),
key.TAB => self.cmd("unindent", .{}),
';' => self.cmd("enter_overlay_mode", command.fmt(.{"command_palette"})),
'N' => self.cmd("goto_prev_match", .{}),
'A' => self.seq(.{ "move_end", "enter_mode" }, command.fmt(.{"vim/insert"})),
';' => 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)
'g' => if (self.count == 0)
self.cmd("move_buffer_end", .{})
else {
const count = self.count;
@ -202,7 +203,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
try self.cmd_count("move_down", .{});
},
'O' => self.seq(.{ "smart_insert_line_before", "enter_mode" }, command.fmt(.{"vim/insert"})),
'o' => self.seq(.{ "smart_insert_line_before", "enter_mode" }, command.fmt(.{"vim/insert"})),
else => {},
},
@ -224,7 +225,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
key.DEL => self.cmd("delete_forward", .{}),
key.BACKSPACE => self.cmd("delete_backward", .{}),
':' => self.cmd("enter_overlay_mode", command.fmt(.{"command_palette"})),
':' => 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"})),
@ -293,49 +294,6 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
keypress == key.LSUPER or
keypress == key.RSUPER) return;
switch (modifiers) {
0 => switch (keypress) {
'1' => {
self.add_count(1);
return;
},
'2' => {
self.add_count(2);
return;
},
'3' => {
self.add_count(3);
return;
},
'4' => {
self.add_count(4);
return;
},
'5' => {
self.add_count(5);
return;
},
'6' => {
self.add_count(6);
return;
},
'7' => {
self.add_count(7);
return;
},
'8' => {
self.add_count(8);
return;
},
'9' => {
self.add_count(9);
return;
},
else => {},
},
else => {},
}
defer self.leader = null;
const ldr = if (self.leader) |leader| leader else return;
return switch (ldr.modifiers) {
@ -489,3 +447,117 @@ fn seq_count(self: *Self, cmds: anytype, ctx: command.Context) tp.result {
inline for (fields_info) |field_info|
try self.cmd(@field(cmds, field_info.name), ctx);
}
const hints = tui.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" },
.{ "enter_find_in_files_mode", "C-S-f" },
.{ "enter_find_mode", "C-f, /" },
.{ "enter_goto_mode", "C-g" },
.{ "enter_move_to_char_mode", "C-b, C-t" }, // true/false
.{ "enter_open_file_mode", "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_diagnostic", "A-n" },
.{ "goto_next_match", "C-n, F3, n" },
.{ "goto_prev_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-;" },
.{ "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" },
.{ "restart", "C-S-r" },
.{ "save_file", "C-s" },
.{ "scroll_view_bottom", "C-l, z z" },
.{ "scroll_view_center", "C-l, z z" },
.{ "scroll_view_top", "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" },
.{ "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_logview", "C-j, F11" },
.{ "toggle_whitespace", "C-F10" },
.{ "to_lower", "A-l" },
.{ "to_upper", "A-u" },
.{ "undo", "C-z" },
.{ "undo", "u" },
.{ "unindent", "S-tab" },
});

View file

@ -28,6 +28,8 @@ inputbox: *InputBox.State(*Self),
logger: log.Logger,
longest: usize = 0,
commands: Commands = undefined,
hints: ?*const tui.KeybindHints = null,
longest_hint: usize = 0,
pub fn create(a: std.mem.Allocator) !tui.Mode {
const mv = if (tui.current().mainview.dynamic_cast(mainview)) |mv_| mv_ else return error.NotFound;
@ -40,7 +42,12 @@ pub fn create(a: std.mem.Allocator) !tui.Mode {
.ctx = self,
.label = "Search commands",
}))).dynamic_cast(InputBox.State(*Self)) orelse unreachable,
.hints = if (tui.current().input_mode) |m| m.keybind_hints else null,
};
if (self.hints) |hints| {
for (hints.values()) |val|
self.longest_hint = @max(self.longest_hint, val.len);
}
try self.commands.init(self);
try self.start_query();
try mv.floating_views.add(self.menu.menu_widget);
@ -62,18 +69,24 @@ pub fn deinit(self: *Self) void {
fn on_render_menu(_: *Self, button: *Button.State(*Menu.State(*Self)), theme: *const Widget.Theme, selected: bool) bool {
const style_base = if (button.active) theme.editor_cursor else if (button.hover or selected) theme.editor_selection else theme.editor_widget;
const style_keybind = if (tui.find_scope_style(theme, "entity.name")) |sty| sty.style else style_base;
button.plane.set_base_style(" ", style_base);
button.plane.erase();
button.plane.home();
var command_name: []const u8 = undefined;
var keybind_hint: []const u8 = undefined;
var iter = button.opts.label; // label contains cbor, first the file name, then multiple match indexes
if (!(cbor.matchString(&iter, &command_name) catch false))
command_name = "#ERROR#";
if (!(cbor.matchString(&iter, &keybind_hint) catch false))
keybind_hint = "";
const pointer = if (selected) "" else " ";
_ = button.plane.print("{s}{s} ", .{
pointer,
command_name,
}) catch {};
button.plane.set_style(style_keybind);
_ = button.plane.print_aligned_right(0, "{s} ", .{keybind_hint}) catch {};
var index: usize = 0;
var len = cbor.decodeArrayHeader(&iter) catch return false;
while (len > 0) : (len -= 1) {
@ -139,7 +152,6 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
'J' => self.cmd("toggle_logview", .{}),
'Q' => self.cmd("quit", .{}),
'W' => self.cmd("close_file", .{}),
'E' => self.cmd("command_palette_menu_down", .{}),
'P' => self.cmd("command_palette_menu_up", .{}),
'N' => self.cmd("command_palette_menu_down", .{}),
'V' => self.cmd("system_paste", .{}),
@ -153,13 +165,12 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) tp.result {
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
'P' => self.cmd("exit_overlay_mode", .{}),
'P' => self.cmd("command_palette_menu_down", .{}),
'Q' => self.cmd("quit_without_saving", .{}),
'W' => self.cmd("close_file_without_saving", .{}),
'R' => self.cmd("restart", .{}),
'L' => self.cmd_async("toggle_logview"),
'I' => self.cmd_async("toggle_inputview"),
'E' => self.cmd("command_palette_menu_up", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
@ -260,6 +271,7 @@ fn add_item(self: *Self, command_name: []const u8, matches: ?[]const usize) !voi
defer label.deinit();
const writer = label.writer();
try cbor.writeValue(writer, command_name);
try cbor.writeValue(writer, if (self.hints) |hints| hints.get(command_name) else "");
if (matches) |matches_|
try cbor.writeValue(writer, matches_);
try self.menu.add_item_with_handler(label.items, menu_action_execute_command);

View file

@ -58,7 +58,7 @@ pub fn create(a: Allocator, parent: Plane) !Widget {
}
fn on_click(_: *Self, _: *Button.State(Self)) void {
command.executeName("enter_overlay_mode", command.fmt(.{"open_recent"})) catch {};
command.executeName("open_recent", .{}) catch {};
}
fn on_click2(_: *Self, _: *Button.State(Self)) void {

View file

@ -63,6 +63,6 @@ fn on_click(_: *void, _: *Button.State(void)) void {
} else if (is_overlay_mode()) {
command.executeName("exit_overlay_mode", .{}) catch {};
} else {
command.executeName("enter_overlay_mode", command.fmt(.{"command_palette"})) catch {};
command.executeName("open_command_palette", .{}) catch {};
}
}

View file

@ -559,23 +559,18 @@ const cmds = struct {
return enter_mode(self, Ctx.fmt(.{self.config.input_mode}));
}
pub fn enter_overlay_mode(self: *Self, ctx: Ctx) tp.result {
var mode: []const u8 = undefined;
if (!try ctx.args.match(.{tp.extract(&mode)}))
return tp.exit_error(error.InvalidArgument);
pub fn open_command_palette(self: *Self, _: Ctx) tp.result {
if (self.mini_mode) |_| try exit_mini_mode(self, .{});
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
self.input_mode = if (std.mem.eql(u8, mode, "command_palette")) ret: {
self.input_mode_outer = self.input_mode;
break :ret @import("mode/overlay/command_palette.zig").create(self.a) catch |e| return tp.exit_error(e);
} else if (std.mem.eql(u8, mode, "open_recent")) ret: {
self.input_mode_outer = self.input_mode;
break :ret @import("mode/overlay/open_recent.zig").create(self.a) catch |e| return tp.exit_error(e);
} else {
self.logger.print("unknown mode {s}", .{mode});
return;
};
// self.logger.print("input mode: {s}", .{(self.input_mode orelse return).description});
self.input_mode_outer = self.input_mode;
self.input_mode = @import("mode/overlay/command_palette.zig").create(self.a) catch |e| return tp.exit_error(e);
}
pub fn open_recent(self: *Self, _: Ctx) tp.result {
if (self.mini_mode) |_| try exit_mini_mode(self, .{});
if (self.input_mode_outer) |_| try exit_overlay_mode(self, .{});
self.input_mode_outer = self.input_mode;
self.input_mode = @import("mode/overlay/open_recent.zig").create(self.a) catch |e| return tp.exit_error(e);
}
pub fn exit_overlay_mode(self: *Self, _: Ctx) tp.result {
@ -643,6 +638,7 @@ pub const Mode = struct {
name: []const u8,
description: []const u8,
line_numbers: enum { absolute, relative } = .absolute,
keybind_hints: ?*const KeybindHints = null,
fn deinit(self: *Mode) void {
self.handler.deinit();
@ -654,6 +650,8 @@ pub const MiniModeState = struct {
cursor: ?usize = null,
};
pub const KeybindHints = std.static_string_map.StaticStringMap([]const u8);
threadlocal var instance_: ?*Self = null;
pub fn current() *Self {