Spectre.Console
.NETのための美しいコンソールアプリケーションを作成するライブラリ。リッチなテーブル、チャート、プロンプトを提供。
GitHub概要
spectreconsole/spectre.console
A .NET library that makes it easier to create beautiful console applications.
スター10,443
ウォッチ82
フォーク576
作成日:2020年7月21日
言語:C#
ライセンス:MIT License
トピックス
ansi-colorsconsoleconsole-tablesconsole-visualizationdotnetdotnet-coredotnet-standard
スター履歴
データ取得日時: 2025/7/25 11:09
フレームワーク
Spectre.Console
概要
Spectre.Consoleは、.NETのための美しいコンソールアプリケーションを作成するライブラリです。リッチなテーブル、チャート、プロンプトを提供し、美しいCLI出力と対話的な機能により人気が急上昇しています。モダンな.NETアプリケーションで広く採用されており、従来の単調なコンソール出力を劇的に改善します。
詳細
Spectre.Consoleは、コンソールアプリケーションに豊かな視覚体験をもたらすモダンなライブラリです。テキストスタイリング、テーブル、プログレスバー、チャート、対話的プロンプトなど、多様なUI要素を提供します。.NET 5+、.NET Framework、.NET Standardで利用可能で、クロスプラットフォーム対応しています。
主な特徴
- 豊富なテキストスタイリング: 色、太字、斜体、下線など多様なスタイル
- テーブル表示: 美しく整理されたテーブル表示機能
- プログレスバー: 単一・複数のプログレスバー表示
- 対話的プロンプト: 選択、入力、確認などのユーザー対話
- チャート: バーチャート、ブレークダウンチャートなど
- レイアウト: パネル、グリッド、カラムなどのレイアウト機能
- ライブ表示: リアルタイムでの表示更新
- マークアップ記法: HTMLライクなマークアップでのスタイリング
- カラーサポート: 豊富な色のサポートと自動色調整
メリット・デメリット
メリット
- 美しい出力: プロフェッショナルで視覚的に魅力的なコンソール出力
- 豊富なUI要素: テーブル、チャート、プロンプトなど多様な要素
- 使いやすいAPI: 直感的で学習しやすいAPIデザイン
- クロスプラットフォーム: Windows、Linux、macOSで動作
- パフォーマンス: 高速で効率的な描画エンジン
- 拡張性: カスタムレンダラーやスタイルの作成が可能
- アクティブな開発: 継続的な機能追加とバグ修正
デメリット
- 学習コスト: 豊富な機能ゆえに習得に時間が必要
- 依存関係: 外部ライブラリへの依存が追加される
- ターミナル依存: ターミナルの機能に依存する部分がある
- オーバーヘッド: シンプルなアプリケーションには過剰な場合がある
主要リンク
書き方の例
基本的なテキストスタイリング
using Spectre.Console;
class Program
{
static void Main(string[] args)
{
// 基本的なテキストスタイリング
AnsiConsole.WriteLine("普通のテキスト");
AnsiConsole.MarkupLine("[red]赤いテキスト[/]");
AnsiConsole.MarkupLine("[bold blue]太字の青いテキスト[/]");
AnsiConsole.MarkupLine("[italic green]斜体の緑のテキスト[/]");
AnsiConsole.MarkupLine("[underline yellow]下線付きの黄色いテキスト[/]");
// 背景色付き
AnsiConsole.MarkupLine("[white on red]白文字に赤背景[/]");
// 複合スタイル
AnsiConsole.MarkupLine("[bold italic underline red]すべてのスタイル適用[/]");
// Ruleで区切り線
AnsiConsole.Write(new Rule("[green]セクション区切り[/]"));
// Panelでボックス表示
AnsiConsole.Write(
new Panel("[yellow]これはパネル内のテキストです[/]")
.Header("情報パネル")
.Border(BoxBorder.Rounded)
.BorderColor(Color.Blue));
}
}
テーブル表示の例
using Spectre.Console;
class Program
{
static void Main(string[] args)
{
// 基本的なテーブル
var table = new Table();
// カラムを追加
table.AddColumn("名前");
table.AddColumn(new TableColumn("年齢").Centered());
table.AddColumn(new TableColumn("部署").RightAligned());
// 行を追加
table.AddRow("田中太郎", "30", "開発部");
table.AddRow("佐藤花子", "25", "営業部");
table.AddRow("鈴木一郎", "35", "企画部");
// スタイルを設定
table.Border(TableBorder.Rounded);
table.BorderColor(Color.Blue);
table.Title("社員一覧");
table.Caption("2024年度データ");
AnsiConsole.Write(table);
AnsiConsole.WriteLine();
// より高度なテーブル
var advancedTable = new Table()
.Border(TableBorder.Square)
.BorderColor(Color.Red)
.Title("[yellow]プロジェクト進捗[/]");
advancedTable.AddColumn("[green]プロジェクト名[/]");
advancedTable.AddColumn(new TableColumn("[blue]進捗率[/]").Centered());
advancedTable.AddColumn(new TableColumn("[red]ステータス[/]").RightAligned());
advancedTable.AddColumn("[purple]担当者[/]");
// 条件付きでスタイルを適用
advancedTable.AddRow(
"Webサイト改修",
"[green]85%[/]",
"[green]進行中[/]",
"田中");
advancedTable.AddRow(
"モバイルアプリ",
"[yellow]60%[/]",
"[yellow]遅延[/]",
"佐藤");
advancedTable.AddRow(
"API開発",
"[red]30%[/]",
"[red]要注意[/]",
"鈴木");
AnsiConsole.Write(advancedTable);
}
}
プログレスバーの例
using Spectre.Console;
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
// 単一プログレスバー
await AnsiConsole.Progress()
.StartAsync(async context =>
{
var task = context.AddTask("[green]ファイルをダウンロード中...[/]");
while (!task.IsFinished)
{
await Task.Delay(100);
task.Increment(2);
}
});
AnsiConsole.MarkupLine("[green]ダウンロード完了![/]");
AnsiConsole.WriteLine();
// 複数プログレスバー
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(), // タスク説明
new ProgressBarColumn(), // プログレスバー
new PercentageColumn(), // パーセンテージ
new RemainingTimeColumn(), // 残り時間
new SpinnerColumn(), // スピナー
})
.StartAsync(async context =>
{
var downloadTask = context.AddTask("[blue]ファイルダウンロード[/]", maxValue: 100);
var processTask = context.AddTask("[yellow]データ処理[/]", maxValue: 50);
var uploadTask = context.AddTask("[green]アップロード[/]", maxValue: 30);
// 並行処理をシミュレート
var tasks = new[]
{
SimulateWork(downloadTask, 50),
SimulateWork(processTask, 80),
SimulateWork(uploadTask, 120)
};
await Task.WhenAll(tasks);
});
AnsiConsole.MarkupLine("[green]すべての処理が完了しました![/]");
}
static async Task SimulateWork(ProgressTask task, int delay)
{
while (!task.IsFinished)
{
await Task.Delay(delay);
task.Increment(1);
}
}
}
対話的プロンプトの例
using Spectre.Console;
using System;
using System.ComponentModel.DataAnnotations;
class Program
{
static void Main(string[] args)
{
AnsiConsole.MarkupLine("[bold blue]ユーザー情報の入力[/]");
AnsiConsole.WriteLine();
// テキスト入力
var name = AnsiConsole.Ask<string>("お名前を入力してください:");
// パスワード入力(マスク)
var password = AnsiConsole.Prompt(
new TextPrompt<string>("パスワードを入力してください:")
.PromptStyle("red")
.Secret());
// 数値入力(バリデーション付き)
var age = AnsiConsole.Prompt(
new TextPrompt<int>("年齢を入力してください:")
.PromptStyle("green")
.ValidationErrorMessage("[red]有効な数値を入力してください[/]")
.Validate(age =>
{
return age switch
{
<= 0 => ValidationResult.Error("[red]年齢は正の数である必要があります[/]"),
>= 150 => ValidationResult.Error("[red]年齢が現実的ではありません[/]"),
_ => ValidationResult.Success(),
};
}));
// 選択プロンプト
var department = AnsiConsole.Prompt(
new SelectionPrompt<string>()
.Title("所属部署を選択してください:")
.PageSize(10)
.MoreChoicesText("[grey](上下キーで選択、Enterで決定)[/]")
.AddChoices(new[] {
"開発部", "営業部", "企画部", "人事部", "経理部", "総務部"
}));
// 複数選択プロンプト
var skills = AnsiConsole.Prompt(
new MultiSelectionPrompt<string>()
.Title("スキルを選択してください(複数選択可):")
.NotRequired() // 必須ではない
.PageSize(10)
.MoreChoicesText("[grey](スペースで選択/選択解除、Enterで決定)[/]")
.InstructionsText(
"[grey](スペースキーで選択、上下キーで移動、Enterで決定)[/]")
.AddChoices(new[] {
"C#", "JavaScript", "Python", "Java", "Go",
"React", "Vue.js", "Angular", "Docker", "Kubernetes"
}));
// 確認プロンプト
var confirm = AnsiConsole.Confirm("入力内容を保存しますか?");
// 結果表示
AnsiConsole.WriteLine();
var panel = new Panel(
$"[bold]名前:[/] {name}\n" +
$"[bold]年齢:[/] {age}\n" +
$"[bold]部署:[/] {department}\n" +
$"[bold]スキル:[/] {string.Join(", ", skills)}\n" +
$"[bold]保存:[/] {(confirm ? "[green]はい[/]" : "[red]いいえ[/]")}")
.Header("入力結果")
.Border(BoxBorder.Rounded)
.BorderColor(Color.Green);
AnsiConsole.Write(panel);
if (confirm)
{
// 保存処理をシミュレート
AnsiConsole.Status()
.Start("データを保存中...", ctx =>
{
ctx.Spinner(Spinner.Known.Star);
ctx.SpinnerStyle(Style.Parse("green"));
System.Threading.Thread.Sleep(2000);
});
AnsiConsole.MarkupLine("[green]データが正常に保存されました![/]");
}
}
}
チャートとライブ表示の例
using Spectre.Console;
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
// バーチャート
AnsiConsole.Write(
new BarChart()
.Width(60)
.Label("[green bold underline]売上実績[/]")
.CenterLabel()
.AddItem("1月", 12.5, Color.Yellow)
.AddItem("2月", 15.8, Color.Green)
.AddItem("3月", 10.2, Color.Red)
.AddItem("4月", 18.9, Color.Blue)
.AddItem("5月", 22.1, Color.Purple));
AnsiConsole.WriteLine();
// ブレークダウンチャート
AnsiConsole.Write(
new BreakdownChart()
.Width(100)
.AddItem("開発", 45, Color.Red)
.AddItem("テスト", 25, Color.Green)
.AddItem("設計", 20, Color.Blue)
.AddItem("その他", 10, Color.Yellow));
AnsiConsole.WriteLine();
// ライブ表示の例
await AnsiConsole.Live(CreateStatusDisplay())
.StartAsync(async context =>
{
for (int i = 0; i <= 100; i += 5)
{
// 表示を更新
context.UpdateTarget(CreateStatusDisplay(i));
await Task.Delay(200);
}
});
AnsiConsole.MarkupLine("[green]処理完了![/]");
}
static Panel CreateStatusDisplay(int progress = 0)
{
var grid = new Grid()
.AddColumn()
.AddColumn();
grid.AddRow(
new Panel("[bold]システム状態[/]")
.BorderColor(Color.Blue),
new Panel($"[bold]進行状況: {progress}%[/]")
.BorderColor(Color.Green));
// プログレスバーを追加
if (progress > 0)
{
var progressBar = new ProgressBar()
.Value(progress)
.MaxValue(100);
grid.AddRow(
new Panel(progressBar)
.Header("処理進行中")
.BorderColor(Color.Yellow),
new Panel($"[bold]残り時間: {(100-progress)/5}秒[/]")
.BorderColor(Color.Purple));
}
return new Panel(grid)
.Header("[bold yellow]ダッシュボード[/]")
.Border(BoxBorder.Double)
.BorderColor(Color.Cyan1);
}
}
カスタムレンダラーの例
using Spectre.Console;
using Spectre.Console.Rendering;
using System;
using System.Collections.Generic;
// カスタムレンダラークラス
public class CustomStatusRenderer : Renderable
{
private readonly string _title;
private readonly Dictionary<string, (int current, int total, Color color)> _items;
public CustomStatusRenderer(string title)
{
_title = title;
_items = new Dictionary<string, (int, int, Color)>();
}
public CustomStatusRenderer AddItem(string name, int current, int total, Color color)
{
_items[name] = (current, total, color);
return this;
}
protected override IEnumerable<Segment> Render(RenderOptions options, int maxWidth)
{
var segments = new List<Segment>();
// タイトル
segments.Add(new Segment(_title, new Style(Color.Yellow, decoration: Decoration.Bold)));
segments.Add(Segment.LineBreak);
segments.Add(Segment.LineBreak);
// 各アイテムのプログレス
foreach (var (name, (current, total, color)) in _items)
{
var percentage = (double)current / total * 100;
var barWidth = (int)(maxWidth * 0.6);
var filledWidth = (int)(barWidth * current / total);
// アイテム名
segments.Add(new Segment($"{name}: ", new Style(Color.White)));
// プログレスバー
segments.Add(new Segment(new string('█', filledWidth), new Style(color)));
segments.Add(new Segment(new string('░', barWidth - filledWidth), new Style(Color.Grey19)));
// パーセンテージ
segments.Add(new Segment($" {percentage:F1}% ({current}/{total})", new Style(Color.Grey)));
segments.Add(Segment.LineBreak);
}
return segments;
}
}
class Program
{
static void Main(string[] args)
{
var customStatus = new CustomStatusRenderer("プロジェクト進捗状況")
.AddItem("フロントエンド", 8, 10, Color.Green)
.AddItem("バックエンド", 6, 12, Color.Yellow)
.AddItem("データベース", 3, 5, Color.Red)
.AddItem("テスト", 2, 8, Color.Blue);
AnsiConsole.Write(customStatus);
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("[green]カスタムレンダラーの例[/]");
}
}
設定とプロファイル管理の例
using Spectre.Console;
using System;
using System.IO;
using System.Text.Json;
public class UserProfile
{
public string Name { get; set; }
public string Email { get; set; }
public string Department { get; set; }
public string[] Skills { get; set; }
public ConsoleTheme Theme { get; set; }
}
public enum ConsoleTheme
{
Default,
Dark,
Light,
Colorful
}
class Program
{
static void Main(string[] args)
{
AnsiConsole.Write(
new FigletText("Profile Manager")
.Centered()
.Color(Color.Green));
var choice = AnsiConsole.Prompt(
new SelectionPrompt<string>()
.Title("操作を選択してください:")
.AddChoices(new[] {
"新規プロファイル作成",
"既存プロファイル読み込み",
"プロファイル一覧表示",
"テーマ設定",
"終了"
}));
switch (choice)
{
case "新規プロファイル作成":
CreateNewProfile();
break;
case "既存プロファイル読み込み":
LoadExistingProfile();
break;
case "プロファイル一覧表示":
DisplayProfiles();
break;
case "テーマ設定":
ConfigureTheme();
break;
case "終了":
AnsiConsole.MarkupLine("[yellow]アプリケーションを終了します[/]");
break;
}
}
static void CreateNewProfile()
{
AnsiConsole.MarkupLine("[bold blue]新規プロファイル作成[/]");
var profile = new UserProfile
{
Name = AnsiConsole.Ask<string>("名前:"),
Email = AnsiConsole.Ask<string>("メールアドレス:"),
Department = AnsiConsole.Prompt(
new SelectionPrompt<string>()
.Title("部署:")
.AddChoices("開発部", "営業部", "企画部", "人事部")),
Skills = AnsiConsole.Prompt(
new MultiSelectionPrompt<string>()
.Title("スキル:")
.AddChoices("C#", "JavaScript", "Python", "Docker", "AWS"))
.ToArray(),
Theme = AnsiConsole.Prompt(
new SelectionPrompt<ConsoleTheme>()
.Title("テーマ:")
.AddChoices(Enum.GetValues<ConsoleTheme>()))
};
// プロファイルを保存
SaveProfile(profile);
DisplayProfile(profile);
}
static void LoadExistingProfile()
{
// 実装省略
AnsiConsole.MarkupLine("[yellow]この機能は未実装です[/]");
}
static void DisplayProfiles()
{
// 実装省略
AnsiConsole.MarkupLine("[yellow]この機能は未実装です[/]");
}
static void ConfigureTheme()
{
// 実装省略
AnsiConsole.MarkupLine("[yellow]この機能は未実装です[/]");
}
static void SaveProfile(UserProfile profile)
{
var json = JsonSerializer.Serialize(profile, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText($"{profile.Name}_profile.json", json);
AnsiConsole.MarkupLine($"[green]プロファイルを保存しました: {profile.Name}_profile.json[/]");
}
static void DisplayProfile(UserProfile profile)
{
var table = new Table()
.Border(TableBorder.Rounded)
.BorderColor(Color.Blue)
.Title("プロファイル情報");
table.AddColumn("項目");
table.AddColumn("値");
table.AddRow("名前", $"[bold]{profile.Name}[/]");
table.AddRow("メール", profile.Email);
table.AddRow("部署", $"[blue]{profile.Department}[/]");
table.AddRow("スキル", string.Join(", ", profile.Skills));
table.AddRow("テーマ", $"[green]{profile.Theme}[/]");
AnsiConsole.Write(table);
}
}
プロジェクトファイル例
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Spectre.Console" Version="0.47.0" />
<PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup>
</Project>