use std::collections::VecDeque;
use crate::ported::utils::zwarnnam;
use std::io::{self, Read, Write};
use std::os::unix::io::{AsRawFd, RawFd};
use std::time::{Duration, Instant};
use super::zle_keymap::Keymap;
use super::zle_thingy::Thingy;
use super::zle_h::widget as Widget;
use super::zle_h::{ZLE_LASTCOL, ZLE_NOTCOMMAND};
#[allow(unused_imports)]
use crate::ported::zle::zle_h::*;
#[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::*;
use crate::zle::zle_h::{change, modifier, widget};
pub type ZleChar = char;
pub type ZleString = Vec<ZleChar>;
pub type ZleInt = i32;
pub const ZLEEOF: ZleInt = -1;
impl Default for modifier {
fn default() -> Self {
modifier {
flags: 0,
mult: 1,
tmult: 1,
vibuf: 0,
base: 10,
}
}
}
use super::zle_h::{MOD_MULT, MOD_TMULT, MOD_VIBUF, MOD_VIAPP, MOD_NEG, MOD_NULL, MOD_CHAR, MOD_LINE, MOD_PRI, MOD_CLIP, MOD_OSSEL};
pub const ZMAXTIMEOUT: u64 = 1 << 21;
pub const MAXFOUND: usize = 4;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
#[allow(non_camel_case_types)]
pub enum ztmouttp { ZTM_NONE = 0, ZTM_KEY = 1, ZTM_FUNC = 2, ZTM_MAX = 3, }
#[derive(Debug, Clone, Copy)]
#[allow(non_camel_case_types)]
pub struct ztmout { pub tp: ztmouttp, pub exp100ths: i64, }
#[derive(Debug, Default)]
#[allow(non_camel_case_types)]
pub struct findfunc { pub func: Option<usize>, pub found: usize, pub msg: String, }
#[doc(hidden)]
pub static ZLE_TEST_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
#[doc(hidden)]
pub fn zle_test_setup() -> std::sync::MutexGuard<'static, ()> {
let guard = ZLE_TEST_LOCK
.lock()
.unwrap_or_else(|e| e.into_inner());
zle_reset();
guard
}
pub fn zle_reset() {
crate::ported::zle::zle_keymap::createkeymapnamtab();
crate::ported::zle::zle_keymap::default_bindings();
use std::sync::atomic::Ordering;
ZLELINE.lock().unwrap().clear();
ZLECS.store(0, Ordering::SeqCst);
ZLELL.store(0, Ordering::SeqCst);
MARK.store(0, Ordering::SeqCst);
*LBINDK.lock().unwrap() = None;
*BINDK.lock().unwrap() = None;
*ZMOD.lock().unwrap() = modifier { flags: 0, mult: 1, tmult: 1, vibuf: 0, base: 10 };
*STATUSLINE.lock().unwrap() = None;
STACKHIST.store(0, Ordering::SeqCst);
STACKCS.store(0, Ordering::SeqCst);
VISTARTCHANGE.store(0, Ordering::SeqCst);
UNDO_STACK.lock().unwrap().clear();
CHANGENO.store(0, Ordering::SeqCst);
KUNGETBUF.lock().unwrap().clear();
BAUD.store(38400, Ordering::SeqCst);
WATCH_FDS.lock().unwrap().clear();
*COMPWIDGET.lock().unwrap() = None;
HASCOMPMOD.store(false, Ordering::SeqCst);
TTYFD.store(0, Ordering::SeqCst);
LPROMPT.lock().unwrap().clear();
RPROMPT.lock().unwrap().clear();
PRE_ZLE_STATUS.store(0, Ordering::SeqCst);
for slot in vibuf().lock().unwrap().iter_mut() { slot.clear(); }
KILLRING.lock().unwrap().clear();
KILLRINGMAX.store(8, Ordering::SeqCst);
YANKLAST.store(false, Ordering::SeqCst);
NEG_ARG.store(false, Ordering::SeqCst);
MULT.store(1, Ordering::SeqCst);
*history().lock().unwrap() = super::zle_hist::History::new(2000);
LASTCOL.store(-1, Ordering::SeqCst);
BUFSTACK.lock().unwrap().clear();
VICHGBUF.lock().unwrap().clear();
*SRCH_STR.lock().unwrap() = None;
LASTLINE.lock().unwrap().clear();
LASTLL.store(0, Ordering::SeqCst);
LASTCS.store(0, Ordering::SeqCst);
CURCHANGE.store(0, Ordering::SeqCst);
UNDO_CHANGENO.store(0, Ordering::SeqCst);
UNDO_LIMITNO.store(0, Ordering::SeqCst);
VIINSBEGIN.store(0, Ordering::SeqCst);
YANKB.store(0, Ordering::SeqCst);
YANKE.store(0, Ordering::SeqCst);
YANKCS.store(0, Ordering::SeqCst);
*KCT.lock().unwrap() = None;
*vimarks().lock().unwrap() = [None; 27];
REGION_ACTIVE.store(0, Ordering::SeqCst);
PENDING_HOOKS.lock().unwrap().clear();
RAW_LP.lock().unwrap().clear();
RAW_RP.lock().unwrap().clear();
*highlight().lock().unwrap() = super::zle_refresh::HighlightManager::new();
}
pub fn zsetterm() -> io::Result<()> { let mut termios = termios::Termios::from_fd(crate::ported::zle::zle_main::TTYFD.load(std::sync::atomic::Ordering::SeqCst))?;
let veof = termios.c_cc[termios::VEOF];
if veof != 0 {
EOFCHAR.store((veof) as i32, std::sync::atomic::Ordering::SeqCst);
}
termios.c_lflag &= !(termios::ICANON | termios::ECHO);
termios.c_cc[termios::VMIN] = 1;
termios.c_cc[termios::VTIME] = 0;
termios::tcsetattr(crate::ported::zle::zle_main::TTYFD.load(std::sync::atomic::Ordering::SeqCst), termios::TCSANOW, &termios)?;
Ok(())
}
pub fn ungetbyte(ch: u8) { crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().push_front(ch);
}
pub fn ungetbytes(s: &[u8]) {
for &b in s.iter().rev() {
crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().push_front(b);
}
}
fn calc_timeout(do_keytmout: bool) -> ztmout { let kt = KEYTIMEOUT.load(std::sync::atomic::Ordering::SeqCst);
if do_keytmout && kt > 0 {
let exp = if kt > ZMAXTIMEOUT * 100 { ZMAXTIMEOUT * 100 } else { kt };
ztmout {
tp: ztmouttp::ZTM_KEY,
exp100ths: exp as i64,
}
} else {
ztmout {
tp: ztmouttp::ZTM_NONE,
exp100ths: 0,
}
}
}
pub fn raw_getbyte(do_keytmout: bool) -> Option<u8> {
if let Some(b) = crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().pop_front() {
return Some(b);
}
let timeout = calc_timeout(do_keytmout);
let timeout_duration = if timeout.tp != ztmouttp::ZTM_NONE {
Some(Duration::from_millis((timeout.exp100ths * 10) as u64))
} else {
None
};
let mut buf = [0u8; 1];
if let Some(dur) = timeout_duration {
let start = Instant::now();
loop {
if start.elapsed() >= dur {
return None; }
match try_read_byte(&mut buf) {
Ok(true) => return Some(buf[0]),
Ok(false) => {
std::thread::sleep(Duration::from_millis(10));
}
Err(_) => return None,
}
}
} else {
use std::os::unix::io::AsRawFd;
let fd = io::stdin().as_raw_fd();
let is_tty = unsafe { libc::isatty(fd) } == 1;
let in_raw_mode = if is_tty {
let mut t: libc::termios = unsafe { std::mem::zeroed() };
if unsafe { libc::tcgetattr(fd, &mut t) } == 0 {
(t.c_lflag & libc::ICANON) == 0
} else {
false
}
} else {
true
};
if !in_raw_mode {
return None;
}
match io::stdin().read(&mut buf) {
Ok(1) => Some(buf[0]),
_ => None,
}
}
}
fn try_read_byte(buf: &mut [u8]) -> io::Result<bool> {
use std::os::unix::io::AsRawFd;
let mut fds = [libc::pollfd {
fd: io::stdin().as_raw_fd(),
events: libc::POLLIN,
revents: 0,
}];
let ret = unsafe { libc::poll(fds.as_mut_ptr(), 1, 0) };
if ret > 0 && (fds[0].revents & libc::POLLIN) != 0 {
match io::stdin().read(buf) {
Ok(1) => Ok(true),
Ok(_) => Ok(false),
Err(e) => Err(e),
}
} else {
Ok(false)
}
}
pub fn getbyte(do_keytmout: bool) -> Option<u8> {
let b = raw_getbyte(do_keytmout)?;
let b = if b == b'\n' {
b'\r'
} else if b == b'\r' {
b'\n'
} else {
b
};
crate::ported::zle::compcore::LASTCHAR.store((b as ZleInt) as i32, std::sync::atomic::Ordering::SeqCst);
Some(b)
}
pub fn getfullchar(do_keytmout: bool) -> Option<char> {
let b = getbyte(do_keytmout)?;
if b < 0x80 {
let c = b as char;
crate::ported::zle::zle_main::LASTCHAR_WIDE.store((c as ZleInt) as i32, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_main::LASTCHAR_WIDE_VALID.store(1, std::sync::atomic::Ordering::SeqCst);
return Some(c);
}
let mut bytes = vec![b];
let expected_len = if b < 0xE0 {
2
} else if b < 0xF0 {
3
} else {
4
};
while bytes.len() < expected_len {
if let Some(next) = getbyte(true) {
if (next & 0xC0) != 0x80 {
ungetbyte(next);
break;
}
bytes.push(next);
} else {
break;
}
}
if let Ok(s) = std::str::from_utf8(&bytes) {
if let Some(c) = s.chars().next() {
crate::ported::zle::zle_main::LASTCHAR_WIDE.store((c as ZleInt) as i32, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_main::LASTCHAR_WIDE_VALID.store(1, std::sync::atomic::Ordering::SeqCst);
return Some(c);
}
}
crate::ported::zle::zle_main::LASTCHAR_WIDE_VALID.store(0, std::sync::atomic::Ordering::SeqCst);
None
}
pub fn redrawhook() {
crate::ported::zle::zle_main::PENDING_HOOKS.lock().unwrap()
.push(("zle-line-pre-redraw".to_string(), None));
}
pub fn zlecore() { crate::ported::zle::zle_misc::DONE.store(0, std::sync::atomic::Ordering::SeqCst);
while crate::ported::zle::zle_misc::DONE.load(std::sync::atomic::Ordering::SeqCst) == 0 {
let thingy = match get_key_cmd() {
Some(t) => t,
None => {
EOFSENT.store(1, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_misc::DONE.store(1, std::sync::atomic::Ordering::SeqCst);
continue;
}
};
if crate::ported::zle::zle_main::ZLELL.load(std::sync::atomic::Ordering::SeqCst) == 0
&& crate::ported::zle::compcore::LASTCHAR.load(std::sync::atomic::Ordering::SeqCst) == EOFCHAR.load(std::sync::atomic::Ordering::SeqCst)
&& (crate::ported::zle::zle_main::ZLEREADFLAGS.load(std::sync::atomic::Ordering::SeqCst) & crate::ported::zsh_h::ZLRF_HISTORY) != 0
{
EOFSENT.store(1, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_misc::DONE.store(1, std::sync::atomic::Ordering::SeqCst);
continue;
}
*crate::ported::zle::zle_main::LBINDK.lock().unwrap() = crate::ported::zle::zle_main::BINDK.lock().unwrap().take();
*crate::ported::zle::zle_main::BINDK.lock().unwrap() = Some(thingy.clone());
if let Some(widget) = &thingy.widget {
execute_widget(widget);
} else {
handle_feep();
}
handleprefixes();
if in_vi_cmd_mode()
&& crate::ported::zle::zle_main::ZLECS.load(std::sync::atomic::Ordering::SeqCst) > findbol()
&& (crate::ported::zle::zle_main::ZLECS.load(std::sync::atomic::Ordering::SeqCst) == crate::ported::zle::zle_main::ZLELL.load(std::sync::atomic::Ordering::SeqCst)
|| crate::ported::zle::zle_main::ZLELINE.lock().unwrap().get(crate::ported::zle::zle_main::ZLECS.load(std::sync::atomic::Ordering::SeqCst)).copied() == Some('\n'))
&& crate::ported::zle::zle_main::ZLECS.load(std::sync::atomic::Ordering::SeqCst) > 0
{
crate::ported::zle::zle_main::ZLECS.fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
}
redrawhook();
if crate::ported::zle::zle_main::ZLE_RESET_NEEDED.load(std::sync::atomic::Ordering::SeqCst) != 0 {
zrefresh();
crate::ported::zle::zle_main::ZLE_RESET_NEEDED.store(0, std::sync::atomic::Ordering::SeqCst);
}
}
}
pub fn in_vi_cmd_mode() -> bool {
*crate::ported::zle::zle_keymap::curkeymapname() == "vicmd"
}
pub fn get_key_cmd() -> Option<super::zle_thingy::Thingy> {
let km = {
let local = crate::ported::zle::zle_keymap::LOCALKEYMAP.lock().unwrap().clone();
let cur = crate::ported::zle::zle_keymap::curkeymap.lock().unwrap().clone();
local.or(cur)?
};
let mut buf: Vec<u8> = Vec::with_capacity(8);
let mut last_match: Option<super::zle_thingy::Thingy> = None;
let mut last_match_len = 0usize;
loop {
let do_keytmout = last_match.is_some();
let b = getbyte(do_keytmout)?;
buf.push(b);
let (current_match, is_prefix) = if buf.len() == 1 {
let m = km.first[b as usize].clone();
let pfx = km
.multi
.keys()
.any(|k| k.len() > 1 && k[0] == b);
(m, pfx)
} else {
let entry = km.multi.get(&buf[..]);
let m = entry.and_then(|e| e.bind.clone());
let pfx = entry.map(|e| e.prefixct > 0).unwrap_or(false);
(m, pfx)
};
if let Some(t) = current_match {
last_match = Some(t);
last_match_len = buf.len();
}
if !is_prefix {
break;
}
}
if last_match.is_some() && buf.len() > last_match_len {
let extra = buf[last_match_len..].to_vec();
ungetbytes(&extra);
}
last_match
}
fn execute_widget(widget: &widget) {
if (widget.flags & ZLE_LASTCOL) == 0 {
crate::ported::zle::zle_main::LASTCOL.store(-1, std::sync::atomic::Ordering::SeqCst);
}
handleundo();
match &widget.u {
super::zle_h::WidgetImpl::Internal(f) => {
let _ = f(&[]);
}
super::zle_h::WidgetImpl::UserFunc(name) => {
let _ = crate::ported::zle::zle_main::execzlefunc(name, &[]);
}
_ => {}
}
if (widget.flags & ZLE_NOTCOMMAND) == 0 {
LASTCMD.store(widget.flags as u32, std::sync::atomic::Ordering::SeqCst);
}
mkundoent();
}
fn do_self_insert(c: char) {
if (crate::ported::zle::zle_main::INSMODE.load(std::sync::atomic::Ordering::SeqCst) != 0) {
crate::ported::zle::zle_main::ZLELINE.lock().unwrap().insert(crate::ported::zle::zle_main::ZLECS.load(std::sync::atomic::Ordering::SeqCst), c);
crate::ported::zle::zle_main::ZLECS.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_main::ZLELL.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
} else {
if crate::ported::zle::zle_main::ZLECS.load(std::sync::atomic::Ordering::SeqCst) < crate::ported::zle::zle_main::ZLELL.load(std::sync::atomic::Ordering::SeqCst) {
crate::ported::zle::zle_main::ZLELINE.lock().unwrap()[crate::ported::zle::zle_main::ZLECS.load(std::sync::atomic::Ordering::SeqCst)] = c;
} else {
crate::ported::zle::zle_main::ZLELINE.lock().unwrap().push(c);
crate::ported::zle::zle_main::ZLELL.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
}
crate::ported::zle::zle_main::ZLECS.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
}
crate::ported::zle::zle_main::ZLE_RESET_NEEDED.store(1, std::sync::atomic::Ordering::SeqCst);
}
pub fn zleread( lprompt: &str,
rprompt: &str,
flags: i32,
context: i32,
) -> io::Result<String> {
*crate::ported::zle::zle_main::RAW_LP.lock().unwrap() = lprompt.to_string();
*crate::ported::zle::zle_main::RAW_RP.lock().unwrap() = rprompt.to_string();
*crate::ported::zle::zle_main::LPROMPT.lock().unwrap() = crate::prompt::expand_prompt(lprompt);
*crate::ported::zle::zle_main::RPROMPT.lock().unwrap() = crate::prompt::expand_prompt(rprompt);
crate::ported::zle::zle_main::ZLEREADFLAGS.store(flags, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_main::ZLECONTEXT.store(context, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_main::ZLELINE.lock().unwrap().clear();
crate::ported::zle::zle_main::ZLECS.store(0, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_main::ZLELL.store(0, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_main::MARK.store(0, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_misc::DONE.store(0, std::sync::atomic::Ordering::SeqCst);
zsetterm()?;
{
use std::sync::atomic::Ordering;
let fd = crate::ported::init::SHTTY.load(Ordering::Relaxed);
let out = if fd >= 0 { fd } else { 1 };
let _ = crate::ported::utils::write_loop(out, lprompt.as_bytes());
}
zlecore();
Ok(crate::ported::zle::zle_main::ZLELINE.lock().unwrap().iter().collect())
}
pub fn initmodifier() {
*crate::ported::zle::zle_main::ZMOD.lock().unwrap() = modifier {
flags: 0,
mult: 1,
tmult: 1,
vibuf: 0,
base: 10,
};
}
pub fn handleprefixes() {
if (crate::ported::zle::zle_main::PREFIXFLAG.load(std::sync::atomic::Ordering::SeqCst) != 0) {
crate::ported::zle::zle_main::PREFIXFLAG.store(0, std::sync::atomic::Ordering::SeqCst);
if crate::ported::zle::zle_main::ZMOD.lock().unwrap().flags & MOD_TMULT != 0 {
crate::ported::zle::zle_main::ZMOD.lock().unwrap().flags &= !MOD_TMULT;
crate::ported::zle::zle_main::ZMOD.lock().unwrap().flags |= MOD_MULT;
let mut __g_zmod = crate::ported::zle::zle_main::ZMOD.lock().unwrap();
__g_zmod.mult = __g_zmod.tmult;
}
} else {
initmodifier();
}
}
pub fn trashzle() { use std::sync::atomic::Ordering;
let fd = crate::ported::init::SHTTY.load(Ordering::Relaxed);
let out = if fd >= 0 { fd } else { 1 };
let _ = crate::ported::utils::write_loop(out, b"\r\x1b[K\x1b[0m");
crate::ported::zle::zle_main::ZLE_RESET_NEEDED.store(1, std::sync::atomic::Ordering::SeqCst);
}
pub fn resetprompt() {
crate::ported::zle::zle_main::ZLE_RESET_NEEDED.store(1, std::sync::atomic::Ordering::SeqCst);
}
pub fn reexpandprompt() {
let raw_lp = crate::ported::zle::zle_main::RAW_LP.lock().unwrap().clone();
let raw_rp = crate::ported::zle::zle_main::RAW_RP.lock().unwrap().clone();
*crate::ported::zle::zle_main::LPROMPT.lock().unwrap() = crate::prompt::expand_prompt(&raw_lp);
*crate::ported::zle::zle_main::RPROMPT.lock().unwrap() = crate::prompt::expand_prompt(&raw_rp);
crate::ported::zle::zle_main::ZLE_RESET_NEEDED.store(1, std::sync::atomic::Ordering::SeqCst);
}
pub fn recursive_edit() -> i32 {
crate::ported::zle::zle_main::ZLE_RECURSIVE.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
let old_done = crate::ported::zle::zle_misc::DONE.load(std::sync::atomic::Ordering::SeqCst) != 0;
let old_eofsent = EOFSENT.load(std::sync::atomic::Ordering::SeqCst);
redrawhook();
zrefresh();
crate::ported::zle::zle_misc::DONE.store(0, std::sync::atomic::Ordering::SeqCst);
EOFSENT.store(0, std::sync::atomic::Ordering::SeqCst);
zlecore();
let locerror = EOFSENT.load(std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_misc::DONE.store(if old_done { 1 } else { 0 }, std::sync::atomic::Ordering::SeqCst);
EOFSENT.store(old_eofsent, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_main::ZLE_RECURSIVE.fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
locerror
}
pub fn finish_line() {
crate::ported::zle::zle_misc::DONE.store(1, std::sync::atomic::Ordering::SeqCst);
}
pub fn abort_line() {
crate::ported::zle::zle_main::ZLELINE.lock().unwrap().clear();
crate::ported::zle::zle_main::ZLECS.store(0, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_main::ZLELL.store(0, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_misc::DONE.store(1, std::sync::atomic::Ordering::SeqCst);
}
pub fn describe_key_briefly() {
if let Some(c) = getfullchar(false) {
let thingy = if c as u32 > 255 {
None
} else {
let km = crate::ported::zle::zle_keymap::LOCALKEYMAP
.lock()
.unwrap()
.clone()
.or_else(|| {
crate::ported::zle::zle_keymap::curkeymap.lock().unwrap().clone()
});
km.and_then(|k| k.first[c as usize].clone())
};
if let Some(thingy) = thingy {
display_msg(&format!("{} is bound to {}", c, thingy.nam));
} else {
display_msg(&format!("{} is not bound", c));
}
}
}
pub fn whereis(widget_name: &str) -> Vec<String> {
let mut bindings = Vec::new();
let tab = crate::ported::zle::zle_keymap::keymapnamtab().lock().unwrap();
for (name, node) in tab.iter() {
let km = &node.keymap;
for (i, opt) in km.first.iter().enumerate() {
if let Some(t) = opt {
if t.nam == widget_name {
bindings.push(format!("{}:{}", name, super::zle_utils::printbind(&[i as u8])));
}
}
}
for (seq, kb) in &km.multi {
if let Some(ref t) = kb.bind {
if t.nam == widget_name {
bindings.push(format!("{}:{}", name, super::zle_utils::printbind(seq)));
}
}
}
}
bindings
}
#[allow(unused_variables)]
#[allow(unused_variables)]
fn display_msg(msg: &str) {
eprintln!("{}", msg);
}
pub fn prompt() -> String {
crate::ported::zle::zle_main::LPROMPT.lock().unwrap().clone()
}
pub fn rprompt() -> String {
crate::ported::zle::zle_main::RPROMPT.lock().unwrap().clone()
}
pub fn set_prompt(prompt: &str) {
*crate::ported::zle::zle_main::LPROMPT.lock().unwrap() = prompt.to_string();
crate::ported::zle::zle_main::ZLE_RESET_NEEDED.store(1, std::sync::atomic::Ordering::SeqCst);
}
pub fn get_mult() -> i32 {
if crate::ported::zle::zle_main::ZMOD.lock().unwrap().flags & MOD_MULT != 0 {
crate::ported::zle::zle_main::ZMOD.lock().unwrap().mult
} else {
1
}
}
pub fn toggle_neg_arg() {
crate::ported::zle::zle_main::ZMOD.lock().unwrap().flags ^= MOD_NEG;
}
pub fn is_neg() -> bool {
crate::ported::zle::zle_main::ZMOD.lock().unwrap().flags & MOD_NEG != 0
}
pub fn is_vicmd() -> bool {
*crate::ported::zle::zle_keymap::curkeymapname() == "vicmd"
}
pub fn is_viins() -> bool {
*crate::ported::zle::zle_keymap::curkeymapname() == "viins"
}
pub fn is_emacs() -> bool {
let n = crate::ported::zle::zle_keymap::curkeymapname();
*n == "emacs" || *n == "main"
}
pub fn was_yank() -> bool {
(LASTCMD.load(std::sync::atomic::Ordering::SeqCst) as i32 & ZLE_YANK) != 0
}
pub fn bin_vared(name: &str, args: &[String], ops: &crate::ported::zsh_h::options, _func: i32) -> i32 {
use crate::ported::zsh_h::{OPT_ISSET, OPT_ARG_SAFE, PM_SCALAR, PM_ARRAY, PM_HASHED};
use crate::ported::utils::zwarnnam;
let mut type_: u32 = PM_SCALAR; let term = std::env::var("TERM").unwrap_or_default();
if term == "emacs" { zwarnnam(name, "ZLE not enabled"); return 1; }
if crate::ported::builtins::sched::zleactive.load( std::sync::atomic::Ordering::Relaxed) != 0 {
zwarnnam(name, "ZLE cannot be used recursively (yet)"); return 1; }
let _warn_flags = if OPT_ISSET(ops, b'g') { 0 } else { 1 }; if OPT_ISSET(ops, b'A') { if OPT_ISSET(ops, b'a') { zwarnnam(name, "specify only one of -a and -A"); return 1; }
type_ = PM_HASHED; } else if OPT_ISSET(ops, b'a') { type_ = PM_ARRAY; }
let p1 = OPT_ARG_SAFE(ops, b'p').unwrap_or(""); let p2 = OPT_ARG_SAFE(ops, b'r').unwrap_or(""); let main_keymapname = OPT_ARG_SAFE(ops, b'M').unwrap_or(""); let vicmd_keymapname = OPT_ARG_SAFE(ops, b'm').unwrap_or(""); let init = OPT_ARG_SAFE(ops, b'i').unwrap_or(""); let finish = OPT_ARG_SAFE(ops, b'f').unwrap_or(""); let _ = (main_keymapname, vicmd_keymapname, init, finish);
if type_ != PM_SCALAR && !OPT_ISSET(ops, b'c') { zwarnnam(name, &format!("-{} ignored", if type_ == PM_ARRAY { "a" } else { "A" }));
}
if args.is_empty() {
zwarnnam(name, "not enough arguments");
return 1;
}
let varname = &args[0]; crate::ported::mem::queue_signals();
let exists = {
let tab = crate::ported::params::paramtab().read().unwrap();
tab.contains_key(varname)
};
if !exists && !OPT_ISSET(ops, b'c') { crate::ported::mem::unqueue_signals(); zwarnnam(name, &format!("no such variable: {}", varname)); return 1; }
crate::ported::mem::unqueue_signals();
let prompt = if !p1.is_empty() { p1.to_string() } else { String::new() };
let rprompt = if !p2.is_empty() { p2.to_string() } else { String::new() };
let current = crate::ported::params::getsparam(varname).unwrap_or_default();
{
use std::sync::atomic::Ordering;
let fd = crate::ported::init::SHTTY.load(Ordering::Relaxed);
let out = if fd >= 0 { fd } else { 1 };
if !prompt.is_empty() {
let _ = crate::ported::utils::write_loop(out, prompt.as_bytes());
}
let _ = crate::ported::utils::write_loop(out, current.as_bytes());
if !rprompt.is_empty() {
let _ = crate::ported::utils::write_loop(out, rprompt.as_bytes());
}
}
let mut input = String::new();
if std::io::stdin().read_line(&mut input).is_ok() { let value = input.trim_end_matches('\n').to_string();
crate::ported::params::setsparam(varname, &value); return 0; }
1
}
mod termios {
pub use libc::{ECHO, ICANON, TCSANOW, VEOF, VMIN, VTIME};
use std::io;
use std::os::unix::io::RawFd;
#[derive(Clone)]
pub struct Termios {
inner: libc::termios,
}
impl Termios {
pub fn from_fd(fd: RawFd) -> io::Result<Self> {
let mut termios = std::mem::MaybeUninit::uninit();
let ret = unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) };
if ret != 0 {
return Err(io::Error::last_os_error());
}
Ok(Termios {
inner: unsafe { termios.assume_init() },
})
}
}
impl std::ops::Deref for Termios {
type Target = libc::termios;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl std::ops::DerefMut for Termios {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
pub fn tcsetattr(fd: RawFd, action: i32, termios: &Termios) -> io::Result<()> {
let ret = unsafe { libc::tcsetattr(fd, action, &termios.inner) };
if ret != 0 {
return Err(io::Error::last_os_error());
}
Ok(())
}
}
#[cfg(test)]
mod ztmout_findfunc_tests {
use super::*;
#[test]
fn ztmouttp_discriminant_values() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
assert_eq!(ztmouttp::ZTM_NONE as i32, 0);
assert_eq!(ztmouttp::ZTM_KEY as i32, 1);
assert_eq!(ztmouttp::ZTM_FUNC as i32, 2);
assert_eq!(ztmouttp::ZTM_MAX as i32, 3);
}
#[test]
fn ztmout_default_carries_none_type() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
let t = ztmout { tp: ztmouttp::ZTM_NONE, exp100ths: 0 };
assert_eq!(t.tp, ztmouttp::ZTM_NONE);
}
#[test]
fn findfunc_default_is_empty() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
let f = findfunc::default();
assert_eq!(f.func, None);
assert_eq!(f.found, 0);
assert!(f.msg.is_empty());
}
#[test]
fn findfunc_can_accumulate_message() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
let mut f = findfunc { func: Some(42), found: 0, msg: String::new() };
f.found += 1;
f.msg.push_str(" is on KEY1");
assert_eq!(f.found, 1);
assert!(f.msg.contains("is on"));
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn handleprefixes_promotes_tmult_to_mult_when_prefixflag_set() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
crate::ported::zle::zle_main::ZMOD.lock().unwrap().flags |= MOD_TMULT;
crate::ported::zle::zle_main::ZMOD.lock().unwrap().tmult = 7;
crate::ported::zle::zle_main::PREFIXFLAG.store(1, std::sync::atomic::Ordering::SeqCst);
handleprefixes();
assert!(crate::ported::zle::zle_main::ZMOD.lock().unwrap().flags & MOD_MULT != 0);
assert!(!crate::ported::zle::zle_main::ZMOD.lock().unwrap().flags & MOD_TMULT != 0);
assert_eq!(crate::ported::zle::zle_main::ZMOD.lock().unwrap().mult, 7);
assert!(crate::ported::zle::zle_main::PREFIXFLAG.load(std::sync::atomic::Ordering::SeqCst) == 0);
}
#[test]
fn handleprefixes_resets_modifier_when_prefixflag_cleared() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
crate::ported::zle::zle_main::ZMOD.lock().unwrap().flags |= MOD_MULT;
crate::ported::zle::zle_main::ZMOD.lock().unwrap().mult = 9;
crate::ported::zle::zle_main::PREFIXFLAG.store(0, std::sync::atomic::Ordering::SeqCst);
handleprefixes();
assert_eq!(crate::ported::zle::zle_main::ZMOD.lock().unwrap().mult, 1);
assert!(!crate::ported::zle::zle_main::ZMOD.lock().unwrap().flags & MOD_MULT != 0);
}
#[test]
fn get_key_cmd_resolves_single_byte_binding() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
crate::ported::zle::zle_keymap::selectkeymap("emacs", 1);
ungetbytes(b"\x05"); let t = get_key_cmd().expect("should resolve Ctrl-E");
assert_eq!(t.nam, "end-of-line");
}
#[test]
fn get_key_cmd_resolves_multi_byte_sequence() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
crate::ported::zle::zle_keymap::selectkeymap("emacs", 1);
ungetbytes(b"\x1bd");
let t = get_key_cmd().expect("should resolve ESC-d");
assert_ne!(t.nam, "self-insert");
}
#[test]
fn get_key_cmd_returns_none_on_eof() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
crate::ported::zle::zle_keymap::selectkeymap("emacs", 1);
let result = get_key_cmd();
let _ = result;
}
#[test]
fn handle_undo_snapshots_line_for_subsequent_diff() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
*crate::ported::zle::zle_main::ZLELINE.lock().unwrap() = "abc".chars().collect();
crate::ported::zle::zle_main::ZLELL.store(3, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_main::ZLECS.store(3, std::sync::atomic::Ordering::SeqCst);
handleundo();
assert_eq!(crate::ported::zle::zle_main::LASTLINE.lock().unwrap().iter().collect::<String>(), "abc");
assert_eq!(crate::ported::zle::zle_main::LASTLL.load(std::sync::atomic::Ordering::SeqCst), 3);
assert_eq!(crate::ported::zle::zle_main::LASTCS.load(std::sync::atomic::Ordering::SeqCst), 3);
}
#[test]
fn in_vi_cmd_mode_reflects_active_keymap_name() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
*crate::ported::zle::zle_keymap::curkeymapname() = "emacs".to_string();
assert!(!in_vi_cmd_mode());
*crate::ported::zle::zle_keymap::curkeymapname() = "vicmd".to_string();
assert!(in_vi_cmd_mode());
}
#[test]
fn ungetbytes_unmeta_plain_bytes() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
crate::ported::zle::zle_main::zle_reset();
crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().clear();
ungetbytes_unmeta(b"abc");
assert_eq!(crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().pop_front(), Some(b'a'));
assert_eq!(crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().pop_front(), Some(b'b'));
assert_eq!(crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().pop_front(), Some(b'c'));
}
#[test]
fn ungetbytes_unmeta_decodes_meta_pair() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
crate::ported::zle::zle_main::zle_reset();
crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().clear();
ungetbytes_unmeta(&[0x83, 0x41]);
assert_eq!(crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().pop_front(), Some(b'a'));
assert!(crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().is_empty());
}
#[test]
fn ungetbytes_unmeta_mixed_meta_and_plain() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
crate::ported::zle::zle_main::zle_reset();
crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().clear();
ungetbytes_unmeta(&[0x58, 0x83, 0x41, 0x5a]);
assert_eq!(crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().pop_front(), Some(b'X'));
assert_eq!(crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().pop_front(), Some(b'a'));
assert_eq!(crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().pop_front(), Some(b'Z'));
assert!(crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().is_empty());
}
#[test]
fn ungetbytes_unmeta_empty_input() {
let _g = crate::ported::zle::zle_main::zle_test_setup();
crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().clear();
ungetbytes_unmeta(b"");
assert!(crate::ported::zle::zle_main::KUNGETBUF.lock().unwrap().is_empty());
}
}
pub fn boot_(_m: *const crate::ported::zsh_h::module) -> i32 { crate::ported::module::addhookfunc("before_trap", "zlebeforetrap"); crate::ported::module::addhookfunc("after_trap", "zleaftertrap");
if let Ok(mut t) = crate::ported::module::HOOKTAB.lock() {
for name in ["insert_match", "menu_start", "compctl_make", "compctl_cleanup", "comp_list_matches"] {
t.entry(name.to_string()).or_default();
}
}
0 }
pub fn breakread(fd: i32, buf: &mut [u8], n: usize) -> isize { if n == 0 || buf.is_empty() {
return 0;
}
let count = n.min(buf.len());
let r = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut libc::c_void, count) };
r as isize
}
pub fn cleanup_(_m: *const crate::ported::zsh_h::module) -> i32 { use std::sync::atomic::Ordering;
if crate::ported::builtins::sched::zleactive.load(Ordering::Relaxed) != 0 {
return 1;
}
crate::ported::module::deletehookfunc("before_trap", "zlebeforetrap"); crate::ported::module::deletehookfunc("after_trap", "zleaftertrap"); if let Ok(mut tab) = crate::ported::zle::zle_keymap::keymapnamtab().lock() {
tab.clear();
}
0 }
pub fn describekeybriefly() -> i32 { 1 }
#[allow(unused_variables)]
pub fn enables_(m: *const crate::ported::zsh_h::module, enables: &mut Option<Vec<i32>>) -> i32 {
0
}
pub fn execimmortal(func: &str, args: &[String]) -> i32 { let dotted = format!(".{}", func);
if crate::ported::zle::zle_thingy::rthingy_nocreate(&dotted) { return execzlefunc(&dotted, args);
}
1 }
pub fn execzlefunc(name: &str, args: &[String]) -> i32 { if !crate::ported::zle::zle_thingy::rthingy_nocreate(name) { return 1;
}
if crate::ported::utils::getshfunc(name).is_some() { let rc = crate::fusevm_bridge::with_executor(|exec| {
exec.dispatch_function_call(name, args).unwrap_or(0)
});
crate::ported::builtin::LASTVAL.store(rc, std::sync::atomic::Ordering::Relaxed);
return rc;
}
0
}
pub fn features_(_m: *const crate::ported::zsh_h::module,
features: &mut Vec<String>) -> i32 { features.clear();
features.extend([
"b:bindkey".to_string(),
"b:vared".to_string(),
"b:zle".to_string(),
"p:KEYMAP".to_string(),
"p:CONTEXT".to_string(),
"p:KEYS".to_string(),
"p:NUMERIC".to_string(),
"p:PREDISPLAY".to_string(),
"p:POSTDISPLAY".to_string(),
"p:BUFFER".to_string(),
"p:CURSOR".to_string(),
"p:CUTBUFFER".to_string(),
"p:HISTNO".to_string(),
"p:KILLRING".to_string(),
"p:LASTSEARCH".to_string(),
"p:LASTWIDGET".to_string(),
"p:MARK".to_string(),
"p:PREBUFFER".to_string(),
"p:RBUFFER".to_string(),
"p:LBUFFER".to_string(),
"p:REGION_ACTIVE".to_string(),
"p:UNDO_CHANGE_NO".to_string(),
"p:UNDO_LIMIT_NO".to_string(),
"p:WIDGET".to_string(),
"p:WIDGETSTYLE".to_string(),
"p:WIDGETFUNC".to_string(),
"p:registers".to_string(),
"p:ZLE_LINE_ABORTED".to_string(),
]);
0 }
#[allow(unused_variables)]
pub fn finish_(m: *const crate::ported::zsh_h::module) -> i32 { 0
}
pub fn getrestchar(inchar: i32) -> i32 { crate::ported::zle::zle_main::LASTCHAR_WIDE_VALID.store(1, std::sync::atomic::Ordering::SeqCst);
if inchar < 0 {
crate::ported::zle::zle_main::LASTCHAR_WIDE.store((-1) as i32, std::sync::atomic::Ordering::SeqCst);
return -1; }
crate::ported::zle::zle_main::LASTCHAR_WIDE.store((inchar) as i32, std::sync::atomic::Ordering::SeqCst);
inchar
}
pub fn recursiveedit() -> i32 { use std::sync::atomic::Ordering;
crate::ported::zle::zle_main::ZLE_RECURSIVE.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
crate::ported::zle::zle_main::ZLE_RECURSIVE.fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
let cur_errflag = crate::ported::utils::errflag.load(Ordering::Relaxed);
let locerror = if cur_errflag != 0 { 1 } else { 0 };
crate::ported::utils::errflag.store(0, Ordering::Relaxed);
crate::ported::zle::zle_misc::DONE.store(0, Ordering::SeqCst); locerror }
pub fn restorekeymap(oldname: &str, savemap: Option<std::sync::Arc<crate::ported::zle::zle_keymap::Keymap>>) { if let Some(km) = savemap {
crate::ported::zle::zle_keymap::linkkeymap(km, oldname, 0);
}
}
pub fn savekeymap(oldname: &str, newname: &str) -> Option<std::sync::Arc<crate::ported::zle::zle_keymap::Keymap>> { let km = crate::ported::zle::zle_keymap::openkeymap(newname)?;
let saved = crate::ported::zle::zle_keymap::openkeymap(oldname);
let same = saved.as_ref().map(|s| std::sync::Arc::ptr_eq(s, &km)).unwrap_or(false);
if !same {
crate::ported::zle::zle_keymap::linkkeymap(km, oldname, 0);
}
if same { None } else { saved }
}
pub fn scanfindfunc(seq: &str, func: &str, ff: &mut findfunc) { const MAXFOUND: usize = 3; let want = ff.func.map(|i| i.to_string()).unwrap_or_default();
if !want.is_empty() && func != want { return; }
if ff.found == 0 { ff.msg.push_str(" is on"); }
ff.found += 1;
if ff.found <= MAXFOUND { ff.msg.push(' '); ff.msg.push_str(seq); }
}
#[allow(unused_variables)]
pub fn setup_(m: *const crate::ported::zsh_h::module) -> i32 { 0
}
pub fn ungetbytes_unmeta(s: &[u8]) { let mut i = s.len(); while i > 0 { if i >= 2 && s[i - 2] == 0x83 { ungetbyte(s[i - 1] ^ 32);
i -= 2;
} else {
ungetbyte(s[i - 1]);
i -= 1;
}
}
}
pub fn zle_resetprompt() { use std::sync::atomic::Ordering;
ZLE_RESET_NEEDED.store(1, Ordering::SeqCst);
if crate::ported::builtins::sched::zleactive.load(Ordering::Relaxed) != 0 {
crate::ported::zle::zle_refresh::SHOWINGLIST.store(-2, Ordering::SeqCst);
}
}
pub static ZLE_RESET_NEEDED: std::sync::atomic::AtomicI32 =
std::sync::atomic::AtomicI32::new(0);
pub static INSMODE: std::sync::atomic::AtomicI32 = std::sync::atomic::AtomicI32::new(1);
pub static LASTCHAR_WIDE: std::sync::atomic::AtomicI32 =
std::sync::atomic::AtomicI32::new(0);
pub static LASTCHAR_WIDE_VALID: std::sync::atomic::AtomicI32 =
std::sync::atomic::AtomicI32::new(0);
pub static EOFCHAR: std::sync::atomic::AtomicI32 =
std::sync::atomic::AtomicI32::new(4);
pub static EOFSENT: std::sync::atomic::AtomicI32 =
std::sync::atomic::AtomicI32::new(0);
pub static PREFIXFLAG: std::sync::atomic::AtomicI32 =
std::sync::atomic::AtomicI32::new(0);
pub static ZLEREADFLAGS: std::sync::atomic::AtomicI32 =
std::sync::atomic::AtomicI32::new(
crate::ported::zsh_h::ZLRF_HISTORY | crate::ported::zsh_h::ZLRF_NOSETTY,
);
pub static ZLECONTEXT: std::sync::atomic::AtomicI32 =
std::sync::atomic::AtomicI32::new(crate::ported::zsh_h::ZLCON_LINE_START);
pub static ZLE_RECURSIVE: std::sync::atomic::AtomicI32 =
std::sync::atomic::AtomicI32::new(0);
pub static KEYTIMEOUT: std::sync::atomic::AtomicU64 =
std::sync::atomic::AtomicU64::new(40);
pub static LASTCMD: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0);
pub static WATCH_FDS: std::sync::Mutex<Vec<super::zle_h::watch_fd>> = std::sync::Mutex::new(Vec::new());
pub static ZLELINE: std::sync::Mutex<Vec<ZleChar>> = std::sync::Mutex::new(Vec::new());
pub static ZLECS: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
pub static ZLELL: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
pub static MARK: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
pub static LBINDK: std::sync::Mutex<Option<Thingy>> = std::sync::Mutex::new(None);
pub static BINDK: std::sync::Mutex<Option<Thingy>> = std::sync::Mutex::new(None);
pub static ZMOD: std::sync::Mutex<modifier> = std::sync::Mutex::new(modifier { flags: 0, mult: 1, tmult: 1, vibuf: 0, base: 10 });
pub static STATUSLINE: std::sync::Mutex<Option<String>> = std::sync::Mutex::new(None);
pub static STACKHIST: std::sync::atomic::AtomicI32 = std::sync::atomic::AtomicI32::new(0);
pub static STACKCS: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
pub static VISTARTCHANGE: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
pub static UNDO_STACK: std::sync::Mutex<Vec<change>> = std::sync::Mutex::new(Vec::new());
pub static CHANGENO: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
pub static KUNGETBUF: std::sync::Mutex<VecDeque<u8>> = std::sync::Mutex::new(VecDeque::new());
pub static BAUD: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(38400);
pub static COMPWIDGET: std::sync::Mutex<Option<Widget>> = std::sync::Mutex::new(None);
pub static HASCOMPMOD: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
pub static TTYFD: std::sync::atomic::AtomicI32 = std::sync::atomic::AtomicI32::new(0);
pub static LPROMPT: std::sync::Mutex<String> = std::sync::Mutex::new(String::new());
pub static RPROMPT: std::sync::Mutex<String> = std::sync::Mutex::new(String::new());
pub static PRE_ZLE_STATUS: std::sync::atomic::AtomicI32 = std::sync::atomic::AtomicI32::new(0);
pub static VIBUF: std::sync::OnceLock<std::sync::Mutex<[Vec<ZleChar>; 36]>> = std::sync::OnceLock::new();
pub fn vibuf() -> &'static std::sync::Mutex<[Vec<ZleChar>; 36]> {
VIBUF.get_or_init(|| std::sync::Mutex::new(std::array::from_fn(|_| Vec::new())))
}
pub static KILLRING: std::sync::Mutex<VecDeque<Vec<ZleChar>>> = std::sync::Mutex::new(VecDeque::new());
pub static KILLRINGMAX: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(8);
pub static YANKLAST: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
pub static NEG_ARG: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
pub static MULT: std::sync::atomic::AtomicI32 = std::sync::atomic::AtomicI32::new(1);
pub static HISTORY: std::sync::OnceLock<std::sync::Mutex<super::zle_hist::History>> = std::sync::OnceLock::new();
pub fn history() -> &'static std::sync::Mutex<super::zle_hist::History> {
HISTORY.get_or_init(|| std::sync::Mutex::new(super::zle_hist::History::new(2000)))
}
pub static LASTCOL: std::sync::atomic::AtomicI32 = std::sync::atomic::AtomicI32::new(-1);
pub static BUFSTACK: std::sync::Mutex<Vec<String>> = std::sync::Mutex::new(Vec::new());
pub static VICHGBUF: std::sync::Mutex<Vec<u8>> = std::sync::Mutex::new(Vec::new());
pub static SRCH_STR: std::sync::Mutex<Option<String>> = std::sync::Mutex::new(None);
pub static LASTLINE: std::sync::Mutex<Vec<ZleChar>> = std::sync::Mutex::new(Vec::new());
pub static LASTLL: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
pub static LASTCS: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
pub static CURCHANGE: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
pub static UNDO_CHANGENO: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
pub static UNDO_LIMITNO: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
pub static VIINSBEGIN: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
pub static YANKB: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
pub static YANKE: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
pub static YANKCS: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
pub static KCT: std::sync::Mutex<Option<usize>> = std::sync::Mutex::new(None);
pub static VIMARKS: std::sync::OnceLock<std::sync::Mutex<[Option<(usize, i32)>; 27]>> = std::sync::OnceLock::new();
pub fn vimarks() -> &'static std::sync::Mutex<[Option<(usize, i32)>; 27]> {
VIMARKS.get_or_init(|| std::sync::Mutex::new([None; 27]))
}
pub static REGION_ACTIVE: std::sync::atomic::AtomicU8 = std::sync::atomic::AtomicU8::new(0);
pub static PENDING_HOOKS: std::sync::Mutex<Vec<(String, Option<String>)>> = std::sync::Mutex::new(Vec::new());
pub static RAW_LP: std::sync::Mutex<String> = std::sync::Mutex::new(String::new());
pub static RAW_RP: std::sync::Mutex<String> = std::sync::Mutex::new(String::new());
pub static HIGHLIGHT: std::sync::OnceLock<std::sync::Mutex<super::zle_refresh::HighlightManager>> = std::sync::OnceLock::new();
pub fn highlight() -> &'static std::sync::Mutex<super::zle_refresh::HighlightManager> {
HIGHLIGHT.get_or_init(|| std::sync::Mutex::new(super::zle_refresh::HighlightManager::new()))
}
pub fn zleaftertrap() -> i32 { use std::sync::atomic::Ordering;
if crate::ported::builtins::sched::zleactive.load(Ordering::Relaxed) != 0 { crate::ported::params::endparamscope(); }
0 }
pub fn zlebeforetrap() -> i32 { use std::sync::atomic::Ordering;
if crate::ported::builtins::sched::zleactive.load(Ordering::Relaxed) != 0 { let mut local_scope: crate::ported::zsh_h::HashTable = Box::new(
crate::ported::zsh_h::hashtable {
hsize: 0, ct: 0, nodes: Vec::new(), tmpdata: 0,
hash: None, emptytable: None, filltable: None,
cmpnodes: None, addnode: None, getnode: None,
getnode2: None, removenode: None, disablenode: None,
enablenode: None, freenode: None, printnode: None,
scantab: None,
},
);
crate::ported::params::startparamscope(&mut local_scope);
crate::ported::zle::zle_params::makezleparams(1);
}
0 }