use crate::{DetectionError, Terminal};
use configparser::ini::Ini;
use std::{env::var, fs::read_to_string, path::Path};
fn xdg_term_from_desktop_file<P: AsRef<Path>>(path: P) -> Result<Terminal, DetectionError> {
let path = path.as_ref();
let mut config = Ini::new_cs();
if let Err(e) = config.load(path) {
return Err(DetectionError::IniParseError(e));
};
let Some(term) = config.get("Desktop Entry", "Exec") else {
return Err(DetectionError::DesktopFileError(
path.to_string_lossy().to_string(),
));
};
Ok(term.into())
}
fn xdg_try_desktop<P: AsRef<Path>>(path: P) -> Result<Terminal, DetectionError> {
let path = path.as_ref();
let mut errors = vec![];
macro_rules! return_or_add {
($($arg:tt)*) => {
match xdg_term_from_desktop_file(format!($($arg)*)) {
Ok(term) => return Ok(term),
Err(e) => errors.push(e),
}
};
}
if path.is_absolute() {
return xdg_term_from_desktop_file(path);
}
if let Ok(home) = var("HOME") {
return_or_add!(
"{}/.local/share/applications/{}",
home,
path.to_string_lossy()
);
};
return_or_add!("/usr/share/applications/{}", path.to_string_lossy());
Err(errors.into())
}
fn xdg_try_config<P: AsRef<Path>>(path: P) -> Result<Terminal, DetectionError> {
let path = path.as_ref();
let config = read_to_string(path)?;
let lines = config.lines();
let mut errors = vec![];
for maybe_term_desktop in lines {
match xdg_try_desktop(maybe_term_desktop) {
Ok(term) => return Ok(term),
Err(e) => errors.push(e),
}
}
Err(errors.into())
}
pub fn detect_terminal_xdg_proposed() -> Result<Terminal, DetectionError> {
let home = var("HOME");
let desktop = var("XDG_CURRENT_DESKTOP");
let mut errors = vec![];
macro_rules! return_or_add {
($($arg:tt)*) => {
match xdg_try_config(format!($($arg)*)) {
Ok(term) => return Ok(term),
Err(e) => errors.push(e),
}
};
}
if let Ok(home) = home {
if let Ok(desktop) = &desktop {
return_or_add!(
"{}/.config/{}-xdg-terminals.list",
home,
desktop.to_lowercase()
);
}
return_or_add!("{}/.config/xdg-terminals.list", home);
};
if let Ok(desktop) = &desktop {
return_or_add!("/etc/xdg/{}-xdg-terminals.list", desktop.to_lowercase());
};
return_or_add!("/etc/xdg/xdg-terminals.list");
if let Ok(desktop) = desktop {
return_or_add!("/usr/etc/xdg/{}-xdg-terminals.list", desktop.to_lowercase());
};
return_or_add!("/usr/etc/xdg/xdg-terminals.list");
Err(errors.into())
}