use std::collections::HashMap;
#[allow(unused_imports)]
use crate::ported::zle::{
deltochar::*, textobjects::*, zle_h::*, zle_hist::*, zle_main::*, zle_misc::*, zle_move::*,
zle_params::*, zle_refresh::*, zle_tricky::*, zle_utils::*, zle_vi::*, zle_word::*,
};
#[allow(unused_imports)]
pub fn widgetstr(name: &str, is_user: bool, is_completion: bool) -> String {
if is_completion {
format!("completion:{}", name)
} else if is_user {
format!("user:{}", name)
} else {
"builtin".to_string()
}
}
pub fn getpmwidgets(
_ht: *mut crate::ported::zsh_h::HashTable,
name: &str,
) -> Option<crate::ported::zsh_h::Param> {
use crate::ported::zsh_h::{hashnode, param, Param, PM_READONLY, PM_SCALAR, PM_UNSET};
static WIDGETS_PARAM_INIT: std::sync::Once = std::sync::Once::new();
WIDGETS_PARAM_INIT.call_once(|| {
crate::ported::zle::zle_thingy::init_thingies();
});
let mk = |u_str: String, extra: i32| -> Param {
Box::new(param {
node: hashnode {
next: None,
nam: name.to_string(),
flags: PM_SCALAR as i32 | PM_READONLY as i32 | extra,
},
u_data: 0,
u_arr: None,
u_str: Some(u_str),
u_val: 0,
u_dval: 0.0,
u_hash: None,
gsu_s: None,
gsu_i: None,
gsu_f: None,
gsu_a: None,
gsu_h: None,
base: 0,
width: 0,
env: None,
ename: None,
old: None,
level: 0,
})
};
let label_opt = {
let tab = crate::ported::zle::zle_thingy::thingytab().lock().ok();
tab.and_then(|t| {
t.get(name).cloned().map(|th| {
let w_opt = th.widget;
match w_opt {
None => "undefined".to_string(),
Some(w) => {
use crate::ported::zle::zle_h::{
WidgetImpl, WIDGET_INT, WIDGET_NCOMP,
};
if (w.flags & WIDGET_INT) != 0 {
"builtin".to_string()
} else if (w.flags & WIDGET_NCOMP) != 0 {
if let WidgetImpl::Comp { wid, func, .. } = &w.u {
format!("completion:{}:{}", wid, func)
} else {
"builtin".to_string()
}
} else {
match &w.u {
WidgetImpl::Internal(_) => "builtin".to_string(),
WidgetImpl::UserFunc(fnnam) => format!("user:{}", fnnam),
WidgetImpl::Comp { wid, func, .. } => {
format!("completion:{}:{}", wid, func)
}
}
}
}
}
})
})
};
match label_opt {
Some(label) => Some(mk(label, 0)),
None => Some(mk(String::new(), PM_UNSET as i32)),
}
}
pub fn scanpmwidgets(
_ht: *mut crate::ported::zsh_h::HashTable,
func: Option<crate::ported::zsh_h::ScanFunc>,
flags: i32,
) {
use crate::ported::zsh_h::{hashnode, param, PM_READONLY, PM_SCALAR};
static WIDGETS_SCAN_INIT: std::sync::Once = std::sync::Once::new();
WIDGETS_SCAN_INIT.call_once(|| {
crate::ported::zle::zle_thingy::init_thingies();
});
let f = match func {
Some(f) => f,
None => return,
};
let names = crate::ported::zle::zle_thingy::listwidgets();
for name in &names {
let label = match crate::ported::zle::zle_thingy::getwidgettarget(name) {
Some(t) if t == *name => "builtin".to_string(),
Some(t) => format!("user:{}", t),
None => continue,
};
let pm = param {
node: hashnode {
next: None,
nam: name.clone(),
flags: PM_SCALAR as i32 | PM_READONLY as i32,
},
u_data: 0,
u_arr: None,
u_str: Some(label),
u_val: 0,
u_dval: 0.0,
u_hash: None,
gsu_s: None,
gsu_i: None,
gsu_f: None,
gsu_a: None,
gsu_h: None,
base: 0,
width: 0,
env: None,
ename: None,
old: None,
level: 0,
};
let node_box = Box::new(pm.node.clone());
f(&node_box, flags); }
}
pub fn keymapsgetfn(_pm: *mut crate::ported::zsh_h::param) -> Vec<String> {
static KEYMAPS_PARAM_INIT: std::sync::Once = std::sync::Once::new();
KEYMAPS_PARAM_INIT.call_once(|| {
crate::ported::zle::zle_keymap::default_bindings();
});
let mut names: Vec<String> = crate::ported::zle::zle_keymap::keymapnamtab()
.lock()
.map(|t| t.keys().cloned().collect())
.unwrap_or_default();
names.sort();
names
}
pub fn setup_() -> i32 {
0 }
pub fn features_() -> i32 {
0 }
pub fn enables_() -> i32 {
0 }
pub fn boot_() -> i32 {
0 }
pub fn cleanup_() -> i32 {
0 }
pub fn finish_() -> i32 {
0 }
pub const BUILTIN_WIDGETS: &[&str] = &[
"accept-and-hold",
"accept-and-infer-next-history",
"accept-line",
"accept-line-and-down-history",
"backward-char",
"backward-delete-char",
"backward-kill-line",
"backward-kill-word",
"backward-word",
"beep",
"beginning-of-buffer-or-history",
"beginning-of-history",
"beginning-of-line",
"beginning-of-line-hist",
"capitalize-word",
"clear-screen",
"complete-word",
"copy-prev-word",
"copy-region-as-kill",
"delete-char",
"delete-char-or-list",
"delete-word",
"describe-key-briefly",
"digit-argument",
"down-case-word",
"down-history",
"down-line",
"down-line-or-history",
"down-line-or-search",
"emacs-backward-word",
"emacs-forward-word",
"end-of-buffer-or-history",
"end-of-history",
"end-of-line",
"end-of-line-hist",
"exchange-point-and-mark",
"execute-last-named-cmd",
"execute-named-cmd",
"expand-history",
"expand-or-complete",
"expand-or-complete-prefix",
"expand-word",
"forward-char",
"forward-word",
"get-line",
"gosmacs-transpose-chars",
"history-beginning-search-backward",
"history-beginning-search-forward",
"history-incremental-search-backward",
"history-incremental-search-forward",
"history-search-backward",
"history-search-forward",
"insert-last-word",
"kill-buffer",
"kill-line",
"kill-region",
"kill-whole-line",
"kill-word",
"list-choices",
"list-expand",
"magic-space",
"menu-complete",
"menu-expand-or-complete",
"neg-argument",
"overwrite-mode",
"pound-insert",
"push-input",
"push-line",
"push-line-or-edit",
"quoted-insert",
"bslashquote-line",
"bslashquote-region",
"read-command",
"recursive-edit",
"redisplay",
"redo",
"reset-prompt",
"reverse-menu-complete",
"run-help",
"self-insert",
"self-insert-unmeta",
"send-break",
"set-mark-command",
"spell-word",
"split-undo",
"transpose-chars",
"transpose-words",
"undefined-key",
"undo",
"universal-argument",
"up-case-word",
"up-history",
"up-line",
"up-line-or-history",
"up-line-or-search",
"vi-add-eol",
"vi-add-next",
"vi-backward-blank-word",
"vi-backward-char",
"vi-backward-delete-char",
"vi-backward-kill-word",
"vi-backward-word",
"vi-beginning-of-line",
"vi-caps-lock-panic",
"vi-change",
"vi-change-eol",
"vi-change-whole-line",
"vi-cmd-mode",
"vi-delete",
"vi-delete-char",
"vi-digit-or-beginning-of-line",
"vi-down-line-or-history",
"vi-end-of-line",
"vi-fetch-history",
"vi-find-next-char",
"vi-find-next-char-skip",
"vi-find-prev-char",
"vi-find-prev-char-skip",
"vi-first-non-blank",
"vi-forward-blank-word",
"vi-forward-blank-word-end",
"vi-forward-char",
"vi-forward-word",
"vi-forward-word-end",
"vi-goto-column",
"vi-goto-mark",
"vi-goto-mark-line",
"vi-history-search-backward",
"vi-history-search-forward",
"vi-indent",
"vi-insert",
"vi-insert-bol",
"vi-join",
"vi-kill-eol",
"vi-kill-line",
"vi-match-bracket",
"vi-open-line-above",
"vi-open-line-below",
"vi-oper-swap-case",
"vi-pound-insert",
"vi-put-after",
"vi-put-before",
"vi-quoted-insert",
"vi-repeat-change",
"vi-repeat-find",
"vi-repeat-search",
"vi-replace",
"vi-replace-chars",
"vi-rev-repeat-find",
"vi-rev-repeat-search",
"vi-set-buffer",
"vi-set-mark",
"vi-substitute",
"vi-swap-case",
"vi-undo-change",
"vi-unindent",
"vi-up-line-or-history",
"vi-yank",
"vi-yank-eol",
"vi-yank-whole-line",
"what-cursor-position",
"where-is",
"which-command",
"yank",
"yank-pop",
"zap-to-char",
];
pub const DEFAULT_KEYMAPS: &[&str] = &[
"emacs", "viins", "vicmd", "viopp", "visual", "isearch", "command", "main", ".safe",
];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_widgetstr() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
assert_eq!(widgetstr("self-insert", false, false), "builtin");
assert_eq!(widgetstr("my-widget", true, false), "user:my-widget");
assert_eq!(widgetstr("my-comp", false, true), "completion:my-comp");
}
#[test]
fn test_getpmwidgets() {
let _g = crate::test_util::global_state_lock();
let _g2 = zle_test_setup();
use crate::ported::zsh_h::PM_UNSET;
let pm = getpmwidgets(std::ptr::null_mut(), "definitely-not-a-widget")
.expect("getpmwidgets always returns Some(Param)");
assert!(pm.node.flags & PM_UNSET as i32 != 0, "PM_UNSET set");
assert_eq!(pm.u_str.as_deref(), Some(""));
}
#[test]
fn test_keymapsgetfn() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
let keymaps = keymapsgetfn(std::ptr::null_mut());
assert!(keymaps.contains(&"emacs".to_string()));
assert!(keymaps.contains(&"vicmd".to_string()));
}
#[test]
fn test_builtin_widget_count() {
let _g = crate::test_util::global_state_lock();
let _g = zle_test_setup();
assert!(BUILTIN_WIDGETS.len() > 150);
}
#[test]
fn widgetstr_user_form_carries_function_name_after_colon() {
let _g = crate::test_util::global_state_lock();
let s = widgetstr("a-fn", true, false);
let (kind, rest) = s.split_once(':').expect("missing colon");
assert_eq!(kind, "user");
assert_eq!(rest, "a-fn", "function-name suffix must round-trip");
}
#[test]
fn widgetstr_completion_wins_over_user_when_both_true() {
let _g = crate::test_util::global_state_lock();
let s = widgetstr("foo", true, true);
assert!(
s.starts_with("completion:"),
"is_completion must dominate is_user, got: {}",
s
);
}
#[test]
fn keymapsgetfn_returns_independent_copies() {
let _g = crate::test_util::global_state_lock();
let _g2 = zle_test_setup();
let mut out = keymapsgetfn(std::ptr::null_mut());
let original_len = out.len();
out.push("d".to_string());
let again = keymapsgetfn(std::ptr::null_mut());
assert_eq!(again.len(), original_len);
assert_eq!(out.len(), original_len + 1);
}
#[test]
fn builtin_widgets_has_no_duplicates() {
let _g = crate::test_util::global_state_lock();
let unique: std::collections::HashSet<_> = BUILTIN_WIDGETS.iter().copied().collect();
assert_eq!(
unique.len(),
BUILTIN_WIDGETS.len(),
"duplicate widget name in BUILTIN_WIDGETS — would corrupt $widgets"
);
}
#[test]
fn builtin_widgets_entries_are_kebab_case() {
let _g = crate::test_util::global_state_lock();
for w in BUILTIN_WIDGETS {
assert!(!w.is_empty(), "empty widget name");
for c in w.chars() {
assert!(
c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-',
"widget {:?} has non-kebab-case char {:?}",
w,
c
);
}
assert!(
!w.starts_with('-'),
"widget {:?} starts with '-' — would parse as a flag",
w
);
assert!(!w.ends_with('-'), "widget {:?} ends with '-'", w);
}
}
#[test]
fn default_keymaps_includes_required_names() {
let _g = crate::test_util::global_state_lock();
for required in ["emacs", "viins", "vicmd", "main"] {
assert!(
DEFAULT_KEYMAPS.contains(&required),
"DEFAULT_KEYMAPS missing required name: {}",
required
);
}
}
#[test]
fn module_lifecycle_shims_all_return_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(setup_(), 0);
assert_eq!(boot_(), 0);
assert_eq!(cleanup_(), 0);
assert_eq!(finish_(), 0);
}
#[test]
fn widgetstr_builtin_form_ignores_name() {
let _g = crate::test_util::global_state_lock();
assert_eq!(widgetstr("anything", false, false), "builtin");
assert_eq!(widgetstr("", false, false), "builtin");
assert_eq!(widgetstr("with spaces", false, false), "builtin");
}
#[test]
fn widgetstr_completion_form_carries_function_name() {
let _g = crate::test_util::global_state_lock();
let s = widgetstr("_complete-foo", false, true);
let (kind, rest) = s.split_once(':').expect("missing colon");
assert_eq!(kind, "completion");
assert_eq!(rest, "_complete-foo");
}
#[test]
fn zleparameter_setup_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(setup_(), 0);
}
#[test]
fn zleparameter_features_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(features_(), 0);
}
#[test]
fn zleparameter_enables_returns_zero() {
let _g = crate::test_util::global_state_lock();
assert_eq!(enables_(), 0);
}
#[test]
fn getpmwidgets_unknown_widget_has_readonly_flag() {
let _g = crate::test_util::global_state_lock();
let _g2 = zle_test_setup();
use crate::ported::zsh_h::PM_READONLY;
let pm = getpmwidgets(std::ptr::null_mut(), "no-such-widget").expect("always returns Some");
assert!(pm.node.flags & PM_READONLY as i32 != 0, "PM_READONLY set");
}
#[test]
fn getpmwidgets_param_name_round_trips_input() {
let _g = crate::test_util::global_state_lock();
let _g2 = zle_test_setup();
let pm = getpmwidgets(std::ptr::null_mut(), "my-test-widget").expect("always returns Some");
assert_eq!(pm.node.nam, "my-test-widget");
}
#[test]
fn keymapsgetfn_output_is_sorted() {
let _g = crate::test_util::global_state_lock();
let _g2 = zle_test_setup();
let names = keymapsgetfn(std::ptr::null_mut());
let mut sorted = names.clone();
sorted.sort();
assert_eq!(names, sorted, "keymapsgetfn output must be sorted");
}
#[test]
fn keymapsgetfn_output_has_no_duplicates() {
let _g = crate::test_util::global_state_lock();
let _g2 = zle_test_setup();
let names = keymapsgetfn(std::ptr::null_mut());
let unique: std::collections::HashSet<_> = names.iter().collect();
assert_eq!(
unique.len(),
names.len(),
"keymapsgetfn returned duplicate keymap names"
);
}
#[test]
fn getpmwidgets_always_returns_some() {
let _g = crate::test_util::global_state_lock();
let _g2 = zle_test_setup();
for name in &["x", "", "ANY"] {
assert!(
getpmwidgets(std::ptr::null_mut(), name).is_some(),
"getpmwidgets({:?}) returned None — C never returns NULL",
name
);
}
}
#[test]
fn widgetstr_builtin_ignores_all_names() {
for name in &["", "anything", "with spaces", "包含中文", "x\ny"] {
assert_eq!(
widgetstr(name, false, false),
"builtin",
"builtin arm must ignore name {:?}",
name
);
}
}
#[test]
fn widgetstr_output_has_canonical_prefix() {
let outs = [
widgetstr("x", false, false),
widgetstr("y", true, false),
widgetstr("z", false, true),
];
for s in &outs {
assert!(
s == "builtin" || s.starts_with("user:") || s.starts_with("completion:"),
"widgetstr output {:?} not in known set",
s
);
}
}
#[test]
fn widgetstr_user_colon_is_position_four() {
let s = widgetstr("abc", true, false);
assert_eq!(s.find(':'), Some(4));
assert!(s.starts_with("user:"));
}
#[test]
fn widgetstr_completion_colon_is_position_ten() {
let s = widgetstr("abc", false, true);
assert_eq!(s.find(':'), Some(10));
assert!(s.starts_with("completion:"));
}
#[test]
fn widgetstr_empty_name_each_arm_well_formed() {
assert_eq!(widgetstr("", false, false), "builtin");
assert_eq!(widgetstr("", true, false), "user:");
assert_eq!(widgetstr("", false, true), "completion:");
}
#[test]
fn widgetstr_is_pure() {
for _ in 0..50 {
assert_eq!(widgetstr("x", false, false), "builtin");
assert_eq!(widgetstr("y", true, false), "user:y");
assert_eq!(widgetstr("z", false, true), "completion:z");
}
}
#[test]
fn keymapsgetfn_null_pm_no_panic() {
let _g = crate::test_util::global_state_lock();
let _g2 = zle_test_setup();
let _ = keymapsgetfn(std::ptr::null_mut());
}
#[test]
fn keymapsgetfn_is_deterministic() {
let _g = crate::test_util::global_state_lock();
let _g2 = zle_test_setup();
let first = keymapsgetfn(std::ptr::null_mut());
for _ in 0..5 {
assert_eq!(
keymapsgetfn(std::ptr::null_mut()),
first,
"keymapsgetfn must be deterministic"
);
}
}
#[test]
fn getpmwidgets_unknown_sets_pm_unset_flag() {
use crate::ported::zsh_h::PM_UNSET;
let _g = crate::test_util::global_state_lock();
let _g2 = zle_test_setup();
let pm =
getpmwidgets(std::ptr::null_mut(), "zshrs_never_a_widget_xyz").expect("always Some");
assert_ne!(
pm.node.flags & PM_UNSET as i32,
0,
"unknown widget must have PM_UNSET bit set"
);
}
#[test]
fn scanpmwidgets_none_callback_no_panic() {
let _g = crate::test_util::global_state_lock();
let _g2 = zle_test_setup();
scanpmwidgets(std::ptr::null_mut(), None, 0);
}
#[test]
fn zleparameter_interleaved_lifecycle_safe() {
for _ in 0..5 {
assert_eq!(setup_(), 0);
assert_eq!(boot_(), 0);
assert_eq!(cleanup_(), 0);
assert_eq!(finish_(), 0);
}
}
#[test]
fn widgetstr_returns_string_type() {
let _g = crate::test_util::global_state_lock();
let _: String = widgetstr("", false, false);
}
#[test]
fn keymapsgetfn_returns_vec_string_type() {
let _g = crate::test_util::global_state_lock();
let _: Vec<String> = keymapsgetfn(std::ptr::null_mut());
}
#[test]
fn zleparameter_setup_returns_i32_type() {
let _: i32 = setup_();
}
#[test]
fn zleparameter_features_returns_i32_type() {
let _: i32 = features_();
}
#[test]
fn zleparameter_enables_returns_i32_type() {
let _: i32 = enables_();
}
#[test]
fn zleparameter_boot_returns_i32_type() {
let _: i32 = boot_();
}
#[test]
fn zleparameter_cleanup_returns_i32_type() {
let _: i32 = cleanup_();
}
#[test]
fn zleparameter_finish_returns_i32_type() {
let _: i32 = finish_();
}
#[test]
fn zleparameter_all_lifecycle_hooks_return_zero() {
assert_eq!(setup_(), 0);
assert_eq!(features_(), 0);
assert_eq!(enables_(), 0);
assert_eq!(boot_(), 0);
assert_eq!(cleanup_(), 0);
assert_eq!(finish_(), 0);
}
#[test]
fn zleparameter_setup_idempotent_full_sweep() {
for _ in 0..10 {
assert_eq!(setup_(), 0);
}
}
#[test]
fn zleparameter_finish_idempotent_full_sweep() {
for _ in 0..10 {
assert_eq!(finish_(), 0);
}
}
#[test]
fn widgetstr_builtin_is_pure() {
let _g = crate::test_util::global_state_lock();
for name in ["", "a", "fwd", "back-word", "complete-word"] {
let first = widgetstr(name, false, false);
for _ in 0..3 {
assert_eq!(
widgetstr(name, false, false),
first,
"widgetstr({:?}, false, false) must be pure",
name
);
}
}
}
#[test]
fn widgetstr_builtin_ignores_name() {
let _g = crate::test_util::global_state_lock();
for name in ["", "a", "x", "self-insert", "fancy-name"] {
assert_eq!(
widgetstr(name, false, false),
"builtin",
"builtin mode ignores name; got name={:?}",
name
);
}
}
#[test]
fn widgetstr_completion_precedence_over_user() {
let _g = crate::test_util::global_state_lock();
assert_eq!(
widgetstr("foo", true, true),
"completion:foo",
"completion bit dominates user bit"
);
}
#[test]
fn widgetstr_user_format() {
let _g = crate::test_util::global_state_lock();
for name in ["", "a", "complete-word", "_complete"] {
assert_eq!(widgetstr(name, true, false), format!("user:{}", name));
}
}
#[test]
fn widgetstr_completion_format() {
let _g = crate::test_util::global_state_lock();
for name in ["", "_main_complete", "_complete_help", "x"] {
assert_eq!(widgetstr(name, false, true), format!("completion:{}", name));
}
}
#[test]
fn widgetstr_return_type_is_owned_string() {
let _g = crate::test_util::global_state_lock();
let _: String = widgetstr("x", false, false);
let _: String = widgetstr("x", true, false);
let _: String = widgetstr("x", false, true);
}
#[test]
fn scanpmwidgets_none_callback_safe() {
let _g = crate::test_util::global_state_lock();
scanpmwidgets(std::ptr::null_mut(), None, 0);
scanpmwidgets(std::ptr::null_mut(), None, 0xff);
}
#[test]
fn keymapsgetfn_returns_vec_string_compile_pin() {
let _g = crate::test_util::global_state_lock();
let _: Vec<String> = keymapsgetfn(std::ptr::null_mut());
}
#[test]
fn keymapsgetfn_sorted_clone_compare() {
let _g = crate::test_util::global_state_lock();
let v = keymapsgetfn(std::ptr::null_mut());
let mut sorted = v.clone();
sorted.sort();
assert_eq!(v, sorted, "keymapsgetfn must return sorted names");
}
#[test]
fn keymapsgetfn_deterministic() {
let _g = crate::test_util::global_state_lock();
let first = keymapsgetfn(std::ptr::null_mut());
for _ in 0..5 {
assert_eq!(
keymapsgetfn(std::ptr::null_mut()),
first,
"must be deterministic across calls"
);
}
}
#[test]
fn getpmwidgets_returns_some_for_unknown_name() {
let _g = crate::test_util::global_state_lock();
let pm = getpmwidgets(std::ptr::null_mut(), "definitely-not-a-widget-xyz123");
assert!(
pm.is_some(),
"even unknown name returns Some (flags carry PM_UNSET)"
);
}
#[test]
fn zleparameter_features_idempotent() {
for _ in 0..10 {
assert_eq!(features_(), 0);
}
}
#[test]
fn zleparameter_enables_idempotent() {
for _ in 0..10 {
assert_eq!(enables_(), 0);
}
}
#[test]
fn zleparameter_boot_idempotent() {
for _ in 0..10 {
assert_eq!(boot_(), 0);
}
}
#[test]
fn zleparameter_cleanup_idempotent() {
for _ in 0..10 {
assert_eq!(cleanup_(), 0);
}
}
#[test]
fn widgetstr_empty_name_user_format() {
assert_eq!(
widgetstr("", true, false),
"user:",
"empty name still gets user: prefix"
);
}
#[test]
fn widgetstr_empty_name_completion_format() {
assert_eq!(
widgetstr("", false, true),
"completion:",
"empty + completion → completion: prefix only"
);
}
#[test]
fn widgetstr_completion_beats_both_flags() {
assert_eq!(
widgetstr("foo", true, true),
"completion:foo",
"completion takes precedence when both flags set"
);
}
#[test]
fn widgetstr_both_flags_false_returns_builtin() {
assert_eq!(widgetstr("anything", false, false), "builtin");
}
#[test]
fn widgetstr_deterministic_repeated_calls() {
for _ in 0..10 {
assert_eq!(widgetstr("foo", true, false), "user:foo");
assert_eq!(widgetstr("bar", false, true), "completion:bar");
assert_eq!(widgetstr("baz", false, false), "builtin");
}
}
#[test]
fn widgetstr_preserves_special_chars_in_name() {
assert_eq!(widgetstr("a b\tc", true, false), "user:a b\tc");
assert_eq!(widgetstr("\\n", true, false), "user:\\n");
}
#[test]
fn getpmwidgets_empty_name_no_panic() {
let _g = crate::test_util::global_state_lock();
let _ = getpmwidgets(std::ptr::null_mut(), "");
}
#[test]
fn scanpmwidgets_none_repeat_safe() {
let _g = crate::test_util::global_state_lock();
for _ in 0..5 {
scanpmwidgets(std::ptr::null_mut(), None, 0);
}
}
#[test]
fn keymapsgetfn_returns_vec_string_compile_pin_alt() {
let _: Vec<String> = keymapsgetfn(std::ptr::null_mut());
}
#[test]
fn keymapsgetfn_null_pm_no_panic_alt() {
let _g = crate::test_util::global_state_lock();
let _ = keymapsgetfn(std::ptr::null_mut());
}
#[test]
fn zleparameter_setup_idempotent() {
for _ in 0..10 {
assert_eq!(setup_(), 0);
}
}
#[test]
fn zleparameter_finish_idempotent() {
for _ in 0..10 {
assert_eq!(finish_(), 0);
}
}
#[test]
fn zleparameter_full_lifecycle_sequence_safe() {
assert_eq!(setup_(), 0);
assert_eq!(features_(), 0);
assert_eq!(enables_(), 0);
assert_eq!(boot_(), 0);
assert_eq!(cleanup_(), 0);
assert_eq!(finish_(), 0);
}
}