use crate::ported::lib::dict::{mergeargs, mergedicts};
use crate::ported::lib::overrides::parse_override_var;
use serde_json::{Map, Value};
pub struct PDBPowerline;
impl Default for PDBPowerline {
fn default() -> Self {
Self::new()
}
}
impl PDBPowerline {
pub fn new() -> Self {
Self
}
pub fn init() -> (&'static str, &'static str) {
("pdb", "pdb")
}
pub fn do_setup(&self, _pdb: &Value) {
}
pub fn load_main_config(&self, base: &mut Map<String, Value>) {
if let Ok(s) = std::env::var("POWERLINE_CONFIG_OVERRIDES") {
if !s.is_empty() {
if let Some(overlay) = mergeargs(parse_override_var(&s), false) {
mergedicts(base, overlay, false);
}
}
}
}
pub fn load_theme_config(&self, name: &str, base: &mut Map<String, Value>) {
if let Ok(s) = std::env::var("POWERLINE_THEME_OVERRIDES") {
if !s.is_empty() {
if let Some(overlay) = mergeargs(parse_override_var(&s), false) {
if let Some(theme) = overlay.get(name) {
if let Some(theme_obj) = theme.as_object() {
mergedicts(base, theme_obj.clone(), false);
}
}
}
}
}
}
pub fn get_config_paths() -> Vec<String> {
match std::env::var("POWERLINE_CONFIG_PATHS") {
Ok(s) if !s.is_empty() => s
.split(':')
.filter(|p| !p.is_empty())
.map(|p| p.to_string())
.collect(),
_ => Vec::new(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Mutex;
use std::sync::OnceLock;
static ENV_LOCK: OnceLock<Mutex<()>> = OnceLock::new();
macro_rules! lock_env {
() => {{
ENV_LOCK
.get_or_init(|| Mutex::new(()))
.lock()
.unwrap_or_else(|e| e.into_inner())
}};
}
#[test]
fn init_pins_ext_and_renderer_module_to_pdb() {
let (ext, renderer) = PDBPowerline::init();
assert_eq!(ext, "pdb");
assert_eq!(renderer, "pdb");
}
#[test]
fn do_setup_does_not_panic() {
let p = PDBPowerline::new();
p.do_setup(&Value::Null);
}
#[test]
fn load_main_config_no_env_leaves_base_untouched() {
let _g = lock_env!();
unsafe {
std::env::remove_var("POWERLINE_CONFIG_OVERRIDES");
}
let mut base: Map<String, Value> = Map::new();
base.insert("a".to_string(), Value::from(1));
let p = PDBPowerline::new();
p.load_main_config(&mut base);
assert_eq!(base.get("a"), Some(&Value::from(1)));
assert_eq!(base.len(), 1);
}
#[test]
fn load_main_config_overlays_from_env() {
let _g = lock_env!();
unsafe {
std::env::set_var("POWERLINE_CONFIG_OVERRIDES", "common.term_truecolor=true");
}
let mut base: Map<String, Value> = Map::new();
let p = PDBPowerline::new();
p.load_main_config(&mut base);
unsafe {
std::env::remove_var("POWERLINE_CONFIG_OVERRIDES");
}
let common = base.get("common").and_then(|v| v.as_object());
assert!(common.is_some(), "expected 'common' overlay key");
let truecolor = common.unwrap().get("term_truecolor");
assert_eq!(truecolor, Some(&Value::Bool(true)));
}
#[test]
fn load_main_config_empty_env_leaves_base_untouched() {
let _g = lock_env!();
unsafe {
std::env::set_var("POWERLINE_CONFIG_OVERRIDES", "");
}
let mut base: Map<String, Value> = Map::new();
base.insert("k".to_string(), Value::from(1));
let p = PDBPowerline::new();
p.load_main_config(&mut base);
unsafe {
std::env::remove_var("POWERLINE_CONFIG_OVERRIDES");
}
assert_eq!(base.get("k"), Some(&Value::from(1)));
}
#[test]
fn load_theme_config_overlays_matching_name() {
let _g = lock_env!();
unsafe {
std::env::set_var("POWERLINE_THEME_OVERRIDES", "default.foo=bar");
}
let mut base: Map<String, Value> = Map::new();
let p = PDBPowerline::new();
p.load_theme_config("default", &mut base);
unsafe {
std::env::remove_var("POWERLINE_THEME_OVERRIDES");
}
assert_eq!(base.get("foo"), Some(&Value::String("bar".into())));
}
#[test]
fn load_theme_config_ignores_non_matching_name() {
let _g = lock_env!();
unsafe {
std::env::set_var("POWERLINE_THEME_OVERRIDES", "default.foo=bar");
}
let mut base: Map<String, Value> = Map::new();
let p = PDBPowerline::new();
p.load_theme_config("other_theme", &mut base);
unsafe {
std::env::remove_var("POWERLINE_THEME_OVERRIDES");
}
assert!(base.get("foo").is_none());
}
#[test]
fn load_theme_config_no_env_leaves_base_untouched() {
let _g = lock_env!();
unsafe {
std::env::remove_var("POWERLINE_THEME_OVERRIDES");
}
let mut base: Map<String, Value> = Map::new();
base.insert("k".to_string(), Value::from(0));
let p = PDBPowerline::new();
p.load_theme_config("default", &mut base);
assert_eq!(base.get("k"), Some(&Value::from(0)));
}
#[test]
fn get_config_paths_reads_colon_separated_env() {
let _g = lock_env!();
unsafe {
std::env::set_var("POWERLINE_CONFIG_PATHS", "/a:/b:/c");
}
let paths = PDBPowerline::get_config_paths();
unsafe {
std::env::remove_var("POWERLINE_CONFIG_PATHS");
}
assert_eq!(paths, vec!["/a", "/b", "/c"]);
}
#[test]
fn get_config_paths_filters_empty_entries() {
let _g = lock_env!();
unsafe {
std::env::set_var("POWERLINE_CONFIG_PATHS", "::/a::/b:");
}
let paths = PDBPowerline::get_config_paths();
unsafe {
std::env::remove_var("POWERLINE_CONFIG_PATHS");
}
assert_eq!(paths, vec!["/a", "/b"]);
}
#[test]
fn get_config_paths_empty_returns_empty_vec() {
let _g = lock_env!();
unsafe {
std::env::remove_var("POWERLINE_CONFIG_PATHS");
}
let paths = PDBPowerline::get_config_paths();
assert!(paths.is_empty());
}
#[test]
fn get_config_paths_empty_env_string_returns_empty() {
let _g = lock_env!();
unsafe {
std::env::set_var("POWERLINE_CONFIG_PATHS", "");
}
let paths = PDBPowerline::get_config_paths();
unsafe {
std::env::remove_var("POWERLINE_CONFIG_PATHS");
}
assert!(paths.is_empty());
}
}