on master help sign in
Show pending keys in status line (#515)

* Show pending keys and counts in status line * Refactor pending key display

commit1493313750bb4e8850da2a4c0d591ce04153106e authorGokul Soumya <gokulps15@gmail.com> dateWed 28 Jul 2021, 10:27 (5 years ago) parent581a3d4
2 files changed+51−1
helix-term/src/keymap.rs+19 helix-term/src/ui/editor.rs+32−1
helix-term/src/keymap.rs+19
@@ -234,6 +234,7 @@ pub struct Keymap {
234234 /// Always a Node
235235 #[serde(flatten)]
236236 root: KeyTrie,
237+ /// Stores pending keys waiting for the next key
237238 #[serde(skip)]
238239 state: Vec<KeyEvent>,
239240}
@@ -250,6 +251,11 @@ impl Keymap {
250251 &self.root
251252 }
252253
254+ /// Returns list of keys waiting to be disambiguated.
255+ pub fn pending(&self) -> &[KeyEvent] {
256+ &self.state
257+ }
258+
253259 /// Lookup `key` in the keymap to try and find a command to execute
254260 pub fn get(&mut self, key: KeyEvent) -> KeymapResult {
255261 let &first = self.state.get(0).unwrap_or(&key);
@@ -292,6 +298,19 @@ impl Default for Keymap {
292298#[serde(transparent)]
293299pub struct Keymaps(pub HashMap<Mode, Keymap>);
294300
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+
295314impl Deref for Keymaps {
296315 type Target = HashMap<Mode, Keymap>;
297316
helix-term/src/ui/editor.rs+32−1
@@ -10,6 +10,8 @@ use helix_core::{
1010 coords_at_pos,
1111 graphemes::{ensure_grapheme_boundary, next_grapheme_boundary},
1212 syntax::{self, HighlightEvent},
13+ unicode::segmentation::UnicodeSegmentation,
14+ unicode::width::UnicodeWidthStr,
1315 LineEnding, Position, Range,
1416};
1517use helix_view::{
@@ -627,7 +629,7 @@ impl EditorView {
627629 }
628630 _ => {
629631 // set the count
630− cxt.count = cxt.editor.count.take();
632+ cxt.count = cxt.editor.count;
631633 // TODO: edge case: 0j -> reset to 1
632634 // if this fails, count was Some(0)
633635 // debug_assert!(cxt.count != 0);
@@ -636,6 +638,9 @@ impl EditorView {
636638 cxt.selected_register = cxt.editor.selected_register.take();
637639
638640 self.handle_keymap_event(mode, cxt, event);
641+ if self.keymaps.pending().is_empty() {
642+ cxt.editor.count = None
643+ }
639644 }
640645 }
641646 }
@@ -795,8 +800,12 @@ impl Component for EditorView {
795800 info.render(area, surface, cx);
796801 }
797802
803+ let key_width = 15u16; // for showing pending keys
804+ let mut status_msg_width = 0;
805+
798806 // render status msg
799807 if let Some((status_msg, severity)) = &cx.editor.status_msg {
808+ status_msg_width = status_msg.width();
800809 use helix_view::editor::Severity;
801810 let style = if *severity == Severity::Error {
802811 cx.editor.theme.get("error")
@@ -812,6 +821,28 @@ impl Component for EditorView {
812821 );
813822 }
814823
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+
815846 if let Some(completion) = &self.completion {
816847 completion.render(area, surface, cx);
817848 }