diff --git a/Cargo.lock b/Cargo.lock index d2b6157..8842f60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,6 +42,55 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" + +[[package]] +name = "anstyle-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + [[package]] name = "anyhow" version = "1.0.71" @@ -326,13 +375,19 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" name = "cbd-tui" version = "0.1.0" dependencies = [ + "clap", + "clap-serde-derive", "crabidy-core", "crossterm", + "dirs", "flume", + "lazy_static", "notify-rust", "ratatui", + "serde", "tokio", "tokio-stream", + "toml 0.7.4", "tonic", ] @@ -392,12 +447,82 @@ dependencies = [ "libloading", ] +[[package]] +name = "clap" +version = "4.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8f255e4b8027970e78db75e78831229c9815fdbfa67eb1a1b777a62e24b4a0" +dependencies = [ + "clap_builder", + "clap_derive", + "once_cell", +] + +[[package]] +name = "clap-serde-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b917611f6596c7e42bd9c039b7202e50375aee5b7aab5817551b6d506aa8a5a8" +dependencies = [ + "clap", + "clap-serde-proc", + "serde", +] + +[[package]] +name = "clap-serde-proc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6725cfcf906f158cdad4ca9a2a426133b36a3f91b5da2b971f8b956823ef55e" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "clap_builder" +version = "4.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acd4f3c17c83b0ba34ffbc4f8bbd74f079413f747f84a6f89292f138057e36ab" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.16", +] + +[[package]] +name = "clap_lex" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + [[package]] name = "claxon" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "combine" version = "4.6.6" @@ -1178,6 +1303,18 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "itertools" version = "0.10.5" @@ -2214,18 +2351,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", @@ -2420,6 +2557,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.22.0" @@ -3169,6 +3312,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "valuable" version = "0.1.0" diff --git a/cbd-tui/Cargo.toml b/cbd-tui/Cargo.toml index 5d9296f..4a4f8a9 100644 --- a/cbd-tui/Cargo.toml +++ b/cbd-tui/Cargo.toml @@ -14,3 +14,9 @@ tokio = { version = "1", features = ["full"] } tokio-stream = "0.1" tonic = "0.9" notify-rust = "4.8.0" +clap = "4.3.3" +clap-serde-derive = "0.2.0" +serde = "1.0.164" +toml = "0.7.4" +dirs = "5.0.1" +lazy_static = "1.4.0" diff --git a/cbd-tui/src/config.rs b/cbd-tui/src/config.rs new file mode 100644 index 0000000..d8cf2f0 --- /dev/null +++ b/cbd-tui/src/config.rs @@ -0,0 +1,54 @@ +use std::{ + fs::{create_dir_all, read_to_string, File}, + io::Write, + path::Path, +}; + +use clap_serde_derive::{ + clap::{self, Parser}, + serde::Serialize, + ClapSerde, +}; + +#[derive(ClapSerde, Serialize, Debug)] +#[clap(author, version, about)] +pub struct Config { + #[clap_serde] + #[clap(flatten)] + pub server: ServerConfig, +} + +#[derive(ClapSerde, Serialize, Debug)] +pub struct ServerConfig { + /// Server address + #[default("http://127.0.0.1:50051".to_string())] + #[clap(short, long)] + pub address: String, +} + +pub fn init() -> Config { + if let Some(config_dir) = dirs::config_dir() { + let dir = Path::new(&config_dir).join("crabidy"); + if !dir.is_dir() { + create_dir_all(&dir); + } + let config_file_path = dir.join("cbd-tui.toml"); + if !config_file_path.is_file() { + let config = Config::default().merge_clap(); + let content = toml::to_string_pretty(&config).expect("Could not serialize config"); + let mut config_file = + File::create(config_file_path).expect("Could not open config file for writing"); + config_file + .write_all(content.as_bytes()) + .expect("Failed to write to file"); + config_file.flush().ok(); + return config; + } else { + let content = read_to_string(config_file_path).expect("Could not read config file"); + let parsed = toml::from_str::<::Opt>(&content).unwrap(); + let config: Config = Config::from(parsed).merge_clap(); + return config; + } + } + Config::default().merge_clap() +} diff --git a/cbd-tui/src/main.rs b/cbd-tui/src/main.rs index a320585..618b435 100644 --- a/cbd-tui/src/main.rs +++ b/cbd-tui/src/main.rs @@ -1,5 +1,7 @@ +mod config; mod rpc; +use config::Config; use crabidy_core::proto::crabidy::{ crabidy_service_client::CrabidyServiceClient, get_update_stream_response::Update as StreamUpdate, GetLibraryNodeRequest, @@ -16,6 +18,8 @@ use crossterm::{ terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; use flume::{Receiver, Sender}; +use lazy_static::lazy_static; +use notify_rust::Notification; use ratatui::{ backend::{Backend, CrosstermBackend}, layout::{Alignment, Constraint, Corner, Direction, Layout}, @@ -41,8 +45,6 @@ use tokio::{fs, select, signal, task}; use tokio_stream::StreamExt; use tonic::{transport::Channel, Request, Status, Streaming}; -use notify_rust::Notification; - const COLOR_PRIMARY: Color = Color::Rgb(129, 161, 193); // const COLOR_PRIMARY_DARK: Color = Color::Rgb(94, 129, 172); const COLOR_PRIMARY_DARK: Color = Color::Rgb(59, 66, 82); @@ -52,6 +54,11 @@ const COLOR_GREEN: Color = Color::Rgb(163, 190, 140); // const COLOR_ORANGE: Color = Color::Rgb(208, 135, 112); // const COLOR_BRIGHT: Color = Color::Rgb(216, 222, 233); +// FIXME: is lazy-static needed here?? +lazy_static! { + static ref CONFIG: Config = config::init(); +} + trait ListView { fn get_size(&self) -> usize; fn select(&mut self, idx: Option); @@ -566,9 +573,10 @@ async fn poll( } async fn orchestrate<'a>( + config: &'static Config, (tx, rx): (Sender, Receiver), ) -> Result<(), Box> { - let mut rpc_client = rpc::RpcClient::connect("http://192.168.1.149:50051").await?; + let mut rpc_client = rpc::RpcClient::connect(&config.server.address).await?; if let Some(root_node) = rpc_client.get_library_node("node:/").await? { tx.send(MessageToUi::ReplaceLibraryNode(root_node.clone())); @@ -588,7 +596,7 @@ async fn main() -> Result<(), Box> { let (tx, ui_rx): (Sender, Receiver) = flume::unbounded(); // FIXME: unwrap - tokio::spawn(async move { orchestrate((tx, rx)).await.ok() }); + tokio::spawn(async move { orchestrate(&CONFIG, (tx, rx)).await.unwrap() }); tokio::task::spawn_blocking(|| { run_ui(ui_tx, ui_rx);