use crate::log::Log;
use crate::{cli::open::core::*, tpl::doc::INIT_CONFIG};
use crate::{
config::open::Config,
utils::conf::{parse, save},
};
use clap::{Args, Subcommand};
use dirs;
use dyn_fmt::AsStrFormatExt;
use owo_colors::OwoColorize;
use std::{fs::File, io::Read};
#[derive(Args)]
pub struct Cmd {
#[arg(help = "Open what you want to open")]
name: Option<String>,
#[arg(short, long, default_value_t = false, help = "Open Repository")]
rep: bool,
#[arg(short, long, default_value_t = false, help = "Open playground")]
play: bool,
#[arg(short, long, default_value_t = false, help = "Search docs in config file")]
search: bool,
#[arg(
help = "Search content by 'config.search' which will be replace by google if it is empty"
)]
content: Option<String>,
#[arg(short, long)]
dir: Option<String>,
#[command(subcommand)]
command: Option<Sub>,
}
#[derive(Subcommand)]
enum Sub {
#[command(long_about = "See all config", alias = "ls")]
List {
#[arg(short, long)]
filter: Option<String>,
#[arg(short, long, default_value_t = false)]
detail: bool,
},
#[command(
long_about = "Init config, you can use -f to update config forcedly, -u to get remote config, -m to merge remote config to local"
)]
Init {
#[arg(short, long, default_value_t = false)]
force: bool,
#[arg(short, long)]
url: Option<String>,
#[arg(short, long, default_value_t = false)]
merge: bool,
},
}
pub async fn run(cli: &Cmd) -> anyhow::Result<()> {
if let Some(name) = &cli.name {
let config = Config::new(cli.dir.clone())?;
if cli.search {
let mut st = "https://www.google.com/search?q={}";
let mut sc = "{} ".format(&[&name]);
if let Some(doc) = config.map.get(name) {
if let Some(s) = &doc.search {
st = &s;
sc.clear();
}
if let Some(c) = &cli.content {
sc.push_str(&c);
}
};
webbrowser::open(&st.format(&[sc.trim()]))?;
return Ok(());
}
config.open(&name, &OpenOption { rep: cli.rep, play: cli.play })?;
return Ok(());
}
match &cli.command {
Some(Sub::List { filter, detail }) => {
let config = Config::new(cli.dir.clone())?;
println!("{}", "docs:".yellow());
config.walk(|n, doc| {
if let Some(f) = filter {
if doc.contains(n, f) {
config.view(n, *detail)
}
} else {
config.view(n, *detail)
}
})
}
Some(Sub::Init { force, url, merge }) => {
let home = dirs::home_dir();
let is_force = *force;
let should_merge = *merge;
let mut write_config = String::new();
let mut remote_config = String::new();
if let Some(home) = home {
let config_path = home.join(".doc.toml");
if let Some(url) = url {
remote_config = reqwest::get(url).await?.text().await?;
}
if config_path.exists() {
File::open(&config_path)?.read_to_string(&mut write_config)?;
let mut user_config = if write_config.is_empty() {
Config::new_empty()
} else {
parse(&write_config)?
};
if should_merge {
let rc_config = parse::<Config>(&remote_config)?;
rc_config.map.keys().for_each(|s| {
if let Some(doc) = rc_config.map.get(s) {
user_config.map.insert(s.to_string(), doc.clone());
}
});
write_config = user_config.to_string()?;
}
if is_force && !remote_config.is_empty() {
save(&config_path, &remote_config, INIT_CONFIG)?;
return Ok(());
}
save(&config_path, &write_config, INIT_CONFIG)?;
} else {
write_config = String::from(if remote_config.is_empty() {
INIT_CONFIG
} else {
&remote_config
});
save(&config_path, &write_config, INIT_CONFIG)?;
}
Log::Suc(&"Success init config in {}".format([&config_path.display()])).println();
} else {
return Err(anyhow::Error::msg(Log::Err("Can not find home dir.").to_string()));
}
}
None => {
let config = Config::new(cli.dir.clone())?;
if cli.name.is_none() {
Log::Warn("Please select one of the names below to see, or just use '-s' to search by google \neg: crax go xx -s 👇:").println();
config.walk(|n, doc| println!("{} ", doc.get_printed_name(n).green()));
println!("\n");
}
}
}
Ok(())
}