1pub use crate::xdg::detect_terminal_xdg_proposed;
6use crate::{desktops::*, DetectionError, Terminal};
7use std::{env::var, path::Path};
8
9pub fn detect_terminal_env() -> Result<Terminal, DetectionError> {
11 let term = var("TERMINAL")?;
12 Ok(term.into())
13}
14
15pub fn detect_terminal_desktop() -> Result<Terminal, DetectionError> {
17 let desktop = var("XDG_CURRENT_DESKTOP")?;
18 let desktop = desktop.split(':').last().unwrap_or_default();
20 match desktop {
21 "Deepin" => detect_terminal_desktop_deepin(),
22 "GNOME" => detect_terminal_desktop_gnome(),
23 "KDE" => detect_terminal_desktop_kde(),
24 "LXDE" => detect_terminal_desktop_lxde(),
25 "LXQt" => detect_terminal_desktop_lxqt(),
26 "X-Cinnamon" => detect_terminal_desktop_cinnamon(),
27 "XFCE" => detect_terminal_desktop_xfce(),
28 _ => Err(DetectionError::UnsupportedDesktopError),
29 }
30}
31
32pub(crate) fn path_check(path_var: &Vec<&str>, term: &str) -> Option<String> {
33 for path in path_var {
35 let bin = format!("{}/{}", path, term);
36 let bin_path = Path::new(&bin);
37 if bin_path.exists() {
38 return Some(term.to_owned());
39 }
40 }
41 None
42}
43
44pub fn detect_terminal_path() -> Result<Terminal, DetectionError> {
46 let path_var = var("PATH").unwrap_or_default();
47 let path_var: Vec<&str> = path_var.split(':').collect();
48 for term in &[
49 "x-terminal-emulator", "konsole",
51 "gnome-terminal",
52 "alacritty",
53 "terminator",
54 "st",
55 "urxvt",
56 ] {
57 if let Some(term) = path_check(&path_var, term) {
58 return Ok(term.into());
59 }
60 }
61 Err(DetectionError::FindError)
62}
63
64#[cfg(target_os = "linux")]
66pub fn detect_terminal() -> Result<Terminal, DetectionError> {
67 let mut errors = Vec::new();
68 macro_rules! return_or_add {
69 ($e:expr) => {
70 match $e {
71 Ok(term) => return Ok(term),
72 Err(e) => errors.push(e),
73 }
74 };
75 }
76
77 return_or_add!(detect_terminal_env());
79 return_or_add!(detect_terminal_xdg_proposed());
81 return_or_add!(detect_terminal_desktop());
83 return_or_add!(detect_terminal_path());
85
86 Err(errors.into())
87}
88
89#[cfg(not(target_os = "linux"))]
90fn detect_terminal() -> Result<String, DetectionError> {
91 panic!("unsupported os")
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn env_test() {
100 let term = Terminal::from("abcterm");
101 std::env::set_var("TERMINAL", &term.0);
102 assert!(detect_terminal_env().unwrap() == term);
103 }
104 }