Skip to content
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

Taskbar progress reporting via ANSI codes #14615

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Gordon01
Copy link

@Gordon01 Gordon01 commented Sep 29, 2024

What does this PR try to resolve?

A few terminal emulators support progress output to Windows taskbar. winget uses this to show install progress.

Notably, Windows Terminal recently (2020) added support for ANSI codes specified in ConEmu (another terminal emulator for Windows) documentation. Also, in "Learn Windows".

I've found the previous attempt to add this feature: #11436

As per @weihanglo's request, I've added the config option to enable/disable this feature. It's enabled on supported terminal emulators.

Fixes #11432

How should we test and review this PR?

Run cargo build in Windows Terminal with configuration option term.progress.taskbar set to true.

Not sure

  • Should all the code be #[cfg(windows)]? Probably no, because the feature is also usable in WSL.

Solved by introducing heuristic based on environment variable set by terminal

  • If Ctrl+C is pressed, a progressbar will stay in a last state forever (shown in the ConEmu video). winget is also behaves like alike. I've experimented with ctrl_c handler and it's totally fixable.
  • Enabled is a sensible default for WSL because it works on linux builds in Windows Terminal too

Solved by introducing heuristic based on environment variable set by terminal

  • Downloading stage may produce unpleasant blinking due to a rapid 0-100 changes

Solved by not displaying bar when downloading and using indeterminate state in other cases so amination don't reset

TLDR

  • An term.progress.taskbar option with bool type is added
  • On Windows Terminal and ConEmu is enabled by default
  • If enabled reports build progress to taskbar icon and/or tab header

Videos

Windows.PowerShell.2024-09-29.23-21-21.mp4
cmd.2024-09-29.23-36-25.mp4

@rustbot
Copy link
Collaborator

rustbot commented Sep 29, 2024

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @epage (or someone else) some time within the next two weeks.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue

@rustbot rustbot added A-configuration Area: cargo config files and env vars A-console-output Area: Terminal output, colors, progress bar, etc. A-documenting-cargo-itself Area: Cargo's documentation S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 29, 2024
src/cargo/util/progress.rs Outdated Show resolved Hide resolved
src/cargo/util/progress.rs Outdated Show resolved Hide resolved
src/cargo/util/progress.rs Outdated Show resolved Hide resolved
@epage epage added the T-cargo Team: Cargo label Sep 30, 2024
@weihanglo
Copy link
Member

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 15, 2024
@Gordon01
Copy link
Author

Hello, Ed, thank you for the review and sorry for the late feedback. It's been a lot of work lately.

@epage
Copy link
Contributor

epage commented Nov 18, 2024

Hello, Ed, thank you for the review and sorry for the late feedback. It's been a lot of work lately.

Understandable!

Comment on lines +150 to +171
// From https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC
// ESC ] 9 ; 4 ; st ; pr ST
// When st is 0: remove progress.
// When st is 1: set progress value to pr (number, 0-100).
// When st is 2: set error state in taskbar, pr is optional.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From #14615 (comment)

This also raises another small issue: if user stops cargo with ctrl+c, taskbar progress is not cleared and it stays until the next invocation of a program with taskbar progress report capability. Microsoft's own winget behaves like this.
I've tried to set ctrl+c handler in cargo and clear taskbar from there. It works, but it 50-100 LOC which would be used rarely. What do you think of this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am hesitant to have a ctrl+c handler but I also have had enough bad experience on Windows with colors being leaked from a program and could see myself being annoyed about progress state leaking as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's my prvious work on ctrl+c handler: de22a7f

The approach works, but then we need to set the handler depending on Progress.state. Can you please advice on this? Do you want to have a handler in src/bin/cargo/main.rs ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ehuss I'd be interested in your opinion on this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're now detecting a terminal regardless of the OS, a ctrl+c handler needs to be portable too, not like in my first implementation. If we still want to go this way, a few questions:

  1. Can we use external crate like https://crates.io/crates/ctrlc? I assume your policy is to use as few external crates as possible
  2. Will it iterfere with https://github.com/rust-lang/cargo/blob/master/crates/cargo-util/src/process_builder.rs#L259-L276? I don't fully understand when this code is used.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used when cargo executes binaries for cargo run or cargo <plugin>. Not familiar with Windows but I would assume for these execvp cases we are not expected to see them returning.

@Gordon01 Gordon01 force-pushed the taskbar_progress branch 4 times, most recently from 5ff7484 to 584ee00 Compare November 21, 2024 19:28
@rustbot rustbot added the A-build-execution Area: anything dealing with executing the compiler label Nov 21, 2024
src/cargo/util/progress.rs Outdated Show resolved Hide resolved
@epage
Copy link
Contributor

epage commented Nov 21, 2024

This is looking really great and making me jealous that my terminal doesn't support it!

@Gordon01 Gordon01 force-pushed the taskbar_progress branch 2 times, most recently from 10e457d to c6d0d63 Compare November 23, 2024 08:45
@Gordon01
Copy link
Author

