use serde_json::{json, Value};
pub fn enumerate_all_overlays() -> Vec<(String, Value)> {
let mut out: Vec<(String, Value)> = Vec::new();
crate::fusevm_bridge::with_executor(|exec| {
let alias_e = exec.alias_entries();
if !alias_e.is_empty() {
out.push(("alias".into(), entries_to_json(&alias_e)));
}
let galias_e = exec.global_alias_entries();
if !galias_e.is_empty() {
out.push(("galias".into(), entries_to_json(&galias_e)));
}
let salias_e = exec.suffix_alias_entries();
if !salias_e.is_empty() {
out.push(("salias".into(), entries_to_json(&salias_e)));
}
let opts_snap = crate::ported::options::opt_state_snapshot();
if !opts_snap.is_empty() {
let map: serde_json::Map<String, Value> = opts_snap
.iter()
.map(|(k, v)| (k.clone(), Value::String(if *v { "on" } else { "off" }.into())))
.collect();
out.push(("setopt".into(), Value::Object(map)));
}
let scalar_entries: Vec<(String, String)> =
if let Ok(tab) = crate::ported::params::paramtab().read() {
tab.iter()
.filter(|(_, pm)| pm.u_arr.is_none())
.map(|(k, pm)| (k.clone(), pm.u_str.clone().unwrap_or_default()))
.collect()
} else {
Vec::new()
};
let array_entries: Vec<(String, Vec<String>)> =
if let Ok(tab) = crate::ported::params::paramtab().read() {
tab.iter()
.filter_map(|(k, pm)| pm.u_arr.clone().map(|a| (k.clone(), a)))
.collect()
} else {
Vec::new()
};
let assoc_entries: Vec<(String, indexmap::IndexMap<String, String>)> =
if let Ok(m) = crate::ported::params::paramtab_hashed_storage().lock() {
m.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
} else {
Vec::new()
};
if !scalar_entries.is_empty() || !array_entries.is_empty() || !assoc_entries.is_empty() {
let mut params = serde_json::Map::new();
for (k, v) in scalar_entries {
params.insert(k, Value::String(v));
}
for (k, v) in array_entries {
params.insert(
k,
Value::Array(v.iter().map(|s| Value::String(s.clone())).collect()),
);
}
for (k, v) in assoc_entries {
let inner: serde_json::Map<String, Value> = v
.iter()
.map(|(ik, iv)| (ik.clone(), Value::String(iv.clone())))
.collect();
params.insert(k, Value::Object(inner));
}
out.push(("params".into(), Value::Object(params)));
}
if !exec.fpath.is_empty() {
out.push((
"fpath".into(),
Value::Array(
exec.fpath
.iter()
.map(|p| Value::String(p.display().to_string()))
.collect(),
),
));
}
let nd_snap: Vec<(String, String)> = crate::ported::hashnameddir::nameddirtab()
.lock().ok()
.map(|g| g.iter().map(|(k, v)| (k.clone(), v.dir.clone())).collect())
.unwrap_or_default();
if !nd_snap.is_empty() {
let map: serde_json::Map<String, Value> = nd_snap
.into_iter()
.map(|(k, v)| (k, Value::String(v)))
.collect();
out.push(("named_dir".into(), Value::Object(map)));
}
let _ = exec;
if !exec.completions.is_empty() {
let map: serde_json::Map<String, Value> = exec
.completions
.iter()
.map(|(k, v)| (k.clone(), json!(format!("{:?}", v))))
.collect();
out.push(("compdef".into(), Value::Object(map)));
}
if !exec.zstyles.is_empty() {
let arr: Vec<Value> = exec
.zstyles
.iter()
.map(|z| json!(format!("{:?}", z)))
.collect();
out.push(("zstyle".into(), Value::Array(arr)));
}
});
let mut env_map = serde_json::Map::new();
for (k, v) in std::env::vars() {
env_map.insert(k, Value::String(v));
}
if !env_map.is_empty() {
out.push(("env".into(), Value::Object(env_map)));
}
if let Ok(p) = std::env::var("PATH") {
let parts: Vec<Value> = p
.split(':')
.filter(|s| !s.is_empty())
.map(|s| Value::String(s.into()))
.collect();
if !parts.is_empty() {
out.push(("path".into(), Value::Array(parts)));
}
}
if let Ok(p) = std::env::var("MANPATH") {
let parts: Vec<Value> = p
.split(':')
.filter(|s| !s.is_empty())
.map(|s| Value::String(s.into()))
.collect();
if !parts.is_empty() {
out.push(("manpath".into(), Value::Array(parts)));
}
}
out
}
fn map_to_json<'a, I>(iter: I) -> Value
where
I: IntoIterator<Item = (&'a String, &'a String)>,
{
let map: serde_json::Map<String, Value> = iter
.into_iter()
.map(|(k, v)| (k.clone(), Value::String(v.clone())))
.collect();
Value::Object(map)
}
fn entries_to_json(entries: &[(String, String)]) -> Value {
let map: serde_json::Map<String, Value> = entries
.iter()
.map(|(k, v)| (k.clone(), Value::String(v.clone())))
.collect();
Value::Object(map)
}