use std::{
error::Error,
io::{BufRead, IsTerminal, stdin},
path::PathBuf,
process::exit,
};
use m2dir::Entry;
pub fn shortest_unique(strs: Vec<String>) -> Vec<String> {
let n = strs.len();
if n <= 1 {
return strs;
}
let mut idx: Vec<usize> = (0..n).collect();
idx.sort_by_key(|&i| &strs[i]);
fn common_prefix_bytes(a: &str, b: &str) -> usize {
a.as_bytes()
.iter()
.zip(b.as_bytes().iter())
.take_while(|(x, y)| x == y)
.count()
}
let mut need = vec![0; n];
for w in idx.windows(2) {
let i = w[0];
let j = w[1];
let cp = common_prefix_bytes(&strs[i], &strs[j]);
need[i] = need[i].max(cp);
need[j] = need[j].max(cp);
}
let mut out = Vec::with_capacity(n);
for (i, s) in strs.iter().enumerate() {
let l = need[i];
let take = if l >= s.len() { s.len() } else { l + 1 };
out.push(s[..take].to_string());
}
out
}
pub fn run() -> Result<(), Box<dyn Error>> {
let mut paths = Vec::new();
for arg in std::env::args().skip(1) {
match arg.as_str() {
"-h" | "--help" => {
eprint!("{}", include_str!("./help.txt"));
exit(0)
}
"-v" | "--version" => {
eprintln!("{} v{}", env!("CARGO_BIN_NAME"), env!("CARGO_PKG_VERSION"));
exit(0);
}
_ => paths.push(arg),
}
}
if !stdin().is_terminal() {
paths.extend(stdin().lock().lines().filter_map(Result::ok));
}
shortest_unique(
paths
.iter()
.map(PathBuf::from)
.map(Entry::try_from)
.filter_map(Result::ok)
.map(|entry| entry.id().to_string())
.collect(),
)
.iter()
.for_each(|id| println!("{id}"));
Ok(())
}
pub fn main() {
if let Err(e) = run() {
eprintln!("m2sort: {e}");
}
}