erlang: Update structure to accommodate multiple language servers (#14915)

Marshall Bowers created

This PR updates the structure of the Erlang extension to accommodate
multiple language servers.

Release Notes:

- N/A

Change summary

extensions/erlang/src/erlang.rs                     | 31 +++++++++-----
extensions/erlang/src/language_servers.rs           |  3 +
extensions/erlang/src/language_servers/erlang_ls.rs | 21 ++++++++++
3 files changed, 44 insertions(+), 11 deletions(-)

Detailed changes

extensions/erlang/src/erlang.rs 🔗

@@ -1,26 +1,35 @@
+mod language_servers;
+
 use zed_extension_api::{self as zed, Result};
 
-struct ErlangExtension;
+use crate::language_servers::ErlangLs;
+
+struct ErlangExtension {
+    erlang_ls: Option<ErlangLs>,
+}
 
 impl zed::Extension for ErlangExtension {
     fn new() -> Self {
-        Self
+        Self { erlang_ls: None }
     }
 
     fn language_server_command(
         &mut self,
-        _language_server_id: &zed::LanguageServerId,
+        language_server_id: &zed::LanguageServerId,
         worktree: &zed::Worktree,
     ) -> Result<zed::Command> {
-        let path = worktree
-            .which("erlang_ls")
-            .ok_or_else(|| "erlang_ls must be installed and available on your $PATH".to_string())?;
+        match language_server_id.as_ref() {
+            ErlangLs::LANGUAGE_SERVER_ID => {
+                let erlang_ls = self.erlang_ls.get_or_insert_with(|| ErlangLs::new());
 
-        Ok(zed::Command {
-            command: path,
-            args: Vec::new(),
-            env: Default::default(),
-        })
+                Ok(zed::Command {
+                    command: erlang_ls.language_server_binary_path(language_server_id, worktree)?,
+                    args: vec![],
+                    env: Default::default(),
+                })
+            }
+            language_server_id => Err(format!("unknown language server: {language_server_id}")),
+        }
     }
 }
 

extensions/erlang/src/language_servers/erlang_ls.rs 🔗

@@ -0,0 +1,21 @@
+use zed_extension_api::{self as zed, LanguageServerId, Result};
+
+pub struct ErlangLs;
+
+impl ErlangLs {
+    pub const LANGUAGE_SERVER_ID: &'static str = "erlang-ls";
+
+    pub fn new() -> Self {
+        Self
+    }
+
+    pub fn language_server_binary_path(
+        &mut self,
+        _language_server_id: &LanguageServerId,
+        worktree: &zed::Worktree,
+    ) -> Result<String> {
+        worktree
+            .which("erlang_ls")
+            .ok_or_else(|| "erlang_ls must be installed and available on your $PATH".to_string())
+    }
+}