use std::ffi::{CStr, c_void};
use std::sync::LazyLock;
use indexmap::IndexSet;
use crate::variables::optional;
mod internal;
pub use internal::*;
pub fn set_opts() -> IndexSet<String> {
let opts = optional("SHELLOPTS").unwrap_or_default();
opts.split(':').map(|s| s.to_string()).collect()
}
pub fn shopt_opts() -> IndexSet<String> {
let opts = optional("BASHOPTS").unwrap_or_default();
opts.split(':').map(|s| s.to_string()).collect()
}
pub static SET_OPTS: LazyLock<IndexSet<&str>> = LazyLock::new(|| {
let mut opts = IndexSet::new();
let mut i = 0;
unsafe {
let opt_ptrs = get_set_options();
while let Some(p) = (*opt_ptrs.offset(i)).as_ref() {
opts.insert(CStr::from_ptr(p).to_str().unwrap());
i += 1;
}
libc::free(opt_ptrs as *mut c_void);
}
opts
});
pub static SHOPT_OPTS: LazyLock<IndexSet<&str>> = LazyLock::new(|| {
let mut opts = IndexSet::new();
let mut i = 0;
unsafe {
let opt_ptrs = get_shopt_options();
while let Some(p) = (*opt_ptrs.offset(i)).as_ref() {
opts.insert(CStr::from_ptr(p).to_str().unwrap());
i += 1;
}
libc::free(opt_ptrs as *mut c_void);
}
opts
});
#[cfg(test)]
mod tests {
use crate::builtins::{set, shopt};
use super::*;
#[test]
fn test_set_opts() {
assert!(SET_OPTS.contains("noexec"));
assert!(!set_opts().contains("noexec"));
set::enable(["noexec"]).unwrap();
assert!(set_opts().contains("noexec"));
set::disable(["noexec"]).unwrap();
assert!(!set_opts().contains("noexec"));
}
#[test]
fn test_shopt_opts() {
assert!(SHOPT_OPTS.contains("autocd"));
assert!(!shopt_opts().contains("autocd"));
shopt::enable(["autocd"]).unwrap();
assert!(shopt_opts().contains("autocd"));
shopt::disable(["autocd"]).unwrap();
assert!(!shopt_opts().contains("autocd"));
}
}