diff --git a/examples/Console/Borders/Program.cs b/examples/Console/Borders/Program.cs
index 0dca101..2b755ae 100644
--- a/examples/Console/Borders/Program.cs
+++ b/examples/Console/Borders/Program.cs
@@ -20,21 +20,22 @@ public static class Program
{
static IRenderable CreatePanel(string name, BoxBorder border)
{
- return new Panel($"This is a panel with\nthe [yellow]{name}[/] border.")
- .Header($" [blue]{name}[/] ", Justify.Center)
- .Border(border)
- .BorderStyle(Style.Parse("grey"));
+ return
+ new Panel($"This is a panel with\nthe [yellow]{name}[/] border.")
+ .Header($" [blue]{name}[/] ", Justify.Center)
+ .Border(border)
+ .BorderStyle(Style.Parse("grey"));
}
var items = new[]
{
- CreatePanel("Ascii", BoxBorder.Ascii),
- CreatePanel("Square", BoxBorder.Square),
- CreatePanel("Rounded", BoxBorder.Rounded),
- CreatePanel("Heavy", BoxBorder.Heavy),
- CreatePanel("Double", BoxBorder.Double),
- CreatePanel("None", BoxBorder.None),
- };
+ CreatePanel("Ascii", BoxBorder.Ascii),
+ CreatePanel("Square", BoxBorder.Square),
+ CreatePanel("Rounded", BoxBorder.Rounded),
+ CreatePanel("Heavy", BoxBorder.Heavy),
+ CreatePanel("Double", BoxBorder.Double),
+ CreatePanel("None", BoxBorder.None),
+ };
AnsiConsole.Write(
new Padder(
@@ -47,6 +48,7 @@ public static class Program
static IRenderable CreateTable(string name, TableBorder border)
{
var table = new Table().Border(border);
+ table.ShowRowSeparators();
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");
@@ -54,29 +56,23 @@ public static class Program
return new Panel(table)
.Header($" [blue]{name}[/] ", Justify.Center)
+ .PadBottom(1)
.NoBorder();
}
var items = new[]
{
- CreateTable("Ascii", TableBorder.Ascii),
- CreateTable("Ascii2", TableBorder.Ascii2),
- CreateTable("AsciiDoubleHead", TableBorder.AsciiDoubleHead),
- CreateTable("Horizontal", TableBorder.Horizontal),
- CreateTable("Simple", TableBorder.Simple),
- CreateTable("SimpleHeavy", TableBorder.SimpleHeavy),
- CreateTable("Minimal", TableBorder.Minimal),
- CreateTable("MinimalHeavyHead", TableBorder.MinimalHeavyHead),
- CreateTable("MinimalDoubleHead", TableBorder.MinimalDoubleHead),
- CreateTable("Square", TableBorder.Square),
- CreateTable("Rounded", TableBorder.Rounded),
- CreateTable("Heavy", TableBorder.Heavy),
- CreateTable("HeavyEdge", TableBorder.HeavyEdge),
- CreateTable("HeavyHead", TableBorder.HeavyHead),
- CreateTable("Double", TableBorder.Double),
- CreateTable("DoubleEdge", TableBorder.DoubleEdge),
- CreateTable("Markdown", TableBorder.Markdown),
- };
+ CreateTable("Ascii", TableBorder.Ascii), CreateTable("Ascii2", TableBorder.Ascii2),
+ CreateTable("AsciiDoubleHead", TableBorder.AsciiDoubleHead),
+ CreateTable("Horizontal", TableBorder.Horizontal), CreateTable("Simple", TableBorder.Simple),
+ CreateTable("SimpleHeavy", TableBorder.SimpleHeavy), CreateTable("Minimal", TableBorder.Minimal),
+ CreateTable("MinimalHeavyHead", TableBorder.MinimalHeavyHead),
+ CreateTable("MinimalDoubleHead", TableBorder.MinimalDoubleHead),
+ CreateTable("Square", TableBorder.Square), CreateTable("Rounded", TableBorder.Rounded),
+ CreateTable("Heavy", TableBorder.Heavy), CreateTable("HeavyEdge", TableBorder.HeavyEdge),
+ CreateTable("HeavyHead", TableBorder.HeavyHead), CreateTable("Double", TableBorder.Double),
+ CreateTable("DoubleEdge", TableBorder.DoubleEdge), CreateTable("Markdown", TableBorder.Markdown),
+ };
AnsiConsole.Write(new Columns(items).Collapse());
}
@@ -87,4 +83,4 @@ public static class Program
AnsiConsole.Write(new Rule($"[white bold]{title}[/]").RuleStyle("grey").LeftJustified());
AnsiConsole.WriteLine();
}
-}
+}
\ No newline at end of file
diff --git a/src/Spectre.Console/Extensions/TableExtensions.cs b/src/Spectre.Console/Extensions/TableExtensions.cs
index e232e64..ddb2331 100644
--- a/src/Spectre.Console/Extensions/TableExtensions.cs
+++ b/src/Spectre.Console/Extensions/TableExtensions.cs
@@ -334,6 +334,38 @@ public static class TableExtensions
return table;
}
+ ///
+ /// Shows row separators.
+ ///
+ /// The table.
+ /// The same instance so that multiple calls can be chained.
+ public static Table ShowRowSeparators(this Table table)
+ {
+ if (table is null)
+ {
+ throw new ArgumentNullException(nameof(table));
+ }
+
+ table.ShowRowSeparators = true;
+ return table;
+ }
+
+ ///
+ /// Hides row separators.
+ ///
+ /// The table.
+ /// The same instance so that multiple calls can be chained.
+ public static Table HideRowSeparators(this Table table)
+ {
+ if (table is null)
+ {
+ throw new ArgumentNullException(nameof(table));
+ }
+
+ table.ShowRowSeparators = false;
+ return table;
+ }
+
///
/// Shows table footers.
///
diff --git a/src/Spectre.Console/Rendering/Borders/TableBorderPart.cs b/src/Spectre.Console/Rendering/Borders/TableBorderPart.cs
index 2359266..dbf64af 100644
--- a/src/Spectre.Console/Rendering/Borders/TableBorderPart.cs
+++ b/src/Spectre.Console/Rendering/Borders/TableBorderPart.cs
@@ -114,4 +114,24 @@ public enum TableBorderPart
/// The bottom right part of a footer.
///
FooterBottomRight,
+
+ ///
+ /// The left part of a row.
+ ///
+ RowLeft,
+
+ ///
+ /// The center part of a row.
+ ///
+ RowCenter,
+
+ ///
+ /// The separator part of a row.
+ ///
+ RowSeparator,
+
+ ///
+ /// The right part of a row.
+ ///
+ RowRight,
}
\ No newline at end of file
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/Ascii2TableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/Ascii2TableBorder.cs
index 7bd17d6..0cd6122 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/Ascii2TableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/Ascii2TableBorder.cs
@@ -32,6 +32,10 @@ public sealed class Ascii2TableBorder : TableBorder
TableBorderPart.FooterBottom => "-",
TableBorderPart.FooterBottomSeparator => "+",
TableBorderPart.FooterBottomRight => "+",
+ TableBorderPart.RowLeft => "|",
+ TableBorderPart.RowCenter => "-",
+ TableBorderPart.RowSeparator => "+",
+ TableBorderPart.RowRight => "|",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/AsciiDoubleHeadTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/AsciiDoubleHeadTableBorder.cs
index f5f2bad..33c78ce 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/AsciiDoubleHeadTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/AsciiDoubleHeadTableBorder.cs
@@ -32,6 +32,10 @@ public sealed class AsciiDoubleHeadTableBorder : TableBorder
TableBorderPart.FooterBottom => "-",
TableBorderPart.FooterBottomSeparator => "+",
TableBorderPart.FooterBottomRight => "+",
+ TableBorderPart.RowLeft => "|",
+ TableBorderPart.RowCenter => "-",
+ TableBorderPart.RowSeparator => "+",
+ TableBorderPart.RowRight => "|",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/AsciiTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/AsciiTableBorder.cs
index 7f4f743..903665c 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/AsciiTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/AsciiTableBorder.cs
@@ -32,6 +32,10 @@ public sealed class AsciiTableBorder : TableBorder
TableBorderPart.FooterBottom => "-",
TableBorderPart.FooterBottomSeparator => "-",
TableBorderPart.FooterBottomRight => "+",
+ TableBorderPart.RowLeft => "|",
+ TableBorderPart.RowCenter => "-",
+ TableBorderPart.RowSeparator => "+",
+ TableBorderPart.RowRight => "|",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/DoubleEdgeTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/DoubleEdgeTableBorder.cs
index ab13621..6f756ff 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/DoubleEdgeTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/DoubleEdgeTableBorder.cs
@@ -32,6 +32,10 @@ public sealed class DoubleEdgeTableBorder : TableBorder
TableBorderPart.FooterBottom => "═",
TableBorderPart.FooterBottomSeparator => "╧",
TableBorderPart.FooterBottomRight => "╝",
+ TableBorderPart.RowLeft => "╟",
+ TableBorderPart.RowCenter => "─",
+ TableBorderPart.RowSeparator => "┼",
+ TableBorderPart.RowRight => "╢",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/DoubleTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/DoubleTableBorder.cs
index b5eca04..40b2f6b 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/DoubleTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/DoubleTableBorder.cs
@@ -32,6 +32,10 @@ public sealed class DoubleTableBorder : TableBorder
TableBorderPart.FooterBottom => "═",
TableBorderPart.FooterBottomSeparator => "╩",
TableBorderPart.FooterBottomRight => "╝",
+ TableBorderPart.RowLeft => "╠",
+ TableBorderPart.RowCenter => "═",
+ TableBorderPart.RowSeparator => "╬",
+ TableBorderPart.RowRight => "╣",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/HeavyEdgeTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/HeavyEdgeTableBorder.cs
index f5728be..31cadca 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/HeavyEdgeTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/HeavyEdgeTableBorder.cs
@@ -35,6 +35,10 @@ public sealed class HeavyEdgeTableBorder : TableBorder
TableBorderPart.FooterBottom => "━",
TableBorderPart.FooterBottomSeparator => "┷",
TableBorderPart.FooterBottomRight => "┛",
+ TableBorderPart.RowLeft => "┠",
+ TableBorderPart.RowCenter => "─",
+ TableBorderPart.RowSeparator => "┼",
+ TableBorderPart.RowRight => "┨",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/HeavyHeadTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/HeavyHeadTableBorder.cs
index 87f3574..36c71c3 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/HeavyHeadTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/HeavyHeadTableBorder.cs
@@ -35,6 +35,10 @@ public sealed class HeavyHeadTableBorder : TableBorder
TableBorderPart.FooterBottom => "─",
TableBorderPart.FooterBottomSeparator => "┴",
TableBorderPart.FooterBottomRight => "┘",
+ TableBorderPart.RowLeft => "├",
+ TableBorderPart.RowCenter => "─",
+ TableBorderPart.RowSeparator => "┼",
+ TableBorderPart.RowRight => "┤",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/HeavyTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/HeavyTableBorder.cs
index 783f742..68d3675 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/HeavyTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/HeavyTableBorder.cs
@@ -35,6 +35,10 @@ public sealed class HeavyTableBorder : TableBorder
TableBorderPart.FooterBottom => "━",
TableBorderPart.FooterBottomSeparator => "┻",
TableBorderPart.FooterBottomRight => "┛",
+ TableBorderPart.RowLeft => "┣",
+ TableBorderPart.RowCenter => "━",
+ TableBorderPart.RowSeparator => "╋",
+ TableBorderPart.RowRight => "┫",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/HorizontalTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/HorizontalTableBorder.cs
index db3021d..740f8e5 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/HorizontalTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/HorizontalTableBorder.cs
@@ -32,6 +32,10 @@ public sealed class HorizontalTableBorder : TableBorder
TableBorderPart.FooterBottom => "─",
TableBorderPart.FooterBottomSeparator => "─",
TableBorderPart.FooterBottomRight => "─",
+ TableBorderPart.RowLeft => "─",
+ TableBorderPart.RowCenter => "─",
+ TableBorderPart.RowSeparator => "─",
+ TableBorderPart.RowRight => "─",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/MarkdownTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/MarkdownTableBorder.cs
index f338c39..fa21f1c 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/MarkdownTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/MarkdownTableBorder.cs
@@ -5,6 +5,9 @@ namespace Spectre.Console.Rendering;
///
public sealed class MarkdownTableBorder : TableBorder
{
+ ///
+ public override bool SupportsRowSeparator => false;
+
///
public override string GetPart(TableBorderPart part)
{
@@ -32,6 +35,10 @@ public sealed class MarkdownTableBorder : TableBorder
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
TableBorderPart.FooterBottomRight => " ",
+ TableBorderPart.RowLeft => " ",
+ TableBorderPart.RowCenter => " ",
+ TableBorderPart.RowSeparator => " ",
+ TableBorderPart.RowRight => " ",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/MinimalDoubleHeadTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/MinimalDoubleHeadTableBorder.cs
index 5fd281e..8d58d8f 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/MinimalDoubleHeadTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/MinimalDoubleHeadTableBorder.cs
@@ -32,6 +32,10 @@ public sealed class MinimalDoubleHeadTableBorder : TableBorder
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
TableBorderPart.FooterBottomRight => " ",
+ TableBorderPart.RowLeft => " ",
+ TableBorderPart.RowCenter => "─",
+ TableBorderPart.RowSeparator => "┼",
+ TableBorderPart.RowRight => " ",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/MinimalHeavyHeadTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/MinimalHeavyHeadTableBorder.cs
index 7c8cffe..4d9fd6d 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/MinimalHeavyHeadTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/MinimalHeavyHeadTableBorder.cs
@@ -35,6 +35,10 @@ public sealed class MinimalHeavyHeadTableBorder : TableBorder
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
TableBorderPart.FooterBottomRight => " ",
+ TableBorderPart.RowLeft => " ",
+ TableBorderPart.RowCenter => "─",
+ TableBorderPart.RowSeparator => "┼",
+ TableBorderPart.RowRight => " ",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/MinimalTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/MinimalTableBorder.cs
index 06d47aa..54d1d17 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/MinimalTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/MinimalTableBorder.cs
@@ -32,6 +32,10 @@ public sealed class MinimalTableBorder : TableBorder
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
TableBorderPart.FooterBottomRight => " ",
+ TableBorderPart.RowLeft => " ",
+ TableBorderPart.RowCenter => "─",
+ TableBorderPart.RowSeparator => "┼",
+ TableBorderPart.RowRight => " ",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/NoTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/NoTableBorder.cs
index c251d9b..26ed655 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/NoTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/NoTableBorder.cs
@@ -8,6 +8,9 @@ public sealed class NoTableBorder : TableBorder
///
public override bool Visible => false;
+ ///
+ public override bool SupportsRowSeparator => false;
+
///
public override string GetPart(TableBorderPart part)
{
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/RoundedTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/RoundedTableBorder.cs
index 9d02c68..5db78ad 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/RoundedTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/RoundedTableBorder.cs
@@ -35,6 +35,10 @@ public sealed class RoundedTableBorder : TableBorder
TableBorderPart.FooterBottom => "─",
TableBorderPart.FooterBottomSeparator => "┴",
TableBorderPart.FooterBottomRight => "╯",
+ TableBorderPart.RowLeft => "├",
+ TableBorderPart.RowCenter => "─",
+ TableBorderPart.RowSeparator => "┼",
+ TableBorderPart.RowRight => "┤",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/SimpleHeavyTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/SimpleHeavyTableBorder.cs
index d8ae957..1a703ab 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/SimpleHeavyTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/SimpleHeavyTableBorder.cs
@@ -35,6 +35,10 @@ public sealed class SimpleHeavyTableBorder : TableBorder
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
TableBorderPart.FooterBottomRight => " ",
+ TableBorderPart.RowLeft => "─",
+ TableBorderPart.RowCenter => "─",
+ TableBorderPart.RowSeparator => "─",
+ TableBorderPart.RowRight => "─",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/SimpleTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/SimpleTableBorder.cs
index 30fa563..0bc8531 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/SimpleTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/SimpleTableBorder.cs
@@ -32,6 +32,10 @@ public sealed class SimpleTableBorder : TableBorder
TableBorderPart.FooterBottom => " ",
TableBorderPart.FooterBottomSeparator => " ",
TableBorderPart.FooterBottomRight => " ",
+ TableBorderPart.RowLeft => "─",
+ TableBorderPart.RowCenter => "─",
+ TableBorderPart.RowSeparator => "─",
+ TableBorderPart.RowRight => "─",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/Borders/Tables/SquareTableBorder.cs b/src/Spectre.Console/Rendering/Borders/Tables/SquareTableBorder.cs
index 4e7e731..e30ce3d 100644
--- a/src/Spectre.Console/Rendering/Borders/Tables/SquareTableBorder.cs
+++ b/src/Spectre.Console/Rendering/Borders/Tables/SquareTableBorder.cs
@@ -32,6 +32,10 @@ public sealed class SquareTableBorder : TableBorder
TableBorderPart.FooterBottom => "─",
TableBorderPart.FooterBottomSeparator => "┴",
TableBorderPart.FooterBottomRight => "┘",
+ TableBorderPart.RowLeft => "├",
+ TableBorderPart.RowCenter => "─",
+ TableBorderPart.RowSeparator => "┼",
+ TableBorderPart.RowRight => "┤",
_ => throw new InvalidOperationException("Unknown border part."),
};
}
diff --git a/src/Spectre.Console/Rendering/TablePart.cs b/src/Spectre.Console/Rendering/TablePart.cs
index 1992252..1634967 100644
--- a/src/Spectre.Console/Rendering/TablePart.cs
+++ b/src/Spectre.Console/Rendering/TablePart.cs
@@ -15,6 +15,11 @@ public enum TablePart
///
HeaderSeparator,
+ ///
+ /// The separator between the rows.
+ ///
+ RowSeparator,
+
///
/// The separator between the footer and the cells.
///
diff --git a/src/Spectre.Console/Spectre.Console.csproj b/src/Spectre.Console/Spectre.Console.csproj
index bf1630c..fdecc82 100644
--- a/src/Spectre.Console/Spectre.Console.csproj
+++ b/src/Spectre.Console/Spectre.Console.csproj
@@ -36,9 +36,6 @@
-
-
-
$(DefineConstants)TRACE;WCWIDTH_VISIBILITY_INTERNAL
diff --git a/src/Spectre.Console/TableBorder.cs b/src/Spectre.Console/TableBorder.cs
index a206544..a339713 100644
--- a/src/Spectre.Console/TableBorder.cs
+++ b/src/Spectre.Console/TableBorder.cs
@@ -13,7 +13,12 @@ public abstract partial class TableBorder
///
/// Gets the safe border for this border or null if none exist.
///
- public virtual TableBorder? SafeBorder { get; }
+ public virtual TableBorder? SafeBorder { get; } = null;
+
+ ///
+ /// Gets a value indicating whether the border supports row separators or not.
+ ///
+ public virtual bool SupportsRowSeparator { get; } = true;
///
/// Gets the string representation of a specified table border part.
@@ -81,6 +86,11 @@ public abstract partial class TableBorder
(GetPart(TableBorderPart.HeaderBottomLeft), GetPart(TableBorderPart.HeaderBottom),
GetPart(TableBorderPart.HeaderBottomSeparator), GetPart(TableBorderPart.HeaderBottomRight)),
+ // Separator between header and cells
+ TablePart.RowSeparator =>
+ (GetPart(TableBorderPart.RowLeft), GetPart(TableBorderPart.RowCenter),
+ GetPart(TableBorderPart.RowSeparator), GetPart(TableBorderPart.RowRight)),
+
// Separator between footer and cells
TablePart.FooterSeparator =>
(GetPart(TableBorderPart.FooterTopLeft), GetPart(TableBorderPart.FooterTop),
diff --git a/src/Spectre.Console/Widgets/Panel.cs b/src/Spectre.Console/Widgets/Panel.cs
index 05d41d4..7a34d95 100644
--- a/src/Spectre.Console/Widgets/Panel.cs
+++ b/src/Spectre.Console/Widgets/Panel.cs
@@ -132,6 +132,15 @@ public sealed class Panel : Renderable, IHasBoxBorder, IHasBorder, IExpandable,
{
AddTopBorder(result, options, border, borderStyle, panelWidth);
}
+ else
+ {
+ // Not showing border, but we have a header text?
+ // Use a invisible border to draw the top border
+ if (Header?.Text != null)
+ {
+ AddTopBorder(result, options, BoxBorder.None, borderStyle, panelWidth);
+ }
+ }
// Split the child segments into lines.
var childSegments = ((IRenderable)child).Render(options with { Height = height }, innerWidth);
diff --git a/src/Spectre.Console/Widgets/Table/Table.cs b/src/Spectre.Console/Widgets/Table/Table.cs
index c0d83e1..345e83d 100644
--- a/src/Spectre.Console/Widgets/Table/Table.cs
+++ b/src/Spectre.Console/Widgets/Table/Table.cs
@@ -31,6 +31,11 @@ public sealed class Table : Renderable, IHasTableBorder, IExpandable, IAlignable
///
public bool ShowHeaders { get; set; } = true;
+ ///
+ /// Gets or sets a value indicating whether or not row separators should be shown.
+ ///
+ public bool ShowRowSeparators { get; set; }
+
///
/// Gets or sets a value indicating whether or not table footers should be shown.
///
diff --git a/src/Spectre.Console/Widgets/Table/TableRenderer.cs b/src/Spectre.Console/Widgets/Table/TableRenderer.cs
index d27326e..23bff61 100644
--- a/src/Spectre.Console/Widgets/Table/TableRenderer.cs
+++ b/src/Spectre.Console/Widgets/Table/TableRenderer.cs
@@ -36,7 +36,9 @@ internal static class TableRenderer
// Show top of header?
if (isFirstRow && context.ShowBorder)
{
- var separator = Aligner.Align(context.Border.GetColumnRow(TablePart.Top, columnWidths, context.Columns), context.Alignment, context.MaxWidth);
+ var separator = Aligner.Align(
+ context.Border.GetColumnRow(TablePart.Top, columnWidths, context.Columns),
+ context.Alignment, context.MaxWidth);
result.Add(new Segment(separator, context.BorderStyle));
result.Add(Segment.LineBreak);
}
@@ -66,7 +68,9 @@ internal static class TableRenderer
if (isFirstCell && context.ShowBorder)
{
// Show left column edge
- var part = isFirstRow && context.ShowHeaders ? TableBorderPart.HeaderLeft : TableBorderPart.CellLeft;
+ var part = isFirstRow && context.ShowHeaders
+ ? TableBorderPart.HeaderLeft
+ : TableBorderPart.CellLeft;
rowResult.Add(new Segment(context.Border.GetPart(part), context.BorderStyle));
}
@@ -91,7 +95,8 @@ internal static class TableRenderer
}
// Pad column on the right side
- if (context.ShowBorder || (context.HideBorder && !isLastCell) || (context.HideBorder && isLastCell && context.IsGrid && context.PadRightCell))
+ if (context.ShowBorder || (context.HideBorder && !isLastCell) ||
+ (context.HideBorder && isLastCell && context.IsGrid && context.PadRightCell))
{
var rightPadding = context.Columns[cellIndex].Padding.GetRightSafe();
if (rightPadding > 0)
@@ -103,13 +108,17 @@ internal static class TableRenderer
if (isLastCell && context.ShowBorder)
{
// Add right column edge
- var part = isFirstRow && context.ShowHeaders ? TableBorderPart.HeaderRight : TableBorderPart.CellRight;
+ var part = isFirstRow && context.ShowHeaders
+ ? TableBorderPart.HeaderRight
+ : TableBorderPart.CellRight;
rowResult.Add(new Segment(context.Border.GetPart(part), context.BorderStyle));
}
else if (context.ShowBorder)
{
// Add column separator
- var part = isFirstRow && context.ShowHeaders ? TableBorderPart.HeaderSeparator : TableBorderPart.CellSeparator;
+ var part = isFirstRow && context.ShowHeaders
+ ? TableBorderPart.HeaderSeparator
+ : TableBorderPart.CellSeparator;
rowResult.Add(new Segment(context.Border.GetPart(part), context.BorderStyle));
}
}
@@ -133,15 +142,40 @@ internal static class TableRenderer
// Show header separator?
if (isFirstRow && context.ShowBorder && context.ShowHeaders && context.HasRows)
{
- var separator = Aligner.Align(context.Border.GetColumnRow(TablePart.HeaderSeparator, columnWidths, context.Columns), context.Alignment, context.MaxWidth);
+ var separator =
+ Aligner.Align(
+ context.Border.GetColumnRow(TablePart.HeaderSeparator, columnWidths, context.Columns),
+ context.Alignment, context.MaxWidth);
result.Add(new Segment(separator, context.BorderStyle));
result.Add(Segment.LineBreak);
}
+ // Show row separator?
+ if (context.Border.SupportsRowSeparator && context.ShowRowSeparators
+ && !isFirstRow && !isLastRow)
+ {
+ var hasVisibleFootes = context is { ShowFooters: true, HasFooters: true };
+ var isNextLastLine = index == context.Rows.Count - 2;
+
+ var isRenderingFooter = hasVisibleFootes && isNextLastLine;
+ if (!isRenderingFooter)
+ {
+ var separator =
+ Aligner.Align(
+ context.Border.GetColumnRow(TablePart.RowSeparator, columnWidths, context.Columns),
+ context.Alignment, context.MaxWidth);
+ result.Add(new Segment(separator, context.BorderStyle));
+ result.Add(Segment.LineBreak);
+ }
+ }
+
// Show bottom of footer?
if (isLastRow && context.ShowBorder)
{
- var separator = Aligner.Align(context.Border.GetColumnRow(TablePart.Bottom, columnWidths, context.Columns), context.Alignment, context.MaxWidth);
+ var separator =
+ Aligner.Align(
+ context.Border.GetColumnRow(TablePart.Bottom, columnWidths, context.Columns),
+ context.Alignment, context.MaxWidth);
result.Add(new Segment(separator, context.BorderStyle));
result.Add(Segment.LineBreak);
}
@@ -151,7 +185,8 @@ internal static class TableRenderer
return result;
}
- private static IEnumerable RenderAnnotation(TableRendererContext context, TableTitle? header, Style defaultStyle)
+ private static IEnumerable RenderAnnotation(TableRendererContext context, TableTitle? header,
+ Style defaultStyle)
{
if (header == null)
{
diff --git a/src/Spectre.Console/Widgets/Table/TableRendererContext.cs b/src/Spectre.Console/Widgets/Table/TableRendererContext.cs
index b549802..ad9b709 100644
--- a/src/Spectre.Console/Widgets/Table/TableRendererContext.cs
+++ b/src/Spectre.Console/Widgets/Table/TableRendererContext.cs
@@ -10,6 +10,7 @@ internal sealed class TableRendererContext : TableAccessor
public TableBorder Border { get; }
public Style BorderStyle { get; }
public bool ShowBorder { get; }
+ public bool ShowRowSeparators { get; }
public bool HasRows { get; }
public bool HasFooters { get; }
@@ -47,6 +48,7 @@ internal sealed class TableRendererContext : TableAccessor
HasFooters = Rows.Any(column => column.IsFooter);
Border = table.Border.GetSafeBorder(!options.Unicode && table.UseSafeBorder);
BorderStyle = table.BorderStyle ?? Style.Plain;
+ ShowRowSeparators = table.ShowRowSeparators;
TableWidth = tableWidth;
MaxWidth = maxWidth;
diff --git a/test/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder.Output.verified.txt b/test/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder.Output.verified.txt
index 0d3e931..a254250 100644
--- a/test/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder.Output.verified.txt
+++ b/test/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder.Output.verified.txt
@@ -1 +1 @@
- Hello World
+ Hello World
diff --git a/test/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder_With_Header.Output.verified.txt b/test/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder_With_Header.Output.verified.txt
new file mode 100644
index 0000000..2ad34ae
--- /dev/null
+++ b/test/Spectre.Console.Tests/Expectations/Rendering/Borders/Box/NoBorder_With_Header.Output.verified.txt
@@ -0,0 +1,2 @@
+ Greeting
+ Hello World
diff --git a/test/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators.Output.verified.txt b/test/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators.Output.verified.txt
new file mode 100644
index 0000000..02d8f0d
--- /dev/null
+++ b/test/Spectre.Console.Tests/Expectations/Widgets/Table/Render_Row_Separators.Output.verified.txt
@@ -0,0 +1,7 @@
+┌────────┬────────┬───────┐
+│ Foo │ Bar │ Baz │
+├────────┼────────┼───────┤
+│ Qux │ Corgi │ Waldo │
+├────────┼────────┼───────┤
+│ Grault │ Garply │ Fred │
+└────────┴────────┴───────┘
diff --git a/test/Spectre.Console.Tests/Unit/Rendering/Borders/BoxBorderTests.cs b/test/Spectre.Console.Tests/Unit/Rendering/Borders/BoxBorderTests.cs
index f16fe97..d9643cb 100644
--- a/test/Spectre.Console.Tests/Unit/Rendering/Borders/BoxBorderTests.cs
+++ b/test/Spectre.Console.Tests/Unit/Rendering/Borders/BoxBorderTests.cs
@@ -23,6 +23,22 @@ public sealed class BoxBorderTests
[Fact]
[Expectation("NoBorder")]
public Task Should_Render_As_Expected()
+ {
+ // Given
+ var console = new TestConsole();
+ var panel = Fixture.GetPanel().NoBorder();
+ panel.Header = null;
+
+ // When
+ console.Write(panel);
+
+ // Then
+ return Verifier.Verify(console.Output);
+ }
+
+ [Fact]
+ [Expectation("NoBorder_With_Header")]
+ public Task Should_Render_NoBorder_With_Header_As_Expected()
{
// Given
var console = new TestConsole();
diff --git a/test/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs b/test/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs
index a8fb908..8a1ce1d 100644
--- a/test/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs
+++ b/test/Spectre.Console.Tests/Unit/Widgets/Table/TableTests.cs
@@ -142,6 +142,25 @@ public sealed class TableTests
return Verifier.Verify(console.Output);
}
+ [Fact]
+ [Expectation("Render_Row_Separators")]
+ public Task Should_Render_Table_With_Row_Separators_Correctly()
+ {
+ // Given
+ var console = new TestConsole();
+ var table = new Table();
+ table.ShowRowSeparators();
+ table.AddColumns("Foo", "Bar", "Baz");
+ table.AddRow("Qux", "Corgi", "Waldo");
+ table.AddRow("Grault", "Garply", "Fred");
+
+ // When
+ console.Write(table);
+
+ // Then
+ return Verifier.Verify(console.Output);
+ }
+
[Fact]
[Expectation("Render_EA_Character")]
public Task Should_Render_Table_With_EA_Character_Correctly()