Skip to content

fix(windows): keep VT enabled during progress#1465

Open
shaanmajid wants to merge 2 commits intoj178:masterfrom
shaanmajid:fix/windows-ansi-1237
Open

fix(windows): keep VT enabled during progress#1465
shaanmajid wants to merge 2 commits intoj178:masterfrom
shaanmajid:fix/windows-ansi-1237

Conversation

@shaanmajid
Copy link
Collaborator

@shaanmajid shaanmajid commented Jan 22, 2026

Some Windows hook installers (uv, pip, npm, cargo) disable ENABLE_VIRTUAL_TERMINAL_PROCESSING on exit, which causes indicatif's progress output to render as raw ANSI escape sequences during prek install.

This PR attempts two fixes:

  1. Re-enable VT mode after subprocess output() and status() calls (148fe45)
  2. Run a background thread that periodically re-enables VT while progress bars are active (d31b4bd)

Notably, the first alone did not fix the issue (see #1465 (comment)), but the second did.

Video of issue behavior: https://github.com/user-attachments/assets/10b75c59-f528-4a5e-95cd-c1987ee5de4a
Video of behavior after fix: https://github.com/user-attachments/assets/531000c8-32c7-4d98-a6a9-b1ab05e25582
(both courtesy of @chrisoro)

Fixes #1237

@codecov
Copy link

codecov bot commented Jan 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.67%. Comparing base (f8df4e7) to head (47a215d).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1465      +/-   ##
==========================================
+ Coverage   91.65%   91.67%   +0.02%     
==========================================
  Files          90       90              
  Lines       17813    17845      +32     
==========================================
+ Hits        16326    16359      +33     
+ Misses       1487     1486       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 22, 2026

📦 Cargo Bloat Comparison

Binary size change: +0.00% (23.2 MiB → 23.2 MiB)

Expand for cargo-bloat output

Head Branch Results

 File  .text    Size             Crate Name
 0.3%   0.8% 74.5KiB             prek? <prek::cli::Command as clap_builder::derive::Subcommand>::augment_subcommands
 0.3%   0.7% 71.3KiB              prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.3%   0.7% 65.7KiB              prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.2%   0.5% 51.2KiB annotate_snippets annotate_snippets::renderer::render::render
 0.2%   0.5% 50.8KiB              prek prek::languages::<impl prek::config::Language>::install::{{closure}}
 0.2%   0.4% 43.4KiB              prek prek::identify::by_extension::{{closure}}
 0.2%   0.4% 43.1KiB              prek prek::run::{{closure}}
 0.2%   0.4% 41.6KiB              prek prek::cli::run::run::run::{{closure}}
 0.1%   0.3% 31.1KiB             prek? <prek::cli::RunArgs as clap_builder::derive::Args>::augment_args
 0.1%   0.3% 28.4KiB      serde_saphyr saphyr_parser_bw::scanner::Scanner<T>::fetch_more_tokens
 0.1%   0.3% 24.9KiB             prek? <prek::config::_::<impl serde_core::de::Deserialize for prek::config::Config>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map
 0.1%   0.2% 22.6KiB      serde_saphyr saphyr_parser_bw::scanner::Scanner<T>::fetch_more_tokens
 0.1%   0.2% 22.1KiB              prek prek::hooks::meta_hooks::MetaHooks::run::{{closure}}
 0.1%   0.2% 21.2KiB      clap_builder clap_builder::parser::parser::Parser::get_matches_with
 0.1%   0.2% 20.0KiB   cargo_metadata? <cargo_metadata::_::<impl serde_core::de::Deserialize for cargo_metadata::Package>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map
 0.1%   0.2% 19.7KiB              prek prek::hooks::meta_hooks::MetaHooks::run::{{closure}}
 0.1%   0.2% 19.5KiB              prek prek::archive::unzip::{{closure}}
 0.1%   0.2% 19.5KiB              prek prek::cli::run::filter::collect_files_from_args::{{closure}}
 0.1%   0.2% 19.3KiB               std core::ptr::drop_in_place<prek::languages::<impl prek::config::Language>::install::{{closure}}>
 0.1%   0.2% 19.3KiB              prek <prek::languages::ruby::ruby::Ruby as prek::languages::LanguageImpl>::install::{{closure}}
37.8%  91.2%  8.8MiB                   And 20451 smaller methods. Use -n N to show more.
41.5% 100.0%  9.6MiB                   .text section size, the file size is 23.2MiB

Base Branch Results

 File  .text    Size             Crate Name
 0.3%   0.8% 74.5KiB             prek? <prek::cli::Command as clap_builder::derive::Subcommand>::augment_subcommands
 0.3%   0.7% 71.3KiB              prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.3%   0.7% 65.7KiB              prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.2%   0.5% 51.2KiB annotate_snippets annotate_snippets::renderer::render::render
 0.2%   0.5% 50.8KiB              prek prek::languages::<impl prek::config::Language>::install::{{closure}}
 0.2%   0.4% 43.4KiB              prek prek::identify::by_extension::{{closure}}
 0.2%   0.4% 43.1KiB              prek prek::run::{{closure}}
 0.2%   0.4% 41.6KiB              prek prek::cli::run::run::run::{{closure}}
 0.1%   0.3% 31.1KiB             prek? <prek::cli::RunArgs as clap_builder::derive::Args>::augment_args
 0.1%   0.3% 28.4KiB      serde_saphyr saphyr_parser_bw::scanner::Scanner<T>::fetch_more_tokens
 0.1%   0.3% 24.9KiB             prek? <prek::config::_::<impl serde_core::de::Deserialize for prek::config::Config>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map
 0.1%   0.2% 22.6KiB      serde_saphyr saphyr_parser_bw::scanner::Scanner<T>::fetch_more_tokens
 0.1%   0.2% 22.1KiB              prek prek::hooks::meta_hooks::MetaHooks::run::{{closure}}
 0.1%   0.2% 21.2KiB      clap_builder clap_builder::parser::parser::Parser::get_matches_with
 0.1%   0.2% 20.0KiB   cargo_metadata? <cargo_metadata::_::<impl serde_core::de::Deserialize for cargo_metadata::Package>::deserialize::__Visitor as serde_core::de::Visitor>::visit_map
 0.1%   0.2% 19.7KiB              prek prek::hooks::meta_hooks::MetaHooks::run::{{closure}}
 0.1%   0.2% 19.5KiB              prek prek::archive::unzip::{{closure}}
 0.1%   0.2% 19.5KiB              prek prek::cli::run::filter::collect_files_from_args::{{closure}}
 0.1%   0.2% 19.3KiB               std core::ptr::drop_in_place<prek::languages::<impl prek::config::Language>::install::{{closure}}>
 0.1%   0.2% 19.3KiB              prek <prek::languages::ruby::ruby::Ruby as prek::languages::LanguageImpl>::install::{{closure}}
37.8%  91.2%  8.8MiB                   And 20451 smaller methods. Use -n N to show more.
41.5% 100.0%  9.6MiB                   .text section size, the file size is 23.2MiB

@shaanmajid shaanmajid force-pushed the fix/windows-ansi-1237 branch 3 times, most recently from f7e1e45 to 762d114 Compare January 22, 2026 20:34
@shaanmajid
Copy link
Collaborator Author

Keeping in draft until @chrisoro or someone with a Windows machine can confirm this actually fixes the issue lolol

@chrisoro
Copy link

Any chance to build arm64 version of it? I won't have access to my amd64 win machine until end of next week. I do have windows on arm as a vm on my mac

@shaanmajid
Copy link
Collaborator Author

shaanmajid commented Jan 24, 2026

Just did a dummy change to build-binaries.yml to trigger the build job and build ARM Windows binaries. Those artifacts can be found at https://github.com/j178/prek/actions/runs/21322541711#artifacts.

@chrisoro The link for the ARM Windows standalone binary specifically is https://github.com/j178/prek/actions/runs/21322541711/artifacts/5245733919. Looks like it's a zip file in another zip file lol, but the inner zip has a prek.exe which is what you should be able to test with. The rest of the instructions I left in my issue comment should still apply.

Let me know how it goes!

@chrisoro
Copy link

chrisoro commented Jan 28, 2026

Tried the arm executable and it shows the same errors in both cmd and powershell. Maybe it is the region/language setting in Windows? Mine is set to Germany / German

@shaanmajid shaanmajid force-pushed the fix/windows-ansi-1237 branch from bf6d4cc to dd596f1 Compare January 28, 2026 20:13
@shaanmajid
Copy link
Collaborator Author

Sad, can you try the latest build? Tried some more changes.

@chrisoro
Copy link

Nice, this seems to have done the trick. I can't overserve the broken output anymore. See: https://streamable.com/qaa5qs

@shaanmajid
Copy link
Collaborator Author

Awesome! Just to confirm, you were able to consistently reproduce in both cmd and powershell in prek 0.3.0, but the bug is consistently gone in both shells with the fix?

@shaanmajid shaanmajid marked this pull request as ready for review January 30, 2026 17:57
@chrisoro
Copy link

Correct. I only did it in my Win11 ARM VM and not x86 but that shouldn't matter, right?

@shaanmajid shaanmajid force-pushed the fix/windows-ansi-1237 branch 3 times, most recently from 51e4656 to d31b4bd Compare January 31, 2026 17:26
Some Windows hook installers (uv, pip, npm, cargo) disable
ENABLE_VIRTUAL_TERMINAL_PROCESSING on exit, which causes indicatif's
progress output to render as raw ANSI escape sequences.

Re-enable VT mode after subprocess output() and status() calls to
restore console state before prek resumes its own output.
Subprocesses like uv/pip/npm can disable ENABLE_VIRTUAL_TERMINAL_PROCESSING
while indicatif's spinner is actively rendering, causing raw ANSI escape
sequences to appear mid-install.

Add a Windows-only background thread that re-enables VT mode every 200ms
(matching the spinner tick rate) while progress bars are visible. The thread
is scoped to ProgressReporter lifetime and only spawns when color is enabled.
@shaanmajid shaanmajid force-pushed the fix/windows-ansi-1237 branch from d31b4bd to 47a215d Compare February 3, 2026 05:26
@shaanmajid shaanmajid requested a review from j178 as a code owner February 3, 2026 05:26
@shaanmajid
Copy link
Collaborator Author

@j178 no pressure, but not sure if you saw this, it was in draft for a while haha. Any concerns?

@j178
Copy link
Owner

j178 commented Feb 6, 2026

Yeah, I've been keeping an eye on this. Thanks for the hard work! But the solution feels a bit unusual to me. I'm not sure if any other projects run into the same issue or handle it this way. Having a background thread constantly re‑enabling VT just seems a little unfortunate to me :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Coloring on Powershell broken

3 participants