mirror of
https://github.com/spectreconsole/spectre.console.git
synced 2025-10-25 15:19:23 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e429f6434b | ||
|
|
93ec7401c8 | ||
|
|
697273917e | ||
|
|
2943535973 | ||
|
|
cd0d182f12 | ||
|
|
b197f278ed |
6
.github/workflows/ci.yaml
vendored
6
.github/workflows/ci.yaml
vendored
@@ -65,9 +65,9 @@ jobs:
|
||||
run: |
|
||||
dotnet tool restore
|
||||
dotnet example info
|
||||
dotnet example table
|
||||
dotnet example grid
|
||||
dotnet example panel
|
||||
dotnet example tables
|
||||
dotnet example grids
|
||||
dotnet example panels
|
||||
dotnet example colors
|
||||
dotnet example emojis
|
||||
|
||||
|
||||
@@ -4,16 +4,30 @@ Order: 2
|
||||
|
||||
There is different built-in borders you can use for tables and panels.
|
||||
|
||||
# Built-in borders
|
||||
# Table borders
|
||||
|
||||
<img src="../assets/images/borders.png" style="max-width: 100%;">
|
||||
<img src="../assets/images/borders/table.png" style="max-width: 100%;">
|
||||
|
||||
# Usage
|
||||
## Example
|
||||
|
||||
To create a table and set it's border to `SimpleHeavy` as seen in the
|
||||
image above:
|
||||
To set a table border to `SimpleHeavy`:
|
||||
|
||||
```csharp
|
||||
var table = new Table();
|
||||
table.Border = Border.SimpleHeavy;
|
||||
table.Border = TableBorder.SimpleHeavy;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Panel borders
|
||||
|
||||
<img src="../assets/images/borders/panel.png" style="max-width: 100%;">
|
||||
|
||||
## Example
|
||||
|
||||
To set a panel border to `Rounded`:
|
||||
|
||||
```csharp
|
||||
var panel = new Panel("Hello World");
|
||||
panel.Border = BoxBorder.Rounded;
|
||||
```
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 415 KiB |
BIN
docs/input/assets/images/borders/panel.png
Normal file
BIN
docs/input/assets/images/borders/panel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 112 KiB |
BIN
docs/input/assets/images/borders/table.png
Normal file
BIN
docs/input/assets/images/borders/table.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 503 KiB |
@@ -4,6 +4,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Title>Borders</Title>
|
||||
<Description>Demonstrates the different kind of borders.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -1,40 +1,58 @@
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Borders
|
||||
namespace BordersExample
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
var items = new[]
|
||||
{
|
||||
Create("Ascii", Border.Ascii),
|
||||
Create("Ascii2", Border.Ascii2),
|
||||
Create("AsciiDoubleHead", Border.AsciiDoubleHead),
|
||||
Create("Horizontal", Border.Horizontal),
|
||||
Create("Simple", Border.Simple),
|
||||
Create("SimpleHeavy", Border.SimpleHeavy),
|
||||
Create("Minimal", Border.Minimal),
|
||||
Create("MinimalHeavyHead", Border.MinimalHeavyHead),
|
||||
Create("MinimalDoubleHead", Border.MinimalDoubleHead),
|
||||
Create("Square", Border.Square),
|
||||
Create("Rounded", Border.Rounded),
|
||||
Create("Heavy", Border.Heavy),
|
||||
Create("HeavyEdge", Border.HeavyEdge),
|
||||
Create("HeavyHead", Border.HeavyHead),
|
||||
Create("Double", Border.Double),
|
||||
Create("DoubleEdge", Border.DoubleEdge),
|
||||
};
|
||||
|
||||
// Render panel borders
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.Render(new Columns(items).Collapse());
|
||||
AnsiConsole.MarkupLine("[white bold underline]PANEL BORDERS[/]");
|
||||
AnsiConsole.WriteLine();
|
||||
RenderPanelBorders();
|
||||
|
||||
// Render table borders
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine("[white bold underline]TABLE BORDERS[/]");
|
||||
AnsiConsole.WriteLine();
|
||||
RenderTableBorders();
|
||||
}
|
||||
|
||||
private static IRenderable Create(string name, Border border)
|
||||
private static void RenderPanelBorders()
|
||||
{
|
||||
static IRenderable CreatePanel(string name, BoxBorder border)
|
||||
{
|
||||
return new Panel($"This is a panel with\nthe [yellow]{name}[/] border.")
|
||||
.SetHeader($" {name} ", Style.Parse("blue"), Justify.Center)
|
||||
.SetBorderStyle(Style.Parse("grey"))
|
||||
.SetBorder(border);
|
||||
}
|
||||
|
||||
var items = new[]
|
||||
{
|
||||
CreatePanel("Ascii", BoxBorder.Ascii),
|
||||
CreatePanel("Square", BoxBorder.Square),
|
||||
CreatePanel("Rounded", BoxBorder.Rounded),
|
||||
CreatePanel("Heavy", BoxBorder.Heavy),
|
||||
CreatePanel("Double", BoxBorder.Double),
|
||||
CreatePanel("None", BoxBorder.None),
|
||||
};
|
||||
|
||||
AnsiConsole.Render(
|
||||
new Padder(
|
||||
new Columns(items).PadRight(2),
|
||||
new Padding(2,0,0,0)));
|
||||
}
|
||||
|
||||
private static void RenderTableBorders()
|
||||
{
|
||||
static IRenderable CreateTable(string name, TableBorder border)
|
||||
{
|
||||
var table = new Table().SetBorder(border);
|
||||
table.AddColumns("[yellow]Header 1[/]", "[yellow]Header 2[/]");
|
||||
table.AddColumn("[yellow]Header 1[/]");
|
||||
table.AddColumn("[yellow]Header 2[/]", col => col.RightAligned());
|
||||
table.AddRow("Cell", "Cell");
|
||||
table.AddRow("Cell", "Cell");
|
||||
|
||||
@@ -43,5 +61,29 @@ namespace Borders
|
||||
.SetBorderStyle(Style.Parse("grey"))
|
||||
.NoBorder();
|
||||
}
|
||||
|
||||
var items = new[]
|
||||
{
|
||||
CreateTable("Ascii", TableBorder.Ascii),
|
||||
CreateTable("Ascii2", TableBorder.Ascii2),
|
||||
CreateTable("AsciiDoubleHead", TableBorder.AsciiDoubleHead),
|
||||
CreateTable("Horizontal", TableBorder.Horizontal),
|
||||
CreateTable("Simple", TableBorder.Simple),
|
||||
CreateTable("SimpleHeavy", TableBorder.SimpleHeavy),
|
||||
CreateTable("Minimal", TableBorder.Minimal),
|
||||
CreateTable("MinimalHeavyHead", TableBorder.MinimalHeavyHead),
|
||||
CreateTable("MinimalDoubleHead", TableBorder.MinimalDoubleHead),
|
||||
CreateTable("Square", TableBorder.Square),
|
||||
CreateTable("Rounded", TableBorder.Rounded),
|
||||
CreateTable("Heavy", TableBorder.Heavy),
|
||||
CreateTable("HeavyEdge", TableBorder.HeavyEdge),
|
||||
CreateTable("HeavyHead", TableBorder.HeavyHead),
|
||||
CreateTable("Double", TableBorder.Double),
|
||||
CreateTable("DoubleEdge", TableBorder.DoubleEdge),
|
||||
CreateTable("Markdown", TableBorder.Markdown),
|
||||
};
|
||||
|
||||
AnsiConsole.Render(new Columns(items).Collapse());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Title>Colors</Title>
|
||||
<Description>Demonstrates how to use [yellow]c[/][red]o[/][green]l[/][blue]o[/][aqua]r[/][lime]s[/] in the console.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Title>Columns</Title>
|
||||
<Description>Demonstrates how to render data into columns.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Title>Emojis</Title>
|
||||
<Description>Demonstrates how to render emojis.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace Emojis
|
||||
namespace EmojiExample
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Title>Grids</Title>
|
||||
<Description>Demonstrates how to render grids in a console.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Title>Info</Title>
|
||||
<Description>Displays the capabilities of the current console.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Spectre.Console;
|
||||
|
||||
namespace Info
|
||||
namespace InfoExample
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
@@ -9,19 +9,20 @@ namespace Info
|
||||
var grid = new Grid()
|
||||
.AddColumn(new GridColumn().NoWrap().PadRight(4))
|
||||
.AddColumn()
|
||||
.AddRow("[b]:artist_palette: Color system[/]", $"{AnsiConsole.Capabilities.ColorSystem}")
|
||||
.AddRow("[b]:nail_polish: Supports ansi?[/]", $"{GetEmoji(AnsiConsole.Capabilities.SupportsAnsi)}")
|
||||
.AddRow("[b]:top_hat: Legacy console?[/]", $"{GetEmoji(AnsiConsole.Capabilities.LegacyConsole)}")
|
||||
.AddRow("[b]:left_right_arrow: Buffer width[/]", $"{AnsiConsole.Console.Width}")
|
||||
.AddRow("[b]:up_down_arrow: Buffer height[/]", $"{AnsiConsole.Console.Height}");
|
||||
.AddRow("[b]Color system[/]", $"{AnsiConsole.Capabilities.ColorSystem}")
|
||||
.AddRow("[b]Supports ansi?[/]", $"{YesNo(AnsiConsole.Capabilities.SupportsAnsi)}")
|
||||
.AddRow("[b]Legacy console?[/]", $"{YesNo(AnsiConsole.Capabilities.LegacyConsole)}")
|
||||
.AddRow("[b]Buffer width[/]", $"{AnsiConsole.Console.Width}")
|
||||
.AddRow("[b]Buffer height[/]", $"{AnsiConsole.Console.Height}");
|
||||
|
||||
AnsiConsole.Render(
|
||||
new Panel(grid)
|
||||
.SetHeader("Information"));
|
||||
}
|
||||
|
||||
private static string GetEmoji(bool value) => value
|
||||
? ":thumbs_up:"
|
||||
: ":thumbs_down:";
|
||||
private static string YesNo(bool value)
|
||||
{
|
||||
return value ? "Yes" : "No";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Title>Links</Title>
|
||||
<Description>Demonstrates how to render links in a console.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Spectre.Console;
|
||||
|
||||
namespace Links
|
||||
namespace LinkExample
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Title>Panels</Title>
|
||||
<Description>Demonstrates how to render items in panels.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace PanelExample
|
||||
AnsiConsole.Render(
|
||||
new Panel(
|
||||
new Panel(content)
|
||||
.SetBorder(Border.Rounded)));
|
||||
.SetBorder(BoxBorder.Rounded)));
|
||||
|
||||
// Left adjusted panel with text
|
||||
AnsiConsole.Render(
|
||||
@@ -35,7 +35,7 @@ namespace TableExample
|
||||
private static void RenderBigTable()
|
||||
{
|
||||
// Create the table.
|
||||
var table = new Table().SetBorder(Border.Rounded);
|
||||
var table = new Table().SetBorder(TableBorder.Rounded);
|
||||
table.AddColumn("[red underline]Foo[/]");
|
||||
table.AddColumn(new TableColumn("[blue]Bar[/]") { Alignment = Justify.Right, NoWrap = true });
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace TableExample
|
||||
private static void RenderNestedTable()
|
||||
{
|
||||
// Create simple table.
|
||||
var simple = new Table().SetBorder(Border.Rounded).SetBorderColor(Color.Red);
|
||||
var simple = new Table().SetBorder(TableBorder.Rounded).SetBorderColor(Color.Red);
|
||||
simple.AddColumn(new TableColumn("[u]Foo[/]").Centered());
|
||||
simple.AddColumn(new TableColumn("[u]Bar[/]"));
|
||||
simple.AddColumn(new TableColumn("[u]Baz[/]"));
|
||||
@@ -66,7 +66,7 @@ namespace TableExample
|
||||
simple.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", "");
|
||||
|
||||
// Create other table.
|
||||
var second = new Table().SetBorder(Border.Square).SetBorderColor(Color.Green);
|
||||
var second = new Table().SetBorder(TableBorder.Square).SetBorderColor(Color.Green);
|
||||
second.AddColumn(new TableColumn("[u]Foo[/]"));
|
||||
second.AddColumn(new TableColumn("[u]Bar[/]"));
|
||||
second.AddColumn(new TableColumn("[u]Baz[/]"));
|
||||
@@ -74,7 +74,7 @@ namespace TableExample
|
||||
second.AddRow(simple, new Text("Whaaat"), new Text("Lolz"));
|
||||
second.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", "");
|
||||
|
||||
var table = new Table().SetBorder(Border.Rounded);
|
||||
var table = new Table().SetBorder(TableBorder.Rounded);
|
||||
table.AddColumn(new TableColumn(new Panel("[u]Foo[/]").SetBorderColor(Color.Red)));
|
||||
table.AddColumn(new TableColumn(new Panel("[u]Bar[/]").SetBorderColor(Color.Green)));
|
||||
table.AddColumn(new TableColumn(new Panel("[u]Baz[/]").SetBorderColor(Color.Blue)));
|
||||
@@ -4,6 +4,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Title>Tables</Title>
|
||||
<Description>Demonstrates how to render tables in a console.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"projects": [ "src" ],
|
||||
"sdk": {
|
||||
"version": "3.1.301",
|
||||
"rollForward": "latestMajor"
|
||||
"rollForward": "latestPatch"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
using Spectre.Console.Tests.Tools;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
@@ -36,9 +37,9 @@ namespace Spectre.Console.Tests
|
||||
_writer?.Dispose();
|
||||
}
|
||||
|
||||
public void Write(string text, Style style)
|
||||
public void Write(Segment segment)
|
||||
{
|
||||
_console.Write(text, style);
|
||||
_console.Write(segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
@@ -40,9 +41,14 @@ namespace Spectre.Console.Tests
|
||||
Writer.Dispose();
|
||||
}
|
||||
|
||||
public void Write(string text, Style style)
|
||||
public void Write(Segment segment)
|
||||
{
|
||||
Writer.Write(text);
|
||||
if (segment is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(segment));
|
||||
}
|
||||
|
||||
Writer.Write(segment.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
210
src/Spectre.Console.Tests/Unit/BoxBorderTests.cs
Normal file
210
src/Spectre.Console.Tests/Unit/BoxBorderTests.cs
Normal file
@@ -0,0 +1,210 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Rendering;
|
||||
using Xunit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public sealed class BoxBorderTests
|
||||
{
|
||||
public sealed class NoBorder
|
||||
{
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxBorder.None.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.None);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var panel = Fixture.GetPanel().NoBorder();
|
||||
|
||||
// When
|
||||
console.Render(panel);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(3);
|
||||
console.Lines[0].ShouldBe(" Greeting ");
|
||||
console.Lines[1].ShouldBe(" Hello World ");
|
||||
console.Lines[2].ShouldBe(" ");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AsciiBorder
|
||||
{
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxBorder.Ascii.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Ascii);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var panel = Fixture.GetPanel().AsciiBorder();
|
||||
|
||||
// When
|
||||
console.Render(panel);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(3);
|
||||
console.Lines[0].ShouldBe("+-Greeting----+");
|
||||
console.Lines[1].ShouldBe("| Hello World |");
|
||||
console.Lines[2].ShouldBe("+-------------+");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DoubleBorder
|
||||
{
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxBorder.Double.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Double);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var panel = Fixture.GetPanel().DoubleBorder();
|
||||
|
||||
// When
|
||||
console.Render(panel);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(3);
|
||||
console.Lines[0].ShouldBe("╔═Greeting════╗");
|
||||
console.Lines[1].ShouldBe("║ Hello World ║");
|
||||
console.Lines[2].ShouldBe("╚═════════════╝");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HeavyBorder
|
||||
{
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxBorder.Heavy.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Square);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var panel = Fixture.GetPanel().HeavyBorder();
|
||||
|
||||
// When
|
||||
console.Render(panel);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(3);
|
||||
console.Lines[0].ShouldBe("┏━Greeting━━━━┓");
|
||||
console.Lines[1].ShouldBe("┃ Hello World ┃");
|
||||
console.Lines[2].ShouldBe("┗━━━━━━━━━━━━━┛");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RoundedBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxBorder.Rounded.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Square);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var panel = Fixture.GetPanel().RoundedBorder();
|
||||
|
||||
// When
|
||||
console.Render(panel);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(3);
|
||||
console.Lines[0].ShouldBe("╭─Greeting────╮");
|
||||
console.Lines[1].ShouldBe("│ Hello World │");
|
||||
console.Lines[2].ShouldBe("╰─────────────╯");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SquareBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = BoxBorder.Square.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(BoxBorder.Square);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var panel = Fixture.GetPanel().SquareBorder();
|
||||
|
||||
// When
|
||||
console.Render(panel);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(3);
|
||||
console.Lines[0].ShouldBe("┌─Greeting────┐");
|
||||
console.Lines[1].ShouldBe("│ Hello World │");
|
||||
console.Lines[2].ShouldBe("└─────────────┘");
|
||||
}
|
||||
}
|
||||
|
||||
private static class Fixture
|
||||
{
|
||||
public static Panel GetPanel()
|
||||
{
|
||||
return new Panel("Hello World")
|
||||
.SetHeader("Greeting");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
66
src/Spectre.Console.Tests/Unit/RecorderTests.cs
Normal file
66
src/Spectre.Console.Tests/Unit/RecorderTests.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public sealed class RecorderTests
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Export_Text_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var recorder = new Recorder(console);
|
||||
|
||||
recorder.Render(new Table()
|
||||
.AddColumns("Foo", "Bar", "Qux")
|
||||
.AddRow("Corgi", "Waldo", "Zap")
|
||||
.AddRow(new Panel("Hello World").RoundedBorder()));
|
||||
|
||||
// When
|
||||
var result = recorder.ExportText().Split(new[] { '\n' });
|
||||
|
||||
// Then
|
||||
result.Length.ShouldBe(8);
|
||||
result[0].ShouldBe("┌─────────────────┬───────┬─────┐");
|
||||
result[1].ShouldBe("│ Foo │ Bar │ Qux │");
|
||||
result[2].ShouldBe("├─────────────────┼───────┼─────┤");
|
||||
result[3].ShouldBe("│ Corgi │ Waldo │ Zap │");
|
||||
result[4].ShouldBe("│ ╭─────────────╮ │ │ │");
|
||||
result[5].ShouldBe("│ │ Hello World │ │ │ │");
|
||||
result[6].ShouldBe("│ ╰─────────────╯ │ │ │");
|
||||
result[7].ShouldBe("└─────────────────┴───────┴─────┘");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Export_Html_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var recorder = new Recorder(console);
|
||||
|
||||
recorder.Render(new Table()
|
||||
.AddColumns("[red on black]Foo[/]", "[green bold]Bar[/]", "[blue italic]Qux[/]")
|
||||
.AddRow("[invert underline]Corgi[/]", "[bold strikethrough]Waldo[/]", "[dim]Zap[/]")
|
||||
.AddRow(new Panel("[blue]Hello World[/]")
|
||||
.SetBorderColor(Color.Red).RoundedBorder()));
|
||||
|
||||
// When
|
||||
var html = recorder.ExportHtml();
|
||||
var result = html.Split(new[] { '\n' });
|
||||
|
||||
// Then
|
||||
result.Length.ShouldBe(10);
|
||||
result[0].ShouldBe("<pre style=\"font-size:90%;font-family:consolas,'Courier New',monospace\">");
|
||||
result[1].ShouldBe("<span>┌─────────────────┬───────┬─────┐</span>");
|
||||
result[2].ShouldBe("<span>│ </span><span style=\"color: #FF0000;background-color: #000000\">Foo</span><span> │ </span><span style=\"color: #008000;font-weight: bold;font-style: italic\">Bar</span><span> │ </span><span style=\"color: #0000FF\">Qux</span><span> │</span>");
|
||||
result[3].ShouldBe("<span>├─────────────────┼───────┼─────┤</span>");
|
||||
result[4].ShouldBe("<span>│ </span><span style=\"text-decoration: underline\">Corgi</span><span> │ </span><span style=\"font-weight: bold;font-style: italic;text-decoration: line-through\">Waldo</span><span> │ </span><span style=\"color: #7F7F7F\">Zap</span><span> │</span>");
|
||||
result[5].ShouldBe("<span>│ </span><span style=\"color: #FF0000\">╭─────────────╮</span><span> │ │ │</span>");
|
||||
result[6].ShouldBe("<span>│ </span><span style=\"color: #FF0000\">│</span><span> </span><span style=\"color: #0000FF\">Hello World</span><span> </span><span style=\"color: #FF0000\">│</span><span> │ │ │</span>");
|
||||
result[7].ShouldBe("<span>│ </span><span style=\"color: #FF0000\">╰─────────────╯</span><span> │ │ │</span>");
|
||||
result[8].ShouldBe("<span>└─────────────────┴───────┴─────┘</span>");
|
||||
result[9].ShouldBe("</pre>");
|
||||
}
|
||||
}
|
||||
}
|
||||
96
src/Spectre.Console.Tests/Unit/RowsTests.cs
Normal file
96
src/Spectre.Console.Tests/Unit/RowsTests.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using Shouldly;
|
||||
using Spectre.Console.Rendering;
|
||||
using Xunit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public sealed class RowsTests
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Render_Rows()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole(width: 60);
|
||||
var rows = new Rows(
|
||||
new IRenderable[]
|
||||
{
|
||||
new Markup("Hello"),
|
||||
new Table()
|
||||
.AddColumns("Foo", "Bar")
|
||||
.AddRow("Baz", "Qux"),
|
||||
new Markup("World"),
|
||||
});
|
||||
|
||||
// When
|
||||
console.Render(rows);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(7);
|
||||
console.Lines[0].ShouldBe("Hello");
|
||||
console.Lines[1].ShouldBe("┌─────┬─────┐");
|
||||
console.Lines[2].ShouldBe("│ Foo │ Bar │");
|
||||
console.Lines[3].ShouldBe("├─────┼─────┤");
|
||||
console.Lines[4].ShouldBe("│ Baz │ Qux │");
|
||||
console.Lines[5].ShouldBe("└─────┴─────┘");
|
||||
console.Lines[6].ShouldBe("World");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_Rows_Correctly_Inside_Other_Widget()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole(width: 60);
|
||||
var table = new Table()
|
||||
.AddColumns("Foo", "Bar")
|
||||
.AddRow("HELLO WORLD")
|
||||
.AddRow(
|
||||
new Rows(new IRenderable[]
|
||||
{
|
||||
new Markup("Hello"),
|
||||
new Markup("World"),
|
||||
}), new Text("Qux"));
|
||||
|
||||
// When
|
||||
console.Render(table);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(7);
|
||||
console.Lines[0].ShouldBe("┌─────────────┬─────┐");
|
||||
console.Lines[1].ShouldBe("│ Foo │ Bar │");
|
||||
console.Lines[2].ShouldBe("├─────────────┼─────┤");
|
||||
console.Lines[3].ShouldBe("│ HELLO WORLD │ │");
|
||||
console.Lines[4].ShouldBe("│ Hello │ Qux │");
|
||||
console.Lines[5].ShouldBe("│ World │ │");
|
||||
console.Lines[6].ShouldBe("└─────────────┴─────┘");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_Rows_Correctly_Inside_Other_Widget_When_Expanded()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole(width: 60);
|
||||
var table = new Table()
|
||||
.AddColumns("Foo", "Bar")
|
||||
.AddRow("HELLO WORLD")
|
||||
.AddRow(
|
||||
new Rows(new IRenderable[]
|
||||
{
|
||||
new Markup("Hello"),
|
||||
new Markup("World"),
|
||||
}).Expand(), new Text("Qux"));
|
||||
|
||||
// When
|
||||
console.Render(table);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(7);
|
||||
console.Lines[0].ShouldBe("┌────────────────────────────────────────────────────┬─────┐");
|
||||
console.Lines[1].ShouldBe("│ Foo │ Bar │");
|
||||
console.Lines[2].ShouldBe("├────────────────────────────────────────────────────┼─────┤");
|
||||
console.Lines[3].ShouldBe("│ HELLO WORLD │ │");
|
||||
console.Lines[4].ShouldBe("│ Hello │ Qux │");
|
||||
console.Lines[5].ShouldBe("│ World │ │");
|
||||
console.Lines[6].ShouldBe("└────────────────────────────────────────────────────┴─────┘");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using Xunit;
|
||||
|
||||
namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public sealed class BorderTests
|
||||
public sealed class TableBorderTests
|
||||
{
|
||||
public sealed class NoBorder
|
||||
{
|
||||
@@ -12,7 +12,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.None.Visible;
|
||||
var visibility = TableBorder.None.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeFalse();
|
||||
@@ -24,10 +24,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.None.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.None.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.None);
|
||||
border.ShouldBeSameAs(TableBorder.None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Ascii.Visible;
|
||||
var visibility = TableBorder.Ascii.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -67,10 +67,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Ascii.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.Ascii.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Ascii);
|
||||
border.ShouldBeSameAs(TableBorder.Ascii);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Ascii2.Visible;
|
||||
var visibility = TableBorder.Ascii2.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -113,10 +113,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Ascii2.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.Ascii2.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Ascii2);
|
||||
border.ShouldBeSameAs(TableBorder.Ascii2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.AsciiDoubleHead.Visible;
|
||||
var visibility = TableBorder.AsciiDoubleHead.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -159,10 +159,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.AsciiDoubleHead.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.AsciiDoubleHead.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.AsciiDoubleHead);
|
||||
border.ShouldBeSameAs(TableBorder.AsciiDoubleHead);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Square.Visible;
|
||||
var visibility = TableBorder.Square.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -205,10 +205,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Square.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.Square.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Square);
|
||||
border.ShouldBeSameAs(TableBorder.Square);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Rounded.Visible;
|
||||
var visibility = TableBorder.Rounded.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -251,10 +251,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Rounded.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.Rounded.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Square);
|
||||
border.ShouldBeSameAs(TableBorder.Square);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Minimal.Visible;
|
||||
var visibility = TableBorder.Minimal.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -297,10 +297,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Minimal.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.Minimal.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Minimal);
|
||||
border.ShouldBeSameAs(TableBorder.Minimal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,7 +331,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.MinimalHeavyHead.Visible;
|
||||
var visibility = TableBorder.MinimalHeavyHead.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -343,10 +343,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.MinimalHeavyHead.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.MinimalHeavyHead.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Minimal);
|
||||
border.ShouldBeSameAs(TableBorder.Minimal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.MinimalDoubleHead.Visible;
|
||||
var visibility = TableBorder.MinimalDoubleHead.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -389,10 +389,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.MinimalDoubleHead.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.MinimalDoubleHead.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.MinimalDoubleHead);
|
||||
border.ShouldBeSameAs(TableBorder.MinimalDoubleHead);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,7 +423,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Simple.Visible;
|
||||
var visibility = TableBorder.Simple.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -435,10 +435,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Simple.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.Simple.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Simple);
|
||||
border.ShouldBeSameAs(TableBorder.Simple);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +469,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Horizontal.Visible;
|
||||
var visibility = TableBorder.Horizontal.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -481,10 +481,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Horizontal.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.Horizontal.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Horizontal);
|
||||
border.ShouldBeSameAs(TableBorder.Horizontal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,7 +515,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.SimpleHeavy.Visible;
|
||||
var visibility = TableBorder.SimpleHeavy.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -527,10 +527,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.SimpleHeavy.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.SimpleHeavy.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Simple);
|
||||
border.ShouldBeSameAs(TableBorder.Simple);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -561,7 +561,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Heavy.Visible;
|
||||
var visibility = TableBorder.Heavy.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -573,10 +573,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Heavy.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.Heavy.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Square);
|
||||
border.ShouldBeSameAs(TableBorder.Square);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -607,7 +607,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.HeavyEdge.Visible;
|
||||
var visibility = TableBorder.HeavyEdge.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -619,10 +619,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.HeavyEdge.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.HeavyEdge.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Square);
|
||||
border.ShouldBeSameAs(TableBorder.Square);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,7 +653,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.HeavyHead.Visible;
|
||||
var visibility = TableBorder.HeavyHead.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -665,10 +665,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.HeavyHead.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.HeavyHead.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Square);
|
||||
border.ShouldBeSameAs(TableBorder.Square);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,7 +699,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Double.Visible;
|
||||
var visibility = TableBorder.Double.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -711,10 +711,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Double.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.Double.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Double);
|
||||
border.ShouldBeSameAs(TableBorder.Double);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -745,7 +745,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.DoubleEdge.Visible;
|
||||
var visibility = TableBorder.DoubleEdge.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
@@ -757,10 +757,10 @@ namespace Spectre.Console.Tests.Unit
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.DoubleEdge.GetSafeBorder(safe: true);
|
||||
var border = TableBorder.DoubleEdge.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.DoubleEdge);
|
||||
border.ShouldBeSameAs(TableBorder.DoubleEdge);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,12 +785,119 @@ namespace Spectre.Console.Tests.Unit
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MarkdownBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = TableBorder.Markdown.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = TableBorder.Markdown.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(TableBorder.Markdown);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().MarkdownBorder();
|
||||
|
||||
// When
|
||||
console.Render(table);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(6);
|
||||
console.Lines[0].ShouldBe(" ");
|
||||
console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
|
||||
console.Lines[2].ShouldBe("| -------- | -------- |");
|
||||
console.Lines[3].ShouldBe("| Cell | Cell |");
|
||||
console.Lines[4].ShouldBe("| Cell | Cell |");
|
||||
console.Lines[5].ShouldBe(" ");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_Left_Aligned_Table_Columns_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable(header2: Justify.Left).MarkdownBorder();
|
||||
|
||||
// When
|
||||
console.Render(table);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(6);
|
||||
console.Lines[0].ShouldBe(" ");
|
||||
console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
|
||||
console.Lines[2].ShouldBe("| -------- | :------- |");
|
||||
console.Lines[3].ShouldBe("| Cell | Cell |");
|
||||
console.Lines[4].ShouldBe("| Cell | Cell |");
|
||||
console.Lines[5].ShouldBe(" ");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_Center_Aligned_Table_Columns_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable(header2: Justify.Center).MarkdownBorder();
|
||||
|
||||
// When
|
||||
console.Render(table);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(6);
|
||||
console.Lines[0].ShouldBe(" ");
|
||||
console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
|
||||
console.Lines[2].ShouldBe("| -------- | :------: |");
|
||||
console.Lines[3].ShouldBe("| Cell | Cell |");
|
||||
console.Lines[4].ShouldBe("| Cell | Cell |");
|
||||
console.Lines[5].ShouldBe(" ");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_Right_Aligned_Table_Columns_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable(header2: Justify.Right).MarkdownBorder();
|
||||
|
||||
// When
|
||||
console.Render(table);
|
||||
|
||||
// Then
|
||||
console.Lines.Count.ShouldBe(6);
|
||||
console.Lines[0].ShouldBe(" ");
|
||||
console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
|
||||
console.Lines[2].ShouldBe("| -------- | -------: |");
|
||||
console.Lines[3].ShouldBe("| Cell | Cell |");
|
||||
console.Lines[4].ShouldBe("| Cell | Cell |");
|
||||
console.Lines[5].ShouldBe(" ");
|
||||
}
|
||||
}
|
||||
|
||||
private static class Fixture
|
||||
{
|
||||
public static Table GetTable()
|
||||
public static Table GetTable(Justify? header1 = null, Justify? header2 = null)
|
||||
{
|
||||
var table = new Table();
|
||||
table.AddColumns("Header 1", "Header 2");
|
||||
table.AddColumn("Header 1", c => c.Alignment = header1);
|
||||
table.AddColumn("Header 2", c => c.Alignment = header2);
|
||||
table.AddRow("Cell", "Cell");
|
||||
table.AddRow("Cell", "Cell");
|
||||
return table;
|
||||
@@ -173,7 +173,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
// A simple table
|
||||
var console = new PlainConsole(width: 80);
|
||||
var table = new Table() { Border = Border.Rounded };
|
||||
var table = new Table() { Border = TableBorder.Rounded };
|
||||
table.AddColumn("Foo");
|
||||
table.AddColumn("Bar");
|
||||
table.AddColumn(new TableColumn("Baz") { Alignment = Justify.Right });
|
||||
@@ -183,7 +183,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
// Render a table in some panels.
|
||||
console.Render(new Panel(new Panel(table)
|
||||
{
|
||||
Border = Border.Ascii,
|
||||
Border = BoxBorder.Ascii,
|
||||
}));
|
||||
|
||||
// Then
|
||||
@@ -255,7 +255,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole(width: 80);
|
||||
var table = new Table { Border = Border.Ascii };
|
||||
var table = new Table { Border = TableBorder.Ascii };
|
||||
table.AddColumns("Foo", "Bar", "Baz");
|
||||
table.AddRow("Qux", "Corgi", "Waldo");
|
||||
table.AddRow("Grault", "Garply", "Fred");
|
||||
@@ -278,7 +278,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole(width: 80);
|
||||
var table = new Table { Border = Border.Rounded };
|
||||
var table = new Table { Border = TableBorder.Rounded };
|
||||
table.AddColumns("Foo", "Bar", "Baz");
|
||||
table.AddRow("Qux", "Corgi", "Waldo");
|
||||
table.AddRow("Grault", "Garply", "Fred");
|
||||
@@ -301,7 +301,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole(width: 80);
|
||||
var table = new Table { Border = Border.None };
|
||||
var table = new Table { Border = TableBorder.None };
|
||||
table.AddColumns("Foo", "Bar", "Baz");
|
||||
table.AddRow("Qux", "Corgi", "Waldo");
|
||||
table.AddRow("Grault", "Garply", "Fred");
|
||||
|
||||
@@ -17,11 +17,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{F0575243-121F-4DEE-9F6B-246E26DC0844}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Table", "..\examples\Table\Table.csproj", "{94ECCBA8-7EBF-4B53-8379-52EB2327417E}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tables", "..\examples\Tables\Tables.csproj", "{94ECCBA8-7EBF-4B53-8379-52EB2327417E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Panel", "..\examples\Panel\Panel.csproj", "{BFF37228-B376-4ADD-9657-4E501F929713}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Panels", "..\examples\Panels\Panels.csproj", "{BFF37228-B376-4ADD-9657-4E501F929713}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grid", "..\examples\Grid\Grid.csproj", "{C7FF6FDB-FB59-4517-8669-521C96AB7323}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grids", "..\examples\Grids\Grids.csproj", "{C7FF6FDB-FB59-4517-8669-521C96AB7323}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Colors", "..\examples\Colors\Colors.csproj", "{1F51C55C-BA4C-4856-9001-0F7924FFB179}"
|
||||
EndProject
|
||||
@@ -33,7 +33,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Borders", "..\examples\Bord
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Links", "..\examples\Links\Links.csproj", "{6AF8C93B-AA41-4F44-8B1B-B8D166576174}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emojis", "..\examples\Emojis\Emojis.csproj", "{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emojis", "..\examples\Emojis\Emojis.csproj", "{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
||||
67
src/Spectre.Console/AnsiConsole.Recording.cs
Normal file
67
src/Spectre.Console/AnsiConsole.Recording.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// A console capable of writing ANSI escape sequences.
|
||||
/// </summary>
|
||||
public static partial class AnsiConsole
|
||||
{
|
||||
/// <summary>
|
||||
/// Starts recording the console output.
|
||||
/// </summary>
|
||||
public static void Record()
|
||||
{
|
||||
_recorder = new Recorder(_console.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports all recorded console output as text.
|
||||
/// </summary>
|
||||
/// <returns>The recorded output as text.</returns>
|
||||
public static string ExportText()
|
||||
{
|
||||
if (_recorder == null)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot export text since a recording hasn't been started.");
|
||||
}
|
||||
|
||||
return _recorder.ExportText();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports all recorded console output as HTML.
|
||||
/// </summary>
|
||||
/// <returns>The recorded output as HTML.</returns>
|
||||
public static string ExportHtml()
|
||||
{
|
||||
if (_recorder == null)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot export HTML since a recording hasn't been started.");
|
||||
}
|
||||
|
||||
return _recorder.ExportHtml();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports all recorded console output using a custom encoder.
|
||||
/// </summary>
|
||||
/// <param name="encoder">The encoder to use.</param>
|
||||
/// <returns>The recorded output.</returns>
|
||||
public static string ExportCustom(IAnsiConsoleEncoder encoder)
|
||||
{
|
||||
if (_recorder == null)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot export HTML since a recording hasn't been started.");
|
||||
}
|
||||
|
||||
if (encoder is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(encoder));
|
||||
}
|
||||
|
||||
return _recorder.Export(encoder);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,10 +21,12 @@ namespace Spectre.Console
|
||||
return console;
|
||||
});
|
||||
|
||||
private static Recorder? _recorder;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying <see cref="IAnsiConsole"/>.
|
||||
/// </summary>
|
||||
public static IAnsiConsole Console => _console.Value;
|
||||
public static IAnsiConsole Console => _recorder ?? _console.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the console's capabilities.
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents another old school ASCII border.
|
||||
/// </summary>
|
||||
public sealed class Ascii2Border : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => "+",
|
||||
BorderPart.HeaderTop => "-",
|
||||
BorderPart.HeaderTopSeparator => "+",
|
||||
BorderPart.HeaderTopRight => "+",
|
||||
BorderPart.HeaderLeft => "|",
|
||||
BorderPart.HeaderSeparator => "|",
|
||||
BorderPart.HeaderRight => "|",
|
||||
BorderPart.HeaderBottomLeft => "|",
|
||||
BorderPart.HeaderBottom => "-",
|
||||
BorderPart.HeaderBottomSeparator => "+",
|
||||
BorderPart.HeaderBottomRight => "|",
|
||||
BorderPart.CellLeft => "|",
|
||||
BorderPart.CellSeparator => "|",
|
||||
BorderPart.CellRight => "|",
|
||||
BorderPart.FooterBottomLeft => "+",
|
||||
BorderPart.FooterBottom => "-",
|
||||
BorderPart.FooterBottomSeparator => "+",
|
||||
BorderPart.FooterBottomRight => "+",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an old school ASCII border.
|
||||
/// </summary>
|
||||
public sealed class AsciiBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => "+",
|
||||
BorderPart.HeaderTop => "-",
|
||||
BorderPart.HeaderTopSeparator => "-",
|
||||
BorderPart.HeaderTopRight => "+",
|
||||
BorderPart.HeaderLeft => "|",
|
||||
BorderPart.HeaderSeparator => "|",
|
||||
BorderPart.HeaderRight => "|",
|
||||
BorderPart.HeaderBottomLeft => "|",
|
||||
BorderPart.HeaderBottom => "-",
|
||||
BorderPart.HeaderBottomSeparator => "+",
|
||||
BorderPart.HeaderBottomRight => "|",
|
||||
BorderPart.CellLeft => "|",
|
||||
BorderPart.CellSeparator => "|",
|
||||
BorderPart.CellRight => "|",
|
||||
BorderPart.FooterBottomLeft => "+",
|
||||
BorderPart.FooterBottom => "-",
|
||||
BorderPart.FooterBottomSeparator => "-",
|
||||
BorderPart.FooterBottomRight => "+",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an old school ASCII border with a double header border.
|
||||
/// </summary>
|
||||
public sealed class AsciiDoubleHeadBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => "+",
|
||||
BorderPart.HeaderTop => "-",
|
||||
BorderPart.HeaderTopSeparator => "+",
|
||||
BorderPart.HeaderTopRight => "+",
|
||||
BorderPart.HeaderLeft => "|",
|
||||
BorderPart.HeaderSeparator => "|",
|
||||
BorderPart.HeaderRight => "|",
|
||||
BorderPart.HeaderBottomLeft => "|",
|
||||
BorderPart.HeaderBottom => "=",
|
||||
BorderPart.HeaderBottomSeparator => "+",
|
||||
BorderPart.HeaderBottomRight => "|",
|
||||
BorderPart.CellLeft => "|",
|
||||
BorderPart.CellSeparator => "|",
|
||||
BorderPart.CellRight => "|",
|
||||
BorderPart.FooterBottomLeft => "+",
|
||||
BorderPart.FooterBottom => "-",
|
||||
BorderPart.FooterBottomSeparator => "+",
|
||||
BorderPart.FooterBottomRight => "+",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a double border.
|
||||
/// </summary>
|
||||
public sealed class DoubleBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => "╔",
|
||||
BorderPart.HeaderTop => "═",
|
||||
BorderPart.HeaderTopSeparator => "╦",
|
||||
BorderPart.HeaderTopRight => "╗",
|
||||
BorderPart.HeaderLeft => "║",
|
||||
BorderPart.HeaderSeparator => "║",
|
||||
BorderPart.HeaderRight => "║",
|
||||
BorderPart.HeaderBottomLeft => "╠",
|
||||
BorderPart.HeaderBottom => "═",
|
||||
BorderPart.HeaderBottomSeparator => "╬",
|
||||
BorderPart.HeaderBottomRight => "╣",
|
||||
BorderPart.CellLeft => "║",
|
||||
BorderPart.CellSeparator => "║",
|
||||
BorderPart.CellRight => "║",
|
||||
BorderPart.FooterBottomLeft => "╚",
|
||||
BorderPart.FooterBottom => "═",
|
||||
BorderPart.FooterBottomSeparator => "╩",
|
||||
BorderPart.FooterBottomRight => "╝",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a border with a double edge.
|
||||
/// </summary>
|
||||
public sealed class DoubleEdgeBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => "╔",
|
||||
BorderPart.HeaderTop => "═",
|
||||
BorderPart.HeaderTopSeparator => "╤",
|
||||
BorderPart.HeaderTopRight => "╗",
|
||||
BorderPart.HeaderLeft => "║",
|
||||
BorderPart.HeaderSeparator => "│",
|
||||
BorderPart.HeaderRight => "║",
|
||||
BorderPart.HeaderBottomLeft => "╟",
|
||||
BorderPart.HeaderBottom => "─",
|
||||
BorderPart.HeaderBottomSeparator => "┼",
|
||||
BorderPart.HeaderBottomRight => "╢",
|
||||
BorderPart.CellLeft => "║",
|
||||
BorderPart.CellSeparator => "│",
|
||||
BorderPart.CellRight => "║",
|
||||
BorderPart.FooterBottomLeft => "╚",
|
||||
BorderPart.FooterBottom => "═",
|
||||
BorderPart.FooterBottomSeparator => "╧",
|
||||
BorderPart.FooterBottomRight => "╝",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a heavy border.
|
||||
/// </summary>
|
||||
public sealed class HeavyBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override Border? SafeBorder => Border.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => "┏",
|
||||
BorderPart.HeaderTop => "━",
|
||||
BorderPart.HeaderTopSeparator => "┳",
|
||||
BorderPart.HeaderTopRight => "┓",
|
||||
BorderPart.HeaderLeft => "┃",
|
||||
BorderPart.HeaderSeparator => "┃",
|
||||
BorderPart.HeaderRight => "┃",
|
||||
BorderPart.HeaderBottomLeft => "┣",
|
||||
BorderPart.HeaderBottom => "━",
|
||||
BorderPart.HeaderBottomSeparator => "╋",
|
||||
BorderPart.HeaderBottomRight => "┫",
|
||||
BorderPart.CellLeft => "┃",
|
||||
BorderPart.CellSeparator => "┃",
|
||||
BorderPart.CellRight => "┃",
|
||||
BorderPart.FooterBottomLeft => "┗",
|
||||
BorderPart.FooterBottom => "━",
|
||||
BorderPart.FooterBottomSeparator => "┻",
|
||||
BorderPart.FooterBottomRight => "┛",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a border with a heavy edge.
|
||||
/// </summary>
|
||||
public sealed class HeavyEdgeBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override Border? SafeBorder => Border.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => "┏",
|
||||
BorderPart.HeaderTop => "━",
|
||||
BorderPart.HeaderTopSeparator => "┯",
|
||||
BorderPart.HeaderTopRight => "┓",
|
||||
BorderPart.HeaderLeft => "┃",
|
||||
BorderPart.HeaderSeparator => "│",
|
||||
BorderPart.HeaderRight => "┃",
|
||||
BorderPart.HeaderBottomLeft => "┠",
|
||||
BorderPart.HeaderBottom => "─",
|
||||
BorderPart.HeaderBottomSeparator => "┼",
|
||||
BorderPart.HeaderBottomRight => "┨",
|
||||
BorderPart.CellLeft => "┃",
|
||||
BorderPart.CellSeparator => "│",
|
||||
BorderPart.CellRight => "┃",
|
||||
BorderPart.FooterBottomLeft => "┗",
|
||||
BorderPart.FooterBottom => "━",
|
||||
BorderPart.FooterBottomSeparator => "┷",
|
||||
BorderPart.FooterBottomRight => "┛",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a border with a heavy header.
|
||||
/// </summary>
|
||||
public sealed class HeavyHeadBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override Border? SafeBorder => Border.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => "┏",
|
||||
BorderPart.HeaderTop => "━",
|
||||
BorderPart.HeaderTopSeparator => "┳",
|
||||
BorderPart.HeaderTopRight => "┓",
|
||||
BorderPart.HeaderLeft => "┃",
|
||||
BorderPart.HeaderSeparator => "┃",
|
||||
BorderPart.HeaderRight => "┃",
|
||||
BorderPart.HeaderBottomLeft => "┡",
|
||||
BorderPart.HeaderBottom => "━",
|
||||
BorderPart.HeaderBottomSeparator => "╇",
|
||||
BorderPart.HeaderBottomRight => "┩",
|
||||
BorderPart.CellLeft => "│",
|
||||
BorderPart.CellSeparator => "│",
|
||||
BorderPart.CellRight => "│",
|
||||
BorderPart.FooterBottomLeft => "└",
|
||||
BorderPart.FooterBottom => "─",
|
||||
BorderPart.FooterBottomSeparator => "┴",
|
||||
BorderPart.FooterBottomRight => "┘",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a horizontal border.
|
||||
/// </summary>
|
||||
public sealed class HorizontalBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => "─",
|
||||
BorderPart.HeaderTop => "─",
|
||||
BorderPart.HeaderTopSeparator => "─",
|
||||
BorderPart.HeaderTopRight => "─",
|
||||
BorderPart.HeaderLeft => " ",
|
||||
BorderPart.HeaderSeparator => " ",
|
||||
BorderPart.HeaderRight => " ",
|
||||
BorderPart.HeaderBottomLeft => "─",
|
||||
BorderPart.HeaderBottom => "─",
|
||||
BorderPart.HeaderBottomSeparator => "─",
|
||||
BorderPart.HeaderBottomRight => "─",
|
||||
BorderPart.CellLeft => " ",
|
||||
BorderPart.CellSeparator => " ",
|
||||
BorderPart.CellRight => " ",
|
||||
BorderPart.FooterBottomLeft => "─",
|
||||
BorderPart.FooterBottom => "─",
|
||||
BorderPart.FooterBottomSeparator => "─",
|
||||
BorderPart.FooterBottomRight => "─",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a minimal border.
|
||||
/// </summary>
|
||||
public sealed class MinimalBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => " ",
|
||||
BorderPart.HeaderTop => " ",
|
||||
BorderPart.HeaderTopSeparator => " ",
|
||||
BorderPart.HeaderTopRight => " ",
|
||||
BorderPart.HeaderLeft => " ",
|
||||
BorderPart.HeaderSeparator => "│",
|
||||
BorderPart.HeaderRight => " ",
|
||||
BorderPart.HeaderBottomLeft => " ",
|
||||
BorderPart.HeaderBottom => "─",
|
||||
BorderPart.HeaderBottomSeparator => "┼",
|
||||
BorderPart.HeaderBottomRight => " ",
|
||||
BorderPart.CellLeft => " ",
|
||||
BorderPart.CellSeparator => "│",
|
||||
BorderPart.CellRight => " ",
|
||||
BorderPart.FooterBottomLeft => " ",
|
||||
BorderPart.FooterBottom => " ",
|
||||
BorderPart.FooterBottomSeparator => " ",
|
||||
BorderPart.FooterBottomRight => " ",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a minimal border with a double header border.
|
||||
/// </summary>
|
||||
public sealed class MinimalDoubleHeadBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => " ",
|
||||
BorderPart.HeaderTop => " ",
|
||||
BorderPart.HeaderTopSeparator => " ",
|
||||
BorderPart.HeaderTopRight => " ",
|
||||
BorderPart.HeaderLeft => " ",
|
||||
BorderPart.HeaderSeparator => "│",
|
||||
BorderPart.HeaderRight => " ",
|
||||
BorderPart.HeaderBottomLeft => " ",
|
||||
BorderPart.HeaderBottom => "═",
|
||||
BorderPart.HeaderBottomSeparator => "╪",
|
||||
BorderPart.HeaderBottomRight => " ",
|
||||
BorderPart.CellLeft => " ",
|
||||
BorderPart.CellSeparator => "│",
|
||||
BorderPart.CellRight => " ",
|
||||
BorderPart.FooterBottomLeft => " ",
|
||||
BorderPart.FooterBottom => " ",
|
||||
BorderPart.FooterBottomSeparator => " ",
|
||||
BorderPart.FooterBottomRight => " ",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a minimal border with a heavy header.
|
||||
/// </summary>
|
||||
public sealed class MinimalHeavyHeadBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override Border? SafeBorder => Border.Minimal;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => " ",
|
||||
BorderPart.HeaderTop => " ",
|
||||
BorderPart.HeaderTopSeparator => " ",
|
||||
BorderPart.HeaderTopRight => " ",
|
||||
BorderPart.HeaderLeft => " ",
|
||||
BorderPart.HeaderSeparator => "│",
|
||||
BorderPart.HeaderRight => " ",
|
||||
BorderPart.HeaderBottomLeft => " ",
|
||||
BorderPart.HeaderBottom => "━",
|
||||
BorderPart.HeaderBottomSeparator => "┿",
|
||||
BorderPart.HeaderBottomRight => " ",
|
||||
BorderPart.CellLeft => " ",
|
||||
BorderPart.CellSeparator => "│",
|
||||
BorderPart.CellRight => " ",
|
||||
BorderPart.FooterBottomLeft => " ",
|
||||
BorderPart.FooterBottom => " ",
|
||||
BorderPart.FooterBottomSeparator => " ",
|
||||
BorderPart.FooterBottomRight => " ",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a rounded border.
|
||||
/// </summary>
|
||||
public sealed class RoundedBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override Border? SafeBorder { get; } = Border.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => "╭",
|
||||
BorderPart.HeaderTop => "─",
|
||||
BorderPart.HeaderTopSeparator => "┬",
|
||||
BorderPart.HeaderTopRight => "╮",
|
||||
BorderPart.HeaderLeft => "│",
|
||||
BorderPart.HeaderSeparator => "│",
|
||||
BorderPart.HeaderRight => "│",
|
||||
BorderPart.HeaderBottomLeft => "├",
|
||||
BorderPart.HeaderBottom => "─",
|
||||
BorderPart.HeaderBottomSeparator => "┼",
|
||||
BorderPart.HeaderBottomRight => "┤",
|
||||
BorderPart.CellLeft => "│",
|
||||
BorderPart.CellSeparator => "│",
|
||||
BorderPart.CellRight => "│",
|
||||
BorderPart.FooterBottomLeft => "╰",
|
||||
BorderPart.FooterBottom => "─",
|
||||
BorderPart.FooterBottomSeparator => "┴",
|
||||
BorderPart.FooterBottomRight => "╯",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a simple border.
|
||||
/// </summary>
|
||||
public sealed class SimpleBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => " ",
|
||||
BorderPart.HeaderTop => " ",
|
||||
BorderPart.HeaderTopSeparator => " ",
|
||||
BorderPart.HeaderTopRight => " ",
|
||||
BorderPart.HeaderLeft => " ",
|
||||
BorderPart.HeaderSeparator => " ",
|
||||
BorderPart.HeaderRight => " ",
|
||||
BorderPart.HeaderBottomLeft => "─",
|
||||
BorderPart.HeaderBottom => "─",
|
||||
BorderPart.HeaderBottomSeparator => "─",
|
||||
BorderPart.HeaderBottomRight => "─",
|
||||
BorderPart.CellLeft => " ",
|
||||
BorderPart.CellSeparator => " ",
|
||||
BorderPart.CellRight => " ",
|
||||
BorderPart.FooterBottomLeft => " ",
|
||||
BorderPart.FooterBottom => " ",
|
||||
BorderPart.FooterBottomSeparator => " ",
|
||||
BorderPart.FooterBottomRight => " ",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a simple border with heavy lines.
|
||||
/// </summary>
|
||||
public sealed class SimpleHeavyBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override Border? SafeBorder => Border.Simple;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => " ",
|
||||
BorderPart.HeaderTop => " ",
|
||||
BorderPart.HeaderTopSeparator => " ",
|
||||
BorderPart.HeaderTopRight => " ",
|
||||
BorderPart.HeaderLeft => " ",
|
||||
BorderPart.HeaderSeparator => " ",
|
||||
BorderPart.HeaderRight => " ",
|
||||
BorderPart.HeaderBottomLeft => "━",
|
||||
BorderPart.HeaderBottom => "━",
|
||||
BorderPart.HeaderBottomSeparator => "━",
|
||||
BorderPart.HeaderBottomRight => "━",
|
||||
BorderPart.CellLeft => " ",
|
||||
BorderPart.CellSeparator => " ",
|
||||
BorderPart.CellRight => " ",
|
||||
BorderPart.FooterBottomLeft => " ",
|
||||
BorderPart.FooterBottom => " ",
|
||||
BorderPart.FooterBottomSeparator => " ",
|
||||
BorderPart.FooterBottomRight => " ",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a square border.
|
||||
/// </summary>
|
||||
public sealed class SquareBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BorderPart.HeaderTopLeft => "┌",
|
||||
BorderPart.HeaderTop => "─",
|
||||
BorderPart.HeaderTopSeparator => "┬",
|
||||
BorderPart.HeaderTopRight => "┐",
|
||||
BorderPart.HeaderLeft => "│",
|
||||
BorderPart.HeaderSeparator => "│",
|
||||
BorderPart.HeaderRight => "│",
|
||||
BorderPart.HeaderBottomLeft => "├",
|
||||
BorderPart.HeaderBottom => "─",
|
||||
BorderPart.HeaderBottomSeparator => "┼",
|
||||
BorderPart.HeaderBottomRight => "┤",
|
||||
BorderPart.CellLeft => "│",
|
||||
BorderPart.CellSeparator => "│",
|
||||
BorderPart.CellRight => "│",
|
||||
BorderPart.FooterBottomLeft => "└",
|
||||
BorderPart.FooterBottom => "─",
|
||||
BorderPart.FooterBottomSeparator => "┴",
|
||||
BorderPart.FooterBottomRight => "┘",
|
||||
_ => throw new InvalidOperationException("Unknown box part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
42
src/Spectre.Console/BoxBorder.Known.cs
Normal file
42
src/Spectre.Console/BoxBorder.Known.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a border.
|
||||
/// </summary>
|
||||
public abstract partial class BoxBorder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets an invisible border.
|
||||
/// </summary>
|
||||
public static BoxBorder None { get; } = new NoBoxBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an ASCII border.
|
||||
/// </summary>
|
||||
public static BoxBorder Ascii { get; } = new AsciiBoxBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a double border.
|
||||
/// </summary>
|
||||
[SuppressMessage("Naming", "CA1720:Identifier contains type name")]
|
||||
public static BoxBorder Double { get; } = new DoubleBoxBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a heavy border.
|
||||
/// </summary>
|
||||
public static BoxBorder Heavy { get; } = new HeavyBoxBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a rounded border.
|
||||
/// </summary>
|
||||
public static BoxBorder Rounded { get; } = new RoundedBoxBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a square border.
|
||||
/// </summary>
|
||||
public static BoxBorder Square { get; } = new SquareBoxBorder();
|
||||
}
|
||||
}
|
||||
@@ -9,45 +9,40 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Represents a border.
|
||||
/// </summary>
|
||||
public abstract partial class Border
|
||||
public abstract partial class BoxBorder
|
||||
{
|
||||
private readonly Dictionary<BorderPart, string> _lookup;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether or not the border is visible.
|
||||
/// </summary>
|
||||
public virtual bool Visible { get; } = true;
|
||||
private readonly Dictionary<BoxBorderPart, string> _lookup;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the safe border for this border or <c>null</c> if none exist.
|
||||
/// </summary>
|
||||
public virtual Border? SafeBorder { get; }
|
||||
public virtual BoxBorder? SafeBorder { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Border"/> class.
|
||||
/// Initializes a new instance of the <see cref="BoxBorder"/> class.
|
||||
/// </summary>
|
||||
protected Border()
|
||||
protected BoxBorder()
|
||||
{
|
||||
_lookup = Initialize();
|
||||
}
|
||||
|
||||
private Dictionary<BorderPart, string> Initialize()
|
||||
private Dictionary<BoxBorderPart, string> Initialize()
|
||||
{
|
||||
var lookup = new Dictionary<BorderPart, string>();
|
||||
foreach (BorderPart? part in Enum.GetValues(typeof(BorderPart)))
|
||||
var lookup = new Dictionary<BoxBorderPart, string>();
|
||||
foreach (BoxBorderPart? part in Enum.GetValues(typeof(BoxBorderPart)))
|
||||
{
|
||||
if (part == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var text = GetBoxPart(part.Value);
|
||||
var text = GetBorderPart(part.Value);
|
||||
if (text.Length > 1)
|
||||
{
|
||||
throw new InvalidOperationException("A box part cannot contain more than one character.");
|
||||
}
|
||||
|
||||
lookup.Add(part.Value, GetBoxPart(part.Value));
|
||||
lookup.Add(part.Value, GetBorderPart(part.Value));
|
||||
}
|
||||
|
||||
return lookup;
|
||||
@@ -59,10 +54,10 @@ namespace Spectre.Console
|
||||
/// <param name="part">The part to get a string representation for.</param>
|
||||
/// <param name="count">The number of repetitions.</param>
|
||||
/// <returns>A string representation of the specified border part.</returns>
|
||||
public string GetPart(BorderPart part, int count)
|
||||
public string GetPart(BoxBorderPart part, int count)
|
||||
{
|
||||
// TODO: This need some optimization...
|
||||
return string.Join(string.Empty, Enumerable.Repeat(GetBoxPart(part)[0], count));
|
||||
return string.Join(string.Empty, Enumerable.Repeat(GetBorderPart(part)[0], count));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -70,7 +65,7 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
/// <param name="part">The part to get a string representation for.</param>
|
||||
/// <returns>A string representation of the specified border part.</returns>
|
||||
public string GetPart(BorderPart part)
|
||||
public string GetPart(BoxBorderPart part)
|
||||
{
|
||||
return _lookup[part].ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
@@ -80,6 +75,6 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
/// <param name="part">The part to get the character representation for.</param>
|
||||
/// <returns>A character representation of the specified border part.</returns>
|
||||
protected abstract string GetBoxPart(BorderPart part);
|
||||
protected abstract string GetBorderPart(BoxBorderPart part);
|
||||
}
|
||||
}
|
||||
@@ -60,6 +60,35 @@ namespace Spectre.Console
|
||||
Number = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Blends two colors.
|
||||
/// </summary>
|
||||
/// <param name="other">The other color.</param>
|
||||
/// <param name="factor">The blend factor.</param>
|
||||
/// <returns>The resulting color.</returns>
|
||||
public Color Blend(Color other, float factor)
|
||||
{
|
||||
// https://github.com/willmcgugan/rich/blob/f092b1d04252e6f6812021c0f415dd1d7be6a16a/rich/color.py#L494
|
||||
return new Color(
|
||||
(byte)(R + ((other.R - R) * factor)),
|
||||
(byte)(G + ((other.G - G) * factor)),
|
||||
(byte)(B + ((other.B - B) * factor)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hexadecimal representation of the color.
|
||||
/// </summary>
|
||||
/// <returns>The hexadecimal representation of the color.</returns>
|
||||
public string ToHex()
|
||||
{
|
||||
return string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"{0}{1}{2}",
|
||||
R.ToString("X2", CultureInfo.InvariantCulture),
|
||||
G.ToString("X2", CultureInfo.InvariantCulture),
|
||||
B.ToString("X2", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
@@ -7,6 +8,32 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
public static partial class AnsiConsoleExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a recorder for the specified console.
|
||||
/// </summary>
|
||||
/// <param name="console">The console to record.</param>
|
||||
/// <returns>A recorder for the specified console.</returns>
|
||||
public static Recorder CreateRecorder(this IAnsiConsole console)
|
||||
{
|
||||
return new Recorder(console);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the specified string value to the console.
|
||||
/// </summary>
|
||||
/// <param name="console">The console to write to.</param>
|
||||
/// <param name="text">The text to write.</param>
|
||||
/// <param name="style">The text style.</param>
|
||||
public static void Write(this IAnsiConsole console, string text, Style style)
|
||||
{
|
||||
if (console is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(console));
|
||||
}
|
||||
|
||||
console.Write(new Segment(text, style));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an empty line to the console.
|
||||
/// </summary>
|
||||
@@ -34,7 +61,7 @@ namespace Spectre.Console
|
||||
throw new ArgumentNullException(nameof(console));
|
||||
}
|
||||
|
||||
console.Write(text, style);
|
||||
console.Write(new Segment(text, style));
|
||||
console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using System;
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="Border"/>.
|
||||
/// Contains extension methods for <see cref="TableBorder"/>.
|
||||
/// </summary>
|
||||
public static class BorderExtensions
|
||||
{
|
||||
@@ -13,7 +13,7 @@ namespace Spectre.Console.Rendering
|
||||
/// <param name="border">The border to get the safe border for.</param>
|
||||
/// <param name="safe">Whether or not to return the safe border.</param>
|
||||
/// <returns>The safe border if one exist, otherwise the original border.</returns>
|
||||
public static Border GetSafeBorder(this Border border, bool safe)
|
||||
public static TableBorder GetSafeBorder(this TableBorder border, bool safe)
|
||||
{
|
||||
if (border is null)
|
||||
{
|
||||
|
||||
31
src/Spectre.Console/Extensions/BoxExtensions.cs
Normal file
31
src/Spectre.Console/Extensions/BoxExtensions.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="BoxBorder"/>.
|
||||
/// </summary>
|
||||
public static class BoxExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the safe border for a border.
|
||||
/// </summary>
|
||||
/// <param name="border">The border to get the safe border for.</param>
|
||||
/// <param name="safe">Whether or not to return the safe border.</param>
|
||||
/// <returns>The safe border if one exist, otherwise the original border.</returns>
|
||||
public static BoxBorder GetSafeBorder(this BoxBorder border, bool safe)
|
||||
{
|
||||
if (border is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(border));
|
||||
}
|
||||
|
||||
if (safe && border.SafeBorder != null)
|
||||
{
|
||||
border = border.SafeBorder;
|
||||
}
|
||||
|
||||
return border;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,229 +7,6 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
public static class HasBorderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Do not display a border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T NoBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a square border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SquareBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.Square);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display an ASCII border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T AsciiBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.Ascii);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display another ASCII border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T Ascii2Border<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.Ascii2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display an ASCII border with a double header border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T AsciiDoubleHeadBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.AsciiDoubleHead);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a rounded border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T RoundedBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.Rounded);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a minimal border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T MinimalBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.Minimal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a minimal border with a heavy head.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T MinimalHeavyHeadBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.MinimalHeavyHead);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a minimal border with a double header border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T MinimalDoubleHeadBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.MinimalDoubleHead);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a simple border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SimpleBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.Simple);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a simple border with heavy lines.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SimpleHeavyBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.SimpleHeavy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a simple border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T HorizontalBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.Horizontal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a heavy border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T HeavyBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.Heavy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a border with a heavy edge.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T HeavyEdgeBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.HeavyEdge);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a border with a heavy header.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T HeavyHeadBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.HeavyHead);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a double border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T DoubleBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.Double);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a border with a double edge.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T DoubleEdgeBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
return SetBorder(obj, Border.DoubleEdge);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <param name="border">The border to use.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SetBorder<T>(this T obj, Border border)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
obj.Border = border;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables the safe border.
|
||||
/// </summary>
|
||||
|
||||
101
src/Spectre.Console/Extensions/HasBoxBorderExtensions.cs
Normal file
101
src/Spectre.Console/Extensions/HasBoxBorderExtensions.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="IHasBoxBorder"/>.
|
||||
/// </summary>
|
||||
public static class HasBoxBorderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Do not display a border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T NoBorder<T>(this T obj)
|
||||
where T : class, IHasBoxBorder
|
||||
{
|
||||
return SetBorder(obj, BoxBorder.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a square border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SquareBorder<T>(this T obj)
|
||||
where T : class, IHasBoxBorder
|
||||
{
|
||||
return SetBorder(obj, BoxBorder.Square);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display an ASCII border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T AsciiBorder<T>(this T obj)
|
||||
where T : class, IHasBoxBorder
|
||||
{
|
||||
return SetBorder(obj, BoxBorder.Ascii);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a rounded border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T RoundedBorder<T>(this T obj)
|
||||
where T : class, IHasBoxBorder
|
||||
{
|
||||
return SetBorder(obj, BoxBorder.Rounded);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a heavy border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T HeavyBorder<T>(this T obj)
|
||||
where T : class, IHasBoxBorder
|
||||
{
|
||||
return SetBorder(obj, BoxBorder.Heavy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a double border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T DoubleBorder<T>(this T obj)
|
||||
where T : class, IHasBoxBorder
|
||||
{
|
||||
return SetBorder(obj, BoxBorder.Double);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <param name="border">The border to use.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SetBorder<T>(this T obj, BoxBorder border)
|
||||
where T : class, IHasBoxBorder
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
obj.Border = border;
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
245
src/Spectre.Console/Extensions/HasTableBorderExtensions.cs
Normal file
245
src/Spectre.Console/Extensions/HasTableBorderExtensions.cs
Normal file
@@ -0,0 +1,245 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="IHasTableBorder"/>.
|
||||
/// </summary>
|
||||
public static class HasTableBorderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Do not display a border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T NoBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a square border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SquareBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.Square);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display an ASCII border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T AsciiBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.Ascii);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display another ASCII border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T Ascii2Border<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.Ascii2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display an ASCII border with a double header border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T AsciiDoubleHeadBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.AsciiDoubleHead);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a rounded border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T RoundedBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.Rounded);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a minimal border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T MinimalBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.Minimal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a minimal border with a heavy head.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T MinimalHeavyHeadBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.MinimalHeavyHead);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a minimal border with a double header border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T MinimalDoubleHeadBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.MinimalDoubleHead);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a simple border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SimpleBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.Simple);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a simple border with heavy lines.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SimpleHeavyBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.SimpleHeavy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a simple border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T HorizontalBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.Horizontal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a heavy border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T HeavyBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.Heavy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a border with a heavy edge.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T HeavyEdgeBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.HeavyEdge);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a border with a heavy header.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T HeavyHeadBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.HeavyHead);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a double border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T DoubleBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.Double);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a border with a double edge.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T DoubleEdgeBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.DoubleEdge);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a markdown border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T MarkdownBorder<T>(this T obj)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
return SetBorder(obj, TableBorder.Markdown);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the border.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border for.</param>
|
||||
/// <param name="border">The border to use.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SetBorder<T>(this T obj, TableBorder border)
|
||||
where T : class, IHasTableBorder
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
obj.Border = border;
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/Spectre.Console/Extensions/RecorderExtensions.cs
Normal file
44
src/Spectre.Console/Extensions/RecorderExtensions.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using Spectre.Console.Internal;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="Recorder"/>.
|
||||
/// </summary>
|
||||
public static class RecorderExtensions
|
||||
{
|
||||
private static readonly TextEncoder _textEncoder = new TextEncoder();
|
||||
private static readonly HtmlEncoder _htmlEncoder = new HtmlEncoder();
|
||||
|
||||
/// <summary>
|
||||
/// Exports the recorded content as text.
|
||||
/// </summary>
|
||||
/// <param name="recorder">The recorder.</param>
|
||||
/// <returns>The recorded content as text.</returns>
|
||||
public static string ExportText(this Recorder recorder)
|
||||
{
|
||||
if (recorder is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(recorder));
|
||||
}
|
||||
|
||||
return recorder.Export(_textEncoder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports the recorded content as HTML.
|
||||
/// </summary>
|
||||
/// <param name="recorder">The recorder.</param>
|
||||
/// <returns>The recorded content as HTML.</returns>
|
||||
public static string ExportHtml(this Recorder recorder)
|
||||
{
|
||||
if (recorder is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(recorder));
|
||||
}
|
||||
|
||||
return recorder.Export(_htmlEncoder);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
@@ -30,8 +31,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Writes a string followed by a line terminator to the console.
|
||||
/// </summary>
|
||||
/// <param name="text">The string to write.</param>
|
||||
/// <param name="style">The style to use.</param>
|
||||
void Write(string text, Style style);
|
||||
/// <param name="segment">The segment to write.</param>
|
||||
void Write(Segment segment);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,7 @@ namespace Spectre.Console
|
||||
bool UseSafeBorder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the border.
|
||||
/// </summary>
|
||||
public Border Border { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the border style.
|
||||
/// Gets or sets the box style.
|
||||
/// </summary>
|
||||
public Style? BorderStyle { get; set; }
|
||||
}
|
||||
|
||||
13
src/Spectre.Console/IHasBoxBorder.cs
Normal file
13
src/Spectre.Console/IHasBoxBorder.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents something that has a box border.
|
||||
/// </summary>
|
||||
public interface IHasBoxBorder : IHasBorder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the box.
|
||||
/// </summary>
|
||||
public BoxBorder Border { get; set; }
|
||||
}
|
||||
}
|
||||
13
src/Spectre.Console/IHasTableBorder.cs
Normal file
13
src/Spectre.Console/IHasTableBorder.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents something that has a border.
|
||||
/// </summary>
|
||||
public interface IHasTableBorder : IHasBorder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the border.
|
||||
/// </summary>
|
||||
public TableBorder Border { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
{
|
||||
@@ -48,21 +49,14 @@ namespace Spectre.Console.Internal
|
||||
_ansiBuilder = new AnsiBuilder(Capabilities, linkHasher);
|
||||
}
|
||||
|
||||
public void Write(string text, Style style)
|
||||
public void Write(Segment segment)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
style ??= Style.Plain;
|
||||
|
||||
var parts = text.NormalizeLineEndings().Split(new[] { '\n' });
|
||||
var parts = segment.Text.NormalizeLineEndings().Split(new[] { '\n' });
|
||||
foreach (var (_, _, last, part) in parts.Enumerate())
|
||||
{
|
||||
if (!string.IsNullOrEmpty(part))
|
||||
{
|
||||
_out.Write(_ansiBuilder.GetAnsi(part, style));
|
||||
_out.Write(_ansiBuilder.GetAnsi(part, segment.Style));
|
||||
}
|
||||
|
||||
if (!last)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
@@ -80,27 +81,24 @@ namespace Spectre.Console.Internal
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
// https://andrewlock.net/why-is-string-gethashcode-different-each-time-i-run-my-program-in-net-core/
|
||||
public static int GetDeterministicHashCode(this string str)
|
||||
public static string Multiply(this string text, int count)
|
||||
{
|
||||
unchecked
|
||||
if (text is null)
|
||||
{
|
||||
var hash1 = (5381 << 16) + 5381;
|
||||
var hash2 = hash1;
|
||||
|
||||
for (var i = 0; i < str.Length; i += 2)
|
||||
{
|
||||
hash1 = ((hash1 << 5) + hash1) ^ str[i];
|
||||
if (i == str.Length - 1)
|
||||
{
|
||||
break;
|
||||
throw new ArgumentNullException(nameof(text));
|
||||
}
|
||||
|
||||
hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
|
||||
if (count <= 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return hash1 + (hash2 * 1566083941);
|
||||
if (count == 1)
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
return string.Concat(Enumerable.Repeat(text, count));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
{
|
||||
@@ -61,14 +62,14 @@ namespace Spectre.Console.Internal
|
||||
Capabilities = capabilities;
|
||||
}
|
||||
|
||||
public void Write(string text, Style style)
|
||||
public void Write(Segment segment)
|
||||
{
|
||||
if (_lastStyle?.Equals(style) != true)
|
||||
if (_lastStyle?.Equals(segment.Style) != true)
|
||||
{
|
||||
SetStyle(style);
|
||||
SetStyle(segment.Style);
|
||||
}
|
||||
|
||||
_out.Write(text.NormalizeLineEndings(native: true));
|
||||
_out.Write(segment.Text.NormalizeLineEndings(native: true));
|
||||
}
|
||||
|
||||
private void SetStyle(Style style)
|
||||
|
||||
114
src/Spectre.Console/Internal/HtmlEncoder.cs
Normal file
114
src/Spectre.Console/Internal/HtmlEncoder.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
{
|
||||
internal sealed class HtmlEncoder : IAnsiConsoleEncoder
|
||||
{
|
||||
public string Encode(IEnumerable<Segment> segments)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
builder.Append("<pre style=\"font-size:90%;font-family:consolas,'Courier New',monospace\">\n");
|
||||
|
||||
foreach (var (_, first, _, segment) in segments.Enumerate())
|
||||
{
|
||||
if (segment.Text == "\n" && !first)
|
||||
{
|
||||
builder.Append('\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
var parts = segment.Text.Split(new[] { '\n' }, StringSplitOptions.None);
|
||||
foreach (var (_, _, last, line) in parts.Enumerate())
|
||||
{
|
||||
if (string.IsNullOrEmpty(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.Append("<span");
|
||||
if (!segment.Style.Equals(Style.Plain))
|
||||
{
|
||||
builder.Append(" style=\"");
|
||||
builder.Append(BuildCss(segment.Style));
|
||||
builder.Append('"');
|
||||
}
|
||||
|
||||
builder.Append('>');
|
||||
builder.Append(line);
|
||||
builder.Append("</span>");
|
||||
|
||||
if (parts.Length > 1 && !last)
|
||||
{
|
||||
builder.Append('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.Append("</pre>");
|
||||
|
||||
return builder.ToString().TrimEnd('\n');
|
||||
}
|
||||
|
||||
private static string BuildCss(Style style)
|
||||
{
|
||||
var css = new List<string>();
|
||||
|
||||
var foreground = style.Foreground;
|
||||
var background = style.Background;
|
||||
|
||||
if ((style.Decoration & Decoration.Invert) != 0)
|
||||
{
|
||||
var temp = foreground;
|
||||
foreground = background;
|
||||
background = temp;
|
||||
}
|
||||
|
||||
if ((style.Decoration & Decoration.Dim) != 0)
|
||||
{
|
||||
var blender = background;
|
||||
if (blender.Equals(Color.Default))
|
||||
{
|
||||
blender = Color.White;
|
||||
}
|
||||
|
||||
foreground = foreground.Blend(blender, 0.5f);
|
||||
}
|
||||
|
||||
if (!foreground.Equals(Color.Default))
|
||||
{
|
||||
css.Add($"color: #{foreground.ToHex()}");
|
||||
}
|
||||
|
||||
if (!background.Equals(Color.Default))
|
||||
{
|
||||
css.Add($"background-color: #{background.ToHex()}");
|
||||
}
|
||||
|
||||
if ((style.Decoration & Decoration.Bold) != 0)
|
||||
{
|
||||
css.Add("font-weight: bold");
|
||||
}
|
||||
|
||||
if ((style.Decoration & Decoration.Bold) != 0)
|
||||
{
|
||||
css.Add("font-style: italic");
|
||||
}
|
||||
|
||||
if ((style.Decoration & Decoration.Underline) != 0)
|
||||
{
|
||||
css.Add("text-decoration: underline");
|
||||
}
|
||||
|
||||
if ((style.Decoration & Decoration.Strikethrough) != 0)
|
||||
{
|
||||
css.Add("text-decoration: line-through");
|
||||
}
|
||||
|
||||
return string.Join(";", css);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/Spectre.Console/Internal/TextEncoder.cs
Normal file
21
src/Spectre.Console/Internal/TextEncoder.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
{
|
||||
internal sealed class TextEncoder : IAnsiConsoleEncoder
|
||||
{
|
||||
public string Encode(IEnumerable<Segment> segments)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
foreach (var segment in Segment.Merge(segments))
|
||||
{
|
||||
builder.Append(segment.Text);
|
||||
}
|
||||
|
||||
return builder.ToString().TrimEnd('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
66
src/Spectre.Console/Recorder.cs
Normal file
66
src/Spectre.Console/Recorder.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// A console recorder used to record output from a console.
|
||||
/// </summary>
|
||||
public sealed class Recorder : IAnsiConsole, IDisposable
|
||||
{
|
||||
private readonly IAnsiConsole _console;
|
||||
private readonly List<Segment> _recorded;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Capabilities Capabilities => _console.Capabilities;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Encoding Encoding => _console.Encoding;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Width => _console.Width;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Height => _console.Height;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Recorder"/> class.
|
||||
/// </summary>
|
||||
/// <param name="console">The console to record output for.</param>
|
||||
public Recorder(IAnsiConsole console)
|
||||
{
|
||||
_console = console ?? throw new ArgumentNullException(nameof(console));
|
||||
_recorded = new List<Segment>();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
// Only used for scoping.
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Write(Segment segment)
|
||||
{
|
||||
_recorded.Add(segment);
|
||||
_console.Write(segment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports the recorded data.
|
||||
/// </summary>
|
||||
/// <param name="encoder">The encoder.</param>
|
||||
/// <returns>The recorded data represented as a string.</returns>
|
||||
public string Export(IAnsiConsoleEncoder encoder)
|
||||
{
|
||||
if (encoder is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(encoder));
|
||||
}
|
||||
|
||||
return encoder.Encode(_recorded);
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/Spectre.Console/Rendering/Borders/BoxBorderPart.cs
Normal file
48
src/Spectre.Console/Rendering/Borders/BoxBorderPart.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the different parts of a box border.
|
||||
/// </summary>
|
||||
public enum BoxBorderPart
|
||||
{
|
||||
/// <summary>
|
||||
/// The top left part of a box.
|
||||
/// </summary>
|
||||
TopLeft,
|
||||
|
||||
/// <summary>
|
||||
/// The top part of a box.
|
||||
/// </summary>
|
||||
Top,
|
||||
|
||||
/// <summary>
|
||||
/// The top right part of a box.
|
||||
/// </summary>
|
||||
TopRight,
|
||||
|
||||
/// <summary>
|
||||
/// The left part of a box.
|
||||
/// </summary>
|
||||
Left,
|
||||
|
||||
/// <summary>
|
||||
/// The right part of a box.
|
||||
/// </summary>
|
||||
Right,
|
||||
|
||||
/// <summary>
|
||||
/// The bottom left part of a box.
|
||||
/// </summary>
|
||||
BottomLeft,
|
||||
|
||||
/// <summary>
|
||||
/// The bottom part of a box.
|
||||
/// </summary>
|
||||
Bottom,
|
||||
|
||||
/// <summary>
|
||||
/// The bottom right part of a box.
|
||||
/// </summary>
|
||||
BottomRight,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an old school ASCII border.
|
||||
/// </summary>
|
||||
public sealed class AsciiBoxBorder : BoxBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(BoxBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BoxBorderPart.TopLeft => "+",
|
||||
BoxBorderPart.Top => "-",
|
||||
BoxBorderPart.TopRight => "+",
|
||||
BoxBorderPart.Left => "|",
|
||||
BoxBorderPart.Right => "|",
|
||||
BoxBorderPart.BottomLeft => "+",
|
||||
BoxBorderPart.Bottom => "-",
|
||||
BoxBorderPart.BottomRight => "+",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a double border.
|
||||
/// </summary>
|
||||
public sealed class DoubleBoxBorder : BoxBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(BoxBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BoxBorderPart.TopLeft => "╔",
|
||||
BoxBorderPart.Top => "═",
|
||||
BoxBorderPart.TopRight => "╗",
|
||||
BoxBorderPart.Left => "║",
|
||||
BoxBorderPart.Right => "║",
|
||||
BoxBorderPart.BottomLeft => "╚",
|
||||
BoxBorderPart.Bottom => "═",
|
||||
BoxBorderPart.BottomRight => "╝",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a heavy border.
|
||||
/// </summary>
|
||||
public sealed class HeavyBoxBorder : BoxBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override BoxBorder? SafeBorder => BoxBorder.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(BoxBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BoxBorderPart.TopLeft => "┏",
|
||||
BoxBorderPart.Top => "━",
|
||||
BoxBorderPart.TopRight => "┓",
|
||||
BoxBorderPart.Left => "┃",
|
||||
BoxBorderPart.Right => "┃",
|
||||
BoxBorderPart.BottomLeft => "┗",
|
||||
BoxBorderPart.Bottom => "━",
|
||||
BoxBorderPart.BottomRight => "┛",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/Spectre.Console/Rendering/Borders/Boxes/NoBoxBorder.cs
Normal file
14
src/Spectre.Console/Rendering/Borders/Boxes/NoBoxBorder.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an invisible border.
|
||||
/// </summary>
|
||||
public sealed class NoBoxBorder : BoxBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(BoxBorderPart part)
|
||||
{
|
||||
return " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a rounded border.
|
||||
/// </summary>
|
||||
public sealed class RoundedBoxBorder : BoxBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override BoxBorder? SafeBorder => BoxBorder.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(BoxBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BoxBorderPart.TopLeft => "╭",
|
||||
BoxBorderPart.Top => "─",
|
||||
BoxBorderPart.TopRight => "╮",
|
||||
BoxBorderPart.Left => "│",
|
||||
BoxBorderPart.Right => "│",
|
||||
BoxBorderPart.BottomLeft => "╰",
|
||||
BoxBorderPart.Bottom => "─",
|
||||
BoxBorderPart.BottomRight => "╯",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a square border.
|
||||
/// </summary>
|
||||
public sealed class SquareBoxBorder : BoxBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(BoxBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
BoxBorderPart.TopLeft => "┌",
|
||||
BoxBorderPart.Top => "─",
|
||||
BoxBorderPart.TopRight => "┐",
|
||||
BoxBorderPart.Left => "│",
|
||||
BoxBorderPart.Right => "│",
|
||||
BoxBorderPart.BottomLeft => "└",
|
||||
BoxBorderPart.Bottom => "─",
|
||||
BoxBorderPart.BottomRight => "┘",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the different border parts.
|
||||
/// Represents the different parts of a table border.
|
||||
/// </summary>
|
||||
public enum BorderPart
|
||||
public enum TableBorderPart
|
||||
{
|
||||
/// <summary>
|
||||
/// The top left part of a header.
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents another old school ASCII border.
|
||||
/// </summary>
|
||||
public sealed class Ascii2TableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => "+",
|
||||
TableBorderPart.HeaderTop => "-",
|
||||
TableBorderPart.HeaderTopSeparator => "+",
|
||||
TableBorderPart.HeaderTopRight => "+",
|
||||
TableBorderPart.HeaderLeft => "|",
|
||||
TableBorderPart.HeaderSeparator => "|",
|
||||
TableBorderPart.HeaderRight => "|",
|
||||
TableBorderPart.HeaderBottomLeft => "|",
|
||||
TableBorderPart.HeaderBottom => "-",
|
||||
TableBorderPart.HeaderBottomSeparator => "+",
|
||||
TableBorderPart.HeaderBottomRight => "|",
|
||||
TableBorderPart.CellLeft => "|",
|
||||
TableBorderPart.CellSeparator => "|",
|
||||
TableBorderPart.CellRight => "|",
|
||||
TableBorderPart.FooterBottomLeft => "+",
|
||||
TableBorderPart.FooterBottom => "-",
|
||||
TableBorderPart.FooterBottomSeparator => "+",
|
||||
TableBorderPart.FooterBottomRight => "+",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an old school ASCII border with a double header border.
|
||||
/// </summary>
|
||||
public sealed class AsciiDoubleHeadTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => "+",
|
||||
TableBorderPart.HeaderTop => "-",
|
||||
TableBorderPart.HeaderTopSeparator => "+",
|
||||
TableBorderPart.HeaderTopRight => "+",
|
||||
TableBorderPart.HeaderLeft => "|",
|
||||
TableBorderPart.HeaderSeparator => "|",
|
||||
TableBorderPart.HeaderRight => "|",
|
||||
TableBorderPart.HeaderBottomLeft => "|",
|
||||
TableBorderPart.HeaderBottom => "=",
|
||||
TableBorderPart.HeaderBottomSeparator => "+",
|
||||
TableBorderPart.HeaderBottomRight => "|",
|
||||
TableBorderPart.CellLeft => "|",
|
||||
TableBorderPart.CellSeparator => "|",
|
||||
TableBorderPart.CellRight => "|",
|
||||
TableBorderPart.FooterBottomLeft => "+",
|
||||
TableBorderPart.FooterBottom => "-",
|
||||
TableBorderPart.FooterBottomSeparator => "+",
|
||||
TableBorderPart.FooterBottomRight => "+",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an old school ASCII border.
|
||||
/// </summary>
|
||||
public sealed class AsciiTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => "+",
|
||||
TableBorderPart.HeaderTop => "-",
|
||||
TableBorderPart.HeaderTopSeparator => "-",
|
||||
TableBorderPart.HeaderTopRight => "+",
|
||||
TableBorderPart.HeaderLeft => "|",
|
||||
TableBorderPart.HeaderSeparator => "|",
|
||||
TableBorderPart.HeaderRight => "|",
|
||||
TableBorderPart.HeaderBottomLeft => "|",
|
||||
TableBorderPart.HeaderBottom => "-",
|
||||
TableBorderPart.HeaderBottomSeparator => "+",
|
||||
TableBorderPart.HeaderBottomRight => "|",
|
||||
TableBorderPart.CellLeft => "|",
|
||||
TableBorderPart.CellSeparator => "|",
|
||||
TableBorderPart.CellRight => "|",
|
||||
TableBorderPart.FooterBottomLeft => "+",
|
||||
TableBorderPart.FooterBottom => "-",
|
||||
TableBorderPart.FooterBottomSeparator => "-",
|
||||
TableBorderPart.FooterBottomRight => "+",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a border with a double edge.
|
||||
/// </summary>
|
||||
public sealed class DoubleEdgeTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => "╔",
|
||||
TableBorderPart.HeaderTop => "═",
|
||||
TableBorderPart.HeaderTopSeparator => "╤",
|
||||
TableBorderPart.HeaderTopRight => "╗",
|
||||
TableBorderPart.HeaderLeft => "║",
|
||||
TableBorderPart.HeaderSeparator => "│",
|
||||
TableBorderPart.HeaderRight => "║",
|
||||
TableBorderPart.HeaderBottomLeft => "╟",
|
||||
TableBorderPart.HeaderBottom => "─",
|
||||
TableBorderPart.HeaderBottomSeparator => "┼",
|
||||
TableBorderPart.HeaderBottomRight => "╢",
|
||||
TableBorderPart.CellLeft => "║",
|
||||
TableBorderPart.CellSeparator => "│",
|
||||
TableBorderPart.CellRight => "║",
|
||||
TableBorderPart.FooterBottomLeft => "╚",
|
||||
TableBorderPart.FooterBottom => "═",
|
||||
TableBorderPart.FooterBottomSeparator => "╧",
|
||||
TableBorderPart.FooterBottomRight => "╝",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a double border.
|
||||
/// </summary>
|
||||
public sealed class DoubleTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => "╔",
|
||||
TableBorderPart.HeaderTop => "═",
|
||||
TableBorderPart.HeaderTopSeparator => "╦",
|
||||
TableBorderPart.HeaderTopRight => "╗",
|
||||
TableBorderPart.HeaderLeft => "║",
|
||||
TableBorderPart.HeaderSeparator => "║",
|
||||
TableBorderPart.HeaderRight => "║",
|
||||
TableBorderPart.HeaderBottomLeft => "╠",
|
||||
TableBorderPart.HeaderBottom => "═",
|
||||
TableBorderPart.HeaderBottomSeparator => "╬",
|
||||
TableBorderPart.HeaderBottomRight => "╣",
|
||||
TableBorderPart.CellLeft => "║",
|
||||
TableBorderPart.CellSeparator => "║",
|
||||
TableBorderPart.CellRight => "║",
|
||||
TableBorderPart.FooterBottomLeft => "╚",
|
||||
TableBorderPart.FooterBottom => "═",
|
||||
TableBorderPart.FooterBottomSeparator => "╩",
|
||||
TableBorderPart.FooterBottomRight => "╝",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a border with a heavy edge.
|
||||
/// </summary>
|
||||
public sealed class HeavyEdgeTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override TableBorder? SafeBorder => TableBorder.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => "┏",
|
||||
TableBorderPart.HeaderTop => "━",
|
||||
TableBorderPart.HeaderTopSeparator => "┯",
|
||||
TableBorderPart.HeaderTopRight => "┓",
|
||||
TableBorderPart.HeaderLeft => "┃",
|
||||
TableBorderPart.HeaderSeparator => "│",
|
||||
TableBorderPart.HeaderRight => "┃",
|
||||
TableBorderPart.HeaderBottomLeft => "┠",
|
||||
TableBorderPart.HeaderBottom => "─",
|
||||
TableBorderPart.HeaderBottomSeparator => "┼",
|
||||
TableBorderPart.HeaderBottomRight => "┨",
|
||||
TableBorderPart.CellLeft => "┃",
|
||||
TableBorderPart.CellSeparator => "│",
|
||||
TableBorderPart.CellRight => "┃",
|
||||
TableBorderPart.FooterBottomLeft => "┗",
|
||||
TableBorderPart.FooterBottom => "━",
|
||||
TableBorderPart.FooterBottomSeparator => "┷",
|
||||
TableBorderPart.FooterBottomRight => "┛",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a border with a heavy header.
|
||||
/// </summary>
|
||||
public sealed class HeavyHeadTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override TableBorder? SafeBorder => TableBorder.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => "┏",
|
||||
TableBorderPart.HeaderTop => "━",
|
||||
TableBorderPart.HeaderTopSeparator => "┳",
|
||||
TableBorderPart.HeaderTopRight => "┓",
|
||||
TableBorderPart.HeaderLeft => "┃",
|
||||
TableBorderPart.HeaderSeparator => "┃",
|
||||
TableBorderPart.HeaderRight => "┃",
|
||||
TableBorderPart.HeaderBottomLeft => "┡",
|
||||
TableBorderPart.HeaderBottom => "━",
|
||||
TableBorderPart.HeaderBottomSeparator => "╇",
|
||||
TableBorderPart.HeaderBottomRight => "┩",
|
||||
TableBorderPart.CellLeft => "│",
|
||||
TableBorderPart.CellSeparator => "│",
|
||||
TableBorderPart.CellRight => "│",
|
||||
TableBorderPart.FooterBottomLeft => "└",
|
||||
TableBorderPart.FooterBottom => "─",
|
||||
TableBorderPart.FooterBottomSeparator => "┴",
|
||||
TableBorderPart.FooterBottomRight => "┘",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a heavy border.
|
||||
/// </summary>
|
||||
public sealed class HeavyTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override TableBorder? SafeBorder => TableBorder.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => "┏",
|
||||
TableBorderPart.HeaderTop => "━",
|
||||
TableBorderPart.HeaderTopSeparator => "┳",
|
||||
TableBorderPart.HeaderTopRight => "┓",
|
||||
TableBorderPart.HeaderLeft => "┃",
|
||||
TableBorderPart.HeaderSeparator => "┃",
|
||||
TableBorderPart.HeaderRight => "┃",
|
||||
TableBorderPart.HeaderBottomLeft => "┣",
|
||||
TableBorderPart.HeaderBottom => "━",
|
||||
TableBorderPart.HeaderBottomSeparator => "╋",
|
||||
TableBorderPart.HeaderBottomRight => "┫",
|
||||
TableBorderPart.CellLeft => "┃",
|
||||
TableBorderPart.CellSeparator => "┃",
|
||||
TableBorderPart.CellRight => "┃",
|
||||
TableBorderPart.FooterBottomLeft => "┗",
|
||||
TableBorderPart.FooterBottom => "━",
|
||||
TableBorderPart.FooterBottomSeparator => "┻",
|
||||
TableBorderPart.FooterBottomRight => "┛",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a horizontal border.
|
||||
/// </summary>
|
||||
public sealed class HorizontalTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => "─",
|
||||
TableBorderPart.HeaderTop => "─",
|
||||
TableBorderPart.HeaderTopSeparator => "─",
|
||||
TableBorderPart.HeaderTopRight => "─",
|
||||
TableBorderPart.HeaderLeft => " ",
|
||||
TableBorderPart.HeaderSeparator => " ",
|
||||
TableBorderPart.HeaderRight => " ",
|
||||
TableBorderPart.HeaderBottomLeft => "─",
|
||||
TableBorderPart.HeaderBottom => "─",
|
||||
TableBorderPart.HeaderBottomSeparator => "─",
|
||||
TableBorderPart.HeaderBottomRight => "─",
|
||||
TableBorderPart.CellLeft => " ",
|
||||
TableBorderPart.CellSeparator => " ",
|
||||
TableBorderPart.CellRight => " ",
|
||||
TableBorderPart.FooterBottomLeft => "─",
|
||||
TableBorderPart.FooterBottom => "─",
|
||||
TableBorderPart.FooterBottomSeparator => "─",
|
||||
TableBorderPart.FooterBottomRight => "─",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Spectre.Console.Internal;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Markdown border.
|
||||
/// </summary>
|
||||
public sealed class MarkdownTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => " ",
|
||||
TableBorderPart.HeaderTop => " ",
|
||||
TableBorderPart.HeaderTopSeparator => " ",
|
||||
TableBorderPart.HeaderTopRight => " ",
|
||||
TableBorderPart.HeaderLeft => "|",
|
||||
TableBorderPart.HeaderSeparator => "|",
|
||||
TableBorderPart.HeaderRight => "|",
|
||||
TableBorderPart.HeaderBottomLeft => "|",
|
||||
TableBorderPart.HeaderBottom => "-",
|
||||
TableBorderPart.HeaderBottomSeparator => "|",
|
||||
TableBorderPart.HeaderBottomRight => "|",
|
||||
TableBorderPart.CellLeft => "|",
|
||||
TableBorderPart.CellSeparator => "|",
|
||||
TableBorderPart.CellRight => "|",
|
||||
TableBorderPart.FooterBottomLeft => " ",
|
||||
TableBorderPart.FooterBottom => " ",
|
||||
TableBorderPart.FooterBottomSeparator => " ",
|
||||
TableBorderPart.FooterBottomRight => " ",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string GetColumnRow(TablePart part, IReadOnlyList<int> widths, IReadOnlyList<IColumn> columns)
|
||||
{
|
||||
if (part != TablePart.Separator)
|
||||
{
|
||||
return base.GetColumnRow(part, widths, columns);
|
||||
}
|
||||
|
||||
var (left, center, separator, right) = GetTableParts(part);
|
||||
|
||||
var builder = new StringBuilder();
|
||||
builder.Append(left);
|
||||
|
||||
foreach (var (columnIndex, _, lastColumn, columnWidth) in widths.Enumerate())
|
||||
{
|
||||
var padding = columns[columnIndex].Padding;
|
||||
|
||||
if (padding.Left > 0)
|
||||
{
|
||||
// Left padding
|
||||
builder.Append(" ".Multiply(padding.Left));
|
||||
}
|
||||
|
||||
var justification = columns[columnIndex].Alignment;
|
||||
if (justification == null)
|
||||
{
|
||||
// No alignment
|
||||
builder.Append(center.Multiply(columnWidth));
|
||||
}
|
||||
else if (justification.Value == Justify.Left)
|
||||
{
|
||||
// Left
|
||||
builder.Append(':');
|
||||
builder.Append(center.Multiply(columnWidth - 1));
|
||||
}
|
||||
else if (justification.Value == Justify.Center)
|
||||
{
|
||||
// Centered
|
||||
builder.Append(':');
|
||||
builder.Append(center.Multiply(columnWidth - 2));
|
||||
builder.Append(':');
|
||||
}
|
||||
else if (justification.Value == Justify.Right)
|
||||
{
|
||||
// Right
|
||||
builder.Append(center.Multiply(columnWidth - 1));
|
||||
builder.Append(':');
|
||||
}
|
||||
|
||||
// Right padding
|
||||
if (padding.Right > 0)
|
||||
{
|
||||
builder.Append(" ".Multiply(padding.Right));
|
||||
}
|
||||
|
||||
if (!lastColumn)
|
||||
{
|
||||
builder.Append(separator);
|
||||
}
|
||||
}
|
||||
|
||||
builder.Append(right);
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a minimal border with a double header border.
|
||||
/// </summary>
|
||||
public sealed class MinimalDoubleHeadTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => " ",
|
||||
TableBorderPart.HeaderTop => " ",
|
||||
TableBorderPart.HeaderTopSeparator => " ",
|
||||
TableBorderPart.HeaderTopRight => " ",
|
||||
TableBorderPart.HeaderLeft => " ",
|
||||
TableBorderPart.HeaderSeparator => "│",
|
||||
TableBorderPart.HeaderRight => " ",
|
||||
TableBorderPart.HeaderBottomLeft => " ",
|
||||
TableBorderPart.HeaderBottom => "═",
|
||||
TableBorderPart.HeaderBottomSeparator => "╪",
|
||||
TableBorderPart.HeaderBottomRight => " ",
|
||||
TableBorderPart.CellLeft => " ",
|
||||
TableBorderPart.CellSeparator => "│",
|
||||
TableBorderPart.CellRight => " ",
|
||||
TableBorderPart.FooterBottomLeft => " ",
|
||||
TableBorderPart.FooterBottom => " ",
|
||||
TableBorderPart.FooterBottomSeparator => " ",
|
||||
TableBorderPart.FooterBottomRight => " ",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a minimal border with a heavy header.
|
||||
/// </summary>
|
||||
public sealed class MinimalHeavyHeadTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override TableBorder? SafeBorder => TableBorder.Minimal;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => " ",
|
||||
TableBorderPart.HeaderTop => " ",
|
||||
TableBorderPart.HeaderTopSeparator => " ",
|
||||
TableBorderPart.HeaderTopRight => " ",
|
||||
TableBorderPart.HeaderLeft => " ",
|
||||
TableBorderPart.HeaderSeparator => "│",
|
||||
TableBorderPart.HeaderRight => " ",
|
||||
TableBorderPart.HeaderBottomLeft => " ",
|
||||
TableBorderPart.HeaderBottom => "━",
|
||||
TableBorderPart.HeaderBottomSeparator => "┿",
|
||||
TableBorderPart.HeaderBottomRight => " ",
|
||||
TableBorderPart.CellLeft => " ",
|
||||
TableBorderPart.CellSeparator => "│",
|
||||
TableBorderPart.CellRight => " ",
|
||||
TableBorderPart.FooterBottomLeft => " ",
|
||||
TableBorderPart.FooterBottom => " ",
|
||||
TableBorderPart.FooterBottomSeparator => " ",
|
||||
TableBorderPart.FooterBottomRight => " ",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a minimal border.
|
||||
/// </summary>
|
||||
public sealed class MinimalTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => " ",
|
||||
TableBorderPart.HeaderTop => " ",
|
||||
TableBorderPart.HeaderTopSeparator => " ",
|
||||
TableBorderPart.HeaderTopRight => " ",
|
||||
TableBorderPart.HeaderLeft => " ",
|
||||
TableBorderPart.HeaderSeparator => "│",
|
||||
TableBorderPart.HeaderRight => " ",
|
||||
TableBorderPart.HeaderBottomLeft => " ",
|
||||
TableBorderPart.HeaderBottom => "─",
|
||||
TableBorderPart.HeaderBottomSeparator => "┼",
|
||||
TableBorderPart.HeaderBottomRight => " ",
|
||||
TableBorderPart.CellLeft => " ",
|
||||
TableBorderPart.CellSeparator => "│",
|
||||
TableBorderPart.CellRight => " ",
|
||||
TableBorderPart.FooterBottomLeft => " ",
|
||||
TableBorderPart.FooterBottom => " ",
|
||||
TableBorderPart.FooterBottomSeparator => " ",
|
||||
TableBorderPart.FooterBottomRight => " ",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,13 @@ namespace Spectre.Console.Rendering
|
||||
/// <summary>
|
||||
/// Represents an invisible border.
|
||||
/// </summary>
|
||||
public sealed class NoBorder : Border
|
||||
public sealed class NoTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override bool Visible => false;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return " ";
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a rounded border.
|
||||
/// </summary>
|
||||
public sealed class RoundedTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override TableBorder? SafeBorder => TableBorder.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => "╭",
|
||||
TableBorderPart.HeaderTop => "─",
|
||||
TableBorderPart.HeaderTopSeparator => "┬",
|
||||
TableBorderPart.HeaderTopRight => "╮",
|
||||
TableBorderPart.HeaderLeft => "│",
|
||||
TableBorderPart.HeaderSeparator => "│",
|
||||
TableBorderPart.HeaderRight => "│",
|
||||
TableBorderPart.HeaderBottomLeft => "├",
|
||||
TableBorderPart.HeaderBottom => "─",
|
||||
TableBorderPart.HeaderBottomSeparator => "┼",
|
||||
TableBorderPart.HeaderBottomRight => "┤",
|
||||
TableBorderPart.CellLeft => "│",
|
||||
TableBorderPart.CellSeparator => "│",
|
||||
TableBorderPart.CellRight => "│",
|
||||
TableBorderPart.FooterBottomLeft => "╰",
|
||||
TableBorderPart.FooterBottom => "─",
|
||||
TableBorderPart.FooterBottomSeparator => "┴",
|
||||
TableBorderPart.FooterBottomRight => "╯",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a simple border with heavy lines.
|
||||
/// </summary>
|
||||
public sealed class SimpleHeavyTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override TableBorder? SafeBorder => TableBorder.Simple;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => " ",
|
||||
TableBorderPart.HeaderTop => " ",
|
||||
TableBorderPart.HeaderTopSeparator => " ",
|
||||
TableBorderPart.HeaderTopRight => " ",
|
||||
TableBorderPart.HeaderLeft => " ",
|
||||
TableBorderPart.HeaderSeparator => " ",
|
||||
TableBorderPart.HeaderRight => " ",
|
||||
TableBorderPart.HeaderBottomLeft => "━",
|
||||
TableBorderPart.HeaderBottom => "━",
|
||||
TableBorderPart.HeaderBottomSeparator => "━",
|
||||
TableBorderPart.HeaderBottomRight => "━",
|
||||
TableBorderPart.CellLeft => " ",
|
||||
TableBorderPart.CellSeparator => " ",
|
||||
TableBorderPart.CellRight => " ",
|
||||
TableBorderPart.FooterBottomLeft => " ",
|
||||
TableBorderPart.FooterBottom => " ",
|
||||
TableBorderPart.FooterBottomSeparator => " ",
|
||||
TableBorderPart.FooterBottomRight => " ",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a simple border.
|
||||
/// </summary>
|
||||
public sealed class SimpleTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => " ",
|
||||
TableBorderPart.HeaderTop => " ",
|
||||
TableBorderPart.HeaderTopSeparator => " ",
|
||||
TableBorderPart.HeaderTopRight => " ",
|
||||
TableBorderPart.HeaderLeft => " ",
|
||||
TableBorderPart.HeaderSeparator => " ",
|
||||
TableBorderPart.HeaderRight => " ",
|
||||
TableBorderPart.HeaderBottomLeft => "─",
|
||||
TableBorderPart.HeaderBottom => "─",
|
||||
TableBorderPart.HeaderBottomSeparator => "─",
|
||||
TableBorderPart.HeaderBottomRight => "─",
|
||||
TableBorderPart.CellLeft => " ",
|
||||
TableBorderPart.CellSeparator => " ",
|
||||
TableBorderPart.CellRight => " ",
|
||||
TableBorderPart.FooterBottomLeft => " ",
|
||||
TableBorderPart.FooterBottom => " ",
|
||||
TableBorderPart.FooterBottomSeparator => " ",
|
||||
TableBorderPart.FooterBottomRight => " ",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a square border.
|
||||
/// </summary>
|
||||
public sealed class SquareTableBorder : TableBorder
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBorderPart(TableBorderPart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
TableBorderPart.HeaderTopLeft => "┌",
|
||||
TableBorderPart.HeaderTop => "─",
|
||||
TableBorderPart.HeaderTopSeparator => "┬",
|
||||
TableBorderPart.HeaderTopRight => "┐",
|
||||
TableBorderPart.HeaderLeft => "│",
|
||||
TableBorderPart.HeaderSeparator => "│",
|
||||
TableBorderPart.HeaderRight => "│",
|
||||
TableBorderPart.HeaderBottomLeft => "├",
|
||||
TableBorderPart.HeaderBottom => "─",
|
||||
TableBorderPart.HeaderBottomSeparator => "┼",
|
||||
TableBorderPart.HeaderBottomRight => "┤",
|
||||
TableBorderPart.CellLeft => "│",
|
||||
TableBorderPart.CellSeparator => "│",
|
||||
TableBorderPart.CellRight => "│",
|
||||
TableBorderPart.FooterBottomLeft => "└",
|
||||
TableBorderPart.FooterBottom => "─",
|
||||
TableBorderPart.FooterBottomSeparator => "┴",
|
||||
TableBorderPart.FooterBottomRight => "┘",
|
||||
_ => throw new InvalidOperationException("Unknown border part."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/Spectre.Console/Rendering/IAnsiConsoleEncoder.cs
Normal file
18
src/Spectre.Console/Rendering/IAnsiConsoleEncoder.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a console encoder that can encode
|
||||
/// recorded segments into a string.
|
||||
/// </summary>
|
||||
public interface IAnsiConsoleEncoder
|
||||
{
|
||||
/// <summary>
|
||||
/// Encodes the specified segments.
|
||||
/// </summary>
|
||||
/// <param name="segments">The segments to encode.</param>
|
||||
/// <returns>The encoded string.</returns>
|
||||
string Encode(IEnumerable<Segment> segments);
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ namespace Spectre.Console.Rendering
|
||||
/// <summary>
|
||||
/// Gets the segment text.
|
||||
/// </summary>
|
||||
public string Text { get; private set; }
|
||||
public string Text { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether or not this is an expicit line break
|
||||
@@ -38,12 +38,12 @@ namespace Spectre.Console.Rendering
|
||||
/// <summary>
|
||||
/// Gets a segment representing a line break.
|
||||
/// </summary>
|
||||
public static Segment LineBreak => new Segment(Environment.NewLine, Style.Plain, true);
|
||||
public static Segment LineBreak { get; } = new Segment(Environment.NewLine, Style.Plain, true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an empty segment.
|
||||
/// </summary>
|
||||
public static Segment Empty => new Segment(string.Empty, Style.Plain, false);
|
||||
public static Segment Empty { get; } = new Segment(string.Empty, Style.Plain, false);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Segment"/> class.
|
||||
@@ -72,7 +72,7 @@ namespace Spectre.Console.Rendering
|
||||
}
|
||||
|
||||
Text = text.NormalizeLineEndings();
|
||||
Style = style;
|
||||
Style = style ?? throw new ArgumentNullException(nameof(style));
|
||||
IsLineBreak = lineBreak;
|
||||
IsWhiteSpace = string.IsNullOrWhiteSpace(text);
|
||||
}
|
||||
@@ -241,12 +241,10 @@ namespace Spectre.Console.Rendering
|
||||
// Same style?
|
||||
if (previous.Style.Equals(segment.Style))
|
||||
{
|
||||
// Modify the content of the previous segment
|
||||
previous.Text += segment.Text;
|
||||
previous = new Segment(previous.Text + segment.Text, previous.Style);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Push the current one to the results.
|
||||
result.Add(previous);
|
||||
previous = segment;
|
||||
}
|
||||
@@ -260,6 +258,15 @@ namespace Spectre.Console.Rendering
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clones the segment.
|
||||
/// </summary>
|
||||
/// <returns>A new segment that's identical to this one.</returns>
|
||||
public Segment Clone()
|
||||
{
|
||||
return new Segment(Text, Style);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits an overflowing segment into several new segments.
|
||||
/// </summary>
|
||||
|
||||
23
src/Spectre.Console/Rendering/TablePart.cs
Normal file
23
src/Spectre.Console/Rendering/TablePart.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents different parts of a table.
|
||||
/// </summary>
|
||||
public enum TablePart
|
||||
{
|
||||
/// <summary>
|
||||
/// The top of a table.
|
||||
/// </summary>
|
||||
Top,
|
||||
|
||||
/// <summary>
|
||||
/// The separator between the header and the cells.
|
||||
/// </summary>
|
||||
Separator,
|
||||
|
||||
/// <summary>
|
||||
/// The bottom of a table.
|
||||
/// </summary>
|
||||
Bottom,
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
@@ -14,12 +14,15 @@
|
||||
<Compile Update="AnsiConsole.*.cs">
|
||||
<DependentUpon>AnsiConsole.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Color.*.cs">
|
||||
<DependentUpon>Color.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Border.*.cs">
|
||||
<DependentUpon>Border.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="BoxBorder.*.cs">
|
||||
<DependentUpon>BoxBorder.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Color.*.cs">
|
||||
<DependentUpon>Color.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Emoji.*.cs">
|
||||
<DependentUpon>Emoji.cs</DependentUpon>
|
||||
</Compile>
|
||||
@@ -39,6 +42,12 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="BoxBorder.Known.cs">
|
||||
<DependentUpon>BoxBorder.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="TableBorder.Known.cs">
|
||||
<DependentUpon>TableBorder.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Extensions\AnsiConsoleExtensions.Markup.cs">
|
||||
<DependentUpon>AnsiConsoleExtensions.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
||||
@@ -6,92 +6,97 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Represents a border.
|
||||
/// </summary>
|
||||
public abstract partial class Border
|
||||
public abstract partial class TableBorder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets an invisible border.
|
||||
/// </summary>
|
||||
public static Border None { get; } = new NoBorder();
|
||||
public static TableBorder None { get; } = new NoTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an ASCII border.
|
||||
/// </summary>
|
||||
public static Border Ascii { get; } = new AsciiBorder();
|
||||
public static TableBorder Ascii { get; } = new AsciiTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets another ASCII border.
|
||||
/// Gets an ASCII border.
|
||||
/// </summary>
|
||||
public static Border Ascii2 { get; } = new Ascii2Border();
|
||||
public static TableBorder Ascii2 { get; } = new Ascii2TableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an ASCII border with a double header border.
|
||||
/// </summary>
|
||||
public static Border AsciiDoubleHead { get; } = new AsciiDoubleHeadBorder();
|
||||
public static TableBorder AsciiDoubleHead { get; } = new AsciiDoubleHeadTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a square border.
|
||||
/// </summary>
|
||||
public static Border Square { get; } = new SquareBorder();
|
||||
public static TableBorder Square { get; } = new SquareTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a rounded border.
|
||||
/// </summary>
|
||||
public static Border Rounded { get; } = new RoundedBorder();
|
||||
public static TableBorder Rounded { get; } = new RoundedTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a minimal border.
|
||||
/// </summary>
|
||||
public static Border Minimal { get; } = new MinimalBorder();
|
||||
public static TableBorder Minimal { get; } = new MinimalTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a minimal border with a heavy head.
|
||||
/// </summary>
|
||||
public static Border MinimalHeavyHead { get; } = new MinimalHeavyHeadBorder();
|
||||
public static TableBorder MinimalHeavyHead { get; } = new MinimalHeavyHeadTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a minimal border with a double header border.
|
||||
/// </summary>
|
||||
public static Border MinimalDoubleHead { get; } = new MinimalDoubleHeadBorder();
|
||||
public static TableBorder MinimalDoubleHead { get; } = new MinimalDoubleHeadTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a simple border.
|
||||
/// </summary>
|
||||
public static Border Simple { get; } = new SimpleBorder();
|
||||
public static TableBorder Simple { get; } = new SimpleTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a simple border with heavy lines.
|
||||
/// </summary>
|
||||
public static Border SimpleHeavy { get; } = new SimpleHeavyBorder();
|
||||
public static TableBorder SimpleHeavy { get; } = new SimpleHeavyTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a horizontal border.
|
||||
/// </summary>
|
||||
public static Border Horizontal { get; } = new HorizontalBorder();
|
||||
public static TableBorder Horizontal { get; } = new HorizontalTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a heavy border.
|
||||
/// </summary>
|
||||
public static Border Heavy { get; } = new HeavyBorder();
|
||||
public static TableBorder Heavy { get; } = new HeavyTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a border with a heavy edge.
|
||||
/// </summary>
|
||||
public static Border HeavyEdge { get; } = new HeavyEdgeBorder();
|
||||
public static TableBorder HeavyEdge { get; } = new HeavyEdgeTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a border with a heavy header.
|
||||
/// </summary>
|
||||
public static Border HeavyHead { get; } = new HeavyHeadBorder();
|
||||
public static TableBorder HeavyHead { get; } = new HeavyHeadTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a double border.
|
||||
/// </summary>
|
||||
[SuppressMessage("Naming", "CA1720:Identifier contains type name")]
|
||||
public static Border Double { get; } = new DoubleBorder();
|
||||
public static TableBorder Double { get; } = new DoubleTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a border with a double edge.
|
||||
/// </summary>
|
||||
public static Border DoubleEdge { get; } = new DoubleEdgeBorder();
|
||||
public static TableBorder DoubleEdge { get; } = new DoubleEdgeTableBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a markdown border.
|
||||
/// </summary>
|
||||
public static TableBorder Markdown { get; } = new MarkdownTableBorder();
|
||||
}
|
||||
}
|
||||
157
src/Spectre.Console/TableBorder.cs
Normal file
157
src/Spectre.Console/TableBorder.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Spectre.Console.Internal;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a border.
|
||||
/// </summary>
|
||||
public abstract partial class TableBorder
|
||||
{
|
||||
private readonly Dictionary<TableBorderPart, string> _lookup;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether or not the border is visible.
|
||||
/// </summary>
|
||||
public virtual bool Visible { get; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the safe border for this border or <c>null</c> if none exist.
|
||||
/// </summary>
|
||||
public virtual TableBorder? SafeBorder { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TableBorder"/> class.
|
||||
/// </summary>
|
||||
protected TableBorder()
|
||||
{
|
||||
_lookup = Initialize();
|
||||
}
|
||||
|
||||
private Dictionary<TableBorderPart, string> Initialize()
|
||||
{
|
||||
var lookup = new Dictionary<TableBorderPart, string>();
|
||||
foreach (TableBorderPart? part in Enum.GetValues(typeof(TableBorderPart)))
|
||||
{
|
||||
if (part == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var text = GetBorderPart(part.Value);
|
||||
if (text.Length > 1)
|
||||
{
|
||||
throw new InvalidOperationException("A box part cannot contain more than one character.");
|
||||
}
|
||||
|
||||
lookup.Add(part.Value, GetBorderPart(part.Value));
|
||||
}
|
||||
|
||||
return lookup;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the string representation of a specific border part.
|
||||
/// </summary>
|
||||
/// <param name="part">The part to get a string representation for.</param>
|
||||
/// <param name="count">The number of repetitions.</param>
|
||||
/// <returns>A string representation of the specified border part.</returns>
|
||||
public string GetPart(TableBorderPart part, int count)
|
||||
{
|
||||
// TODO: This need some optimization...
|
||||
return string.Join(string.Empty, Enumerable.Repeat(GetBorderPart(part)[0], count));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a whole column row for the specific column row part.
|
||||
/// </summary>
|
||||
/// <param name="part">The column row part.</param>
|
||||
/// <param name="widths">The column widths.</param>
|
||||
/// <param name="columns">The columns.</param>
|
||||
/// <returns>A string representing the column row.</returns>
|
||||
public virtual string GetColumnRow(TablePart part, IReadOnlyList<int> widths, IReadOnlyList<IColumn> columns)
|
||||
{
|
||||
if (widths is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(widths));
|
||||
}
|
||||
|
||||
if (columns is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(columns));
|
||||
}
|
||||
|
||||
var (left, center, separator, right) = GetTableParts(part);
|
||||
|
||||
var builder = new StringBuilder();
|
||||
builder.Append(left);
|
||||
|
||||
foreach (var (columnIndex, _, lastColumn, columnWidth) in widths.Enumerate())
|
||||
{
|
||||
var padding = columns[columnIndex].Padding;
|
||||
var centerWidth = padding.Left + columnWidth + padding.Right;
|
||||
builder.Append(center.Multiply(centerWidth));
|
||||
|
||||
if (!lastColumn)
|
||||
{
|
||||
builder.Append(separator);
|
||||
}
|
||||
}
|
||||
|
||||
builder.Append(right);
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the string representation of a specific border part.
|
||||
/// </summary>
|
||||
/// <param name="part">The part to get a string representation for.</param>
|
||||
/// <returns>A string representation of the specified border part.</returns>
|
||||
public string GetPart(TableBorderPart part)
|
||||
{
|
||||
return _lookup[part].ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the character representing the specified border part.
|
||||
/// </summary>
|
||||
/// <param name="part">The part to get the character representation for.</param>
|
||||
/// <returns>A character representation of the specified border part.</returns>
|
||||
protected abstract string GetBorderPart(TableBorderPart part);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the table parts used to render a specific table row.
|
||||
/// </summary>
|
||||
/// <param name="part">The table part.</param>
|
||||
/// <returns>The table parts used to render the specific table row.</returns>
|
||||
protected (string Left, string Center, string Separator, string Right)
|
||||
GetTableParts(TablePart part)
|
||||
{
|
||||
return part switch
|
||||
{
|
||||
// Top part
|
||||
TablePart.Top =>
|
||||
(GetPart(TableBorderPart.HeaderTopLeft), GetPart(TableBorderPart.HeaderTop),
|
||||
GetPart(TableBorderPart.HeaderTopSeparator), GetPart(TableBorderPart.HeaderTopRight)),
|
||||
|
||||
// Separator between header and cells
|
||||
TablePart.Separator =>
|
||||
(GetPart(TableBorderPart.HeaderBottomLeft), GetPart(TableBorderPart.HeaderBottom),
|
||||
GetPart(TableBorderPart.HeaderBottomSeparator), GetPart(TableBorderPart.HeaderBottomRight)),
|
||||
|
||||
// Bottom part
|
||||
TablePart.Bottom =>
|
||||
(GetPart(TableBorderPart.FooterBottomLeft), GetPart(TableBorderPart.FooterBottom),
|
||||
GetPart(TableBorderPart.FooterBottomSeparator), GetPart(TableBorderPart.FooterBottomRight)),
|
||||
|
||||
// Unknown
|
||||
_ => throw new NotSupportedException("Unknown column row part"),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user