Pester
Pester copied to clipboard
Add ANSI support for output
PR Summary
Introduces a configuration option Output.RenderMode and a wrapper-function to replace Write-Host so we can output strings using ANSI-escaped sequences to get colors in CI or plaintext etc. The option supports the following levels:
- Auto (default):
- Sets to Plaintext if $env:NO_COLOR
- Sets to Ansi if $host.UI.SupportsVirtualTerminal
- Else, Legacy (same as today)
- Ansi
- To force it. PSv3/v4 doesn't support auto-detect but CI might. Ex. our Azure Pipeline CI in this repo
- Legacy (same as before this PR)
- For those who want color in GUI, but not in CI or redirected output to logs etc.
- Plaintext (why not.. https://no-color.org/)
The new function Write-PesterHostMessage supports all parameters of Write-Host to make it an easy replacement.
Fix #1953
TODO:
- [x] Fix auto-detection
- [x] V3/V4 compatible
- [x] PS6_2 run in CI should not use Ansi
- [x] Add tests for
Write-PesterHostMessage - [x] Add tests for config option and auto-detection
- [x] Test Azure DevOps and GitHub Actions
- [x] Fix multiline-strings
- [x] Test PSJobs (remoting)
- [x] Support custom PSHosts without UI
- Works for PS3 and PS4 now. Output only available in PS5+ where Information-stream exists
- [x] Support NO_COLOR
PR Checklist
- [x] PR has meaningful title
- [x] Summary describes changes
- [x] PR is ready to be merged
- If not, use the arrow next to
Create Pull Requestto mark it as a draft. PR can be markedReady for reviewwhen it's ready.
- If not, use the arrow next to
- [x] Tests are added/update (if required)
- [x] Documentation is updated/added (if required)
- Website-update tracked in pester/docs#214
Alternative configuration using StringOption Output.RenderMode:
- Auto (default):
- Set to Plaintext if
$env:NO_COLOR - Set to Ansi if
$host.UI.SupportsVirtualTerminal - Else, default (ConsoleColor like today)
- Set to Plaintext if
- Ansi (force it, because PSv3/v4 doesn't support auto-detect but CI might (like our Azure Pipeline checks in this PR)
- ConsoleColor (for those who want color in GUI, but not in CI or redirected output to logs etc)
- Plaintext (idk.. https://no-color.org/)
@nohwnd @beatcracker @briantist Thoughts? Overcomplicating it? 😄
Alternative configuration using
StringOption Output.RenderMode:
Auto (default):
- Set to Plaintext if
$env:NO_COLOR- Set to Ansi if
$host.UI.SupportsVirtualTerminal- Else, default (ConsoleColor like today)
Ansi (force it, because PSv3/v4 doesn't support auto-detect but CI might (like our Azure Pipeline checks in this PR)
ConsoleColor (for those who want color in GUI, but not in CI or redirected output to logs etc)
Plaintext (idk.. https://no-color.org/)
@nohwnd @beatcracker @briantist Thoughts? Overcomplicating it? 😄
I like the options as you have them laid out here. It doesn't seem overcomplicated to me, it seems thorough and well thought out. I didn't know about no-color and I think it's a nice idea and should be supported.
The options seem more straightforward to me, if we add a "conflicting" FQFQ (or whatever) output option in the future, we don't have to solve what happens where there are both UseAnsi and UseFQFQ.
The breaking change:
Is writing via console directly necessary to implement this? Or is that just for perf?
Is writing via console directly necessary to implement this? Or is that just for perf?
Perf. Regain the delay added by wrapper (and more).
I'm considering replacing option ConsoleColor with Legacy above and passthrough to write-host as before though somewhat slower due to wrapper overhead.
Then custom PSHosts could still use the information-output, even though it's still broken regarding -nonewline. Need to implement ugly array of dict-input to solve that and I don't really thinks it's worth it.
Printing 1000 lines with ForegroundColor (average of 5 runs)
| Method | PowerShell 5.1 | Pwsh 7.2.5 | VSCode Integrated 5.1 |
|---|---|---|---|
| Write-Host (reference) | 450ms | 217ms | 660ms |
| New with ANSI and $host.UI | 260ms | 132ms | 418ms |
| New without ANSI and $host.UI | 323ms | 210ms | 500ms |
| New with ANSI and Write-Host | 620ms | 350ms | 980ms |
| New without ANSI and Write-Host | 580ms | 290ms | 830ms |
We got 5x lines in pipeline, so ~2sec test-time per runner maybe. Maybe not worth it?
- Passthru to
Write-Hostfor Legacy (without ANSI) for backwards-compatibility, but $host.UI for ANSI? - Passthru for all to keep it simple (but slower than today)?
I'm fine either way, just thought we already had gotten some feedback on output being slow 🙂
The difference was bigger last year when I tried to support array-input to fix the broken information-stream at the same time.
I think sticking with Write-Host is the right thing to do here, even though it is a bit slower.
Ready for review. Good thing we squash commits. 😄 Let me know if I should rebase
Really nice, some small suggestions.
Merged, thanks for that.
Thanks! Finally done with this conflict-magnet 😄 🎉