From b6908ead8434c9df71b5d584c9c086a1687fcbc8 Mon Sep 17 00:00:00 2001 From: Sergey Zaytsev Date: Thu, 29 Aug 2024 08:10:46 +0700 Subject: [PATCH] feat: Add support for external JSON config file Fixes #68 --- crates/lsp-ai/src/main.rs | 18 ++++++++++++++++-- crates/lsp-ai/src/utils.rs | 30 +++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/crates/lsp-ai/src/main.rs b/crates/lsp-ai/src/main.rs index 1ec5abe..a698d4f 100644 --- a/crates/lsp-ai/src/main.rs +++ b/crates/lsp-ai/src/main.rs @@ -11,7 +11,7 @@ use std::sync::Mutex; use std::{ collections::HashMap, fs, - path::Path, + path::{Path, PathBuf}, sync::{mpsc, Arc}, thread, }; @@ -68,6 +68,9 @@ struct Args { // A dummy argument for now #[arg(long, default_value_t = true)] stdio: bool, + // JSON configuration file location + #[arg(long, value_parser = utils::validate_file_exists, required = false)] + config: Option, } fn create_log_file(base_path: &Path) -> anyhow::Result { @@ -109,6 +112,17 @@ fn init_logger(args: &Args) { } } +fn load_config(args: &Args, init_args: serde_json::Value) -> anyhow::Result { + if let Some(config_path) = &args.config { + let config_data = fs::read_to_string(config_path)?; + let mut config = serde_json::from_str(&config_data)?; + utils::merge_json(&mut config, &init_args); + Ok(config) + } else { + Ok(init_args) + } +} + fn main() -> Result<()> { let args = Args::parse(); init_logger(&args); @@ -130,7 +144,7 @@ fn main() -> Result<()> { })?; let initialization_args = connection.initialize(server_capabilities)?; - if let Err(e) = main_loop(connection, initialization_args) { + if let Err(e) = main_loop(connection, load_config(&args, initialization_args)?) { error!("{e:?}"); } diff --git a/crates/lsp-ai/src/utils.rs b/crates/lsp-ai/src/utils.rs index 5aa44f5..cde2987 100644 --- a/crates/lsp-ai/src/utils.rs +++ b/crates/lsp-ai/src/utils.rs @@ -1,6 +1,9 @@ -use anyhow::Context; +use std::path::PathBuf; + +use anyhow::{anyhow, Context}; use lsp_server::ResponseError; use once_cell::sync::Lazy; +use serde_json::Value; use tokio::runtime; use tree_sitter::Tree; @@ -93,3 +96,28 @@ pub(crate) fn format_file_chunk(uri: &str, excerpt: &str, root_uri: Option<&str> {excerpt}"#, ) } + +pub(crate) fn validate_file_exists(path: &str) -> anyhow::Result { + let path = PathBuf::from(path); + if path.is_file() { + Ok(path) + } else { + Err(anyhow!("File doesn't exist: {}", path.display())) + } +} + +pub(crate) fn merge_json(a: &mut Value, b: &Value) { + match (a, b) { + (&mut Value::Object(ref mut a), &Value::Object(ref b)) => { + for (k, v) in b { + merge_json(a.entry(k.clone()).or_insert(Value::Null), v); + } + } + (&mut Value::Array(ref mut a), &Value::Array(ref b)) => { + a.extend(b.clone()); + } + (a, b) => { + *a = b.clone(); + } + } +}