extern crate picleo;
use anyhow::Result;
use clap::Parser;
use picleo::{picker::Picker, selectable::SelectableItem};
use std::{
fmt, fs,
io::{self, BufRead},
path::PathBuf,
};
#[derive(Debug, Clone)]
struct DisplayPath(PathBuf);
impl fmt::Display for DisplayPath {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0.display())
}
}
impl From<PathBuf> for DisplayPath {
fn from(path: PathBuf) -> Self {
DisplayPath(path)
}
}
impl AsRef<PathBuf> for DisplayPath {
fn as_ref(&self) -> &PathBuf {
&self.0
}
}
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
#[arg(name = "DIRS")]
dirs: Vec<PathBuf>,
#[arg(short, long)]
recursive: bool,
#[arg(short, long)]
threaded: bool,
}
fn main() -> Result<()> {
let args = Args::parse();
if !args.dirs.is_empty() {
let mut picker = Picker::<DisplayPath>::new();
for dir in args.dirs {
if args.threaded {
picker.inject_items_threaded(move |i| {
if args.recursive {
walk_dir_recursive(&dir, i);
} else {
walk_dir(dir, i);
}
});
} else {
picker.inject_items(|i| {
if args.recursive {
walk_dir_recursive(&dir, i);
} else {
walk_dir(dir, i);
}
});
}
}
match picker.run() {
Ok(paths) => {
for path in paths {
println!("{}", path.0.display())
}
}
Err(err) => {
println!("{err:?}");
return Err(anyhow::anyhow!("{:?}", err));
}
}
} else {
let mut picker = Picker::<String>::new();
if args.threaded {
picker.inject_items_threaded(|i| {
for line in io::stdin().lock().lines().map_while(Result::ok) {
i.push(SelectableItem::new(line), |item, columns| {
columns[0] = item.to_string().into()
});
}
});
} else {
picker.inject_items(|i| {
for line in io::stdin().lock().lines().map_while(Result::ok) {
i.push(SelectableItem::new(line), |item, columns| {
columns[0] = item.to_string().into()
});
}
});
}
match picker.run() {
Ok(lines) => {
for line in lines {
println!("{}", line)
}
}
Err(err) => {
println!("{err:?}");
return Err(anyhow::anyhow!("{:?}", err));
}
}
}
Ok(())
}
fn walk_dir(dir: PathBuf, i: &nucleo::Injector<SelectableItem<DisplayPath>>) {
if let Ok(entries) = fs::read_dir(&dir) {
for entry in entries.flatten() {
let path = entry.path();
i.push(SelectableItem::new(DisplayPath(path)), |item, columns| {
columns[0] = item.to_string().into()
});
}
}
}
fn walk_dir_recursive(dir: &PathBuf, injector: &nucleo::Injector<SelectableItem<DisplayPath>>) {
if let Ok(entries) = fs::read_dir(dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
walk_dir_recursive(&path, injector);
} else {
injector.push(SelectableItem::new(DisplayPath(path)), |item, columns| {
columns[0] = item.to_string().into()
});
}
}
}
}