mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-11-01 01:25:27 +08:00 
			
		
		
		
	Add option to show separator between table rows (#1304)
* Add option to show separator between table rows * Panels should show header if borders are not shown Closes #835
This commit is contained in:
		| @@ -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(); | ||||
|     } | ||||
| } | ||||
| } | ||||
| @@ -334,6 +334,38 @@ public static class TableExtensions | ||||
|         return table; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Shows row separators. | ||||
|     /// </summary> | ||||
|     /// <param name="table">The table.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static Table ShowRowSeparators(this Table table) | ||||
|     { | ||||
|         if (table is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(table)); | ||||
|         } | ||||
|  | ||||
|         table.ShowRowSeparators = true; | ||||
|         return table; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Hides row separators. | ||||
|     /// </summary> | ||||
|     /// <param name="table">The table.</param> | ||||
|     /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|     public static Table HideRowSeparators(this Table table) | ||||
|     { | ||||
|         if (table is null) | ||||
|         { | ||||
|             throw new ArgumentNullException(nameof(table)); | ||||
|         } | ||||
|  | ||||
|         table.ShowRowSeparators = false; | ||||
|         return table; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Shows table footers. | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -114,4 +114,24 @@ public enum TableBorderPart | ||||
|     /// The bottom right part of a footer. | ||||
|     /// </summary> | ||||
|     FooterBottomRight, | ||||
|  | ||||
|     /// <summary> | ||||
|     /// The left part of a row. | ||||
|     /// </summary> | ||||
|     RowLeft, | ||||
|  | ||||
|     /// <summary> | ||||
|     /// The center part of a row. | ||||
|     /// </summary> | ||||
|     RowCenter, | ||||
|  | ||||
|     /// <summary> | ||||
|     /// The separator part of a row. | ||||
|     /// </summary> | ||||
|     RowSeparator, | ||||
|  | ||||
|     /// <summary> | ||||
|     /// The right part of a row. | ||||
|     /// </summary> | ||||
|     RowRight, | ||||
| } | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -5,6 +5,9 @@ namespace Spectre.Console.Rendering; | ||||
| /// </summary> | ||||
| public sealed class MarkdownTableBorder : TableBorder | ||||
| { | ||||
|     /// <inheritdoc /> | ||||
|     public override bool SupportsRowSeparator => false; | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -8,6 +8,9 @@ public sealed class NoTableBorder : TableBorder | ||||
|     /// <inheritdoc/> | ||||
|     public override bool Visible => false; | ||||
|  | ||||
|     /// <inheritdoc /> | ||||
|     public override bool SupportsRowSeparator => false; | ||||
|  | ||||
|     /// <inheritdoc/> | ||||
|     public override string GetPart(TableBorderPart part) | ||||
|     { | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -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."), | ||||
|         }; | ||||
|     } | ||||
|   | ||||
| @@ -15,6 +15,11 @@ public enum TablePart | ||||
|     /// </summary> | ||||
|     HeaderSeparator, | ||||
|  | ||||
|     /// <summary> | ||||
|     /// The separator between the rows. | ||||
|     /// </summary> | ||||
|     RowSeparator, | ||||
|  | ||||
|     /// <summary> | ||||
|     /// The separator between the footer and the cells. | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -36,9 +36,6 @@ | ||||
|     </PackageReference> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <Folder Include="Widgets\Json\" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <PropertyGroup> | ||||
|     <DefineConstants>$(DefineConstants)TRACE;WCWIDTH_VISIBILITY_INTERNAL</DefineConstants> | ||||
|   | ||||
| @@ -13,7 +13,12 @@ public abstract partial class TableBorder | ||||
|     /// <summary> | ||||
|     /// Gets the safe border for this border or <c>null</c> if none exist. | ||||
|     /// </summary> | ||||
|     public virtual TableBorder? SafeBorder { get; } | ||||
|     public virtual TableBorder? SafeBorder { get; } = null; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets a value indicating whether the border supports row separators or not. | ||||
|     /// </summary> | ||||
|     public virtual bool SupportsRowSeparator { get; } = true; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// 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), | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -31,6 +31,11 @@ public sealed class Table : Renderable, IHasTableBorder, IExpandable, IAlignable | ||||
|     /// </summary> | ||||
|     public bool ShowHeaders { get; set; } = true; | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets a value indicating whether or not row separators should be shown. | ||||
|     /// </summary> | ||||
|     public bool ShowRowSeparators { get; set; } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Gets or sets a value indicating whether or not table footers should be shown. | ||||
|     /// </summary> | ||||
|   | ||||
| @@ -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<Segment> RenderAnnotation(TableRendererContext context, TableTitle? header, Style defaultStyle) | ||||
|     private static IEnumerable<Segment> RenderAnnotation(TableRendererContext context, TableTitle? header, | ||||
|         Style defaultStyle) | ||||
|     { | ||||
|         if (header == null) | ||||
|         { | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
|  Hello World  | ||||
|  Hello World  | ||||
|   | ||||
| @@ -0,0 +1,2 @@ | ||||
|   Greeting    | ||||
|  Hello World  | ||||
| @@ -0,0 +1,7 @@ | ||||
| ┌────────┬────────┬───────┐ | ||||
| │ Foo    │ Bar    │ Baz   │ | ||||
| ├────────┼────────┼───────┤ | ||||
| │ Qux    │ Corgi  │ Waldo │ | ||||
| ├────────┼────────┼───────┤ | ||||
| │ Grault │ Garply │ Fred  │ | ||||
| └────────┴────────┴───────┘ | ||||
| @@ -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(); | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Patrik Svensson
					Patrik Svensson