use std::str::FromStr;
use std::time::Duration;
use std::{collections::HashMap, path::PathBuf};
use anyhow::Result;
use std::time::SystemTime;
use diwe::config::Configuration;
use lsp_server::Connection;
use crossbeam_channel::unbounded;
use diwe::fs::{new_for_path, new_from_hashmap};
use diwe::watcher::{start_poll_watcher, start_watcher, FsChange};
use router::{LspClient, Router, ServerConfig};
pub mod router;
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq, Default)]
pub struct ServerParams {
pub state: Option<HashMap<String, String>>,
pub sequential_ids: Option<bool>,
pub client_name: Option<String>,
pub configuration: Configuration,
pub base_path: String,
#[serde(skip)]
pub override_now: Option<SystemTime>,
#[serde(skip)]
pub watch_poll_interval: Option<Duration>,
}
pub fn main_loop(connection: Connection, params: ServerParams) -> Result<()> {
let client = params
.clone()
.client_name
.filter(|name| name.eq("helix"))
.map(|_| LspClient::Helix)
.unwrap_or(LspClient::Unknown);
let watch_filesystem = params.state.is_none();
let base_path = params.base_path.clone();
let format = params.configuration.format;
let watch_poll_interval = params.watch_poll_interval;
let (fs_sender, fs_receiver) = unbounded::<FsChange>();
let router = if let Some(state) = params.state {
Router::new(
connection.sender,
ServerConfig {
base_path: params.base_path.clone(),
state: new_from_hashmap(state),
sequential_ids: Some(true),
lsp_client: client,
configuration: params.configuration,
override_now: params.override_now,
},
)
} else {
Router::new(
connection.sender,
ServerConfig {
base_path: params.base_path.clone(),
state: new_for_path(
&PathBuf::from_str(¶ms.base_path).expect("to work"),
params.configuration.format,
),
sequential_ids: None,
lsp_client: client,
configuration: params.configuration,
override_now: params.override_now,
},
)
};
let handler_sender = fs_sender.clone();
let handler = move |change| {
let _ = handler_sender.send(change);
};
let watch_root = PathBuf::from(base_path);
let _watcher: Option<Box<dyn Send>> = if !watch_filesystem {
None
} else if let Some(interval) = watch_poll_interval {
start_poll_watcher(watch_root, format, interval, handler)
.map(|w| Box::new(w) as Box<dyn Send>)
} else {
start_watcher(watch_root, format, handler).map(|w| Box::new(w) as Box<dyn Send>)
};
let _fs_sender = fs_sender;
router.run(connection.receiver, fs_receiver)
}