m2 0.0.0

Set of Unix tools to work with m2dirs
Documentation
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}");
    }
}