diff options
Diffstat (limited to 'helix-term/src/keymap.rs')
-rw-r--r-- | helix-term/src/keymap.rs | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs new file mode 100644 index 00000000..af46f7a4 --- /dev/null +++ b/helix-term/src/keymap.rs @@ -0,0 +1,217 @@ +use crate::commands::{self, Command}; +use helix_core::hashmap; +use helix_view::document::Mode; +use std::collections::HashMap; + +// Kakoune-inspired: +// mode = { +// normal = { +// q = record_macro +// w = (next) word +// W = next WORD +// e = end of word +// E = end of WORD +// r = +// t = 'till char +// y = yank +// u = undo +// U = redo +// i = insert +// I = INSERT (start of line) +// o = open below (insert on new line below) +// O = open above (insert on new line above) +// p = paste (before cursor) +// P = PASTE (after cursor) +// ` = +// [ = select to text object start (alt = select whole object) +// ] = select to text object end +// { = extend to inner object start +// } = extend to inner object end +// a = append +// A = APPEND (end of line) +// s = split +// S = select +// d = delete() +// f = find_char() +// g = goto (gg, G, gc, gd, etc) +// +// h = move_char_left(n) +// j = move_line_down(n) +// k = move_line_up(n) +// l = move_char_right(n) +// : = command line +// ; = collapse selection to cursor +// " = use register +// ` = convert case? (to lower) (alt = swap case) +// ~ = convert to upper case +// . = repeat last command +// \ = disable hook? +// / = search +// > = indent +// < = deindent +// % = select whole buffer (in vim = jump to matching bracket) +// * = search pattern in selection +// ( = rotate main selection backward +// ) = rotate main selection forward +// - = trim selections? (alt = merge contiguous sel together) +// @ = convert tabs to spaces +// & = align cursor +// ? = extend to next given regex match (alt = to prev) +// +// in kakoune these are alt-h alt-l / gh gl +// select from curs to begin end / move curs to begin end +// 0 = start of line +// ^ = start of line (first non blank char) +// $ = end of line +// +// z = save selections +// Z = restore selections +// x = select line +// X = extend line +// c = change selected text +// C = copy selection? +// v = view menu (viewport manipulation) +// b = select to previous word start +// B = select to previous WORD start +// +// +// +// +// +// +// = = align? +// + = +// } +// +// gd = goto definition +// gr = goto reference +// } + +// #[cfg(feature = "term")] +pub use crossterm::event::{KeyCode, KeyEvent as Key, KeyModifiers as Modifiers}; + +// TODO: could be trie based +pub type Keymap = HashMap<Vec<Key>, Command>; +pub type Keymaps = HashMap<Mode, Keymap>; + +macro_rules! key { + ($ch:expr) => { + Key { + code: KeyCode::Char($ch), + modifiers: Modifiers::NONE, + } + }; +} + +macro_rules! shift { + ($ch:expr) => { + Key { + code: KeyCode::Char($ch), + modifiers: Modifiers::SHIFT, + } + }; +} + +macro_rules! ctrl { + ($ch:expr) => { + Key { + code: KeyCode::Char($ch), + modifiers: Modifiers::CONTROL, + } + }; +} + +// macro_rules! alt { +// ($ch:expr) => { +// Key { +// code: KeyCode::Char($ch), +// modifiers: Modifiers::ALT, +// } +// }; +// } + +pub fn default() -> Keymaps { + hashmap!( + Mode::Normal => + // as long as you cast the first item, rust is able to infer the other cases + hashmap!( + vec![key!('h')] => commands::move_char_left as Command, + vec![key!('j')] => commands::move_line_down, + vec![key!('k')] => commands::move_line_up, + vec![key!('0')] => commands::move_line_start, + vec![key!('$')] => commands::move_line_end, + vec![key!('l')] => commands::move_char_right, + vec![shift!('H')] => commands::extend_char_left, + vec![shift!('J')] => commands::extend_line_down, + vec![shift!('K')] => commands::extend_line_up, + vec![shift!('L')] => commands::extend_char_right, + vec![key!('w')] => commands::move_next_word_start, + vec![key!('b')] => commands::move_prev_word_start, + vec![key!('e')] => commands::move_next_word_end, + vec![key!('g')] => commands::goto_mode, + vec![key!('i')] => commands::insert_mode, + vec![shift!('I')] => commands::prepend_to_line, + vec![key!('a')] => commands::append_mode, + vec![shift!('A')] => commands::append_to_line, + vec![key!('o')] => commands::open_below, + vec![key!('d')] => commands::delete_selection, + vec![key!('c')] => commands::change_selection, + vec![key!('s')] => commands::split_selection_on_newline, + vec![key!(';')] => commands::collapse_selection, + // TODO should be alt(;) + vec![key!('%')] => commands::flip_selections, + vec![key!('x')] => commands::select_line, + vec![key!('u')] => commands::undo, + vec![shift!('U')] => commands::redo, + vec![key!('y')] => commands::yank, + vec![key!('p')] => commands::paste, + vec![key!('>')] => commands::indent, + vec![key!('<')] => commands::unindent, + vec![key!(':')] => commands::command_mode, + vec![Key { + code: KeyCode::Esc, + modifiers: Modifiers::NONE + }] => commands::normal_mode, + vec![Key { + code: KeyCode::PageUp, + modifiers: Modifiers::NONE + }] => commands::page_up, + vec![Key { + code: KeyCode::PageDown, + modifiers: Modifiers::NONE + }] => commands::page_down, + vec![ctrl!('u')] => commands::half_page_up, + vec![ctrl!('d')] => commands::half_page_down, + ), + Mode::Insert => hashmap!( + vec![Key { + code: KeyCode::Esc, + modifiers: Modifiers::NONE + }] => commands::normal_mode as Command, + vec![Key { + code: KeyCode::Backspace, + modifiers: Modifiers::NONE + }] => commands::insert::delete_char_backward, + vec![Key { + code: KeyCode::Delete, + modifiers: Modifiers::NONE + }] => commands::insert::delete_char_forward, + vec![Key { + code: KeyCode::Enter, + modifiers: Modifiers::NONE + }] => commands::insert::insert_newline, + vec![Key { + code: KeyCode::Tab, + modifiers: Modifiers::NONE + }] => commands::insert::insert_tab, + ), + Mode::Goto => hashmap!( + vec![Key { + code: KeyCode::Esc, + modifiers: Modifiers::NONE + }] => commands::normal_mode as Command, + vec![key!('g')] => commands::move_file_start as Command, + vec![key!('e')] => commands::move_file_end as Command, + ), + ) +} |