@@ -91,7 +91,7 @@ use std::collections::HashMap;
91pub use crossterm::event::{KeyCode, KeyEvent as Key, KeyModifiers as Modifiers};
91pub use crossterm::event::{KeyCode, KeyEvent as Key, KeyModifiers as Modifiers};
93// TODO: could be trie based
93// TODO: could be trie based
94−pub type Keymap = HashMap<Vec<Key>, Command>;
94+pub type Keymap = HashMap<Key, Command>;
95pub type Keymaps = HashMap<Mode, Keymap>;
95pub type Keymaps = HashMap<Mode, Keymap>;
97macro_rules! key {
97macro_rules! key {
@@ -131,125 +131,180 @@ macro_rules! alt {
133pub fn default() -> Keymaps {
133pub fn default() -> Keymaps {
134+ let normal = hashmap!(
135+ key!('h') => commands::move_char_left as Command,
136+ key!('j') => commands::move_line_down,
137+ key!('k') => commands::move_line_up,
138+ key!('l') => commands::move_char_right,
140+ // key!('t') => commands::till_next_char,
141+ // key!('f') => commands::find_next_char,
142+ // key!('T') => commands::till_prev_char,
143+ // key!('f') => commands::find_prev_char,
144+ // and matching set for select mode (extend)
146+ key!('0') => commands::move_line_start,
147+ key!('$') => commands::move_line_end,
149+ key!('w') => commands::move_next_word_start,
150+ key!('b') => commands::move_prev_word_start,
151+ key!('e') => commands::move_next_word_end,
153+ key!('v') => commands::select_mode,
154+ key!('g') => commands::goto_mode,
155+ key!(':') => commands::command_mode,
157+ key!('i') => commands::insert_mode,
158+ shift!('I') => commands::prepend_to_line,
159+ key!('a') => commands::append_mode,
160+ shift!('A') => commands::append_to_line,
161+ key!('o') => commands::open_below,
162+ // key!('O') => commands::open_above,
163+ // [<space> ]<space> equivalents too (add blank new line, no edit)
166+ key!('d') => commands::delete_selection,
167+ // TODO: also delete without yanking
168+ key!('c') => commands::change_selection,
169+ // TODO: also change delete without yanking
171+ // key!('r') => commands::replace_with_char,
173+ key!('s') => commands::select_regex,
174+ alt!('s') => commands::split_selection_on_newline,
175+ shift!('S') => commands::split_selection,
176+ key!(';') => commands::collapse_selection,
177+ alt!(';') => commands::flip_selections,
178+ key!('%') => commands::select_all,
179+ key!('x') => commands::select_line,
180+ // key!('X') => commands::extend_line,
181+ // or select mode X?
182+ // extend_to_whole_line, crop_to_whole_line
184+ // key!('m') => commands::select_to_matching,
185+ // key!('M') => commands::back_select_to_matching,
186+ // select mode extend equivalents
188+ // key!('.') => commands::repeat_insert,
191+ // TODO: figure out what key to use
192+ key!('[') => commands::expand_selection,
194+ key!('/') => commands::search,
195+ key!('n') => commands::search_next,
196+ key!('*') => commands::search_selection,
198+ key!('u') => commands::undo,
199+ shift!('U') => commands::redo,
201+ key!('y') => commands::yank,
203+ key!('p') => commands::paste,
206+ key!('>') => commands::indent,
207+ key!('<') => commands::unindent,
208+ key!('=') => commands::format_selections,
209+ shift!('J') => commands::join_selections,
210+ shift!('K') => commands::keep_selections,
212+ // key!('q') => commands::record_macro,
213+ // key!('Q') => commands::replay_macro,
215+ // ~ / apostrophe => change case
216+ // & align selections
217+ // _ trim selections
219+ // C / altC = copy (repeat) selections on prev/next lines
223+ modifiers: Modifiers::NONE
224+ } => commands::normal_mode,
226+ code: KeyCode::PageUp,
227+ modifiers: Modifiers::NONE
228+ } => commands::page_up,
230+ code: KeyCode::PageDown,
231+ modifiers: Modifiers::NONE
232+ } => commands::page_down,
233+ ctrl!('u') => commands::half_page_up,
234+ ctrl!('d') => commands::half_page_down,
236+ ctrl!('p') => commands::file_picker,
237+ ctrl!('b') => commands::buffer_picker,
240+ modifiers: Modifiers::NONE
241+ } => commands::next_view,
243+ // move under <space>c
244+ ctrl!('c') => commands::toggle_comments,
245+ ctrl!('K') => commands::hover,
247+ // z family for save/restore/combine from/to sels from register
249+ // TODO: decide whether we want normal mode to also be select mode (kakoune-like), or whether
250+ // we keep this separate select mode. More keys can fit into normal mode then, but it's weird
251+ // because some selection operations can now be done from normal mode, some from select mode.
252+ let mut select = normal.clone();
255+ key!('h') => commands::extend_char_left as Command,
256+ key!('j') => commands::extend_line_down,
257+ key!('k') => commands::extend_line_up,
258+ key!('l') => commands::extend_char_right,
260+ key!('w') => commands::extend_next_word_start,
261+ key!('b') => commands::extend_prev_word_start,
262+ key!('e') => commands::extend_next_word_end,
266+ modifiers: Modifiers::NONE
267+ } => commands::exit_select_mode as Command,
134 hashmap!(
272 hashmap!(
136− // as long as you cast the first item, rust is able to infer the other cases
273+ // as long as you cast the first item, rust is able to infer the other cases
137− hashmap!(
274+ // TODO: select could be normal mode with some bindings merged over
138− vec![key!('h')] => commands::move_char_left as Command,
275+ Mode::Normal => normal,
139− vec![key!('j')] => commands::move_line_down,
276+ Mode::Select => select,
140− vec![key!('k')] => commands::move_line_up,
141− vec![key!('l')] => commands::move_char_right,
143− vec![key!('0')] => commands::move_line_start,
144− vec![key!('$')] => commands::move_line_end,
146− vec![shift!('H')] => commands::extend_char_left,
147− vec![shift!('J')] => commands::extend_line_down,
148− vec![shift!('K')] => commands::extend_line_up,
149− vec![shift!('L')] => commands::extend_char_right,
151− vec![key!('w')] => commands::move_next_word_start,
152− vec![shift!('W')] => commands::extend_next_word_start,
153− vec![key!('b')] => commands::move_prev_word_start,
154− vec![shift!('B')] => commands::extend_prev_word_start,
155− vec![key!('e')] => commands::move_next_word_end,
156− vec![key!('E')] => commands::extend_next_word_end,
158− vec![key!('g')] => commands::goto_mode,
159− vec![key!(':')] => commands::command_mode,
161− vec![key!('i')] => commands::insert_mode,
162− vec![shift!('I')] => commands::prepend_to_line,
163− vec![key!('a')] => commands::append_mode,
164− vec![shift!('A')] => commands::append_to_line,
165− vec![key!('o')] => commands::open_below,
167− vec![key!('d')] => commands::delete_selection,
168− vec![key!('c')] => commands::change_selection,
170− vec![key!('s')] => commands::select_regex,
171− vec![alt!('s')] => commands::split_selection_on_newline,
172− vec![shift!('S')] => commands::split_selection,
173− vec![key!(';')] => commands::collapse_selection,
174− vec![alt!(';')] => commands::flip_selections,
175− vec![key!('%')] => commands::select_all,
176− vec![key!('x')] => commands::select_line,
178− // TODO: figure out what key to use
179− vec![key!('[')] => commands::expand_selection,
181− vec![key!('/')] => commands::search,
182− vec![key!('n')] => commands::search_next,
183− vec![key!('*')] => commands::search_selection,
185− vec![key!('u')] => commands::undo,
186− vec![shift!('U')] => commands::redo,
188− vec![key!('y')] => commands::yank,
189− vec![key!('p')] => commands::paste,
191− vec![key!('>')] => commands::indent,
192− vec![key!('<')] => commands::unindent,
193− vec![key!('=')] => commands::format_selections,
194− vec![ctrl!('j')] => commands::join_selections,
197− modifiers: Modifiers::NONE
198− }] => commands::normal_mode,
200− code: KeyCode::PageUp,
201− modifiers: Modifiers::NONE
202− }] => commands::page_up,
204− code: KeyCode::PageDown,
205− modifiers: Modifiers::NONE
206− }] => commands::page_down,
207− vec![ctrl!('u')] => commands::half_page_up,
208− vec![ctrl!('d')] => commands::half_page_down,
210− vec![ctrl!('p')] => commands::file_picker,
211− vec![ctrl!('b')] => commands::buffer_picker,
214− modifiers: Modifiers::NONE
215− }] => commands::next_view,
217− // move under <space>c
218− vec![ctrl!('c')] => commands::toggle_comments,
219− // was K, figure out a key
220− vec![ctrl!('k')] => commands::hover,
222− Mode::Insert => hashmap!(
277+ Mode::Insert => hashmap!(
223− vec![Key {
278+ Key {
224− code: KeyCode::Esc,
279+ code: KeyCode::Esc,
225− modifiers: Modifiers::NONE
280+ modifiers: Modifiers::NONE
226− }] => commands::normal_mode as Command,
281+ } => commands::normal_mode as Command,
227− vec![Key {
282+ Key {
228− code: KeyCode::Backspace,
283+ code: KeyCode::Backspace,
229− modifiers: Modifiers::NONE
284+ modifiers: Modifiers::NONE
230− }] => commands::insert::delete_char_backward,
285+ } => commands::insert::delete_char_backward,
231− vec![Key {
286+ Key {
232− code: KeyCode::Delete,
287+ code: KeyCode::Delete,
233− modifiers: Modifiers::NONE
288+ modifiers: Modifiers::NONE
234− }] => commands::insert::delete_char_forward,
289+ } => commands::insert::delete_char_forward,
235− vec![Key {
290+ Key {
236− code: KeyCode::Enter,
291+ code: KeyCode::Enter,
237− modifiers: Modifiers::NONE
292+ modifiers: Modifiers::NONE
238− }] => commands::insert::insert_newline,
293+ } => commands::insert::insert_newline,
239− vec![Key {
294+ Key {
240− code: KeyCode::Tab,
295+ code: KeyCode::Tab,
241− modifiers: Modifiers::NONE
296+ modifiers: Modifiers::NONE
242− }] => commands::insert::insert_tab,
297+ } => commands::insert::insert_tab,
244− vec![ctrl!('x')] => commands::completion,
299+ ctrl!('x') => commands::completion,
246− Mode::Goto => hashmap!(
301+ Mode::Goto => hashmap!(
247− vec![Key {
302+ Key {
248− code: KeyCode::Esc,
303+ code: KeyCode::Esc,
249− modifiers: Modifiers::NONE
304+ modifiers: Modifiers::NONE
250− }] => commands::normal_mode as Command,
305+ } => commands::normal_mode as Command,
251− vec![key!('g')] => commands::move_file_start as Command,
306+ key!('g') => commands::move_file_start as Command,
252− vec![key!('e')] => commands::move_file_end as Command,
307+ key!('e') => commands::move_file_end as Command,