use crate::compsys::ported::shared::{declare_locals, eval_comp};
use crate::ported::glob::shtokenize;
use crate::ported::params::{getaparam, getsparam, setaparam, setsparam};
use crate::ported::subst::filesubstr;
use crate::ported::utils::{errflag, quotestring};
use crate::ported::zle::complete::bin_compadd;
use crate::ported::zsh_h::{options, ERRFLAG_ERROR, MAX_OPS, QT_BACKSLASH};
use std::sync::atomic::Ordering;
fn make_ops() -> options {
options {
ind: [0u8; MAX_OPS],
args: Vec::new(),
argscount: 0,
argsalloc: 0,
}
}
fn eval_glob(prefix: &str, suffix: &str, line: u64) -> Vec<String> {
let numeric = getsparam("NUMERIC")
.filter(|v| !v.is_empty())
.unwrap_or_else(|| "1".to_string());
eval_comp(&format!("file=({prefix}*{suffix}(om[{numeric}]N))"), line);
getaparam("file").unwrap_or_default()
}
pub fn _most_recent_file() -> i32 {
let _fn_scope = crate::compsys::ported::shared::FnScope::enter("_most_recent_file");
declare_locals(&["file", "tilde", "etilde"], 0);
let prefix = getsparam("PREFIX").unwrap_or_default();
let suffix = getsparam("SUFFIX").unwrap_or_default();
let file: Vec<String> = if prefix.starts_with('~') && prefix[1..].contains('/') {
let tilde = prefix[..prefix.find('/').unwrap()].to_string();
let _ = setsparam("tilde", &tilde);
let mut tok = tilde.clone();
shtokenize(&mut tok);
let etilde = filesubstr(&tok, true).unwrap_or_else(|| tilde.clone());
if errflag.load(Ordering::SeqCst) & ERRFLAG_ERROR != 0 {
return 1;
}
let _ = setsparam("etilde", &etilde);
let globbed = eval_glob(&prefix, &suffix, 17);
globbed
.iter()
.map(|f| {
let rest = f.strip_prefix(etilde.as_str()).unwrap_or(f);
format!("{tilde}{}", quotestring(rest, QT_BACKSLASH))
})
.collect()
} else {
eval_glob(&prefix, &suffix, 21)
.iter()
.map(|f| quotestring(f, QT_BACKSLASH))
.collect()
};
setaparam("file", file.clone());
if file.is_empty() {
return 1;
}
let mut argv: Vec<String> = vec![
"-U".to_string(),
"-i".to_string(),
getsparam("IPREFIX").unwrap_or_default(),
"-I".to_string(),
getsparam("ISUFFIX").unwrap_or_default(),
"-f".to_string(),
"-Q".to_string(),
"--".to_string(),
];
argv.extend(file);
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);
}
}