Re-request workspace symbols on keypress in picker

Most language servers limit the number of workspace symbols that
are returned with an empty query even though all symbols are
supposed to be returned, according to the spec (for perfomance
reasons). This patch adds a workspace symbol picker based on a
dynamic picker that allows re-requesting the symbols on every
keypress (i.e. when the picker query text changes). The old behavior
has been completely replaced, and I have only tested with
rust-analyzer so far.
This commit is contained in:
Gokul Soumya 2022-07-19 22:15:03 +05:30 committed by Blaž Hrastnik
parent 914d294499
commit d1f717eb8d

View File

@ -1,3 +1,4 @@
use futures_util::FutureExt;
use helix_lsp::{
block_on,
lsp::{self, CodeAction, CodeActionOrCommand, DiagnosticSeverity, NumberOrString},
@ -14,7 +15,8 @@
use crate::{
compositor::{self, Compositor},
ui::{
self, lsp::SignatureHelp, overlay::overlayed, FileLocation, FilePicker, Popup, PromptEvent,
self, lsp::SignatureHelp, overlay::overlayed, DynamicPicker, FileLocation, FilePicker,
Popup, PromptEvent,
},
};
@ -384,10 +386,48 @@ pub fn workspace_symbol_picker(cx: &mut Context) {
cx.callback(
future,
move |_editor, compositor, response: Option<Vec<lsp::SymbolInformation>>| {
if let Some(symbols) = response {
let picker = sym_picker(symbols, current_url, offset_encoding);
compositor.push(Box::new(overlayed(picker)))
}
let symbols = match response {
Some(s) => s,
None => return,
};
let picker = sym_picker(symbols, current_url, offset_encoding);
let get_symbols = |query: String, editor: &mut Editor| {
let doc = doc!(editor);
let language_server = match doc.language_server() {
Some(s) => s,
None => {
// This should not generally happen since the picker will not
// even open in the first place if there is no server.
return async move { Err(anyhow::anyhow!("LSP not active")) }.boxed();
}
};
let symbol_request = match language_server.workspace_symbols(query) {
Some(future) => future,
None => {
// This should also not happen since the language server must have
// supported workspace symbols before to reach this block.
return async move {
Err(anyhow::anyhow!(
"Language server does not support workspace symbols"
))
}
.boxed();
}
};
let future = async move {
let json = symbol_request.await?;
let response: Option<Vec<lsp::SymbolInformation>> =
serde_json::from_value(json)?;
response.ok_or_else(|| {
anyhow::anyhow!("No response for workspace symbols from language server")
})
};
future.boxed()
};
let dyn_picker = DynamicPicker::new(picker, Box::new(get_symbols));
compositor.push(Box::new(overlayed(dyn_picker)))
},
)
}