use crate::compsys::ported::_message::_message;
use crate::compsys::ported::_normal::_normal;
use crate::ported::exec_hooks::dispatch_function_call;
use crate::ported::params::{getaparam, getsparam, setsparam};
use crate::ported::zle::compcore::{get_compstate_str, set_compstate_str};
fn assoc_get(name: &str, key: &str) -> Option<String> {
let arr = getaparam(name)?;
arr.chunks(2)
.find(|kv| kv.first().map(|k| k == key).unwrap_or(false))
.and_then(|kv| kv.get(1).cloned())
}
pub fn _complete() -> i32 {
let mut ret: i32 = 1;
let oldcontext = getsparam("curcontext").unwrap_or_default();
let compcontext = getsparam("compcontext").unwrap_or_default();
if !compcontext.is_empty() {
if compcontext.matches(':').count() >= 2 {
let mut parts = compcontext.splitn(3, ':');
let tag = parts
.next()
.filter(|s| !s.is_empty())
.map(|s| s.to_string())
.unwrap_or_else(|| "values".to_string());
let descr = parts
.next()
.filter(|s| !s.is_empty())
.map(|s| s.to_string())
.unwrap_or_else(|| "value".to_string());
let action = parts.next().unwrap_or("").to_string();
if action.trim().is_empty() {
return _message(&["-e".to_string(), tag, descr]);
}
let parts: Vec<String> = action
.split_whitespace()
.map(|s| s.to_string())
.collect();
if let Some((cmd, rest)) = parts.split_first() {
return dispatch_function_call(cmd, rest).unwrap_or(1);
}
return 1;
}
let comp = assoc_get("_comps", &compcontext).unwrap_or_default();
if !comp.is_empty() {
return dispatch_function_call(&comp, &[]).unwrap_or(1);
}
return 1;
}
let first_comp = assoc_get("_comps", "-first-").unwrap_or_default();
if !first_comp.is_empty() {
let service =
assoc_get("_services", "-first-").unwrap_or_else(|| "-first-".to_string());
let _ = setsparam("service", &service);
if dispatch_function_call(&first_comp, &[]).unwrap_or(1) == 0 {
ret = 0;
}
if getsparam("_compskip").as_deref() == Some("all") {
let _ = setsparam("_compskip", "");
return ret;
}
}
let vared = get_compstate_str("vared").unwrap_or_default();
if !vared.is_empty() {
set_compstate_str("context", "vared");
}
let context = get_compstate_str("context").unwrap_or_default();
if context == "command" {
let _ = setsparam("curcontext", &oldcontext);
if _normal(&["-s".to_string()]) == 0 {
ret = 0;
}
} else {
let cname = format!("-{}-", context.replace('_', "-"));
let mut comp = assoc_get("_comps", &cname).unwrap_or_default();
let service = assoc_get("_services", &cname).unwrap_or_else(|| cname.clone());
let _ = setsparam("service", &service);
if comp.is_empty() {
let cs = getsparam("_compskip").unwrap_or_default();
if cs.contains("default") {
let _ = setsparam("_compskip", "");
return 1;
}
comp = assoc_get("_comps", "-default-").unwrap_or_default();
let default_service =
assoc_get("_services", "-default-").unwrap_or_else(|| "-default-".to_string());
let _ = setsparam("service", &default_service);
}
if !comp.is_empty() {
if dispatch_function_call(&comp, &[]).unwrap_or(1) == 0 {
ret = 0;
}
}
}
let _ = setsparam("_compskip", "");
ret
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn returns_one_without_executor() {
let _g = crate::test_util::global_state_lock();
let _ = setsparam("compcontext", "");
set_compstate_str("context", "command");
crate::ported::params::setaparam("_comps", Vec::new());
let _r = _complete();
}
}