diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs index 9ae8f20e..ac66674a 100644 --- a/helix-lsp/src/client.rs +++ b/helix-lsp/src/client.rs @@ -299,6 +299,9 @@ impl Client { dynamic_registration: Some(false), ..Default::default() }), + execute_command: Some(lsp::DynamicRegistrationClientCapabilities { + dynamic_registration: Some(false), + }), ..Default::default() }), text_document: Some(lsp::TextDocumentClientCapabilities { diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 9e0c4d47..e2071ed9 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -265,6 +265,7 @@ impl MappableCommand { file_picker, "Open file picker", file_picker_in_current_directory, "Open file picker at current working directory", code_action, "Perform code action", + workspace_command_picker, "Open workspace command picker", buffer_picker, "Open buffer picker", jumplist_picker, "Open jumplist picker", symbol_picker, "Open symbol picker", diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 1113b44e..5a33e833 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -496,6 +496,42 @@ pub fn code_action(cx: &mut Context) { }, ) } + +impl ui::menu::Item for lsp::Command { + type Data = (); + fn label(&self, _data: &Self::Data) -> Spans { + self.title.as_str().into() + } +} + +pub fn workspace_command_picker(cx: &mut Context) { + let (_, doc) = current!(cx.editor); + + let language_server = language_server!(cx.editor, doc); + + let execute_command_provider = match &language_server.capabilities().execute_command_provider { + Some(p) => p, + None => return, + }; + let commands = execute_command_provider + .commands + .iter() + .map(|command| lsp::Command { + title: command.clone(), + command: command.clone(), + arguments: None, + }) + .collect::>(); + cx.callback = Some(Box::new( + move |compositor: &mut Compositor, _cx: &mut compositor::Context| { + let picker = ui::Picker::new(commands, (), move |cx, command, _action| { + execute_lsp_command(cx.editor, command.clone()); + }); + compositor.push(Box::new(overlayed(picker))) + }, + )); +} + pub fn execute_lsp_command(editor: &mut Editor, cmd: lsp::Command) { let doc = doc!(editor); let language_server = language_server!(editor, doc);