use arboard::Clipboard;
use clap::Parser;
use ignore::WalkBuilder;
use std::fs;
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Cli {
#[arg(default_value = ".")]
path: PathBuf,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
let root_path = cli.path;
if !root_path.is_dir() {
eprintln!(
"Error: Provided path '{}' is not a directory.",
root_path.display()
);
return Err("Invalid path".into());
}
println!(
"Scanning directory: {}",
root_path.canonicalize()?.display()
);
let mut full_content = String::new();
let mut file_count: u32 = 0;
let walker = WalkBuilder::new(&root_path).build();
for result in walker {
match result {
Ok(entry) => {
if let Some(file_type) = entry.file_type() {
if file_type.is_file() {
let path = entry.path();
match fs::read_to_string(path) {
Ok(content) => {
full_content.push_str("--- FILENAME: ");
full_content.push_str(
&path
.strip_prefix(&root_path)
.unwrap_or(path)
.display()
.to_string(),
);
full_content.push_str(" ---\n\n");
full_content.push_str(&content);
full_content.push_str("\n\n");
file_count += 1;
}
Err(_) => {
eprintln!(
"Warning: Could not read non-UTF8 file, skipping: {}",
path.display()
);
}
}
}
}
}
Err(err) => eprintln!("ERROR: {}", err),
}
}
if file_count == 0 {
println!("No files found to copy.");
return Ok(());
}
let total_bytes = full_content.len();
let mut clipboard = Clipboard::new()?;
clipboard.set_text(full_content)?;
println!("\n✅ Success!");
println!(
"Copied {} files ({} bytes) to the clipboard.",
file_count, total_bytes
);
Ok(())
}