mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-11-01 01:25:27 +08:00 
			
		
		
		
	 Patrik Svensson
					Patrik Svensson
				
			
				
					committed by
					
						 Patrik Svensson
						Patrik Svensson
					
				
			
			
				
	
			
			
			 Patrik Svensson
						Patrik Svensson
					
				
			
						parent
						
							57731c0d55
						
					
				
				
					commit
					e169df6303
				
			
							
								
								
									
										2
									
								
								.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -89,7 +89,7 @@ jobs: | |||||||
|         shell: bash |         shell: bash | ||||||
|         run: | |         run: | | ||||||
|           dotnet tool restore |           dotnet tool restore | ||||||
|           dotnet example --all |           dotnet example --all --skip live --skip livetable --skip prompt | ||||||
|  |  | ||||||
|       - name: Build |       - name: Build | ||||||
|         shell: bash |         shell: bash | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "dotnet-example": { |     "dotnet-example": { | ||||||
|       "version": "1.3.1", |       "version": "1.5.0", | ||||||
|       "commands": [ |       "commands": [ | ||||||
|         "dotnet-example" |         "dotnet-example" | ||||||
|       ] |       ] | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|     <TargetFramework>net5.0</TargetFramework> |     <TargetFramework>net5.0</TargetFramework> | ||||||
|     <ExampleTitle>Live</ExampleTitle> |     <ExampleTitle>Live</ExampleTitle> | ||||||
|     <ExampleDescription>Demonstrates how to do live updates.</ExampleDescription> |     <ExampleDescription>Demonstrates how to do live updates.</ExampleDescription> | ||||||
|     <ExampleGroup>Misc</ExampleGroup> |     <ExampleGroup>Live</ExampleGroup> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								examples/Console/LiveTable/LiveTable.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								examples/Console/LiveTable/LiveTable.csproj
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | <Project Sdk="Microsoft.NET.Sdk"> | ||||||
|  |  | ||||||
|  |   <PropertyGroup> | ||||||
|  |     <OutputType>Exe</OutputType> | ||||||
|  |     <TargetFramework>net5.0</TargetFramework> | ||||||
|  |     <ExampleTitle>LiveTable</ExampleTitle> | ||||||
|  |     <ExampleDescription>Demonstrates how to do live updates in a table.</ExampleDescription> | ||||||
|  |     <ExampleGroup>Live</ExampleGroup> | ||||||
|  |   </PropertyGroup> | ||||||
|  |  | ||||||
|  |   <ItemGroup> | ||||||
|  |     <ProjectReference Include="..\..\Shared\Shared.csproj" /> | ||||||
|  |   </ItemGroup> | ||||||
|  |  | ||||||
|  | </Project> | ||||||
							
								
								
									
										86
									
								
								examples/Console/LiveTable/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								examples/Console/LiveTable/Program.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | |||||||
|  | using System; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console.Examples | ||||||
|  | { | ||||||
|  |     public static class Program | ||||||
|  |     { | ||||||
|  |         private const int NumberOfRows = 10; | ||||||
|  |  | ||||||
|  |         private static readonly Random _random = new(); | ||||||
|  |         private static readonly string[] _exchanges = new string[] | ||||||
|  |         { | ||||||
|  |             "SGD", "SEK", "PLN", | ||||||
|  |             "MYR", "EUR", "USD", | ||||||
|  |             "AUD", "JPY", "CNH", | ||||||
|  |             "HKD", "CAD", "INR", | ||||||
|  |             "DKK", "GBP", "RUB", | ||||||
|  |             "NZD", "MXN", "IDR", | ||||||
|  |             "TWD", "THB", "VND", | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         public static async Task Main(string[] args) | ||||||
|  |         { | ||||||
|  |             var table = new Table().Expand().BorderColor(Color.Grey); | ||||||
|  |             table.AddColumn("[yellow]Source currency[/]"); | ||||||
|  |             table.AddColumn("[yellow]Destination currency[/]"); | ||||||
|  |             table.AddColumn("[yellow]Exchange rate[/]"); | ||||||
|  |  | ||||||
|  |             AnsiConsole.MarkupLine("Press [yellow]CTRL+C[/] to exit"); | ||||||
|  |  | ||||||
|  |             await AnsiConsole.Live(table) | ||||||
|  |                 .AutoClear(false) | ||||||
|  |                 .Overflow(VerticalOverflow.Ellipsis) | ||||||
|  |                 .Cropping(VerticalOverflowCropping.Bottom) | ||||||
|  |                 .StartAsync(async ctx => | ||||||
|  |                 { | ||||||
|  |                     // Add some initial rows | ||||||
|  |                     foreach (var _ in Enumerable.Range(0, NumberOfRows)) | ||||||
|  |                     { | ||||||
|  |                         AddExchangeRateRow(table); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     // Continously update the table | ||||||
|  |                     while (true) | ||||||
|  |                     { | ||||||
|  |                         // More rows than we want? | ||||||
|  |                         if (table.Rows.Count > NumberOfRows) | ||||||
|  |                         { | ||||||
|  |                             // Remove the first one | ||||||
|  |                             table.Rows.RemoveAt(0); | ||||||
|  |                         } | ||||||
|  |  | ||||||
|  |                         // Add a new row | ||||||
|  |                         AddExchangeRateRow(table); | ||||||
|  |  | ||||||
|  |                         // Refresh and wait for a while | ||||||
|  |                         ctx.Refresh(); | ||||||
|  |                         await Task.Delay(400); | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static void AddExchangeRateRow(Table table) | ||||||
|  |         { | ||||||
|  |             var (source, destination, rate) = GetExchangeRate(); | ||||||
|  |             table.AddRow( | ||||||
|  |                 source, destination, | ||||||
|  |                 _random.NextDouble() > 0.35D ? $"[green]{rate}[/]" : $"[red]{rate}[/]"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static (string Source, string Destination, double Rate) GetExchangeRate() | ||||||
|  |         { | ||||||
|  |             var source = _exchanges[_random.Next(0, _exchanges.Length)]; | ||||||
|  |             var dest = _exchanges[_random.Next(0, _exchanges.Length)]; | ||||||
|  |             var rate = 200 / ((_random.NextDouble() * 320) + 1); | ||||||
|  |  | ||||||
|  |             while (source == dest) | ||||||
|  |             { | ||||||
|  |                 dest = _exchanges[_random.Next(0, _exchanges.Length)]; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return (source, dest, rate); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -63,6 +63,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tables", "Console\Tables\Ta | |||||||
| EndProject | EndProject | ||||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Trees", "Console\Trees\Trees.csproj", "{2BD88288-E05D-4978-B045-17937078E63C}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Trees", "Console\Trees\Trees.csproj", "{2BD88288-E05D-4978-B045-17937078E63C}" | ||||||
| EndProject | EndProject | ||||||
|  | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiveTable", "Console\LiveTable\LiveTable.csproj", "{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}" | ||||||
|  | EndProject | ||||||
| Global | Global | ||||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||||
| 		Debug|Any CPU = Debug|Any CPU | 		Debug|Any CPU = Debug|Any CPU | ||||||
| @@ -409,6 +411,18 @@ Global | |||||||
| 		{2BD88288-E05D-4978-B045-17937078E63C}.Release|x64.Build.0 = Release|Any CPU | 		{2BD88288-E05D-4978-B045-17937078E63C}.Release|x64.Build.0 = Release|Any CPU | ||||||
| 		{2BD88288-E05D-4978-B045-17937078E63C}.Release|x86.ActiveCfg = Release|Any CPU | 		{2BD88288-E05D-4978-B045-17937078E63C}.Release|x86.ActiveCfg = Release|Any CPU | ||||||
| 		{2BD88288-E05D-4978-B045-17937078E63C}.Release|x86.Build.0 = Release|Any CPU | 		{2BD88288-E05D-4978-B045-17937078E63C}.Release|x86.Build.0 = Release|Any CPU | ||||||
|  | 		{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
|  | 		{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Debug|x64.Build.0 = Debug|Any CPU | ||||||
|  | 		{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Debug|x86.Build.0 = Debug|Any CPU | ||||||
|  | 		{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
|  | 		{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Release|Any CPU.Build.0 = Release|Any CPU | ||||||
|  | 		{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Release|x64.ActiveCfg = Release|Any CPU | ||||||
|  | 		{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Release|x64.Build.0 = Release|Any CPU | ||||||
|  | 		{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Release|x86.ActiveCfg = Release|Any CPU | ||||||
|  | 		{E5FAAFB4-1D0F-4E29-A94F-A647D64AE64E}.Release|x86.Build.0 = Release|Any CPU | ||||||
| 	EndGlobalSection | 	EndGlobalSection | ||||||
| 	GlobalSection(SolutionProperties) = preSolution | 	GlobalSection(SolutionProperties) = preSolution | ||||||
| 		HideSolutionNode = FALSE | 		HideSolutionNode = FALSE | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| using System; | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using Spectre.Console.Rendering; | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
| @@ -35,6 +36,28 @@ namespace Spectre.Console | |||||||
|             return table; |             return table; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Adds a row to the table. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="table">The table to add the row to.</param> | ||||||
|  |         /// <param name="columns">The row columns to add.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static Table AddRow(this Table table, IEnumerable<IRenderable> columns) | ||||||
|  |         { | ||||||
|  |             if (table is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(table)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (columns is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(columns)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             table.Rows.Add(new TableRow(columns)); | ||||||
|  |             return table; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Adds a row to the table. |         /// Adds a row to the table. | ||||||
|         /// </summary> |         /// </summary> | ||||||
| @@ -48,7 +71,7 @@ namespace Spectre.Console | |||||||
|                 throw new ArgumentNullException(nameof(table)); |                 throw new ArgumentNullException(nameof(table)); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return table.AddRow(columns); |             return table.AddRow((IEnumerable<IRenderable>)columns); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -143,6 +166,80 @@ namespace Spectre.Console | |||||||
|             return table; |             return table; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Inserts a row in the table at the specified index. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="table">The table to add the row to.</param> | ||||||
|  |         /// <param name="index">The index to insert the row at.</param> | ||||||
|  |         /// <param name="columns">The row columns to add.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static Table InsertRow(this Table table, int index, IEnumerable<IRenderable> columns) | ||||||
|  |         { | ||||||
|  |             if (table is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(table)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (columns is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(columns)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             table.Rows.Insert(index, new TableRow(columns)); | ||||||
|  |             return table; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Inserts a row in the table at the specified index. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="table">The table to add the row to.</param> | ||||||
|  |         /// <param name="index">The index to insert the row at.</param> | ||||||
|  |         /// <param name="columns">The row columns to add.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static Table InsertRow(this Table table, int index, params IRenderable[] columns) | ||||||
|  |         { | ||||||
|  |             if (table is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(table)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return InsertRow(table, index, (IEnumerable<IRenderable>)columns); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Inserts a row in the table at the specified index. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="table">The table to add the row to.</param> | ||||||
|  |         /// <param name="index">The index to insert the row at.</param> | ||||||
|  |         /// <param name="columns">The row columns to add.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static Table InsertRow(this Table table, int index, params string[] columns) | ||||||
|  |         { | ||||||
|  |             if (table is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(table)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return InsertRow(table, index, columns.Select(column => new Markup(column))); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Removes a row from the table with the specified index. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="table">The table to add the row to.</param> | ||||||
|  |         /// <param name="index">The index to remove the row at.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static Table RemoveRow(this Table table, int index) | ||||||
|  |         { | ||||||
|  |             if (table is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(table)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             table.Rows.RemoveAt(index); | ||||||
|  |             return table; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Sets the table width. |         /// Sets the table width. | ||||||
|         /// </summary> |         /// </summary> | ||||||
|   | |||||||
| @@ -11,7 +11,6 @@ namespace Spectre.Console | |||||||
|     public sealed class Table : Renderable, IHasTableBorder, IExpandable, IAlignable |     public sealed class Table : Renderable, IHasTableBorder, IExpandable, IAlignable | ||||||
|     { |     { | ||||||
|         private readonly List<TableColumn> _columns; |         private readonly List<TableColumn> _columns; | ||||||
|         private readonly List<TableRow> _rows; |  | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Gets the table columns. |         /// Gets the table columns. | ||||||
| @@ -21,7 +20,7 @@ namespace Spectre.Console | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Gets the table rows. |         /// Gets the table rows. | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public IReadOnlyList<TableRow> Rows => _rows; |         public TableRowCollection Rows { get; } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public TableBorder Border { get; set; } = TableBorder.Square; |         public TableBorder Border { get; set; } = TableBorder.Square; | ||||||
| @@ -81,7 +80,7 @@ namespace Spectre.Console | |||||||
|         public Table() |         public Table() | ||||||
|         { |         { | ||||||
|             _columns = new List<TableColumn>(); |             _columns = new List<TableColumn>(); | ||||||
|             _rows = new List<TableRow>(); |             Rows = new TableRowCollection(this); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
| @@ -96,7 +95,7 @@ namespace Spectre.Console | |||||||
|                 throw new ArgumentNullException(nameof(column)); |                 throw new ArgumentNullException(nameof(column)); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (_rows.Count > 0) |             if (Rows.Count > 0) | ||||||
|             { |             { | ||||||
|                 throw new InvalidOperationException("Cannot add new columns to table with existing rows."); |                 throw new InvalidOperationException("Cannot add new columns to table with existing rows."); | ||||||
|             } |             } | ||||||
| @@ -105,36 +104,6 @@ namespace Spectre.Console | |||||||
|             return this; |             return this; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Adds a row to the table. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="columns">The row columns to add.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public Table AddRow(IEnumerable<IRenderable> columns) |  | ||||||
|         { |  | ||||||
|             if (columns is null) |  | ||||||
|             { |  | ||||||
|                 throw new ArgumentNullException(nameof(columns)); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             var rowColumnCount = columns.GetCount(); |  | ||||||
|             if (rowColumnCount > _columns.Count) |  | ||||||
|             { |  | ||||||
|                 throw new InvalidOperationException("The number of row columns are greater than the number of table columns."); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             _rows.Add(new TableRow(columns)); |  | ||||||
|  |  | ||||||
|             // Need to add missing columns? |  | ||||||
|             if (rowColumnCount < _columns.Count) |  | ||||||
|             { |  | ||||||
|                 var diff = _columns.Count - rowColumnCount; |  | ||||||
|                 Enumerable.Range(0, diff).ForEach(_ => _rows.Last().Add(Text.Empty)); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             return this; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         protected override Measurement Measure(RenderContext context, int maxWidth) |         protected override Measurement Measure(RenderContext context, int maxWidth) | ||||||
|         { |         { | ||||||
| @@ -190,7 +159,7 @@ namespace Spectre.Console | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             // Add rows |             // Add rows | ||||||
|             rows.AddRange(_rows); |             rows.AddRange(Rows); | ||||||
|  |  | ||||||
|             // Show footers? |             // Show footers? | ||||||
|             if (ShowFooters && _columns.Any(c => c.Footer != null)) |             if (ShowFooters && _columns.Any(c => c.Footer != null)) | ||||||
|   | |||||||
| @@ -12,6 +12,11 @@ namespace Spectre.Console | |||||||
|     { |     { | ||||||
|         private readonly List<IRenderable> _items; |         private readonly List<IRenderable> _items; | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets the number of columns in the row. | ||||||
|  |         /// </summary> | ||||||
|  |         public int Count => _items.Count; | ||||||
|  |  | ||||||
|         internal bool IsHeader { get; } |         internal bool IsHeader { get; } | ||||||
|         internal bool IsFooter { get; } |         internal bool IsFooter { get; } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										160
									
								
								src/Spectre.Console/Widgets/Table/TableRowCollection.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								src/Spectre.Console/Widgets/Table/TableRowCollection.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,160 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Represents a collection holding table rows. | ||||||
|  |     /// </summary> | ||||||
|  |     public sealed class TableRowCollection : IReadOnlyList<TableRow> | ||||||
|  |     { | ||||||
|  |         private readonly Table _table; | ||||||
|  |         private readonly IList<TableRow> _list; | ||||||
|  |         private readonly object _lock; | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         TableRow IReadOnlyList<TableRow>.this[int index] | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 lock (_lock) | ||||||
|  |                 { | ||||||
|  |                     return _list[index]; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets the number of rows in the collection. | ||||||
|  |         /// </summary> | ||||||
|  |         public int Count | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 lock (_lock) | ||||||
|  |                 { | ||||||
|  |                     return _list.Count; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         internal TableRowCollection(Table table) | ||||||
|  |         { | ||||||
|  |             _table = table ?? throw new ArgumentNullException(nameof(table)); | ||||||
|  |             _list = new List<TableRow>(); | ||||||
|  |             _lock = new object(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Adds a new row. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="columns">The columns that are part of the row to add.</param> | ||||||
|  |         /// <returns>The index of the added item.</returns> | ||||||
|  |         public int Add(IEnumerable<IRenderable> columns) | ||||||
|  |         { | ||||||
|  |             if (columns is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(columns)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             lock (_lock) | ||||||
|  |             { | ||||||
|  |                 var row = CreateRow(columns); | ||||||
|  |                 _list.Add(row); | ||||||
|  |                 return _list.IndexOf(row); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Inserts a new row at the specified index. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="index">The index to insert the row at.</param> | ||||||
|  |         /// <param name="columns">The columns that are part of the row to insert.</param> | ||||||
|  |         /// <returns>The index of the inserted item.</returns> | ||||||
|  |         public int Insert(int index, IEnumerable<IRenderable> columns) | ||||||
|  |         { | ||||||
|  |             if (columns is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(columns)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             lock (_lock) | ||||||
|  |             { | ||||||
|  |                 var row = CreateRow(columns); | ||||||
|  |                 _list.Insert(index, row); | ||||||
|  |                 return _list.IndexOf(row); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Removes a row at the specified index. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="index">The index to remove a row at.</param> | ||||||
|  |         public void RemoveAt(int index) | ||||||
|  |         { | ||||||
|  |             lock (_lock) | ||||||
|  |             { | ||||||
|  |                 if (index < 0) | ||||||
|  |                 { | ||||||
|  |                     throw new IndexOutOfRangeException("Table row index cannot be negative."); | ||||||
|  |                 } | ||||||
|  |                 else if (index >= _list.Count) | ||||||
|  |                 { | ||||||
|  |                     throw new IndexOutOfRangeException("Table row index cannot exceed the number of rows in the table."); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 _list.RemoveAt(index); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Clears all rows. | ||||||
|  |         /// </summary> | ||||||
|  |         public void Clear() | ||||||
|  |         { | ||||||
|  |             lock (_lock) | ||||||
|  |             { | ||||||
|  |                 _list.Clear(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         public IEnumerator<TableRow> GetEnumerator() | ||||||
|  |         { | ||||||
|  |             lock (_lock) | ||||||
|  |             { | ||||||
|  |                 var items = new TableRow[_list.Count]; | ||||||
|  |                 _list.CopyTo(items, 0); | ||||||
|  |                 return new TableRowEnumerator(items); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <inheritdoc/> | ||||||
|  |         IEnumerator IEnumerable.GetEnumerator() | ||||||
|  |         { | ||||||
|  |             return GetEnumerator(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private TableRow CreateRow(IEnumerable<IRenderable> columns) | ||||||
|  |         { | ||||||
|  |             var row = new TableRow(columns); | ||||||
|  |  | ||||||
|  |             if (row.Count > _table.Columns.Count) | ||||||
|  |             { | ||||||
|  |                 throw new InvalidOperationException("The number of row columns are greater than the number of table columns."); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Need to add missing columns | ||||||
|  |             if (row.Count < _table.Columns.Count) | ||||||
|  |             { | ||||||
|  |                 var diff = _table.Columns.Count - row.Count; | ||||||
|  |                 Enumerable.Range(0, diff).ForEach(_ => row.Add(Text.Empty)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return row; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								src/Spectre.Console/Widgets/Table/TableRowEnumerator.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/Spectre.Console/Widgets/Table/TableRowEnumerator.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     internal sealed class TableRowEnumerator : IEnumerator<TableRow> | ||||||
|  |     { | ||||||
|  |         private readonly TableRow[] _items; | ||||||
|  |         private int _index; | ||||||
|  |  | ||||||
|  |         public TableRow Current => _items[_index]; | ||||||
|  |         object? IEnumerator.Current => _items[_index]; | ||||||
|  |  | ||||||
|  |         public TableRowEnumerator(TableRow[] items) | ||||||
|  |         { | ||||||
|  |             _items = items ?? throw new ArgumentNullException(nameof(items)); | ||||||
|  |             _index = -1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public void Dispose() | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public bool MoveNext() | ||||||
|  |         { | ||||||
|  |             _index++; | ||||||
|  |             return _index < _items.Length; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public void Reset() | ||||||
|  |         { | ||||||
|  |             _index = -1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | ┌───────────┐ | ||||||
|  | │ Column #1 │ | ||||||
|  | ├───────────┤ | ||||||
|  | │ 1         │ | ||||||
|  | │ 2         │ | ||||||
|  | │ 3         │ | ||||||
|  | └───────────┘ | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | ┌───────────┬───────────┐ | ||||||
|  | │ Column #1 │ Column #2 │ | ||||||
|  | ├───────────┼───────────┤ | ||||||
|  | │ 1         │ 1-2       │ | ||||||
|  | │ 2         │ 2-2       │ | ||||||
|  | │ 3         │ 3-2       │ | ||||||
|  | └───────────┴───────────┘ | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | ┌───────────┬───────────┐ | ||||||
|  | │ Column #1 │ Column #2 │ | ||||||
|  | ├───────────┼───────────┤ | ||||||
|  | │ 1         │ 1-2       │ | ||||||
|  | │ 2         │ 2-2       │ | ||||||
|  | │ 3         │ 3-2       │ | ||||||
|  | └───────────┴───────────┘ | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | ┌───────────┬───────────┐ | ||||||
|  | │ Column #1 │ Column #2 │ | ||||||
|  | ├───────────┼───────────┤ | ||||||
|  | │ 1         │ 1-2       │ | ||||||
|  | │ 3         │ 3-2       │ | ||||||
|  | │ 2         │ 2-2       │ | ||||||
|  | └───────────┴───────────┘ | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | ┌───────────┬───────────┐ | ||||||
|  | │ Column #1 │ Column #2 │ | ||||||
|  | ├───────────┼───────────┤ | ||||||
|  | │ 1         │ 1-2       │ | ||||||
|  | │ 3         │ 3-2       │ | ||||||
|  | │ 2         │ 2-2       │ | ||||||
|  | └───────────┴───────────┘ | ||||||
| @@ -0,0 +1,6 @@ | |||||||
|  | ┌───────────┬───────────┐ | ||||||
|  | │ Column #1 │ Column #2 │ | ||||||
|  | ├───────────┼───────────┤ | ||||||
|  | │ 1         │ 1-2       │ | ||||||
|  | │ 3         │ 3-2       │ | ||||||
|  | └───────────┴───────────┘ | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | ┌───────────┐ | ||||||
|  | │ Column #1 │ | ||||||
|  | ├───────────┤ | ||||||
|  | │ 1         │ | ||||||
|  | │ 3         │ | ||||||
|  | │ 2         │ | ||||||
|  | └───────────┘ | ||||||
| @@ -0,0 +1,6 @@ | |||||||
|  | ┌───────────┐ | ||||||
|  | │ Column #1 │ | ||||||
|  | ├───────────┤ | ||||||
|  | │ 1         │ | ||||||
|  | │ 3         │ | ||||||
|  | └───────────┘ | ||||||
| @@ -37,6 +37,7 @@ | |||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|  |     <Folder Include="Expectations\Widgets\Table\Rows\Extensions\" /> | ||||||
|     <Folder Include="Expectations\Widgets\Tree\" /> |     <Folder Include="Expectations\Widgets\Tree\" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,3 @@ | |||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using Shouldly; | using Shouldly; | ||||||
| using Spectre.Console.Testing; | using Spectre.Console.Testing; | ||||||
| using Spectre.Console.Tests.Data; | using Spectre.Console.Tests.Data; | ||||||
|   | |||||||
| @@ -0,0 +1,131 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | using Spectre.Console.Testing; | ||||||
|  | using Spectre.Verify.Extensions; | ||||||
|  | using VerifyXunit; | ||||||
|  | using Xunit; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console.Tests.Unit | ||||||
|  | { | ||||||
|  |     [UsesVerify] | ||||||
|  |     [ExpectationPath("Widgets/Table/Rows/Extensions")] | ||||||
|  |     public sealed class TableRowCollectionExtensionsTests | ||||||
|  |     { | ||||||
|  |         [UsesVerify] | ||||||
|  |         public sealed class TheAddRowMethod | ||||||
|  |         { | ||||||
|  |             [Fact] | ||||||
|  |             [Expectation("Add", "Renderables")] | ||||||
|  |             public Task Should_Add_Renderables() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new TestConsole(); | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.AddColumn("Column #2"); | ||||||
|  |                 table.AddRow(new[] { new Text("1"), new Text("1-2") }); | ||||||
|  |                 table.AddRow(new[] { new Text("2"), new Text("2-2") }); | ||||||
|  |                 table.AddRow(new[] { new Text("3"), new Text("3-2") }); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 console.Write(table); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 return Verifier.Verify(console.Output); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             [Expectation("Add", "Strings")] | ||||||
|  |             public Task Should_Add_Strings() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new TestConsole(); | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.AddColumn("Column #2"); | ||||||
|  |                 table.AddRow("1", "1-2"); | ||||||
|  |                 table.AddRow("2", "2-2"); | ||||||
|  |                 table.AddRow("3", "3-2"); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 console.Write(table); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 return Verifier.Verify(console.Output); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [UsesVerify] | ||||||
|  |         public sealed class TheInsertRowMethod | ||||||
|  |         { | ||||||
|  |             [Fact] | ||||||
|  |             [Expectation("Insert", "Renderables")] | ||||||
|  |             public Task Should_Insert_Renderables() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new TestConsole(); | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.AddColumn("Column #2"); | ||||||
|  |                 table.AddRow(new[] { new Text("1"), new Text("1-2") }); | ||||||
|  |                 table.AddRow(new[] { new Text("2"), new Text("2-2") }); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 table.InsertRow(1, new[] { new Text("3"), new Text("3-2") }); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 console.Write(table); | ||||||
|  |                 return Verifier.Verify(console.Output); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             [Expectation("Insert", "Strings")] | ||||||
|  |             public Task Should_Insert_Strings() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new TestConsole(); | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.AddColumn("Column #2"); | ||||||
|  |                 table.AddRow("1", "1-2"); | ||||||
|  |                 table.AddRow("2", "2-2"); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 table.InsertRow(1, "3", "3-2"); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 console.Write(table); | ||||||
|  |                 return Verifier.Verify(console.Output); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [UsesVerify] | ||||||
|  |         public sealed class TheRemoveRowMethod | ||||||
|  |         { | ||||||
|  |             [Fact] | ||||||
|  |             [Expectation("Remove")] | ||||||
|  |             public Task Should_Remove_Row() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new TestConsole(); | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.AddColumn("Column #2"); | ||||||
|  |                 table.AddRow(new[] { new Text("1"), new Text("1-2") }); | ||||||
|  |                 table.AddRow(new[] { new Text("2"), new Text("2-2") }); | ||||||
|  |                 table.AddRow(new[] { new Text("3"), new Text("3-2") }); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 table.RemoveRow(1); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 console.Write(table); | ||||||
|  |                 return Verifier.Verify(console.Output); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,226 @@ | |||||||
|  | using System; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | using Shouldly; | ||||||
|  | using Spectre.Console.Testing; | ||||||
|  | using Spectre.Verify.Extensions; | ||||||
|  | using VerifyXunit; | ||||||
|  | using Xunit; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console.Tests.Unit | ||||||
|  | { | ||||||
|  |     [ExpectationPath("Widgets/Table/Rows")] | ||||||
|  |     public sealed class TableRowCollectionTests | ||||||
|  |     { | ||||||
|  |         [UsesVerify] | ||||||
|  |         public sealed class TheAddMethod | ||||||
|  |         { | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Throw_If_Columns_Are_Null() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var table = new Table(); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 var result = Record.Exception(() => table.Rows.Add(null)); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 result.ShouldBeOfType<ArgumentNullException>() | ||||||
|  |                     .ParamName.ShouldBe("columns"); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Add_Row_To_Collection() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 table.Rows.Add(new[] { Text.Empty }); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 table.Rows.Count.ShouldBe(1); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Return_Index_Of_Added_Row() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.Rows.Add(new[] { Text.Empty }); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 var result = table.Rows.Add(new[] { Text.Empty }); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 result.ShouldBe(1); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             [Expectation("Add")] | ||||||
|  |             public Task Should_Add_Item_At_Correct_Place() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new TestConsole(); | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.Rows.Add(new[] { new Text("1") }); | ||||||
|  |                 table.Rows.Add(new[] { new Text("2") }); | ||||||
|  |                 table.Rows.Add(new[] { new Text("3") }); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 console.Write(table); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 return Verifier.Verify(console.Output); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [UsesVerify] | ||||||
|  |         public sealed class TheInsertMethod | ||||||
|  |         { | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Throw_If_Columns_Are_Null() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var table = new Table(); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 var result = Record.Exception(() => table.Rows.Insert(0, null)); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 result.ShouldBeOfType<ArgumentNullException>() | ||||||
|  |                     .ParamName.ShouldBe("columns"); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Insert_Row() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.Rows.Add(new[] { Text.Empty }); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 table.Rows.Insert(0, new[] { Text.Empty }); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 table.Rows.Count.ShouldBe(2); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Return_Index_Of_Inserted_Row() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.Rows.Add(new[] { new Text("1") }); | ||||||
|  |                 table.Rows.Add(new[] { new Text("2") }); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 var result = table.Rows.Insert(1, new[] { new Text("3") }); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 result.ShouldBe(1); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             [Expectation("Insert")] | ||||||
|  |             public Task Should_Insert_Item_At_Correct_Place() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new TestConsole(); | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.Rows.Add(new[] { new Text("1") }); | ||||||
|  |                 table.Rows.Add(new[] { new Text("2") }); | ||||||
|  |                 table.Rows.Insert(1, new[] { new Text("3") }); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 console.Write(table); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 return Verifier.Verify(console.Output); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [UsesVerify] | ||||||
|  |         public sealed class TheRemoveMethod | ||||||
|  |         { | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Throw_If_Index_Is_Negative() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 var result = Record.Exception(() => table.Rows.RemoveAt(-1)); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 result.ShouldBeOfType<IndexOutOfRangeException>() | ||||||
|  |                     .Message.ShouldBe("Table row index cannot be negative."); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Throw_If_Index_Is_Larger_Than_Number_Of_Rows() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.Rows.Add(new[] { new Text("1") }); | ||||||
|  |                 table.Rows.Add(new[] { new Text("2") }); | ||||||
|  |                 table.Rows.Add(new[] { new Text("3") }); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 var result = Record.Exception(() => table.Rows.RemoveAt(3)); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 result.ShouldBeOfType<IndexOutOfRangeException>() | ||||||
|  |                     .Message.ShouldBe("Table row index cannot exceed the number of rows in the table."); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             [Expectation("Remove")] | ||||||
|  |             public Task Should_Remove_Row() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new TestConsole(); | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.Rows.Add(new[] { new Text("1") }); | ||||||
|  |                 table.Rows.Add(new[] { new Text("2") }); | ||||||
|  |                 table.Rows.Add(new[] { new Text("3") }); | ||||||
|  |                 table.Rows.RemoveAt(1); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 console.Write(table); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 return Verifier.Verify(console.Output); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public sealed class TheClearMethod | ||||||
|  |         { | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Remove_All_Rows() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var table = new Table(); | ||||||
|  |                 table.AddColumn("Column #1"); | ||||||
|  |                 table.Rows.Add(new[] { new Text("1") }); | ||||||
|  |                 table.Rows.Add(new[] { new Text("2") }); | ||||||
|  |                 table.Rows.Add(new[] { new Text("3") }); | ||||||
|  |                 table.Rows.Clear(); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 var result = table.Rows.Count; | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 result.ShouldBe(0); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -78,20 +78,6 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                     .ParamName.ShouldBe("columns"); |                     .ParamName.ShouldBe("columns"); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             [Fact] |  | ||||||
|             public void Should_Throw_If_Renderable_Rows_Are_Null() |  | ||||||
|             { |  | ||||||
|                 // Given |  | ||||||
|                 var table = new Table(); |  | ||||||
| 
 |  | ||||||
|                 // When |  | ||||||
|                 var result = Record.Exception(() => table.AddRow(null)); |  | ||||||
| 
 |  | ||||||
|                 // Then |  | ||||||
|                 result.ShouldBeOfType<ArgumentNullException>() |  | ||||||
|                     .ParamName.ShouldBe("columns"); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             [Fact] |             [Fact] | ||||||
|             public void Should_Add_Empty_Items_If_User_Provides_Less_Row_Items_Than_Columns() |             public void Should_Add_Empty_Items_If_User_Provides_Less_Row_Items_Than_Columns() | ||||||
|             { |             { | ||||||
| @@ -1,8 +1,4 @@ | |||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Linq; |  | ||||||
| using System.Text; |  | ||||||
| using System.Threading.Tasks; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Tests | namespace Spectre.Console.Tests | ||||||
| { | { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user