on master help sign in
Show pending keys in status line (#515)
1493313Gokul Soumya
helix-term/src/keymap.rs+19
@@ -234,6 +234,7 @@ pub struct Keymap {
234 /// Always a Node
234 /// Always a Node
235 #[serde(flatten)]
235 #[serde(flatten)]
236 root: KeyTrie,
236 root: KeyTrie,
237+ /// Stores pending keys waiting for the next key
237 #[serde(skip)]
238 #[serde(skip)]
238 state: Vec<KeyEvent>,
239 state: Vec<KeyEvent>,
239}
240}
@@ -250,6 +251,11 @@ impl Keymap {
250 &self.root
251 &self.root
251 }
252 }
252
253
254+ /// Returns list of keys waiting to be disambiguated.
255+ pub fn pending(&self) -> &[KeyEvent] {
256+ &self.state
257+ }
258+
253 /// Lookup `key` in the keymap to try and find a command to execute
259 /// Lookup `key` in the keymap to try and find a command to execute
254 pub fn get(&mut self, key: KeyEvent) -> KeymapResult {
260 pub fn get(&mut self, key: KeyEvent) -> KeymapResult {
255 let &first = self.state.get(0).unwrap_or(&key);
261 let &first = self.state.get(0).unwrap_or(&key);
@@ -292,6 +298,19 @@ impl Default for Keymap {
292#[serde(transparent)]
298#[serde(transparent)]
293pub struct Keymaps(pub HashMap<Mode, Keymap>);
299pub struct Keymaps(pub HashMap<Mode, Keymap>);
294
300
301+impl Keymaps {
302+ /// Returns list of keys waiting to be disambiguated in current mode.
303+ pub fn pending(&self) -> &[KeyEvent] {
304+ self.0
305+ .values()
306+ .find_map(|keymap| match keymap.pending().is_empty() {
307+ true => None,
308+ false => Some(keymap.pending()),
309+ })
310+ .unwrap_or_default()
311+ }
312+}
313+
295impl Deref for Keymaps {
314impl Deref for Keymaps {
296 type Target = HashMap<Mode, Keymap>;
315 type Target = HashMap<Mode, Keymap>;
297
316
helix-term/src/ui/editor.rs+32−1
@@ -10,6 +10,8 @@ use helix_core::{
10 coords_at_pos,
10 coords_at_pos,
11 graphemes::{ensure_grapheme_boundary, next_grapheme_boundary},
11 graphemes::{ensure_grapheme_boundary, next_grapheme_boundary},
12 syntax::{self, HighlightEvent},
12 syntax::{self, HighlightEvent},
13+ unicode::segmentation::UnicodeSegmentation,
14+ unicode::width::UnicodeWidthStr,
13 LineEnding, Position, Range,
15 LineEnding, Position, Range,
14};
16};
15use helix_view::{
17use helix_view::{
@@ -627,7 +629,7 @@ impl EditorView {
627 }
629 }
628 _ => {
630 _ => {
629 // set the count
631 // set the count
630− cxt.count = cxt.editor.count.take();
632+ cxt.count = cxt.editor.count;
631 // TODO: edge case: 0j -> reset to 1
633 // TODO: edge case: 0j -> reset to 1
632 // if this fails, count was Some(0)
634 // if this fails, count was Some(0)
633 // debug_assert!(cxt.count != 0);
635 // debug_assert!(cxt.count != 0);
@@ -636,6 +638,9 @@ impl EditorView {
636 cxt.selected_register = cxt.editor.selected_register.take();
638 cxt.selected_register = cxt.editor.selected_register.take();
637
639
638 self.handle_keymap_event(mode, cxt, event);
640 self.handle_keymap_event(mode, cxt, event);
641+ if self.keymaps.pending().is_empty() {
642+ cxt.editor.count = None
643+ }
639 }
644 }
640 }
645 }
641 }
646 }
@@ -795,8 +800,12 @@ impl Component for EditorView {
795 info.render(area, surface, cx);
800 info.render(area, surface, cx);
796 }
801 }
797
802
803+ let key_width = 15u16; // for showing pending keys
804+ let mut status_msg_width = 0;
805+
798 // render status msg
806 // render status msg
799 if let Some((status_msg, severity)) = &cx.editor.status_msg {
807 if let Some((status_msg, severity)) = &cx.editor.status_msg {
808+ status_msg_width = status_msg.width();
800 use helix_view::editor::Severity;
809 use helix_view::editor::Severity;
801 let style = if *severity == Severity::Error {
810 let style = if *severity == Severity::Error {
802 cx.editor.theme.get("error")
811 cx.editor.theme.get("error")
@@ -812,6 +821,28 @@ impl Component for EditorView {
812 );
821 );
813 }
822 }
814
823
824+ if area.width.saturating_sub(status_msg_width as u16) > key_width {
825+ let mut disp = String::new();
826+ if let Some(count) = cx.editor.count {
827+ disp.push_str(&count.to_string())
828+ }
829+ for key in self.keymaps.pending() {
830+ let s = key.to_string();
831+ if s.graphemes(true).count() > 1 {
832+ disp.push_str(&format!("<{}>", s));
833+ } else {
834+ disp.push_str(&s);
835+ }
836+ }
837+ surface.set_string(
838+ area.x + area.width.saturating_sub(key_width),
839+ area.y + area.height.saturating_sub(1),
840+ disp.get(disp.len().saturating_sub(key_width as usize)..)
841+ .unwrap_or(&disp),
842+ cx.editor.theme.get("ui.text"),
843+ );
844+ }
845+
815 if let Some(completion) = &self.completion {
846 if let Some(completion) = &self.completion {
816 completion.render(area, surface, cx);
847 completion.render(area, surface, cx);
817 }
848 }