|
| 1 | +/// Determines whether the terminal supports ANSI OSC 9;4. |
| 2 | +pub 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/ |
| 27 | +fn 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)] |
| 48 | +mod 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 | +} |
0 commit comments