anstyle_progress/query.rs
1/// Determines whether the terminal supports ANSI OSC 9;4.
2pub fn supports_term_progress(is_terminal: bool) -> bool {
3 if !is_terminal {
4 return false;
5 }
6
7 // Terminal feature detection, includes
8 // - iTerm support in v3.6.6
9 let term_features = std::env::var("TERM_FEATURES")
10 .ok()
11 .map(|v| term_features_has_progress(&v))
12 .unwrap_or(false);
13 if term_features {
14 return true;
15 }
16
17 // https://github.com/wezterm/wezterm/issues/6581
18 // https://ghostty.org/docs/install/release-notes/1-2-0#graphical-progress-bars
19 let term_program = std::env::var("TERM_PROGRAM").ok();
20 if matches!(term_program.as_deref(), Some("WezTerm") | Some("ghostty")) {
21 return true;
22 }
23
24 // https://github.com/microsoft/terminal/pull/8055
25 if std::env::var("WT_SESSION").is_ok() {
26 return true;
27 }
28
29 // https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC
30 if std::env::var("ConEmuANSI").ok() == Some("ON".into()) {
31 return true;
32 }
33
34 // Ptyxis added OSC 9;4 support in 48.0.
35 // See https://gitlab.gnome.org/chergert/ptyxis/-/issues/305
36 let ptyxis = std::env::var("PTYXIS_VERSION")
37 .ok()
38 .and_then(|version| version.split(".").next()?.parse::<i32>().ok())
39 .map(|major_version| major_version >= 48)
40 .unwrap_or(false);
41 if ptyxis {
42 return true;
43 }
44
45 false
46}
47
48// For iTerm, the TERM_FEATURES value "P" indicates OSC 9;4 support.
49//
50// Context: https://iterm2.com/feature-reporting/
51fn term_features_has_progress(value: &str) -> bool {
52 let mut current = String::new();
53
54 for ch in value.chars() {
55 if !ch.is_ascii_alphanumeric() {
56 break;
57 }
58 if ch.is_ascii_uppercase() {
59 if current == "P" {
60 return true;
61 }
62 current.clear();
63 current.push(ch);
64 } else {
65 current.push(ch);
66 }
67 }
68 current == "P"
69}
70
71#[cfg(test)]
72mod tests {
73 use super::term_features_has_progress;
74
75 #[test]
76 fn term_features_progress_detection() {
77 // With PROGRESS feature ("P")
78 assert!(term_features_has_progress("MBT2ScP"));
79
80 // Without PROGRESS feature
81 assert!(!term_features_has_progress("MBT2Sc"));
82 }
83}