aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/keymap
diff options
context:
space:
mode:
authorJoe2022-03-25 09:05:20 +0000
committerGitHub2022-03-25 09:05:20 +0000
commitbee05dd32a685b58015514492525673b1b568b0d (patch)
tree4d141ece2ff029b881013f7ef4e89bfb9b064919 /helix-term/src/keymap
parent309f2c2c8e64f8be2123a0232c5f9761496b6514 (diff)
Add refresh-config and open-config command (#1803)
* Add refresh-config and open-config command * clippy * Use dynamic dispatch for editor config * Refactor Result::Ok to Ok * Remove unused import * cargo fmt * Modify config error handling * cargo xtask docgen * impl display for ConfigLoadError * cargo fmt * Put keymaps behind dyn access, refactor config.load() * Update command names * Update helix-term/src/application.rs Co-authored-by: Blaž Hrastnik <blaz@mxxn.io> * Switch to unbounded_channel * Remove --edit-config command * Update configuration docs * Revert "Put keymaps behind dyn access", too hard This reverts commit 06bad8cf492b9331d0a2d1e9242f3ad4e2c1cf79. * Add refresh for keys * Refactor default_keymaps, fix config default, add test * swap -> store, remove unneeded clone * cargo fmt * Rename default_keymaps to default Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Diffstat (limited to 'helix-term/src/keymap')
-rw-r--r--helix-term/src/keymap/default.rs359
-rw-r--r--helix-term/src/keymap/macros.rs127
2 files changed, 486 insertions, 0 deletions
diff --git a/helix-term/src/keymap/default.rs b/helix-term/src/keymap/default.rs
new file mode 100644
index 00000000..b5685082
--- /dev/null
+++ b/helix-term/src/keymap/default.rs
@@ -0,0 +1,359 @@
+use std::collections::HashMap;
+
+use super::macros::keymap;
+use super::{Keymap, Mode};
+use helix_core::hashmap;
+
+pub fn default() -> HashMap<Mode, Keymap> {
+ let normal = keymap!({ "Normal mode"
+ "h" | "left" => move_char_left,
+ "j" | "down" => move_line_down,
+ "k" | "up" => move_line_up,
+ "l" | "right" => move_char_right,
+
+ "t" => find_till_char,
+ "f" => find_next_char,
+ "T" => till_prev_char,
+ "F" => find_prev_char,
+ "r" => replace,
+ "R" => replace_with_yanked,
+ "A-." => repeat_last_motion,
+
+ "~" => switch_case,
+ "`" => switch_to_lowercase,
+ "A-`" => switch_to_uppercase,
+
+ "home" => goto_line_start,
+ "end" => goto_line_end,
+
+ "w" => move_next_word_start,
+ "b" => move_prev_word_start,
+ "e" => move_next_word_end,
+
+ "W" => move_next_long_word_start,
+ "B" => move_prev_long_word_start,
+ "E" => move_next_long_word_end,
+
+ "v" => select_mode,
+ "G" => goto_line,
+ "g" => { "Goto"
+ "g" => goto_file_start,
+ "e" => goto_last_line,
+ "f" => goto_file,
+ "h" => goto_line_start,
+ "l" => goto_line_end,
+ "s" => goto_first_nonwhitespace,
+ "d" => goto_definition,
+ "y" => goto_type_definition,
+ "r" => goto_reference,
+ "i" => goto_implementation,
+ "t" => goto_window_top,
+ "c" => goto_window_center,
+ "b" => goto_window_bottom,
+ "a" => goto_last_accessed_file,
+ "m" => goto_last_modified_file,
+ "n" => goto_next_buffer,
+ "p" => goto_previous_buffer,
+ "." => goto_last_modification,
+ },
+ ":" => command_mode,
+
+ "i" => insert_mode,
+ "I" => prepend_to_line,
+ "a" => append_mode,
+ "A" => append_to_line,
+ "o" => open_below,
+ "O" => open_above,
+
+ "d" => delete_selection,
+ "A-d" => delete_selection_noyank,
+ "c" => change_selection,
+ "A-c" => change_selection_noyank,
+
+ "C" => copy_selection_on_next_line,
+ "A-C" => copy_selection_on_prev_line,
+
+
+ "s" => select_regex,
+ "A-s" => split_selection_on_newline,
+ "S" => split_selection,
+ ";" => collapse_selection,
+ "A-;" => flip_selections,
+ "A-k" | "A-up" => expand_selection,
+ "A-j" | "A-down" => shrink_selection,
+ "A-h" | "A-left" => select_prev_sibling,
+ "A-l" | "A-right" => select_next_sibling,
+
+ "%" => select_all,
+ "x" => extend_line,
+ "X" => extend_to_line_bounds,
+ // crop_to_whole_line
+
+ "m" => { "Match"
+ "m" => match_brackets,
+ "s" => surround_add,
+ "r" => surround_replace,
+ "d" => surround_delete,
+ "a" => select_textobject_around,
+ "i" => select_textobject_inner,
+ },
+ "[" => { "Left bracket"
+ "d" => goto_prev_diag,
+ "D" => goto_first_diag,
+ "f" => goto_prev_function,
+ "c" => goto_prev_class,
+ "a" => goto_prev_parameter,
+ "o" => goto_prev_comment,
+ "space" => add_newline_above,
+ },
+ "]" => { "Right bracket"
+ "d" => goto_next_diag,
+ "D" => goto_last_diag,
+ "f" => goto_next_function,
+ "c" => goto_next_class,
+ "a" => goto_next_parameter,
+ "o" => goto_next_comment,
+ "space" => add_newline_below,
+ },
+
+ "/" => search,
+ "?" => rsearch,
+ "n" => search_next,
+ "N" => search_prev,
+ "*" => search_selection,
+
+ "u" => undo,
+ "U" => redo,
+ "A-u" => earlier,
+ "A-U" => later,
+
+ "y" => yank,
+ // yank_all
+ "p" => paste_after,
+ // paste_all
+ "P" => paste_before,
+
+ "Q" => record_macro,
+ "q" => replay_macro,
+
+ ">" => indent,
+ "<" => unindent,
+ "=" => format_selections,
+ "J" => join_selections,
+ "K" => keep_selections,
+ "A-K" => remove_selections,
+
+ "," => keep_primary_selection,
+ "A-," => remove_primary_selection,
+
+ // "q" => record_macro,
+ // "Q" => replay_macro,
+
+ "&" => align_selections,
+ "_" => trim_selections,
+
+ "(" => rotate_selections_backward,
+ ")" => rotate_selections_forward,
+ "A-(" => rotate_selection_contents_backward,
+ "A-)" => rotate_selection_contents_forward,
+
+ "A-:" => ensure_selections_forward,
+
+ "esc" => normal_mode,
+ "C-b" | "pageup" => page_up,
+ "C-f" | "pagedown" => page_down,
+ "C-u" => half_page_up,
+ "C-d" => half_page_down,
+
+ "C-w" => { "Window"
+ "C-w" | "w" => rotate_view,
+ "C-s" | "s" => hsplit,
+ "C-v" | "v" => vsplit,
+ "f" => goto_file_hsplit,
+ "F" => goto_file_vsplit,
+ "C-q" | "q" => wclose,
+ "C-o" | "o" => wonly,
+ "C-h" | "h" | "left" => jump_view_left,
+ "C-j" | "j" | "down" => jump_view_down,
+ "C-k" | "k" | "up" => jump_view_up,
+ "C-l" | "l" | "right" => jump_view_right,
+ "n" => { "New split scratch buffer"
+ "C-s" | "s" => hsplit_new,
+ "C-v" | "v" => vsplit_new,
+ },
+ },
+
+ // move under <space>c
+ "C-c" => toggle_comments,
+
+ // z family for save/restore/combine from/to sels from register
+
+ "tab" => jump_forward, // tab == <C-i>
+ "C-o" => jump_backward,
+ "C-s" => save_selection,
+
+ "space" => { "Space"
+ "f" => file_picker,
+ "b" => buffer_picker,
+ "s" => symbol_picker,
+ "S" => workspace_symbol_picker,
+ "a" => code_action,
+ "'" => last_picker,
+ "d" => { "Debug (experimental)" sticky=true
+ "l" => dap_launch,
+ "b" => dap_toggle_breakpoint,
+ "c" => dap_continue,
+ "h" => dap_pause,
+ "i" => dap_step_in,
+ "o" => dap_step_out,
+ "n" => dap_next,
+ "v" => dap_variables,
+ "t" => dap_terminate,
+ "C-c" => dap_edit_condition,
+ "C-l" => dap_edit_log,
+ "s" => { "Switch"
+ "t" => dap_switch_thread,
+ "f" => dap_switch_stack_frame,
+ // sl, sb
+ },
+ "e" => dap_enable_exceptions,
+ "E" => dap_disable_exceptions,
+ },
+ "w" => { "Window"
+ "C-w" | "w" => rotate_view,
+ "C-s" | "s" => hsplit,
+ "C-v" | "v" => vsplit,
+ "f" => goto_file_hsplit,
+ "F" => goto_file_vsplit,
+ "C-q" | "q" => wclose,
+ "C-o" | "o" => wonly,
+ "C-h" | "h" | "left" => jump_view_left,
+ "C-j" | "j" | "down" => jump_view_down,
+ "C-k" | "k" | "up" => jump_view_up,
+ "C-l" | "l" | "right" => jump_view_right,
+ "n" => { "New split scratch buffer"
+ "C-s" | "s" => hsplit_new,
+ "C-v" | "v" => vsplit_new,
+ },
+ },
+ "y" => yank_joined_to_clipboard,
+ "Y" => yank_main_selection_to_clipboard,
+ "p" => paste_clipboard_after,
+ "P" => paste_clipboard_before,
+ "R" => replace_selections_with_clipboard,
+ "/" => global_search,
+ "k" => hover,
+ "r" => rename_symbol,
+ "?" => command_palette,
+ },
+ "z" => { "View"
+ "z" | "c" => align_view_center,
+ "t" => align_view_top,
+ "b" => align_view_bottom,
+ "m" => align_view_middle,
+ "k" | "up" => scroll_up,
+ "j" | "down" => scroll_down,
+ "C-b" | "pageup" => page_up,
+ "C-f" | "pagedown" => page_down,
+ "C-u" => half_page_up,
+ "C-d" => half_page_down,
+ },
+ "Z" => { "View" sticky=true
+ "z" | "c" => align_view_center,
+ "t" => align_view_top,
+ "b" => align_view_bottom,
+ "m" => align_view_middle,
+ "k" | "up" => scroll_up,
+ "j" | "down" => scroll_down,
+ "C-b" | "pageup" => page_up,
+ "C-f" | "pagedown" => page_down,
+ "C-u" => half_page_up,
+ "C-d" => half_page_down,
+ },
+
+ "\"" => select_register,
+ "|" => shell_pipe,
+ "A-|" => shell_pipe_to,
+ "!" => shell_insert_output,
+ "A-!" => shell_append_output,
+ "$" => shell_keep_pipe,
+ "C-z" => suspend,
+
+ "C-a" => increment,
+ "C-x" => decrement,
+ });
+ let mut select = normal.clone();
+ select.merge_nodes(keymap!({ "Select mode"
+ "h" | "left" => extend_char_left,
+ "j" | "down" => extend_line_down,
+ "k" | "up" => extend_line_up,
+ "l" | "right" => extend_char_right,
+
+ "w" => extend_next_word_start,
+ "b" => extend_prev_word_start,
+ "e" => extend_next_word_end,
+ "W" => extend_next_long_word_start,
+ "B" => extend_prev_long_word_start,
+ "E" => extend_next_long_word_end,
+
+ "n" => extend_search_next,
+ "N" => extend_search_prev,
+
+ "t" => extend_till_char,
+ "f" => extend_next_char,
+ "T" => extend_till_prev_char,
+ "F" => extend_prev_char,
+
+ "home" => extend_to_line_start,
+ "end" => extend_to_line_end,
+ "esc" => exit_select_mode,
+
+ "v" => normal_mode,
+ }));
+ let insert = keymap!({ "Insert mode"
+ "esc" => normal_mode,
+
+ "backspace" => delete_char_backward,
+ "C-h" => delete_char_backward,
+ "del" => delete_char_forward,
+ "C-d" => delete_char_forward,
+ "ret" => insert_newline,
+ "C-j" => insert_newline,
+ "tab" => insert_tab,
+ "C-w" => delete_word_backward,
+ "A-backspace" => delete_word_backward,
+ "A-d" => delete_word_forward,
+
+ "left" => move_char_left,
+ "C-b" => move_char_left,
+ "down" => move_line_down,
+ "C-n" => move_line_down,
+ "up" => move_line_up,
+ "C-p" => move_line_up,
+ "right" => move_char_right,
+ "C-f" => move_char_right,
+ "A-b" => move_prev_word_end,
+ "A-left" => move_prev_word_end,
+ "A-f" => move_next_word_start,
+ "A-right" => move_next_word_start,
+ "A-<" => goto_file_start,
+ "A->" => goto_file_end,
+ "pageup" => page_up,
+ "pagedown" => page_down,
+ "home" => goto_line_start,
+ "C-a" => goto_line_start,
+ "end" => goto_line_end_newline,
+ "C-e" => goto_line_end_newline,
+
+ "C-k" => kill_to_line_end,
+ "C-u" => kill_to_line_start,
+
+ "C-x" => completion,
+ "C-r" => insert_register,
+ });
+ hashmap!(
+ Mode::Normal => Keymap::new(normal),
+ Mode::Select => Keymap::new(select),
+ Mode::Insert => Keymap::new(insert),
+ )
+}
diff --git a/helix-term/src/keymap/macros.rs b/helix-term/src/keymap/macros.rs
new file mode 100644
index 00000000..c4a1bfbb
--- /dev/null
+++ b/helix-term/src/keymap/macros.rs
@@ -0,0 +1,127 @@
+#[macro_export]
+macro_rules! key {
+ ($key:ident) => {
+ ::helix_view::input::KeyEvent {
+ code: ::helix_view::keyboard::KeyCode::$key,
+ modifiers: ::helix_view::keyboard::KeyModifiers::NONE,
+ }
+ };
+ ($($ch:tt)*) => {
+ ::helix_view::input::KeyEvent {
+ code: ::helix_view::keyboard::KeyCode::Char($($ch)*),
+ modifiers: ::helix_view::keyboard::KeyModifiers::NONE,
+ }
+ };
+}
+
+#[macro_export]
+macro_rules! shift {
+ ($key:ident) => {
+ ::helix_view::input::KeyEvent {
+ code: ::helix_view::keyboard::KeyCode::$key,
+ modifiers: ::helix_view::keyboard::KeyModifiers::SHIFT,
+ }
+ };
+ ($($ch:tt)*) => {
+ ::helix_view::input::KeyEvent {
+ code: ::helix_view::keyboard::KeyCode::Char($($ch)*),
+ modifiers: ::helix_view::keyboard::KeyModifiers::SHIFT,
+ }
+ };
+}
+
+#[macro_export]
+macro_rules! ctrl {
+ ($key:ident) => {
+ ::helix_view::input::KeyEvent {
+ code: ::helix_view::keyboard::KeyCode::$key,
+ modifiers: ::helix_view::keyboard::KeyModifiers::CONTROL,
+ }
+ };
+ ($($ch:tt)*) => {
+ ::helix_view::input::KeyEvent {
+ code: ::helix_view::keyboard::KeyCode::Char($($ch)*),
+ modifiers: ::helix_view::keyboard::KeyModifiers::CONTROL,
+ }
+ };
+}
+
+#[macro_export]
+macro_rules! alt {
+ ($key:ident) => {
+ ::helix_view::input::KeyEvent {
+ code: ::helix_view::keyboard::KeyCode::$key,
+ modifiers: ::helix_view::keyboard::KeyModifiers::ALT,
+ }
+ };
+ ($($ch:tt)*) => {
+ ::helix_view::input::KeyEvent {
+ code: ::helix_view::keyboard::KeyCode::Char($($ch)*),
+ modifiers: ::helix_view::keyboard::KeyModifiers::ALT,
+ }
+ };
+}
+
+/// Macro for defining the root of a `Keymap` object. Example:
+///
+/// ```
+/// # use helix_core::hashmap;
+/// # use helix_term::keymap;
+/// # use helix_term::keymap::Keymap;
+/// let normal_mode = keymap!({ "Normal mode"
+/// "i" => insert_mode,
+/// "g" => { "Goto"
+/// "g" => goto_file_start,
+/// "e" => goto_file_end,
+/// },
+/// "j" | "down" => move_line_down,
+/// });
+/// let keymap = Keymap::new(normal_mode);
+/// ```
+#[macro_export]
+macro_rules! keymap {
+ (@trie $cmd:ident) => {
+ $crate::keymap::KeyTrie::Leaf($crate::commands::MappableCommand::$cmd)
+ };
+
+ (@trie
+ { $label:literal $(sticky=$sticky:literal)? $($($key:literal)|+ => $value:tt,)+ }
+ ) => {
+ keymap!({ $label $(sticky=$sticky)? $($($key)|+ => $value,)+ })
+ };
+
+ (@trie [$($cmd:ident),* $(,)?]) => {
+ $crate::keymap::KeyTrie::Sequence(vec![$($crate::commands::Command::$cmd),*])
+ };
+
+ (
+ { $label:literal $(sticky=$sticky:literal)? $($($key:literal)|+ => $value:tt,)+ }
+ ) => {
+ // modified from the hashmap! macro
+ {
+ let _cap = hashmap!(@count $($($key),+),*);
+ let mut _map = ::std::collections::HashMap::with_capacity(_cap);
+ let mut _order = ::std::vec::Vec::with_capacity(_cap);
+ $(
+ $(
+ let _key = $key.parse::<::helix_view::input::KeyEvent>().unwrap();
+ let _duplicate = _map.insert(
+ _key,
+ keymap!(@trie $value)
+ );
+ assert!(_duplicate.is_none(), "Duplicate key found: {:?}", _duplicate.unwrap());
+ _order.push(_key);
+ )+
+ )*
+ let mut _node = $crate::keymap::KeyTrieNode::new($label, _map, _order);
+ $( _node.is_sticky = $sticky; )?
+ $crate::keymap::KeyTrie::Node(_node)
+ }
+ };
+}
+
+pub use alt;
+pub use ctrl;
+pub use key;
+pub use keymap;
+pub use shift;