use crate::ported::modules::zutil::{lookupstyle, testforstyle};
use crate::ported::params::{getaparam, getiparam, getsparam};
use crate::ported::zle::compcore::{get_compstate_str, set_compstate_str};
use crate::ported::zle::complete::bin_compadd;
use crate::ported::zsh_h::{isset, options, AUTOMENU, MAX_OPS};
fn make_ops() -> options {
options {
ind: [0u8; MAX_OPS],
args: Vec::new(),
argscount: 0,
argsalloc: 0,
}
}
fn lastcomp_get(key: &str) -> Option<String> {
let arr = getaparam("_lastcomp")?;
arr.chunks(2)
.find(|kv| kv.first().map(|k| k == key).unwrap_or(false))
.and_then(|kv| kv.get(1).cloned())
}
pub fn _oldlist() -> i32 {
if getiparam("_matcher_num") > 1 {
return 1;
}
let lastcomp_nmatches: i64 = lastcomp_get("nmatches")
.and_then(|s| s.parse().ok())
.unwrap_or(0);
if lastcomp_nmatches == 0 {
return 1;
}
let curcontext = getsparam("curcontext").unwrap_or_default();
let list = lookupstyle(&format!(":completion:{}:", curcontext), "old-list")
.first()
.cloned()
.unwrap_or_default();
let old_list = get_compstate_str("old_list").unwrap_or_default();
let widget = getsparam("WIDGET").unwrap_or_default();
let lastwidget = getsparam("LASTWIDGET").unwrap_or_default();
let widgetstyle = getsparam("WIDGETSTYLE").unwrap_or_default();
if !old_list.is_empty()
&& list != "never"
&& lastwidget != "_complete_help"
&& widget != "_complete_help"
{
let style_force_list = list == "always" || list != "shown";
if widgetstyle.contains("list") && style_force_list {
set_compstate_str("old_list", "keep");
return 0;
}
let completer = lastcomp_get("completer").unwrap_or_default();
if !completer.is_empty() && list.contains(&completer) {
let insert_kind = lastcomp_get("insert").unwrap_or_default();
if insert_kind.starts_with("unambig") {
set_compstate_str("to_end", "single");
}
set_compstate_str("old_list", "keep");
if isset(AUTOMENU) {
set_compstate_str("insert", "menu");
} else {
let prefix = getsparam("PREFIX").unwrap_or_default();
let suffix = getsparam("SUFFIX").unwrap_or_default();
let argv = vec![
"-Qs".to_string(),
suffix,
"-".to_string(),
prefix,
];
let _ = bin_compadd("compadd", &argv, &make_ops(), 0);
}
return 0;
}
}
let old_insert = get_compstate_str("old_insert").unwrap_or_default();
if old_insert.is_empty()
&& !old_list.is_empty()
&& (lastcomp_nmatches != 0 || widget != lastwidget)
&& lastwidget != "_complete_help"
&& widget != "_complete_help"
{
set_compstate_str("old_list", "keep");
return 0;
}
let widget_is_complete = widgetstyle.contains("complete")
|| widgetstyle.contains("complete-prefix")
|| widgetstyle.contains("complete-word");
let old_menu_on = testforstyle(&format!(":completion:{}:", curcontext), "old-menu") == 0;
if widget_is_complete && old_menu_on {
if !old_insert.is_empty() {
set_compstate_str("old_list", "keep");
let oi: i64 = old_insert.parse().unwrap_or(0);
if widgetstyle.contains("reverse") {
set_compstate_str("insert", &(oi - 1).to_string());
} else {
set_compstate_str("insert", &(oi + 1).to_string());
}
return 0;
} else {
return 1;
}
}
1
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ported::params::setiparam;
#[test]
fn matcher_num_gt_one_short_circuits() {
let _g = crate::test_util::global_state_lock();
setiparam("_matcher_num", 5);
assert_eq!(_oldlist(), 1);
setiparam("_matcher_num", 0);
}
}