1use std::env;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum TerminalName {
6 WindowsTerminal,
7 VsCode,
8 Iterm2,
9 AppleTerminal,
10 Ghostty,
11 Kitty,
12 WezTerm,
13 Alacritty,
14 Tmux,
15 Zellij,
16 Unknown,
17}
18
19impl TerminalName {
20 pub fn label(&self) -> &'static str {
21 match self {
22 TerminalName::WindowsTerminal => "WindowsTerminal",
23 TerminalName::VsCode => "VsCode",
24 TerminalName::Iterm2 => "iTerm2",
25 TerminalName::AppleTerminal => "AppleTerminal",
26 TerminalName::Ghostty => "Ghostty",
27 TerminalName::Kitty => "Kitty",
28 TerminalName::WezTerm => "WezTerm",
29 TerminalName::Alacritty => "Alacritty",
30 TerminalName::Tmux => "Tmux",
31 TerminalName::Zellij => "Zellij",
32 TerminalName::Unknown => "Terminal",
33 }
34 }
35}
36
37pub fn detect_terminal() -> TerminalName {
39 if env::var("ZELLIJ").is_ok() || env::var("ZELLIJ_SESSION_NAME").is_ok() {
41 return TerminalName::Zellij;
42 }
43 if env::var("TMUX").is_ok() {
44 return TerminalName::Tmux;
45 }
46
47 if let Ok(prog) = env::var("TERM_PROGRAM") {
49 match prog.to_lowercase().as_str() {
50 "vscode" => return TerminalName::VsCode,
51 "iterm.app" => return TerminalName::Iterm2,
52 "apple_terminal" => return TerminalName::AppleTerminal,
53 "ghostty" => return TerminalName::Ghostty,
54 "wezterm" => return TerminalName::WezTerm,
55 _ => {}
56 }
57 }
58
59 if env::var("WT_SESSION").is_ok() {
61 return TerminalName::WindowsTerminal;
62 }
63 if env::var("KITTY_WINDOW_ID").is_ok() {
64 return TerminalName::Kitty;
65 }
66 if env::var("ALACRITTY_SOCKET").is_ok() {
67 return TerminalName::Alacritty;
68 }
69
70 if let Ok(term) = env::var("TERM") {
72 let lower = term.to_lowercase();
73 if lower.contains("iterm") {
74 return TerminalName::Iterm2;
75 }
76 if lower.contains("kitty") {
77 return TerminalName::Kitty;
78 }
79 if lower.contains("alacritty") {
80 return TerminalName::Alacritty;
81 }
82 if lower.contains("wezterm") {
83 return TerminalName::WezTerm;
84 }
85 }
86
87 TerminalName::Unknown
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_windows_terminal_detection() {
96 let old_term = std::env::var("TERM_PROGRAM").ok();
98 std::env::remove_var("TERM_PROGRAM");
99
100 std::env::set_var("WT_SESSION", "test-session");
101 assert_eq!(detect_terminal(), TerminalName::WindowsTerminal);
102
103 std::env::remove_var("WT_SESSION");
104 if let Some(val) = old_term {
105 std::env::set_var("TERM_PROGRAM", val);
106 }
107 }
108
109 #[test]
110 fn test_vscode_detection() {
111 std::env::set_var("TERM_PROGRAM", "vscode");
112 assert_eq!(detect_terminal(), TerminalName::VsCode);
113 std::env::remove_var("TERM_PROGRAM");
114 }
115}