@@ -1,3 +1,4 @@
1+use futures_util::FutureExt;
12use helix_lsp::{
23 block_on,
34 lsp::{self, CodeAction, CodeActionOrCommand, DiagnosticSeverity, NumberOrString},
@@ -14,7 +15,8 @@ use helix_view::{apply_transaction, document::Mode, editor::Action, theme::Style
1415use crate::{
1516 compositor::{self, Compositor},
1617 ui::{
17− self, lsp::SignatureHelp, overlay::overlayed, FileLocation, FilePicker, Popup, PromptEvent,
18+ self, lsp::SignatureHelp, overlay::overlayed, DynamicPicker, FileLocation, FilePicker,
19+ Popup, PromptEvent,
1820 },
1921};
2022
@@ -384,10 +386,48 @@ pub fn workspace_symbol_picker(cx: &mut Context) {
384386 cx.callback(
385387 future,
386388 move |_editor, compositor, response: Option<Vec<lsp::SymbolInformation>>| {
387− if let Some(symbols) = response {
388− let picker = sym_picker(symbols, current_url, offset_encoding);
389− compositor.push(Box::new(overlayed(picker)))
390− }
389+ let symbols = match response {
390+ Some(s) => s,
391+ None => return,
392+ };
393+ let picker = sym_picker(symbols, current_url, offset_encoding);
394+ let get_symbols = |query: String, editor: &mut Editor| {
395+ let doc = doc!(editor);
396+ let language_server = match doc.language_server() {
397+ Some(s) => s,
398+ None => {
399+ // This should not generally happen since the picker will not
400+ // even open in the first place if there is no server.
401+ return async move { Err(anyhow::anyhow!("LSP not active")) }.boxed();
402+ }
403+ };
404+ let symbol_request = match language_server.workspace_symbols(query) {
405+ Some(future) => future,
406+ None => {
407+ // This should also not happen since the language server must have
408+ // supported workspace symbols before to reach this block.
409+ return async move {
410+ Err(anyhow::anyhow!(
411+ "Language server does not support workspace symbols"
412+ ))
413+ }
414+ .boxed();
415+ }
416+ };
417+
418+ let future = async move {
419+ let json = symbol_request.await?;
420+ let response: Option<Vec<lsp::SymbolInformation>> =
421+ serde_json::from_value(json)?;
422+
423+ response.ok_or_else(|| {
424+ anyhow::anyhow!("No response for workspace symbols from language server")
425+ })
426+ };
427+ future.boxed()
428+ };
429+ let dyn_picker = DynamicPicker::new(picker, Box::new(get_symbols));
430+ compositor.push(Box::new(overlayed(dyn_picker)))
391431 },
392432 )
393433}