feat: highlight / select symbol under cursor using LSP textDocument/documentHighlight (#2738)

* feat: highlight symbol under cursor using LSP textDocument/documentHighlight

* fix: please clippy

* fix: shorter description and code style
pull/2892/head
lazytanuki 2 years ago committed by GitHub
parent fde9e034d4
commit 096abdd19b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -759,6 +759,26 @@ impl Client {
Ok(response.unwrap_or_default())
}
pub fn text_document_document_highlight(
&self,
text_document: lsp::TextDocumentIdentifier,
position: lsp::Position,
work_done_token: Option<lsp::ProgressToken>,
) -> impl Future<Output = Result<Value>> {
let params = lsp::DocumentHighlightParams {
text_document_position_params: lsp::TextDocumentPositionParams {
text_document,
position,
},
work_done_progress_params: lsp::WorkDoneProgressParams { work_done_token },
partial_result_params: lsp::PartialResultParams {
partial_result_token: None,
},
};
self.call::<lsp::request::DocumentHighlightRequest>(params)
}
fn goto_request<
T: lsp::request::Request<
Params = lsp::GotoDefinitionParams,

@ -263,6 +263,7 @@ impl MappableCommand {
code_action, "Perform code action",
buffer_picker, "Open buffer picker",
symbol_picker, "Open symbol picker",
select_references_to_symbol_under_cursor, "Select symbol references",
workspace_symbol_picker, "Open workspace symbol picker",
last_picker, "Open last picker",
prepend_to_line, "Insert at start of line",

@ -655,6 +655,7 @@ pub fn signature_help(cx: &mut Context) {
},
);
}
pub fn hover(cx: &mut Context) {
let (view, doc) = current!(cx.editor);
let language_server = language_server!(cx.editor, doc);
@ -704,6 +705,7 @@ pub fn hover(cx: &mut Context) {
},
);
}
pub fn rename_symbol(cx: &mut Context) {
ui::prompt(
cx,
@ -729,3 +731,44 @@ pub fn rename_symbol(cx: &mut Context) {
},
);
}
pub fn select_references_to_symbol_under_cursor(cx: &mut Context) {
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 = language_server.text_document_document_highlight(doc.identifier(), pos, None);
cx.callback(
future,
move |editor, _compositor, response: Option<Vec<lsp::DocumentHighlight>>| {
let document_highlights = match response {
Some(highlights) if !highlights.is_empty() => highlights,
_ => return,
};
let (view, doc) = current!(editor);
let language_server = language_server!(editor, doc);
let offset_encoding = language_server.offset_encoding();
let text = doc.text();
let pos = doc.selection(view.id).primary().head;
// We must find the range that contains our primary cursor to prevent our primary cursor to move
let mut primary_index = 0;
let ranges = document_highlights
.iter()
.filter_map(|highlight| lsp_range_to_range(text, highlight.range, offset_encoding))
.enumerate()
.map(|(i, range)| {
if range.contains(pos) {
primary_index = i;
}
range
})
.collect();
let selection = Selection::new(ranges, primary_index);
doc.set_selection(view.id, selection);
},
);
}

@ -259,6 +259,7 @@ pub fn default() -> HashMap<Mode, Keymap> {
"/" => global_search,
"k" => hover,
"r" => rename_symbol,
"h" => select_references_to_symbol_under_cursor,
"?" => command_palette,
},
"z" => { "View"

Loading…
Cancel
Save