Skip to content

Add terminal integration via ANSI OSC 9;4 sequences #14615

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/cargo/core/compiler/job_queue/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ impl<'gctx> DrainState<'gctx> {
}

fn handle_error(
&self,
&mut self,
shell: &mut Shell,
err_state: &mut ErrorsDuringDrain,
new_err: impl Into<ErrorToHandle>,
Expand All @@ -863,6 +863,7 @@ impl<'gctx> DrainState<'gctx> {
if new_err.print_always || err_state.count == 0 {
crate::display_error(&new_err.error, shell);
if err_state.count == 0 && !self.active.is_empty() {
self.progress.indicate_error();
let _ = shell.warn("build failed, waiting for other jobs to finish...");
}
err_state.count += 1;
Expand Down
24 changes: 24 additions & 0 deletions src/cargo/core/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ impl Shell {
stderr_tty: std::io::stderr().is_terminal(),
stdout_unicode: supports_unicode(&std::io::stdout()),
stderr_unicode: supports_unicode(&std::io::stderr()),
stderr_term_integration: supports_term_integration(&std::io::stderr()),
},
verbosity: Verbosity::Verbose,
needs_clear: false,
Expand Down Expand Up @@ -122,6 +123,18 @@ impl Shell {
}
}

pub fn is_err_term_integration_available(&self) -> bool {
if let ShellOut::Stream {
stderr_term_integration,
..
} = self.output
{
stderr_term_integration
} else {
false
}
}

/// Gets a reference to the underlying stdout writer.
pub fn out(&mut self) -> &mut dyn Write {
if self.needs_clear {
Expand Down Expand Up @@ -426,6 +439,7 @@ enum ShellOut {
hyperlinks: bool,
stdout_unicode: bool,
stderr_unicode: bool,
stderr_term_integration: bool,
},
}

Expand Down Expand Up @@ -575,6 +589,16 @@ fn supports_hyperlinks() -> bool {
supports_hyperlinks::supports_hyperlinks()
}

/// Determines whether the terminal supports ANSI OSC 9;4.
#[allow(clippy::disallowed_methods)] // Read environment variables to detect terminal
fn supports_term_integration(stream: &dyn IsTerminal) -> bool {
let windows_terminal = std::env::var("WT_SESSION").is_ok();
let conemu = std::env::var("ConEmuANSI").ok() == Some("ON".into());
let wezterm = std::env::var("TERM_PROGRAM").ok() == Some("WezTerm".into());

(windows_terminal || conemu || wezterm) && stream.is_terminal()
}

pub struct Hyperlink<D: fmt::Display> {
url: Option<D>,
}
Expand Down
5 changes: 5 additions & 0 deletions src/cargo/util/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2832,6 +2832,8 @@ pub struct TermConfig {
pub struct ProgressConfig {
pub when: ProgressWhen,
pub width: Option<usize>,
/// Communicate progress status with a terminal
pub term_integration: Option<bool>,
}

#[derive(Debug, Default, Deserialize)]
Expand Down Expand Up @@ -2864,10 +2866,12 @@ where
"auto" => Ok(Some(ProgressConfig {
when: ProgressWhen::Auto,
width: None,
term_integration: None,
})),
"never" => Ok(Some(ProgressConfig {
when: ProgressWhen::Never,
width: None,
term_integration: None,
})),
"always" => Err(E::custom("\"always\" progress requires a `width` key")),
_ => Err(E::unknown_variant(s, &["auto", "never"])),
Expand All @@ -2889,6 +2893,7 @@ where
if let ProgressConfig {
when: ProgressWhen::Always,
width: None,
..
} = pc
{
return Err(serde::de::Error::custom(
Expand Down
Loading