aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGokul Soumya2021-07-28 04:57:07 +0000
committerGitHub2021-07-28 04:57:07 +0000
commit1493313750bb4e8850da2a4c0d591ce04153106e (patch)
tree71c326601db777be5adc260e6aa8d00da4cf1327
parent581a3d42c81e65a8373329fd61ff6b7d0dae8c84 (diff)
Show pending keys in status line (#515)
* Show pending keys and counts in status line * Refactor pending key display
-rw-r--r--helix-term/src/keymap.rs19
-rw-r--r--helix-term/src/ui/editor.rs33
2 files changed, 51 insertions, 1 deletions
diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs
index 93cc5328..7328e729 100644
--- a/helix-term/src/keymap.rs
+++ b/helix-term/src/keymap.rs
@@ -234,6 +234,7 @@ pub struct Keymap {
/// Always a Node
#[serde(flatten)]
root: KeyTrie,
+ /// Stores pending keys waiting for the next key
#[serde(skip)]
state: Vec<KeyEvent>,
}
@@ -250,6 +251,11 @@ impl Keymap {
&self.root
}
+ /// Returns list of keys waiting to be disambiguated.
+ pub fn pending(&self) -> &[KeyEvent] {
+ &self.state
+ }
+
/// Lookup `key` in the keymap to try and find a command to execute
pub fn get(&mut self, key: KeyEvent) -> KeymapResult {
let &first = self.state.get(0).unwrap_or(&key);
@@ -292,6 +298,19 @@ impl Default for Keymap {
#[serde(transparent)]
pub struct Keymaps(pub HashMap<Mode, Keymap>);
+impl Keymaps {
+ /// Returns list of keys waiting to be disambiguated in current mode.
+ pub fn pending(&self) -> &[KeyEvent] {
+ self.0
+ .values()
+ .find_map(|keymap| match keymap.pending().is_empty() {
+ true => None,
+ false => Some(keymap.pending()),
+ })
+ .unwrap_or_default()
+ }
+}
+
impl Deref for Keymaps {
type Target = HashMap<Mode, Keymap>;
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index 78a54079..99b49309 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -10,6 +10,8 @@ use helix_core::{
coords_at_pos,
graphemes::{ensure_grapheme_boundary, next_grapheme_boundary},
syntax::{self, HighlightEvent},
+ unicode::segmentation::UnicodeSegmentation,
+ unicode::width::UnicodeWidthStr,
LineEnding, Position, Range,
};
use helix_view::{
@@ -627,7 +629,7 @@ impl EditorView {
}
_ => {
// set the count
- cxt.count = cxt.editor.count.take();
+ cxt.count = cxt.editor.count;
// TODO: edge case: 0j -> reset to 1
// if this fails, count was Some(0)
// debug_assert!(cxt.count != 0);
@@ -636,6 +638,9 @@ impl EditorView {
cxt.selected_register = cxt.editor.selected_register.take();
self.handle_keymap_event(mode, cxt, event);
+ if self.keymaps.pending().is_empty() {
+ cxt.editor.count = None
+ }
}
}
}
@@ -795,8 +800,12 @@ impl Component for EditorView {
info.render(area, surface, cx);
}
+ let key_width = 15u16; // for showing pending keys
+ let mut status_msg_width = 0;
+
// render status msg
if let Some((status_msg, severity)) = &cx.editor.status_msg {
+ status_msg_width = status_msg.width();
use helix_view::editor::Severity;
let style = if *severity == Severity::Error {
cx.editor.theme.get("error")
@@ -812,6 +821,28 @@ impl Component for EditorView {
);
}
+ if area.width.saturating_sub(status_msg_width as u16) > key_width {
+ let mut disp = String::new();
+ if let Some(count) = cx.editor.count {
+ disp.push_str(&count.to_string())
+ }
+ for key in self.keymaps.pending() {
+ let s = key.to_string();
+ if s.graphemes(true).count() > 1 {
+ disp.push_str(&format!("<{}>", s));
+ } else {
+ disp.push_str(&s);
+ }
+ }
+ surface.set_string(
+ area.x + area.width.saturating_sub(key_width),
+ area.y + area.height.saturating_sub(1),
+ disp.get(disp.len().saturating_sub(key_width as usize)..)
+ .unwrap_or(&disp),
+ cx.editor.theme.get("ui.text"),
+ );
+ }
+
if let Some(completion) = &self.completion {
completion.render(area, surface, cx);
}