use std::io::Write; use std::str::FromStr; use anyhow::Context; use anyhow::Error; use anyhow::Result; use anyhow::anyhow; use itertools::Itertools; mod config; mod cli; mod schema; use fss::fss_client::FssClient; use fss::VersionRequest; use fss::IndexFileRequest; use fss::SearchQueryRequest; mod fss { tonic::include_proto!("fss"); } #[tokio::main] async fn main() -> Result<()> { let cli = crate::cli::client_app(); let matches = cli.get_matches(); let _ = env_logger::try_init()?; let mut config = ::config::Config::default(); { let xdg = xdg::BaseDirectories::with_prefix("fss")?; let xdg_config = xdg.find_config_file("config.toml") .ok_or_else(|| anyhow!("No configuration file found with XDG: {}", xdg.get_config_home().display()))?; log::debug!("Configuration file found with XDG: {}", xdg_config.display()); config.merge(::config::File::from(xdg_config).required(false)) .context("Failed to load config.toml from XDG configuration directory")?; } let config = config.try_into::()?; let server_addr = matches.value_of("server_addr").unwrap_or_else(|| config.server_addr()); let server_port = matches.value_of("server_port").map(usize::from_str).unwrap_or_else(|| Ok(*config.server_port()))?; let addr = format!("http://{}:{}", server_addr, server_port); let mut client = FssClient::connect(addr).await?; let request = tonic::Request::new(VersionRequest { }); let _response = client.get_version(request).await?; match matches.subcommand() { ("index", Some(mtch)) => { let path = mtch.value_of("file").map(String::from).unwrap(); // safe by clap let path = std::env::current_dir()?.join(path).display().to_string(); let request = tonic::Request::new(IndexFileRequest { path }); let response = client.index_file(request).await?; if response.get_ref().error { Err(anyhow!("Error indexing file")) } else { Ok(()) } }, ("search", Some(mtch)) => { let query = mtch.values_of("term") .unwrap() // safe by clap .join(" "); let request = tonic::Request::new(SearchQueryRequest { query }); let response = client.search_query(request).await?; let mut output = std::io::stdout(); if response.get_ref().success { log::debug!("Success"); response.get_ref() .pathes .iter() .map(|pb| writeln!(output, "{}", pb).map_err(Error::from)) .collect::>>() .map(|_| ()) } else { log::debug!("Failed"); Err(anyhow!("Failed to search")) } }, (_other, _) => { unimplemented!() }, } }