use std::{ collections::HashMap, fs::File, io::{self, Write}, path::PathBuf, vec, }; use clap::Parser; use itertools::Itertools; use log::{debug, error, info}; use smolguess::{ core::{LanguageDefinitions, LanguageMatch}, repository, }; #[derive(Parser)] #[command(author, version, about)] struct CliArgs { /// The path to a git repository on disk (required). pub repository: String, /// Write match data to file (optional). #[clap(short, long, name = "FILENAME")] pub export: Option, /// Display all messages. #[clap(short, long)] pub verbose: bool, } fn main() -> io::Result<()> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init(); let args: CliArgs = CliArgs::parse(); let mut stopwatch = stopwatch::Stopwatch::new(); stopwatch.start(); let repo_languages: Vec = LanguageDefinitions::default() .load_builtins() .identify_files(repository::get_bare_repository_files(PathBuf::from( args.repository, ))); let grouped_matches: HashMap<_, _> = repo_languages .clone() .into_iter() .group_by(|matched| matched.language.name.clone()) .into_iter() .map(|(group, items)| (group, items.collect_vec())) .collect(); let mut sorted_groups: Vec<_> = grouped_matches.into_iter().collect(); sorted_groups.sort_by(|(_, first), (_, second)| second.len().cmp(&first.len())); stopwatch.stop(); let json: String = serde_json::to_string_pretty(&sorted_groups)?; // Print out the results if args.verbose { debug!("======== JSON DATA ========"); println!("{}", json); debug!("======== END DATA ========"); debug!("Files found: {}", repo_languages.len()); } // Write match data to file if args.export.is_some() { let file = PathBuf::from(args.export.as_ref().unwrap()); if !file.is_dir() { File::create(file)?.write_all(json.as_bytes())?; } else { error!( "The provided path is a directory: '{}'", args.export.unwrap() ); } } // Output the identified language if !sorted_groups.is_empty() { let default: (String, Vec) = (String::from("Unknown"), vec![]); println!( "{}", sorted_groups.first().unwrap_or_else(|| { &default }).0 ); } // Print out the execution time if args.verbose { info!("Operation completed in: {}", stopwatch) } Ok(()) }