Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 28 additions & 14 deletions .github/workflows/UnitTests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,36 @@ on:
pull_request:
workflow_dispatch:

env:
TEST_PROJECT: PrettyConsole.UnitTests/PrettyConsole.UnitTests.csproj
TEST_ARTIFACTS: artifacts/
TEST_RUNNER: artifacts/PrettyConsole.UnitTests

jobs:
unit-tests-matrix:
unit-tests:
strategy:
fail-fast: false
matrix:
platform: [ubuntu-latest, windows-latest, macos-latest]
uses: dusrdev/actions/.github/workflows/reusable-dotnet-test-mtp.yaml@main
with:
platform: ${{ matrix.platform }}
dotnet-version: 10.0.x
test-project-path: PrettyConsole.Tests.Unit/PrettyConsole.Tests.Unit.csproj
include:
- os: ubuntu-latest
- os: macos-latest
- os: windows-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- name: Setup .NET 10
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x

- name: Publish native AOT test runner
run: |
dotnet publish ${{ env.TEST_PROJECT }} -c Release -o "${{ env.TEST_ARTIFACTS }}"

unit-tests-debug:
uses: dusrdev/actions/.github/workflows/reusable-dotnet-test-mtp.yaml@main
with:
platform: ubuntu-latest
dotnet-version: 10.0.x
test-project-path: PrettyConsole.Tests.Unit/PrettyConsole.Tests.Unit.csproj
use-debug: true
- name: Run published tests
shell: bash
run: |
exe="${{ env.TEST_RUNNER }}"
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then exe="$exe.exe"; fi
"$exe"
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Summary
- PrettyConsole/ — main library
- PrettyConsole.Tests/ — interactive/demo runner (manually selects visual feature demos)
- PrettyConsole.Tests.Unit/ — xUnit v3 unit tests using Microsoft Testing Platform
- v5.1.0 (current) renames `PrettyConsoleExtensions` to `ConsoleContext`, adds `Console.WriteWhiteSpaces(length, pipe)`, and makes `Out`/`Error`/`In` settable for test doubles. v5.0.0 removed the legacy `ColoredOutput`/`Color` types; color composition now flows through `ConsoleColor` helpers and tuples exposed by the library.
- v5.2.0 (current) rewrites `PrettyConsoleInterpolatedStringHandler` to buffer before writing for a major perf bump, recognizes a new `WhiteSpace` struct that expands to the requested padding length, and adds `IndeterminateProgressBar` overloads that take a `Func<PrettyConsoleInterpolatedStringHandler>` (use `PrettyConsoleInterpolatedStringHandler.Build` to bind the right `OutputPipe`). v5.1.0 renamed `PrettyConsoleExtensions` to `ConsoleContext`, added `Console.WriteWhiteSpaces(length, pipe)`, and made `Out`/`Error`/`In` settable for test doubles. v5.0.0 removed the legacy `ColoredOutput`/`Color` types; color composition now flows through `ConsoleColor` helpers and tuples exposed by the library.

Commands you’ll use often

