mirror of https://github.com/helix-editor/helix
Show pending keys in status line (#515)
* Show pending keys and counts in status line * Refactor pending key displaypull/518/head
parent
581a3d42c8
commit
1493313750
|
@ -234,6 +234,7 @@ pub struct Keymap {
|
||||||
/// Always a Node
|
/// Always a Node
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
root: KeyTrie,
|
root: KeyTrie,
|
||||||
|
/// Stores pending keys waiting for the next key
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
state: Vec<KeyEvent>,
|
state: Vec<KeyEvent>,
|
||||||
}
|
}
|
||||||
|
@ -250,6 +251,11 @@ impl Keymap {
|
||||||
&self.root
|
&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
|
/// Lookup `key` in the keymap to try and find a command to execute
|
||||||
pub fn get(&mut self, key: KeyEvent) -> KeymapResult {
|
pub fn get(&mut self, key: KeyEvent) -> KeymapResult {
|
||||||
let &first = self.state.get(0).unwrap_or(&key);
|
let &first = self.state.get(0).unwrap_or(&key);
|
||||||
|
@ -292,6 +298,19 @@ impl Default for Keymap {
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
pub struct Keymaps(pub HashMap<Mode, Keymap>);
|
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 {
|
impl Deref for Keymaps {
|
||||||
type Target = HashMap<Mode, Keymap>;
|
type Target = HashMap<Mode, Keymap>;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ use helix_core::{
|
||||||
coords_at_pos,
|
coords_at_pos,
|
||||||
graphemes::{ensure_grapheme_boundary, next_grapheme_boundary},
|
graphemes::{ensure_grapheme_boundary, next_grapheme_boundary},
|
||||||
syntax::{self, HighlightEvent},
|
syntax::{self, HighlightEvent},
|
||||||
|
unicode::segmentation::UnicodeSegmentation,
|
||||||
|
unicode::width::UnicodeWidthStr,
|
||||||
LineEnding, Position, Range,
|
LineEnding, Position, Range,
|
||||||
};
|
};
|
||||||
use helix_view::{
|
use helix_view::{
|
||||||
|
@ -627,7 +629,7 @@ impl EditorView {
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// set the count
|
// set the count
|
||||||
cxt.count = cxt.editor.count.take();
|
cxt.count = cxt.editor.count;
|
||||||
// TODO: edge case: 0j -> reset to 1
|
// TODO: edge case: 0j -> reset to 1
|
||||||
// if this fails, count was Some(0)
|
// if this fails, count was Some(0)
|
||||||
// debug_assert!(cxt.count != 0);
|
// debug_assert!(cxt.count != 0);
|
||||||
|
@ -636,6 +638,9 @@ impl EditorView {
|
||||||
cxt.selected_register = cxt.editor.selected_register.take();
|
cxt.selected_register = cxt.editor.selected_register.take();
|
||||||
|
|
||||||
self.handle_keymap_event(mode, cxt, event);
|
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);
|
info.render(area, surface, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let key_width = 15u16; // for showing pending keys
|
||||||
|
let mut status_msg_width = 0;
|
||||||
|
|
||||||
// render status msg
|
// render status msg
|
||||||
if let Some((status_msg, severity)) = &cx.editor.status_msg {
|
if let Some((status_msg, severity)) = &cx.editor.status_msg {
|
||||||
|
status_msg_width = status_msg.width();
|
||||||
use helix_view::editor::Severity;
|
use helix_view::editor::Severity;
|
||||||
let style = if *severity == Severity::Error {
|
let style = if *severity == Severity::Error {
|
||||||
cx.editor.theme.get("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 {
|
if let Some(completion) = &self.completion {
|
||||||
completion.render(area, surface, cx);
|
completion.render(area, surface, cx);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue