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

FCP: #14615 (comment)

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 +167
// 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
@epage
Copy link
Contributor

epage commented Dec 16, 2024

@rfcbot fcp merge

In terms of stability, this adds a new config field

[term]
progress.taskbar = true # whether cargo reports progress to terminal emulator

Like with hyperlinks and unicode, it is auto-detect by default and can be explicitly turned on/off.

For rendering, this ANSI escape code is supported by at least

  • ConEmu
  • Windows Terminal
  • GNOME vte / Ptyxis (not added to cargo's auto-detection yet)

For emitting, this ANSI escape code is supported by at least

  • systemd

In the current implementation, if the user hits ctrl-c, then nothing will remove the taskbar status. We could add a ctrl-c handler but I'm always hesitant about those and would prefer to see if we can get away without it. It also sounds like other existing programs don't add a ctrl-c handler for this.

@rfcbot
Copy link
Collaborator

rfcbot commented Dec 16, 2024

Team member @epage has proposed to merge this. The next step is review by the rest of the tagged team members:

Concerns:

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rfcbot rfcbot added proposed-final-comment-period An FCP proposal has started, but not yet signed off. disposition-merge FCP with intent to merge labels Dec 16, 2024
#### `term.progress.taskbar`
* Type: bool
* Default: auto-detect
* Environment: `CARGO_TERM_PROGRESS_TASKBAR`
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a mild note, this environment variable doesn't work by itself (because it requires the other progress settings).

Copy link
Contributor

Choose a reason for hiding this comment

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

BTW, you might be able to fix this by adding #[serde(default)] to the ProgressConfig::when field.

Copy link
Author

@Gordon01 Gordon01 Dec 17, 2024

Choose a reason for hiding this comment

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

Great point! It's definitely more ergonomic to use now.

image
image

Copy link
Author

@Gordon01 Gordon01 Dec 17, 2024

Choose a reason for hiding this comment

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

This breaks test bad_progress_config_missing_when

Unclear why does ProgressWhen has a Default implementation then...

As for me it feels that any progress setting should imply when = 'auto'. Not sure should 4 years old behavior be changed here.

#8165

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't recall any particular decisions made regarding bad_progress_config_missing_when. I personally would not object to changing that to allow it to pass. I can't think of a reason it would be required to specify when with width.

unicode = true # whether cargo can render output using non-ASCII unicode characters
progress.when = 'auto' # whether cargo shows progress bar
progress.width = 80 # width of progress bar
progress.taskbar = true # whether cargo reports progress to terminal emulator
Copy link
Member

Choose a reason for hiding this comment

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

Different terminal emulators handle this differently; for instance, some of the Linux terminal emulators show this in the terminal's tab bar, instead. Rather than having a name that's specific to the rendering of a subset of terminals, could we use a name that's a little more generic?

Perhaps progress.ansi or progress.osc? Or, if we want something less technical, then perhaps progress.escapes, indicating that it sends escape codes?

Copy link
Author

@Gordon01 Gordon01 Dec 17, 2024

Choose a reason for hiding this comment

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

Here are my points:

  • progress.taskbar - I like this one for easy interchangeability with taskbar_progress-named fields and functions
  • progress.osc or progress.osc9_4 - people name PRs and issues mostly with something like "OSC 9;4" so it's somewhat familiar
  • progress.notification - just high-level

Copy link
Author

@Gordon01 Gordon01 Dec 17, 2024

Choose a reason for hiding this comment

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

Copy link
Contributor

@epage epage Dec 17, 2024

Choose a reason for hiding this comment

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

For me, my care abouts are

  • Easy discover for people wanting to change this behavior
  • Clear meaning when looking at a config or config docs
  • Consistency with wider community

I feel like ansi, osc, escapes, and osc9_4 do neither unless you are someone already in the nitty gritty implementation details. Also, our other OSC configs do not speak this way (color, unicode, hyperlinks, though color can also support wincon APIs).

Copy link
Member

Choose a reason for hiding this comment

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

progress.taskbar - I like this one for easy interchangeability with taskbar_progress-named fields and functions

That's circular. :)

Copy link
Member

Choose a reason for hiding this comment

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

I don't think there is a clear name to explain itself. notification sounds too far away. osc9_4 is too tied to implementation details. Maybe we'll have other reporting mechanism for some specific terminal emulator in the future (I hope not though).

Since what the feature does is reporting the progress. So, perhaps a verb progress.report is a bit clearer?

(Hey report is also a noun 😅)

Copy link
Contributor

Choose a reason for hiding this comment

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

notification can also sound like the kitty feature that slightly overlaps om the codes.

Another name I thought of was progress.system to convey that its reporting through the system that calls into cargo.

Eventually I want to add support for multi-line progress which might need its own config and then if we ever get a watch, I would like it to look like bacon. ui and gui might get confusing in those respects (well, more tui).

Copy link
Member

Choose a reason for hiding this comment

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

Just looked at this again in 2025, notification sounds fine as well :)

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)

I've changed the feature name to progress report. This name keeps the focus on what the feature does (reporting progress) rather than how it’s rendered.

Copy link
Contributor

Choose a reason for hiding this comment

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

Within a terminal emulator, I think that name can make sense (though that is one specific terminals name and not a common name)

Within the context of the term table

[term]
quiet = false          # whether cargo output is quiet
verbose = false        # whether cargo provides verbose output
color = 'auto'         # whether cargo colorizes output
hyperlinks = true      # whether cargo inserts links into output
unicode = true         # whether cargo can render output using non-ASCII unicode characters
progress.when = 'auto' # whether cargo shows progress bar
progress.width = 80    # width of progress bar
progress.report = true # whether cargo reports progress to terminal emulator

