PrettyConsole 4.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package PrettyConsole --version 4.0.0
                    
NuGet\Install-Package PrettyConsole -Version 4.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PrettyConsole" Version="4.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PrettyConsole" Version="4.0.0" />
                    
Directory.Packages.props
<PackageReference Include="PrettyConsole" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PrettyConsole --version 4.0.0
                    
#r "nuget: PrettyConsole, 4.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PrettyConsole@4.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PrettyConsole&version=4.0.0
                    
Install as a Cake Addin
#tool nuget:?package=PrettyConsole&version=4.0.0
                    
Install as a Cake Tool

PrettyConsole

An abstraction over System.Console that adds new input and output methods, colors and advanced outputs like progress bars and menus. And everything is ansi supported so it works on legacy systems and terminals.

Features

  • 🚀 High performance, low allocations and span-first APIs
  • 🪶 Very lightweight (no external dependencies)
  • ✨ Zero-allocation interpolated string handler for inline colors and formatting
  • 💾 Supports legacy ANSI terminals (like Windows 7)
  • 🔥 Complete NativeAOT compatibility
  • Supports all major platforms (Windows, Linux, Mac)
  • ⛓ Uses original output pipes, so that your CLI's can be piped properly

Installation NUGET DOWNLOADS

dotnet add package PrettyConsole

Usage

Everything starts off with the using statements, I recommend using the Console statically

using static PrettyConsole.Console; // Access to all Console methods
using PrettyConsole; // Access to the Color struct and OutputPipe enum

Interpolated Strings

PrettyConsoleInterpolatedStringHandler lets you stream interpolated text directly to the selected pipe without allocating intermediate strings, while still using the familiar $"..." syntax.

Write($"Hello {Color.Green}world{Color.Default}!");
Write(OutputPipe.Error, $"{Color.Yellow}Warning:{Color.Default} {message}");

if (!TryReadLine(out int choice, $"Pick option {Color.Cyan}1-5{Color.Default}: ")) {
    WriteLine($"{Color.Red}Not a number.{Color.Default}");
}

Colors reset automatically at the end of each call. Use Color.Default (or explicit background tuples) when you need to restore colors mid-string.

ColoredOutput

PrettyConsole uses an equation inspired syntax to colorize text. The syntax is as follows:

WriteLine("Test" * Color.Red / Color.Blue);

i.e TEXT * FOREGROUND / BACKGROUND

Any the 2 colors can be played with just like a real equation, omit the foreground and the default will be used, same goes for the background.

Basic Outputs

The most basic method for outputting is Write, which has multiple overloads. All equivalents exist for WriteLine:

// Usage + overload highlights:
Write($"Interpolated {Color.Blue}string{Color.Default}");
Write(OutputPipe.Error, $"...");
Write(ColoredOutput output, OutputPipe pipe = OutputPipe.Out);
Write(ReadOnlySpan<ColoredOutput> outputs, OutputPipe pipe = OutputPipe.Out);
Write(ReadOnlySpan<char> span, OutputPipe pipe, ConsoleColor foreground);
Write(ReadOnlySpan<char> span, OutputPipe pipe, ConsoleColor foreground, ConsoleColor background);
Write<T>(T value, OutputPipe pipe = OutputPipe.Out) where T : ISpanFormattable;
Write<T>(T value, OutputPipe pipe, ConsoleColor foreground, ConsoleColor background,
    ReadOnlySpan<char> format, IFormatProvider? provider);

Overload for WriteLine are available with the same parameters

Basic Inputs

These are the methods for reading user input:

