aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/commands
diff options
context:
space:
mode:
authorGokul Soumya2022-07-19 16:45:03 +0000
committerBlaž Hrastnik2022-12-15 08:52:44 +0000
commitd1f717eb8d02205ce224292f157bfe1bddd1f6db (patch)
tree61687b1ce10a2f6af90ae81c7bce0c4fd4bff13d /helix-term/src/commands
parent914d2944997e11cf76eeabfe43f9031aeb2b1721 (diff)
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.
Diffstat (limited to 'helix-term/src/commands')
-rw-r--r--helix-term/src/commands/lsp.rs50
1 files changed, 45 insertions, 5 deletions
diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs
index 810e3adf..8052dcac 100644
--- a/helix-term/src/commands/lsp.rs
+++ b/helix-term/src/commands/lsp.rs
@@ -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)))
},
)
}