pub const ZREGEX_EXTENDED: i32 = 0;
pub fn zcond_regex_match(a: &[&str], id: i32) -> i32 { if a.len() < 2 {
return 0;
}
let lhstr = a[0]; let rhre = a[1]; let mut return_value: i32 = 0;
if id != ZREGEX_EXTENDED {
return 0;
}
let casematch = crate::ported::zsh_h::isset(crate::ported::options::optlookup("casematch"));
let pat_for_compile = if !casematch { format!("(?i){}", rhre) } else {
rhre.to_string()
};
let re = match regex::Regex::new(&pat_for_compile) {
Ok(r) => r,
Err(_) => { zregex_regerrwarn("-regex-match", "failed to compile regex");
return 0; }
};
let captures = match re.captures(lhstr) {
Some(c) => c,
None => return 0, };
return_value = 1; let nsub = re.captures_len() - 1; let bashre = crate::ported::zsh_h::isset(crate::ported::options::optlookup("bashrematch"));
let ksharr = crate::ported::zsh_h::isset(crate::ported::options::optlookup("ksharrays"));
let (start, nelem) = if bashre {
(0usize, nsub + 1) } else {
(1usize, nsub) };
let mut arr: Vec<String> = Vec::with_capacity(nelem);
for n in start..=nsub { if let Some(m) = captures.get(n) { arr.push(m.as_str().to_string()); } else {
arr.push(String::new());
}
}
if bashre { crate::ported::params::setsparam("BASH_REMATCH", &arr.join(":"));
return return_value;
}
let m0 = captures.get(0).expect("regex matched but no group 0");
let full = m0.as_str().to_string(); crate::ported::params::setsparam("MATCH", &full);
let so = m0.start();
let eo = m0.end();
let mbegin_chars = lhstr[..so].chars().count() as i64; let kshoff: i64 = if ksharr { 0 } else { 1 }; let mbegin = mbegin_chars + kshoff; crate::ported::params::setiparam("MBEGIN", mbegin);
let match_chars = lhstr[so..eo].chars().count() as i64;
let mend_total = mbegin_chars + match_chars;
let mend = mend_total + kshoff - 1; crate::ported::params::setiparam("MEND", mend);
if nelem > 0 { let mut mbegin_arr: Vec<String> = Vec::with_capacity(nelem);
let mut mend_arr: Vec<String> = Vec::with_capacity(nelem);
for n in 0..nelem { let cap_idx = start + n;
match captures.get(cap_idx) { Some(m) => {
let beg_chars = lhstr[..m.start()].chars().count() as i64;
let len_chars = lhstr[m.start()..m.end()].chars().count() as i64;
mbegin_arr.push((beg_chars + kshoff).to_string()); mend_arr.push((beg_chars + len_chars + kshoff - 1).to_string()); }
None => { mbegin_arr.push("-1".to_string());
mend_arr.push("-1".to_string());
}
}
}
crate::ported::params::setsparam("match", &arr.join(":"));
crate::ported::params::setsparam("mbegin", &mbegin_arr.join(":"));
crate::ported::params::setsparam("mend", &mend_arr.join(":"));
}
return_value }
pub fn zregex_regerrwarn(prefix: &str, err_msg: &str) { crate::ported::utils::zwarnnam(prefix, err_msg); }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn match_returns_one() {
let r = zcond_regex_match(&["hello world", "wor.d"], ZREGEX_EXTENDED);
assert_eq!(r, 1);
}
#[test]
fn captures_returns_one() {
let r = zcond_regex_match(&["foo=42", "([a-z]+)=([0-9]+)"], ZREGEX_EXTENDED);
assert_eq!(r, 1);
}
#[test]
fn no_match_returns_zero() {
let r = zcond_regex_match(&["abc", "xyz"], ZREGEX_EXTENDED);
assert_eq!(r, 0);
}
#[test]
fn invalid_pattern_returns_zero() {
assert_eq!(
zcond_regex_match(&["anything", "["], ZREGEX_EXTENDED),
0
);
}
#[test]
fn missing_args_returns_zero() {
assert_eq!(zcond_regex_match(&[], ZREGEX_EXTENDED), 0);
assert_eq!(zcond_regex_match(&["only_lhs"], ZREGEX_EXTENDED), 0);
}
#[test]
fn casematch_off_is_case_insensitive() {
let r = zcond_regex_match(&["HELLO", "hello"], ZREGEX_EXTENDED);
assert_eq!(r, 0);
}
}
use crate::ported::zsh_h::module;
#[allow(unused_variables)]
pub fn setup_(m: *const module) -> i32 { 0
}
pub fn features_(m: *const module, features: &mut Vec<String>) -> i32 {
*features = featuresarray(m, module_features());
0
}
pub fn enables_(m: *const module, enables: &mut Option<Vec<i32>>) -> i32 {
handlefeatures(m, module_features(), enables)
}
#[allow(unused_variables)]
pub fn boot_(m: *const module) -> i32 { 0
}
pub fn cleanup_(m: *const module) -> i32 {
setfeatureenables(m, module_features(), None)
}
#[allow(unused_variables)]
pub fn finish_(m: *const module) -> i32 { 0
}
use crate::ported::zsh_h::features as features_t;
use std::sync::{Mutex, OnceLock};
static MODULE_FEATURES: OnceLock<Mutex<features_t>> = OnceLock::new();
fn module_features() -> &'static Mutex<features_t> {
MODULE_FEATURES.get_or_init(|| Mutex::new(features_t {
bn_list: None,
bn_size: 0,
cd_list: None,
cd_size: 1,
mf_list: None,
mf_size: 0,
pd_list: None,
pd_size: 0,
n_abstract: 0,
}))
}
fn featuresarray(_m: *const module, _f: &Mutex<features_t>) -> Vec<String> {
vec!["c:regex-match".to_string()]
}
fn handlefeatures(
_m: *const module,
_f: &Mutex<features_t>,
enables: &mut Option<Vec<i32>>,
) -> i32 {
if enables.is_none() {
*enables = Some(vec![1; 1]);
}
0
}
fn setfeatureenables(
_m: *const module,
_f: &Mutex<features_t>,
_e: Option<&[i32]>,
) -> i32 {
0
}