diff options
author | Nathan Vegdahl | 2021-07-28 21:11:08 +0000 |
---|---|---|
committer | Nathan Vegdahl | 2021-07-28 21:11:08 +0000 |
commit | a873e719d5dd1816434c16bb02d74f1e00ca847a (patch) | |
tree | 7ea6f6a37f5a7f9e12f3fab4c7e07cb21ae0ec0b /helix-term/src | |
parent | aead4e69a66ba004aa34e5a1a59e05239117250e (diff) | |
parent | b90450b9e8b995e96a723a5d8c7b179ad2967c5a (diff) |
Merge branch 'master' into great_line_ending_and_cursor_range_cleanup
Diffstat (limited to 'helix-term/src')
-rw-r--r-- | helix-term/src/commands.rs | 24 | ||||
-rw-r--r-- | helix-term/src/keymap.rs | 20 | ||||
-rw-r--r-- | helix-term/src/ui/editor.rs | 33 |
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); } |