// Examples:
string? ReadLine(); // ReadLine<string>
string? ReadLine(ReadOnlySpan<ColoredOutput>);
string? ReadLine($"Prompt {Color.Green}text{Color.Default}: ");
T? ReadLine<T>(ReadOnlySpan<ColoredOutput>); // T : IParsable<T>
T? ReadLine<T>($"Prompt {Color.Cyan}text{Color.Default}: ");
T ReadLine<T>(ReadOnlySpan<ColoredOutput>, T @default); // @default will be returned if parsing fails
T ReadLine<T>(T @default, $"Prompt {Color.Cyan}text{Color.Default}: ");
bool TryReadLine<T>(ReadOnlySpan<ColoredOutput>, out T?); // T : IParsable<T>
bool TryReadLine<T>(out T?, $"Prompt {Color.Cyan}text{Color.Default}: ");
bool TryReadLine<T>(ReadOnlySpan<ColoredOutput>, T @default, out T); // @default will be returned if parsing fails
bool TryReadLine<T>(out T, T @default, $"Prompt {Color.Cyan}text{Color.Default}: ");
bool TryReadLine<TEnum>(ReadOnlySpan<ColoredOutput>, bool ignoreCase, out TEnum?); // TEnum : struct, Enum
bool TryReadLine<TEnum>(out TEnum, bool ignoreCase, $"Prompt {Color.Cyan}text{Color.Default}: "); // TEnum : struct, Enum
bool TryReadLine<TEnum>(ReadOnlySpan<ColoredOutput>, bool ignoreCase, TEnum @default, out TEnum); // @default will be returned if parsing fails
bool TryReadLine<TEnum>(out TEnum, bool ignoreCase, TEnum @default, $"Prompt {Color.Cyan}text{Color.Default}: ");

I always recommend using TryReadLine instead of ReadLine as you need to maintain less null checks and the result, especially with @default is much more concise.

Advanced Inputs

These are some special methods for inputs:

// These will wait for the user to press any key
void RequestAnyInput(string message = "Press any key to continue...");
void RequestAnyInput(ReadOnlySpan<ColoredOutput> output);
RequestAnyInput($"Press {Color.Yellow}any key{Color.Default} to continue...");
// These request confirmation by special input from user
bool Confirm(ReadOnlySpan<ColoredOutput> message); // uses the default values ["y", "yes"]
// the default values can also be used by you at Console.DefaultConfirmValues
bool Confirm(ReadOnlySpan<ColoredOutput> message, ReadOnlySpan<string> trueValues, bool emptyIsTrue = true);
bool Confirm($"Deploy to production? ({Color.Green}y{Color.Default}/{Color.Red}n{Color.Default}) ");
bool Confirm(ReadOnlySpan<string> trueValues, bool emptyIsTrue, $"Overwrite existing files? ");

Rendering Controls

To aid in rendering and building your own complex outputs, there are many methods that simplify some processes.

ClearNextLines(int lines, OutputPipe pipe = OutputPipe.Error); // clears the next lines
NewLine(OutputPipe pipe = OutputPipe.Out); // outputs a new line
SetColors(ConsoleColor foreground, ConsoleColor background); // sets the colors of the console output
ResetColors(); // resets the colors of the console output
int GetCurrentLine(); // returns the current line number
GoToLine(int line); // moves the cursor to the specified line

Combining ClearNextLines with GoToLine will enable you to efficiently use the same space in the console for continuous output, such as progress outputting, for some cases there are also built-in methods for this, more on that later.

Advanced Outputs

// This method will essentially write a line, clear it, go back to same position
// This allows a form of text-only progress bar
void OverwriteCurrentLine(ReadOnlySpan<ColoredOutput> output, OutputPipe pipe = OutputPipe.Error);
void Overwrite(Action action, int lines = 1, OutputPipe pipe = OutputPipe.Error);
void Overwrite<TState>(TState state, Action<TState> action, int lines = 1, OutputPipe pipe = OutputPipe.Error)
    where TState : allows ref struct;
