diff --git a/examples/Borders/Program.cs b/examples/Borders/Program.cs
index 868e352..e49b9d1 100644
--- a/examples/Borders/Program.cs
+++ b/examples/Borders/Program.cs
@@ -48,8 +48,8 @@ namespace BordersExample
static IRenderable CreateTable(string name, TableBorder border)
{
var table = new Table().Border(border);
- table.AddColumn("[yellow]Header 1[/]");
- table.AddColumn("[yellow]Header 2[/]", col => col.RightAligned());
+ table.AddColumn("[yellow]Header 1[/]", c => c.Footer("[grey]Footer 1[/]"));
+ table.AddColumn("[yellow]Header 2[/]", col => col.Footer("[grey]Footer 2[/]").RightAligned());
table.AddRow("Cell", "Cell");
table.AddRow("Cell", "Cell");
diff --git a/examples/Tables/Program.cs b/examples/Tables/Program.cs
index cec47f8..31fc3ae 100644
--- a/examples/Tables/Program.cs
+++ b/examples/Tables/Program.cs
@@ -18,9 +18,9 @@ namespace TableExample
var simple = new Table()
.Border(TableBorder.Square)
.BorderColor(Color.Red)
- .AddColumn(new TableColumn("[u]CDE[/]").Centered())
- .AddColumn(new TableColumn("[u]FED[/]"))
- .AddColumn(new TableColumn("[u]IHG[/]"))
+ .AddColumn(new TableColumn("[u]CDE[/]").Footer("EDC").Centered())
+ .AddColumn(new TableColumn("[u]FED[/]").Footer("DEF"))
+ .AddColumn(new TableColumn("[u]IHG[/]").Footer("GHI"))
.AddRow("Hello", "[red]World![/]", "")
.AddRow("[blue]Bonjour[/]", "[white]le[/]", "[red]monde![/]")
.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", "");
@@ -38,11 +38,11 @@ namespace TableExample
return new Table()
.Centered()
.Border(TableBorder.DoubleEdge)
- .Heading("TABLE [yellow]HEADING[/]")
- .Footnote("TABLE [yellow]FOOTNOTE[/]")
- .AddColumn(new TableColumn(new Panel("[u]ABC[/]").BorderColor(Color.Red)))
- .AddColumn(new TableColumn(new Panel("[u]DEF[/]").BorderColor(Color.Green)))
- .AddColumn(new TableColumn(new Panel("[u]GHI[/]").BorderColor(Color.Blue)))
+ .Title("TABLE [yellow]TITLE[/]")
+ .Caption("TABLE [yellow]CAPTION[/]")
+ .AddColumn(new TableColumn(new Panel("[u]ABC[/]").BorderColor(Color.Red)).Footer("[u]FOOTER 1[/]"))
+ .AddColumn(new TableColumn(new Panel("[u]DEF[/]").BorderColor(Color.Green)).Footer("[u]FOOTER 2[/]"))
+ .AddColumn(new TableColumn(new Panel("[u]GHI[/]").BorderColor(Color.Blue)).Footer("[u]FOOTER 3[/]"))
.AddRow(new Text("Hello").Centered(), new Markup("[red]World![/]"), Text.Empty)
.AddRow(second, new Text("Whaaat"), new Text("Lol"))
.AddRow(new Markup("[blue]Hej[/]").Centered(), new Markup("[yellow]Världen![/]"), Text.Empty);
diff --git a/src/Spectre.Console.Tests/Unit/TableBorderTests.cs b/src/Spectre.Console.Tests/Unit/TableBorderTests.cs
index 72fe572..8b47969 100644
--- a/src/Spectre.Console.Tests/Unit/TableBorderTests.cs
+++ b/src/Spectre.Console.Tests/Unit/TableBorderTests.cs
@@ -42,10 +42,11 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(3);
+ console.Lines.Count.ShouldBe(4);
console.Lines[0].ShouldBe("Header 1 Header 2");
console.Lines[1].ShouldBe("Cell Cell ");
console.Lines[2].ShouldBe("Cell Cell ");
+ console.Lines[3].ShouldBe("Footer 1 Footer 2");
}
}
@@ -85,13 +86,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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("+---------------------+");
+ console.Lines[5].ShouldBe("|----------+----------|");
+ console.Lines[6].ShouldBe("| Footer 1 | Footer 2 |");
+ console.Lines[7].ShouldBe("+---------------------+");
}
}
@@ -131,13 +134,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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("+----------+----------+");
+ console.Lines[5].ShouldBe("|----------+----------|");
+ console.Lines[6].ShouldBe("| Footer 1 | Footer 2 |");
+ console.Lines[7].ShouldBe("+----------+----------+");
}
}
@@ -177,13 +182,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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("+----------+----------+");
+ console.Lines[6].ShouldBe("| Footer 1 | Footer 2 |");
+ console.Lines[7].ShouldBe("+----------+----------+");
}
}
@@ -223,13 +230,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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("└──────────┴──────────┘");
+ console.Lines[5].ShouldBe("├──────────┼──────────┤");
+ console.Lines[6].ShouldBe("│ Footer 1 │ Footer 2 │");
+ console.Lines[7].ShouldBe("└──────────┴──────────┘");
}
}
@@ -269,13 +278,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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("╰──────────┴──────────╯");
+ console.Lines[5].ShouldBe("├──────────┼──────────┤");
+ console.Lines[6].ShouldBe("│ Footer 1 │ Footer 2 │");
+ console.Lines[7].ShouldBe("╰──────────┴──────────╯");
}
}
@@ -315,13 +326,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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(" ");
+ console.Lines[5].ShouldBe(" ──────────┼────────── ");
+ console.Lines[6].ShouldBe(" Footer 1 │ Footer 2 ");
+ console.Lines[7].ShouldBe(" ");
}
}
@@ -361,13 +374,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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(" ");
+ console.Lines[5].ShouldBe(" ━━━━━━━━━━┿━━━━━━━━━━ ");
+ console.Lines[6].ShouldBe(" Footer 1 │ Footer 2 ");
+ console.Lines[7].ShouldBe(" ");
}
}
@@ -407,13 +422,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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(" ");
+ console.Lines[5].ShouldBe(" ══════════╪══════════ ");
+ console.Lines[6].ShouldBe(" Footer 1 │ Footer 2 ");
+ console.Lines[7].ShouldBe(" ");
}
}
@@ -453,13 +470,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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(" ");
+ console.Lines[5].ShouldBe("───────────────────────");
+ console.Lines[6].ShouldBe(" Footer 1 Footer 2 ");
+ console.Lines[7].ShouldBe(" ");
}
}
@@ -499,13 +518,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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("───────────────────────");
+ console.Lines[6].ShouldBe(" Footer 1 Footer 2 ");
+ console.Lines[7].ShouldBe("───────────────────────");
}
}
@@ -545,13 +566,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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(" ");
+ console.Lines[5].ShouldBe("━━━━━━━━━━━━━━━━━━━━━━━");
+ console.Lines[6].ShouldBe(" Footer 1 Footer 2 ");
+ console.Lines[7].ShouldBe(" ");
}
}
@@ -591,13 +614,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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("┗━━━━━━━━━━┻━━━━━━━━━━┛");
+ console.Lines[5].ShouldBe("┣━━━━━━━━━━╋━━━━━━━━━━┫");
+ console.Lines[6].ShouldBe("┃ Footer 1 ┃ Footer 2 ┃");
+ console.Lines[7].ShouldBe("┗━━━━━━━━━━┻━━━━━━━━━━┛");
}
}
@@ -637,13 +662,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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("┗━━━━━━━━━━┷━━━━━━━━━━┛");
+ console.Lines[5].ShouldBe("┠──────────┼──────────┨");
+ console.Lines[6].ShouldBe("┃ Footer 1 │ Footer 2 ┃");
+ console.Lines[7].ShouldBe("┗━━━━━━━━━━┷━━━━━━━━━━┛");
}
}
@@ -683,13 +710,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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("└──────────┴──────────┘");
+ console.Lines[5].ShouldBe("├──────────┼──────────┤");
+ console.Lines[6].ShouldBe("│ Footer 1 │ Footer 2 │");
+ console.Lines[7].ShouldBe("└──────────┴──────────┘");
}
}
@@ -729,13 +758,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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("╚══════════╩══════════╝");
+ console.Lines[5].ShouldBe("╠══════════╬══════════╣");
+ console.Lines[6].ShouldBe("║ Footer 1 ║ Footer 2 ║");
+ console.Lines[7].ShouldBe("╚══════════╩══════════╝");
}
}
@@ -775,13 +806,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(8);
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("╚══════════╧══════════╝");
+ console.Lines[5].ShouldBe("╟──────────┼──────────╢");
+ console.Lines[6].ShouldBe("║ Footer 1 │ Footer 2 ║");
+ console.Lines[7].ShouldBe("╚══════════╧══════════╝");
}
}
@@ -821,13 +854,14 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(7);
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(" ");
+ console.Lines[5].ShouldBe("| Footer 1 | Footer 2 |");
+ console.Lines[6].ShouldBe(" ");
}
[Fact]
@@ -841,13 +875,14 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(7);
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(" ");
+ console.Lines[5].ShouldBe("| Footer 1 | Footer 2 |");
+ console.Lines[6].ShouldBe(" ");
}
[Fact]
@@ -861,13 +896,14 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(7);
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(" ");
+ console.Lines[5].ShouldBe("| Footer 1 | Footer 2 |");
+ console.Lines[6].ShouldBe(" ");
}
[Fact]
@@ -881,13 +917,14 @@ namespace Spectre.Console.Tests.Unit
console.Render(table);
// Then
- console.Lines.Count.ShouldBe(6);
+ console.Lines.Count.ShouldBe(7);
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(" ");
+ console.Lines[5].ShouldBe("| Footer 1 | Footer 2 |");
+ console.Lines[6].ShouldBe(" ");
}
}
@@ -896,8 +933,8 @@ namespace Spectre.Console.Tests.Unit
public static Table GetTable(Justify? header1 = null, Justify? header2 = null)
{
var table = new Table();
- table.AddColumn("Header 1", c => c.Alignment = header1);
- table.AddColumn("Header 2", c => c.Alignment = header2);
+ table.AddColumn("Header 1", c => c.Alignment(header1).Footer("Footer 1"));
+ table.AddColumn("Header 2", c => c.Alignment(header2).Footer("Footer 2"));
table.AddRow("Cell", "Cell");
table.AddRow("Cell", "Cell");
return table;
diff --git a/src/Spectre.Console.Tests/Unit/TableTests.cs b/src/Spectre.Console.Tests/Unit/TableTests.cs
index 2a64fdf..ae324c2 100644
--- a/src/Spectre.Console.Tests/Unit/TableTests.cs
+++ b/src/Spectre.Console.Tests/Unit/TableTests.cs
@@ -168,6 +168,33 @@ namespace Spectre.Console.Tests.Unit
console.Lines[5].ShouldBe("└────────┴────────┴───────┘");
}
+ [Fact]
+ public void Should_Render_Table_With_Footers_Correctly()
+ {
+ // Given
+ var console = new PlainConsole(width: 80);
+ var table = new Table();
+ table.AddColumn(new TableColumn("Foo").Footer("Oof").RightAligned());
+ table.AddColumn("Bar");
+ table.AddColumns(new TableColumn("Baz").Footer("Zab"));
+ table.AddRow("Qux", "Corgi", "Waldo");
+ table.AddRow("Grault", "Garply", "Fred");
+
+ // When
+ console.Render(table);
+
+ // Then
+ console.Lines.Count.ShouldBe(8);
+ console.Lines[0].ShouldBe("┌────────┬────────┬───────┐");
+ console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │");
+ console.Lines[2].ShouldBe("├────────┼────────┼───────┤");
+ console.Lines[3].ShouldBe("│ Qux │ Corgi │ Waldo │");
+ console.Lines[4].ShouldBe("│ Grault │ Garply │ Fred │");
+ console.Lines[5].ShouldBe("├────────┼────────┼───────┤");
+ console.Lines[6].ShouldBe("│ Oof │ │ Zab │");
+ console.Lines[7].ShouldBe("└────────┴────────┴───────┘");
+ }
+
[Fact]
public void Should_Left_Align_Table_Correctly()
{
@@ -460,13 +487,13 @@ namespace Spectre.Console.Tests.Unit
}
[Fact]
- public void Should_Render_Table_With_Title_And_Footnote_Correctly()
+ public void Should_Render_Table_With_Title_And_Caption_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = TableBorder.Rounded };
- table.Heading = new TableTitle("Hello World");
- table.Footnote = new TableTitle("Goodbye World");
+ table.Title = new TableTitle("Hello World");
+ table.Caption = new TableTitle("Goodbye World");
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
@@ -487,14 +514,14 @@ namespace Spectre.Console.Tests.Unit
}
[Fact]
- public void Should_Left_Align_Table_With_Title_And_Footnote_Correctly()
+ public void Should_Left_Align_Table_With_Title_And_Caption_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = TableBorder.Rounded };
table.LeftAligned();
- table.Heading = new TableTitle("Hello World");
- table.Footnote = new TableTitle("Goodbye World");
+ table.Title = new TableTitle("Hello World");
+ table.Caption = new TableTitle("Goodbye World");
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
@@ -515,14 +542,14 @@ namespace Spectre.Console.Tests.Unit
}
[Fact]
- public void Should_Center_Table_With_Title_And_Footnote_Correctly()
+ public void Should_Center_Table_With_Title_And_Caption_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = TableBorder.Rounded };
table.Centered();
- table.Heading = new TableTitle("Hello World");
- table.Footnote = new TableTitle("Goodbye World");
+ table.Title = new TableTitle("Hello World");
+ table.Caption = new TableTitle("Goodbye World");
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
@@ -543,14 +570,14 @@ namespace Spectre.Console.Tests.Unit
}
[Fact]
- public void Should_Right_Align_Table_With_Title_And_Footnote_Correctly()
+ public void Should_Right_Align_Table_With_Title_And_Caption_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = TableBorder.Rounded };
table.RightAligned();
- table.Heading = new TableTitle("Hello World");
- table.Footnote = new TableTitle("Goodbye World");
+ table.Title = new TableTitle("Hello World");
+ table.Caption = new TableTitle("Goodbye World");
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
diff --git a/src/Spectre.Console/Extensions/AlignableExtensions.cs b/src/Spectre.Console/Extensions/AlignableExtensions.cs
index f40a8d3..05693ae 100644
--- a/src/Spectre.Console/Extensions/AlignableExtensions.cs
+++ b/src/Spectre.Console/Extensions/AlignableExtensions.cs
@@ -12,7 +12,7 @@ namespace Spectre.Console
/// The alignable object.
/// The alignment.
/// The same instance so that multiple calls can be chained.
- public static T Alignment(this T obj, Justify alignment)
+ public static T Alignment(this T obj, Justify? alignment)
where T : class, IAlignable
{
if (obj is null)
diff --git a/src/Spectre.Console/Extensions/Obsolete/ObsoleteTableExtensions.cs b/src/Spectre.Console/Extensions/Obsolete/ObsoleteTableExtensions.cs
index 0a588ed..2005165 100644
--- a/src/Spectre.Console/Extensions/Obsolete/ObsoleteTableExtensions.cs
+++ b/src/Spectre.Console/Extensions/Obsolete/ObsoleteTableExtensions.cs
@@ -1,7 +1,5 @@
using System;
-using System.Linq;
-using Spectre.Console.Internal;
-using Spectre.Console.Rendering;
+using System.ComponentModel;
namespace Spectre.Console
{
@@ -17,6 +15,7 @@ namespace Spectre.Console
/// The width.
/// The same instance so that multiple calls can be chained.
[Obsolete("Use Width(..) instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public static Table SetWidth(this Table table, int width)
{
if (table is null)
@@ -36,6 +35,7 @@ namespace Spectre.Console
/// The style.
/// The same instance so that multiple calls can be chained.
[Obsolete("Use Heading(..) instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public static Table SetHeading(this Table table, string text, Style? style = null)
{
if (table is null)
@@ -58,6 +58,7 @@ namespace Spectre.Console
/// The heading.
/// The same instance so that multiple calls can be chained.
[Obsolete("Use Heading(..) instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public static Table SetHeading(this Table table, TableTitle heading)
{
if (table is null)
@@ -65,7 +66,7 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(table));
}
- table.Heading = heading;
+ table.Title = heading;
return table;
}
@@ -76,7 +77,8 @@ namespace Spectre.Console
/// The footnote.
/// The style.
/// The same instance so that multiple calls can be chained.
- [Obsolete("Use Footnote(..) instead.")]
+ [Obsolete("Use Caption(..) instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public static Table SetFootnote(this Table table, string text, Style? style = null)
{
if (table is null)
@@ -98,7 +100,8 @@ namespace Spectre.Console
/// The table.
/// The footnote.
/// The same instance so that multiple calls can be chained.
- [Obsolete("Use Footnote(..) instead.")]
+ [Obsolete("Use Caption(..) instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public static Table SetFootnote(this Table table, TableTitle footnote)
{
if (table is null)
@@ -106,7 +109,93 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(table));
}
- table.Footnote = footnote;
+ table.Caption = footnote;
+ return table;
+ }
+
+ ///
+ /// Sets the table footnote.
+ ///
+ /// The table.
+ /// The footnote.
+ /// The style.
+ /// The same instance so that multiple calls can be chained.
+ [Obsolete("Use Caption(..) instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static Table Footnote(this Table table, string text, Style? style = null)
+ {
+ if (table is null)
+ {
+ throw new ArgumentNullException(nameof(table));
+ }
+
+ if (text is null)
+ {
+ throw new ArgumentNullException(nameof(text));
+ }
+
+ return Footnote(table, new TableTitle(text, style));
+ }
+
+ ///
+ /// Sets the table footnote.
+ ///
+ /// The table.
+ /// The footnote.
+ /// The same instance so that multiple calls can be chained.
+ [Obsolete("Use Caption(..) instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static Table Footnote(this Table table, TableTitle footnote)
+ {
+ if (table is null)
+ {
+ throw new ArgumentNullException(nameof(table));
+ }
+
+ table.Caption = footnote;
+ return table;
+ }
+
+ ///
+ /// Sets the table heading.
+ ///
+ /// The table.
+ /// The heading.
+ /// The style.
+ /// The same instance so that multiple calls can be chained.
+ [Obsolete("Use Title(..) instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static Table Heading(this Table table, string text, Style? style = null)
+ {
+ if (table is null)
+ {
+ throw new ArgumentNullException(nameof(table));
+ }
+
+ if (text is null)
+ {
+ throw new ArgumentNullException(nameof(text));
+ }
+
+ return Heading(table, new TableTitle(text, style));
+ }
+
+ ///
+ /// Sets the table heading.
+ ///
+ /// The table.
+ /// The heading.
+ /// The same instance so that multiple calls can be chained.
+ [Obsolete("Use Title(..) instead.")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static Table Heading(this Table table, TableTitle heading)
+ {
+ if (table is null)
+ {
+ throw new ArgumentNullException(nameof(table));
+ }
+
+ table.Title = heading;
return table;
}
}
diff --git a/src/Spectre.Console/Extensions/TableColumnExtensions.cs b/src/Spectre.Console/Extensions/TableColumnExtensions.cs
new file mode 100644
index 0000000..37c8c64
--- /dev/null
+++ b/src/Spectre.Console/Extensions/TableColumnExtensions.cs
@@ -0,0 +1,55 @@
+using System;
+using Spectre.Console.Rendering;
+
+namespace Spectre.Console
+{
+ ///
+ /// Contains extension methods for .
+ ///
+ public static class TableColumnExtensions
+ {
+ ///
+ /// Sets the table column footer.
+ ///
+ /// The table column.
+ /// The table column markup text.
+ /// The same instance so that multiple calls can be chained.
+ public static TableColumn Footer(this TableColumn column, string footer)
+ {
+ if (column is null)
+ {
+ throw new ArgumentNullException(nameof(column));
+ }
+
+ if (footer is null)
+ {
+ throw new ArgumentNullException(nameof(footer));
+ }
+
+ column.Footer = new Markup(footer);
+ return column;
+ }
+
+ ///
+ /// Sets the table column footer.
+ ///
+ /// The table column.
+ /// The table column footer.
+ /// The same instance so that multiple calls can be chained.
+ public static TableColumn Footer(this TableColumn column, IRenderable footer)
+ {
+ if (column is null)
+ {
+ throw new ArgumentNullException(nameof(column));
+ }
+
+ if (footer is null)
+ {
+ throw new ArgumentNullException(nameof(footer));
+ }
+
+ column.Footer = footer;
+ return column;
+ }
+ }
+}
diff --git a/src/Spectre.Console/Extensions/TableExtensions.cs b/src/Spectre.Console/Extensions/TableExtensions.cs
index 5024a8c..3f93b06 100644
--- a/src/Spectre.Console/Extensions/TableExtensions.cs
+++ b/src/Spectre.Console/Extensions/TableExtensions.cs
@@ -178,52 +178,45 @@ namespace Spectre.Console
}
///
- /// Sets the table heading.
+ /// Shows table footers.
///
/// The table.
- /// The heading.
- /// The style.
/// The same instance so that multiple calls can be chained.
- public static Table Heading(this Table table, string text, Style? style = null)
+ public static Table ShowFooters(this Table table)
{
if (table is null)
{
throw new ArgumentNullException(nameof(table));
}
- if (text is null)
- {
- throw new ArgumentNullException(nameof(text));
- }
-
- return Heading(table, new TableTitle(text, style));
- }
-
- ///
- /// Sets the table heading.
- ///
- /// The table.
- /// The heading.
- /// The same instance so that multiple calls can be chained.
- public static Table Heading(this Table table, TableTitle heading)
- {
- if (table is null)
- {
- throw new ArgumentNullException(nameof(table));
- }
-
- table.Heading = heading;
+ table.ShowFooters = true;
return table;
}
///
- /// Sets the table footnote.
+ /// Hides table footers.
///
/// The table.
- /// The footnote.
- /// The style.
/// The same instance so that multiple calls can be chained.
- public static Table Footnote(this Table table, string text, Style? style = null)
+ public static Table HideFooters(this Table table)
+ {
+ if (table is null)
+ {
+ throw new ArgumentNullException(nameof(table));
+ }
+
+ table.ShowFooters = false;
+ return table;
+ }
+
+ ///
+ /// Sets the table title.
+ ///
+ /// The table.
+ /// The table title markup text.
+ /// The table title style.
+ /// The same instance so that multiple calls can be chained.
+ public static Table Title(this Table table, string text, Style? style = null)
{
if (table is null)
{
@@ -235,23 +228,62 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(text));
}
- return Footnote(table, new TableTitle(text, style));
+ return Title(table, new TableTitle(text, style));
}
///
- /// Sets the table footnote.
+ /// Sets the table title.
///
/// The table.
- /// The footnote.
+ /// The table title.
/// The same instance so that multiple calls can be chained.
- public static Table Footnote(this Table table, TableTitle footnote)
+ public static Table Title(this Table table, TableTitle title)
{
if (table is null)
{
throw new ArgumentNullException(nameof(table));
}
- table.Footnote = footnote;
+ table.Title = title;
+ return table;
+ }
+
+ ///
+ /// Sets the table caption.
+ ///
+ /// The table.
+ /// The caption markup text.
+ /// The style.
+ /// The same instance so that multiple calls can be chained.
+ public static Table Caption(this Table table, string text, Style? style = null)
+ {
+ if (table is null)
+ {
+ throw new ArgumentNullException(nameof(table));
+ }
+
+ if (text is null)
+ {
+ throw new ArgumentNullException(nameof(text));
+ }
+
+ return Caption(table, new TableTitle(text, style));
+ }
+
+ ///
+ /// Sets the table caption.
+ ///
+ /// The table.
+ /// The caption.
+ /// The same instance so that multiple calls can be chained.
+ public static Table Caption(this Table table, TableTitle caption)
+ {
+ if (table is null)
+ {
+ throw new ArgumentNullException(nameof(table));
+ }
+
+ table.Caption = caption;
return table;
}
}
diff --git a/src/Spectre.Console/Rendering/Borders/TableBorderPart.cs b/src/Spectre.Console/Rendering/Borders/TableBorderPart.cs
index 370ad20..34b4af0 100644
--- a/src/Spectre.Console/Rendering/Borders/TableBorderPart.cs
+++ b/src/Spectre.Console/Rendering/Borders/TableBorderPart.cs
@@ -60,6 +60,26 @@ namespace Spectre.Console.Rendering
///
HeaderBottomRight,
+ ///
+ /// The top left part of a footer.
+ ///
+ FooterTopLeft,
+
+ ///
+ /// The top part of a footer.
+ ///
+ FooterTop,
+
+ ///
+ /// The top separator part of a footer.
+ ///
+ FooterTopSeparator,
+
+ ///
+ /// The top right part of a footer.
+ ///
+ FooterTopRight,
+
///
/// The left part of a cell.
///
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/Ascii2TableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/Ascii2TableBorder.cs
index 39df6a6..b4c47fc 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/Ascii2TableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/Ascii2TableBorder.cs
@@ -26,6 +26,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => "|",
TableBorderPart.CellSeparator => "|",
TableBorderPart.CellRight => "|",
+ TableBorderPart.FooterTopLeft => "|",
+ TableBorderPart.FooterTop => "-",
+ TableBorderPart.FooterTopSeparator => "+",
+ TableBorderPart.FooterTopRight => "|",
TableBorderPart.FooterBottomLeft => "+",
TableBorderPart.FooterBottom => "-",
TableBorderPart.FooterBottomSeparator => "+",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/AsciiDoubleHeadTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/AsciiDoubleHeadTableBorder.cs
index b4ca73d..c565e5a 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/AsciiDoubleHeadTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/AsciiDoubleHeadTableBorder.cs
@@ -26,6 +26,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => "|",
TableBorderPart.CellSeparator => "|",
TableBorderPart.CellRight => "|",
+ TableBorderPart.FooterTopLeft => "+",
+ TableBorderPart.FooterTop => "-",
+ TableBorderPart.FooterTopSeparator => "+",
+ TableBorderPart.FooterTopRight => "+",
TableBorderPart.FooterBottomLeft => "+",
TableBorderPart.FooterBottom => "-",
TableBorderPart.FooterBottomSeparator => "+",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/AsciiTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/AsciiTableBorder.cs
index 932d717..6eb4000 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/AsciiTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/AsciiTableBorder.cs
@@ -26,6 +26,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => "|",
TableBorderPart.CellSeparator => "|",
TableBorderPart.CellRight => "|",
+ TableBorderPart.FooterTopLeft => "|",
+ TableBorderPart.FooterTop => "-",
+ TableBorderPart.FooterTopSeparator => "+",
+ TableBorderPart.FooterTopRight => "|",
TableBorderPart.FooterBottomLeft => "+",
TableBorderPart.FooterBottom => "-",
TableBorderPart.FooterBottomSeparator => "-",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/DoubleEdgeTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/DoubleEdgeTableBorder.cs
index 1bc7733..e21c9ee 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/DoubleEdgeTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/DoubleEdgeTableBorder.cs
@@ -26,6 +26,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => "║",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => "║",
+ TableBorderPart.FooterTopLeft => "╟",
+ TableBorderPart.FooterTop => "─",
+ TableBorderPart.FooterTopSeparator => "┼",
+ TableBorderPart.FooterTopRight => "╢",
TableBorderPart.FooterBottomLeft => "╚",
TableBorderPart.FooterBottom => "═",
TableBorderPart.FooterBottomSeparator => "╧",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/DoubleTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/DoubleTableBorder.cs
index e88f3f5..3375101 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/DoubleTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/DoubleTableBorder.cs
@@ -26,6 +26,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => "║",
TableBorderPart.CellSeparator => "║",
TableBorderPart.CellRight => "║",
+ TableBorderPart.FooterTopLeft => "╠",
+ TableBorderPart.FooterTop => "═",
+ TableBorderPart.FooterTopSeparator => "╬",
+ TableBorderPart.FooterTopRight => "╣",
TableBorderPart.FooterBottomLeft => "╚",
TableBorderPart.FooterBottom => "═",
TableBorderPart.FooterBottomSeparator => "╩",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/HeavyEdgeTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/HeavyEdgeTableBorder.cs
index 5e8d021..813828d 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/HeavyEdgeTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/HeavyEdgeTableBorder.cs
@@ -29,6 +29,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => "┃",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => "┃",
+ TableBorderPart.FooterTopLeft => "┠",
+ TableBorderPart.FooterTop => "─",
+ TableBorderPart.FooterTopSeparator => "┼",
+ TableBorderPart.FooterTopRight => "┨",
TableBorderPart.FooterBottomLeft => "┗",
TableBorderPart.FooterBottom => "━",
TableBorderPart.FooterBottomSeparator => "┷",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/HeavyHeadTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/HeavyHeadTableBorder.cs
index 3555128..0cf3dbe 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/HeavyHeadTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/HeavyHeadTableBorder.cs
@@ -29,6 +29,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => "│",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => "│",
+ TableBorderPart.FooterTopLeft => "├",
+ TableBorderPart.FooterTop => "─",
+ TableBorderPart.FooterTopSeparator => "┼",
+ TableBorderPart.FooterTopRight => "┤",
TableBorderPart.FooterBottomLeft => "└",
TableBorderPart.FooterBottom => "─",
TableBorderPart.FooterBottomSeparator => "┴",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/HeavyTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/HeavyTableBorder.cs
index c650253..3cd1190 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/HeavyTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/HeavyTableBorder.cs
@@ -29,6 +29,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => "┃",
TableBorderPart.CellSeparator => "┃",
TableBorderPart.CellRight => "┃",
+ TableBorderPart.FooterTopLeft => "┣",
+ TableBorderPart.FooterTop => "━",
+ TableBorderPart.FooterTopSeparator => "╋",
+ TableBorderPart.FooterTopRight => "┫",
TableBorderPart.FooterBottomLeft => "┗",
TableBorderPart.FooterBottom => "━",
TableBorderPart.FooterBottomSeparator => "┻",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/HorizontalTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/HorizontalTableBorder.cs
index b9c121b..1464f7b 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/HorizontalTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/HorizontalTableBorder.cs
@@ -26,6 +26,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => " ",
TableBorderPart.CellSeparator => " ",
TableBorderPart.CellRight => " ",
+ TableBorderPart.FooterTopLeft => "─",
+ TableBorderPart.FooterTop => "─",
+ TableBorderPart.FooterTopSeparator => "─",
+ TableBorderPart.FooterTopRight => "─",
TableBorderPart.FooterBottomLeft => "─",
TableBorderPart.FooterBottom => "─",
TableBorderPart.FooterBottomSeparator => "─",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/MarkdownTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/MarkdownTableBorder.cs
index 840e73e..6654f68 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/MarkdownTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/MarkdownTableBorder.cs
@@ -29,6 +29,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => "|",
TableBorderPart.CellSeparator => "|",
TableBorderPart.CellRight => "|",
+ TableBorderPart.FooterTopLeft => " ",
+ TableBorderPart.FooterTop => " ",
+ TableBorderPart.FooterTopSeparator => " ",
+ TableBorderPart.FooterTopRight => " ",
TableBorderPart.FooterBottomLeft => " ",
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
@@ -40,7 +44,12 @@ namespace Spectre.Console.Rendering
///
public override string GetColumnRow(TablePart part, IReadOnlyList widths, IReadOnlyList columns)
{
- if (part != TablePart.Separator)
+ if (part == TablePart.FooterSeparator)
+ {
+ return string.Empty;
+ }
+
+ if (part != TablePart.HeaderSeparator)
{
return base.GetColumnRow(part, widths, columns);
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/MinimalDoubleHeadTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/MinimalDoubleHeadTableBorder.cs
index b644880..817d707 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/MinimalDoubleHeadTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/MinimalDoubleHeadTableBorder.cs
@@ -26,6 +26,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => " ",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => " ",
+ TableBorderPart.FooterTopLeft => " ",
+ TableBorderPart.FooterTop => "═",
+ TableBorderPart.FooterTopSeparator => "╪",
+ TableBorderPart.FooterTopRight => " ",
TableBorderPart.FooterBottomLeft => " ",
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/MinimalHeavyHeadTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/MinimalHeavyHeadTableBorder.cs
index 9a32bf7..10f01cf 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/MinimalHeavyHeadTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/MinimalHeavyHeadTableBorder.cs
@@ -29,6 +29,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => " ",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => " ",
+ TableBorderPart.FooterTopLeft => " ",
+ TableBorderPart.FooterTop => "━",
+ TableBorderPart.FooterTopSeparator => "┿",
+ TableBorderPart.FooterTopRight => " ",
TableBorderPart.FooterBottomLeft => " ",
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/MinimalTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/MinimalTableBorder.cs
index 8b14617..9893435 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/MinimalTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/MinimalTableBorder.cs
@@ -26,6 +26,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => " ",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => " ",
+ TableBorderPart.FooterTopLeft => " ",
+ TableBorderPart.FooterTop => "─",
+ TableBorderPart.FooterTopSeparator => "┼",
+ TableBorderPart.FooterTopRight => " ",
TableBorderPart.FooterBottomLeft => " ",
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/RoundedTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/RoundedTableBorder.cs
index 6cce42e..38b90af 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/RoundedTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/RoundedTableBorder.cs
@@ -29,6 +29,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => "│",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => "│",
+ TableBorderPart.FooterTopLeft => "├",
+ TableBorderPart.FooterTop => "─",
+ TableBorderPart.FooterTopSeparator => "┼",
+ TableBorderPart.FooterTopRight => "┤",
TableBorderPart.FooterBottomLeft => "╰",
TableBorderPart.FooterBottom => "─",
TableBorderPart.FooterBottomSeparator => "┴",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/SimpleHeavyTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/SimpleHeavyTableBorder.cs
index dd43d93..1f56178 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/SimpleHeavyTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/SimpleHeavyTableBorder.cs
@@ -29,6 +29,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => " ",
TableBorderPart.CellSeparator => " ",
TableBorderPart.CellRight => " ",
+ TableBorderPart.FooterTopLeft => "━",
+ TableBorderPart.FooterTop => "━",
+ TableBorderPart.FooterTopSeparator => "━",
+ TableBorderPart.FooterTopRight => "━",
TableBorderPart.FooterBottomLeft => " ",
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/SimpleTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/SimpleTableBorder.cs
index beadd02..eba1155 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/SimpleTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/SimpleTableBorder.cs
@@ -26,6 +26,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => " ",
TableBorderPart.CellSeparator => " ",
TableBorderPart.CellRight => " ",
+ TableBorderPart.FooterTopLeft => "─",
+ TableBorderPart.FooterTop => "─",
+ TableBorderPart.FooterTopSeparator => "─",
+ TableBorderPart.FooterTopRight => "─",
TableBorderPart.FooterBottomLeft => " ",
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/SquareTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/SquareTableBorder.cs
index 92cf072..e1829c6 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/SquareTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/SquareTableBorder.cs
@@ -26,6 +26,10 @@ namespace Spectre.Console.Rendering
TableBorderPart.CellLeft => "│",
TableBorderPart.CellSeparator => "│",
TableBorderPart.CellRight => "│",
+ TableBorderPart.FooterTopLeft => "├",
+ TableBorderPart.FooterTop => "─",
+ TableBorderPart.FooterTopSeparator => "┼",
+ TableBorderPart.FooterTopRight => "┤",
TableBorderPart.FooterBottomLeft => "└",
TableBorderPart.FooterBottom => "─",
TableBorderPart.FooterBottomSeparator => "┴",
diff --git a/src/Spectre.Console/Rendering/TablePart.cs b/src/Spectre.Console/Rendering/TablePart.cs
index 6c86d01..80cb7be 100644
--- a/src/Spectre.Console/Rendering/TablePart.cs
+++ b/src/Spectre.Console/Rendering/TablePart.cs
@@ -13,7 +13,12 @@ namespace Spectre.Console.Rendering
///
/// The separator between the header and the cells.
///
- Separator,
+ HeaderSeparator,
+
+ ///
+ /// The separator between the footer and the cells.
+ ///
+ FooterSeparator,
///
/// The bottom of a table.
diff --git a/src/Spectre.Console/TableBorder.cs b/src/Spectre.Console/TableBorder.cs
index 7dd937f..544d7b9 100644
--- a/src/Spectre.Console/TableBorder.cs
+++ b/src/Spectre.Console/TableBorder.cs
@@ -83,10 +83,15 @@ namespace Spectre.Console
GetPart(TableBorderPart.HeaderTopSeparator), GetPart(TableBorderPart.HeaderTopRight)),
// Separator between header and cells
- TablePart.Separator =>
+ TablePart.HeaderSeparator =>
(GetPart(TableBorderPart.HeaderBottomLeft), GetPart(TableBorderPart.HeaderBottom),
GetPart(TableBorderPart.HeaderBottomSeparator), GetPart(TableBorderPart.HeaderBottomRight)),
+ // Separator between footer and cells
+ TablePart.FooterSeparator =>
+ (GetPart(TableBorderPart.FooterTopLeft), GetPart(TableBorderPart.FooterTop),
+ GetPart(TableBorderPart.FooterTopSeparator), GetPart(TableBorderPart.FooterTopRight)),
+
// Bottom part
TablePart.Bottom =>
(GetPart(TableBorderPart.FooterBottomLeft), GetPart(TableBorderPart.FooterBottom),
diff --git a/src/Spectre.Console/Widgets/Calendar.cs b/src/Spectre.Console/Widgets/Calendar.cs
index a1e665a..57eede5 100644
--- a/src/Spectre.Console/Widgets/Calendar.cs
+++ b/src/Spectre.Console/Widgets/Calendar.cs
@@ -209,7 +209,7 @@ namespace Spectre.Console
if (ShowHeader)
{
var heading = new DateTime(Year, Month, Day).ToString("Y", culture).EscapeMarkup();
- table.Heading = new TableTitle(heading, HeaderStyle);
+ table.Title = new TableTitle(heading, HeaderStyle);
}
// Add columns
diff --git a/src/Spectre.Console/Widgets/Table.cs b/src/Spectre.Console/Widgets/Table.cs
index 03417ee..0208dce 100644
--- a/src/Spectre.Console/Widgets/Table.cs
+++ b/src/Spectre.Console/Widgets/Table.cs
@@ -17,7 +17,7 @@ namespace Spectre.Console
private readonly List> _rows;
private static Style _defaultHeadingStyle = new Style(Color.Silver);
- private static Style _defaultFootnoteStyle = new Style(Color.Grey);
+ private static Style _defaultCaptionStyle = new Style(Color.Grey);
///
/// Gets the number of columns in the table.
@@ -43,6 +43,11 @@ namespace Spectre.Console
///
public bool ShowHeaders { get; set; } = true;
+ ///
+ /// Gets or sets a value indicating whether or not table footers should be shown.
+ ///
+ public bool ShowFooters { get; set; } = true;
+
///
/// Gets or sets a value indicating whether or not the table should
/// fit the available space. If false, the table width will be
@@ -58,12 +63,12 @@ namespace Spectre.Console
///
/// Gets or sets the table title.
///
- public TableTitle? Heading { get; set; }
+ public TableTitle? Title { get; set; }
///
/// Gets or sets the table footnote.
///
- public TableTitle? Footnote { get; set; }
+ public TableTitle? Caption { get; set; }
///
public Justify? Alignment { get; set; }
@@ -174,6 +179,7 @@ namespace Spectre.Console
var showBorder = Border.Visible;
var hideBorder = !Border.Visible;
var hasRows = _rows.Count > 0;
+ var hasFooters = _columns.Any(c => c.Footer != null);
if (Width != null)
{
@@ -196,14 +202,19 @@ namespace Spectre.Console
if (ShowHeaders)
{
// Add columns to top of rows
- rows.Add(new List(_columns.Select(c => c.Text)));
+ rows.Add(new List(_columns.Select(c => c.Header)));
}
// Add rows.
rows.AddRange(_rows);
+ if (hasFooters)
+ {
+ rows.Add(new List(_columns.Select(c => c.Footer ?? Text.Empty)));
+ }
+
var result = new List();
- result.AddRange(RenderAnnotation(context, Heading, actualMaxWidth, tableWidth, _defaultHeadingStyle));
+ result.AddRange(RenderAnnotation(context, Title, actualMaxWidth, tableWidth, _defaultHeadingStyle));
// Iterate all rows
foreach (var (index, firstRow, lastRow, row) in rows.Enumerate())
@@ -230,6 +241,18 @@ namespace Spectre.Console
result.Add(Segment.LineBreak);
}
+ // Show footer separator?
+ if (ShowFooters && lastRow && showBorder && hasFooters)
+ {
+ var textBorder = border.GetColumnRow(TablePart.FooterSeparator, columnWidths, _columns);
+ if (!string.IsNullOrEmpty(textBorder))
+ {
+ var separator = Aligner.Align(context, textBorder, Alignment, actualMaxWidth);
+ result.Add(new Segment(separator, borderStyle));
+ result.Add(Segment.LineBreak);
+ }
+ }
+
// Make cells the same shape
cells = Segment.MakeSameHeight(cellHeight, cells);
@@ -310,7 +333,7 @@ namespace Spectre.Console
// Show header separator?
if (firstRow && showBorder && ShowHeaders && hasRows)
{
- var separator = Aligner.Align(context, border.GetColumnRow(TablePart.Separator, columnWidths, _columns), Alignment, actualMaxWidth);
+ var separator = Aligner.Align(context, border.GetColumnRow(TablePart.HeaderSeparator, columnWidths, _columns), Alignment, actualMaxWidth);
result.Add(new Segment(separator, borderStyle));
result.Add(Segment.LineBreak);
}
@@ -324,7 +347,7 @@ namespace Spectre.Console
}
}
- result.AddRange(RenderAnnotation(context, Footnote, actualMaxWidth, tableWidth, _defaultFootnoteStyle));
+ result.AddRange(RenderAnnotation(context, Caption, actualMaxWidth, tableWidth, _defaultCaptionStyle));
return result;
}
@@ -437,16 +460,17 @@ namespace Spectre.Console
var minWidths = new List();
var maxWidths = new List();
- // Include columns in measurement
- var measure = column.Text.Measure(options, maxWidth);
- minWidths.Add(measure.Min);
- maxWidths.Add(measure.Max);
+ // Include columns (both header and footer) in measurement
+ var headerMeasure = column.Header.Measure(options, maxWidth);
+ var footerMeasure = column.Footer?.Measure(options, maxWidth) ?? headerMeasure;
+ minWidths.Add(Math.Min(headerMeasure.Min, footerMeasure.Min));
+ maxWidths.Add(Math.Max(headerMeasure.Max, footerMeasure.Max));
foreach (var row in rows)
{
- measure = row.Measure(options, maxWidth);
- minWidths.Add(measure.Min);
- maxWidths.Add(measure.Max);
+ var rowMeasure = row.Measure(options, maxWidth);
+ minWidths.Add(rowMeasure.Min);
+ maxWidths.Add(rowMeasure.Max);
}
return (minWidths.Count > 0 ? minWidths.Max() : padding,
diff --git a/src/Spectre.Console/Widgets/TableColumn.cs b/src/Spectre.Console/Widgets/TableColumn.cs
index eca6eeb..91bba5a 100644
--- a/src/Spectre.Console/Widgets/TableColumn.cs
+++ b/src/Spectre.Console/Widgets/TableColumn.cs
@@ -9,9 +9,14 @@ namespace Spectre.Console
public sealed class TableColumn : IColumn
{
///
- /// Gets the text associated with the column.
+ /// Gets the column header.
///
- public IRenderable Text { get; }
+ public IRenderable Header { get; }
+
+ ///
+ /// Gets or sets the column footer.
+ ///
+ public IRenderable? Footer { get; set; }
///
/// Gets or sets the width of the column.
@@ -39,19 +44,19 @@ namespace Spectre.Console
///
/// Initializes a new instance of the class.
///
- /// The table column text.
- public TableColumn(string text)
- : this(new Markup(text).Overflow(Overflow.Ellipsis))
+ /// The table column header.
+ public TableColumn(string header)
+ : this(new Markup(header).Overflow(Overflow.Ellipsis))
{
}
///
/// Initializes a new instance of the class.
///
- /// The instance to use as the table column.
- public TableColumn(IRenderable renderable)
+ /// The instance to use as the table column header.
+ public TableColumn(IRenderable header)
{
- Text = renderable ?? throw new ArgumentNullException(nameof(renderable));
+ Header = header ?? throw new ArgumentNullException(nameof(header));
Width = null;
Padding = new Padding(1, 0, 1, 0);
NoWrap = false;