use crate::compsys::ported::shared::dispatch_action_command;
use crate::ported::params::getsparam;
pub fn _bash_completions() -> i32 {
let _fn_scope = crate::compsys::ported::shared::FnScope::enter("_bash_completions");
let keys = getsparam("KEYS").unwrap_or_default();
let key = keys.chars().last().unwrap_or(' ');
let line: u64 = match key {
'!' => 33,
'$' => 35,
'@' => 38,
'/' => 40,
'~' => 42,
_ => 44,
};
let argv: Vec<String> = match key {
'!' => vec!["_command_names".to_string()],
'$' => vec![
"-".to_string(),
"parameters".to_string(),
"_wanted".to_string(),
"parameters".to_string(),
"expl".to_string(),
"exported parameter".to_string(),
"_parameters".to_string(),
"-g".to_string(),
"*export*".to_string(),
],
'@' => vec!["_hosts".to_string()],
'/' => vec!["_files".to_string()],
'~' => vec!["_users".to_string()],
_ => {
return dispatch_action_command(
"_message",
&[format!("Key {} is not understood", key)],
line,
)
}
};
dispatch_action_command("_main_complete", &argv, line)
}
#[cfg(test)]
mod tests {
use super::*;
fn run_with_keys(keys: &[u8]) -> (i32, String) {
use std::io::Read;
*crate::ported::zle::zle_keymap::keybuf.lock().unwrap() = keys.to_vec();
crate::ported::utils::inc_locallevel(); crate::ported::zle::zle_params::makezleparams(1);
let mut fds = [0 as libc::c_int; 2];
assert_eq!(unsafe { libc::pipe(fds.as_mut_ptr()) }, 0, "pipe failed");
let saved_stderr = unsafe { libc::dup(2) };
assert!(saved_stderr >= 0, "dup(2) failed");
assert!(unsafe { libc::dup2(fds[1], 2) } >= 0, "dup2 onto fd 2 failed");
let status = _bash_completions();
unsafe {
libc::dup2(saved_stderr, 2);
libc::close(saved_stderr);
libc::close(fds[1]);
}
let mut err = String::new();
let mut reader = unsafe { <std::fs::File as std::os::fd::FromRawFd>::from_raw_fd(fds[0]) };
let _ = reader.read_to_string(&mut err);
crate::ported::params::endparamscope(); crate::ported::utils::errflag.store(0, std::sync::atomic::Ordering::Relaxed);
(status, err)
}
#[test]
fn unknown_key_takes_the_message_arm() {
let _g = crate::test_util::global_state_lock();
let _z = crate::ported::zle::zle_main::zle_test_setup();
let (status, err) = run_with_keys(b"abc");
assert_eq!(status, 127, "c:908 — `_message` resolves nowhere without an executor");
assert!(
err.contains(":44: command not found: _message"),
"the last key `c` is not understood, so sh:44 runs `_message`; got `{err}`"
);
}
#[test]
fn bang_key_takes_the_command_names_arm() {
let _g = crate::test_util::global_state_lock();
let _z = crate::ported::zle::zle_main::zle_test_setup();
let (status, err) = run_with_keys(b"\x1b!");
assert_eq!(status, 127, "c:908 — `_main_complete` resolves nowhere without an executor");
assert!(
err.contains(":33: command not found: _main_complete"),
"the last key `!` selects sh:33; got `{err}`"
);
}
}