From f976c004e2efa4cb583b06827b44fef84bf925f5 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 8 Mar 2023 01:34:31 +0100 Subject: [PATCH] Allow LSP server to be stopped (#5964) --- book/src/generated/typable-cmd.md | 1 + helix-lsp/src/lib.rs | 10 ++++++++ helix-term/src/commands/typed.rs | 38 +++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/book/src/generated/typable-cmd.md b/book/src/generated/typable-cmd.md index ab36997c7..badadc43d 100644 --- a/book/src/generated/typable-cmd.md +++ b/book/src/generated/typable-cmd.md @@ -49,6 +49,7 @@ | `:update` | Write changes only if the file has been modified. | | `:lsp-workspace-command` | Open workspace command picker | | `:lsp-restart` | Restarts the Language Server that is in use by the current doc | +| `:lsp-stop` | Stops the Language Server that is in use by the current doc | | `:tree-sitter-scopes` | Display tree sitter scopes, primarily for theming and development. | | `:debug-start`, `:dbg` | Start a debug session from a given template with given parameters. | | `:debug-remote`, `:dbg-tcp` | Connect to a debug adapter by TCP address and start a debugging session from a given template with given parameters. | diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs index 341d4a547..ca9d17ace 100644 --- a/helix-lsp/src/lib.rs +++ b/helix-lsp/src/lib.rs @@ -476,6 +476,16 @@ impl Registry { } } + pub fn stop(&mut self, language_config: &LanguageConfiguration) { + let scope = language_config.scope.clone(); + + if let Some((_, client)) = self.inner.remove(&scope) { + tokio::spawn(async move { + let _ = client.force_shutdown().await; + }); + } + } + pub fn get( &mut self, language_config: &LanguageConfiguration, diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index b0fd18a76..0ddca6df7 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1354,6 +1354,37 @@ fn lsp_restart( Ok(()) } +fn lsp_stop( + cx: &mut compositor::Context, + _args: &[Cow], + event: PromptEvent, +) -> anyhow::Result<()> { + if event != PromptEvent::Validate { + return Ok(()); + } + + let doc = doc!(cx.editor); + + let ls_id = doc + .language_server() + .map(|ls| ls.id()) + .context("LSP not running for the current document")?; + + let config = doc + .language_config() + .context("LSP not defined for the current document")?; + cx.editor.language_servers.stop(config); + + for doc in cx.editor.documents_mut() { + if doc.language_server().map_or(false, |ls| ls.id() == ls_id) { + doc.set_language_server(None); + doc.set_diagnostics(Default::default()); + } + } + + Ok(()) +} + fn tree_sitter_scopes( cx: &mut compositor::Context, _args: &[Cow], @@ -2349,6 +2380,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[ fun: lsp_restart, completer: None, }, + TypableCommand { + name: "lsp-stop", + aliases: &[], + doc: "Stops the Language Server that is in use by the current doc", + fun: lsp_stop, + completer: None, + }, TypableCommand { name: "tree-sitter-scopes", aliases: &[],