Expand Down Expand Up @@ -48,7 +48,7 @@ High-level architecture and key concepts
- Output routing
- `OutputPipe` is a two-value enum (`Out`, `Error`). Most write APIs accept an optional pipe; internally `ConsoleContext.GetWriter` resolves the correct `TextWriter` so sequences remain redirect-friendly.
- Interpolated string handler
- `PrettyConsoleInterpolatedStringHandler` enables zero-allocation `$"..."` calls for `WriteInterpolated`, `WriteLineInterpolated`, `ReadLine`, `TryReadLine`, `Confirm`, and `RequestAnyInput`. Colors automatically reset after each invocation, and handlers respect the selected pipe and optional `IFormatProvider`. Recent changes ensure any `object` argument that implements `ISpanFormattable` is emitted through the span-based path before falling back to `IFormattable`/string allocations. `Console.WriteInterpolated`/`WriteLineInterpolated` now return the rendered character count (escape sequences emitted by the handler are excluded), which can be used for padding/layout math.
- `PrettyConsoleInterpolatedStringHandler` buffers the interpolated content before emitting it, yielding a large perf boost while staying allocation-free. It enables `$"..."` calls for `WriteInterpolated`, `WriteLineInterpolated`, `ReadLine`, `TryReadLine`, `Confirm`, and `RequestAnyInput`. Colors auto-reset, handlers respect the selected pipe/`IFormatProvider`, and `object` arguments that implement `ISpanFormattable` are emitted via the span path before falling back to `IFormattable`/string. `Console.WriteInterpolated`/`WriteLineInterpolated` return the rendered character count (handler-emitted escape sequences excluded). Passing the new `WhiteSpace` struct writes a span of padding directly from the handler without allocations.
- Coloring model
- `ConsoleColor` now exposes `DefaultForeground`, `DefaultBackground`, and `Default` tuple properties plus `/` operator overloads so you can inline foreground/background tuples (`$"{ConsoleColor.Red / ConsoleColor.White}Error"`). These tuples play nicely with the interpolated string handler and keep color resets allocation-free.
- Markup decorations
Expand All @@ -66,7 +66,7 @@ High-level architecture and key concepts
- Menus and tables
- `Selection` returns a single choice or empty string on invalid input; `MultiSelection` parses space-separated indices into string arrays; `TreeMenu` renders two-level hierarchies and validates input (throwing `ArgumentException` when selections are invalid); `Table` renders headers + columns with width calculations.
- Progress bars
- `IndeterminateProgressBar` binds to running `Task` instances, optionally starts tasks, supports cancellable `RunAsync` overloads, exposes `AnimationSequence`, `Patterns`, `ForegroundColor`, `DisplayElapsedTime`, and `UpdateRate`. Frames render on the error pipe and auto-clear.
- `IndeterminateProgressBar` binds to running `Task` instances, optionally starts tasks, supports cancellable `RunAsync` overloads, exposes `AnimationSequence`, `Patterns`, `ForegroundColor`, `DisplayElapsedTime`, and `UpdateRate`. Frames render on the error pipe and auto-clear. v5.2.0 adds overloads that accept a `Func<PrettyConsoleInterpolatedStringHandler>` so status text can be built per-frame with captured locals (call `PrettyConsoleInterpolatedStringHandler.Build(pipe)` inside the lambda to target the right output pipe).
- `ProgressBar` maintains a single-line bar on the error pipe. `Update` accepts `int`/`double` percentages plus optional status spans, and exposes `ProgressChar`, `ForegroundColor`, and `ProgressColor` for customization. The static `ProgressBar.WriteProgressBar` helper renders one-off segments without moving the cursor (so you can stack multiple bars within an `Overwrite` block).
- Packaging and targets
- `PrettyConsole.csproj` targets net10.0, enables trimming/AOT (`IsTrimmable`, `IsAotCompatible`), embeds SourceLink, and grants `InternalsVisibleTo` the unit-test project.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
BenchmarkDotNet v0.15.6, macOS 26.1 (25B78) [Darwin 25.1.0]
Apple M2 Pro, 1 CPU, 10 logical and 10 physical cores
.NET SDK 10.0.100
[Host] : .NET 10.0.0 (10.0.0, 10.0.25.52411), Arm64 RyuJIT armv8.0-a
Job-NEXDCO : .NET 10.0.0 (10.0.0, 10.0.25.52411), Arm64 RyuJIT armv8.0-a
[Host] : .NET 10.0.0 (10.0.0, 10.0.25.52411), Arm64 RyuJIT armv8.0-a
PGO1 : .NET 10.0.0 (10.0.0, 10.0.25.52411), Arm64 RyuJIT armv8.0-a

OutlierMode=RemoveAll IterationCount=30 IterationTime=100ms
LaunchCount=3 WarmupCount=5
Job=PGO1 OutlierMode=RemoveAll EnvironmentVariables=DOTNET_TieredPGO=1
IterationCount=30 IterationTime=100ms LaunchCount=3
WarmupCount=5

```
| Method | Mean | Ratio | Gen0 | Allocated | Alloc Ratio |
|--------------- |------------:|--------------:|-------:|----------:|--------------:|
| PrettyConsole | 95.02 ns | 49.73x faster | - | - | NA |
| SpectreConsole | 4,725.48 ns | baseline | 2.0902 | 17840 B | |
| SystemConsole | 68.67 ns | 68.81x faster | 0.0028 | 24 B | 743.333x less |
| PrettyConsole | 58.34 ns | 86.94x faster | - | - | NA |
| SpectreConsole | 5,069.69 ns | baseline | 2.1284 | 17840 B | |
| SystemConsole | 71.82 ns | 70.59x faster | 0.0022 | 24 B | 743.333x less |
13 changes: 6 additions & 7 deletions Benchmarks/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,12 @@ public Config() {
.WithEnvironmentVariable("DOTNET_TieredPGO", "1"); // default, explicit for clarity

AddJob(baseJob);
AddJob(baseJob
.WithId("PGO2")
.WithEnvironmentVariable("DOTNET_TieredPGO", "2"));
AddJob(baseJob
.WithId("NativeAOT")
.WithEnvironmentVariable("DOTNET_TieredPGO", "0") // not applicable, but keep deterministic
.WithToolchain(NativeAotToolchain.Net10_0));
// AddJob(baseJob
// .WithId("PGO2")
// .WithEnvironmentVariable("DOTNET_TieredPGO", "2"));
// AddJob(baseJob
// .WithId("NativeAOT")
// .WithToolchain(NativeAotToolchain.Net10_0));
AddColumnProvider(DefaultColumnProviders.Instance);
HideColumns(Column.Error, Column.StdDev, Column.Median, Column.RatioSD);
WithOrderer(new GroupByTypeOrderer());
Expand Down
40 changes: 0 additions & 40 deletions PrettyConsole.Tests.Unit/ConsoleColorTests.cs

This file was deleted.

4 changes: 0 additions & 4 deletions PrettyConsole.Tests.Unit/GlobalUsings.cs

This file was deleted.

16 changes: 0 additions & 16 deletions PrettyConsole.Tests.Unit/MarkupTests.cs

This file was deleted.

37 changes: 0 additions & 37 deletions PrettyConsole.Tests.Unit/PrettyConsole.Tests.Unit.csproj

This file was deleted.

16 changes: 0 additions & 16 deletions PrettyConsole.Tests.Unit/PrettyConsoleExtensionsTests.cs

This file was deleted.

This file was deleted.

Loading