mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-22 09:26:19 +04:00
Show pending keys in status line (#515)
* Show pending keys and counts in status line * Refactor pending key display
This commit is contained in:
parent
581a3d42c8
commit
1493313750
@ -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 @@ pub fn root(&self) -> &KeyTrie {
|
||||
&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 @@ fn default() -> Self {
|
||||
#[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>;
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
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 @@ fn command_mode(&mut self, mode: Mode, cxt: &mut commands::Context, event: KeyEv
|
||||
}
|
||||
_ => {
|
||||
// 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 @@ fn command_mode(&mut self, mode: Mode, cxt: &mut commands::Context, event: KeyEv
|
||||
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 @@ fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
||||
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 @@ fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
||||
);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user