this is add_post cli implementation in rust

[dependencies]
chrono = "0.4.26"
dirs = "5.0.1"
doe = "0.1.64"
tsu = "1.0.1"
#[allow(warnings)]
pub mod cli {
    use doe::traits::{DebugPrint, Print, Str};
    use doe::*;
    use std::collections::BTreeMap;
    use std::ops::Deref;
    use std::path::{Path, PathBuf};
    use std::str::FromStr;
    use std::sync::{mpsc, Arc, Mutex};
    use std::{fs, thread};

    //path of the config file
    pub fn config_file_path() -> PathBuf {
        let mut development = false;
        if development {
            let path = PathBuf::from_str("./config.toml").unwrap();
            path
        } else {
            let config_dir = dirs::config_dir().expect("get_config_dir fail");
            let config_file_path = config_dir.join("mdbook-post/config.toml");
            config_file_path
        }
    }

    // the config file exists or not
    pub fn is_config_available() -> bool {
        return Path::new(&config_file_path()).exists();
    }

    //if the config file not exists then create it
    pub fn create_config() {
        if !config_file_path().exists() {
            // Create the directory structure if it doesn't already exist
            if let Some(parent_dir) = config_file_path().parent() {
                fs::create_dir_all(parent_dir).expect("Failed to create config directory");
            }
            // Write the default configuration content to the file
            let home_dir = dirs::home_dir().expect("get home_dir fail");
            let blog_dir_path = home_dir.join("code/gitee/blog");
            let default_config = include_str!("../config.toml")
                .format(targets! {"{{blog_dir}}"=>format!("{}",blog_dir_path.to_string_lossy())});
            fs::write(&config_file_path(), default_config.trim()).is_ok_and(|_| {
                println!("{} created", config_file_path().display());
                true
            });
        }
    }

    pub fn edit_config(blog_dir: &str) {
        if !config_file_path().exists() {
            // Create the directory structure if it doesn't already exist
            if let Some(parent_dir) = config_file_path().parent() {
                fs::create_dir_all(parent_dir).expect("Failed to create config directory");
            }
            // Write the default configuration content to the file
            let default_config = format!("[mdbook-post]\nblog_dir = {:?}", blog_dir);
            fs::write(&config_file_path(), default_config.trim())
                .expect("Failed to write config file");
        }
    }

    //if config file exists read the config file
    pub fn read_config() -> Option<String> {
        if config_file_path().exists() {
            // Read the content of the configuration file
            let config_content =
                fs::read_to_string(&config_file_path()).expect("Failed to read config file");
            return Some(config_content);
        }
        None
    }

    //remove the config file
    pub fn remove_config() {
        let config_dir = dirs::config_dir().expect("get_config_dir failed");
        let config_file_path = config_dir.join("mdbook-post/config.toml");
        fs::remove_file(config_file_path.clone()).is_ok_and(|_| {
            println!("{} removed", config_file_path.display());
            true
        });
    }
    //parse get blog_dir
    pub fn parse_toml_config_get_blog_dir(config: &str) -> String {
        let config = tsu::toml_from_str(config);
        let mdbook_post = config.get("mdbook-post").unwrap();
        let name = mdbook_post.get("blog_dir").unwrap();
        name.as_str()
            .expect("get blog_dir from config error")
            .to_string()
    }
    //parse get blog_dir
    pub fn parse_toml_config_get_post_to_path(config: &str) -> BTreeMap<String, String> {
        let mut map: BTreeMap<String, String> = btreemap!();
        let post_config = tsu::toml_from_str(config);
        if let Some(post_to_path) = post_config.get("post-to-path").to_owned().clone() {
            post_to_path
                .as_table()
                .unwrap()
                .into_iter()
                .for_each(|(k, v)| {
                    map.insert(k.to_string(), v.as_str().unwrap().to_string());
                });
        }
        map
    }

