Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-lsp/src/config.rs')
| -rw-r--r-- | helix-lsp/src/config.rs | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/helix-lsp/src/config.rs b/helix-lsp/src/config.rs new file mode 100644 index 00000000..6d9f8008 --- /dev/null +++ b/helix-lsp/src/config.rs @@ -0,0 +1,67 @@ +use std::collections::HashMap; + +use anyhow::bail; +use helix_config::{options, List, Map, String, Ty, Value}; + +use crate::lsp; + +// TODO: differentiating between Some(null) and None is not really practical +// since the distinction is lost on a roundtrip trough config::Value. +// Porbably better to change our code to treat null the way we currently +// treat None +options! { + struct LanguageServerConfig { + /// The name or path of the language server binary to execute. Binaries must be in `$PATH` + command: Option<String> = None, + /// A list of arguments to pass to the language server binary + #[read = deref] + args: List<String> = List::default(), + /// Any environment variables that will be used when starting the language server + enviorment: Map<String> = Map::default(), + /// LSP initialization options + #[name = "config"] + server_config: Option<Box<serde_json::Value>> = None, + /// LSP initialization options + #[read = copy] + timeout: u64 = 20, + // TODO: merge + /// LSP formatting options + #[name = "config.format"] + #[read = fold(HashMap::new(), fold_format_config, FormatConfig)] + format: Map<FormattingProperty> = Map::default() + } +} + +type FormatConfig = HashMap<std::string::String, lsp::FormattingProperty>; + +fn fold_format_config(config: &Map<FormattingProperty>, mut res: FormatConfig) -> FormatConfig { + for (k, v) in config.iter() { + res.entry(k.to_string()).or_insert_with(|| v.0.clone()); + } + res +} + +// damm orphan rules :/ +#[derive(Debug, PartialEq, Clone)] +struct FormattingProperty(lsp::FormattingProperty); + +impl Ty for FormattingProperty { + fn from_value(val: Value) -> anyhow::Result<Self> { + match val { + Value::Int(_) => Ok(FormattingProperty(lsp::FormattingProperty::Number( + i32::from_value(val)?, + ))), + Value::Bool(val) => Ok(FormattingProperty(lsp::FormattingProperty::Bool(val))), + Value::String(val) => Ok(FormattingProperty(lsp::FormattingProperty::String(val))), + _ => bail!("expected a string, boolean or integer"), + } + } + + fn to_value(&self) -> Value { + match self.0 { + lsp::FormattingProperty::Bool(val) => Value::Bool(val), + lsp::FormattingProperty::Number(val) => Value::Int(val as _), + lsp::FormattingProperty::String(ref val) => Value::String(val.clone()), + } + } +} |