@@ -1052,6 +1052,77 @@ fn update(
10521052 }
10531053}
10541054
1055+fn lsp_workspace_command(
1056+ cx: &mut compositor::Context,
1057+ args: &[Cow<str>],
1058+ event: PromptEvent,
1059+) -> anyhow::Result<()> {
1060+ if event != PromptEvent::Validate {
1061+ return Ok(());
1062+ }
1063+
1064+ let (_, doc) = current!(cx.editor);
1065+
1066+ let language_server = match doc.language_server() {
1067+ Some(language_server) => language_server,
1068+ None => {
1069+ cx.editor
1070+ .set_status("Language server not active for current buffer");
1071+ return Ok(());
1072+ }
1073+ };
1074+
1075+ let options = match &language_server.capabilities().execute_command_provider {
1076+ Some(options) => options,
1077+ None => {
1078+ cx.editor
1079+ .set_status("Workspace commands are not supported for this language server");
1080+ return Ok(());
1081+ }
1082+ };
1083+ if args.is_empty() {
1084+ let commands = options
1085+ .commands
1086+ .iter()
1087+ .map(|command| helix_lsp::lsp::Command {
1088+ title: command.clone(),
1089+ command: command.clone(),
1090+ arguments: None,
1091+ })
1092+ .collect::<Vec<_>>();
1093+ let callback = async move {
1094+ let call: job::Callback = Callback::EditorCompositor(Box::new(
1095+ move |_editor: &mut Editor, compositor: &mut Compositor| {
1096+ let picker = ui::Picker::new(commands, (), |cx, command, _action| {
1097+ execute_lsp_command(cx.editor, command.clone());
1098+ });
1099+ compositor.push(Box::new(overlayed(picker)))
1100+ },
1101+ ));
1102+ Ok(call)
1103+ };
1104+ cx.jobs.callback(callback);
1105+ } else {
1106+ let command = args.join(" ");
1107+ if options.commands.iter().any(|c| c == &command) {
1108+ execute_lsp_command(
1109+ cx.editor,
1110+ helix_lsp::lsp::Command {
1111+ title: command.clone(),
1112+ arguments: None,
1113+ command,
1114+ },
1115+ );
1116+ } else {
1117+ cx.editor.set_status(format!(
1118+ "`{command}` is not supported for this language server"
1119+ ));
1120+ return Ok(());
1121+ }
1122+ }
1123+ Ok(())
1124+}
1125+
10551126fn lsp_restart(
10561127 cx: &mut compositor::Context,
10571128 _args: &[Cow<str>],
@@ -1987,6 +2058,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
19872058 fun: update,
19882059 completer: None,
19892060 },
2061+ TypableCommand {
2062+ name: "lsp-workspace-command",
2063+ aliases: &[],
2064+ doc: "Open workspace command picker",
2065+ fun: lsp_workspace_command,
2066+ completer: Some(completers::lsp_workspace_command),
2067+ },
19902068 TypableCommand {
19912069 name: "lsp-restart",
19922070 aliases: &[],