Pester icon indicating copy to clipboard operation
Pester copied to clipboard

Add ANSI support for output

Open fflaten opened this issue 3 years ago • 8 comments
trafficstars

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 Request to mark it as a draft. PR can be marked Ready for review when it's ready.
  • [x] Tests are added/update (if required)
  • [x] Documentation is updated/added (if required)
    • Website-update tracked in pester/docs#214

fflaten avatar Jun 27 '22 18:06 fflaten

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? 😄

fflaten avatar Jun 29 '22 16:06 fflaten

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.

briantist avatar Jun 30 '22 01:06 briantist

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?

nohwnd avatar Jun 30 '22 08:06 nohwnd

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.

fflaten avatar Jun 30 '22 11:06 fflaten

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-Host for 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.

fflaten avatar Jun 30 '22 17:06 fflaten

I think sticking with Write-Host is the right thing to do here, even though it is a bit slower.

nohwnd avatar Jul 01 '22 08:07 nohwnd

Ready for review. Good thing we squash commits. 😄 Let me know if I should rebase

fflaten avatar Jul 01 '22 22:07 fflaten

Really nice, some small suggestions.

nohwnd avatar Aug 03 '22 05:08 nohwnd

Merged, thanks for that.

nohwnd avatar Aug 11 '22 10:08 nohwnd

Thanks! Finally done with this conflict-magnet 😄 🎉

fflaten avatar Aug 11 '22 10:08 fflaten