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:
parent
914d294499
commit
d1f717eb8d
1 changed files with 45 additions and 5 deletions
|
@ -1,3 +1,4 @@
|
|||
use futures_util::FutureExt;
|
||||
use helix_lsp::{
|
||||
block_on,
|
||||
lsp::{self, CodeAction, CodeActionOrCommand, DiagnosticSeverity, NumberOrString},
|
||||
|
@ -14,7 +15,8 @@ use helix_view::{apply_transaction, document::Mode, editor::Action, theme::Style
|
|||
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)))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue