use std::collections::HashMap;
use super::error::ConfigError;
use super::store::config;
pub fn compiled_classes() -> HashMap<String, Vec<String>> {
fn gl(exts: &[&str]) -> Vec<String> {
exts.iter().map(|e| format!("*.{e}")).collect()
}
HashMap::from([
(
"image".into(),
gl(&[
"png", "jfi", "jfif", "jif", "jpe", "jpeg", "jpg", "gif", "bmp", "tiff", "tif",
"ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw", "svg", "stl", "eps", "dvi", "ps",
"cbr", "jpf", "cbz", "xpm", "ico", "cr2", "orf", "nef", "heif", "avif", "jxl",
"j2k", "jp2", "j2c", "jpx",
]),
),
(
"video".into(),
gl(&[
"avi", "flv", "m2v", "m4v", "mkv", "mov", "mp4", "mpeg", "mpg", "ogm", "ogv",
"vob", "wmv", "webm", "m2ts", "heic",
]),
),
(
"music".into(),
gl(&["aac", "m4a", "mp3", "ogg", "wma", "mka", "opus"]),
),
("lossless".into(), gl(&["alac", "ape", "flac", "wav"])),
(
"crypto".into(),
gl(&["asc", "enc", "gpg", "pgp", "sig", "signature", "pfx", "p12"]),
),
(
"document".into(),
gl(&[
"djvu", "doc", "docx", "dvi", "eml", "eps", "fotd", "key", "keynote", "numbers",
"odp", "odt", "pages", "pdf", "ppt", "pptx", "rtf", "xls", "xlsx",
]),
),
(
"compressed".into(),
gl(&[
"zip", "tar", "Z", "z", "gz", "bz2", "a", "ar", "7z", "iso", "dmg", "tc", "rar",
"par", "tgz", "xz", "txz", "lz", "tlz", "lzma", "deb", "rpm", "zst", "lz4", "cpio",
]),
),
(
"compiled".into(),
gl(&["class", "elc", "hi", "o", "pyc", "zwc", "ko"]),
),
(
"temp".into(),
gl(&["tmp", "swp", "swo", "swn", "bak", "bkp", "bk"]),
),
(
"immediate".into(),
vec![
"Makefile".into(),
"Cargo.toml".into(),
"SConstruct".into(),
"CMakeLists.txt".into(),
"build.gradle".into(),
"pom.xml".into(),
"Rakefile".into(),
"package.json".into(),
"Gruntfile.js".into(),
"Gruntfile.coffee".into(),
"BUILD".into(),
"BUILD.bazel".into(),
"WORKSPACE".into(),
"build.xml".into(),
"Podfile".into(),
"webpack.config.js".into(),
"meson.build".into(),
"composer.json".into(),
"RoboFile.php".into(),
"PKGBUILD".into(),
"Justfile".into(),
"Procfile".into(),
"Dockerfile".into(),
"Containerfile".into(),
"Vagrantfile".into(),
"Brewfile".into(),
"Gemfile".into(),
"Pipfile".into(),
"build.sbt".into(),
"mix.exs".into(),
"bsconfig.json".into(),
"tsconfig.json".into(),
],
),
])
}
pub fn resolve_classes() -> HashMap<String, Vec<String>> {
let mut classes = compiled_classes();
if let Some(cfg) = config() {
for (name, patterns) in &cfg.class {
classes.insert(name.clone(), patterns.clone());
}
}
classes
}
pub fn all_class_names() -> Vec<String> {
let mut names: Vec<String> = resolve_classes().into_keys().collect();
names.sort();
names
}
fn format_class_toml(name: &str, patterns: &[String]) -> String {
let indent = " ".repeat(name.len() + 4); let mut lines = vec![format!("{name} = [")];
for (i, pat) in patterns.iter().enumerate() {
let entry = format!("\"{pat}\"");
let last = lines.last_mut().unwrap();
if i == 0 {
last.push_str(&entry);
} else {
let trial_len = last.len() + 2 + entry.len();
if trial_len > 72 {
last.push(',');
lines.push(format!("{indent}{entry}"));
} else {
last.push_str(", ");
last.push_str(&entry);
}
}
}
lines.last_mut().unwrap().push(']');
lines.join("\n")
}
pub fn show_class(name: &str) -> Result<(), ConfigError> {
let classes = resolve_classes();
if let Some(patterns) = classes.get(name) {
println!("[class]");
println!("{}", format_class_toml(name, patterns));
Ok(())
} else {
let mut names: Vec<_> = classes.keys().collect();
names.sort();
let candidates = names
.iter()
.map(|s| s.as_str())
.collect::<Vec<_>>()
.join(", ");
Err(ConfigError::NotFound {
kind: "class",
kind_plural: "classes",
name: name.to_string(),
candidates,
})
}
}
pub fn show_class_all() {
let classes = resolve_classes();
let mut names: Vec<_> = classes.keys().collect();
names.sort();
println!("[class]");
for name in names {
println!("{}", format_class_toml(name, &classes[name]));
}
}