use crate::compsys::ported::_dynamic_directory_name::_dynamic_directory_name;
use crate::compsys::ported::_requested::_requested;
use crate::compsys::ported::_tags::_tags;
use crate::compsys::ported::_wanted::_wanted;
use crate::ported::exec_hooks::dispatch_function_call;
use crate::ported::params::{getaparam, getsparam, setaparam};
use crate::ported::zle::compcore::get_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,
}
}
fn is_array_param(name: &str) -> bool {
getaparam(name).is_some()
}
fn is_assoc_param(name: &str) -> bool {
crate::ported::params::paramtab_hashed_storage()
.lock()
.map(|t| t.contains_key(name))
.unwrap_or(false)
}
pub fn _subscript(args: &[String]) -> i32 {
let isuffix = getsparam("ISUFFIX").unwrap_or_default();
let _osuf = if !isuffix.contains(']') { "]" } else { "" };
let _ = args;
let _ = bin_compset(
"compset",
&[
"-P".to_string(),
"\\(([^\\(\\)]|\\(*\\))##\\)".to_string(),
],
&make_ops(),
0,
);
let prefix = getsparam("PREFIX").unwrap_or_default();
let cursor: i64 = getsparam("CURSOR")
.and_then(|s| s.parse().ok())
.unwrap_or(0);
let buffer = getsparam("BUFFER").unwrap_or_default();
if let Some(open_at) = (1..=cursor as usize).rev().find(|&i| {
buffer.as_bytes().get(i.saturating_sub(1)) == Some(&b'[')
}) {
let head = &buffer[..open_at.saturating_sub(1)];
if head.ends_with('~') {
return _dynamic_directory_name();
}
}
if prefix.starts_with(':') {
let classes: Vec<String> = vec![
"alnum", "alpha", "ascii", "blank", "cntrl", "digit", "graph", "lower",
"print", "punct", "space", "upper", "xdigit", "IFS", "IDENT", "IFSSPACE",
"WORD",
]
.into_iter()
.map(|s| s.to_string())
.collect();
setaparam("classes", classes);
return _wanted(&[
"characters".to_string(),
"expl".to_string(),
"character class".to_string(),
"compadd".to_string(),
"-p:".to_string(),
"-S".to_string(),
":]".to_string(),
"-a".to_string(),
"classes".to_string(),
]);
}
let param = get_compstate_str("parameter").unwrap_or_default();
if !param.is_empty() {
if is_assoc_param(¶m) {
let mut keys: Vec<String> = Vec::new();
if let Ok(tab) = crate::ported::params::paramtab_hashed_storage().lock() {
if let Some(h) = tab.get(¶m) {
keys.extend(h.keys().cloned());
}
}
keys.sort();
setaparam("subscript_keys", keys);
return _wanted(&[
"association-keys".to_string(),
"expl".to_string(),
"association key".to_string(),
"compadd".to_string(),
"-Q".to_string(),
"-a".to_string(),
"subscript_keys".to_string(),
]);
}
if is_array_param(¶m) {
let arr = getaparam(¶m).unwrap_or_default();
let n = arr.len();
let indices: Vec<String> = (1..=n).map(|i| i.to_string()).collect();
setaparam("subscript_indices", indices);
let _ = _tags(&["indexes".to_string(), "parameters".to_string()]);
loop {
if _tags(&[]) != 0 {
break;
}
if _requested(&["indexes".to_string()]) == 0 {
let _ = _wanted(&[
"-V".to_string(),
"indexes".to_string(),
"expl".to_string(),
"array index".to_string(),
"compadd".to_string(),
"-a".to_string(),
"subscript_indices".to_string(),
]);
return 0;
}
}
return 1;
}
}
dispatch_function_call("_dispatch", &["-math-".to_string(), "-math-".to_string()])
.unwrap_or(1)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn returns_one_without_executor() {
let _g = crate::test_util::global_state_lock();
let _ = crate::ported::params::setsparam("PREFIX", "");
let _ = crate::ported::params::setsparam("ISUFFIX", "");
let _r = _subscript(&[]);
}
}