use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};
use std::process;
use uucore::Args;
use uucore::display::Quotable;
use uucore::locale;
#[allow(clippy::type_complexity)]
pub fn get_all_utilities<T: Args>(
util_map: &phf::OrderedMap<&'static str, (fn(T) -> i32, fn() -> clap::Command)>,
) -> Vec<&'static str> {
std::iter::once("coreutils")
.chain(util_map.keys().copied())
.collect()
}
pub fn not_found(util: &OsStr) -> ! {
println!("{}: function/utility not found", util.maybe_quote());
process::exit(1);
}
pub fn setup_localization_or_exit(util_name: &str) {
let util_name = get_canonical_util_name(util_name);
locale::setup_localization(util_name).unwrap_or_else(|err| {
match err {
locale::LocalizationError::ParseResource {
error: err_msg,
snippet,
} => eprintln!("Localization parse error at {snippet}: {err_msg}"),
other => eprintln!("Could not init the localization system: {other}"),
}
process::exit(99)
});
}
fn get_canonical_util_name(util_name: &str) -> &str {
match util_name {
"[" => "test",
"md5sum" | "sha1sum" | "sha224sum" | "sha256sum" | "sha384sum" | "sha512sum"
| "sha3sum" | "sha3-224sum" | "sha3-256sum" | "sha3-384sum" | "sha3-512sum"
| "shake128sum" | "shake256sum" | "b2sum" | "b3sum" => "hashsum",
"dir" => "ls",
_ => util_name,
}
}
pub fn find_prefixed_util<'a>(
binary_name: &str,
mut util_keys: impl Iterator<Item = &'a str>,
) -> Option<&'a str> {
util_keys.find(|util| {
binary_name.ends_with(*util)
&& binary_name.len() > util.len() && !binary_name[..binary_name.len() - (*util).len()]
.ends_with(char::is_alphanumeric)
})
}
pub fn binary_path(args: &mut impl Iterator<Item = OsString>) -> PathBuf {
match args.next() {
Some(ref s) if !s.is_empty() => PathBuf::from(s),
_ => std::env::current_exe().unwrap(),
}
}
pub fn name(binary_path: &Path) -> Option<&str> {
binary_path.file_stem()?.to_str()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_canonical_util_name() {
assert_eq!(get_canonical_util_name("["), "test");
assert_eq!(get_canonical_util_name("md5sum"), "hashsum");
assert_eq!(get_canonical_util_name("dir"), "ls");
assert_eq!(get_canonical_util_name("cat"), "cat");
}
#[test]
fn test_name() {
assert_eq!(name(Path::new("/usr/bin/ls")), Some("ls"));
assert_eq!(name(Path::new("cat")), Some("cat"));
assert_eq!(
name(Path::new("./target/debug/coreutils")),
Some("coreutils")
);
assert_eq!(name(Path::new("program.exe")), Some("program"));
assert_eq!(name(Path::new("/path/to/utility.bin")), Some("utility"));
assert_eq!(name(Path::new("")), None);
assert_eq!(name(Path::new("/")), None);
}
#[test]
fn test_find_prefixed_util() {
let utils = ["test", "cat", "ls", "cp"];
assert_eq!(
find_prefixed_util("uu_test", utils.iter().copied()),
Some("test")
);
assert_eq!(
find_prefixed_util("my-cat", utils.iter().copied()),
Some("cat")
);
assert_eq!(
find_prefixed_util("prefix_ls", utils.iter().copied()),
Some("ls")
);
assert_eq!(find_prefixed_util("prefixcat", utils.iter().copied()), None); assert_eq!(find_prefixed_util("testcat", utils.iter().copied()), None);
assert_eq!(find_prefixed_util("unknown", utils.iter().copied()), None);
assert_eq!(find_prefixed_util("", utils.iter().copied()), None);
assert_eq!(find_prefixed_util("test", utils.iter().copied()), None);
assert_eq!(find_prefixed_util("cat", utils.iter().copied()), None);
}
}