diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 2f41a2dc8..98c530854 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -434,6 +434,8 @@ impl MappableCommand { select_textobject_inner, "Select inside object", goto_next_function, "Goto next function", goto_prev_function, "Goto previous function", + goto_next_reference, "Goto next reference", + goto_prev_reference, "Goto previous reference", goto_next_class, "Goto next type definition", goto_prev_class, "Goto previous type definition", goto_next_parameter, "Goto next parameter", @@ -4709,6 +4711,14 @@ fn goto_prev_function(cx: &mut Context) { goto_ts_object_impl(cx, "function", Direction::Backward) } +fn goto_next_reference(cx: &mut Context) { + goto_reference_direction(cx, Direction::Forward) +} + +fn goto_prev_reference(cx: &mut Context) { + goto_reference_direction(cx, Direction::Backward) +} + fn goto_next_class(cx: &mut Context) { goto_ts_object_impl(cx, "class", Direction::Forward) } diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 0b0d1db4d..526ed9b60 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -15,7 +15,7 @@ use tui::{ use super::{align_view, push_jump, Align, Context, Editor, Open}; -use helix_core::{path, text_annotations::InlineAnnotation, Selection}; +use helix_core::{movement::Direction, path, text_annotations::InlineAnnotation, Selection}; use helix_view::{ document::{DocumentInlayHints, DocumentInlayHintsId, Mode}, editor::Action, @@ -1100,6 +1100,63 @@ pub fn goto_reference(cx: &mut Context) { ); } +pub fn goto_reference_direction(cx: &mut Context, direction: Direction) { + let (view, doc) = current!(cx.editor); + let language_server = language_server!(cx.editor, doc); + let offset_encoding = language_server.offset_encoding(); + + let pos = doc.position(view.id, offset_encoding); + + let future = match language_server.goto_reference(doc.identifier(), pos, None) { + Some(future) => future, + None => { + cx.editor + .set_error("Language server does not support goto-reference"); + return; + } + }; + + cx.callback( + future, + move |editor, _compositor, response: Option>| { + let items = response.unwrap_or_default(); + let (view, doc) = current!(editor); + let mut locations: Vec = items + .into_iter() + .filter(|loc| loc.uri.path() == doc.identifier().uri.path()) + .collect(); + let curr_pos = doc.position(view.id, offset_encoding); + + locations.sort_by(|a, b| { + a.range + .start + .line + .cmp(&b.range.start.line) + .then_with(|| a.range.start.character.cmp(&b.range.start.character)) + }); + let new_location = match direction { + Direction::Forward => locations + .into_iter() + .filter(|l| l.range.start.line > curr_pos.line) + .min_by_key(|l| l.range.start.line), + Direction::Backward => locations + .into_iter() + .filter(|l| l.range.start.line < curr_pos.line) + .max_by_key(|l| l.range.start.line), + }; + match new_location { + Some(location) => { + jump_to_location(editor, &location, offset_encoding, Action::Replace) + } + None => { + editor.set_error("No more references found in this file"); + return; + } + } + }, + ); +} + #[derive(PartialEq, Eq)] pub enum SignatureHelpInvoked { Manual, diff --git a/helix-term/src/keymap/default.rs b/helix-term/src/keymap/default.rs index 9bd002809..7862e1dee 100644 --- a/helix-term/src/keymap/default.rs +++ b/helix-term/src/keymap/default.rs @@ -107,6 +107,7 @@ pub fn default() -> HashMap { "g" => goto_prev_change, "G" => goto_first_change, "f" => goto_prev_function, + "r" => goto_prev_reference, "t" => goto_prev_class, "a" => goto_prev_parameter, "c" => goto_prev_comment, @@ -120,6 +121,7 @@ pub fn default() -> HashMap { "g" => goto_next_change, "G" => goto_last_change, "f" => goto_next_function, + "r" => goto_next_reference, "t" => goto_next_class, "a" => goto_next_parameter, "c" => goto_next_comment,