Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-config/src/definition/lsp.rs')
-rw-r--r--helix-config/src/definition/lsp.rs266
1 files changed, 266 insertions, 0 deletions
diff --git a/helix-config/src/definition/lsp.rs b/helix-config/src/definition/lsp.rs
new file mode 100644
index 00000000..2c6845f4
--- /dev/null
+++ b/helix-config/src/definition/lsp.rs
@@ -0,0 +1,266 @@
+use std::fmt::{self, Display};
+
+use serde::{Deserialize, Serialize};
+
+use crate::*;
+
+/// Describes the severity level of a [`Diagnostic`].
+#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Deserialize, Serialize)]
+pub enum Severity {
+ Hint,
+ Info,
+ Warning,
+ Error,
+}
+
+impl Ty for Severity {
+ fn from_value(val: Value) -> anyhow::Result<Self> {
+ let val: String = val.typed()?;
+ match &*val {
+ "hint" => Ok(Severity::Hint),
+ "info" => Ok(Severity::Info),
+ "warning" => Ok(Severity::Warning),
+ "error" => Ok(Severity::Error),
+ _ => bail!("expected one of 'hint', 'info', 'warning' or 'error' (got {val:?})"),
+ }
+ }
+
+ fn to_value(&self) -> Value {
+ match self {
+ Severity::Hint => "hint".into(),
+ Severity::Info => "info".into(),
+ Severity::Warning => "warning".into(),
+ Severity::Error => "error".into(),
+ }
+ }
+}
+
+// TODO: move to stdx
+/// Helper macro that automatically generates an array
+/// that contains all variants of an enum
+macro_rules! variant_list {
+ (
+ $(#[$outer:meta])*
+ $vis: vis enum $name: ident {
+ $($(#[$inner: meta])* $variant: ident $(= $_: literal)?),*$(,)?
+ }
+ ) => {
+ $(#[$outer])*
+ $vis enum $name {
+ $($(#[$inner])* $variant),*
+ }
+ impl $name {
+ $vis const ALL: &[$name] = &[$(Self::$variant),*];
+ }
+ }
+}
+variant_list! {
+ #[derive(Clone, Copy, PartialEq, Eq, Hash)]
+ pub enum LanguageServerFeature {
+ Format,
+ GotoDeclaration,
+ GotoDefinition,
+ GotoTypeDefinition,
+ GotoReference,
+ GotoImplementation,
+ // Goto, use bitflags, combining previous Goto members?
+ SignatureHelp,
+ Hover,
+ DocumentHighlight,
+ Completion,
+ CodeAction,
+ WorkspaceCommand,
+ DocumentSymbols,
+ WorkspaceSymbols,
+ // Symbols, use bitflags, see above?
+ Diagnostics,
+ RenameSymbol,
+ InlayHints,
+ }
+}
+
+impl LanguageServerFeature {
+ fn to_str(self) -> &'static str {
+ use LanguageServerFeature::*;
+
+ match self {
+ Format => "format",
+ GotoDeclaration => "goto-declaration",
+ GotoDefinition => "goto-definition",
+ GotoTypeDefinition => "goto-type-definition",
+ GotoReference => "goto-reference",
+ GotoImplementation => "goto-implementation",
+ SignatureHelp => "signature-help",
+ Hover => "hover",
+ DocumentHighlight => "document-highlight",
+ Completion => "completion",
+ CodeAction => "code-action",
+ WorkspaceCommand => "workspace-command",
+ DocumentSymbols => "document-symbols",
+ WorkspaceSymbols => "workspace-symbols",
+ Diagnostics => "diagnostics",
+ RenameSymbol => "rename-symbol",
+ InlayHints => "inlay-hints",
+ }
+ }
+ fn description(self) -> &'static str {
+ use LanguageServerFeature::*;
+
+ match self {
+ Format => "Use this language server for autoformatting.",
+ GotoDeclaration => "Use this language server for the goto_declaration command.",
+ GotoDefinition => "Use this language server for the goto_definition command.",
+ GotoTypeDefinition => "Use this language server for the goto_type_definition command.",
+ GotoReference => "Use this language server for the goto_reference command.",
+ GotoImplementation => "Use this language server for the goto_implementation command.",
+ SignatureHelp => "Use this language server to display signature help.",
+ Hover => "Use this language server to display hover information.",
+ DocumentHighlight => {
+ "Use this language server for the select_references_to_symbol_under_cursor command."
+ }
+ Completion => "Request completion items from this language server.",
+ CodeAction => "Use this language server for the code_action command.",
+ WorkspaceCommand => "Use this language server for :lsp-workspace-command.",
+ DocumentSymbols => "Use this language server for the symbol_picker command.",
+ WorkspaceSymbols => "Use this language server for the workspace_symbol_picker command.",
+ Diagnostics => "Display diagnostics emitted by this language server.",
+ RenameSymbol => "Use this language server for the rename_symbol command.",
+ InlayHints => "Display inlay hints form this language server.",
+ }
+ }
+}
+
+impl Display for LanguageServerFeature {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let feature = self.to_str();
+ write!(f, "{feature}",)
+ }
+}
+
+impl Debug for LanguageServerFeature {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{self}")
+ }
+}
+
+impl Ty for LanguageServerFeature {
+ fn from_value(val: Value) -> anyhow::Result<Self> {
+ let val: String = val.typed()?;
+ use LanguageServerFeature::*;
+
+ match &*val {
+ "format" => Ok(Format),
+ "goto-declaration" => Ok(GotoDeclaration),
+ "goto-definition" => Ok(GotoDefinition),
+ "goto-type-definition" => Ok(GotoTypeDefinition),
+ "goto-reference" => Ok(GotoReference),
+ "goto-implementation" => Ok(GotoImplementation),
+ "signature-help" => Ok(SignatureHelp),
+ "hover" => Ok(Hover),
+ "document-highlight" => Ok(DocumentHighlight),
+ "completion" => Ok(Completion),
+ "code-action" => Ok(CodeAction),
+ "workspace-command" => Ok(WorkspaceCommand),
+ "document-symbols" => Ok(DocumentSymbols),
+ "workspace-symbols" => Ok(WorkspaceSymbols),
+ "diagnostics" => Ok(Diagnostics),
+ "rename-symbol" => Ok(RenameSymbol),
+ "inlay-hints" => Ok(InlayHints),
+ _ => bail!("invalid language server feature {val}"),
+ }
+ }
+
+ fn to_value(&self) -> Value {
+ Value::String(self.to_str().into())
+ }
+}
+
+pub fn init_language_server_config(registry: &mut OptionRegistry, languag_server: &str) {
+ registry.register(
+ &format!("language-servers.{languag_server}.active"),
+ "Wether this language servers is used for a buffer",
+ false,
+ );
+ for &feature in LanguageServerFeature::ALL {
+ registry.register(
+ &format!("language-servers.{languag_server}.{feature}"),
+ feature.description(),
+ true,
+ );
+ }
+}
+
+options! {
+ struct LspConfig {
+ /// Enables LSP integration. Setting to false will completely disable language servers.
+ #[name = "lsp.enable"]
+ #[read = copy]
+ enable: bool = true,
+ /// Enables LSP integration. Setting to false will completely disable language servers.
+ #[name = "lsp.display-messages"]
+ #[read = copy]
+ display_messages: bool = false,
+ /// Enable automatic popup of signature help (parameter hints)
+ #[name = "lsp.auto-signature-help"]
+ #[read = copy]
+ auto_signature_help: bool = true,
+ /// Enable automatic popup of signature help (parameter hints)
+ #[name = "lsp.display-inlay-hints"]
+ #[read = copy]
+ display_inlay_hints: bool = false,
+ /// Display docs under signature help popup
+ #[name = "lsp.display-signature-help-docs"]
+ #[read = copy]
+ display_signature_help_docs: bool = true,
+ /// Enables snippet completions. Requires a server restart
+ /// (`:lsp-restart`) to take effect after `:config-reload`/`:set`.
+ #[name = "lsp.snippets"]
+ #[read = copy]
+ snippets: bool = true,
+ /// Include declaration in the goto references popup.
+ #[name = "lsp.goto-reference-include-declaration"]
+ #[read = copy]
+ goto_reference_include_declaration: bool = true,
+ // TODO(breaing): prefix all options below with `lsp.`
+ /// The language-id for language servers, checkout the
+ /// table at [TextDocumentItem](https://microsoft.github.io/
+ /// language-server-protocol/specifications/lsp/3.17/specification/
+ /// #textDocumentItem) for the right id
+ #[name = "languague-id"]
+ language_server_id: Option<String> = None,
+ // TODO(breaking): rename to root-markers to differentiate from workspace-roots
+ // TODO: also makes this setteble on the language server
+ /// A set of marker files to look for when trying to find the workspace
+ /// root. For example `Cargo.lock`, `yarn.lock`
+ roots: List<String> = List::default(),
+ // TODO: also makes this setteble on the language server
+ /// Directories relative to the workspace root that are treated as LSP
+ /// roots. The search for root markers (starting at the path of the
+ /// file) will stop at these paths.
+ #[name = "workspace-lsp-roots"]
+ workspace_roots: List<String> = List::default(),
+ /// An array of LSP diagnostic sources assumed unchanged when the
+ /// language server resends the same set of diagnostics. Helix can track
+ /// the position for these diagnostics internally instead. Useful for
+ /// diagnostics that are recomputed on save.
+ persistent_diagnostic_sources: List<String> = List::default(),
+ /// Minimal severity of diagnostic for it to be displayed. (Allowed
+ /// values: `error`, `warning`, `info`, `hint`)
+ diagnostic_severity: Severity = Severity::Hint,
+ }
+
+ struct CompletionConfig {
+ /// Automatic auto-completion, automatically pop up without user trigger.
+ #[read = copy]
+ auto_completion: bool = true,
+ /// Whether to apply completion item instantly when selected
+ #[read = copy]
+ preview_completion_insert: bool = true,
+ /// Whether to apply completion item instantly when selected
+ #[read = copy]
+ completion_replace: bool = false,
+ /// Whether to apply completion item instantly when selected
+ #[read = copy]
+ completion_trigger_len: u8 = 2,
+ }
+}