Terminal abstractions and widgets for console applications - IConsole, ITerminal, panels, tables, rules, and ANSI color support.
dotnet add package TimeWarp.Terminalusing TimeWarp.Terminal;
// Use the static Terminal class (Console-compatible API)
Terminal.WriteLine("Hello, World!".Green());
Terminal.WriteLine("Warning!".Yellow().Bold());
// Or get a terminal instance — all Write methods return ITerminal for fluent chaining
ITerminal terminal = TimeWarpTerminal.Default;
terminal
.WritePanel("Important message", "Notice")
.WriteRule("Section")
.WriteTable(t => t
.AddColumn("Name")
.AddColumn("Value")
.AddRow("Status", "OK".Green()))
.WriteLine("Done!");The Terminal static class provides a Console-compatible API for easy migration:
using static TimeWarp.Terminal.Terminal;
// Direct replacement for Console methods
WriteLine("Hello, World!");
WriteErrorLine("Error occurred!");
string? input = ReadLine();
Clear();
// Properties
int width = WindowWidth;
bool interactive = IsInteractive;
bool colorSupport = SupportsColor;
// Cursor operations
SetCursorPosition(10, 5);
var (left, top) = GetCursorPosition();// Replace Instance for testing
using TestTerminal testTerminal = new();
Terminal.Instance = testTerminal;
Terminal.WriteLine("test output");
Assert.Contains("test output", testTerminal.Output);
// Restore after test
Terminal.Instance = TimeWarpTerminal.Default;Basic console I/O abstraction for testable console applications.
public interface IConsole
{
IConsole Write(string message);
IConsole WriteLine(string? message = null);
Task WriteLineAsync(string? message = null);
IConsole WriteErrorLine(string? message = null);
Task WriteErrorLineAsync(string? message = null);
string? ReadLine();
}Extended terminal interface with cursor control, colors, and hyperlinks.
public interface ITerminal : IConsole
{
new ITerminal Write(string message);
new ITerminal WriteLine(string? message = null);
new ITerminal WriteErrorLine(string? message = null);
ConsoleKeyInfo ReadKey(bool intercept);
void SetCursorPosition(int left, int top);
(int Left, int Top) GetCursorPosition();
int WindowWidth { get; }
bool IsInteractive { get; }
bool SupportsColor { get; }
bool SupportsHyperlinks { get; }
void Clear();
}| Class | Description |
|---|---|
TimeWarpTerminal |
Production ITerminal with full terminal capabilities |
TimeWarpConsole |
Production IConsole wrapping System.Console |
TestTerminal |
Test implementation with captured output and scripted input |
TestConsole |
Simpler test implementation for basic I/O testing |
using TestTerminal terminal = new();
// Queue input for ReadLine
terminal = new TestTerminal("line1\nline2");
// Queue keys for ReadKey
terminal.QueueKey(ConsoleKey.Enter);
terminal.QueueKeys("hello");
terminal.QueueLine("complete line");
// Run code that uses ITerminal
myCommand.Execute(terminal);
// Verify output
Assert.Contains("expected text", terminal.Output);
Assert.Contains("error message", terminal.ErrorOutput);Bordered panel with optional header and content.
// Simple panel
terminal.WritePanel("This is important information");
// Panel with header
terminal.WritePanel("Content here", "Notice");
// Fluent builder with full options
terminal.WritePanel
(
panel =>
panel
.Header("Configuration".Cyan().Bold())
.Content("Setting: value")
.Border(BorderStyle.Rounded)
.BorderColor(AnsiColors.Cyan)
.Padding(2, 1)
.Width(60)
.WordWrap(true)
);Border Styles: Rounded, Square, Doubled, Heavy, None
Formatted table with columns, alignment, and styling.
// Simple table
terminal.WriteTable
(
t => t
.AddColumn("Name")
.AddColumn("Value", Alignment.Right)
.AddRow("CPU", "45%")
.AddRow("Memory", "2.1 GB")
);
// Full-featured table
terminal.WriteTable(t => t
.AddColumn("Package")
.AddColumn("Downloads", Alignment.Right)
.AddColumn(new TableColumn("Path") { TruncateMode = TruncateMode.Start })
.AddRow("GuardClauses", "12M", "/home/user/packages/guard")
.Border(BorderStyle.Rounded)
.BorderColor(AnsiColors.Cyan)
.Expand()
.Shrink());
terminal.WriteTable(table);Alignment: Left (default), Right, Center
TruncateMode: End (default), Start, Middle
Horizontal rule with optional centered title.
// Simple rule
terminal.WriteRule();
// Rule with title
terminal.WriteRule("Section Title");
// Styled rule
terminal.WriteRule("Results".Cyan().Bold());
// Fluent builder
terminal.WriteRule(rule => rule
.Title("Configuration")
.Style(LineStyle.Doubled)
.Color(AnsiColors.Cyan));Line Styles: Thin, Doubled, Heavy
Extension methods for colored and styled console output.
// Foreground colors
terminal.WriteLine("Success!".Green());
terminal.WriteLine("Warning!".Yellow());
terminal.WriteLine("Error!".Red());
// Chained styles
terminal.WriteLine("Important".Red().Bold().Underline());
// Background colors
terminal.WriteLine("Highlighted".OnYellow());
terminal.WriteLine("Inverted".Black().OnWhite());Standard: Black, Red, Green, Yellow, Blue, Magenta, Cyan, White, Gray
Bright: BrightRed, BrightGreen, BrightYellow, BrightBlue, BrightMagenta, BrightCyan, BrightWhite
Bold(), Dim(), Italic(), Underline(), Strikethrough()
OnBlack(), OnRed(), OnGreen(), OnYellow(), OnBlue(), OnMagenta(), OnCyan(), OnWhite()
Use ConsoleColor enum values for color output without needing ANSI escape codes directly. This provides a Console-compatible API for colored output.
// Single foreground color
Terminal.WriteLine("Error!", ConsoleColor.Red);
Terminal.WriteLine("Success!", ConsoleColor.Green);
Terminal.WriteLine("Warning!", ConsoleColor.Yellow);
// Foreground and background colors
Terminal.WriteLine("Highlighted", ConsoleColor.Black, ConsoleColor.Yellow);
Terminal.WriteLine("Inverted", ConsoleColor.White, ConsoleColor.Black);
// Error output with color
Terminal.WriteErrorLine("Error: File not found", ConsoleColor.Red);
// Write without newline
Terminal.Write("Loading...", ConsoleColor.Cyan);
// Widgets with colors
Terminal.WriteTable(table => table
.AddColumn("Name")
.AddColumn("Value")
.AddRow("Status", "OK"),
ConsoleColor.White, ConsoleColor.DarkBlue);
Terminal.WritePanel("Important content", "Notice",
ConsoleColor.White, ConsoleColor.DarkBlue);All ConsoleColor values are mapped to their ANSI equivalents:
Foreground: Black, Red, Green, Yellow, Blue, Magenta, Cyan, White, Gray, DarkGray, DarkRed, DarkGreen, DarkYellow, DarkBlue, DarkMagenta, DarkCyan
Background: Maps to corresponding ANSI background codes (BgBlack, BgRed, etc.)
OSC 8 hyperlinks for supported terminals (Windows Terminal, iTerm2, VS Code, etc.).
// Write a clickable link
terminal.WriteLink("https://github.com", "GitHub");
terminal.WriteLinkLine("https://example.com", "Click here");
// String extension method
string link = "Click here".Link("https://example.com");
terminal.WriteLine(link);
// Styled hyperlink
terminal.WriteLine("Visit us".Link("https://example.com").Cyan().Underline());
// Check terminal support
if (terminal.SupportsHyperlinks)
terminal.WriteLinkLine("https://docs.com", "View docs");
else
terminal.WriteLine("View docs at https://docs.com");Utilities for working with ANSI-styled strings.
// Get visible length (excludes ANSI codes)
int length = AnsiStringUtils.GetVisibleLength("Hello".Red()); // 5
// Strip all ANSI codes
string plain = AnsiStringUtils.StripAnsiCodes("\x1b[31mError\x1b[0m"); // "Error"
// Pad accounting for ANSI codes
string padded = AnsiStringUtils.PadRightVisible("Hi".Red(), 10);
string centered = AnsiStringUtils.CenterVisible("Title".Bold(), 40);
// Wrap text preserving ANSI codes
string[] lines = AnsiStringUtils.WrapText(longStyledText, maxWidth: 80);