use crate::ported::params::{getsparam, getiparam};
use crate::ported::zle::complete::bin_compadd;
use crate::ported::zsh_h::{options, MAX_OPS};
use std::fs;
use std::path::Path;
use std::time::SystemTime;
fn make_ops() -> options {
options {
ind: [0u8; MAX_OPS],
args: Vec::new(),
argscount: 0,
argsalloc: 0,
}
}
fn pick_nth_recent(prefix: &str, suffix: &str, n: i64) -> Option<String> {
let combined = format!("{}{}", prefix, suffix);
let (dir, fname_prefix) = match combined.rfind('/') {
Some(i) => (combined[..i].to_string(), combined[i + 1..].to_string()),
None => (".".to_string(), combined.clone()),
};
let (real_prefix, real_suffix) = if let Some(slash) = prefix.rfind('/') {
(prefix[slash + 1..].to_string(), suffix.to_string())
} else {
(prefix.to_string(), suffix.to_string())
};
let _ = fname_prefix;
let entries = fs::read_dir(Path::new(&dir)).ok()?;
let mut matches: Vec<(SystemTime, String)> = Vec::new();
for ent in entries.flatten() {
let name = ent.file_name().to_string_lossy().to_string();
if name.starts_with(&real_prefix) && name.ends_with(&real_suffix) {
if let Ok(meta) = ent.metadata() {
if let Ok(mtime) = meta.modified() {
let full = if dir == "." {
name
} else {
format!("{}/{}", dir, name)
};
matches.push((mtime, full));
}
}
}
}
if matches.is_empty() {
return None;
}
matches.sort_by(|a, b| b.0.cmp(&a.0)); let idx = if n >= 0 {
(n.saturating_sub(1)) as usize
} else {
matches.len().saturating_sub((-n) as usize)
};
matches.get(idx).map(|t| t.1.clone())
}
pub fn _most_recent_file() -> i32 {
let prefix = getsparam("PREFIX").unwrap_or_default();
let suffix = getsparam("SUFFIX").unwrap_or_default();
let numeric = getiparam("NUMERIC");
let n = if numeric == 0 { 1 } else { numeric };
let picked = match pick_nth_recent(&prefix, &suffix, n) {
Some(f) => f,
None => return 1,
};
let iprefix = getsparam("IPREFIX").unwrap_or_default();
let isuffix = getsparam("ISUFFIX").unwrap_or_default();
let argv: Vec<String> = vec![
"-U".to_string(),
"-i".to_string(),
iprefix,
"-I".to_string(),
isuffix,
"-f".to_string(),
"-Q".to_string(),
"--".to_string(),
picked,
];
bin_compadd("compadd", &argv, &make_ops(), 0)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ported::params::setsparam;
#[test]
fn no_match_returns_one() {
let _g = crate::test_util::global_state_lock();
let _ = setsparam("PREFIX", "/nonexistent/path/prefix");
let _ = setsparam("SUFFIX", "");
assert_eq!(_most_recent_file(), 1);
}
}