diff --git a/Cargo.lock b/Cargo.lock index a1f0a798..0fa6ad14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -238,15 +238,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" +checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" [[package]] name = "futures-executor" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79" +checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c" dependencies = [ "futures-core", "futures-task", @@ -255,15 +255,15 @@ dependencies = [ [[package]] name = "futures-task" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae" +checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2" [[package]] name = "futures-util" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" +checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" dependencies = [ "autocfg", "futures-core", @@ -475,9 +475,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "jsonrpc-core" -version = "17.1.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4467ab6dfa369b69e52bd0692e480c4d117410538526a57a304a0f2250fd95e" +checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ "futures-util", "log", @@ -1009,9 +1009,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2602b8af3767c285202012822834005f596c811042315fa7e9f5b12b2a43207" +checksum = "4b7b349f11a7047e6d1276853e612d152f5e8a352c61917887cc2169e2366b4c" dependencies = [ "autocfg", "bytes", diff --git a/book/book.toml b/book/book.toml index e6d3eee3..3ccaf71e 100644 --- a/book/book.toml +++ b/book/book.toml @@ -4,6 +4,7 @@ language = "en" multilingual = false src = "src" theme = "colibri" +edit-url-template = "https://github.com/helix-editor/helix/tree/master/book/{path}?mode=edit" [output.html] cname = "docs.helix-editor.com" diff --git a/helix-lsp/Cargo.toml b/helix-lsp/Cargo.toml index be099821..cf1f30a7 100644 --- a/helix-lsp/Cargo.toml +++ b/helix-lsp/Cargo.toml @@ -17,11 +17,11 @@ helix-core = { version = "0.3", path = "../helix-core" } anyhow = "1.0" futures-executor = "0.3" futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false } -jsonrpc-core = { version = "17.1", default-features = false } # don't pull in all of futures +jsonrpc-core = { version = "18.0", default-features = false } # don't pull in all of futures log = "0.4" lsp-types = { version = "0.89", features = ["proposed"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.8", features = ["full"] } +tokio = { version = "1.9", features = ["full"] } tokio-stream = "0.1.7" 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 @@ pub fn doc(&self) -> &'static str { 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, } @@ -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); +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; @@ -337,6 +356,7 @@ fn default() -> 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 @@ 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 @@ 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); @@ -671,6 +673,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 + } } } } @@ -830,8 +835,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") @@ -847,6 +856,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); } diff --git a/helix-view/src/keyboard.rs b/helix-view/src/keyboard.rs index 30a169e1..26a4d6d2 100644 --- a/helix-view/src/keyboard.rs +++ b/helix-view/src/keyboard.rs @@ -75,7 +75,7 @@ pub enum KeyCode { End, /// Page up key. PageUp, - /// Page dow key. + /// Page down key. PageDown, /// Tab key. Tab,