on master help sign in
Add support for showing all LSPs in --health (#7315)
d9d7f67Lorenzo Bellina
helix-term/src/health.rs+44−16
@@ -181,8 +181,8 @@ pub fn languages_all() -> std::io::Result<()> {
181 .language
181 .language
182 .sort_unstable_by_key(|l| l.language_id.clone());
182 .sort_unstable_by_key(|l| l.language_id.clone());
183
183
184− let check_binary = |cmd: Option<String>| match cmd {
184+ let check_binary = |cmd: Option<&str>| match cmd {
185− Some(cmd) => match which::which(&cmd) {
185+ Some(cmd) => match which::which(cmd) {
186 Ok(_) => column(&format!("✓ {}", cmd), Color::Green),
186 Ok(_) => column(&format!("✓ {}", cmd), Color::Green),
187 Err(_) => column(&format!("✘ {}", cmd), Color::Red),
187 Err(_) => column(&format!("✘ {}", cmd), Color::Red),
188 },
188 },
@@ -192,17 +192,15 @@ pub fn languages_all() -> std::io::Result<()> {
192 for lang in &syn_loader_conf.language {
192 for lang in &syn_loader_conf.language {
193 column(&lang.language_id, Color::Reset);
193 column(&lang.language_id, Color::Reset);
194
194
195− // TODO multiple language servers (check binary for each supported language server, not just the first)
196−
197− let lsp = lang.language_servers.first().and_then(|ls| {
195+ let mut cmds = lang.language_servers.iter().filter_map(|ls| {
198 syn_loader_conf
196 syn_loader_conf
199 .language_server
197 .language_server
200 .get(&ls.name)
198 .get(&ls.name)
201− .map(|config| config.command.clone())
199+ .map(|config| config.command.as_str())
202 });
200 });
203− check_binary(lsp);
201+ check_binary(cmds.next());
204
202
205− let dap = lang.debugger.as_ref().map(|dap| dap.command.to_string());
203+ let dap = lang.debugger.as_ref().map(|dap| dap.command.as_str());
206 check_binary(dap);
204 check_binary(dap);
207
205
208 for ts_feat in TsFeature::all() {
206 for ts_feat in TsFeature::all() {
@@ -213,6 +211,12 @@ pub fn languages_all() -> std::io::Result<()> {
213 }
211 }
214
212
215 writeln!(stdout)?;
213 writeln!(stdout)?;
214+
215+ for cmd in cmds {
216+ column("", Color::Reset);
217+ check_binary(Some(cmd));
218+ writeln!(stdout)?;
219+ }
216 }
220 }
217
221
218 Ok(())
222 Ok(())
@@ -268,15 +272,12 @@ pub fn language(lang_str: String) -> std::io::Result<()> {
268 }
272 }
269 };
273 };
270
274
271− // TODO multiple language servers
275+ probe_protocols(
272− probe_protocol(
273 "language server",
276 "language server",
274− lang.language_servers.first().and_then(|ls| {
277+ lang.language_servers
278+ .iter()
275− syn_loader_conf
279+ .filter_map(|ls| syn_loader_conf.language_server.get(&ls.name))
276− .language_server
277− .get(&ls.name)
278− .map(|config| config.command.clone())
280+ .map(|config| config.command.as_str()),
279− }),
280 )?;
281 )?;
281
282
282 probe_protocol(
283 probe_protocol(
@@ -291,6 +292,33 @@ pub fn language(lang_str: String) -> std::io::Result<()> {
291 Ok(())
292 Ok(())
292}
293}
293
294
295+/// Display diagnostics about multiple LSPs and DAPs.
296+fn probe_protocols<'a, I: Iterator<Item = &'a str> + 'a>(
297+ protocol_name: &str,
298+ server_cmds: I,
299+) -> std::io::Result<()> {
300+ let stdout = std::io::stdout();
301+ let mut stdout = stdout.lock();
302+ let mut server_cmds = server_cmds.peekable();
303+
304+ write!(stdout, "Configured {}s:", protocol_name)?;
305+ if server_cmds.peek().is_none() {
306+ writeln!(stdout, "{}", " None".yellow())?;
307+ return Ok(());
308+ }
309+ writeln!(stdout)?;
310+
311+ for cmd in server_cmds {
312+ let (path, icon) = match which::which(cmd) {
313+ Ok(path) => (path.display().to_string().green(), "✓".green()),
314+ Err(_) => (format!("'{}' not found in $PATH", cmd).red(), "✘".red()),
315+ };
316+ writeln!(stdout, " {} {}: {}", icon, cmd, path)?;
317+ }
318+
319+ Ok(())
320+}
321+
294/// Display diagnostics about LSP and DAP.
322/// Display diagnostics about LSP and DAP.
295fn probe_protocol(protocol_name: &str, server_cmd: Option<String>) -> std::io::Result<()> {
323fn probe_protocol(protocol_name: &str, server_cmd: Option<String>) -> std::io::Result<()> {
296 let stdout = std::io::stdout();
324 let stdout = std::io::stdout();