especially if you ignore the comments, report sounds like when

@Gordon01 Gordon01 force-pushed the taskbar_progress branch 2 times, most recently from 7f94679 to cbd0508 Compare December 17, 2024 20:45
@rfcbot rfcbot added final-comment-period FCP — a period for last comments before action is taken and removed proposed-final-comment-period An FCP proposal has started, but not yet signed off. labels Dec 17, 2024
@rfcbot
Copy link
Collaborator

rfcbot commented Dec 17, 2024

🔔 This is now entering its final comment period, as per the review above. 🔔

progress_report,
stderr_tty,
..
} => *progress_report && *stderr_tty,
Copy link
Contributor

Choose a reason for hiding this comment

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

Generally this check is done in the supports functions, should we make that consistent?

Copy link
Author

@Gordon01 Gordon01 Feb 10, 2025

Choose a reason for hiding this comment

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

Looking on the other code it seems that it's a separate thing:

  • supports_progress_report() detects the supported terminal from environment variables
  • progress_report_available() (I've renamed is from the supports_osc9_4() for clarity) signals that terminal supports the feature and it's a tty

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I'm following

  • supports_unicode checks !stream.is_terminal() || supports_unicode::supports_unicode()
  • AutoStream::new(std::io::stdout(), stdout_choice) will check is_terminal as well as what the terminal supports

hyperlinks is a bit odd but that is later combined with the AutoStream check

* Default: auto-detect
* Environment: `CARGO_TERM_PROGRESS_TASKBAR`

Report progess to the teminal emulator for display in places like the task bar.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Report progess to the teminal emulator for display in places like the task bar.
Report progress to the teminal emulator for display in places like the task bar.

unicode = true # whether cargo can render output using non-ASCII unicode characters
progress.when = 'auto' # whether cargo shows progress bar
progress.width = 80 # width of progress bar
progress.taskbar = true # whether cargo reports progress to terminal emulator
Copy link
Member

Choose a reason for hiding this comment

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

I don't think there is a clear name to explain itself. notification sounds too far away. osc9_4 is too tied to implementation details. Maybe we'll have other reporting mechanism for some specific terminal emulator in the future (I hope not though).

Since what the feature does is reporting the progress. So, perhaps a verb progress.report is a bit clearer?

(Hey report is also a noun 😅)

@joshtriplett
Copy link
Member

joshtriplett commented Dec 18, 2024

@rfcbot reviewed
@rfcbot concern config-name

Temporary concern until #14615 (comment) gets resolved, because folks may be about to go on holiday soon and I don't want this to get lost. I am not at this time attempting to actually block the FCP if this isn't changed, and I'm happy to defer to consensus; I just want to make sure that this doesn't accidentally FCP without resolving the discussion and reaching some consensus.

@rfcbot rfcbot added proposed-final-comment-period An FCP proposal has started, but not yet signed off. and removed final-comment-period FCP — a period for last comments before action is taken labels Dec 18, 2024
@Gordon01
Copy link
Author

Gordon01 commented Jan 1, 2025

Happy New Year and Merry Christmas!

I had a lot of work in the last weeks of December and now I'm on New Year vacation. I'll be back in the second half of January, I'll fix the tests, decide on naming.

Wishing everyone a happy new 2025!

@wez
Copy link

wez commented Feb 10, 2025

Just wanted to chime in here to say that WezTerm just now added support for these escapes in main.
It should be fine to emit the escapes in earlier versions, but in case you prefer to probe to be sure, you can look for the following environment variables:

TERM_PROGRAM=WezTerm
TERM_PROGRAM_VERSION=20250209-182623-44866cc1

$TERM_PROGRAM_VERSION will be 20250209-182623-44866cc1 or greater in wezterms that support this sequence.

wezterm/wezterm#6581 is the wezterm issue tracking this feature.

@Gordon01 Gordon01 force-pushed the taskbar_progress branch 3 times, most recently from da388a4 to 80e9682 Compare February 10, 2025 21:28
@Gordon01
Copy link
Author

Gordon01 commented Feb 10, 2025

Hi everyone!

I've changed the feature name to progress report. This name keeps the focus on what the feature does (reporting progress) rather than how it’s rendered.

I've also added WizTerm detection.

@wez also called is like this.

I can't make test to work. It passes locally on Windows and Linux but here on pipeline it behaves differently and I can't figure out why.

Comment on lines +589 to +594
// WezTerm: check if TERM_PROGRAM is "WezTerm" and the version is recent enough
// https://github.com/rust-lang/cargo/pull/14615#issuecomment-2646738819
|| (std::env::var("TERM_PROGRAM").ok() == Some("WezTerm".into())
&& std::env::var("TERM_PROGRAM_VERSION")
.ok()
.map_or(false, |v| v.as_str() >= "20250209-182623-44866cc1"))
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the main reason for version checks is to deal with buggy terminal implementations. If older wezterms gracefully handle these codes, should we skip the version check?

Copy link

Choose a reason for hiding this comment

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

FWIW, older versions of wezterm will swallow an OSC they doesn't understand, so you could remove the version number check and just check for wezterm without it. That feels like less magic to keep track of over here.

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 disposition-merge FCP with intent to merge proposed-final-comment-period An FCP proposal has started, but not yet signed off. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-cargo Team: Cargo
Projects
Status: FCP blocked
Development

Successfully merging this pull request may close these issues.

Use ANSI codes to report progress
9 participants