Skip to content

Commit 3a329d5

Browse files
committed
feat(progress): Allow querying support
1 parent 218e6d4 commit 3a329d5

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

crates/anstyle-progress/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
#![warn(clippy::print_stdout)]
1313

1414
mod progress;
15+
mod query;
1516

1617
pub use progress::TermProgress;
1718
pub use progress::TermProgressStatus;
19+
pub use query::supports_term_progress;
1820

1921
#[doc = include_str!("../README.md")]
2022
#[cfg(doctest)]
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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

Comments
 (0)