Skip to main content

anstyle_progress/
query.rs

1/// Determines whether the terminal supports ANSI OSC 9;4.
2pub fn supports_term_progress(is_terminal: bool) -> bool {
3    let windows_terminal = std::env::var("WT_SESSION").is_ok();
4    let conemu = std::env::var("ConEmuANSI").ok() == Some("ON".into());
5    let wezterm = std::env::var("TERM_PROGRAM").ok() == Some("WezTerm".into());
6    let ghostty = std::env::var("TERM_PROGRAM").ok() == Some("ghostty".into());
7    // iTerm added OSC 9;4 support in v3.6.6, which we can check for.
8    // For context: https://github.com/rust-lang/cargo/pull/16506#discussion_r2706584034
9    let iterm = std::env::var("TERM_PROGRAM").ok() == Some("iTerm.app".into())
10        && std::env::var("TERM_FEATURES")
11            .ok()
12            .map(|v| term_features_has_progress(&v))
13            .unwrap_or(false);
14    // Ptyxis added OSC 9;4 support in 48.0.
15    // See https://gitlab.gnome.org/chergert/ptyxis/-/issues/305
16    let ptyxis = std::env::var("PTYXIS_VERSION")
17        .ok()
18        .and_then(|version| version.split(".").next()?.parse::<i32>().ok())
19        .map(|major_version| major_version >= 48)
20        .unwrap_or(false);
21
22    (windows_terminal || conemu || wezterm || ghostty || iterm || ptyxis) && is_terminal
23}
24
25// For iTerm, the TERM_FEATURES value "P" indicates OSC 9;4 support.
26// Context: https://iterm2.com/feature-reporting/
27fn term_features_has_progress(value: &str) -> bool {
28    let mut current = String::new();
29
30    for ch in value.chars() {
31        if !ch.is_ascii_alphanumeric() {
32            break;
33        }
34        if ch.is_ascii_uppercase() {
35            if current == "P" {
36                return true;
37            }
38            current.clear();
39            current.push(ch);
40        } else {
41            current.push(ch);
42        }
43    }
44    current == "P"
45}
46
47#[cfg(test)]
48mod tests {
49    use super::term_features_has_progress;
50
51    #[test]
52    fn term_features_progress_detection() {
53        // With PROGRESS feature ("P")
54        assert!(term_features_has_progress("MBT2ScP"));
55
56        // Without PROGRESS feature
57        assert!(!term_features_has_progress("MBT2Sc"));
58    }
59}