use std::path::PathBuf; use chrono::{DateTime, Local, Utc}; use clap::Parser; use imaging::Renderer; mod cli; mod graphics; mod imaging; fn main() { let args = cli::Args::parse(); capture_all_displays(args.out); } /// Captures a screenshot of all active displays and writes the resulting image to disk. fn capture_all_displays(filename: String) { let captures: Vec<_> = graphics::Display::get_displays() .iter() .filter_map(|screen| screen.capture().ok()) .collect(); let img = Renderer::stitch_horizontally(captures); if !img.is_empty() { let timestamp: DateTime = Utc::now().with_timezone(&Local); const FILENAME_FORMAT: &str = "screenshot-%Y-%m-%d_%H-%M-%S.png"; let mut path = PathBuf::from(timestamp.format(&filename).to_string()); if path.is_dir() { path = path.join(timestamp.format(FILENAME_FORMAT).to_string()); } match img.save(generate_filename(&path)) { Ok(_) => println!("screenshot saved successfully!"), Err(err) => println!("there was an error saving the image: {:?}", err), } } } /// Generate a new filename if a file already exists at the target. /// /// If the file exists, the format of `_.` will be generated. /// /// eg. `my_screenshot-2023-12-20.png` becomes `my_screenshot-2023-12-20_1.png` fn generate_filename(filename: &PathBuf) -> PathBuf { let mut index = 0; let mut new_filename = filename.clone(); let extension = filename .extension() .map(|ext| format!(".{}", ext.to_string_lossy())) .unwrap_or_default(); while new_filename.exists() { index += 1; new_filename.set_file_name(format!( "{}_{}{}", filename.file_stem().unwrap().to_string_lossy(), index, extension )); } new_filename }