use std::{io::BufRead, path::PathBuf}; use terminal_size; use regex; use clap::Parser; fn main() { let cli = Cli::parse(); let source_folder = std::fs::read_dir(std::path::absolute(cli.src).unwrap()).unwrap(); let target_path = std::path::absolute(cli.dst).unwrap(); let episode_matching = regex::Regex::new(r"(?i) s((?:eason\s)?\d+).*?E?((?:pisode)?\d+).*\.(\w+)").unwrap(); let mut found_episodes: Vec = Vec::new(); for f in source_folder { let file = f.unwrap().path(); let filename = file.file_name().unwrap(); let captures = episode_matching.captures(filename.to_str().unwrap()); match captures { Some(c) => { found_episodes.push(EpisodeID { path: file.clone(), filename: file.file_name().unwrap().to_string_lossy().to_string(), season: c.get(1).unwrap().as_str().parse().unwrap(), episode: c.get(2).unwrap().as_str().parse().unwrap(), filetype: c.get(3).unwrap().as_str().to_string(), }); }, None => continue, }; } found_episodes.sort_by(|x, y| x.episode.cmp(&y.episode)); let max_len = found_episodes.iter().max_by(|x, y| { x.filename.len().cmp(&y.filename.len()) }).unwrap().filename.len(); let term_width = terminal_size::terminal_size().unwrap().0.0; let max_filename_cols = (term_width as usize / (max_len + 4)).clamp(1, 5); let filename_rows = (found_episodes.len()/max_filename_cols).clamp(1, usize::MAX); let mut arranged:Vec> = vec![Vec::new();filename_rows]; for (i, f) in found_episodes.iter().enumerate() { arranged[i%filename_rows].push(format!("{:size$}", f.filename, size = max_len+4)); } for i in arranged.iter() { for j in i { print!("{j}"); } println!(""); } println!("Found {} episodes.", found_episodes.len()); println!("Create links at {}? [y/N]", target_path.to_string_lossy()); loop { let mut line = String::new(); let _read = std::io::stdin() .lock() .read_line(&mut line).unwrap(); match line.as_str().trim_end() { "y"|"Y" => break, "n"|"N" => return, _ => println!("Not recognized please type \"y\" for yes or \"n\" for no") } } for i in found_episodes { let mut target = target_path.clone(); target.push(format!("S{:02}E{:02}.{}", i.season, i.episode, i.filetype)); std::os::unix::fs::symlink(i.path, target).expect("Unable to create symlink"); } } #[derive(Parser)] #[command(version, about, long_about=None)] struct Cli { #[arg(short,long)] src: String, #[arg(short,long)] dst: String, } #[derive(Debug)] struct EpisodeID { path: PathBuf, filename: String, season: u32, episode: u32, filetype: String, }