aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src
diff options
context:
space:
mode:
Diffstat (limited to 'helix-term/src')
-rw-r--r--helix-term/src/commands.rs24
-rw-r--r--helix-term/src/keymap.rs20
-rw-r--r--helix-term/src/ui/editor.rs33
3 files changed, 72 insertions, 5 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index a37d2d26..acf1c454 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -228,13 +228,14 @@ impl Command {
goto_definition, "Goto definition",
goto_type_definition, "Goto type definition",
goto_implementation, "Goto implementation",
- goto_file_start, "Goto file start",
+ goto_file_start, "Goto file start/line",
goto_file_end, "Goto file end",
goto_reference, "Goto references",
goto_window_top, "Goto window top",
goto_window_middle, "Goto window middle",
goto_window_bottom, "Goto window bottom",
goto_last_accessed_file, "Goto last accessed file",
+ goto_line, "Goto line",
goto_first_diag, "Goto first diagnostic",
goto_last_diag, "Goto last diagnostic",
goto_next_diag, "Goto next diagnostic",
@@ -553,9 +554,13 @@ fn move_next_long_word_end(cx: &mut Context) {
}
fn goto_file_start(cx: &mut Context) {
- push_jump(cx.editor);
- let (view, doc) = current!(cx.editor);
- doc.set_selection(view.id, Selection::point(0));
+ if cx.count.is_some() {
+ goto_line(cx);
+ } else {
+ push_jump(cx.editor);
+ let (view, doc) = current!(cx.editor);
+ doc.set_selection(view.id, Selection::point(0));
+ }
}
fn goto_file_end(cx: &mut Context) {
@@ -2442,6 +2447,17 @@ fn push_jump(editor: &mut Editor) {
view.jumps.push(jump);
}
+fn goto_line(cx: &mut Context) {
+ if let Some(count) = cx.count {
+ push_jump(cx.editor);
+
+ let (view, doc) = current!(cx.editor);
+ let line_idx = std::cmp::min(count.get() - 1, doc.text().len_lines().saturating_sub(2));
+ let pos = doc.text().line_to_char(line_idx);
+ doc.set_selection(view.id, Selection::point(pos));
+ }
+}
+
fn goto_last_accessed_file(cx: &mut Context) {
let alternate_file = view!(cx.editor).last_accessed_doc;
if let Some(alt) = alternate_file {
diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs
index 93cc5328..95479340 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>;
@@ -337,6 +356,7 @@ impl Default for Keymaps {
"E" => move_next_long_word_end,
"v" => select_mode,
+ "G" => goto_line,
"g" => { "Goto"
"g" => goto_file_start,
"e" => goto_file_end,
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index 3e131bf1..d5c907b8 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, next_grapheme_boundary, prev_grapheme_boundary},
syntax::{self, HighlightEvent},
+ unicode::segmentation::UnicodeSegmentation,
+ unicode::width::UnicodeWidthStr,
LineEnding, Position, Range,
};
use helix_view::{
@@ -662,7 +664,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);
@@ -671,6 +673,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
+ }
}
}
}
@@ -830,8 +835,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")
@@ -847,6 +856,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);
}