    pub fn run() {}
    pub fn show_catogorylist() {
        if let Some(config) = read_config() {
            let blog_dir = PathBuf::from_str(&parse_toml_config_get_blog_dir(&config))
                .expect("get blog_dir from config error");
            if blog_dir.is_dir() {
                let summary = fs::read_to_string(&blog_dir.join("./src/SUMMARY.md")).unwrap();
                from_summary_file_get_categorylist(summary)
                    .into_iter()
                    .map(|(i, s)| s)
                    .collect::<Vec<_>>()
                    .join("   ")
                    .println();
            } else {
                println!("{} do't exists", blog_dir.display());
            }
        }
    }
    pub fn category_to_path(category: &str) -> Option<String> {
        if let Some(config) = read_config() {
            let map = parse_toml_config_get_post_to_path(&config);
            return Some(map.get(category).unwrap().to_string());
        }
        return None;
    }
    fn title_to_markdown(category: &str) -> String {
        category
            .to_lowercase()
            .replace("-", "_")
            .replace(" ", "_")
            .replace("。", ".")
            .replace("(", "(")
            .replace(")", ")")
            .to_string()
    }
    pub fn get_category_list(category: &str) {
        if let Some(config) = read_config() {
            let blog_dir = PathBuf::from_str(&parse_toml_config_get_blog_dir(&config))
                .expect("get blog_dir from config error");
            if blog_dir.is_dir() {
                let summary = fs::read_to_string(&blog_dir.join("./src/SUMMARY.md")).unwrap();
                let mut summary_vec = summary
                    .split("\n")
                    .filter(|s| !s.is_empty())
                    .map(|s| s.to_string())
                    .collect::<Vec<_>>();
                let category_vec = from_summary_file_get_categorylist(summary);
                let index = category_vec
                    .clone()
                    .into_iter()
                    .enumerate()
                    .filter(|(i, s)| s.1 == category.to_string())
                    .nth(0)
                    .expect("get category index error");
                if category_vec.len() > index.0 + 1 {
                    let index_1 = index.clone().1;
                    let index_2 = category_vec.clone().get(index.0 + 1).unwrap().to_owned();
                    for i in index_1.0..index_2.0 {
                        summary_vec[i]
                            .replace(
                                "./posts/",
                                &blog_dir.join("./src/posts/").display().to_string(),
                            )
                            .println();
                    }
                } else {
                    let index_1 = index.clone().1;
                    for i in index_1.0..summary_vec.len() {
                        summary_vec[i]
                            .replace(
                                "./posts/",
                                &blog_dir.join("./src/posts/").display().to_string(),
                            )
                            .println();
                    }
                }
            } else {
                println!("{} do't exists", blog_dir.display());
            }
        }
    }
    pub fn create_post(category: &str, title: &str) {
        if let Some(config) = read_config() {
            let blog_dir = PathBuf::from_str(&parse_toml_config_get_blog_dir(&config))
                .expect("get blog_dir from config error");
            if blog_dir.is_dir() {
                let summary = fs::read_to_string(&blog_dir.join("./src/SUMMARY.md")).unwrap();
                let mut summary_vec = summary
                    .split("\n")
                    .filter(|s| !s.is_empty())
                    .map(|s| s.to_string())
                    .collect::<Vec<_>>();
                let category_vec = from_summary_file_get_categorylist(summary);
                let index = category_vec
                    .clone()
                    .into_iter()
                    .enumerate()
                    .filter(|(i, s)| s.1 == category.to_string())
                    .nth(0)
                    .expect("get category index error");
                if category_vec.len() > index.0 + 1 {
                    let index_1 = index.clone().1;
                    let index_2 = category_vec.clone().get(index.0 + 1).unwrap().to_owned();
                    summary_vec.insert(
                        index_2.0,
                        format!(
                            "    - [{}](./posts/{}/{}.md)",
                            title,
                            category_to_path(category).unwrap_or_else(|| format!("post")),
                            title_to_markdown(title)
                        ),
                    );
                } else {
                    summary_vec.push(format!(
                        "    - [{}](./posts/{}/{}.md)",
                        title,
                        category_to_path(category).unwrap_or_else(|| format!("post")),
                        title_to_markdown(title)
                    ));
                }
                use chrono::format::strftime::StrftimeItems;
                use chrono::Utc;
                let current_date = Utc::today();
                let formatted_date = current_date.format("%Y-%m-%d").to_string();

                let markdown_content = include_str!("../defalut_markdown_content.md")
                    .format(targets! {"{{title}}"=>title.to_string(),"{{date}}"=>formatted_date});
                fs::write(
                    &blog_dir.join(format!(
                        "./src/posts/{}/{}.md",
                        category_to_path(category).unwrap_or_else(|| format!("post")),
                        title_to_markdown(title)
                    )),
                    markdown_content,
                )
                .unwrap();
                fs::write(&blog_dir.join("./src/SUMMARY.md"), summary_vec.join("\n")).unwrap();
                blog_dir
                    .join(format!(
                        "./src/posts/{}/{}.md",
                        category_to_path(category).unwrap_or_else(|| format!("post")),
                        title_to_markdown(title)
                    ))
                    .display()
                    .println();
            } else {
                println!("{} do't exists", blog_dir.display());
            }
        }
    }
    pub fn from_summary_file_get_categorylist(summary: String) -> Vec<(usize, String)> {
        let summary_vec = summary
            .split("\n")
            .filter(|s| !s.is_empty())
            .map(|s| s.to_string())
            .collect::<Vec<_>>();
        let v = summary_vec
            .clone()
            .into_iter()
            .filter(|s| s.contains("- "))
            .collect::<Vec<_>>();
        let v_title = summary_vec
            .clone()
            .into_iter()
            .filter(|s| s.contains("-"))
            .into_iter()
            .enumerate()
            .map(|(i, s)| {
                if s.starts_with("- [") {
                    return Some((
                        i + 2,
                        split_to_vec!(split_to_vec!(s, "[").get(1).unwrap(), "]")
                            .get(0)
                            .unwrap()
                            .to_string(),
                    ));
                }
                None
            })
            .filter(|s| s.is_some())
            .map(|s| s.unwrap())
            .collect::<Vec<_>>();
        v_title
    }

