use crate::compsys::ported::_arguments::_arguments;
use crate::ported::exec::execute_script;
const HOOKS_FN_SOURCE: &str = r#"_add-zsh-hook_hooks() {
local expl
if (( $+opt_args[-d] )); then
_wanted functions expl "installed hook" compadd -a - "$line[1]_functions" && return 0
else
_functions && return 0
fi
return 1
}"#;
fn build_specs() -> Vec<String> {
[
"(-d -D -U -z -k)-L[output in form of 'typeset' commands]",
"(-L -D -U -z -k)-d[remove HOOK from the array]",
"(-L -d -U -z -k)-D[interpret HOOK as pattern to remove from the array]",
"(-L -d -D)-U[suppress alias expansion for functions]",
"(-L -d -D -k)-z[mark function for zsh-style autoloading]",
"(-L -d -D -z)-k[mark function for ksh-style autoloading]",
":hook class:(chpwd precmd preexec periodic zshaddhistory zshexit zsh_directory_name)",
":hook function:_add-zsh-hook_hooks",
]
.iter()
.map(|s| s.to_string())
.collect()
}
fn build_arguments_call() -> Vec<String> {
let mut call: Vec<String> = vec![
"-s".to_string(),
"-w".to_string(),
"-S".to_string(),
":".to_string(),
];
call.extend(build_specs());
call
}
pub fn _add_zsh_hook(_args: &[String]) -> i32 {
let _ = execute_script(HOOKS_FN_SOURCE);
let call = build_arguments_call();
_arguments(&call)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn specs_match_upstream_list() {
let specs = build_specs();
assert_eq!(specs.len(), 8);
assert_eq!(
specs[0],
"(-d -D -U -z -k)-L[output in form of 'typeset' commands]"
);
assert_eq!(specs[1], "(-L -D -U -z -k)-d[remove HOOK from the array]");
assert_eq!(
specs[2],
"(-L -d -U -z -k)-D[interpret HOOK as pattern to remove from the array]"
);
assert_eq!(
specs[3],
"(-L -d -D)-U[suppress alias expansion for functions]"
);
assert_eq!(
specs[4],
"(-L -d -D -k)-z[mark function for zsh-style autoloading]"
);
assert_eq!(
specs[5],
"(-L -d -D -z)-k[mark function for ksh-style autoloading]"
);
}
#[test]
fn hook_class_positional_lists_all_classes() {
let specs = build_specs();
assert_eq!(
specs[6],
":hook class:(chpwd precmd preexec periodic zshaddhistory zshexit zsh_directory_name)"
);
}
#[test]
fn hook_function_positional_uses_nested_helper() {
let specs = build_specs();
assert_eq!(specs[7], ":hook function:_add-zsh-hook_hooks");
}
#[test]
fn arguments_call_has_leading_flags_then_specs() {
let call = build_arguments_call();
assert_eq!(&call[..4], &["-s", "-w", "-S", ":"]);
assert_eq!(call.len(), 4 + 8);
assert_eq!(call.last().unwrap(), ":hook function:_add-zsh-hook_hooks");
}
#[test]
fn hooks_fn_source_is_faithful() {
assert!(HOOKS_FN_SOURCE.starts_with("_add-zsh-hook_hooks() {"));
assert!(HOOKS_FN_SOURCE.contains("(( $+opt_args[-d] ))"));
assert!(HOOKS_FN_SOURCE.contains(
r#"_wanted functions expl "installed hook" compadd -a - "$line[1]_functions""#
));
assert!(HOOKS_FN_SOURCE.contains("_functions && return 0"));
assert!(HOOKS_FN_SOURCE.contains("return 1"));
}
}