TUI: Add config file and argument parsing w/ clap

This commit is contained in:
chmanie 2023-06-11 01:02:05 +02:00
parent a65ad793dc
commit d970e372af
4 changed files with 225 additions and 8 deletions

157
Cargo.lock generated
View File

@ -42,6 +42,55 @@ dependencies = [
"libc", "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]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.71" version = "1.0.71"
@ -326,13 +375,19 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
name = "cbd-tui" name = "cbd-tui"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap",
"clap-serde-derive",
"crabidy-core", "crabidy-core",
"crossterm", "crossterm",
"dirs",
"flume", "flume",
"lazy_static",
"notify-rust", "notify-rust",
"ratatui", "ratatui",
"serde",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"toml 0.7.4",
"tonic", "tonic",
] ]
@ -392,12 +447,82 @@ dependencies = [
"libloading", "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]] [[package]]
name = "claxon" name = "claxon"
version = "0.4.3" version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]] [[package]]
name = "combine" name = "combine"
version = "4.6.6" version = "4.6.6"
@ -1178,6 +1303,18 @@ version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" 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]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.5" version = "0.10.5"
@ -2214,18 +2351,18 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.163" version = "1.0.164"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.163" version = "1.0.164"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2420,6 +2557,12 @@ dependencies = [
"tracing-subscriber", "tracing-subscriber",
] ]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "strum" name = "strum"
version = "0.22.0" version = "0.22.0"
@ -3169,6 +3312,12 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]] [[package]]
name = "valuable" name = "valuable"
version = "0.1.0" version = "0.1.0"

View File

@ -14,3 +14,9 @@ tokio = { version = "1", features = ["full"] }
tokio-stream = "0.1" tokio-stream = "0.1"
tonic = "0.9" tonic = "0.9"
notify-rust = "4.8.0" 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"

54
cbd-tui/src/config.rs Normal file
View File

@ -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::<<Config as ClapSerde>::Opt>(&content).unwrap();
let config: Config = Config::from(parsed).merge_clap();
return config;
}
}
Config::default().merge_clap()
}

View File

@ -1,5 +1,7 @@
mod config;
mod rpc; mod rpc;
use config::Config;
use crabidy_core::proto::crabidy::{ use crabidy_core::proto::crabidy::{
crabidy_service_client::CrabidyServiceClient, crabidy_service_client::CrabidyServiceClient,
get_update_stream_response::Update as StreamUpdate, GetLibraryNodeRequest, get_update_stream_response::Update as StreamUpdate, GetLibraryNodeRequest,
@ -16,6 +18,8 @@ use crossterm::{
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
}; };
use flume::{Receiver, Sender}; use flume::{Receiver, Sender};
use lazy_static::lazy_static;
use notify_rust::Notification;
use ratatui::{ use ratatui::{
backend::{Backend, CrosstermBackend}, backend::{Backend, CrosstermBackend},
layout::{Alignment, Constraint, Corner, Direction, Layout}, layout::{Alignment, Constraint, Corner, Direction, Layout},
@ -41,8 +45,6 @@ use tokio::{fs, select, signal, task};
use tokio_stream::StreamExt; use tokio_stream::StreamExt;
use tonic::{transport::Channel, Request, Status, Streaming}; use tonic::{transport::Channel, Request, Status, Streaming};
use notify_rust::Notification;
const COLOR_PRIMARY: Color = Color::Rgb(129, 161, 193); 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(94, 129, 172);
const COLOR_PRIMARY_DARK: Color = Color::Rgb(59, 66, 82); 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_ORANGE: Color = Color::Rgb(208, 135, 112);
// const COLOR_BRIGHT: Color = Color::Rgb(216, 222, 233); // 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 { trait ListView {
fn get_size(&self) -> usize; fn get_size(&self) -> usize;
fn select(&mut self, idx: Option<usize>); fn select(&mut self, idx: Option<usize>);
@ -566,9 +573,10 @@ async fn poll(
} }
async fn orchestrate<'a>( async fn orchestrate<'a>(
config: &'static Config,
(tx, rx): (Sender<MessageToUi>, Receiver<MessageFromUi>), (tx, rx): (Sender<MessageToUi>, Receiver<MessageFromUi>),
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
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? { if let Some(root_node) = rpc_client.get_library_node("node:/").await? {
tx.send(MessageToUi::ReplaceLibraryNode(root_node.clone())); tx.send(MessageToUi::ReplaceLibraryNode(root_node.clone()));
@ -588,7 +596,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (tx, ui_rx): (Sender<MessageToUi>, Receiver<MessageToUi>) = flume::unbounded(); let (tx, ui_rx): (Sender<MessageToUi>, Receiver<MessageToUi>) = flume::unbounded();
// FIXME: unwrap // 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(|| { tokio::task::spawn_blocking(|| {
run_ui(ui_tx, ui_rx); run_ui(ui_tx, ui_rx);