#![allow(non_camel_case_types, non_snake_case, dead_code)]
use crate::ported::zsh_h::{HashNode, zattr};
#[allow(unused_imports)]
#[allow(unused_imports)]
use crate::ported::zle::zle_main::*;
#[allow(unused_imports)]
use crate::ported::zle::zle_misc::*;
#[allow(unused_imports)]
use crate::ported::zle::zle_hist::*;
#[allow(unused_imports)]
use crate::ported::zle::zle_move::*;
#[allow(unused_imports)]
use crate::ported::zle::zle_word::*;
#[allow(unused_imports)]
use crate::ported::zle::zle_params::*;
#[allow(unused_imports)]
use crate::ported::zle::zle_vi::*;
#[allow(unused_imports)]
use crate::ported::zle::zle_utils::*;
#[allow(unused_imports)]
use crate::ported::zle::zle_refresh::*;
#[allow(unused_imports)]
use crate::ported::zle::zle_tricky::*;
#[allow(unused_imports)]
use crate::ported::zle::textobjects::*;
#[allow(unused_imports)]
use crate::ported::zle::deltochar::*;
pub type ZLE_CHAR_T = char;
pub type ZLE_STRING_T = String;
pub type ZLE_INT_T = i32;
pub const ZLE_CHAR_SIZE: usize = 4;
pub const ZLEEOF: i32 = -1;
#[inline]
pub fn Th(index: i32) -> Option<crate::ported::zle::zle_thingy::Thingy> { let i: usize = (index as i64).try_into().ok()?;
let name = T_THINGY_NAMES.get(i)?;
crate::ported::zle::zle_thingy::gethashnode2(name)
}
pub const T_THINGY_NAMES: &[&str] = &[
"accept-and-hold", "accept-line", "accept-line-and-down-history", "accept-search", "auto-suffix-remove", "auto-suffix-retain", "backward-char", "backward-delete-char", "beep", "clear-screen", "complete-word", "describe-key-briefly", "down-line-or-history", "execute-named-cmd", "exit", "forward-char", "history-incremental-search-backward", "history-incremental-search-forward", "list-choices", "menu-complete", "menu-expand-or-complete", "redisplay", "self-insert", "self-insert-unmeta", "send-break", "undefined-key", "undo", "up-line-or-history", "vi-cmd-mode", "yank", ];
#[inline] pub fn invicmdmode(curkeymapname: &str) -> bool { curkeymapname == "vicmd"
}
#[inline] pub fn ZS_memcpy(dst: &mut [ZLE_CHAR_T], src: &[ZLE_CHAR_T], n: usize) { dst[..n].copy_from_slice(&src[..n]);
}
#[inline] pub fn ZS_memmove(dst: &mut [ZLE_CHAR_T], src: &[ZLE_CHAR_T], n: usize) { let v: Vec<ZLE_CHAR_T> = src[..n].to_vec();
dst[..n].copy_from_slice(&v);
}
#[inline] pub fn ZS_memset(dst: &mut [ZLE_CHAR_T], c: ZLE_CHAR_T, n: usize) { for slot in dst.iter_mut().take(n) {
*slot = c;
}
}
#[inline] pub fn ZS_memcmp(a: &[ZLE_CHAR_T], b: &[ZLE_CHAR_T], n: usize) -> std::cmp::Ordering { a[..n].cmp(&b[..n])
}
#[inline] pub fn ZS_strlen(s: &[ZLE_CHAR_T]) -> usize { s.iter().position(|&c| c == '\0').unwrap_or(s.len())
}
#[inline] pub fn ZS_strcpy(dst: &mut [ZLE_CHAR_T], src: &[ZLE_CHAR_T]) { let n = ZS_strlen(src);
let limit = dst.len().min(n);
dst[..limit].copy_from_slice(&src[..limit]);
if limit < dst.len() {
dst[limit] = '\0';
}
}
#[inline] pub fn ZS_strncpy(dst: &mut [ZLE_CHAR_T], src: &[ZLE_CHAR_T], n: usize) { let s_len = ZS_strlen(src).min(n);
let limit = dst.len().min(n);
let copy = s_len.min(limit);
dst[..copy].copy_from_slice(&src[..copy]);
for slot in dst.iter_mut().take(limit).skip(copy) {
*slot = '\0';
}
}
#[inline] pub fn ZS_strncmp(a: &[ZLE_CHAR_T], b: &[ZLE_CHAR_T], n: usize) -> std::cmp::Ordering { let a_n = ZS_strlen(a).min(n);
let b_n = ZS_strlen(b).min(n);
let limit = a_n.min(b_n);
let cmp = a[..limit].cmp(&b[..limit]);
if cmp != std::cmp::Ordering::Equal {
return cmp;
}
a_n.cmp(&b_n)
}
#[inline] pub fn ZS_strchr(s: &[ZLE_CHAR_T], c: ZLE_CHAR_T) -> Option<usize> { s.iter().position(|&x| x == c)
}
#[inline] pub fn ZS_memchr(s: &[ZLE_CHAR_T], c: ZLE_CHAR_T, n: usize) -> Option<usize> { s[..n.min(s.len())].iter().position(|&x| x == c)
}
#[inline] pub fn ZS_width(s: &[ZLE_CHAR_T]) -> usize { ZS_strlen(s)
}
#[inline] pub fn ZC_ialpha(c: ZLE_CHAR_T) -> bool { c.is_alphabetic() } #[inline] pub fn ZC_ialnum(c: ZLE_CHAR_T) -> bool { c.is_alphanumeric() } #[inline] pub fn ZC_iblank(c: ZLE_CHAR_T) -> bool { crate::ported::utils::wcsiblank(c)
}
#[inline] pub fn ZC_icntrl(c: ZLE_CHAR_T) -> bool { c.is_control() } #[inline] pub fn ZC_idigit(c: ZLE_CHAR_T) -> bool { c.is_ascii_digit() } #[inline] pub fn ZC_iident(c: ZLE_CHAR_T) -> bool { c.is_alphanumeric() || c == '_' } #[inline] pub fn ZC_ilower(c: ZLE_CHAR_T) -> bool { c.is_lowercase() } #[inline] pub fn ZC_inblank(c: ZLE_CHAR_T) -> bool { c.is_whitespace() } #[inline] pub fn ZC_iupper(c: ZLE_CHAR_T) -> bool { c.is_uppercase() } #[inline] pub fn ZC_iword(c: ZLE_CHAR_T) -> bool { c.is_alphanumeric() || c == '_' } #[inline] pub fn ZC_ipunct(c: ZLE_CHAR_T) -> bool { c.is_ascii_punctuation() }
#[inline] pub fn ZC_tolower(c: ZLE_CHAR_T) -> ZLE_CHAR_T { c.to_lowercase().next().unwrap_or(c)
}
#[inline] pub fn ZC_toupper(c: ZLE_CHAR_T) -> ZLE_CHAR_T { c.to_uppercase().next().unwrap_or(c)
}
pub type WidgetPtr = Box<widget>;
pub type ThingyPtr = Box<thingy>;
pub type ZleIntFunc = fn(args: &[String]) -> i32;
pub use self::WidgetImpl as WidgetFunc;
pub type Widget = widget;
pub struct widget { pub flags: i32, pub first: Option<ThingyPtr>, pub u: WidgetImpl, }
impl Clone for widget {
fn clone(&self) -> Self {
widget {
flags: self.flags,
first: None, u: match &self.u {
WidgetImpl::Internal(f) => WidgetImpl::Internal(*f),
WidgetImpl::UserFunc(s) => WidgetImpl::UserFunc(s.clone()),
WidgetImpl::Comp { fn_, wid, func } => WidgetImpl::Comp {
fn_: *fn_,
wid: wid.clone(),
func: func.clone(),
},
},
}
}
}
impl std::fmt::Debug for widget {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("widget")
.field("flags", &self.flags)
.field("u", &match &self.u {
WidgetImpl::Internal(_) => "Internal(<fn>)".to_string(),
WidgetImpl::UserFunc(s) => format!("UserFunc({})", s),
WidgetImpl::Comp { .. } => "Comp{..}".to_string(),
})
.finish()
}
}
impl widget {
pub fn internal(name: &str, func: ZleIntFunc, flags: i32) -> Self {
let _ = name;
widget { flags: flags | WIDGET_INT, first: None, u: WidgetImpl::Internal(func) }
}
pub fn builtin(name: &str) -> Self {
let f = super::zle_bindings::iwidget_lookup(name)
.unwrap_or(|_args: &[String]| 0i32);
widget { flags: WIDGET_INT, first: None, u: WidgetImpl::Internal(f) }
}
pub fn user_defined(name: &str, func_name: &str) -> Self {
let _ = name;
widget { flags: 0i32, first: None, u: WidgetImpl::UserFunc(func_name.to_string()) }
}
}
pub enum WidgetImpl { Internal(ZleIntFunc), UserFunc(String), Comp { fn_: ZleIntFunc, wid: String, func: String }, }
pub const WIDGET_INT: i32 = 1 << 0; pub const WIDGET_NCOMP: i32 = 1 << 1; pub const ZLE_MENUCMP: i32 = 1 << 2; pub const ZLE_YANKAFTER: i32 = 1 << 3; pub const ZLE_YANKBEFORE:i32 = 1 << 4; pub const ZLE_YANK: i32 = ZLE_YANKAFTER | ZLE_YANKBEFORE; pub const ZLE_LINEMOVE: i32 = 1 << 5; pub const ZLE_VIOPER: i32 = 1 << 6; pub const ZLE_LASTCOL: i32 = 1 << 7; pub const ZLE_KILL: i32 = 1 << 8; pub const ZLE_KEEPSUFFIX:i32 = 1 << 9; pub const ZLE_NOTCOMMAND:i32 = 1 << 10; pub const ZLE_ISCOMP: i32 = 1 << 11; pub const WIDGET_INUSE: i32 = 1 << 12; pub const WIDGET_FREE: i32 = 1 << 13; pub const ZLE_NOLAST: i32 = 1 << 14;
pub struct thingy { pub next: Option<HashNode>, pub nam: String, pub flags: i32, pub rc: i32, pub widget: Option<WidgetPtr>, pub samew: Option<ThingyPtr>, }
pub const TH_IMMORTAL: i32 = 1 << 1;
pub struct modifier { pub flags: i32, pub mult: i32, pub tmult: i32, pub vibuf: i32, pub base: i32, }
pub const MOD_MULT: i32 = 1 << 0; pub const MOD_TMULT: i32 = 1 << 1; pub const MOD_VIBUF: i32 = 1 << 2; pub const MOD_VIAPP: i32 = 1 << 3; pub const MOD_NEG: i32 = 1 << 4; pub const MOD_NULL: i32 = 1 << 5; pub const MOD_CHAR: i32 = 1 << 6; pub const MOD_LINE: i32 = 1 << 7; pub const MOD_PRI: i32 = 1 << 8; pub const MOD_CLIP: i32 = 1 << 9; pub const MOD_OSSEL: i32 = MOD_PRI | MOD_CLIP;
pub const CUT_FRONT: i32 = 1 << 0; pub const CUT_REPLACE: i32 = 1 << 1; pub const CUT_RAW: i32 = 1 << 2; pub const CUT_YANK: i32 = 1 << 3;
#[derive(Clone, Debug)]
pub struct change { pub prev: Option<Box<change>>, pub next: Option<Box<change>>, pub flags: i32, pub hist: i32, pub off: i32, pub del: ZLE_STRING_T, pub dell: i32, pub ins: ZLE_STRING_T, pub insl: i32, pub old_cs: i32, pub new_cs: i32, pub changeno: i64, }
pub const CH_NEXT: i32 = 1 << 0; pub const CH_PREV: i32 = 1 << 1;
pub struct vichange { pub mod_: modifier, pub buf: Vec<u8>, pub bufsz: i32, pub bufptr: i32, }
pub type KeyScanFunc = fn(seq: &str, t: &thingy, ext: &str, data: usize);
pub const NO_INSERT_CHAR: i32 = 256;
pub fn removesuffix() -> i32 { 0
}
pub struct cutbuffer { pub buf: ZLE_STRING_T, pub len: usize, pub flags: u8, }
pub type CutbufferPtr = Box<cutbuffer>;
pub const CUTBUFFER_LINE: u8 = 1; pub const KRINGCTDEF: i32 = 8;
pub const COMP_COMPLETE: i32 = 0; pub const COMP_LIST_COMPLETE: i32 = 1; pub const COMP_SPELL: i32 = 2; pub const COMP_EXPAND: i32 = 3; pub const COMP_EXPAND_COMPLETE: i32 = 4; pub const COMP_LIST_EXPAND: i32 = 5;
#[inline]
pub fn COMP_ISEXPAND(x: i32) -> bool { x >= COMP_EXPAND }
pub type BrinfoPtr = Box<brinfo>;
pub struct brinfo { pub next: Option<BrinfoPtr>, pub prev: Option<BrinfoPtr>, pub str: String, pub pos: i32, pub qpos: i32, pub curpos: i32, }
pub const LISTMATCHESHOOK: i32 = 0; pub const COMPLETEHOOK: i32 = 1; pub const BEFORECOMPLETEHOOK: i32 = 2; pub const AFTERCOMPLETEHOOK: i32 = 3; pub const ACCEPTCOMPHOOK: i32 = 4; pub const INVALIDATELISTHOOK: i32 = 5;
pub type CompldatPtr = Box<compldat>;
pub struct compldat { pub s: String, pub lst: i32, pub incmd: i32, }
pub fn listmatches() { let registered = crate::ported::module::HOOKTAB.lock().ok()
.and_then(|tab| tab.get("list-matches").cloned())
.unwrap_or_default();
let mut handled = false;
for f in ®istered {
if crate::ported::utils::getshfunc(f).is_some() {
let _ = crate::ported::zle::compcore::shfunc_call(f);
handled = true;
}
}
if !handled {
let _ = crate::ported::zle::compresult::ilistmatches();
}
}
pub fn invalidatelist() { let registered = crate::ported::module::HOOKTAB.lock().ok()
.and_then(|tab| tab.get("invalidate-list").cloned())
.unwrap_or_default();
let mut handled = false;
for f in ®istered {
if crate::ported::utils::getshfunc(f).is_some() {
let _ = crate::ported::zle::compcore::shfunc_call(f);
handled = true;
}
}
if !handled {
let _ = crate::ported::zle::compresult::invalidate_list();
}
}
pub const ZSL_COPY: i32 = 1; pub const ZSL_TOEND: i32 = 2;
pub const SUFTYP_POSSTR: i32 = 0; pub const SUFTYP_NEGSTR: i32 = 1; pub const SUFTYP_POSRNG: i32 = 2; pub const SUFTYP_NEGRNG: i32 = 3;
pub const SUFFLAGS_SPACE: i32 = 0x0001;
pub const ZRH_PREDISPLAY: i32 = 1;
pub struct region_highlight { pub atr: zattr, pub atrmask: zattr, pub layer: i32, pub start: i32, pub start_meta: i32, pub end: i32, pub end_meta: i32, pub flags: i32, pub memo: Option<String>, }
pub const N_SPECIAL_HIGHLIGHTS: i32 = 4;
pub const CURC_EDIT: i32 = 0; pub const CURC_COMMAND: i32 = 1; pub const CURC_INSERT: i32 = 2; pub const CURC_OVERWRITE: i32 = 3; pub const CURC_PENDING: i32 = 4; pub const CURC_REGION_START: i32 = 5; pub const CURC_REGION_END: i32 = 6; pub const CURC_VISUAL: i32 = 7; pub const CURC_DEFAULT: i32 = 8;
pub const CURF_DEFAULT: i32 = 0; pub const CURF_UNDERLINE: i32 = 1; pub const CURF_BAR: i32 = 2; pub const CURF_BLOCK: i32 = 3; pub const CURF_SHAPE_MASK: i32 = 3; pub const CURF_BLINK: i32 = 1 << 2; pub const CURF_STEADY: i32 = 1 << 3; pub const CURF_HIDDEN: i32 = 1 << 4; pub const CURF_COLOR: i32 = 1 << 5; pub const CURF_COLOR_MASK: u32 = (0xffffff_u32 << 8) | (CURF_COLOR as u32); pub const CURF_RED_SHIFT: i32 = 24; pub const CURF_GREEN_SHIFT: i32 = 16; pub const CURF_BLUE_SHIFT: i32 = 8;
pub type REFRESH_CHAR = char;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct REFRESH_ELEMENT { pub chr: REFRESH_CHAR, pub atr: zattr, }
pub type REFRESH_STRING = Vec<REFRESH_ELEMENT>;
pub const ZSH_INVALID_WCHAR_BASE: u32 = 0xe000;
#[inline]
pub fn ZSH_INVALID_WCHAR_TEST(x: u32) -> bool { x >= ZSH_INVALID_WCHAR_BASE && x <= ZSH_INVALID_WCHAR_BASE + 255
}
#[inline]
pub fn ZSH_INVALID_WCHAR_TO_CHAR(x: u32) -> u8 { (x - ZSH_INVALID_WCHAR_BASE) as u8
}
#[inline]
pub fn ZSH_INVALID_WCHAR_TO_INT(x: u32) -> i32 { (x - ZSH_INVALID_WCHAR_BASE) as i32
}
#[inline]
pub fn ZSH_CHAR_TO_INVALID_WCHAR(x: u8) -> u32 { (x as u32) + ZSH_INVALID_WCHAR_BASE
}
#[inline]
pub fn METACHECK() { }
#[inline]
pub fn UNMETACHECK() { }
pub type WatchFdPtr = Box<watch_fd>;
pub struct watch_fd { pub func: String, pub fd: i32, pub widget: i32, }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn zs_strlen_stops_at_nul() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
assert_eq!(ZS_strlen(&['a', 'b', 'c']), 3);
assert_eq!(ZS_strlen(&['a', '\0', 'c']), 1);
assert_eq!(ZS_strlen(&[]), 0);
}
#[test]
fn zs_memcpy_first_n_chars() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
let mut dst = ['x'; 5];
let src = ['a', 'b', 'c', 'd', 'e'];
ZS_memcpy(&mut dst, &src, 3);
assert_eq!(dst, ['a', 'b', 'c', 'x', 'x']);
}
#[test]
fn zs_memmove_handles_self_copy() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
let mut buf = ['a', 'b', 'c', 'd', 'e'];
let src: Vec<char> = buf[1..4].to_vec();
ZS_memmove(&mut buf, &src, 3);
assert_eq!(buf, ['b', 'c', 'd', 'd', 'e']);
}
#[test]
fn zs_memset_fills_n() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
let mut dst = ['x'; 5];
ZS_memset(&mut dst, 'z', 3);
assert_eq!(dst, ['z', 'z', 'z', 'x', 'x']);
}
#[test]
fn zs_memcmp_ordering() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
assert_eq!(ZS_memcmp(&['a', 'b'], &['a', 'b'], 2), std::cmp::Ordering::Equal);
assert_eq!(ZS_memcmp(&['a', 'b'], &['a', 'c'], 2), std::cmp::Ordering::Less);
}
#[test]
fn zs_strncmp_terminates_at_nul() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
assert_eq!(ZS_strncmp(&['a', 'b'], &['a', 'b'], 2), std::cmp::Ordering::Equal);
assert_eq!(ZS_strncmp(&['a', 'b'], &['a', 'c'], 2), std::cmp::Ordering::Less);
assert_eq!(ZS_strncmp(&['a', '\0'], &['a'], 5), std::cmp::Ordering::Equal);
}
#[test]
fn zs_strchr_returns_first_index() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
assert_eq!(ZS_strchr(&['a', 'b', 'c'], 'b'), Some(1));
assert_eq!(ZS_strchr(&['a', 'b', 'c'], 'z'), None);
}
#[test]
fn zc_iblank_matches_wcsiblank_semantics() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
assert!(ZC_iblank(' '), "space is iblank");
assert!(ZC_iblank('\t'), "tab is iblank");
assert!(ZC_iblank('\r'), "CR is iblank per wcsiblank");
assert!(ZC_iblank('\x0c'), "FF is iblank per wcsiblank");
assert!(ZC_iblank('\x0b'), "VT is iblank per wcsiblank");
assert!(ZC_iblank('\u{00A0}'), "NBSP is iblank per wcsiblank");
assert!(ZC_iblank('\u{2028}'), "line-separator U+2028 is iblank");
assert!(!ZC_iblank('\n'), "newline is the sole iswspace exclusion");
assert!(!ZC_iblank('a'));
assert!(!ZC_iblank('0'));
assert!(!ZC_iblank('_'));
}
#[test]
fn zc_inblank_matches_iswspace_semantics() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
assert!(ZC_inblank('\n'), "newline IS iswspace");
assert!(ZC_inblank(' '));
assert!(ZC_inblank('\t'));
assert!(ZC_inblank('\r'), "CR is iswspace");
assert!(ZC_inblank('\x0c'), "FF is iswspace");
assert!(ZC_inblank('\x0b'), "VT is iswspace");
assert!(ZC_inblank('\u{00A0}'), "NBSP is iswspace");
assert!(!ZC_inblank('a'));
assert!(!ZC_inblank('0'));
}
#[test]
fn zc_iword_includes_underscore() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
assert!(ZC_iword('a'));
assert!(ZC_iword('1'));
assert!(ZC_iword('_'));
assert!(!ZC_iword('-'));
}
#[test]
fn zc_iident_matches_iword() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
for c in ['a', 'A', '0', '_'] {
assert_eq!(ZC_iident(c), ZC_iword(c));
}
}
#[test]
fn zc_tolower_toupper_round_trip() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
assert_eq!(ZC_tolower('A'), 'a');
assert_eq!(ZC_toupper('a'), 'A');
assert_eq!(ZC_tolower('1'), '1');
}
#[test]
fn invicmdmode_only_true_for_vicmd() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
assert!(invicmdmode("vicmd"));
assert!(!invicmdmode("main"));
assert!(!invicmdmode("emacs"));
assert!(!invicmdmode(""));
}
#[test]
fn th_out_of_range_returns_none() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
assert!(Th(99).is_none());
assert!(Th(-1).is_none());
}
#[test]
fn th_in_range_looks_up_thingytab() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
assert_eq!(T_THINGY_NAMES[10], "complete-word");
assert!(Th(10).is_none() || Th(10).is_some());
}
#[test]
fn zle_widget_flags_match_c_zle_h_canonical_values() {
assert_eq!(ZLE_MENUCMP, 1 << 2, "c:207");
assert_eq!(ZLE_YANKAFTER, 1 << 3, "c:208");
assert_eq!(ZLE_YANKBEFORE, 1 << 4, "c:209");
assert_eq!(ZLE_YANK, ZLE_YANKAFTER | ZLE_YANKBEFORE,
"c:210 — composite");
assert_eq!(ZLE_LINEMOVE, 1 << 5, "c:211");
assert_eq!(ZLE_VIOPER, 1 << 6, "c:212");
assert_eq!(ZLE_LASTCOL, 1 << 7, "c:213");
assert_eq!(ZLE_KILL, 1 << 8, "c:214");
assert_eq!(ZLE_KEEPSUFFIX, 1 << 9, "c:215");
assert_eq!(ZLE_NOTCOMMAND, 1 << 10, "c:216");
assert_eq!(ZLE_ISCOMP, 1 << 11, "c:217");
assert_eq!(ZLE_NOLAST, 1 << 14, "c:220");
}
}