Spectre.Console Package
If an automation script only outputs “Processing… Done: 10 files” with Console.WriteLine, it is difficult to understand what is happening at which step. This problem gets worse as the number of components increases and analysis time grows. Spectre.Console is a UI library that creates console output developers actually want to read. Tables, progress indicators, color highlighting, and more make the script execution status visible at a glance.
Package Installation
Section titled “Package Installation”#:package Spectre.Console@0.54.0Basic Output: MarkupLine
Section titled “Basic Output: MarkupLine”The most basic feature is text output with color and style applied. Specify the color or style inside square brackets and close with [/].
using Spectre.Console;
// ColorsAnsiConsole.MarkupLine("[red]Error:[/] Something went wrong");AnsiConsole.MarkupLine("[green]Success:[/] Operation completed");AnsiConsole.MarkupLine("[yellow]Warning:[/] Please check");AnsiConsole.MarkupLine("[blue]Info:[/] Processing started");
// StylesAnsiConsole.MarkupLine("[bold]Bold text[/]");AnsiConsole.MarkupLine("[dim]Dimmed text[/]");AnsiConsole.MarkupLine("[italic]Italic text[/]");AnsiConsole.MarkupLine("[underline]Underlined text[/]");
// CombinationsAnsiConsole.MarkupLine("[bold red]Critical Error![/]");AnsiConsole.MarkupLine("[bold green]✓[/] [dim]Task completed[/]");Available main colors include [red], [green], [yellow], [blue], [cyan], [magenta], [grey], [white], etc.
Table: For Structuring Analysis Results
Section titled “Table: For Structuring Analysis Results”When structured data needs to be shown in rows and columns, like analysis results for multiple components, use Table. You can compare file counts, commit counts, and status of each component at a glance.
using Spectre.Console;
var table = new Table();
// Border styletable.Border(TableBorder.Rounded);table.BorderColor(Color.Grey);
// Add columnstable.AddColumn("Name");table.AddColumn("Status");table.AddColumn(new TableColumn("Time").RightAligned());
// Add rowstable.AddRow("App.cs", "[green]Done[/]", "0.3s");table.AddRow("Config.cs", "[green]Done[/]", "0.1s");table.AddRow("Program.cs", "[yellow]Processing[/]", "-");
// OutputAnsiConsole.Write(table);Output:
╭───────────┬────────────┬──────╮│ Name │ Status │ Time │├───────────┼────────────┼──────┤│ App.cs │ Done │ 0.3s ││ Config.cs │ Done │ 0.1s ││ Program.cs│ Processing │ - │╰───────────┴────────────┴──────╯Rule: For Visually Separating Sections
Section titled “Rule: For Visually Separating Sections”When script output is divided into multiple steps, Rule clearly marks section boundaries. Placing a divider between “Analysis Start” and “Analysis Complete” immediately shows where one step begins and ends.
using Spectre.Console;
// Basic RuleAnsiConsole.Write(new Rule("[bold blue]Analysis Results[/]"));
// With styleAnsiConsole.Write(new Rule("[bold green]Success[/]").RuleStyle("green"));
// Left-alignedAnsiConsole.Write(new Rule("[yellow]Warning[/]").LeftJustified());Output:
─────────────────── Analysis Results ───────────────────Panel: For Highlighting Important Information
Section titled “Panel: For Highlighting Important Information”For content that users must check, like error messages or configuration information, place it in a box to make it stand out.
using Spectre.Console;
var panel = new Panel("This is the content inside the panel."){ Header = new PanelHeader("[bold]Information[/]"), Border = BoxBorder.Rounded, BorderStyle = new Style(Color.Blue), Padding = new Padding(2, 1)};
AnsiConsole.Write(panel);Output:
╭─────────── Information ───────────╮│ ││ This is the content inside the ││ panel. ││ │╰───────────────────────────────────╯Status: For Showing Progress of Long-Running Tasks
Section titled “Status: For Showing Progress of Long-Running Tasks”For time-consuming tasks like project builds or Git analysis, show “what is currently in progress” with a spinner. The status message can be updated as the task phase changes.
using Spectre.Console;
await AnsiConsole.Status() .Spinner(Spinner.Known.Dots) .SpinnerStyle(Style.Parse("cyan")) .StartAsync("Processing...", async ctx => { // Task 1 ctx.Status("Loading files..."); await Task.Delay(1000);
// Task 2 ctx.Status("Analyzing..."); await Task.Delay(1000);
// Task 3 ctx.Status("Generating report..."); await Task.Delay(1000); });
AnsiConsole.MarkupLine("[green]Done![/]");Various spinner types are available, including Dots, Line(-\|/), Star, Arrow, and more.
Progress: For Tracking Multiple Tasks Simultaneously
Section titled “Progress: For Tracking Multiple Tasks Simultaneously”Use when processing multiple components in parallel and showing progress for each.
using Spectre.Console;
await AnsiConsole.Progress() .StartAsync(async ctx => { var task1 = ctx.AddTask("[green]Downloading[/]"); var task2 = ctx.AddTask("[blue]Installing[/]");
while (!ctx.IsFinished) { task1.Increment(1.5); task2.Increment(0.5); await Task.Delay(50); } });Output:
Downloading [████████████████████] 100%Installing [██████████──────────] 50%Practical Example: Console Output of AnalyzeAllComponents.cs
Section titled “Practical Example: Console Output of AnalyzeAllComponents.cs”Let’s see how these elements are combined in release note automation. Rule separates sections, Table shows configuration information, MarkupLine shows step-by-step progress, Status shows analysis work, and finally a result Table is output.
#!/usr/bin/env dotnet
#:package System.CommandLine@2.0.1#:package Spectre.Console@0.54.0
using System;using System.Threading.Tasks;using Spectre.Console;
// HeaderAnsiConsole.WriteLine();AnsiConsole.Write(new Rule("[bold blue]Analyzing All Components[/]").RuleStyle("blue"));AnsiConsole.WriteLine();
// Information tablevar infoTable = new Table() .Border(TableBorder.Rounded) .BorderColor(Color.Grey);
infoTable.AddColumn(new TableColumn("[grey]Property[/]").NoWrap());infoTable.AddColumn(new TableColumn("[grey]Value[/]"));infoTable.AddRow("[white]Config[/]", "[dim]config/component-priority.json[/]");infoTable.AddRow("[white]Output[/]", "[dim].analysis-output[/]");infoTable.AddRow("[white]Base Branch[/]", "[cyan]origin/release/1.0[/]");infoTable.AddRow("[white]Target Branch[/]", "[cyan]HEAD[/]");
AnsiConsole.Write(infoTable);AnsiConsole.WriteLine();
// Step-by-step progressAnsiConsole.MarkupLine("[bold]Step 1[/] [dim]Loading components...[/]");AnsiConsole.MarkupLine(" [green]Found[/] Src/Functorium");AnsiConsole.MarkupLine(" [green]Found[/] Src/Functorium.Testing");AnsiConsole.MarkupLine(" [dim]Total: 2 components[/]");AnsiConsole.WriteLine();
// Show analysis progress with spinnerawait AnsiConsole.Status() .Spinner(Spinner.Known.Dots) .SpinnerStyle(Style.Parse("cyan")) .StartAsync("Analyzing components...", async ctx => { await Task.Delay(2000); // Actual analysis work });
// Result tableAnsiConsole.WriteLine();var resultTable = new Table() .Border(TableBorder.Rounded) .AddColumn("Component") .AddColumn("Files") .AddColumn("Commits") .AddColumn("Status");
resultTable.AddRow("Functorium", "31", "19", "[green]✓[/]");resultTable.AddRow("Functorium.Testing", "18", "13", "[green]✓[/]");
AnsiConsole.Write(resultTable);AnsiConsole.WriteLine();
// Completion messageAnsiConsole.Write(new Rule("[bold green]Analysis Complete[/]").RuleStyle("green"));Frequently Used Patterns
Section titled “Frequently Used Patterns”Here is a summary of patterns used repeatedly across release note scripts.
For step-by-step progress display:
AnsiConsole.MarkupLine("[bold]Step 1[/] [dim]Loading...[/]");AnsiConsole.MarkupLine(" [green]✓[/] File loaded");AnsiConsole.MarkupLine(" [green]✓[/] Config parsed");AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("[bold]Step 2[/] [dim]Processing...[/]");Success, failure, and warning messages:
// SuccessAnsiConsole.MarkupLine("[green]✓[/] Operation completed successfully");
// FailureAnsiConsole.MarkupLine("[red]✗[/] Operation failed: {0}", errorMessage);
// WarningAnsiConsole.MarkupLine("[yellow]⚠[/] Warning: {0}", warningMessage);Highlighting information requiring user attention with Panel:
var panel = new Panel($"[yellow]Base branch[/] [cyan]{baseBranch}[/] [yellow]does not exist.[/]"){ Border = BoxBorder.Rounded, BorderStyle = new Style(Color.Yellow), Padding = new Padding(2, 1)};AnsiConsole.Write(panel);Q1: Why use Spectre.Console instead of Console.WriteLine?
Section titled “Q1: Why use Spectre.Console instead of Console.WriteLine?”A: Console.WriteLine only outputs plain text, making it difficult to compare analysis results of multiple components at a glance. Spectre.Console provides tables, color highlighting, progress indicators, dividers, and more, showing script execution status visually and transparently. The difference is especially significant in long-running tasks when understanding what step you are currently at.
Q2: When should Status and Progress each be used?
Section titled “Q2: When should Status and Progress each be used?”A: Status is suitable for displaying a spinner and status message when a single task is in progress, updating the message as phases change. Progress is used for simultaneously tracking the progress of multiple tasks, showing percentage progress bars for each task. In release note scripts, Status is used for single component analysis and Progress for parallel processing of multiple components.
Q3: How do you output literal square brackets in Spectre.Console’s markup syntax?
Section titled “Q3: How do you output literal square brackets in Spectre.Console’s markup syntax?”A: Spectre.Console interprets [ and ] as markup tags, so to output literal brackets, escape them with [[ and ]]. For example, AnsiConsole.MarkupLine("Array: [[0]]") outputs Array: [0].
Thanks to Spectre.Console, the execution process of automation scripts becomes transparent. Starting from the next section, we will analyze the actual scripts utilizing these two packages one by one.