    pub fn display_help() {
        println!("mdbook-post");
        println!("Example:");
        println!("mdbook-post <-c || --config> show  => show cli config");
        println!("mdbook-post <-c || --config> remove => remove cli config");
        println!("mdbook-post <-c || --config> edit /home/andrew/code/gitee/blog =>set blog path");
        println!("mdbook-post <-l || --catogorylist>  => show category list");
        println!("mdbook-post <-l Rust || --catogorylist Rust>  => show all list of Rust");
        println!("mdbook-post <-n || --new> Rust 'implement todo CLI'  => add new post");
    }

    pub fn cli() {
        let t1 = thread::spawn({
            move || {
                if is_config_available() {
                    let args = args!();
                    let first_arg = args
                        .clone()
                        .into_iter()
                        .nth(0)
                        .map_or_else(|| String::from(""), |arg| arg.to_string());
                    if args.len() > 0 {
                        if &first_arg == "--config" || &first_arg == "-c" {
                            let second_arg = args
                                .clone()
                                .into_iter()
                                .nth(1)
                                .map_or_else(|| String::from(""), |arg| arg.to_string());
                            if second_arg == "show" {
                                println!(
                                    "config path: {}",
                                    config_file_path().display().to_string()
                                );
                                println!("");
                                fs::read_to_string(config_file_path()).unwrap().println();
                            }
                            if second_arg == "remove" {
                                remove_config();
                            }
                            if second_arg == "edit" {
                                let path = args
                                    .clone()
                                    .into_iter()
                                    .nth(2)
                                    .expect("edit path must be specified");
                                edit_config(&path);
                            }
                        } else if &first_arg == "--catogorylist" || &first_arg == "-l" {
                            if args.len() == 1 {
                                show_catogorylist();
                            } else {
                                let title = args
                                    .clone()
                                    .into_iter()
                                    .nth(1)
                                    .map_or_else(|| String::from(""), |arg| arg.to_string());
                                if !title.is_empty() {
                                    get_category_list(&title);
                                }
                            }
                        } else if &first_arg == "--new" || &first_arg == "-n" {
                            let title = args
                                .clone()
                                .into_iter()
                                .nth(1)
                                .map_or_else(|| String::from(""), |arg| arg.to_string());
                            let content_name = args
                                .clone()
                                .into_iter()
                                .nth(2)
                                .map_or_else(|| String::from(""), |arg| arg.to_string());
                            if title.is_empty() && content_name.is_empty() {
                                display_help();
                            } else {
                                create_post(&title, &content_name);
                            }
                        } else if &first_arg == "--help" || &first_arg == "-h" {
                            display_help();
                        }
                    } else {
                        display_help();
                    }
                } else {
                    create_config();
                }
            }
        });
        t1.join().unwrap();
    }
}

fn main() {
    cli::cli();
}