//! Logic to define and parse a configuration from command line arguments. use clap::Parser; use colored::Color; /// Contains all the arguments parsed from the command line. /// /// # Fields /// /// - `titles_path`: Specifies the path to the ASCII text files directory. If not provided, assumes the directory is in the current directory. /// - `art_path`: Specifies the path to the ASCII image files directory. If not provided, assumes the directory is in the current directory. /// - `banner_path`: Specifies the path to the ASCII banner file. If not provided, assumes the file is in the current directory. /// - `color`: Specifies the color to output the terminal header as. If not provided, outputs as normal. /// /// # Examples /// ``` /// use clap::Parser; /// use term_header::config; /// /// let args = config::Args::parse(); /// /// assert_eq!(args.titles_path, "./titles/"); /// assert_eq!(args.art_path, "./art/"); /// assert_eq!(args.banner_path, "./banner.txt"); /// assert_eq!(args.color, None); /// ``` #[derive(Parser, Debug)] #[command( name = "term-header", author = "r0r-5chach", version = "1.0", about = "A program that generates ASCII art terminal headers. color can cause unexpected behaviour when used with terminal themes.", long_about = None)] pub struct Args { /// The path to the ASCII text files directory #[arg(short, long, default_value = "./titles/")] pub titles_path: String, /// The path to the ASCII image files directory #[arg(short, long, default_value = "./art/")] pub art_path: String, /// The path to the ASCII banner #[arg(short, long, default_value = "./banner.txt")] pub banner_path: String, /// The color the text should be outputed as (Terminal themes can cause unexpected behaviour) #[arg(short, long, default_value = None)] pub color: Option, } /// Contains the configuration for the program. /// /// # Fields /// - `title_file`: The contents of the randomly selected ASCII text file. /// - `art_file`: The contents of the randomly selected ASCII image file. /// - `banner_file`: The contents of the randomly selected ASCII banner file. /// pub struct Config { pub title_file: String, pub art_file: String, pub banner_file: String, pub color: Option, } impl Config { /// Returns a new configuration parsed from the [Args] parsed from the command line. pub fn new(args: Args) -> Self { //TODO: Add examples using tempdir to create a dir let title_file = rand_file_from_path(args.titles_path); let art_file = rand_file_from_path(args.art_path); let banner_file = args.banner_path; let color = args.color; Self { title_file, art_file, banner_file, color, } } } fn get_file_count(dir: &str) -> usize { use std::fs; let files = match fs::read_dir(&dir) { Ok(files) => files, Err(_) => path_not_found_error(&dir), }; files.count() } fn rand_file_from_path(path: String) -> String { use rand::Rng; let mut rng = rand::thread_rng(); let mut file = path.clone(); let file_count = get_file_count(&path); match file_count { count if count < 2 => file.push_str("1"), _ => file.push_str(&rng.gen_range(1..get_file_count(&path)).to_string()), } file.push_str(".txt"); file.to_string() } fn path_not_found_error(path: &str) -> ! { eprintln!("This path does not exist: {}", path); std::process::exit(1); }