@@ -9,7 +9,8 @@ pub use lsp::{Position, Url};
9pub use lsp_types as lsp;
9pub use lsp_types as lsp;
11use futures_util::stream::select_all::SelectAll;
11use futures_util::stream::select_all::SelectAll;
12−use helix_core::syntax::LanguageConfiguration;
12+use helix_core::syntax::{LanguageConfiguration, LanguageServerConfiguration};
13+use tokio::sync::mpsc::UnboundedReceiver;
15 collections::{hash_map::Entry, HashMap},
16 collections::{hash_map::Entry, HashMap},
@@ -335,6 +336,33 @@ impl Registry {
335 .map(|(_, client)| client.as_ref())
336 .map(|(_, client)| client.as_ref())
341+ language_config: &LanguageConfiguration,
342+ ) -> Result<Option<Arc<Client>>> {
343+ let config = match &language_config.language_server {
344+ Some(config) => config,
345+ None => return Ok(None),
348+ let scope = language_config.scope.clone();
350+ match self.inner.entry(scope) {
351+ Entry::Vacant(_) => Ok(None),
352+ Entry::Occupied(mut entry) => {
353+ // initialize a new client
354+ let id = self.counter.fetch_add(1, Ordering::Relaxed);
356+ let NewClientResult(client, incoming) = start_client(id, language_config, config)?;
357+ self.incoming.push(UnboundedReceiverStream::new(incoming));
359+ entry.insert((id, client.clone()));
338 pub fn get(&mut self, language_config: &LanguageConfiguration) -> Result<Option<Arc<Client>>> {
366 pub fn get(&mut self, language_config: &LanguageConfiguration) -> Result<Option<Arc<Client>>> {
339 let config = match &language_config.language_server {
367 let config = match &language_config.language_server {
340 Some(config) => config,
368 Some(config) => config,
@@ -346,43 +374,9 @@ impl Registry {
346 Entry::Vacant(entry) => {
374 Entry::Vacant(entry) => {
347 // initialize a new client
375 // initialize a new client
348 let id = self.counter.fetch_add(1, Ordering::Relaxed);
376 let id = self.counter.fetch_add(1, Ordering::Relaxed);
349− let (client, incoming, initialize_notify) = Client::start(
377+
350− &config.command,
378+ let NewClientResult(client, incoming) = start_client(id, language_config, config)?;
352− language_config.config.clone(),
353− &language_config.roots,
357 self.incoming.push(UnboundedReceiverStream::new(incoming));
379 self.incoming.push(UnboundedReceiverStream::new(incoming));
358− let client = Arc::new(client);
360− // Initialize the client asynchronously
361− let _client = client.clone();
362− tokio::spawn(async move {
363− use futures_util::TryFutureExt;
366− .get_or_try_init(|| {
369− .map_ok(|response| response.capabilities)
373− if let Err(e) = value {
374− log::error!("failed to initialize language server: {}", e);
378− // next up, notify<initialized>
380− .notify::<lsp::notification::Initialized>(lsp::InitializedParams {})
384− initialize_notify.notify_one();
387 entry.insert((id, client.clone()));
381 entry.insert((id, client.clone()));
388 Ok(Some(client))
382 Ok(Some(client))
@@ -473,6 +467,56 @@ impl LspProgressMap {
470+struct NewClientResult(Arc<Client>, UnboundedReceiver<(usize, Call)>);
472+/// start_client takes both a LanguageConfiguration and a LanguageServerConfiguration to ensure that
473+/// it is only called when it makes sense.
476+ config: &LanguageConfiguration,
477+ ls_config: &LanguageServerConfiguration,
478+) -> Result<NewClientResult> {
479+ let (client, incoming, initialize_notify) = Client::start(
482+ config.config.clone(),
488+ let client = Arc::new(client);
490+ // Initialize the client asynchronously
491+ let _client = client.clone();
492+ tokio::spawn(async move {
493+ use futures_util::TryFutureExt;
496+ .get_or_try_init(|| {
499+ .map_ok(|response| response.capabilities)
503+ if let Err(e) = value {
504+ log::error!("failed to initialize language server: {}", e);
508+ // next up, notify<initialized>
510+ .notify::<lsp::notification::Initialized>(lsp::InitializedParams {})
514+ initialize_notify.notify_one();
517+ Ok(NewClientResult(client, incoming))
476#[cfg(test)]
520#[cfg(test)]
477mod tests {
521mod tests {
478 use super::{lsp, util::*, OffsetEncoding};
522 use super::{lsp, util::*, OffsetEncoding};