diff options
author | Gokul Soumya | 2021-07-26 16:07:13 +0000 |
---|---|---|
committer | GitHub | 2021-07-26 16:07:13 +0000 |
commit | 88d6f652390922b389667f469b6d308db569bdaf (patch) | |
tree | 12d23bd03d89744880e87fca12f192e676272ee9 /helix-term/src/ui | |
parent | a630fb5d2022b264bcac34317bbadd0973bd57d4 (diff) |
Allow multi key remappings in config file (#454)
* Use tree like structure to store keymaps
* Allow multi key keymaps in config file
* Allow multi key keymaps in insert mode
* Make keymap state self contained
* Add keymap! macro for ergonomic declaration
* Add descriptions for editor commands
* Allow keymap! to take multiple keys
* Restore infobox display
* Fix keymap merging and add infobox titles
* Fix and add tests for keymaps
* Clean up comments and apply suggestions
* Allow trailing commas in keymap!
* Remove mode suffixes from keymaps
* Preserve order of keys when showing infobox
* Make command descriptions smaller
* Strip infobox title prefix from items
* Strip infobox title prefix from items
Diffstat (limited to 'helix-term/src/ui')
-rw-r--r-- | helix-term/src/ui/editor.rs | 76 | ||||
-rw-r--r-- | helix-term/src/ui/info.rs | 2 |
2 files changed, 58 insertions, 20 deletions
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 9a2fbf57..78a54079 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -2,7 +2,7 @@ use crate::{ commands, compositor::{Component, Context, EventResult}, key, - keymap::Keymaps, + keymap::{KeymapResult, Keymaps}, ui::{Completion, ProgressSpinners}, }; @@ -15,6 +15,7 @@ use helix_core::{ use helix_view::{ document::Mode, graphics::{CursorKind, Modifier, Rect, Style}, + info::Info, input::KeyEvent, keyboard::{KeyCode, KeyModifiers}, Document, Editor, Theme, View, @@ -30,6 +31,7 @@ pub struct EditorView { last_insert: (commands::Command, Vec<KeyEvent>), completion: Option<Completion>, spinners: ProgressSpinners, + pub autoinfo: Option<Info>, } const OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter @@ -48,6 +50,7 @@ impl EditorView { last_insert: (commands::Command::normal_mode, Vec::new()), completion: None, spinners: ProgressSpinners::default(), + autoinfo: None, } } @@ -559,19 +562,53 @@ impl EditorView { ); } - fn insert_mode(&self, cx: &mut commands::Context, event: KeyEvent) { - if let Some(command) = self.keymaps[&Mode::Insert].get(&event) { - command.execute(cx); - } else if let KeyEvent { - code: KeyCode::Char(ch), - .. - } = event - { - commands::insert::insert_char(cx, ch); + /// Handle events by looking them up in `self.keymaps`. Returns None + /// if event was handled (a command was executed or a subkeymap was + /// activated). Only KeymapResult::{NotFound, Cancelled} is returned + /// otherwise. + fn handle_keymap_event( + &mut self, + mode: Mode, + cxt: &mut commands::Context, + event: KeyEvent, + ) -> Option<KeymapResult> { + self.autoinfo = None; + match self.keymaps.get_mut(&mode).unwrap().get(event) { + KeymapResult::Matched(command) => command.execute(cxt), + KeymapResult::Pending(node) => self.autoinfo = Some(node.into()), + k @ KeymapResult::NotFound | k @ KeymapResult::Cancelled(_) => return Some(k), } + None } - fn command_mode(&self, mode: Mode, cxt: &mut commands::Context, event: KeyEvent) { + fn insert_mode(&mut self, cx: &mut commands::Context, event: KeyEvent) { + if let Some(keyresult) = self.handle_keymap_event(Mode::Insert, cx, event) { + match keyresult { + KeymapResult::NotFound => { + if let Some(ch) = event.char() { + commands::insert::insert_char(cx, ch) + } + } + KeymapResult::Cancelled(pending) => { + for ev in pending { + match ev.char() { + Some(ch) => commands::insert::insert_char(cx, ch), + None => { + if let KeymapResult::Matched(command) = + self.keymaps.get_mut(&Mode::Insert).unwrap().get(ev) + { + command.execute(cx); + } + } + } + } + } + _ => unreachable!(), + } + } + } + + fn command_mode(&mut self, mode: Mode, cxt: &mut commands::Context, event: KeyEvent) { match event { // count handling key!(i @ '0'..='9') => { @@ -584,8 +621,8 @@ impl EditorView { // first execute whatever put us into insert mode self.last_insert.0.execute(cxt); // then replay the inputs - for key in &self.last_insert.1 { - self.insert_mode(cxt, *key) + for &key in &self.last_insert.1.clone() { + self.insert_mode(cxt, key) } } _ => { @@ -598,9 +635,7 @@ impl EditorView { // set the register cxt.selected_register = cxt.editor.selected_register.take(); - if let Some(command) = self.keymaps[&mode].get(&event) { - command.execute(cxt); - } + self.handle_keymap_event(mode, cxt, event); } } } @@ -714,7 +749,11 @@ impl Component for EditorView { // how we entered insert mode is important, and we should track that so // we can repeat the side effect. - self.last_insert.0 = self.keymaps[&mode][&key]; + self.last_insert.0 = match self.keymaps.get_mut(&mode).unwrap().get(key) { + KeymapResult::Matched(command) => command, + // FIXME: insert mode can only be entered through single KeyCodes + _ => unimplemented!(), + }; self.last_insert.1.clear(); } (Mode::Insert, Mode::Normal) => { @@ -752,9 +791,8 @@ impl Component for EditorView { ); } - if let Some(info) = std::mem::take(&mut cx.editor.autoinfo) { + if let Some(ref info) = self.autoinfo { info.render(area, surface, cx); - cx.editor.autoinfo = Some(info); } // render status msg diff --git a/helix-term/src/ui/info.rs b/helix-term/src/ui/info.rs index e5f20562..36b096db 100644 --- a/helix-term/src/ui/info.rs +++ b/helix-term/src/ui/info.rs @@ -8,7 +8,7 @@ impl Component for Info { fn render(&self, viewport: Rect, surface: &mut Surface, cx: &mut Context) { let style = cx.editor.theme.get("ui.popup"); let block = Block::default() - .title(self.title) + .title(self.title.as_str()) .borders(Borders::ALL) .border_style(style); let Info { width, height, .. } = self; |