haskell.rs

 1use zed::lsp::{Symbol, SymbolKind};
 2use zed::{CodeLabel, CodeLabelSpan};
 3use zed_extension_api::{self as zed, Result};
 4
 5struct HaskellExtension;
 6
 7impl zed::Extension for HaskellExtension {
 8    fn new() -> Self {
 9        Self
10    }
11
12    fn language_server_command(
13        &mut self,
14        _language_server_id: &zed::LanguageServerId,
15        worktree: &zed::Worktree,
16    ) -> Result<zed::Command> {
17        let path = worktree
18            .which("haskell-language-server-wrapper")
19            .ok_or_else(|| "hls must be installed via ghcup".to_string())?;
20
21        Ok(zed::Command {
22            command: path,
23            args: vec!["lsp".to_string()],
24            env: worktree.shell_env(),
25        })
26    }
27
28    fn label_for_symbol(
29        &self,
30        _language_server_id: &zed::LanguageServerId,
31        symbol: Symbol,
32    ) -> Option<CodeLabel> {
33        let name = &symbol.name;
34
35        let (code, display_range, filter_range) = match symbol.kind {
36            SymbolKind::Struct => {
37                let data_decl = "data ";
38                let code = format!("{data_decl}{name} = A");
39                let display_range = 0..data_decl.len() + name.len();
40                let filter_range = data_decl.len()..display_range.end;
41                (code, display_range, filter_range)
42            }
43            SymbolKind::Constructor => {
44                let data_decl = "data A = ";
45                let code = format!("{data_decl}{name}");
46                let display_range = data_decl.len()..data_decl.len() + name.len();
47                let filter_range = 0..name.len();
48                (code, display_range, filter_range)
49            }
50            SymbolKind::Variable => {
51                let code = format!("{name} :: T");
52                let display_range = 0..name.len();
53                let filter_range = 0..name.len();
54                (code, display_range, filter_range)
55            }
56            _ => return None,
57        };
58
59        Some(CodeLabel {
60            spans: vec![CodeLabelSpan::code_range(display_range)],
61            filter_range: filter_range.into(),
62            code,
63        })
64    }
65}
66
67zed::register_extension!(HaskellExtension);