crax 0.1.8

An interesting CLI for frontend programmer
Documentation
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(())
}