mirror of
https://github.com/spectreconsole/spectre.console.git
synced 2025-10-25 15:19:23 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1601ef24b3 | ||
|
|
b46d0fa4f6 | ||
|
|
4f06687104 | ||
|
|
003e15686f | ||
|
|
3e9796849b | ||
|
|
3cc19520b0 | ||
|
|
87bde3e5a2 |
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -64,7 +64,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
dotnet tool restore
|
||||
dotnet example diagnostic
|
||||
dotnet example info
|
||||
dotnet example table
|
||||
dotnet example grid
|
||||
dotnet example panel
|
||||
|
||||
19
docs/input/appendix/borders.md
Normal file
19
docs/input/appendix/borders.md
Normal file
@@ -0,0 +1,19 @@
|
||||
Title: Borders
|
||||
Order: 2
|
||||
---
|
||||
|
||||
There is different built-in borders you can use for tables and panels.
|
||||
|
||||
# Built-in borders
|
||||
|
||||
<img src="../assets/images/borders.png" style="max-width: 100%;">
|
||||
|
||||
# Usage
|
||||
|
||||
To create a table and set it's border to `SimpleHeavy` as seen in the
|
||||
image above:
|
||||
|
||||
```csharp
|
||||
var table = new Table();
|
||||
table.Border = Border.SimpleHeavy;
|
||||
```
|
||||
@@ -1,5 +1,5 @@
|
||||
Title: Colors
|
||||
Order: 4
|
||||
Order: 0
|
||||
---
|
||||
|
||||
The following is a list of the standard 8-bit colors supported in terminals.
|
||||
3
docs/input/appendix/index.md
Normal file
3
docs/input/appendix/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Title: Appendix
|
||||
Order: 10
|
||||
---
|
||||
44
docs/input/appendix/styles.md
Normal file
44
docs/input/appendix/styles.md
Normal file
@@ -0,0 +1,44 @@
|
||||
Title: Styles
|
||||
Order: 1
|
||||
---
|
||||
|
||||
Note that what styles that can be used is defined by the system or your terminal software, and may not appear as they should.
|
||||
|
||||
<table class="table">
|
||||
<tr>
|
||||
<td><code>bold</code></td>
|
||||
<td>Bold text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dim</code></td>
|
||||
<td>Dim or faint text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>italic</code></td>
|
||||
<td>Italic text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>underline</code></td>
|
||||
<td>Underlined text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>invert</code></td>
|
||||
<td>Swaps the foreground and background colors</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>conceal</code></td>
|
||||
<td>Hides the text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>slowblink</code></td>
|
||||
<td>Makes text blink slowly</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>rapidblink</code></td>
|
||||
<td>Makes text blink</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>strikethrough</code></td>
|
||||
<td>Shows text with a horizontal line through the center</td>
|
||||
</tr>
|
||||
</table>
|
||||
BIN
docs/input/assets/images/borders.png
Normal file
BIN
docs/input/assets/images/borders.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 415 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB |
BIN
docs/input/assets/images/table.png
Normal file
BIN
docs/input/assets/images/table.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
@@ -1,21 +1,19 @@
|
||||
Title: Markup
|
||||
Order: 3
|
||||
Hidden: False
|
||||
Order: 2
|
||||
---
|
||||
|
||||
In `Spectre.Console` there's a class called `Markup` that
|
||||
allows you to output rich text to the console.
|
||||
|
||||
# Syntax
|
||||
|
||||
Console markup uses a syntax inspired by bbcode. If you write the style (see Styles)
|
||||
in square brackets, e.g. `[bold red]`, that style will apply until it is closed with a `[/]`.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Render(new Markup("[bold yellow]Hello[/] [red]World![/]"));
|
||||
```
|
||||
|
||||
Which should output something similar to the image below. Note that the
|
||||
actual appearance might vary depending on your terminal.
|
||||
|
||||

|
||||
|
||||
|
||||
The `Markup` class implements `IRenderable` which means that you
|
||||
can use this in tables, grids, and panels. Most classes that support
|
||||
rendering of `IRenderable` also have overloads for rendering rich text.
|
||||
@@ -58,47 +56,8 @@ You can set the background color in markup by prefixing the color with
|
||||
|
||||
# Colors
|
||||
|
||||
For a list of colors, see the [Colors](xref:colors) section.
|
||||
For a list of colors, see the [Colors](xref:colors) appendix section.
|
||||
|
||||
# Styles
|
||||
|
||||
Note that what styles that can be used is defined by the system or your terminal software, and may not appear as they should.
|
||||
|
||||
<table class="table">
|
||||
<tr>
|
||||
<td><code>bold</code></td>
|
||||
<td>Bold text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dim</code></td>
|
||||
<td>Dim or faint text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>italic</code></td>
|
||||
<td>Italic text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>underline</code></td>
|
||||
<td>Underlined text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>invert</code></td>
|
||||
<td>Swaps the foreground and background colors</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>conceal</code></td>
|
||||
<td>Hides the text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>slowblink</code></td>
|
||||
<td>Makes text blink slowly</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>rapidblink</code></td>
|
||||
<td>Makes text blink</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>strikethrough</code></td>
|
||||
<td>Shows text with a horizontal line through the center</td>
|
||||
</tr>
|
||||
</table>
|
||||
For a list of styles, see the [Styles](xref:styles) appendix section.
|
||||
120
docs/input/tables.md
Normal file
120
docs/input/tables.md
Normal file
@@ -0,0 +1,120 @@
|
||||
Title: Tables
|
||||
Order: 3
|
||||
---
|
||||
|
||||
Tables are a perfect way of displaying tabular data in a terminal.
|
||||
|
||||
`Spectre.Console` is super smart about rendering tables and will adjust
|
||||
all columns to fit whatever is inside them. Anything that implements
|
||||
`IRenderable` can be used as a column header or column cell, even another table!
|
||||
|
||||
# Usage
|
||||
|
||||
<!------------------------->
|
||||
<!--- USAGE --->
|
||||
<!------------------------->
|
||||
|
||||
To render a table, create a `Table` instance, add the number of
|
||||
columns that you need, and then add the rows. Finish by passing the
|
||||
table to a console's `Render` method.
|
||||
|
||||
```csharp
|
||||
// Create a table
|
||||
var table = new Table();
|
||||
|
||||
// Add some columns
|
||||
table.AddColumn("Foo");
|
||||
table.AddColumn(new TableColumn("Bar").Centered());
|
||||
|
||||
// Add some rows
|
||||
table.AddRow("Baz", "[green]Qux[/]");
|
||||
table.AddRow(new Markup("[blue]Corgi[/]"), new Panel("Waldo"));
|
||||
|
||||
// Render the table to the console
|
||||
AnsiConsole.Render(table);
|
||||
```
|
||||
|
||||
This will render the following output:
|
||||
|
||||

|
||||
|
||||
# Table appearance
|
||||
|
||||
<!------------------------->
|
||||
<!--- TABLE APPEARANCE --->
|
||||
<!------------------------->
|
||||
|
||||
## Borders
|
||||
|
||||
For a list of borders, see the [Borders](xref:borders) appendix section.
|
||||
|
||||
```csharp
|
||||
// Sets the border
|
||||
table.SetBorder(Border.None);
|
||||
table.SetBorder(Border.Ascii);
|
||||
table.SetBorder(Border.Square);
|
||||
table.SetBorder(Border.Rounded);
|
||||
```
|
||||
|
||||
## Expand / Collapse
|
||||
|
||||
```csharp
|
||||
// Table will take up as much space as it can
|
||||
// with respect to other things.
|
||||
table.Expand();
|
||||
|
||||
// Table will take up minimal width
|
||||
table.Collapse();
|
||||
```
|
||||
|
||||
## Hide headers
|
||||
|
||||
```csharp
|
||||
// Hides all column headers
|
||||
table.HideHeaders();
|
||||
```
|
||||
|
||||
## Set table width
|
||||
|
||||
```csharp
|
||||
// Sets the table width to 50 cells
|
||||
table.SetWidth(50);
|
||||
```
|
||||
|
||||
# Column appearance
|
||||
|
||||
<!------------------------->
|
||||
<!--- COLUMN APPEARANCE --->
|
||||
<!------------------------->
|
||||
|
||||
## Alignment
|
||||
|
||||
```csharp
|
||||
// Set the alignment explicitly
|
||||
column.SetAlignment(Justify.Right);
|
||||
```
|
||||
|
||||
## Padding
|
||||
|
||||
```csharp
|
||||
// Set left and right padding
|
||||
column.SetPadding(left: 3, right: 5);
|
||||
|
||||
// Set padding individually.
|
||||
column.PadLeft(3);
|
||||
column.PadRight(5);
|
||||
```
|
||||
|
||||
## Disable column wrapping
|
||||
|
||||
```csharp
|
||||
// Disable column wrapping
|
||||
column.NoWrap();
|
||||
```
|
||||
|
||||
## Set column width
|
||||
|
||||
```csharp
|
||||
// Set the column width (no fluent extension method for this yet)
|
||||
column.Width = 15;
|
||||
```
|
||||
14
examples/Borders/Borders.csproj
Normal file
14
examples/Borders/Borders.csproj
Normal file
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Description>Demonstrates the different kind of borders.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
48
examples/Borders/Program.cs
Normal file
48
examples/Borders/Program.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Borders
|
||||
{
|
||||
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),
|
||||
};
|
||||
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.Render(new Columns(items).Collapse());
|
||||
}
|
||||
|
||||
private static IRenderable Create(string name, Border border)
|
||||
{
|
||||
var table = new Table().SetBorder(border);
|
||||
table.AddColumns("[yellow]Header 1[/]", "[yellow]Header 2[/]");
|
||||
table.AddRow("Cell", "Cell");
|
||||
table.AddRow("Cell", "Cell");
|
||||
|
||||
return new Panel(table)
|
||||
.SetHeader($" {name} ", Style.Parse("blue"), Justify.Center)
|
||||
.SetBorderStyle(Style.Parse("grey"))
|
||||
.NoBorder();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace PanelExample
|
||||
{
|
||||
@@ -14,7 +13,7 @@ namespace PanelExample
|
||||
AnsiConsole.Render(
|
||||
new Panel(
|
||||
new Panel(content)
|
||||
.SetBorderKind(BorderKind.Rounded)));
|
||||
.SetBorder(Border.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().SetBorderKind(BorderKind.Rounded);
|
||||
var table = new Table().SetBorder(Border.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().SetBorderKind(BorderKind.Rounded).SetBorderColor(Color.Red);
|
||||
var simple = new Table().SetBorder(Border.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().SetBorderKind(BorderKind.Square).SetBorderColor(Color.Green);
|
||||
var second = new Table().SetBorder(Border.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().SetBorderKind(BorderKind.Rounded);
|
||||
var table = new Table().SetBorder(Border.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)));
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.113">
|
||||
<PrivateAssets>All</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Roslynator.Analyzers" Version="2.3.0">
|
||||
<PackageReference Include="Roslynator.Analyzers" Version="3.0.0">
|
||||
<PrivateAssets>All</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using Shouldly;
|
||||
using Spectre.Console.Rendering;
|
||||
using Xunit;
|
||||
@@ -7,35 +6,794 @@ namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
public sealed class BorderTests
|
||||
{
|
||||
public sealed class TheGetBorderMethod
|
||||
public sealed class NoBorder
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(BorderKind.None, false, typeof(NoBorder))]
|
||||
[InlineData(BorderKind.Ascii, false, typeof(AsciiBorder))]
|
||||
[InlineData(BorderKind.Square, false, typeof(SquareBorder))]
|
||||
[InlineData(BorderKind.Rounded, false, typeof(RoundedBorder))]
|
||||
[InlineData(BorderKind.None, true, typeof(NoBorder))]
|
||||
[InlineData(BorderKind.Ascii, true, typeof(AsciiBorder))]
|
||||
[InlineData(BorderKind.Square, true, typeof(SquareBorder))]
|
||||
[InlineData(BorderKind.Rounded, true, typeof(SquareBorder))]
|
||||
public void Should_Return_Correct_Border_For_Specified_Kind(BorderKind kind, bool safe, Type expected)
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var result = Border.GetBorder(kind, safe);
|
||||
var visibility = Border.None.Visible;
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType(expected);
|
||||
visibility.ShouldBeFalse();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.None.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.None);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Throw_If_Unknown_Border_Kind_Is_Specified()
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given, When
|
||||
var result = Record.Exception(() => Border.GetBorder((BorderKind)int.MaxValue, false));
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().NoBorder();
|
||||
|
||||
// When
|
||||
console.Render(table);
|
||||
|
||||
// Then
|
||||
result.ShouldBeOfType<InvalidOperationException>();
|
||||
result.Message.ShouldBe("Unknown border kind");
|
||||
console.Lines.Count.ShouldBe(3);
|
||||
console.Lines[0].ShouldBe("Header 1 Header 2");
|
||||
console.Lines[1].ShouldBe("Cell Cell ");
|
||||
console.Lines[2].ShouldBe("Cell Cell ");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AsciiBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Ascii.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Ascii.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Ascii);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().AsciiBorder();
|
||||
|
||||
// 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("+---------------------+");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Ascii2Border
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Ascii2.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Ascii2.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Ascii2);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().Ascii2Border();
|
||||
|
||||
// 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("+----------+----------+");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AsciiDoubleHeadBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.AsciiDoubleHead.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.AsciiDoubleHead.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.AsciiDoubleHead);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().AsciiDoubleHeadBorder();
|
||||
|
||||
// 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("+----------+----------+");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SquareBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Square.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Square.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Square);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().SquareBorder();
|
||||
|
||||
// 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("└──────────┴──────────┘");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RoundedBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Rounded.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Rounded.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Square);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().RoundedBorder();
|
||||
|
||||
// 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("╰──────────┴──────────╯");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MinimalBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Minimal.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Minimal.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Minimal);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().MinimalBorder();
|
||||
|
||||
// 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(" ");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MinimalHeavyHeadBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.MinimalHeavyHead.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.MinimalHeavyHead.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Minimal);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().MinimalHeavyHeadBorder();
|
||||
|
||||
// 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(" ");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MinimalDoubleHeadBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.MinimalDoubleHead.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.MinimalDoubleHead.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.MinimalDoubleHead);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().MinimalDoubleHeadBorder();
|
||||
|
||||
// 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(" ");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SimpleBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Simple.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Simple.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Simple);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().SimpleBorder();
|
||||
|
||||
// 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(" ");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HorizontalBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Horizontal.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Horizontal.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Horizontal);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().HorizontalBorder();
|
||||
|
||||
// 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("───────────────────────");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SimpleHeavyBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.SimpleHeavy.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.SimpleHeavy.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Simple);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().SimpleHeavyBorder();
|
||||
|
||||
// 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(" ");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HeavyBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Heavy.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Heavy.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Square);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().HeavyBorder();
|
||||
|
||||
// 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("┗━━━━━━━━━━┻━━━━━━━━━━┛");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HeavyEdgeBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.HeavyEdge.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.HeavyEdge.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Square);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().HeavyEdgeBorder();
|
||||
|
||||
// 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("┗━━━━━━━━━━┷━━━━━━━━━━┛");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class HeavyHeadBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.HeavyHead.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.HeavyHead.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Square);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().HeavyHeadBorder();
|
||||
|
||||
// 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("└──────────┴──────────┘");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DoubleBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.Double.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.Double.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.Double);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().DoubleBorder();
|
||||
|
||||
// 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("╚══════════╩══════════╝");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DoubleEdgeBorder
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Correct_Visibility()
|
||||
{
|
||||
// Given, When
|
||||
var visibility = Border.DoubleEdge.Visible;
|
||||
|
||||
// Then
|
||||
visibility.ShouldBeTrue();
|
||||
}
|
||||
|
||||
public sealed class TheSafeGetBorderMethod
|
||||
{
|
||||
[Fact]
|
||||
public void Should_Return_Safe_Border()
|
||||
{
|
||||
// Given, When
|
||||
var border = Border.DoubleEdge.GetSafeBorder(safe: true);
|
||||
|
||||
// Then
|
||||
border.ShouldBeSameAs(Border.DoubleEdge);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_Render_As_Expected()
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole();
|
||||
var table = Fixture.GetTable().DoubleEdgeBorder();
|
||||
|
||||
// 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()
|
||||
{
|
||||
var table = new Table();
|
||||
table.AddColumns("Header 1", "Header 2");
|
||||
table.AddRow("Cell", "Cell");
|
||||
table.AddRow("Cell", "Cell");
|
||||
return table;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
// When
|
||||
console.Render(new Panel("Hello World")
|
||||
{
|
||||
Header = new Header("Greeting"),
|
||||
Header = new PanelHeader("Greeting"),
|
||||
Expand = true,
|
||||
Padding = new Padding(2, 2),
|
||||
});
|
||||
@@ -70,7 +70,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
// When
|
||||
console.Render(new Panel("Hello World")
|
||||
{
|
||||
Header = new Header("Greeting").LeftAligned(),
|
||||
Header = new PanelHeader("Greeting").LeftAligned(),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
// When
|
||||
console.Render(new Panel("Hello World")
|
||||
{
|
||||
Header = new Header("Greeting").Centered(),
|
||||
Header = new PanelHeader("Greeting").Centered(),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
// When
|
||||
console.Render(new Panel("Hello World")
|
||||
{
|
||||
Header = new Header("Greeting").RightAligned(),
|
||||
Header = new PanelHeader("Greeting").RightAligned(),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
// When
|
||||
console.Render(new Panel("Hello World")
|
||||
{
|
||||
Header = new Header("Greeting"),
|
||||
Header = new PanelHeader("Greeting"),
|
||||
Expand = true,
|
||||
});
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
// A simple table
|
||||
var console = new PlainConsole(width: 80);
|
||||
var table = new Table() { BorderKind = BorderKind.Rounded };
|
||||
var table = new Table() { Border = Border.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)
|
||||
{
|
||||
BorderKind = BorderKind.Ascii,
|
||||
Border = Border.Ascii,
|
||||
}));
|
||||
|
||||
// Then
|
||||
@@ -255,7 +255,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
// Given
|
||||
var console = new PlainConsole(width: 80);
|
||||
var table = new Table { BorderKind = BorderKind.Ascii };
|
||||
var table = new Table { Border = Border.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 { BorderKind = BorderKind.Rounded };
|
||||
var table = new Table { Border = Border.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 { BorderKind = BorderKind.None };
|
||||
var table = new Table { Border = Border.None };
|
||||
table.AddColumns("Foo", "Bar", "Baz");
|
||||
table.AddRow("Qux", "Corgi", "Waldo");
|
||||
table.AddRow("Grault", "Garply", "Fred");
|
||||
|
||||
@@ -29,6 +29,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Columns", "..\examples\Colu
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Info", "..\examples\Info\Info.csproj", "{225CE0D4-06AB-411A-8D29-707504FE53B3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borders", "..\examples\Borders\Borders.csproj", "{094245E6-4C94-485D-B5AC-3153E878B112}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -135,6 +137,18 @@ Global
|
||||
{225CE0D4-06AB-411A-8D29-707504FE53B3}.Release|x64.Build.0 = Release|Any CPU
|
||||
{225CE0D4-06AB-411A-8D29-707504FE53B3}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{225CE0D4-06AB-411A-8D29-707504FE53B3}.Release|x86.Build.0 = Release|Any CPU
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112}.Release|x64.Build.0 = Release|Any CPU
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -146,6 +160,7 @@ Global
|
||||
{1F51C55C-BA4C-4856-9001-0F7924FFB179} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
||||
{33357599-C79D-4299-888F-634E2C3EACEF} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
||||
{225CE0D4-06AB-411A-8D29-707504FE53B3} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
||||
{094245E6-4C94-485D-B5AC-3153E878B112} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5729B071-67A0-48FB-8B1B-275E6822086C}
|
||||
|
||||
97
src/Spectre.Console/Border.Known.cs
Normal file
97
src/Spectre.Console/Border.Known.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a border.
|
||||
/// </summary>
|
||||
public abstract partial class Border
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets an invisible border.
|
||||
/// </summary>
|
||||
public static Border None { get; } = new NoBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an ASCII border.
|
||||
/// </summary>
|
||||
public static Border Ascii { get; } = new AsciiBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets another ASCII border.
|
||||
/// </summary>
|
||||
public static Border Ascii2 { get; } = new Ascii2Border();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an ASCII border with a double header border.
|
||||
/// </summary>
|
||||
public static Border AsciiDoubleHead { get; } = new AsciiDoubleHeadBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a square border.
|
||||
/// </summary>
|
||||
public static Border Square { get; } = new SquareBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a rounded border.
|
||||
/// </summary>
|
||||
public static Border Rounded { get; } = new RoundedBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a minimal border.
|
||||
/// </summary>
|
||||
public static Border Minimal { get; } = new MinimalBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a minimal border with a heavy head.
|
||||
/// </summary>
|
||||
public static Border MinimalHeavyHead { get; } = new MinimalHeavyHeadBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a minimal border with a double header border.
|
||||
/// </summary>
|
||||
public static Border MinimalDoubleHead { get; } = new MinimalDoubleHeadBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a simple border.
|
||||
/// </summary>
|
||||
public static Border Simple { get; } = new SimpleBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a simple border with heavy lines.
|
||||
/// </summary>
|
||||
public static Border SimpleHeavy { get; } = new SimpleHeavyBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a horizontal border.
|
||||
/// </summary>
|
||||
public static Border Horizontal { get; } = new HorizontalBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a heavy border.
|
||||
/// </summary>
|
||||
public static Border Heavy { get; } = new HeavyBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a border with a heavy edge.
|
||||
/// </summary>
|
||||
public static Border HeavyEdge { get; } = new HeavyEdgeBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a border with a heavy header.
|
||||
/// </summary>
|
||||
public static Border HeavyHead { get; } = new HeavyHeadBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a double border.
|
||||
/// </summary>
|
||||
[SuppressMessage("Naming", "CA1720:Identifier contains type name")]
|
||||
public static Border Double { get; } = new DoubleBorder();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a border with a double edge.
|
||||
/// </summary>
|
||||
public static Border DoubleEdge { get; } = new DoubleEdgeBorder();
|
||||
}
|
||||
}
|
||||
@@ -2,28 +2,26 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a border used by tables.
|
||||
/// Represents a border.
|
||||
/// </summary>
|
||||
public abstract class Border
|
||||
public abstract partial class Border
|
||||
{
|
||||
private readonly Dictionary<BorderPart, string> _lookup;
|
||||
|
||||
private static readonly Dictionary<BorderKind, Border> _borders = new Dictionary<BorderKind, Border>
|
||||
{
|
||||
{ BorderKind.None, new NoBorder() },
|
||||
{ BorderKind.Ascii, new AsciiBorder() },
|
||||
{ BorderKind.Square, new SquareBorder() },
|
||||
{ BorderKind.Rounded, new RoundedBorder() },
|
||||
};
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether or not the border is visible.
|
||||
/// </summary>
|
||||
public virtual bool Visible { get; } = true;
|
||||
|
||||
private static readonly Dictionary<BorderKind, BorderKind> _safeLookup = new Dictionary<BorderKind, BorderKind>
|
||||
{
|
||||
{ BorderKind.Rounded, BorderKind.Square },
|
||||
};
|
||||
/// <summary>
|
||||
/// Gets the safe border for this border or <c>null</c> if none exist.
|
||||
/// </summary>
|
||||
public virtual Border? SafeBorder { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Border"/> class.
|
||||
@@ -33,27 +31,6 @@ namespace Spectre.Console.Rendering
|
||||
_lookup = Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="Border"/> represented by the specified <see cref="BorderKind"/>.
|
||||
/// </summary>
|
||||
/// <param name="kind">The kind of border to get.</param>
|
||||
/// <param name="safe">Whether or not to get a "safe" border that can be rendered in a legacy console.</param>
|
||||
/// <returns>A <see cref="Border"/> instance representing the specified <see cref="BorderKind"/>.</returns>
|
||||
public static Border GetBorder(BorderKind kind, bool safe)
|
||||
{
|
||||
if (safe && _safeLookup.TryGetValue(kind, out var safeKind))
|
||||
{
|
||||
kind = safeKind;
|
||||
}
|
||||
|
||||
if (!_borders.TryGetValue(kind, out var border))
|
||||
{
|
||||
throw new InvalidOperationException("Unknown border kind");
|
||||
}
|
||||
|
||||
return border;
|
||||
}
|
||||
|
||||
private Dictionary<BorderPart, string> Initialize()
|
||||
{
|
||||
var lookup = new Dictionary<BorderPart, string>();
|
||||
37
src/Spectre.Console/Borders/Ascii2Border.cs
Normal file
37
src/Spectre.Console/Borders/Ascii2Border.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/Spectre.Console/Borders/AsciiDoubleHeadBorder.cs
Normal file
37
src/Spectre.Console/Borders/AsciiDoubleHeadBorder.cs
Normal file
@@ -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 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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/Spectre.Console/Borders/DoubleBorder.cs
Normal file
37
src/Spectre.Console/Borders/DoubleBorder.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/Spectre.Console/Borders/DoubleEdgeBorder.cs
Normal file
37
src/Spectre.Console/Borders/DoubleEdgeBorder.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/Spectre.Console/Borders/HeavyBorder.cs
Normal file
40
src/Spectre.Console/Borders/HeavyBorder.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/Spectre.Console/Borders/HeavyEdgeBorder.cs
Normal file
40
src/Spectre.Console/Borders/HeavyEdgeBorder.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/Spectre.Console/Borders/HeavyHeadBorder.cs
Normal file
40
src/Spectre.Console/Borders/HeavyHeadBorder.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/Spectre.Console/Borders/HorizontalBorder.cs
Normal file
37
src/Spectre.Console/Borders/HorizontalBorder.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/Spectre.Console/Borders/MinimalBorder.cs
Normal file
37
src/Spectre.Console/Borders/MinimalBorder.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/Spectre.Console/Borders/MinimalDoubleHeadBorder.cs
Normal file
37
src/Spectre.Console/Borders/MinimalDoubleHeadBorder.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/Spectre.Console/Borders/MinimalHeavyHeadBorder.cs
Normal file
40
src/Spectre.Console/Borders/MinimalHeavyHeadBorder.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,9 @@ namespace Spectre.Console.Rendering
|
||||
/// </summary>
|
||||
public sealed class NoBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override bool Visible => false;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
@@ -7,6 +7,9 @@ namespace Spectre.Console.Rendering
|
||||
/// </summary>
|
||||
public sealed class RoundedBorder : Border
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override Border? SafeBorder { get; } = Border.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string GetBoxPart(BorderPart part)
|
||||
{
|
||||
37
src/Spectre.Console/Borders/SimpleBorder.cs
Normal file
37
src/Spectre.Console/Borders/SimpleBorder.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/Spectre.Console/Borders/SimpleHeavyBorder.cs
Normal file
40
src/Spectre.Console/Borders/SimpleHeavyBorder.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
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."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="IAnsiConsole"/>.
|
||||
/// </summary>
|
||||
public static partial class ConsoleExtensions
|
||||
public static partial class AnsiConsoleExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the specified markup to the console.
|
||||
@@ -8,7 +8,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="IAnsiConsole"/>.
|
||||
/// </summary>
|
||||
public static partial class ConsoleExtensions
|
||||
public static partial class AnsiConsoleExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Renders the specified object to the console.
|
||||
@@ -6,7 +6,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="IAnsiConsole"/>.
|
||||
/// </summary>
|
||||
public static partial class ConsoleExtensions
|
||||
public static partial class AnsiConsoleExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the specified string value to the console.
|
||||
@@ -6,7 +6,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="IAnsiConsole"/>.
|
||||
/// </summary>
|
||||
public static partial class ConsoleExtensions
|
||||
public static partial class AnsiConsoleExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes an empty line to the console.
|
||||
@@ -5,7 +5,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="IAnsiConsole"/>.
|
||||
/// </summary>
|
||||
public static partial class ConsoleExtensions
|
||||
public static partial class AnsiConsoleExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Resets colors and text decorations.
|
||||
31
src/Spectre.Console/Extensions/BorderExtensions.cs
Normal file
31
src/Spectre.Console/Extensions/BorderExtensions.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="Border"/>.
|
||||
/// </summary>
|
||||
public static class BorderExtensions
|
||||
{
|
||||
/// <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 Border GetSafeBorder(this Border border, bool safe)
|
||||
{
|
||||
if (border is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(border));
|
||||
}
|
||||
|
||||
if (safe && border.SafeBorder != null)
|
||||
{
|
||||
border = border.SafeBorder;
|
||||
}
|
||||
|
||||
return border;
|
||||
}
|
||||
}
|
||||
}
|
||||
289
src/Spectre.Console/Extensions/HasBorderExtensions.cs
Normal file
289
src/Spectre.Console/Extensions/HasBorderExtensions.cs
Normal file
@@ -0,0 +1,289 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="IHasBorder"/>.
|
||||
/// </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>
|
||||
/// <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 NoSafeBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
obj.UseSafeBorder = false;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the border style.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border color for.</param>
|
||||
/// <param name="style">The border style to set.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SetBorderStyle<T>(this T obj, Style style)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
obj.BorderStyle = style;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the border color.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border color for.</param>
|
||||
/// <param name="color">The border color to set.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SetBorderColor<T>(this T obj, Color color)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
obj.BorderStyle = (obj.BorderStyle ?? Style.Plain).WithForeground(color);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ namespace Spectre.Console
|
||||
throw new ArgumentNullException(nameof(text));
|
||||
}
|
||||
|
||||
return SetHeader(panel, new Header(text, style, alignment));
|
||||
return SetHeader(panel, new PanelHeader(text, style, alignment));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -36,7 +36,7 @@ namespace Spectre.Console
|
||||
/// <param name="panel">The panel.</param>
|
||||
/// <param name="header">The header to use.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static Panel SetHeader(this Panel panel, Header header)
|
||||
public static Panel SetHeader(this Panel panel, PanelHeader header)
|
||||
{
|
||||
if (panel is null)
|
||||
{
|
||||
@@ -10,12 +10,12 @@ namespace Spectre.Console
|
||||
/// a "safe" border on legacy consoles that might not be able
|
||||
/// to render non-ASCII characters.
|
||||
/// </summary>
|
||||
bool SafeBorder { get; set; }
|
||||
bool UseSafeBorder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the kind of border to use.
|
||||
/// Gets or sets the border.
|
||||
/// </summary>
|
||||
public BorderKind BorderKind { get; set; }
|
||||
public Border Border { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the border style.
|
||||
@@ -1,28 +0,0 @@
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents different kinds of borders.
|
||||
/// </summary>
|
||||
public enum BorderKind
|
||||
{
|
||||
/// <summary>
|
||||
/// No border.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// A square border.
|
||||
/// </summary>
|
||||
Square = 1,
|
||||
|
||||
/// <summary>
|
||||
/// An old school ASCII border.
|
||||
/// </summary>
|
||||
Ascii = 2,
|
||||
|
||||
/// <summary>
|
||||
/// A rounded border.
|
||||
/// </summary>
|
||||
Rounded = 3,
|
||||
}
|
||||
}
|
||||
@@ -266,8 +266,8 @@ namespace Spectre.Console.Rendering
|
||||
/// </summary>
|
||||
/// <param name="segment">The segment to split.</param>
|
||||
/// <param name="overflow">The overflow strategy to use.</param>
|
||||
/// <param name="encoding">The encodign to use.</param>
|
||||
/// <param name="width">The maxiumum width.</param>
|
||||
/// <param name="encoding">The encoding to use.</param>
|
||||
/// <param name="width">The maximum width.</param>
|
||||
/// <returns>A list of segments that has been split.</returns>
|
||||
public static List<Segment> SplitOverflow(Segment segment, Overflow? overflow, Encoding encoding, int width)
|
||||
{
|
||||
@@ -317,7 +317,7 @@ namespace Spectre.Console.Rendering
|
||||
new Segment(text, style),
|
||||
Overflow.Ellipsis,
|
||||
encoding,
|
||||
maxWidth).First();
|
||||
maxWidth)[0];
|
||||
}
|
||||
|
||||
internal static List<List<SegmentLine>> MakeSameHeight(int cellHeight, List<List<SegmentLine>> cells)
|
||||
|
||||
@@ -3,20 +3,34 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
internal sealed class SegmentLineEnumerator : IEnumerable<Segment>
|
||||
/// <summary>
|
||||
/// An enumerator for <see cref="SegmentLine"/> collections.
|
||||
/// </summary>
|
||||
public sealed class SegmentLineEnumerator : IEnumerable<Segment>
|
||||
{
|
||||
private readonly List<SegmentLine> _lines;
|
||||
|
||||
public SegmentLineEnumerator(List<SegmentLine> lines)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SegmentLineEnumerator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="lines">The lines to enumerate.</param>
|
||||
public SegmentLineEnumerator(IEnumerable<SegmentLine> lines)
|
||||
{
|
||||
_lines = lines;
|
||||
if (lines is null)
|
||||
{
|
||||
throw new System.ArgumentNullException(nameof(lines));
|
||||
}
|
||||
|
||||
_lines = new List<SegmentLine>(lines);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<Segment> GetEnumerator()
|
||||
{
|
||||
return new SegmentLineIterator(_lines);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
|
||||
@@ -3,29 +3,48 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Spectre.Console.Rendering
|
||||
{
|
||||
internal sealed class SegmentLineIterator : IEnumerator<Segment>
|
||||
/// <summary>
|
||||
/// An iterator for <see cref="SegmentLine"/> collections.
|
||||
/// </summary>
|
||||
public sealed class SegmentLineIterator : IEnumerator<Segment>
|
||||
{
|
||||
private readonly List<SegmentLine> _lines;
|
||||
private int _currentLine;
|
||||
private int _currentIndex;
|
||||
private bool _lineBreakEmitted;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current segment.
|
||||
/// </summary>
|
||||
public Segment Current { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
object? IEnumerator.Current => Current;
|
||||
|
||||
public SegmentLineIterator(List<SegmentLine> lines)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SegmentLineIterator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="lines">The lines to iterate.</param>
|
||||
public SegmentLineIterator(IEnumerable<SegmentLine> lines)
|
||||
{
|
||||
if (lines is null)
|
||||
{
|
||||
throw new System.ArgumentNullException(nameof(lines));
|
||||
}
|
||||
|
||||
_currentLine = 0;
|
||||
_currentIndex = -1;
|
||||
_lines = lines;
|
||||
_lines = new List<SegmentLine>(lines);
|
||||
|
||||
Current = Segment.Empty;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_currentLine > _lines.Count - 1)
|
||||
@@ -88,6 +107,7 @@ namespace Spectre.Console.Rendering
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Reset()
|
||||
{
|
||||
_currentLine = 0;
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Spectre.Console.Internal;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a table.
|
||||
/// </summary>
|
||||
public sealed partial class Table
|
||||
{
|
||||
private const int EdgeCount = 2;
|
||||
|
||||
// Calculate the widths of each column, including padding, not including borders.
|
||||
// Ported from Rich by Will McGugan, licensed under MIT.
|
||||
// https://github.com/willmcgugan/rich/blob/527475837ebbfc427530b3ee0d4d0741d2d0fc6d/rich/table.py#L394
|
||||
private List<int> CalculateColumnWidths(RenderContext options, int maxWidth)
|
||||
{
|
||||
var width_ranges = _columns.Select(column => MeasureColumn(column, options, maxWidth)).ToArray();
|
||||
var widths = width_ranges.Select(range => range.Max).ToList();
|
||||
|
||||
var tableWidth = widths.Sum();
|
||||
|
||||
if (tableWidth > maxWidth)
|
||||
{
|
||||
var wrappable = _columns.Select(c => !c.NoWrap).ToList();
|
||||
widths = CollapseWidths(widths, wrappable, maxWidth);
|
||||
tableWidth = widths.Sum();
|
||||
|
||||
// last resort, reduce columns evenly
|
||||
if (tableWidth > maxWidth)
|
||||
{
|
||||
var excessWidth = tableWidth - maxWidth;
|
||||
widths = Ratio.Reduce(excessWidth, widths.Select(_ => 1).ToList(), widths, widths);
|
||||
tableWidth = widths.Sum();
|
||||
}
|
||||
}
|
||||
|
||||
if (tableWidth < maxWidth && ShouldExpand())
|
||||
{
|
||||
var padWidths = Ratio.Distribute(maxWidth - tableWidth, widths);
|
||||
widths = widths.Zip(padWidths, (a, b) => (a, b)).Select(f => f.a + f.b).ToList();
|
||||
}
|
||||
|
||||
return widths;
|
||||
}
|
||||
|
||||
// Reduce widths so that the total is less or equal to the max width.
|
||||
// Ported from Rich by Will McGugan, licensed under MIT.
|
||||
// https://github.com/willmcgugan/rich/blob/527475837ebbfc427530b3ee0d4d0741d2d0fc6d/rich/table.py#L442
|
||||
private static List<int> CollapseWidths(List<int> widths, List<bool> wrappable, int maxWidth)
|
||||
{
|
||||
var totalWidth = widths.Sum();
|
||||
var excessWidth = totalWidth - maxWidth;
|
||||
|
||||
if (wrappable.AnyTrue())
|
||||
{
|
||||
while (totalWidth != 0 && excessWidth > 0)
|
||||
{
|
||||
var maxColumn = widths.Zip(wrappable, (first, second) => (width: first, allowWrap: second))
|
||||
.Where(x => x.allowWrap)
|
||||
.Max(x => x.width);
|
||||
|
||||
var secondMaxColumn = widths.Zip(wrappable, (width, allowWrap) => allowWrap && width != maxColumn ? width : 1).Max();
|
||||
var columnDifference = maxColumn - secondMaxColumn;
|
||||
|
||||
var ratios = widths.Zip(wrappable, (width, allowWrap) => width == maxColumn && allowWrap ? 1 : 0).ToList();
|
||||
if (!ratios.Any(x => x != 0) || columnDifference == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var maxReduce = widths.Select(_ => Math.Min(excessWidth, columnDifference)).ToList();
|
||||
widths = Ratio.Reduce(excessWidth, ratios, maxReduce, widths);
|
||||
|
||||
totalWidth = widths.Sum();
|
||||
excessWidth = totalWidth - maxWidth;
|
||||
}
|
||||
}
|
||||
|
||||
return widths;
|
||||
}
|
||||
|
||||
private (int Min, int Max) MeasureColumn(TableColumn column, RenderContext options, int maxWidth)
|
||||
{
|
||||
var padding = column.Padding.GetHorizontalPadding();
|
||||
|
||||
// Predetermined width?
|
||||
if (column.Width != null)
|
||||
{
|
||||
return (column.Width.Value + padding, column.Width.Value + padding);
|
||||
}
|
||||
|
||||
var columnIndex = _columns.IndexOf(column);
|
||||
var rows = _rows.Select(row => row[columnIndex]);
|
||||
|
||||
var minWidths = new List<int>();
|
||||
var maxWidths = new List<int>();
|
||||
|
||||
// Include columns in measurement
|
||||
var measure = column.Text.Measure(options, maxWidth);
|
||||
minWidths.Add(measure.Min);
|
||||
maxWidths.Add(measure.Max);
|
||||
|
||||
foreach (var row in rows)
|
||||
{
|
||||
measure = row.Measure(options, maxWidth);
|
||||
minWidths.Add(measure.Min);
|
||||
maxWidths.Add(measure.Max);
|
||||
}
|
||||
|
||||
return (minWidths.Count > 0 ? minWidths.Max() : padding,
|
||||
maxWidths.Count > 0 ? maxWidths.Max() : maxWidth);
|
||||
}
|
||||
|
||||
private int GetExtraWidth(bool includePadding)
|
||||
{
|
||||
var hideBorder = BorderKind == BorderKind.None;
|
||||
var separators = hideBorder ? 0 : _columns.Count - 1;
|
||||
var edges = hideBorder ? 0 : EdgeCount;
|
||||
var padding = includePadding ? _columns.Select(x => x.Padding.GetHorizontalPadding()).Sum() : 0;
|
||||
|
||||
if (!PadRightCell)
|
||||
{
|
||||
padding -= _columns.Last().Padding.Right;
|
||||
}
|
||||
|
||||
return separators + edges + padding;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="IHasBorder"/>.
|
||||
/// </summary>
|
||||
public static class BorderExtensions
|
||||
{
|
||||
/// <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 SetBorderKind(obj, BorderKind.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 SetBorderKind(obj, BorderKind.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 SetBorderKind(obj, BorderKind.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, IHasBorder
|
||||
{
|
||||
return SetBorderKind(obj, BorderKind.Rounded);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the border kind.
|
||||
/// </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 kind to use.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SetBorderKind<T>(this T obj, BorderKind border)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
obj.BorderKind = border;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables the safe 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 NoSafeBorder<T>(this T obj)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
obj.SafeBorder = false;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the border style.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border color for.</param>
|
||||
/// <param name="style">The border style to set.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SetBorderStyle<T>(this T obj, Style style)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
obj.BorderStyle = style;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the border color.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object type with a border.</typeparam>
|
||||
/// <param name="obj">The object to set the border color for.</param>
|
||||
/// <param name="color">The border color to set.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T SetBorderColor<T>(this T obj, Color color)
|
||||
where T : class, IHasBorder
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
obj.BorderStyle = (obj.BorderStyle ?? Style.Plain).WithForeground(color);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,21 @@
|
||||
<None Include="../../resources/gfx/small-logo.png" Pack="true" PackagePath="\" Link="Properties/small-logo.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<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="Extensions/AnsiConsoleExtensions.*.cs">
|
||||
<DependentUpon>Extensions/AnsiConsoleExtensions.cs</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TunnelVisionLabs.ReferenceAssemblyAnnotator" Version="1.0.0-alpha.160" PrivateAssets="all" />
|
||||
<PackageDownload Include="Microsoft.NETCore.App.Ref" Version="[$(AnnotatedReferenceAssemblyVersion)]" />
|
||||
@@ -18,6 +33,21 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Extensions\AnsiConsoleExtensions.Markup.cs">
|
||||
<DependentUpon>AnsiConsoleExtensions.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Extensions\AnsiConsoleExtensions.Rendering.cs">
|
||||
<DependentUpon>AnsiConsoleExtensions.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Extensions\AnsiConsoleExtensions.Write.cs">
|
||||
<DependentUpon>AnsiConsoleExtensions.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Extensions\AnsiConsoleExtensions.WriteLine.cs">
|
||||
<DependentUpon>AnsiConsoleExtensions.cs</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<AnnotatedReferenceAssemblyVersion>3.0.0</AnnotatedReferenceAssemblyVersion>
|
||||
<GenerateNullableAttributes>False</GenerateNullableAttributes>
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents color and text decoration.
|
||||
/// </summary>
|
||||
public sealed partial class Style : IEquatable<Style>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new style from the specified foreground color.
|
||||
/// </summary>
|
||||
/// <param name="color">The foreground color.</param>
|
||||
/// <returns>A new <see cref="Style"/> with the specified foreground color.</returns>
|
||||
public static Style WithForeground(Color color)
|
||||
{
|
||||
return new Style(foreground: color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new style from the specified background color.
|
||||
/// </summary>
|
||||
/// <param name="color">The background color.</param>
|
||||
/// <returns>A new <see cref="Style"/> with the specified background color.</returns>
|
||||
public static Style WithBackground(Color color)
|
||||
{
|
||||
return new Style(background: color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new style from the specified text decoration.
|
||||
/// </summary>
|
||||
/// <param name="decoration">The text decoration.</param>
|
||||
/// <returns>A new <see cref="Style"/> with the specified text decoration.</returns>
|
||||
public static Style WithDecoration(Decoration decoration)
|
||||
{
|
||||
return new Style(decoration: decoration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Spectre.Console.Internal;
|
||||
|
||||
namespace Spectre.Console
|
||||
@@ -6,7 +7,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Represents color and text decoration.
|
||||
/// </summary>
|
||||
public sealed partial class Style : IEquatable<Style>
|
||||
public sealed class Style : IEquatable<Style>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the foreground color.
|
||||
@@ -48,13 +49,33 @@ namespace Spectre.Console
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of a style to its <see cref="Style"/> equivalent.
|
||||
/// Creates a new style from the specified foreground color.
|
||||
/// </summary>
|
||||
/// <param name="text">A string containing a style to parse.</param>
|
||||
/// <returns>A <see cref="Style"/> equivalent of the text contained in <paramref name="text"/>.</returns>
|
||||
public static Style Parse(string text)
|
||||
/// <param name="color">The foreground color.</param>
|
||||
/// <returns>A new <see cref="Style"/> with the specified foreground color.</returns>
|
||||
public static Style WithForeground(Color color)
|
||||
{
|
||||
return StyleParser.Parse(text);
|
||||
return new Style(foreground: color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new style from the specified background color.
|
||||
/// </summary>
|
||||
/// <param name="color">The background color.</param>
|
||||
/// <returns>A new <see cref="Style"/> with the specified background color.</returns>
|
||||
public static Style WithBackground(Color color)
|
||||
{
|
||||
return new Style(background: color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new style from the specified text decoration.
|
||||
/// </summary>
|
||||
/// <param name="decoration">The text decoration.</param>
|
||||
/// <returns>A new <see cref="Style"/> with the specified text decoration.</returns>
|
||||
public static Style WithDecoration(Decoration decoration)
|
||||
{
|
||||
return new Style(decoration: decoration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -66,21 +87,6 @@ namespace Spectre.Console
|
||||
return new Style(Foreground, Background, Decoration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of a style to its <see cref="Style"/> equivalent.
|
||||
/// A return value indicates whether the operation succeeded.
|
||||
/// </summary>
|
||||
/// <param name="text">A string containing a style to parse.</param>
|
||||
/// <param name="result">
|
||||
/// When this method returns, contains the <see cref="Style"/> equivalent of the text contained in <paramref name="text"/>,
|
||||
/// if the conversion succeeded, or <c>null</c> if the conversion failed.
|
||||
/// </param>
|
||||
/// <returns><c>true</c> if s was converted successfully; otherwise, <c>false</c>.</returns>
|
||||
public static bool TryParse(string text, out Style? result)
|
||||
{
|
||||
return StyleParser.TryParse(text, out result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Combines this style with another one.
|
||||
/// </summary>
|
||||
@@ -108,6 +114,41 @@ namespace Spectre.Console
|
||||
return new Style(foreground, background, Decoration | other.Decoration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts <see cref="string"/> into a <see cref="Style"/>.
|
||||
/// </summary>
|
||||
/// <param name="style">The style string.</param>
|
||||
[SuppressMessage("Usage", "CA2225:Operator overloads have named alternates")]
|
||||
public static explicit operator Style(string style)
|
||||
{
|
||||
return Parse(style);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of a style to its <see cref="Style"/> equivalent.
|
||||
/// </summary>
|
||||
/// <param name="text">A string containing a style to parse.</param>
|
||||
/// <returns>A <see cref="Style"/> equivalent of the text contained in <paramref name="text"/>.</returns>
|
||||
public static Style Parse(string text)
|
||||
{
|
||||
return StyleParser.Parse(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of a style to its <see cref="Style"/> equivalent.
|
||||
/// A return value indicates whether the operation succeeded.
|
||||
/// </summary>
|
||||
/// <param name="text">A string containing a style to parse.</param>
|
||||
/// <param name="result">
|
||||
/// When this method returns, contains the <see cref="Style"/> equivalent of the text contained in <paramref name="text"/>,
|
||||
/// if the conversion succeeded, or <c>null</c> if the conversion failed.
|
||||
/// </param>
|
||||
/// <returns><c>true</c> if s was converted successfully; otherwise, <c>false</c>.</returns>
|
||||
public static bool TryParse(string text, out Style? result)
|
||||
{
|
||||
return StyleParser.TryParse(text, out result);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Spectre.Console
|
||||
{
|
||||
_table = new Table
|
||||
{
|
||||
BorderKind = BorderKind.None,
|
||||
Border = Border.None,
|
||||
ShowHeaders = false,
|
||||
IsGrid = true,
|
||||
PadRightCell = false,
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Spectre.Console.Rendering;
|
||||
using SpectreBorder = Spectre.Console.Rendering.Border;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
@@ -16,10 +15,10 @@ namespace Spectre.Console
|
||||
private readonly IRenderable _child;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public BorderKind BorderKind { get; set; } = BorderKind.Square;
|
||||
public Border Border { get; set; } = Border.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool SafeBorder { get; set; } = true;
|
||||
public bool UseSafeBorder { get; set; } = true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Style? BorderStyle { get; set; }
|
||||
@@ -39,7 +38,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Gets or sets the header.
|
||||
/// </summary>
|
||||
public Header? Header { get; set; }
|
||||
public PanelHeader? Header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Panel"/> class.
|
||||
@@ -71,7 +70,7 @@ namespace Spectre.Console
|
||||
/// <inheritdoc/>
|
||||
protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth)
|
||||
{
|
||||
var border = SpectreBorder.GetBorder(BorderKind, (context.LegacyConsole || !context.Unicode) && SafeBorder);
|
||||
var border = Border.GetSafeBorder((context.LegacyConsole || !context.Unicode) && UseSafeBorder);
|
||||
var borderStyle = BorderStyle ?? Style.Plain;
|
||||
|
||||
var paddingWidth = Padding.GetHorizontalPadding();
|
||||
@@ -132,7 +131,7 @@ namespace Spectre.Console
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void AddBottomBorder(List<Segment> result, SpectreBorder border, Style borderStyle, int panelWidth)
|
||||
private static void AddBottomBorder(List<Segment> result, Border border, Style borderStyle, int panelWidth)
|
||||
{
|
||||
result.Add(new Segment(border.GetPart(BorderPart.FooterBottomLeft), borderStyle));
|
||||
result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, panelWidth - EdgeWidth), borderStyle));
|
||||
@@ -140,7 +139,7 @@ namespace Spectre.Console
|
||||
result.Add(Segment.LineBreak);
|
||||
}
|
||||
|
||||
private void AddTopBorder(List<Segment> segments, RenderContext context, SpectreBorder border, Style borderStyle, int panelWidth)
|
||||
private void AddTopBorder(List<Segment> segments, RenderContext context, Border border, Style borderStyle, int panelWidth)
|
||||
{
|
||||
segments.Add(new Segment(border.GetPart(BorderPart.HeaderTopLeft), borderStyle));
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// Represents a header.
|
||||
/// </summary>
|
||||
public sealed class Header : IAlignable
|
||||
public sealed class PanelHeader : IAlignable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the header text.
|
||||
@@ -23,12 +23,12 @@ namespace Spectre.Console
|
||||
public Justify? Alignment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Header"/> class.
|
||||
/// Initializes a new instance of the <see cref="PanelHeader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="text">The header text.</param>
|
||||
/// <param name="style">The header style.</param>
|
||||
/// <param name="alignment">The header alignment.</param>
|
||||
public Header(string text, Style? style = null, Justify? alignment = null)
|
||||
public PanelHeader(string text, Style? style = null, Justify? alignment = null)
|
||||
{
|
||||
Text = text ?? throw new ArgumentNullException(nameof(text));
|
||||
Style = style;
|
||||
@@ -40,7 +40,7 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
/// <param name="style">The header style.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public Header SetStyle(Style? style)
|
||||
public PanelHeader SetStyle(Style? style)
|
||||
{
|
||||
Style = style ?? Style.Plain;
|
||||
return this;
|
||||
@@ -51,7 +51,7 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
/// <param name="alignment">The header alignment.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public Header SetAlignment(Justify alignment)
|
||||
public PanelHeader SetAlignment(Justify alignment)
|
||||
{
|
||||
Alignment = alignment;
|
||||
return this;
|
||||
@@ -3,15 +3,16 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Spectre.Console.Internal;
|
||||
using Spectre.Console.Rendering;
|
||||
using SpectreBorder = Spectre.Console.Rendering.Border;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// A renderable table.
|
||||
/// </summary>
|
||||
public sealed partial class Table : Renderable, IHasBorder, IExpandable
|
||||
public sealed class Table : Renderable, IHasBorder, IExpandable
|
||||
{
|
||||
private const int EdgeCount = 2;
|
||||
|
||||
private readonly List<TableColumn> _columns;
|
||||
private readonly List<List<IRenderable>> _rows;
|
||||
|
||||
@@ -26,13 +27,13 @@ namespace Spectre.Console
|
||||
public int RowCount => _rows.Count;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public BorderKind BorderKind { get; set; } = BorderKind.Square;
|
||||
public Border Border { get; set; } = Border.Square;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Style? BorderStyle { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool SafeBorder { get; set; } = true;
|
||||
public bool UseSafeBorder { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not table headers should be shown.
|
||||
@@ -148,13 +149,13 @@ namespace Spectre.Console
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var border = SpectreBorder.GetBorder(BorderKind, (context.LegacyConsole || !context.Unicode) && SafeBorder);
|
||||
var border = Border.GetSafeBorder((context.LegacyConsole || !context.Unicode) && UseSafeBorder);
|
||||
var borderStyle = BorderStyle ?? Style.Plain;
|
||||
|
||||
var tableWidth = maxWidth;
|
||||
|
||||
var showBorder = BorderKind != BorderKind.None;
|
||||
var hideBorder = BorderKind == BorderKind.None;
|
||||
var showBorder = Border.Visible;
|
||||
var hideBorder = !Border.Visible;
|
||||
var hasRows = _rows.Count > 0;
|
||||
|
||||
if (Width != null)
|
||||
@@ -231,7 +232,8 @@ namespace Spectre.Console
|
||||
if (firstCell && showBorder)
|
||||
{
|
||||
// Show left column edge
|
||||
result.Add(new Segment(border.GetPart(BorderPart.CellLeft), borderStyle));
|
||||
var part = firstRow && ShowHeaders ? BorderPart.HeaderLeft : BorderPart.CellLeft;
|
||||
result.Add(new Segment(border.GetPart(part), borderStyle));
|
||||
}
|
||||
|
||||
// Pad column on left side.
|
||||
@@ -267,12 +269,14 @@ namespace Spectre.Console
|
||||
if (lastCell && showBorder)
|
||||
{
|
||||
// Add right column edge
|
||||
result.Add(new Segment(border.GetPart(BorderPart.CellRight), borderStyle));
|
||||
var part = firstRow && ShowHeaders ? BorderPart.HeaderRight : BorderPart.CellRight;
|
||||
result.Add(new Segment(border.GetPart(part), borderStyle));
|
||||
}
|
||||
else if (showBorder)
|
||||
{
|
||||
// Add column separator
|
||||
result.Add(new Segment(border.GetPart(BorderPart.CellSeparator), borderStyle));
|
||||
var part = firstRow && ShowHeaders ? BorderPart.HeaderSeparator : BorderPart.CellSeparator;
|
||||
result.Add(new Segment(border.GetPart(part), borderStyle));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,6 +331,123 @@ namespace Spectre.Console
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate the widths of each column, including padding, not including borders.
|
||||
// Ported from Rich by Will McGugan, licensed under MIT.
|
||||
// https://github.com/willmcgugan/rich/blob/527475837ebbfc427530b3ee0d4d0741d2d0fc6d/rich/table.py#L394
|
||||
private List<int> CalculateColumnWidths(RenderContext options, int maxWidth)
|
||||
{
|
||||
var width_ranges = _columns.Select(column => MeasureColumn(column, options, maxWidth)).ToArray();
|
||||
var widths = width_ranges.Select(range => range.Max).ToList();
|
||||
|
||||
var tableWidth = widths.Sum();
|
||||
|
||||
if (tableWidth > maxWidth)
|
||||
{
|
||||
var wrappable = _columns.Select(c => !c.NoWrap).ToList();
|
||||
widths = CollapseWidths(widths, wrappable, maxWidth);
|
||||
tableWidth = widths.Sum();
|
||||
|
||||
// last resort, reduce columns evenly
|
||||
if (tableWidth > maxWidth)
|
||||
{
|
||||
var excessWidth = tableWidth - maxWidth;
|
||||
widths = Ratio.Reduce(excessWidth, widths.Select(_ => 1).ToList(), widths, widths);
|
||||
tableWidth = widths.Sum();
|
||||
}
|
||||
}
|
||||
|
||||
if (tableWidth < maxWidth && ShouldExpand())
|
||||
{
|
||||
var padWidths = Ratio.Distribute(maxWidth - tableWidth, widths);
|
||||
widths = widths.Zip(padWidths, (a, b) => (a, b)).Select(f => f.a + f.b).ToList();
|
||||
}
|
||||
|
||||
return widths;
|
||||
}
|
||||
|
||||
// Reduce widths so that the total is less or equal to the max width.
|
||||
// Ported from Rich by Will McGugan, licensed under MIT.
|
||||
// https://github.com/willmcgugan/rich/blob/527475837ebbfc427530b3ee0d4d0741d2d0fc6d/rich/table.py#L442
|
||||
private static List<int> CollapseWidths(List<int> widths, List<bool> wrappable, int maxWidth)
|
||||
{
|
||||
var totalWidth = widths.Sum();
|
||||
var excessWidth = totalWidth - maxWidth;
|
||||
|
||||
if (wrappable.AnyTrue())
|
||||
{
|
||||
while (totalWidth != 0 && excessWidth > 0)
|
||||
{
|
||||
var maxColumn = widths.Zip(wrappable, (first, second) => (width: first, allowWrap: second))
|
||||
.Where(x => x.allowWrap)
|
||||
.Max(x => x.width);
|
||||
|
||||
var secondMaxColumn = widths.Zip(wrappable, (width, allowWrap) => allowWrap && width != maxColumn ? width : 1).Max();
|
||||
var columnDifference = maxColumn - secondMaxColumn;
|
||||
|
||||
var ratios = widths.Zip(wrappable, (width, allowWrap) => width == maxColumn && allowWrap ? 1 : 0).ToList();
|
||||
if (!ratios.Any(x => x != 0) || columnDifference == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var maxReduce = widths.Select(_ => Math.Min(excessWidth, columnDifference)).ToList();
|
||||
widths = Ratio.Reduce(excessWidth, ratios, maxReduce, widths);
|
||||
|
||||
totalWidth = widths.Sum();
|
||||
excessWidth = totalWidth - maxWidth;
|
||||
}
|
||||
}
|
||||
|
||||
return widths;
|
||||
}
|
||||
|
||||
private (int Min, int Max) MeasureColumn(TableColumn column, RenderContext options, int maxWidth)
|
||||
{
|
||||
var padding = column.Padding.GetHorizontalPadding();
|
||||
|
||||
// Predetermined width?
|
||||
if (column.Width != null)
|
||||
{
|
||||
return (column.Width.Value + padding, column.Width.Value + padding);
|
||||
}
|
||||
|
||||
var columnIndex = _columns.IndexOf(column);
|
||||
var rows = _rows.Select(row => row[columnIndex]);
|
||||
|
||||
var minWidths = new List<int>();
|
||||
var maxWidths = new List<int>();
|
||||
|
||||
// Include columns in measurement
|
||||
var measure = column.Text.Measure(options, maxWidth);
|
||||
minWidths.Add(measure.Min);
|
||||
maxWidths.Add(measure.Max);
|
||||
|
||||
foreach (var row in rows)
|
||||
{
|
||||
measure = row.Measure(options, maxWidth);
|
||||
minWidths.Add(measure.Min);
|
||||
maxWidths.Add(measure.Max);
|
||||
}
|
||||
|
||||
return (minWidths.Count > 0 ? minWidths.Max() : padding,
|
||||
maxWidths.Count > 0 ? maxWidths.Max() : maxWidth);
|
||||
}
|
||||
|
||||
private int GetExtraWidth(bool includePadding)
|
||||
{
|
||||
var hideBorder = !Border.Visible;
|
||||
var separators = hideBorder ? 0 : _columns.Count - 1;
|
||||
var edges = hideBorder ? 0 : EdgeCount;
|
||||
var padding = includePadding ? _columns.Select(x => x.Padding.GetHorizontalPadding()).Sum() : 0;
|
||||
|
||||
if (!PadRightCell)
|
||||
{
|
||||
padding -= _columns.Last().Padding.Right;
|
||||
}
|
||||
|
||||
return separators + edges + padding;
|
||||
}
|
||||
|
||||
private bool ShouldExpand()
|
||||
{
|
||||
return Expand || Width != null;
|
||||
Reference in New Issue
Block a user