Gordon01 commented Nov 23, 2024

This is looking really great and making me jealous that my terminal doesn't support it!

Happy to hear!
With the help of your feedback it works better than my first iteration.

I've cleaned up the code a little it the latest commit. TaskbarProgress::from_config() now has terminal detection and config logic. new() is #[cfg(test)] now.
And also added a test that the disabled taskbar doesn't output anything.

I think it looks like it's finished.

@Gordon01 Gordon01 force-pushed the taskbar_progress branch 2 times, most recently from 30233e5 to 371087c Compare November 24, 2024 18:53
Self::Indeterminate => (3, 0.0),
Self::Error(v) => (2, *v),
};
write!(f, "\x1b]9;4;{state};{progress:.0}\x1b\\")
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to 1, wiki and MS Learn <ST> is ESC \ (0x1B 0x5C) or BEL (0x7). Both are supported but ESC \ is preferred

Copy link
Author

@Gordon01 Gordon01 Dec 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Gordon01
Copy link
Author

@rustbot review

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. labels Nov 27, 2024
@Gordon01
Copy link
Author

Gordon01 commented Dec 7, 2024

Hello, @epage and everyone interested. Hope, you're well!

I have a good news! The progress in standartisation of the sequence is going well. Soon it's gonna be supported by systemd and GNOME vte. Here is the message from Christian Persch:

So my conclusion after reading through this issue, the windows terminal issue/pr, and conemu implementation, is that while this API has flaws and might be improved, it's reasonably widely implemented, and small enough (and the flaws small enough) so as to make it not worthwhile to try to invent yet another protocol for this.
Therefore I'm going to commit a patch to support OSC 9 ; 4 to vte (plus hook it up in the test app). I've changed it a bit since the last wip/progress branch; please check and test if this still meets the requirements. The parser at least should fully copy conemu behaviour.

And, cosequently support to Ptyxis was added.

From Lennart Poettering:

Since a while systemd has been showing nice terminal progress bars when doing certain slow operations (for example, when systemd-repart initializes a disk). With v257 we go one step further with this. Whenever we show the progress bar we'll now also issue certain terminal ANSI sequences that tell your terminal emulator that a slow operation is going on and what the progress currently is.

And the bug in kitty about the conflict with their OSC 9 implementation was fixed here. Also in foot.

So, to sum it up, Ed, it looks like you will get the support in your terminal earlier than you anticipated.

@weihanglo
Copy link
Member

Thank you for driving this!

I use Kitty so may gain nothing, but still a great feature!

src/cargo/util/progress.rs Outdated Show resolved Hide resolved
Comment on lines +150 to +171
// From https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC
// ESC ] 9 ; 4 ; st ; pr ST
// When st is 0: remove progress.
// When st is 1: set progress value to pr (number, 0-100).
// When st is 2: set error state in taskbar, pr is optional.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used when cargo executes binaries for cargo run or cargo <plugin>. Not familiar with Windows but I would assume for these execvp cases we are not expected to see them returning.

src/cargo/util/progress.rs Outdated Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we feel too risky (like excessive notification on Kitty), should we roll this out only on nightly for a while?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. It will take time for linux users to upgrade their terminals. And who knows what other bugs systemd will catch. I definitely want people to associate Rust ecosystem with quality.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure if this is needed. This feature is "auto" by default and the only places where it auto-enables are inside of terminals that are known to support this feature.

So the only way this would be a problem is if the user does CARGO_TERM_PROGRESS_TASKBAR = true cargo ... and that is by design so people can experiment with this feature and report back on support so we can expand it.

When it comes to a terminal having bad behavior in an old version and good behavior in a new, we can sometimes do version detection, e.g. https://github.com/zkat/supports-hyperlinks/blob/a2cc083668eb47c046f32ae0bc89d5bbdb8398ef/src/lib.rs#L23-L28

Comment on lines +124 to +129
let enabled = gctx.progress_config().taskbar.unwrap_or_else(|| {
// Windows Terminal session.
gctx.get_env("WT_SESSION").is_ok()
// Compatibility with ConEmu's ANSI support.
|| gctx.get_env("ConEmuANSI").ok() == Some("ON".into())
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we break the detection out into a function like we do for hyperlinks?

(and this would be allowed to use std::env::var_os, like hyperlinks)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally I see us breaking this out into a crate as some point

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll see what I can do.

Ideally I see us breaking this out into a crate as some point

After Lennart's push I think that it may be beneficial for the community to have a crate exactly for this one purpose: detecting supported terminal and serializing progress value and status into escape sequences.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-build-execution Area: anything dealing with executing the compiler A-configuration Area: cargo config files and env vars A-console-output Area: Terminal output, colors, progress bar, etc. A-documenting-cargo-itself Area: Cargo's documentation S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-cargo Team: Cargo
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use ANSI codes to report progress
4 participants