diff options
author | Blaž Hrastnik | 2021-03-16 14:09:04 +0000 |
---|---|---|
committer | GitHub | 2021-03-16 14:09:04 +0000 |
commit | 8dc0b18e35cdfdd76f435dcd43c1cfd5a3f0c7f7 (patch) | |
tree | a26c6025d45658b4d85d6917ea82489d6ba8fb2e /helix-term/src | |
parent | d8599f3a140eca7cd14f47e9b64f1ae9d829a0eb (diff) | |
parent | e3ec5e31ec005e33da4c848b4272e81a6d21a5f0 (diff) |
Merge pull request #8 from helix-editor/gd
Goto
Diffstat (limited to 'helix-term/src')
-rw-r--r-- | helix-term/src/commands.rs | 106 | ||||
-rw-r--r-- | helix-term/src/keymap.rs | 8 |
2 files changed, 112 insertions, 2 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 353d79cc..3e90fb63 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -13,6 +13,8 @@ use once_cell::sync::Lazy; use crate::compositor::Compositor; use crate::ui::{self, Popup, Prompt, PromptEvent}; +use std::path::PathBuf; + use helix_view::{ document::Mode, view::{View, PADDING}, @@ -21,6 +23,8 @@ use helix_view::{ use crossterm::event::{KeyCode, KeyEvent}; +use helix_lsp::lsp; + pub struct Context<'a> { pub count: usize, pub editor: &'a mut Editor, @@ -846,6 +850,108 @@ pub fn exit_select_mode(cx: &mut Context) { cx.doc().mode = Mode::Normal; } +fn goto(cx: &mut Context, locations: Vec<lsp::Location>) { + let executor = cx.executor; + let doc = cx.doc(); + + doc.mode = Mode::Normal; + + match locations.as_slice() { + [location] => { + cx.editor + .open(PathBuf::from(location.uri.path()), cx.executor); + let doc = cx.doc(); + let definition_pos = location.range.start; + let new_pos = helix_lsp::util::lsp_pos_to_pos(doc.text().slice(..), definition_pos); + doc.set_selection(Selection::point(new_pos)); + } + [] => (), // maybe show user message that no definition was found? + _locations => { + let mut picker = ui::Picker::new( + locations, + |item| { + let file = item.uri.as_str(); + let line = item.range.start.line; + format!("{}:{}", file, line).into() + }, + move |editor: &mut Editor, item| { + editor.open(PathBuf::from(item.uri.path()), &executor); + let mut doc = &mut editor.view_mut().doc; + let definition_pos = item.range.start; + let new_pos = + helix_lsp::util::lsp_pos_to_pos(doc.text().slice(..), definition_pos); + doc.set_selection(Selection::point(new_pos)); + }, + ); + cx.push_layer(Box::new(picker)); + } + } +} + +pub fn goto_definition(cx: &mut Context) { + let doc = cx.doc(); + let language_server = match doc.language_server.as_ref() { + Some(language_server) => language_server, + None => return, + }; + + // TODO: blocking here is not ideal + let pos = helix_lsp::util::pos_to_lsp_pos(doc.text().slice(..), doc.selection().cursor()); + + // TODO: handle fails + let res = + smol::block_on(language_server.goto_definition(doc.identifier(), pos)).unwrap_or_default(); + goto(cx, res); +} + +pub fn goto_type_definition(cx: &mut Context) { + let doc = cx.doc(); + let language_server = match doc.language_server.as_ref() { + Some(language_server) => language_server, + None => return, + }; + + // TODO: blocking here is not ideal + let pos = helix_lsp::util::pos_to_lsp_pos(doc.text().slice(..), doc.selection().cursor()); + + // TODO: handle fails + let res = smol::block_on(language_server.goto_type_definition(doc.identifier(), pos)) + .unwrap_or_default(); + goto(cx, res); +} + +pub fn goto_implementation(cx: &mut Context) { + let doc = cx.doc(); + let language_server = match doc.language_server.as_ref() { + Some(language_server) => language_server, + None => return, + }; + + // TODO: blocking here is not ideal + let pos = helix_lsp::util::pos_to_lsp_pos(doc.text().slice(..), doc.selection().cursor()); + + // TODO: handle fails + let res = smol::block_on(language_server.goto_implementation(doc.identifier(), pos)) + .unwrap_or_default(); + goto(cx, res); +} + +pub fn goto_reference(cx: &mut Context) { + let doc = cx.doc(); + let language_server = match doc.language_server.as_ref() { + Some(language_server) => language_server, + None => return, + }; + + // TODO: blocking here is not ideal + let pos = helix_lsp::util::pos_to_lsp_pos(doc.text().slice(..), doc.selection().cursor()); + + // TODO: handle fails + let res = + smol::block_on(language_server.goto_reference(doc.identifier(), pos)).unwrap_or_default(); + goto(cx, res); +} + // NOTE: Transactions in this module get appended to history when we switch back to normal mode. pub mod insert { use super::*; diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 67490003..d9fe348f 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -311,8 +311,12 @@ pub fn default() -> Keymaps { code: KeyCode::Esc, modifiers: Modifiers::NONE } => commands::normal_mode as Command, - key!('g') => commands::move_file_start as Command, - key!('e') => commands::move_file_end as Command, + key!('g') => commands::move_file_start, + key!('e') => commands::move_file_end, + key!('d') => commands::goto_definition, + key!('t') => commands::goto_type_definition, + key!('r') => commands::goto_reference, + key!('i') => commands::goto_implementation, ), ) } |