use crate::compsys::ported::_default::_default;
use crate::compsys::ported::_wanted::_wanted;
use crate::ported::exec_hooks::dispatch_function_call;
use crate::ported::modules::zutil::lookupstyle;
use crate::ported::params::{getaparam, getiparam, getsparam, setsparam};
use crate::ported::pattern::{patcompile, pattry};
use crate::ported::zle::compcore::{get_compstate_str, set_compstate_str};
use crate::ported::zle::complete::bin_compset;
use crate::ported::zsh_h::{options, MAX_OPS};
fn make_ops() -> options {
options {
ind: [0u8; MAX_OPS],
args: Vec::new(),
argscount: 0,
argsalloc: 0,
}
}
pub fn _value(args: &[String]) -> i32 {
let service = getsparam("service").unwrap_or_default();
if !service.starts_with("-value-,") {
let mut strs: Vec<String> = vec!["-default-".to_string()];
let mut ctx = String::new();
let comp_context = get_compstate_str("context").unwrap_or_default();
let cc1 = getsparam("_comp_command1").unwrap_or_default();
let cc2 = getsparam("_comp_command2").unwrap_or_default();
let cc = getsparam("_comp_command").unwrap_or_default();
if !comp_context.ends_with("value") && !cc1.is_empty() {
ctx = cc;
strs.insert(0, cc1);
if !cc2.is_empty() {
strs.insert(0, cc2);
}
}
let param = get_compstate_str("parameter").unwrap_or_default();
let mut argv: Vec<String> = vec![format!("-value-,{},{}", param, ctx)];
for s in &strs {
argv.push(format!("-value-,{},{}", param, s));
argv.push(format!("-value-,-default-,{}", s));
}
return dispatch_function_call("_dispatch", &argv).unwrap_or(1);
}
let param = get_compstate_str("parameter").unwrap_or_default();
let context = get_compstate_str("context").unwrap_or_default();
if !param.contains('-') && context == "array_value" && param_is_assoc(¶m) {
let current = getiparam("CURRENT");
if current & 1 == 1 {
return _wanted(&[
"association-keys".to_string(),
"expl".to_string(),
"association key".to_string(),
"compadd".to_string(),
"-k".to_string(),
param,
]);
}
let words = getaparam("words").unwrap_or_default();
let cur_idx = current as usize;
let prev = if cur_idx >= 2 && cur_idx - 1 <= words.len() {
words[cur_idx - 2].clone()
} else {
String::new()
};
let new_param = format!("{}-{}", param, prev);
set_compstate_str("parameter", &new_param);
let argv = vec![
format!("-value-,{},", new_param),
format!("-value-,{},-default-", new_param),
"-value-,-default-,-default-".to_string(),
];
return dispatch_function_call("_dispatch", &argv).unwrap_or(1);
}
let curcontext = getsparam("curcontext").unwrap_or_default();
let pats = lookupstyle(
&format!(":completion:{}:", curcontext),
"assign-list",
);
let prefix = getsparam("PREFIX").unwrap_or_default();
let suffix = getsparam("SUFFIX").unwrap_or_default();
let assign_match = if !pats.is_empty() {
let joined = pats.join("|");
match patcompile(&joined, 0, None) {
Some(p) => pattry(&p, ¶m),
None => false,
}
} else {
false
};
let has_colon = format!("{}{}", prefix, suffix).contains(':');
if assign_match || has_colon {
let _ = bin_compset(
"compset",
&["-P".to_string(), "*:".to_string()],
&make_ops(),
0,
);
let _ = bin_compset(
"compset",
&["-S".to_string(), ":*".to_string()],
&make_ops(),
0,
);
let mut a: Vec<String> = vec!["-r".to_string(), "\\-\\n\\t /:".to_string()];
a.extend(args.iter().cloned());
_default(&a)
} else {
_default(args)
}
}
fn param_is_assoc(name: &str) -> bool {
crate::ported::params::paramtab_hashed_storage()
.lock()
.map(|tab| tab.contains_key(name))
.unwrap_or(false)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn outer_dispatch_returns_one_without_executor() {
let _g = crate::test_util::global_state_lock();
let _ = setsparam("service", "-value-");
let _ = setsparam("_comp_command", "");
set_compstate_str("context", "value");
set_compstate_str("parameter", "myvar");
assert_eq!(_value(&[]), 1);
}
}