// This methods will write a character at a time, with a delay between each character
async Task TypeWrite(ColoredOutput output, int delay = TypeWriteDefaultDelay);
async Task TypeWriteLine(ColoredOutput output, int delay = TypeWriteDefaultDelay);
// This prints an index view of the list, allows the user to select by index
// returns the actual choice that corresponds to the index
string Selection<TList>(ReadOnlySpan<ColoredOutput> title, TList choices) where TList : IList<string> {}
// Same as selection but allows the user to select multiple indexes
// Separated by spaces, and returns an array of the actual choices that correspond to the indexes
string[] MultiSelection<TList>(ReadOnlySpan<ColoredOutput> title, TList choices) where TList : IList<string> {}
// This prints a tree menu of 2 levels, allows the user to select the index
// Of the first and second level and returns the corresponding choices
(string option, string subOption) TreeMenu<TList>(ReadOnlySpan<ColoredOutput> title,
        Dictionary<string, TList> menu) where TList : IList<string> {}
// This prints a table with headers, and columns for each list
void Table<TList>(TList headers, ReadOnlySpan<TList> columns) where TList : IList<string> {}

Progress Bars

There are two types of progress bars here, they both are implemented using a class to maintain states.

IndeterminateProgressBar
var prg = new IndeterminateProgressBar(); // this setups the internal states
// Then you need to provide either a Task or Task</T>, the progress bar binds to it and runs until the task completes
await prg.RunAsync(task, "Running...", cancellationToken); // There are also overloads without header
// if the task is not started before being passed to the progress bar, it will be started automatically
// It is even better this way to synchronize the runtime of the progress bar with the task
prg.AnimationSequence = IndeterminateProgressBar.Patterns.CarriageReturn; // customize the animation
ProgressBar

ProgressBar is a more powerful version, but requires a percentage of progress.

// ProgressBar implements IDisposable
var prg = new ProgressBar();
// then on each time the progress percentage is actually changed, you call Update
Update(percentage, ReadOnlySpan<char> status);
// There are also overloads without header, and percentage can be either int or double (0-100)
// Also, you can change some of the visual properties of the progress bar after initialization
// by using the properties of the ProgressBar class
prg.ProgressChar = '■'; // Character to fill the progress bar
prg.ForegroundColor = Color.Red; // Color of the empty part
prg.ProgressColor = Color.Blue; // The color of the filled part

Pipes

Console wraps over System.Console and uses its In, Out, and Error streams. Since the names of the classes are identical, combining them in usage is somewhat painful as the compiler doesn't know which overloads to use. To aid in most cases, Console exposes those streams as static properties, and you can use them directly.

In rare cases, you will need something that there is in System.Console but not in Console, such as ReadKey, or SetCursorPosition, some events or otherwise, then you can simply call System.Console, this added verbosity is a worthy trade-off.

Contributing

This project uses an MIT license, if you want to contribute, you can do so by forking the repository and creating a pull request.

If you have feature requests or bug reports, please create an issue.

Contact

For bug reports, feature requests or offers of support/sponsorship contact dusrdev@gmail.com

This project is proudly made in Israel 🇮🇱 for the benefit of mankind.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

- Dropped Sharpify as a dependency - PrettyConsole is now self-sufficient.
- Many overloads were added that support the new PrettyConsoleInterpolatedStringHandler,
enabling zero allocation formatted outputs.
- Fixed issue that could sometimes cause writing into buffers beyond their bounds -
throwing an exception.
- IndeterminateProgressBar will now allow customization of the animated sequence via
the property AnimationSequence, and it also includes an inner class Patterns that
contains some constant sequences that could be used with it.
- IndeterminateProgressBar.UpdateRate is 200 ms by default.
- IndeterminateProgressBar header is now positioned right of the animation. Similar to
common CLIs.
- ProgressBar had numeral optimizations and should perform better in all scenarios.
- Color received 2 new implicit operators, enabling it to convert a combination with any object
to ColoredOutput, which means you can write much less verbose statements with .ToString() calls.
- Internal buffer pooling system was upgraded to further reduce allocations and relief more pressure from the GC.
- Write/WriteLine overload for T, will no longer throw an exception when a capacity above 256 characters is required to format the type, and also support ref structs.