mirror of
				https://github.com/spectreconsole/spectre.console.git
				synced 2025-10-25 15:19:23 +00:00 
			
		
		
		
	Compare commits
	
		
			14 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 3c3afe7439 | ||
|  | 971f9032ba | ||
|  | 5149557560 | ||
|  | e0947708c9 | ||
|  | b1db8a9403 | ||
|  | a2f8652575 | ||
|  | 672faa131f | ||
|  | e429f6434b | ||
|  | 93ec7401c8 | ||
|  | 697273917e | ||
|  | 2943535973 | ||
|  | cd0d182f12 | ||
|  | b197f278ed | ||
|  | 3847a8949f | 
							
								
								
									
										7
									
								
								.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -65,11 +65,12 @@ jobs: | |||||||
|         run: | |         run: | | ||||||
|           dotnet tool restore |           dotnet tool restore | ||||||
|           dotnet example info |           dotnet example info | ||||||
|           dotnet example table |           dotnet example tables | ||||||
|           dotnet example grid |           dotnet example grids | ||||||
|           dotnet example panel |           dotnet example panels | ||||||
|           dotnet example colors |           dotnet example colors | ||||||
|           dotnet example emojis |           dotnet example emojis | ||||||
|  |           dotnet example exceptions | ||||||
|  |  | ||||||
|       - name: Build |       - name: Build | ||||||
|         shell: bash |         shell: bash | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -5,6 +5,7 @@ | |||||||
| [Pp]ackages/ | [Pp]ackages/ | ||||||
| /.artifacts/ | /.artifacts/ | ||||||
| /[Tt]ools/ | /[Tt]ools/ | ||||||
|  | .idea | ||||||
| .DS_Store | .DS_Store | ||||||
|  |  | ||||||
| # Cakeup | # Cakeup | ||||||
|   | |||||||
| @@ -1,8 +1,50 @@ | |||||||
| # Documentation | # Documentation | ||||||
|  |  | ||||||
| Preview the documentation locally by running the following | To start contributing to the [Spectre.Console](https://github.com/spectresystems/spectre.console) documentation, you will need the [.NET Core SDK](https://dot.net) 3.1 or higher. | ||||||
| from your favourite shell: |  | ||||||
|  | ## Running Preview Site | ||||||
|  |  | ||||||
|  | The documentation site uses [Statiq](https://statiq.dev), a static site generator. To build the documentation site run the following in a command-line terminal. | ||||||
|  |  | ||||||
| ``` | ``` | ||||||
| > dotnet run -- preview --virtual-dir "spectre.console" | > dotnet run preview --virtual-dir "spectre.console" | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | After the build is complete, you can navigate to [http://localhost:5080/spectre.consle](http://localhost:5080/spectre.console). | ||||||
|  |  | ||||||
|  | **Note that the site runs under a virtual directory.** | ||||||
|  |  | ||||||
|  | ## Editing Content | ||||||
|  |  | ||||||
|  | The documentation is written using [Markdown](https://www.markdownguide.org/basic-syntax/). | ||||||
|  |  | ||||||
|  | Markdown files can be found under the following directories: | ||||||
|  |  | ||||||
|  | - [/input](./input) | ||||||
|  |   - [/appendix](./input/appendix) | ||||||
|  |      | ||||||
|  | ## Editing Layout | ||||||
|  |  | ||||||
|  | Layout and styling can also be found in the [input](./input) directory. Look for Sass, Css, and Images under the [assets](./input/assets) directory. | ||||||
|  |      | ||||||
|  | ## Custom Build Features | ||||||
|  |  | ||||||
|  | The documentation site has custom enhancements to Statiq located under the [./src](./src) directory. Enhancements to the build process include: | ||||||
|  |  | ||||||
|  | - [Extension Methods](./src/Extensions) | ||||||
|  | - [Models](./src/Models) | ||||||
|  | - [Pipelines](./src/Pipelines) | ||||||
|  | - [Shortcodes](./src/Shortcodes) | ||||||
|  | - [Utilities](./src/Utilities) | ||||||
|  |  | ||||||
|  | ## License | ||||||
|  |  | ||||||
|  | MIT License | ||||||
|  |  | ||||||
|  | Copyright (c) 2020 Spectre Systems AB | ||||||
|  |  | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||||||
|  |  | ||||||
|  | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||||
| @@ -5,8 +5,8 @@ | |||||||
|         <meta http-equiv="X-UA-Compatible" content="IE=Edge"> |         <meta http-equiv="X-UA-Compatible" content="IE=Edge"> | ||||||
|         <meta name="viewport" content="width=device-width, initial-scale=1.0"> |         <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||||
|  |  | ||||||
|         <link href="/spectre.console/assets/bootstrap/bootstrap.css" rel="stylesheet" /> |         <link href="@Context.GetLink("/assets/bootstrap/bootstrap.css")" rel="stylesheet" /> | ||||||
|         <link href="/spectre.console/assets/css/styles.css" rel="stylesheet" /> |         <link href="@Context.GetLink("/assets/css/styles.css")" rel="stylesheet" /> | ||||||
|         <link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;700&family=Roboto+Slab:wght@400;700&family=Roboto:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap" rel="stylesheet" data-no-mirror> |         <link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;700&family=Roboto+Slab:wght@400;700&family=Roboto:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap" rel="stylesheet" data-no-mirror> | ||||||
|         <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.19.0/themes/prism.css"> |         <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.19.0/themes/prism.css"> | ||||||
|  |  | ||||||
| @@ -29,7 +29,7 @@ | |||||||
|  |  | ||||||
|             <nav id="topnav" class="navbar navbar-expand-lg navbar-light"> |             <nav id="topnav" class="navbar navbar-expand-lg navbar-light"> | ||||||
|                 <div class="container py-3"> |                 <div class="container py-3"> | ||||||
|                     <a class="navbar-brand" href="/spectre.console"><img id="logo" src="/spectre.console/assets/logo.svg" alt="Spectre.Console"> Spectre.Console</a> |                     <a class="navbar-brand" href="@Context.GetLink("/")"><img id="logo" src="@Context.GetLink("/assets/logo.svg")" alt="Spectre.Console"> Spectre.Console</a> | ||||||
|                     <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation"> |                     <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation"> | ||||||
|                         <span class="navbar-toggler-icon"></span> |                         <span class="navbar-toggler-icon"></span> | ||||||
|                     </button> |                     </button> | ||||||
| @@ -135,7 +135,7 @@ | |||||||
|                                                     else |                                                     else | ||||||
|                                                     { |                                                     { | ||||||
|                                                         @root.GetTitle() |                                                         @root.GetTitle() | ||||||
|                                                     }  |                                                     } | ||||||
|                                             </div> |                                             </div> | ||||||
|  |  | ||||||
|                                             @foreach (IDocument document in OutputPages.GetChildrenOf(root).OnlyVisible()) |                                             @foreach (IDocument document in OutputPages.GetChildrenOf(root).OnlyVisible()) | ||||||
| @@ -149,7 +149,7 @@ | |||||||
|                                                     else |                                                     else | ||||||
|                                                     { |                                                     { | ||||||
|                                                         @document.GetTitle() |                                                         @document.GetTitle() | ||||||
|                                                     }                                                    |                                                     } | ||||||
|                                                 </div> |                                                 </div> | ||||||
|  |  | ||||||
|                                                 @if (documentChildren.OnlyVisible().Any()) |                                                 @if (documentChildren.OnlyVisible().Any()) | ||||||
|   | |||||||
| @@ -4,16 +4,30 @@ Order: 2 | |||||||
|  |  | ||||||
| There is different built-in borders you can use for tables and panels. | There is different built-in borders you can use for tables and panels. | ||||||
|  |  | ||||||
| # Built-in borders | # Table borders | ||||||
|  |  | ||||||
| <img src="../assets/images/borders.png" style="max-width: 100%;"> | <img src="../assets/images/borders/table.png" style="max-width: 100%;"> | ||||||
|  |  | ||||||
| # Usage | ## Example | ||||||
|  |  | ||||||
| To create a table and set it's border to `SimpleHeavy` as seen in the  | To set a table border to `SimpleHeavy`: | ||||||
| image above: |  | ||||||
|  |  | ||||||
| ```csharp | ```csharp | ||||||
| var table = new Table(); | var table = new Table(); | ||||||
| table.Border = Border.SimpleHeavy; | table.Border = TableBorder.SimpleHeavy; | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | # Panel borders | ||||||
|  |  | ||||||
|  | <img src="../assets/images/borders/panel.png" style="max-width: 100%;"> | ||||||
|  |  | ||||||
|  | ## Example | ||||||
|  |  | ||||||
|  | To set a panel border to `Rounded`: | ||||||
|  |  | ||||||
|  | ```csharp | ||||||
|  | var panel = new Panel("Hello World"); | ||||||
|  | panel.Border = BoxBorder.Rounded; | ||||||
| ``` | ``` | ||||||
| @@ -13,4 +13,19 @@ in markup text such as `AnsiConsole.Markup("[maroon on blue]Hello[/]")`. | |||||||
|  |  | ||||||
| # Standard colors | # Standard colors | ||||||
|  |  | ||||||
| <?# ColorTable /?> | <div class="input-group mb-3"> | ||||||
|  |   <div class="input-group-prepend"> | ||||||
|  |     <span class="input-group-text" id="basic-addon1"> | ||||||
|  |         <i class="fas fa-search" aria-hidden="true"></i> | ||||||
|  |     </span> | ||||||
|  |   </div> | ||||||
|  |   <input | ||||||
|  |     class="form-control w-100 filter" | ||||||
|  |     data-table="color-results" | ||||||
|  |     type="text" placeholder="Search Colors..." autocomplete="off"  | ||||||
|  |     aria-label="Search Colors"> | ||||||
|  | </div> | ||||||
|  |  | ||||||
|  | <?# ColorTable /?> | ||||||
|  |  | ||||||
|  | <script type="text/javascript" src="../assets/js/table-search.js"></script> | ||||||
| @@ -35,4 +35,19 @@ var rendered = Emoji.Replace(phrase); | |||||||
| _The images in the table below might not render correctly in your  | _The images in the table below might not render correctly in your  | ||||||
| browser for the same reasons mentioned in the `Compatibility` section._ | browser for the same reasons mentioned in the `Compatibility` section._ | ||||||
|  |  | ||||||
| <?# EmojiTable /?> | <div class="input-group mb-3"> | ||||||
|  |   <div class="input-group-prepend"> | ||||||
|  |     <span class="input-group-text" id="basic-addon1"> | ||||||
|  |         <i class="fas fa-search" aria-hidden="true"></i> | ||||||
|  |     </span> | ||||||
|  |   </div> | ||||||
|  |   <input | ||||||
|  |     class="form-control w-100 filter" | ||||||
|  |     data-table="emoji-results" | ||||||
|  |     type="text" placeholder="Search Emojis..." autocomplete="off"  | ||||||
|  |     aria-label="Search Emojis"> | ||||||
|  | </div> | ||||||
|  |  | ||||||
|  | <?# EmojiTable /?> | ||||||
|  |  | ||||||
|  | <script type="text/javascript" src="../assets/js/table-search.js"></script> | ||||||
							
								
								
									
										12
									
								
								docs/input/appendix/index.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								docs/input/appendix/index.cshtml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | Title: Appendix | ||||||
|  | Order: 10 | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | <h1>Sections</h1> | ||||||
|  |  | ||||||
|  | <ul> | ||||||
|  | @foreach (IDocument child in OutputPages.GetChildrenOf(Document)) | ||||||
|  | { | ||||||
|  |   <li>@Html.DocumentLink(child)</li> | ||||||
|  | } | ||||||
|  | </ul> | ||||||
| @@ -1,10 +0,0 @@ | |||||||
| Title: Appendix |  | ||||||
| Order: 10 |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| # Sections |  | ||||||
|  |  | ||||||
| * [Styles](xref:styles) |  | ||||||
| * [Colors](xref:colors) |  | ||||||
| * [Borders](xref:borders) |  | ||||||
| * [Emojis](xref:emojis) |  | ||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 415 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/input/assets/images/borders/panel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/input/assets/images/borders/panel.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 112 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/input/assets/images/borders/table.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/input/assets/images/borders/table.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 503 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/input/assets/images/compact_exception.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/input/assets/images/compact_exception.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 163 KiB | 
							
								
								
									
										
											BIN
										
									
								
								docs/input/assets/images/exception.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/input/assets/images/exception.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 421 KiB | 
							
								
								
									
										35
									
								
								docs/input/assets/js/table-search.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								docs/input/assets/js/table-search.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | $(document).ready(function () { | ||||||
|  |  | ||||||
|  |     $('.filter').each(function () { | ||||||
|  |         let input = this; | ||||||
|  |         let table = document.getElementById(input.dataset.table); | ||||||
|  |  | ||||||
|  |         input.onkeyup = function (event) { | ||||||
|  |  | ||||||
|  |             if (event.key === "Enter") { | ||||||
|  |                 event.preventDefault(); | ||||||
|  |                 event.stopPropagation(); | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             let value = input.value.toUpperCase(); | ||||||
|  |             let rows = table.getElementsByClassName('search-row'); | ||||||
|  |  | ||||||
|  |             for (let i = 0; i < rows.length; i++) { | ||||||
|  |                 let row = rows[i]; | ||||||
|  |  | ||||||
|  |                 let match = | ||||||
|  |                     new RegExp(value, "i").test(row.textContent) || | ||||||
|  |                     value === ''; | ||||||
|  |  | ||||||
|  |                 if (match) { | ||||||
|  |                     row.style.display = 'table-row'; | ||||||
|  |                 } else { | ||||||
|  |                     row.style.display = 'none'; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }; // keyup | ||||||
|  |     }) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | }); // ready | ||||||
							
								
								
									
										26
									
								
								docs/input/exceptions.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								docs/input/exceptions.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | Title: Exceptions | ||||||
|  | Order: 3 | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | Exceptions isn't always readable when viewed in the terminal.   | ||||||
|  | You can make exception a bit more readable by using the `WriteException` method. | ||||||
|  |  | ||||||
|  | ```csharp | ||||||
|  | AnsiConsole.WriteException(ex); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | <img src="assets/images/exception.png" style="max-width: 100%; margin-bottom: 20px"> | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | You can also shorten specific parts of the exception to make it even | ||||||
|  | more readable, and make paths clickable hyperlinks. Whether or not | ||||||
|  | the hyperlinks are clickable is up to the terminal.  | ||||||
|  |  | ||||||
|  | ```csharp | ||||||
|  | AnsiConsole.WriteException(ex,  | ||||||
|  |     ExceptionFormat.ShortenPaths | ExceptionFormat.ShortenTypes | | ||||||
|  |     ExceptionFormat.ShortenMethods | ExceptionFormat.ShowLinks); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | <img src="assets/images/compact_exception.png" style="max-width: 100%;"> | ||||||
| @@ -65,6 +65,15 @@ For a list of emoji, see the [Emojis](xref:styles) appendix section. | |||||||
|  |  | ||||||
| # Colors | # Colors | ||||||
|  |  | ||||||
|  | In the examples above, all colors was referenced by their name, | ||||||
|  | but you can also use the hex or rgb representation for colors in markdown. | ||||||
|  |  | ||||||
|  | ```csharp | ||||||
|  | AnsiConsole.Markup("[red]Foo[/] "); | ||||||
|  | AnsiConsole.Markup("[#ff0000]Bar[/] "); | ||||||
|  | AnsiConsole.Markup("[rgb(255,0,0)]Baz[/] "); | ||||||
|  | ``` | ||||||
|  |  | ||||||
| For a list of colors, see the [Colors](xref:colors) appendix section. | For a list of colors, see the [Colors](xref:colors) appendix section. | ||||||
|  |  | ||||||
| # Styles | # Styles | ||||||
|   | |||||||
| @@ -20,10 +20,7 @@ namespace Docs | |||||||
|  |  | ||||||
|         public static Bootstrapper ConfigureDeployment(this Bootstrapper bootstrapper, string deployBranch) |         public static Bootstrapper ConfigureDeployment(this Bootstrapper bootstrapper, string deployBranch) | ||||||
|         { |         { | ||||||
|             if (bootstrapper != null) |             bootstrapper?.AddSetting(Constants.Deployment.TargetBranch, deployBranch); | ||||||
|             { |  | ||||||
|                 bootstrapper.AddSetting(Constants.Deployment.TargetBranch, deployBranch); |  | ||||||
|             } |  | ||||||
|             return bootstrapper; |             return bootstrapper; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -9,15 +9,13 @@ namespace Docs.Pipelines | |||||||
| { | { | ||||||
|     public class ColorsPipeline : Pipeline |     public class ColorsPipeline : Pipeline | ||||||
|     { |     { | ||||||
|         public const string Url = "https://raw.githubusercontent.com/spectresystems/spectre.console/main/resources/scripts/Generator/Data/colors.json"; |  | ||||||
|  |  | ||||||
|         public ColorsPipeline() |         public ColorsPipeline() | ||||||
|         { |         { | ||||||
|             InputModules = new ModuleList |             InputModules = new ModuleList | ||||||
|             { |             { | ||||||
|                 new ExecuteConfig( |                 new ExecuteConfig( | ||||||
|                     Config.FromContext(ctx => { |                     Config.FromContext(ctx => { | ||||||
|                         return new ReadWeb(Url); |                         return new ReadWeb(Constants.Colors.Url); | ||||||
|                     })) |                     })) | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
| @@ -32,4 +30,4 @@ namespace Docs.Pipelines | |||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ namespace Docs.Shortcodes | |||||||
|                 .First().Object; |                 .First().Object; | ||||||
|  |  | ||||||
|             // Headers |             // Headers | ||||||
|             var table = new XElement("table", new XAttribute("class", "table")); |             var table = new XElement("table", new XAttribute("class", "table"), new XAttribute("id", "color-results")); | ||||||
|             var header = new XElement("tr", new XAttribute("class", "color-row")); |             var header = new XElement("tr", new XAttribute("class", "color-row")); | ||||||
|             header.Add(new XElement("th", "")); |             header.Add(new XElement("th", "")); | ||||||
|             header.Add(new XElement("th", "#")); |             header.Add(new XElement("th", "#")); | ||||||
| @@ -33,8 +33,8 @@ namespace Docs.Shortcodes | |||||||
|  |  | ||||||
|             foreach (var color in colors) |             foreach (var color in colors) | ||||||
|             { |             { | ||||||
|                 var rep = new XElement("td",  |                 var rep = new XElement("td", | ||||||
|                     new XElement("span",  |                     new XElement("span", | ||||||
|                     new XAttribute("class", "color-representation"), |                     new XAttribute("class", "color-representation"), | ||||||
|                     new XAttribute("style", $"background-color:{color.Hex};"))); |                     new XAttribute("style", $"background-color:{color.Hex};"))); | ||||||
|                 var name = new XElement("td", new XElement("code", color.Number.ToString())); |                 var name = new XElement("td", new XElement("code", color.Number.ToString())); | ||||||
| @@ -44,7 +44,7 @@ namespace Docs.Shortcodes | |||||||
|                 var clr = new XElement("td", new XElement("code", color.ClrName)); |                 var clr = new XElement("td", new XElement("code", color.ClrName)); | ||||||
|  |  | ||||||
|                 // Create row |                 // Create row | ||||||
|                 var row = new XElement("tr"); |                 var row = new XElement("tr", new XAttribute("class", "search-row")); | ||||||
|                 row.Add(rep); |                 row.Add(rep); | ||||||
|                 row.Add(name); |                 row.Add(name); | ||||||
|                 row.Add(number); |                 row.Add(number); | ||||||
|   | |||||||
| @@ -18,8 +18,8 @@ namespace Docs.Shortcodes | |||||||
|                 .First().Object; |                 .First().Object; | ||||||
|  |  | ||||||
|             // Headers |             // Headers | ||||||
|             var table = new XElement("table", new XAttribute("class", "table")); |             var table = new XElement("table", new XAttribute("class", "table"), new XAttribute("id", "emoji-results")); | ||||||
|             var header = new XElement("tr", new XAttribute("class", "emoji-row")); |             var header = new XElement("tr", new XAttribute("class", "emoji-row-header")); | ||||||
|             header.Add(new XElement("th", "")); |             header.Add(new XElement("th", "")); | ||||||
|             header.Add(new XElement("th", "Markup")); |             header.Add(new XElement("th", "Markup")); | ||||||
|             header.Add(new XElement("th", "Constant")); |             header.Add(new XElement("th", "Constant")); | ||||||
| @@ -28,9 +28,9 @@ namespace Docs.Shortcodes | |||||||
|             foreach (var emoji in emojis) |             foreach (var emoji in emojis) | ||||||
|             { |             { | ||||||
|                 var code = emoji.Code.Replace("U+0000", "U+").Replace("U+000", "U+"); |                 var code = emoji.Code.Replace("U+0000", "U+").Replace("U+000", "U+"); | ||||||
|                 var icon = string.Format("&#x{0};", emoji.Code.Replace("U+", string.Empty)); |                 var icon = $"&#x{emoji.Code.Replace("U+", string.Empty)};"; | ||||||
|  |  | ||||||
|                 var row = new XElement("tr"); |                 var row = new XElement("tr", new XAttribute("class", "search-row")); | ||||||
|                 row.Add(new XElement("td", icon)); |                 row.Add(new XElement("td", icon)); | ||||||
|                 row.Add(new XElement("td", new XElement("code", $":{emoji.Id}:"))); |                 row.Add(new XElement("td", new XElement("code", $":{emoji.Id}:"))); | ||||||
|                 row.Add(new XElement("td", new XElement("code", emoji.Name))); |                 row.Add(new XElement("td", new XElement("code", emoji.Name))); | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|     <OutputType>Exe</OutputType> |     <OutputType>Exe</OutputType> | ||||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> |     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||||
|     <IsPackable>false</IsPackable> |     <IsPackable>false</IsPackable> | ||||||
|  |     <Title>Borders</Title> | ||||||
|     <Description>Demonstrates the different kind of borders.</Description> |     <Description>Demonstrates the different kind of borders.</Description> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,47 +1,89 @@ | |||||||
| using Spectre.Console; | using Spectre.Console; | ||||||
| using Spectre.Console.Rendering; | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
| namespace Borders | namespace BordersExample | ||||||
| { | { | ||||||
|     public static class Program |     public static class Program | ||||||
|     { |     { | ||||||
|         public static void Main() |         public static void Main() | ||||||
|         { |         { | ||||||
|             var items = new[] |             // Render panel borders | ||||||
|             { |  | ||||||
|                 Create("Ascii", Border.Ascii), |  | ||||||
|                 Create("Ascii2", Border.Ascii2), |  | ||||||
|                 Create("AsciiDoubleHead", Border.AsciiDoubleHead), |  | ||||||
|                 Create("Horizontal", Border.Horizontal), |  | ||||||
|                 Create("Simple", Border.Simple), |  | ||||||
|                 Create("SimpleHeavy", Border.SimpleHeavy), |  | ||||||
|                 Create("Minimal", Border.Minimal), |  | ||||||
|                 Create("MinimalHeavyHead", Border.MinimalHeavyHead), |  | ||||||
|                 Create("MinimalDoubleHead", Border.MinimalDoubleHead), |  | ||||||
|                 Create("Square", Border.Square), |  | ||||||
|                 Create("Rounded", Border.Rounded), |  | ||||||
|                 Create("Heavy", Border.Heavy), |  | ||||||
|                 Create("HeavyEdge", Border.HeavyEdge), |  | ||||||
|                 Create("HeavyHead", Border.HeavyHead), |  | ||||||
|                 Create("Double", Border.Double), |  | ||||||
|                 Create("DoubleEdge", Border.DoubleEdge), |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             AnsiConsole.WriteLine(); |             AnsiConsole.WriteLine(); | ||||||
|             AnsiConsole.Render(new Columns(items).Collapse()); |             AnsiConsole.MarkupLine("[white bold underline]PANEL BORDERS[/]"); | ||||||
|  |             AnsiConsole.WriteLine(); | ||||||
|  |             RenderPanelBorders(); | ||||||
|  |  | ||||||
|  |             // Render table borders | ||||||
|  |             AnsiConsole.WriteLine(); | ||||||
|  |             AnsiConsole.MarkupLine("[white bold underline]TABLE BORDERS[/]"); | ||||||
|  |             AnsiConsole.WriteLine(); | ||||||
|  |             RenderTableBorders(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private static IRenderable Create(string name, Border border) |         private static void RenderPanelBorders() | ||||||
|         { |         { | ||||||
|             var table = new Table().SetBorder(border); |             static IRenderable CreatePanel(string name, BoxBorder border) | ||||||
|             table.AddColumns("[yellow]Header 1[/]", "[yellow]Header 2[/]"); |             { | ||||||
|             table.AddRow("Cell", "Cell"); |                 return new Panel($"This is a panel with\nthe [yellow]{name}[/] border.") | ||||||
|             table.AddRow("Cell", "Cell"); |                     .SetHeader($" {name} ", Style.Parse("blue"), Justify.Center) | ||||||
|  |                     .SetBorderStyle(Style.Parse("grey")) | ||||||
|  |                     .SetBorder(border); | ||||||
|  |             } | ||||||
|  |  | ||||||
|             return new Panel(table) |             var items = new[] | ||||||
|                 .SetHeader($" {name} ", Style.Parse("blue"), Justify.Center) |             { | ||||||
|                 .SetBorderStyle(Style.Parse("grey")) |                 CreatePanel("Ascii", BoxBorder.Ascii), | ||||||
|                 .NoBorder(); |                 CreatePanel("Square", BoxBorder.Square), | ||||||
|  |                 CreatePanel("Rounded", BoxBorder.Rounded), | ||||||
|  |                 CreatePanel("Heavy", BoxBorder.Heavy), | ||||||
|  |                 CreatePanel("Double", BoxBorder.Double), | ||||||
|  |                 CreatePanel("None", BoxBorder.None), | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             AnsiConsole.Render( | ||||||
|  |                 new Padder( | ||||||
|  |                     new Columns(items).PadRight(2), | ||||||
|  |                     new Padding(2,0,0,0))); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static void RenderTableBorders() | ||||||
|  |         { | ||||||
|  |             static IRenderable CreateTable(string name, TableBorder border) | ||||||
|  |             { | ||||||
|  |                 var table = new Table().SetBorder(border); | ||||||
|  |                 table.AddColumn("[yellow]Header 1[/]"); | ||||||
|  |                 table.AddColumn("[yellow]Header 2[/]", col => col.RightAligned()); | ||||||
|  |                 table.AddRow("Cell", "Cell"); | ||||||
|  |                 table.AddRow("Cell", "Cell"); | ||||||
|  |  | ||||||
|  |                 return new Panel(table) | ||||||
|  |                     .SetHeader($" {name} ", Style.Parse("blue"), Justify.Center) | ||||||
|  |                     .SetBorderStyle(Style.Parse("grey")) | ||||||
|  |                     .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), | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             AnsiConsole.Render(new Columns(items).Collapse()); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|     <OutputType>Exe</OutputType> |     <OutputType>Exe</OutputType> | ||||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> |     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||||
|     <IsPackable>false</IsPackable> |     <IsPackable>false</IsPackable> | ||||||
|  |     <Title>Colors</Title> | ||||||
|     <Description>Demonstrates how to use [yellow]c[/][red]o[/][green]l[/][blue]o[/][aqua]r[/][lime]s[/] in the console.</Description> |     <Description>Demonstrates how to use [yellow]c[/][red]o[/][green]l[/][blue]o[/][aqua]r[/][lime]s[/] in the console.</Description> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|     <OutputType>Exe</OutputType> |     <OutputType>Exe</OutputType> | ||||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> |     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||||
|     <IsPackable>false</IsPackable> |     <IsPackable>false</IsPackable> | ||||||
|  |     <Title>Columns</Title> | ||||||
|     <Description>Demonstrates how to render data into columns.</Description> |     <Description>Demonstrates how to render data into columns.</Description> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|     <OutputType>Exe</OutputType> |     <OutputType>Exe</OutputType> | ||||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> |     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||||
|     <IsPackable>false</IsPackable> |     <IsPackable>false</IsPackable> | ||||||
|  |     <Title>Emojis</Title> | ||||||
|     <Description>Demonstrates how to render emojis.</Description> |     <Description>Demonstrates how to render emojis.</Description> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,6 @@ | |||||||
| using System; |  | ||||||
| using Spectre.Console; | using Spectre.Console; | ||||||
|  |  | ||||||
| namespace Emojis | namespace EmojiExample | ||||||
| { | { | ||||||
|     public static class Program |     public static class Program | ||||||
|     { |     { | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								examples/Exceptions/Exceptions.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								examples/Exceptions/Exceptions.csproj
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | <Project Sdk="Microsoft.NET.Sdk"> | ||||||
|  |  | ||||||
|  |   <PropertyGroup> | ||||||
|  |     <OutputType>Exe</OutputType> | ||||||
|  |     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||||
|  |     <IsPackable>false</IsPackable> | ||||||
|  |     <Title>Exceptions</Title> | ||||||
|  |     <Description>Demonstrates how to render formatted exceptions.</Description> | ||||||
|  |   </PropertyGroup> | ||||||
|  |  | ||||||
|  |   <ItemGroup> | ||||||
|  |     <ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" /> | ||||||
|  |   </ItemGroup> | ||||||
|  |  | ||||||
|  | </Project> | ||||||
							
								
								
									
										42
									
								
								examples/Exceptions/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								examples/Exceptions/Program.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | using System; | ||||||
|  | using System.Security.Authentication; | ||||||
|  | using Spectre.Console; | ||||||
|  |  | ||||||
|  | namespace Exceptions | ||||||
|  | { | ||||||
|  |     public static class Program | ||||||
|  |     { | ||||||
|  |         public static void Main(string[] args) | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 DoMagic(42, null); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 AnsiConsole.WriteLine(); | ||||||
|  |                 AnsiConsole.WriteException(ex); | ||||||
|  |  | ||||||
|  |                 AnsiConsole.WriteLine(); | ||||||
|  |                 AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static void DoMagic(int foo, string[,] bar) | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 CheckCredentials(foo, bar); | ||||||
|  |             } | ||||||
|  |             catch(Exception ex) | ||||||
|  |             { | ||||||
|  |                 throw new InvalidOperationException("Whaaat?", ex); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static void CheckCredentials(int qux, string[,] corgi) | ||||||
|  |         { | ||||||
|  |             throw new InvalidCredentialException("The credentials are invalid."); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -4,6 +4,7 @@ | |||||||
|     <OutputType>Exe</OutputType> |     <OutputType>Exe</OutputType> | ||||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> |     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||||
|     <IsPackable>false</IsPackable> |     <IsPackable>false</IsPackable> | ||||||
|  |     <Title>Grids</Title> | ||||||
|     <Description>Demonstrates how to render grids in a console.</Description> |     <Description>Demonstrates how to render grids in a console.</Description> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
| 
 | 
 | ||||||
| @@ -1,25 +1,25 @@ | |||||||
| using Spectre.Console; | using Spectre.Console; | ||||||
| 
 | 
 | ||||||
| namespace GridExample | namespace GridExample | ||||||
| { | { | ||||||
|     public static class Program |     public static class Program | ||||||
|     { |     { | ||||||
|         public static void Main() |         public static void Main() | ||||||
|         { |         { | ||||||
|             AnsiConsole.WriteLine(); |             AnsiConsole.WriteLine(); | ||||||
|             AnsiConsole.MarkupLine("Usage: [grey]dotnet [blue]run[/] [[options]] [[[[--]] <additional arguments>...]]]][/]"); |             AnsiConsole.MarkupLine("Usage: [grey]dotnet [blue]run[/] [[options]] [[[[--]] <additional arguments>...]]]][/]"); | ||||||
|             AnsiConsole.WriteLine(); |             AnsiConsole.WriteLine(); | ||||||
| 
 | 
 | ||||||
|             var grid = new Grid(); |             var grid = new Grid(); | ||||||
|             grid.AddColumn(new GridColumn { NoWrap = true }); |             grid.AddColumn(new GridColumn { NoWrap = true }); | ||||||
|             grid.AddColumn(new GridColumn { NoWrap = true, Width = 2 }); |             grid.AddColumn(new GridColumn { NoWrap = true, Width = 2 }); | ||||||
|             grid.AddColumn(); |             grid.AddColumn(); | ||||||
|             grid.AddRow("Options:", "", ""); |             grid.AddRow("Options:", "", ""); | ||||||
|             grid.AddRow("  [blue]-h[/], [blue]--help[/]", "", "Show command line help."); |             grid.AddRow("  [blue]-h[/], [blue]--help[/]", "", "Show command line help."); | ||||||
|             grid.AddRow("  [blue]-c[/], [blue]--configuration[/] <CONFIGURATION>", "", "The configuration to run for."); |             grid.AddRow("  [blue]-c[/], [blue]--configuration[/] <CONFIGURATION>", "", "The configuration to run for."); | ||||||
|             grid.AddRow("  [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "", "Set the [grey]MSBuild[/] verbosity level."); |             grid.AddRow("  [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "", "Set the [grey]MSBuild[/] verbosity level."); | ||||||
| 
 | 
 | ||||||
|             AnsiConsole.Render(grid); |             AnsiConsole.Render(grid); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -4,6 +4,7 @@ | |||||||
|     <OutputType>Exe</OutputType> |     <OutputType>Exe</OutputType> | ||||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> |     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||||
|     <IsPackable>false</IsPackable> |     <IsPackable>false</IsPackable> | ||||||
|  |     <Title>Info</Title> | ||||||
|     <Description>Displays the capabilities of the current console.</Description> |     <Description>Displays the capabilities of the current console.</Description> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| using Spectre.Console; | using Spectre.Console; | ||||||
|  |  | ||||||
| namespace Info | namespace InfoExample | ||||||
| { | { | ||||||
|     public static class Program |     public static class Program | ||||||
|     { |     { | ||||||
| @@ -9,19 +9,20 @@ namespace Info | |||||||
|             var grid = new Grid() |             var grid = new Grid() | ||||||
|                 .AddColumn(new GridColumn().NoWrap().PadRight(4)) |                 .AddColumn(new GridColumn().NoWrap().PadRight(4)) | ||||||
|                 .AddColumn() |                 .AddColumn() | ||||||
|                 .AddRow("[b]:artist_palette: Color system[/]", $"{AnsiConsole.Capabilities.ColorSystem}") |                 .AddRow("[b]Color system[/]", $"{AnsiConsole.Capabilities.ColorSystem}") | ||||||
|                 .AddRow("[b]:nail_polish: Supports ansi?[/]", $"{GetEmoji(AnsiConsole.Capabilities.SupportsAnsi)}") |                 .AddRow("[b]Supports ansi?[/]", $"{YesNo(AnsiConsole.Capabilities.SupportsAnsi)}") | ||||||
|                 .AddRow("[b]:top_hat: Legacy console?[/]", $"{GetEmoji(AnsiConsole.Capabilities.LegacyConsole)}") |                 .AddRow("[b]Legacy console?[/]", $"{YesNo(AnsiConsole.Capabilities.LegacyConsole)}") | ||||||
|                 .AddRow("[b]:left_right_arrow: Buffer width[/]", $"{AnsiConsole.Console.Width}") |                 .AddRow("[b]Buffer width[/]", $"{AnsiConsole.Console.Width}") | ||||||
|                 .AddRow("[b]:up_down_arrow: Buffer height[/]", $"{AnsiConsole.Console.Height}"); |                 .AddRow("[b]Buffer height[/]", $"{AnsiConsole.Console.Height}"); | ||||||
|  |  | ||||||
|             AnsiConsole.Render( |             AnsiConsole.Render( | ||||||
|                 new Panel(grid) |                 new Panel(grid) | ||||||
|                     .SetHeader("Information")); |                     .SetHeader("Information")); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private static string GetEmoji(bool value) => value |         private static string YesNo(bool value) | ||||||
|             ? ":thumbs_up:" |         { | ||||||
|             : ":thumbs_down:"; |             return value ? "Yes" : "No"; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|     <OutputType>Exe</OutputType> |     <OutputType>Exe</OutputType> | ||||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> |     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||||
|     <IsPackable>false</IsPackable> |     <IsPackable>false</IsPackable> | ||||||
|  |     <Title>Links</Title> | ||||||
|     <Description>Demonstrates how to render links in a console.</Description> |     <Description>Demonstrates how to render links in a console.</Description> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| using Spectre.Console; | using Spectre.Console; | ||||||
|  |  | ||||||
| namespace Links | namespace LinkExample | ||||||
| { | { | ||||||
|     public static class Program |     public static class Program | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|     <OutputType>Exe</OutputType> |     <OutputType>Exe</OutputType> | ||||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> |     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||||
|     <IsPackable>false</IsPackable> |     <IsPackable>false</IsPackable> | ||||||
|  |     <Title>Panels</Title> | ||||||
|     <Description>Demonstrates how to render items in panels.</Description> |     <Description>Demonstrates how to render items in panels.</Description> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
| 
 | 
 | ||||||
| @@ -13,7 +13,7 @@ namespace PanelExample | |||||||
|             AnsiConsole.Render( |             AnsiConsole.Render( | ||||||
|                 new Panel( |                 new Panel( | ||||||
|                     new Panel(content) |                     new Panel(content) | ||||||
|                         .SetBorder(Border.Rounded))); |                         .SetBorder(BoxBorder.Rounded))); | ||||||
| 
 | 
 | ||||||
|             // Left adjusted panel with text |             // Left adjusted panel with text | ||||||
|             AnsiConsole.Render( |             AnsiConsole.Render( | ||||||
| @@ -35,7 +35,7 @@ namespace TableExample | |||||||
|         private static void RenderBigTable() |         private static void RenderBigTable() | ||||||
|         { |         { | ||||||
|             // Create the table. |             // Create the table. | ||||||
|             var table = new Table().SetBorder(Border.Rounded); |             var table = new Table().SetBorder(TableBorder.Rounded); | ||||||
|             table.AddColumn("[red underline]Foo[/]"); |             table.AddColumn("[red underline]Foo[/]"); | ||||||
|             table.AddColumn(new TableColumn("[blue]Bar[/]") { Alignment = Justify.Right, NoWrap = true }); |             table.AddColumn(new TableColumn("[blue]Bar[/]") { Alignment = Justify.Right, NoWrap = true }); | ||||||
| 
 | 
 | ||||||
| @@ -57,7 +57,7 @@ namespace TableExample | |||||||
|         private static void RenderNestedTable() |         private static void RenderNestedTable() | ||||||
|         { |         { | ||||||
|             // Create simple table. |             // Create simple table. | ||||||
|             var simple = new Table().SetBorder(Border.Rounded).SetBorderColor(Color.Red); |             var simple = new Table().SetBorder(TableBorder.Rounded).SetBorderColor(Color.Red); | ||||||
|             simple.AddColumn(new TableColumn("[u]Foo[/]").Centered()); |             simple.AddColumn(new TableColumn("[u]Foo[/]").Centered()); | ||||||
|             simple.AddColumn(new TableColumn("[u]Bar[/]")); |             simple.AddColumn(new TableColumn("[u]Bar[/]")); | ||||||
|             simple.AddColumn(new TableColumn("[u]Baz[/]")); |             simple.AddColumn(new TableColumn("[u]Baz[/]")); | ||||||
| @@ -66,7 +66,7 @@ namespace TableExample | |||||||
|             simple.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", ""); |             simple.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", ""); | ||||||
| 
 | 
 | ||||||
|             // Create other table. |             // Create other table. | ||||||
|             var second = new Table().SetBorder(Border.Square).SetBorderColor(Color.Green); |             var second = new Table().SetBorder(TableBorder.Square).SetBorderColor(Color.Green); | ||||||
|             second.AddColumn(new TableColumn("[u]Foo[/]")); |             second.AddColumn(new TableColumn("[u]Foo[/]")); | ||||||
|             second.AddColumn(new TableColumn("[u]Bar[/]")); |             second.AddColumn(new TableColumn("[u]Bar[/]")); | ||||||
|             second.AddColumn(new TableColumn("[u]Baz[/]")); |             second.AddColumn(new TableColumn("[u]Baz[/]")); | ||||||
| @@ -74,7 +74,7 @@ namespace TableExample | |||||||
|             second.AddRow(simple, new Text("Whaaat"), new Text("Lolz")); |             second.AddRow(simple, new Text("Whaaat"), new Text("Lolz")); | ||||||
|             second.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", ""); |             second.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", ""); | ||||||
| 
 | 
 | ||||||
|             var table = new Table().SetBorder(Border.Rounded); |             var table = new Table().SetBorder(TableBorder.Rounded); | ||||||
|             table.AddColumn(new TableColumn(new Panel("[u]Foo[/]").SetBorderColor(Color.Red))); |             table.AddColumn(new TableColumn(new Panel("[u]Foo[/]").SetBorderColor(Color.Red))); | ||||||
|             table.AddColumn(new TableColumn(new Panel("[u]Bar[/]").SetBorderColor(Color.Green))); |             table.AddColumn(new TableColumn(new Panel("[u]Bar[/]").SetBorderColor(Color.Green))); | ||||||
|             table.AddColumn(new TableColumn(new Panel("[u]Baz[/]").SetBorderColor(Color.Blue))); |             table.AddColumn(new TableColumn(new Panel("[u]Baz[/]").SetBorderColor(Color.Blue))); | ||||||
| @@ -4,6 +4,7 @@ | |||||||
|     <OutputType>Exe</OutputType> |     <OutputType>Exe</OutputType> | ||||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> |     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||||
|     <IsPackable>false</IsPackable> |     <IsPackable>false</IsPackable> | ||||||
|  |     <Title>Tables</Title> | ||||||
|     <Description>Demonstrates how to render tables in a console.</Description> |     <Description>Demonstrates how to render tables in a console.</Description> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
| 
 | 
 | ||||||
| @@ -2,6 +2,6 @@ | |||||||
|   "projects": [ "src" ], |   "projects": [ "src" ], | ||||||
|   "sdk": { |   "sdk": { | ||||||
|     "version": "3.1.301", |     "version": "3.1.301", | ||||||
|     "rollForward": "latestMajor" |     "rollForward": "latestPatch" | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -24,3 +24,6 @@ dotnet_diagnostic.CA2000.severity = none | |||||||
|  |  | ||||||
| # SA1118: Parameter should not span multiple lines | # SA1118: Parameter should not span multiple lines | ||||||
| dotnet_diagnostic.SA1118.severity = none | dotnet_diagnostic.SA1118.severity = none | ||||||
|  |  | ||||||
|  | # CA1031: Do not catch general exception types | ||||||
|  | dotnet_diagnostic.CA1031.severity = none | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								src/Spectre.Console.Tests/Data/Exceptions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/Spectre.Console.Tests/Data/Exceptions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | using System; | ||||||
|  | using System.Diagnostics.CodeAnalysis; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console.Tests.Data | ||||||
|  | { | ||||||
|  |     public static class TestExceptions | ||||||
|  |     { | ||||||
|  |         [SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "<Pending>")] | ||||||
|  |         public static bool MethodThatThrows(int? number) => throw new InvalidOperationException("Throwing!"); | ||||||
|  |  | ||||||
|  |         public static void ThrowWithInnerException() | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 MethodThatThrows(null); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 throw new InvalidOperationException("Something threw!", ex); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,13 +1,34 @@ | |||||||
| using System; | using System; | ||||||
|  | using System.Text.RegularExpressions; | ||||||
|  |  | ||||||
| namespace Spectre.Console.Tests | namespace Spectre.Console.Tests | ||||||
| { | { | ||||||
|     public static class StringExtensions |     public static class StringExtensions | ||||||
|     { |     { | ||||||
|  |         private static readonly Regex _lineNumberRegex = new Regex(":\\d+", RegexOptions.Singleline); | ||||||
|  |         private static readonly Regex _filenameRegex = new Regex("\\sin\\s.*cs:nn", RegexOptions.Multiline); | ||||||
|  |  | ||||||
|         public static string NormalizeLineEndings(this string text) |         public static string NormalizeLineEndings(this string text) | ||||||
|         { |         { | ||||||
|             return text?.Replace("\r\n", "\n", StringComparison.OrdinalIgnoreCase) |             return text?.Replace("\r\n", "\n", StringComparison.OrdinalIgnoreCase) | ||||||
|                 ?.Replace("\r", string.Empty, StringComparison.OrdinalIgnoreCase); |                 ?.Replace("\r", string.Empty, StringComparison.OrdinalIgnoreCase); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         public static string NormalizeStackTrace(this string text) | ||||||
|  |         { | ||||||
|  |             text = _lineNumberRegex.Replace(text, match => | ||||||
|  |             { | ||||||
|  |                 return ":nn"; | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             return _filenameRegex.Replace(text, match => | ||||||
|  |             { | ||||||
|  |                 var value = match.Value; | ||||||
|  |                 var index = value.LastIndexOfAny(new[] { '\\', '/' }); | ||||||
|  |                 var filename = value.Substring(index + 1, value.Length - index - 1); | ||||||
|  |  | ||||||
|  |                 return $" in /xyz/{filename}"; | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| using System; | using System; | ||||||
| using System.IO; | using System.IO; | ||||||
| using System.Text; | using System.Text; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
| using Spectre.Console.Tests.Tools; | using Spectre.Console.Tests.Tools; | ||||||
|  |  | ||||||
| namespace Spectre.Console.Tests | namespace Spectre.Console.Tests | ||||||
| @@ -36,9 +37,9 @@ namespace Spectre.Console.Tests | |||||||
|             _writer?.Dispose(); |             _writer?.Dispose(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void Write(string text, Style style) |         public void Write(Segment segment) | ||||||
|         { |         { | ||||||
|             _console.Write(text, style); |             _console.Write(segment); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										44
									
								
								src/Spectre.Console.Tests/Tools/MarkupConsoleFixture.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/Spectre.Console.Tests/Tools/MarkupConsoleFixture.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | using System; | ||||||
|  | using System.IO; | ||||||
|  | using System.Text; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console.Tests.Tools | ||||||
|  | { | ||||||
|  |     public sealed class MarkupConsoleFixture : IDisposable, IAnsiConsole | ||||||
|  |     { | ||||||
|  |         private readonly StringWriter _writer; | ||||||
|  |         private readonly IAnsiConsole _console; | ||||||
|  |  | ||||||
|  |         public string Output => _writer.ToString().TrimEnd('\n'); | ||||||
|  |  | ||||||
|  |         public Capabilities Capabilities => _console.Capabilities; | ||||||
|  |         public Encoding Encoding => _console.Encoding; | ||||||
|  |         public int Width { get; } | ||||||
|  |         public int Height => _console.Height; | ||||||
|  |  | ||||||
|  |         public MarkupConsoleFixture(ColorSystem system, AnsiSupport ansi = AnsiSupport.Yes, int width = 80) | ||||||
|  |         { | ||||||
|  |             _writer = new StringWriter(); | ||||||
|  |             _console = AnsiConsole.Create(new AnsiConsoleSettings | ||||||
|  |             { | ||||||
|  |                 Ansi = ansi, | ||||||
|  |                 ColorSystem = (ColorSystemSupport)system, | ||||||
|  |                 Out = _writer, | ||||||
|  |                 LinkIdentityGenerator = new TestLinkIdentityGenerator(), | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             Width = width; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public void Dispose() | ||||||
|  |         { | ||||||
|  |             _writer?.Dispose(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public void Write(Segment segment) | ||||||
|  |         { | ||||||
|  |             _console.Write(segment); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,7 +1,9 @@ | |||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.IO; | using System.IO; | ||||||
|  | using System.Linq; | ||||||
| using System.Text; | using System.Text; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
| namespace Spectre.Console.Tests | namespace Spectre.Console.Tests | ||||||
| { | { | ||||||
| @@ -40,9 +42,25 @@ namespace Spectre.Console.Tests | |||||||
|             Writer.Dispose(); |             Writer.Dispose(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void Write(string text, Style style) |         public void Write(Segment segment) | ||||||
|         { |         { | ||||||
|             Writer.Write(text); |             if (segment is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(segment)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             Writer.Write(segment.Text); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public string[] WriteExceptionAndGetLines(Exception ex, ExceptionFormats formats = ExceptionFormats.None) | ||||||
|  |         { | ||||||
|  |             this.WriteException(ex, formats); | ||||||
|  |  | ||||||
|  |             return Output.NormalizeStackTrace() | ||||||
|  |                 .NormalizeLineEndings() | ||||||
|  |                 .Split(new char[] { '\n' }) | ||||||
|  |                 .Select(line => line.TrimEnd()) | ||||||
|  |                 .ToArray(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										210
									
								
								src/Spectre.Console.Tests/Unit/BoxBorderTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								src/Spectre.Console.Tests/Unit/BoxBorderTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | |||||||
|  | using Shouldly; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
|  | using Xunit; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console.Tests.Unit | ||||||
|  | { | ||||||
|  |     public sealed class BoxBorderTests | ||||||
|  |     { | ||||||
|  |         public sealed class NoBorder | ||||||
|  |         { | ||||||
|  |             public sealed class TheSafeGetBorderMethod | ||||||
|  |             { | ||||||
|  |                 [Fact] | ||||||
|  |                 public void Should_Return_Safe_Border() | ||||||
|  |                 { | ||||||
|  |                     // Given, When | ||||||
|  |                     var border = BoxBorder.None.GetSafeBorder(safe: true); | ||||||
|  |  | ||||||
|  |                     // Then | ||||||
|  |                     border.ShouldBeSameAs(BoxBorder.None); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Render_As_Expected() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new PlainConsole(); | ||||||
|  |                 var panel = Fixture.GetPanel().NoBorder(); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 console.Render(panel); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 console.Lines.Count.ShouldBe(3); | ||||||
|  |                 console.Lines[0].ShouldBe("  Greeting     "); | ||||||
|  |                 console.Lines[1].ShouldBe("  Hello World  "); | ||||||
|  |                 console.Lines[2].ShouldBe("               "); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public sealed class AsciiBorder | ||||||
|  |         { | ||||||
|  |             public sealed class TheSafeGetBorderMethod | ||||||
|  |             { | ||||||
|  |                 [Fact] | ||||||
|  |                 public void Should_Return_Safe_Border() | ||||||
|  |                 { | ||||||
|  |                     // Given, When | ||||||
|  |                     var border = BoxBorder.Ascii.GetSafeBorder(safe: true); | ||||||
|  |  | ||||||
|  |                     // Then | ||||||
|  |                     border.ShouldBeSameAs(BoxBorder.Ascii); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Render_As_Expected() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new PlainConsole(); | ||||||
|  |                 var panel = Fixture.GetPanel().AsciiBorder(); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 console.Render(panel); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 console.Lines.Count.ShouldBe(3); | ||||||
|  |                 console.Lines[0].ShouldBe("+-Greeting----+"); | ||||||
|  |                 console.Lines[1].ShouldBe("| Hello World |"); | ||||||
|  |                 console.Lines[2].ShouldBe("+-------------+"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public sealed class DoubleBorder | ||||||
|  |         { | ||||||
|  |             public sealed class TheSafeGetBorderMethod | ||||||
|  |             { | ||||||
|  |                 [Fact] | ||||||
|  |                 public void Should_Return_Safe_Border() | ||||||
|  |                 { | ||||||
|  |                     // Given, When | ||||||
|  |                     var border = BoxBorder.Double.GetSafeBorder(safe: true); | ||||||
|  |  | ||||||
|  |                     // Then | ||||||
|  |                     border.ShouldBeSameAs(BoxBorder.Double); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Render_As_Expected() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new PlainConsole(); | ||||||
|  |                 var panel = Fixture.GetPanel().DoubleBorder(); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 console.Render(panel); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 console.Lines.Count.ShouldBe(3); | ||||||
|  |                 console.Lines[0].ShouldBe("╔═Greeting════╗"); | ||||||
|  |                 console.Lines[1].ShouldBe("║ Hello World ║"); | ||||||
|  |                 console.Lines[2].ShouldBe("╚═════════════╝"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public sealed class HeavyBorder | ||||||
|  |         { | ||||||
|  |             public sealed class TheSafeGetBorderMethod | ||||||
|  |             { | ||||||
|  |                 [Fact] | ||||||
|  |                 public void Should_Return_Safe_Border() | ||||||
|  |                 { | ||||||
|  |                     // Given, When | ||||||
|  |                     var border = BoxBorder.Heavy.GetSafeBorder(safe: true); | ||||||
|  |  | ||||||
|  |                     // Then | ||||||
|  |                     border.ShouldBeSameAs(BoxBorder.Square); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Render_As_Expected() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new PlainConsole(); | ||||||
|  |                 var panel = Fixture.GetPanel().HeavyBorder(); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 console.Render(panel); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 console.Lines.Count.ShouldBe(3); | ||||||
|  |                 console.Lines[0].ShouldBe("┏━Greeting━━━━┓"); | ||||||
|  |                 console.Lines[1].ShouldBe("┃ Hello World ┃"); | ||||||
|  |                 console.Lines[2].ShouldBe("┗━━━━━━━━━━━━━┛"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public sealed class RoundedBorder | ||||||
|  |         { | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Return_Safe_Border() | ||||||
|  |             { | ||||||
|  |                 // Given, When | ||||||
|  |                 var border = BoxBorder.Rounded.GetSafeBorder(safe: true); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 border.ShouldBeSameAs(BoxBorder.Square); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Render_As_Expected() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new PlainConsole(); | ||||||
|  |                 var panel = Fixture.GetPanel().RoundedBorder(); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 console.Render(panel); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 console.Lines.Count.ShouldBe(3); | ||||||
|  |                 console.Lines[0].ShouldBe("╭─Greeting────╮"); | ||||||
|  |                 console.Lines[1].ShouldBe("│ Hello World │"); | ||||||
|  |                 console.Lines[2].ShouldBe("╰─────────────╯"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public sealed class SquareBorder | ||||||
|  |         { | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Return_Safe_Border() | ||||||
|  |             { | ||||||
|  |                 // Given, When | ||||||
|  |                 var border = BoxBorder.Square.GetSafeBorder(safe: true); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 border.ShouldBeSameAs(BoxBorder.Square); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Render_As_Expected() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new PlainConsole(); | ||||||
|  |                 var panel = Fixture.GetPanel().SquareBorder(); | ||||||
|  |  | ||||||
|  |                 // When | ||||||
|  |                 console.Render(panel); | ||||||
|  |  | ||||||
|  |                 // Then | ||||||
|  |                 console.Lines.Count.ShouldBe(3); | ||||||
|  |                 console.Lines[0].ShouldBe("┌─Greeting────┐"); | ||||||
|  |                 console.Lines[1].ShouldBe("│ Hello World │"); | ||||||
|  |                 console.Lines[2].ShouldBe("└─────────────┘"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static class Fixture | ||||||
|  |         { | ||||||
|  |             public static Panel GetPanel() | ||||||
|  |             { | ||||||
|  |                 return new Panel("Hello World") | ||||||
|  |                     .SetHeader("Greeting"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										99
									
								
								src/Spectre.Console.Tests/Unit/ExceptionTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/Spectre.Console.Tests/Unit/ExceptionTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | using System; | ||||||
|  | using Shouldly; | ||||||
|  | using Spectre.Console.Tests.Data; | ||||||
|  | using Xunit; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console.Tests.Unit | ||||||
|  | { | ||||||
|  |     public sealed class ExceptionTests | ||||||
|  |     { | ||||||
|  |         [Fact] | ||||||
|  |         public void Should_Write_Exception() | ||||||
|  |         { | ||||||
|  |             // Given | ||||||
|  |             var console = new PlainConsole(width: 1024); | ||||||
|  |             var dex = GetException(() => TestExceptions.MethodThatThrows(null)); | ||||||
|  |  | ||||||
|  |             // When | ||||||
|  |             var result = console.WriteExceptionAndGetLines(dex); | ||||||
|  |  | ||||||
|  |             // Then | ||||||
|  |             result.Length.ShouldBe(4); | ||||||
|  |             result[0].ShouldBe("System.InvalidOperationException: Throwing!"); | ||||||
|  |             result[1].ShouldBe("  at Spectre.Console.Tests.Data.TestExceptions.MethodThatThrows(Nullable`1 number) in /xyz/Exceptions.cs:nn"); | ||||||
|  |             result[2].ShouldBe("  at Spectre.Console.Tests.Unit.ExceptionTests.<>c.<Should_Write_Exception>b__0_0() in /xyz/ExceptionTests.cs:nn"); | ||||||
|  |             result[3].ShouldBe("  at Spectre.Console.Tests.Unit.ExceptionTests.GetException(Action action) in /xyz/ExceptionTests.cs:nn"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [Fact] | ||||||
|  |         public void Should_Write_Exception_With_Shortened_Types() | ||||||
|  |         { | ||||||
|  |             // Given | ||||||
|  |             var console = new PlainConsole(width: 1024); | ||||||
|  |             var dex = GetException(() => TestExceptions.MethodThatThrows(null)); | ||||||
|  |  | ||||||
|  |             // When | ||||||
|  |             var result = console.WriteExceptionAndGetLines(dex, ExceptionFormats.ShortenTypes); | ||||||
|  |  | ||||||
|  |             // Then | ||||||
|  |             result.Length.ShouldBe(4); | ||||||
|  |             result[0].ShouldBe("InvalidOperationException: Throwing!"); | ||||||
|  |             result[1].ShouldBe("  at Spectre.Console.Tests.Data.TestExceptions.MethodThatThrows(Nullable`1 number) in /xyz/Exceptions.cs:nn"); | ||||||
|  |             result[2].ShouldBe("  at Spectre.Console.Tests.Unit.ExceptionTests.<>c.<Should_Write_Exception_With_Shortened_Types>b__1_0() in /xyz/ExceptionTests.cs:nn"); | ||||||
|  |             result[3].ShouldBe("  at Spectre.Console.Tests.Unit.ExceptionTests.GetException(Action action) in /xyz/ExceptionTests.cs:nn"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [Fact] | ||||||
|  |         public void Should_Write_Exception_With_Shortened_Methods() | ||||||
|  |         { | ||||||
|  |             // Given | ||||||
|  |             var console = new PlainConsole(width: 1024); | ||||||
|  |             var dex = GetException(() => TestExceptions.MethodThatThrows(null)); | ||||||
|  |  | ||||||
|  |             // When | ||||||
|  |             var result = console.WriteExceptionAndGetLines(dex, ExceptionFormats.ShortenMethods); | ||||||
|  |  | ||||||
|  |             // Then | ||||||
|  |             result.Length.ShouldBe(4); | ||||||
|  |             result[0].ShouldBe("System.InvalidOperationException: Throwing!"); | ||||||
|  |             result[1].ShouldBe("  at MethodThatThrows(Nullable`1 number) in /xyz/Exceptions.cs:nn"); | ||||||
|  |             result[2].ShouldBe("  at <Should_Write_Exception_With_Shortened_Methods>b__2_0() in /xyz/ExceptionTests.cs:nn"); | ||||||
|  |             result[3].ShouldBe("  at GetException(Action action) in /xyz/ExceptionTests.cs:nn"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [Fact] | ||||||
|  |         public void Should_Write_Exception_With_Inner_Exception() | ||||||
|  |         { | ||||||
|  |             // Given | ||||||
|  |             var console = new PlainConsole(width: 1024); | ||||||
|  |             var dex = GetException(() => TestExceptions.ThrowWithInnerException()); | ||||||
|  |  | ||||||
|  |             // When | ||||||
|  |             var result = console.WriteExceptionAndGetLines(dex); | ||||||
|  |  | ||||||
|  |             // Then | ||||||
|  |             result.Length.ShouldBe(7); | ||||||
|  |             result[0].ShouldBe("System.InvalidOperationException: Something threw!"); | ||||||
|  |             result[1].ShouldBe("     System.InvalidOperationException: Throwing!"); | ||||||
|  |             result[2].ShouldBe("       at Spectre.Console.Tests.Data.TestExceptions.MethodThatThrows(Nullable`1 number) in /xyz/Exceptions.cs:nn"); | ||||||
|  |             result[3].ShouldBe("       at Spectre.Console.Tests.Data.TestExceptions.ThrowWithInnerException() in /xyz/Exceptions.cs:nn"); | ||||||
|  |             result[4].ShouldBe("  at Spectre.Console.Tests.Data.TestExceptions.ThrowWithInnerException() in /xyz/Exceptions.cs:nn"); | ||||||
|  |             result[5].ShouldBe("  at Spectre.Console.Tests.Unit.ExceptionTests.<>c.<Should_Write_Exception_With_Inner_Exception>b__3_0() in /xyz/ExceptionTests.cs:nn"); | ||||||
|  |             result[6].ShouldBe("  at Spectre.Console.Tests.Unit.ExceptionTests.GetException(Action action) in /xyz/ExceptionTests.cs:nn"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static Exception GetException(Action action) | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 action?.Invoke(); | ||||||
|  |             } | ||||||
|  |             catch (Exception e) | ||||||
|  |             { | ||||||
|  |                 return e; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             throw new InvalidOperationException("Exception harness failed"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -36,5 +36,21 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             // Then |             // Then | ||||||
|             console.Output.ShouldBe("Hello [ World ] !"); |             console.Output.ShouldBe("Hello [ World ] !"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         [Theory] | ||||||
|  |         [InlineData("Hello [link=http://example.com]example.com[/]", "Hello example.com")] | ||||||
|  |         [InlineData("Hello [link=http://example.com]http://example.com[/]", "Hello http://example.com")] | ||||||
|  |         public void Should_Render_Links_As_Expected(string input, string output) | ||||||
|  |         { | ||||||
|  |             // Given | ||||||
|  |             var console = new PlainConsole(); | ||||||
|  |             var markup = new Markup(input); | ||||||
|  |  | ||||||
|  |             // When | ||||||
|  |             console.Render(markup); | ||||||
|  |  | ||||||
|  |             // Then | ||||||
|  |             console.Output.ShouldBe(output); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,4 +1,6 @@ | |||||||
|  | using System.Collections.Generic; | ||||||
| using Shouldly; | using Shouldly; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
| using Xunit; | using Xunit; | ||||||
|  |  | ||||||
| namespace Spectre.Console.Tests.Unit | namespace Spectre.Console.Tests.Unit | ||||||
| @@ -298,5 +300,33 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             console.Lines[3].ShouldBe("│ └─────────────┘ │"); |             console.Lines[3].ShouldBe("│ └─────────────┘ │"); | ||||||
|             console.Lines[4].ShouldBe("└─────────────────┘"); |             console.Lines[4].ShouldBe("└─────────────────┘"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         [Fact] | ||||||
|  |         public void Should_Wrap_Content_Correctly() | ||||||
|  |         { | ||||||
|  |             // Given | ||||||
|  |             var console = new PlainConsole(width: 84); | ||||||
|  |             var rows = new List<IRenderable>(); | ||||||
|  |             var grid = new Grid(); | ||||||
|  |             grid.AddColumn(new GridColumn().PadLeft(2).PadRight(0)); | ||||||
|  |             grid.AddColumn(new GridColumn().PadLeft(1).PadRight(0)); | ||||||
|  |             grid.AddRow("at", "[grey]System.Runtime.CompilerServices.TaskAwaiter.[/][yellow]HandleNonSuccessAndDebuggerNotification[/]([blue]Task[/] task)"); | ||||||
|  |             rows.Add(grid); | ||||||
|  |  | ||||||
|  |             var panel = new Panel(grid) | ||||||
|  |                 .Expand().RoundedBorder() | ||||||
|  |                 .SetBorderStyle(Style.WithForeground(Color.Grey)) | ||||||
|  |                 .SetHeader("Short paths ", Style.WithForeground(Color.Grey)); | ||||||
|  |  | ||||||
|  |             // When | ||||||
|  |             console.Render(panel); | ||||||
|  |  | ||||||
|  |             // Then | ||||||
|  |             console.Lines.Count.ShouldBe(4); | ||||||
|  |             console.Lines[0].ShouldBe("╭─Short paths ─────────────────────────────────────────────────────────────────────╮"); | ||||||
|  |             console.Lines[1].ShouldBe("│   at System.Runtime.CompilerServices.TaskAwaiter.                                │"); | ||||||
|  |             console.Lines[2].ShouldBe("│      HandleNonSuccessAndDebuggerNotification(Task task)                          │"); | ||||||
|  |             console.Lines[3].ShouldBe("╰──────────────────────────────────────────────────────────────────────────────────╯"); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										66
									
								
								src/Spectre.Console.Tests/Unit/RecorderTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/Spectre.Console.Tests/Unit/RecorderTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  | using Shouldly; | ||||||
|  | using Xunit; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console.Tests.Unit | ||||||
|  | { | ||||||
|  |     public sealed class RecorderTests | ||||||
|  |     { | ||||||
|  |         [Fact] | ||||||
|  |         public void Should_Export_Text_As_Expected() | ||||||
|  |         { | ||||||
|  |             // Given | ||||||
|  |             var console = new PlainConsole(); | ||||||
|  |             var recorder = new Recorder(console); | ||||||
|  |  | ||||||
|  |             recorder.Render(new Table() | ||||||
|  |                 .AddColumns("Foo", "Bar", "Qux") | ||||||
|  |                 .AddRow("Corgi", "Waldo", "Zap") | ||||||
|  |                 .AddRow(new Panel("Hello World").RoundedBorder())); | ||||||
|  |  | ||||||
|  |             // When | ||||||
|  |             var result = recorder.ExportText().Split(new[] { '\n' }); | ||||||
|  |  | ||||||
|  |             // Then | ||||||
|  |             result.Length.ShouldBe(8); | ||||||
|  |             result[0].ShouldBe("┌─────────────────┬───────┬─────┐"); | ||||||
|  |             result[1].ShouldBe("│ Foo             │ Bar   │ Qux │"); | ||||||
|  |             result[2].ShouldBe("├─────────────────┼───────┼─────┤"); | ||||||
|  |             result[3].ShouldBe("│ Corgi           │ Waldo │ Zap │"); | ||||||
|  |             result[4].ShouldBe("│ ╭─────────────╮ │       │     │"); | ||||||
|  |             result[5].ShouldBe("│ │ Hello World │ │       │     │"); | ||||||
|  |             result[6].ShouldBe("│ ╰─────────────╯ │       │     │"); | ||||||
|  |             result[7].ShouldBe("└─────────────────┴───────┴─────┘"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [Fact] | ||||||
|  |         public void Should_Export_Html_As_Expected() | ||||||
|  |         { | ||||||
|  |             // Given | ||||||
|  |             var console = new PlainConsole(); | ||||||
|  |             var recorder = new Recorder(console); | ||||||
|  |  | ||||||
|  |             recorder.Render(new Table() | ||||||
|  |                 .AddColumns("[red on black]Foo[/]", "[green bold]Bar[/]", "[blue italic]Qux[/]") | ||||||
|  |                 .AddRow("[invert underline]Corgi[/]", "[bold strikethrough]Waldo[/]", "[dim]Zap[/]") | ||||||
|  |                 .AddRow(new Panel("[blue]Hello World[/]") | ||||||
|  |                     .SetBorderColor(Color.Red).RoundedBorder())); | ||||||
|  |  | ||||||
|  |             // When | ||||||
|  |             var html = recorder.ExportHtml(); | ||||||
|  |             var result = html.Split(new[] { '\n' }); | ||||||
|  |  | ||||||
|  |             // Then | ||||||
|  |             result.Length.ShouldBe(10); | ||||||
|  |             result[0].ShouldBe("<pre style=\"font-size:90%;font-family:consolas,'Courier New',monospace\">"); | ||||||
|  |             result[1].ShouldBe("<span>┌─────────────────┬───────┬─────┐</span>"); | ||||||
|  |             result[2].ShouldBe("<span>│ </span><span style=\"color: #FF0000;background-color: #000000\">Foo</span><span>             │ </span><span style=\"color: #008000;font-weight: bold;font-style: italic\">Bar</span><span>   │ </span><span style=\"color: #0000FF\">Qux</span><span> │</span>"); | ||||||
|  |             result[3].ShouldBe("<span>├─────────────────┼───────┼─────┤</span>"); | ||||||
|  |             result[4].ShouldBe("<span>│ </span><span style=\"text-decoration: underline\">Corgi</span><span>           │ </span><span style=\"font-weight: bold;font-style: italic;text-decoration: line-through\">Waldo</span><span> │ </span><span style=\"color: #7F7F7F\">Zap</span><span> │</span>"); | ||||||
|  |             result[5].ShouldBe("<span>│ </span><span style=\"color: #FF0000\">╭─────────────╮</span><span> │       │     │</span>"); | ||||||
|  |             result[6].ShouldBe("<span>│ </span><span style=\"color: #FF0000\">│</span><span> </span><span style=\"color: #0000FF\">Hello World</span><span> </span><span style=\"color: #FF0000\">│</span><span> │       │     │</span>"); | ||||||
|  |             result[7].ShouldBe("<span>│ </span><span style=\"color: #FF0000\">╰─────────────╯</span><span> │       │     │</span>"); | ||||||
|  |             result[8].ShouldBe("<span>└─────────────────┴───────┴─────┘</span>"); | ||||||
|  |             result[9].ShouldBe("</pre>"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										96
									
								
								src/Spectre.Console.Tests/Unit/RowsTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/Spectre.Console.Tests/Unit/RowsTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | |||||||
|  | using Shouldly; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
|  | using Xunit; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console.Tests.Unit | ||||||
|  | { | ||||||
|  |     public sealed class RowsTests | ||||||
|  |     { | ||||||
|  |         [Fact] | ||||||
|  |         public void Should_Render_Rows() | ||||||
|  |         { | ||||||
|  |             // Given | ||||||
|  |             var console = new PlainConsole(width: 60); | ||||||
|  |             var rows = new Rows( | ||||||
|  |                 new IRenderable[] | ||||||
|  |                 { | ||||||
|  |                     new Markup("Hello"), | ||||||
|  |                     new Table() | ||||||
|  |                         .AddColumns("Foo", "Bar") | ||||||
|  |                         .AddRow("Baz", "Qux"), | ||||||
|  |                     new Markup("World"), | ||||||
|  |                 }); | ||||||
|  |  | ||||||
|  |             // When | ||||||
|  |             console.Render(rows); | ||||||
|  |  | ||||||
|  |             // Then | ||||||
|  |             console.Lines.Count.ShouldBe(7); | ||||||
|  |             console.Lines[0].ShouldBe("Hello"); | ||||||
|  |             console.Lines[1].ShouldBe("┌─────┬─────┐"); | ||||||
|  |             console.Lines[2].ShouldBe("│ Foo │ Bar │"); | ||||||
|  |             console.Lines[3].ShouldBe("├─────┼─────┤"); | ||||||
|  |             console.Lines[4].ShouldBe("│ Baz │ Qux │"); | ||||||
|  |             console.Lines[5].ShouldBe("└─────┴─────┘"); | ||||||
|  |             console.Lines[6].ShouldBe("World"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [Fact] | ||||||
|  |         public void Should_Render_Rows_Correctly_Inside_Other_Widget() | ||||||
|  |         { | ||||||
|  |             // Given | ||||||
|  |             var console = new PlainConsole(width: 60); | ||||||
|  |             var table = new Table() | ||||||
|  |                 .AddColumns("Foo", "Bar") | ||||||
|  |                 .AddRow("HELLO WORLD") | ||||||
|  |                 .AddRow( | ||||||
|  |                 new Rows(new IRenderable[] | ||||||
|  |                 { | ||||||
|  |                     new Markup("Hello"), | ||||||
|  |                     new Markup("World"), | ||||||
|  |                 }), new Text("Qux")); | ||||||
|  |  | ||||||
|  |             // When | ||||||
|  |             console.Render(table); | ||||||
|  |  | ||||||
|  |             // Then | ||||||
|  |             console.Lines.Count.ShouldBe(7); | ||||||
|  |             console.Lines[0].ShouldBe("┌─────────────┬─────┐"); | ||||||
|  |             console.Lines[1].ShouldBe("│ Foo         │ Bar │"); | ||||||
|  |             console.Lines[2].ShouldBe("├─────────────┼─────┤"); | ||||||
|  |             console.Lines[3].ShouldBe("│ HELLO WORLD │     │"); | ||||||
|  |             console.Lines[4].ShouldBe("│ Hello       │ Qux │"); | ||||||
|  |             console.Lines[5].ShouldBe("│ World       │     │"); | ||||||
|  |             console.Lines[6].ShouldBe("└─────────────┴─────┘"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         [Fact] | ||||||
|  |         public void Should_Render_Rows_Correctly_Inside_Other_Widget_When_Expanded() | ||||||
|  |         { | ||||||
|  |             // Given | ||||||
|  |             var console = new PlainConsole(width: 60); | ||||||
|  |             var table = new Table() | ||||||
|  |                 .AddColumns("Foo", "Bar") | ||||||
|  |                 .AddRow("HELLO WORLD") | ||||||
|  |                 .AddRow( | ||||||
|  |                 new Rows(new IRenderable[] | ||||||
|  |                 { | ||||||
|  |                     new Markup("Hello"), | ||||||
|  |                     new Markup("World"), | ||||||
|  |                 }).Expand(), new Text("Qux")); | ||||||
|  |  | ||||||
|  |             // When | ||||||
|  |             console.Render(table); | ||||||
|  |  | ||||||
|  |             // Then | ||||||
|  |             console.Lines.Count.ShouldBe(7); | ||||||
|  |             console.Lines[0].ShouldBe("┌────────────────────────────────────────────────────┬─────┐"); | ||||||
|  |             console.Lines[1].ShouldBe("│ Foo                                                │ Bar │"); | ||||||
|  |             console.Lines[2].ShouldBe("├────────────────────────────────────────────────────┼─────┤"); | ||||||
|  |             console.Lines[3].ShouldBe("│ HELLO WORLD                                        │     │"); | ||||||
|  |             console.Lines[4].ShouldBe("│ Hello                                              │ Qux │"); | ||||||
|  |             console.Lines[5].ShouldBe("│ World                                              │     │"); | ||||||
|  |             console.Lines[6].ShouldBe("└────────────────────────────────────────────────────┴─────┘"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -4,7 +4,7 @@ using Xunit; | |||||||
| 
 | 
 | ||||||
| namespace Spectre.Console.Tests.Unit | namespace Spectre.Console.Tests.Unit | ||||||
| { | { | ||||||
|     public sealed class BorderTests |     public sealed class TableBorderTests | ||||||
|     { |     { | ||||||
|         public sealed class NoBorder |         public sealed class NoBorder | ||||||
|         { |         { | ||||||
| @@ -12,7 +12,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.None.Visible; |                 var visibility = TableBorder.None.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeFalse(); |                 visibility.ShouldBeFalse(); | ||||||
| @@ -24,10 +24,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.None.GetSafeBorder(safe: true); |                     var border = TableBorder.None.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.None); |                     border.ShouldBeSameAs(TableBorder.None); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -55,7 +55,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.Ascii.Visible; |                 var visibility = TableBorder.Ascii.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -67,10 +67,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.Ascii.GetSafeBorder(safe: true); |                     var border = TableBorder.Ascii.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Ascii); |                     border.ShouldBeSameAs(TableBorder.Ascii); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -101,7 +101,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.Ascii2.Visible; |                 var visibility = TableBorder.Ascii2.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -113,10 +113,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.Ascii2.GetSafeBorder(safe: true); |                     var border = TableBorder.Ascii2.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Ascii2); |                     border.ShouldBeSameAs(TableBorder.Ascii2); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -147,7 +147,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.AsciiDoubleHead.Visible; |                 var visibility = TableBorder.AsciiDoubleHead.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -159,10 +159,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.AsciiDoubleHead.GetSafeBorder(safe: true); |                     var border = TableBorder.AsciiDoubleHead.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.AsciiDoubleHead); |                     border.ShouldBeSameAs(TableBorder.AsciiDoubleHead); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -193,7 +193,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.Square.Visible; |                 var visibility = TableBorder.Square.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -205,10 +205,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.Square.GetSafeBorder(safe: true); |                     var border = TableBorder.Square.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Square); |                     border.ShouldBeSameAs(TableBorder.Square); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -239,7 +239,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.Rounded.Visible; |                 var visibility = TableBorder.Rounded.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -251,10 +251,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.Rounded.GetSafeBorder(safe: true); |                     var border = TableBorder.Rounded.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Square); |                     border.ShouldBeSameAs(TableBorder.Square); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -285,7 +285,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.Minimal.Visible; |                 var visibility = TableBorder.Minimal.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -297,10 +297,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.Minimal.GetSafeBorder(safe: true); |                     var border = TableBorder.Minimal.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Minimal); |                     border.ShouldBeSameAs(TableBorder.Minimal); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -331,7 +331,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.MinimalHeavyHead.Visible; |                 var visibility = TableBorder.MinimalHeavyHead.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -343,10 +343,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.MinimalHeavyHead.GetSafeBorder(safe: true); |                     var border = TableBorder.MinimalHeavyHead.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Minimal); |                     border.ShouldBeSameAs(TableBorder.Minimal); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -377,7 +377,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.MinimalDoubleHead.Visible; |                 var visibility = TableBorder.MinimalDoubleHead.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -389,10 +389,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.MinimalDoubleHead.GetSafeBorder(safe: true); |                     var border = TableBorder.MinimalDoubleHead.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.MinimalDoubleHead); |                     border.ShouldBeSameAs(TableBorder.MinimalDoubleHead); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -423,7 +423,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.Simple.Visible; |                 var visibility = TableBorder.Simple.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -435,10 +435,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.Simple.GetSafeBorder(safe: true); |                     var border = TableBorder.Simple.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Simple); |                     border.ShouldBeSameAs(TableBorder.Simple); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -469,7 +469,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.Horizontal.Visible; |                 var visibility = TableBorder.Horizontal.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -481,10 +481,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.Horizontal.GetSafeBorder(safe: true); |                     var border = TableBorder.Horizontal.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Horizontal); |                     border.ShouldBeSameAs(TableBorder.Horizontal); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -515,7 +515,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.SimpleHeavy.Visible; |                 var visibility = TableBorder.SimpleHeavy.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -527,10 +527,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.SimpleHeavy.GetSafeBorder(safe: true); |                     var border = TableBorder.SimpleHeavy.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Simple); |                     border.ShouldBeSameAs(TableBorder.Simple); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -561,7 +561,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.Heavy.Visible; |                 var visibility = TableBorder.Heavy.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -573,10 +573,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.Heavy.GetSafeBorder(safe: true); |                     var border = TableBorder.Heavy.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Square); |                     border.ShouldBeSameAs(TableBorder.Square); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -607,7 +607,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.HeavyEdge.Visible; |                 var visibility = TableBorder.HeavyEdge.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -619,10 +619,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.HeavyEdge.GetSafeBorder(safe: true); |                     var border = TableBorder.HeavyEdge.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Square); |                     border.ShouldBeSameAs(TableBorder.Square); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -653,7 +653,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.HeavyHead.Visible; |                 var visibility = TableBorder.HeavyHead.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -665,10 +665,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.HeavyHead.GetSafeBorder(safe: true); |                     var border = TableBorder.HeavyHead.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Square); |                     border.ShouldBeSameAs(TableBorder.Square); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -699,7 +699,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.Double.Visible; |                 var visibility = TableBorder.Double.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -711,10 +711,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.Double.GetSafeBorder(safe: true); |                     var border = TableBorder.Double.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.Double); |                     border.ShouldBeSameAs(TableBorder.Double); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -745,7 +745,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             public void Should_Return_Correct_Visibility() |             public void Should_Return_Correct_Visibility() | ||||||
|             { |             { | ||||||
|                 // Given, When |                 // Given, When | ||||||
|                 var visibility = Border.DoubleEdge.Visible; |                 var visibility = TableBorder.DoubleEdge.Visible; | ||||||
| 
 | 
 | ||||||
|                 // Then |                 // Then | ||||||
|                 visibility.ShouldBeTrue(); |                 visibility.ShouldBeTrue(); | ||||||
| @@ -757,10 +757,10 @@ namespace Spectre.Console.Tests.Unit | |||||||
|                 public void Should_Return_Safe_Border() |                 public void Should_Return_Safe_Border() | ||||||
|                 { |                 { | ||||||
|                     // Given, When |                     // Given, When | ||||||
|                     var border = Border.DoubleEdge.GetSafeBorder(safe: true); |                     var border = TableBorder.DoubleEdge.GetSafeBorder(safe: true); | ||||||
| 
 | 
 | ||||||
|                     // Then |                     // Then | ||||||
|                     border.ShouldBeSameAs(Border.DoubleEdge); |                     border.ShouldBeSameAs(TableBorder.DoubleEdge); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @@ -785,12 +785,119 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         public sealed class MarkdownBorder | ||||||
|  |         { | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Return_Correct_Visibility() | ||||||
|  |             { | ||||||
|  |                 // Given, When | ||||||
|  |                 var visibility = TableBorder.Markdown.Visible; | ||||||
|  | 
 | ||||||
|  |                 // Then | ||||||
|  |                 visibility.ShouldBeTrue(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             public sealed class TheSafeGetBorderMethod | ||||||
|  |             { | ||||||
|  |                 [Fact] | ||||||
|  |                 public void Should_Return_Safe_Border() | ||||||
|  |                 { | ||||||
|  |                     // Given, When | ||||||
|  |                     var border = TableBorder.Markdown.GetSafeBorder(safe: true); | ||||||
|  | 
 | ||||||
|  |                     // Then | ||||||
|  |                     border.ShouldBeSameAs(TableBorder.Markdown); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Render_As_Expected() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new PlainConsole(); | ||||||
|  |                 var table = Fixture.GetTable().MarkdownBorder(); | ||||||
|  | 
 | ||||||
|  |                 // When | ||||||
|  |                 console.Render(table); | ||||||
|  | 
 | ||||||
|  |                 // Then | ||||||
|  |                 console.Lines.Count.ShouldBe(6); | ||||||
|  |                 console.Lines[0].ShouldBe("                       "); | ||||||
|  |                 console.Lines[1].ShouldBe("| Header 1 | Header 2 |"); | ||||||
|  |                 console.Lines[2].ShouldBe("| -------- | -------- |"); | ||||||
|  |                 console.Lines[3].ShouldBe("| Cell     | Cell     |"); | ||||||
|  |                 console.Lines[4].ShouldBe("| Cell     | Cell     |"); | ||||||
|  |                 console.Lines[5].ShouldBe("                       "); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Render_Left_Aligned_Table_Columns_As_Expected() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new PlainConsole(); | ||||||
|  |                 var table = Fixture.GetTable(header2: Justify.Left).MarkdownBorder(); | ||||||
|  | 
 | ||||||
|  |                 // When | ||||||
|  |                 console.Render(table); | ||||||
|  | 
 | ||||||
|  |                 // Then | ||||||
|  |                 console.Lines.Count.ShouldBe(6); | ||||||
|  |                 console.Lines[0].ShouldBe("                       "); | ||||||
|  |                 console.Lines[1].ShouldBe("| Header 1 | Header 2 |"); | ||||||
|  |                 console.Lines[2].ShouldBe("| -------- | :------- |"); | ||||||
|  |                 console.Lines[3].ShouldBe("| Cell     | Cell     |"); | ||||||
|  |                 console.Lines[4].ShouldBe("| Cell     | Cell     |"); | ||||||
|  |                 console.Lines[5].ShouldBe("                       "); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Render_Center_Aligned_Table_Columns_As_Expected() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new PlainConsole(); | ||||||
|  |                 var table = Fixture.GetTable(header2: Justify.Center).MarkdownBorder(); | ||||||
|  | 
 | ||||||
|  |                 // When | ||||||
|  |                 console.Render(table); | ||||||
|  | 
 | ||||||
|  |                 // Then | ||||||
|  |                 console.Lines.Count.ShouldBe(6); | ||||||
|  |                 console.Lines[0].ShouldBe("                       "); | ||||||
|  |                 console.Lines[1].ShouldBe("| Header 1 | Header 2 |"); | ||||||
|  |                 console.Lines[2].ShouldBe("| -------- | :------: |"); | ||||||
|  |                 console.Lines[3].ShouldBe("| Cell     |   Cell   |"); | ||||||
|  |                 console.Lines[4].ShouldBe("| Cell     |   Cell   |"); | ||||||
|  |                 console.Lines[5].ShouldBe("                       "); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             [Fact] | ||||||
|  |             public void Should_Render_Right_Aligned_Table_Columns_As_Expected() | ||||||
|  |             { | ||||||
|  |                 // Given | ||||||
|  |                 var console = new PlainConsole(); | ||||||
|  |                 var table = Fixture.GetTable(header2: Justify.Right).MarkdownBorder(); | ||||||
|  | 
 | ||||||
|  |                 // When | ||||||
|  |                 console.Render(table); | ||||||
|  | 
 | ||||||
|  |                 // Then | ||||||
|  |                 console.Lines.Count.ShouldBe(6); | ||||||
|  |                 console.Lines[0].ShouldBe("                       "); | ||||||
|  |                 console.Lines[1].ShouldBe("| Header 1 | Header 2 |"); | ||||||
|  |                 console.Lines[2].ShouldBe("| -------- | -------: |"); | ||||||
|  |                 console.Lines[3].ShouldBe("| Cell     |     Cell |"); | ||||||
|  |                 console.Lines[4].ShouldBe("| Cell     |     Cell |"); | ||||||
|  |                 console.Lines[5].ShouldBe("                       "); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         private static class Fixture |         private static class Fixture | ||||||
|         { |         { | ||||||
|             public static Table GetTable() |             public static Table GetTable(Justify? header1 = null, Justify? header2 = null) | ||||||
|             { |             { | ||||||
|                 var table = new Table(); |                 var table = new Table(); | ||||||
|                 table.AddColumns("Header 1", "Header 2"); |                 table.AddColumn("Header 1", c => c.Alignment = header1); | ||||||
|  |                 table.AddColumn("Header 2", c => c.Alignment = header2); | ||||||
|                 table.AddRow("Cell", "Cell"); |                 table.AddRow("Cell", "Cell"); | ||||||
|                 table.AddRow("Cell", "Cell"); |                 table.AddRow("Cell", "Cell"); | ||||||
|                 return table; |                 return table; | ||||||
| @@ -173,7 +173,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|         { |         { | ||||||
|             // A simple table |             // A simple table | ||||||
|             var console = new PlainConsole(width: 80); |             var console = new PlainConsole(width: 80); | ||||||
|             var table = new Table() { Border = Border.Rounded }; |             var table = new Table() { Border = TableBorder.Rounded }; | ||||||
|             table.AddColumn("Foo"); |             table.AddColumn("Foo"); | ||||||
|             table.AddColumn("Bar"); |             table.AddColumn("Bar"); | ||||||
|             table.AddColumn(new TableColumn("Baz") { Alignment = Justify.Right }); |             table.AddColumn(new TableColumn("Baz") { Alignment = Justify.Right }); | ||||||
| @@ -183,7 +183,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|             // Render a table in some panels. |             // Render a table in some panels. | ||||||
|             console.Render(new Panel(new Panel(table) |             console.Render(new Panel(new Panel(table) | ||||||
|             { |             { | ||||||
|                 Border = Border.Ascii, |                 Border = BoxBorder.Ascii, | ||||||
|             })); |             })); | ||||||
|  |  | ||||||
|             // Then |             // Then | ||||||
| @@ -255,7 +255,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|         { |         { | ||||||
|             // Given |             // Given | ||||||
|             var console = new PlainConsole(width: 80); |             var console = new PlainConsole(width: 80); | ||||||
|             var table = new Table { Border = Border.Ascii }; |             var table = new Table { Border = TableBorder.Ascii }; | ||||||
|             table.AddColumns("Foo", "Bar", "Baz"); |             table.AddColumns("Foo", "Bar", "Baz"); | ||||||
|             table.AddRow("Qux", "Corgi", "Waldo"); |             table.AddRow("Qux", "Corgi", "Waldo"); | ||||||
|             table.AddRow("Grault", "Garply", "Fred"); |             table.AddRow("Grault", "Garply", "Fred"); | ||||||
| @@ -278,7 +278,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|         { |         { | ||||||
|             // Given |             // Given | ||||||
|             var console = new PlainConsole(width: 80); |             var console = new PlainConsole(width: 80); | ||||||
|             var table = new Table { Border = Border.Rounded }; |             var table = new Table { Border = TableBorder.Rounded }; | ||||||
|             table.AddColumns("Foo", "Bar", "Baz"); |             table.AddColumns("Foo", "Bar", "Baz"); | ||||||
|             table.AddRow("Qux", "Corgi", "Waldo"); |             table.AddRow("Qux", "Corgi", "Waldo"); | ||||||
|             table.AddRow("Grault", "Garply", "Fred"); |             table.AddRow("Grault", "Garply", "Fred"); | ||||||
| @@ -301,7 +301,7 @@ namespace Spectre.Console.Tests.Unit | |||||||
|         { |         { | ||||||
|             // Given |             // Given | ||||||
|             var console = new PlainConsole(width: 80); |             var console = new PlainConsole(width: 80); | ||||||
|             var table = new Table { Border = Border.None }; |             var table = new Table { Border = TableBorder.None }; | ||||||
|             table.AddColumns("Foo", "Bar", "Baz"); |             table.AddColumns("Foo", "Bar", "Baz"); | ||||||
|             table.AddRow("Qux", "Corgi", "Waldo"); |             table.AddRow("Qux", "Corgi", "Waldo"); | ||||||
|             table.AddRow("Grault", "Garply", "Fred"); |             table.AddRow("Grault", "Garply", "Fred"); | ||||||
|   | |||||||
| @@ -17,11 +17,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution | |||||||
| EndProject | EndProject | ||||||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{F0575243-121F-4DEE-9F6B-246E26DC0844}" | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{F0575243-121F-4DEE-9F6B-246E26DC0844}" | ||||||
| EndProject | EndProject | ||||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Table", "..\examples\Table\Table.csproj", "{94ECCBA8-7EBF-4B53-8379-52EB2327417E}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tables", "..\examples\Tables\Tables.csproj", "{94ECCBA8-7EBF-4B53-8379-52EB2327417E}" | ||||||
| EndProject | EndProject | ||||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Panel", "..\examples\Panel\Panel.csproj", "{BFF37228-B376-4ADD-9657-4E501F929713}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Panels", "..\examples\Panels\Panels.csproj", "{BFF37228-B376-4ADD-9657-4E501F929713}" | ||||||
| EndProject | EndProject | ||||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grid", "..\examples\Grid\Grid.csproj", "{C7FF6FDB-FB59-4517-8669-521C96AB7323}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grids", "..\examples\Grids\Grids.csproj", "{C7FF6FDB-FB59-4517-8669-521C96AB7323}" | ||||||
| EndProject | EndProject | ||||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Colors", "..\examples\Colors\Colors.csproj", "{1F51C55C-BA4C-4856-9001-0F7924FFB179}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Colors", "..\examples\Colors\Colors.csproj", "{1F51C55C-BA4C-4856-9001-0F7924FFB179}" | ||||||
| EndProject | EndProject | ||||||
| @@ -33,7 +33,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Borders", "..\examples\Bord | |||||||
| EndProject | EndProject | ||||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Links", "..\examples\Links\Links.csproj", "{6AF8C93B-AA41-4F44-8B1B-B8D166576174}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Links", "..\examples\Links\Links.csproj", "{6AF8C93B-AA41-4F44-8B1B-B8D166576174}" | ||||||
| EndProject | EndProject | ||||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emojis", "..\examples\Emojis\Emojis.csproj", "{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emojis", "..\examples\Emojis\Emojis.csproj", "{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}" | ||||||
|  | EndProject | ||||||
|  | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Exceptions", "..\examples\Exceptions\Exceptions.csproj", "{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}" | ||||||
|  | EndProject | ||||||
|  | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GitHub", "GitHub", "{C3E2CB5C-1517-4C75-B59A-93D4E22BEC8D}" | ||||||
|  | 	ProjectSection(SolutionItems) = preProject | ||||||
|  | 		..\.github\workflows\ci.yaml = ..\.github\workflows\ci.yaml | ||||||
|  | 		..\.github\workflows\docs.yaml = ..\.github\workflows\docs.yaml | ||||||
|  | 		..\.github\workflows\publish.yaml = ..\.github\workflows\publish.yaml | ||||||
|  | 	EndProjectSection | ||||||
| EndProject | EndProject | ||||||
| Global | Global | ||||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||||
| @@ -177,6 +186,18 @@ Global | |||||||
| 		{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Release|x64.Build.0 = Release|Any CPU | 		{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Release|x64.Build.0 = Release|Any CPU | ||||||
| 		{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Release|x86.ActiveCfg = Release|Any CPU | 		{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Release|x86.ActiveCfg = Release|Any CPU | ||||||
| 		{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Release|x86.Build.0 = Release|Any CPU | 		{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2}.Release|x86.Build.0 = Release|Any CPU | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Debug|x64.Build.0 = Debug|Any CPU | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Debug|x86.Build.0 = Debug|Any CPU | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Release|Any CPU.Build.0 = Release|Any CPU | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Release|x64.ActiveCfg = Release|Any CPU | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Release|x64.Build.0 = Release|Any CPU | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Release|x86.ActiveCfg = Release|Any CPU | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Release|x86.Build.0 = Release|Any CPU | ||||||
| 	EndGlobalSection | 	EndGlobalSection | ||||||
| 	GlobalSection(SolutionProperties) = preSolution | 	GlobalSection(SolutionProperties) = preSolution | ||||||
| 		HideSolutionNode = FALSE | 		HideSolutionNode = FALSE | ||||||
| @@ -191,6 +212,8 @@ Global | |||||||
| 		{094245E6-4C94-485D-B5AC-3153E878B112} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | 		{094245E6-4C94-485D-B5AC-3153E878B112} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | ||||||
| 		{6AF8C93B-AA41-4F44-8B1B-B8D166576174} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | 		{6AF8C93B-AA41-4F44-8B1B-B8D166576174} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | ||||||
| 		{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | 		{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | ||||||
|  | 		{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | ||||||
|  | 		{C3E2CB5C-1517-4C75-B59A-93D4E22BEC8D} = {20595AD4-8D75-4AF8-B6BC-9C38C160423F} | ||||||
| 	EndGlobalSection | 	EndGlobalSection | ||||||
| 	GlobalSection(ExtensibilityGlobals) = postSolution | 	GlobalSection(ExtensibilityGlobals) = postSolution | ||||||
| 		SolutionGuid = {5729B071-67A0-48FB-8B1B-275E6822086C} | 		SolutionGuid = {5729B071-67A0-48FB-8B1B-275E6822086C} | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								src/Spectre.Console/AnsiConsole.Exceptions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/Spectre.Console/AnsiConsole.Exceptions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | using System; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// A console capable of writing ANSI escape sequences. | ||||||
|  |     /// </summary> | ||||||
|  |     public static partial class AnsiConsole | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Writes an exception to the console. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="exception">The exception to write to the console.</param> | ||||||
|  |         /// <param name="format">The exception format options.</param> | ||||||
|  |         public static void WriteException(Exception exception, ExceptionFormats format = ExceptionFormats.None) | ||||||
|  |         { | ||||||
|  |             Console.WriteException(exception, format); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										67
									
								
								src/Spectre.Console/AnsiConsole.Recording.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/Spectre.Console/AnsiConsole.Recording.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | |||||||
|  | using System; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// A console capable of writing ANSI escape sequences. | ||||||
|  |     /// </summary> | ||||||
|  |     public static partial class AnsiConsole | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Starts recording the console output. | ||||||
|  |         /// </summary> | ||||||
|  |         public static void Record() | ||||||
|  |         { | ||||||
|  |             _recorder = new Recorder(_console.Value); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Exports all recorded console output as text. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns>The recorded output as text.</returns> | ||||||
|  |         public static string ExportText() | ||||||
|  |         { | ||||||
|  |             if (_recorder == null) | ||||||
|  |             { | ||||||
|  |                 throw new InvalidOperationException("Cannot export text since a recording hasn't been started."); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return _recorder.ExportText(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Exports all recorded console output as HTML. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns>The recorded output as HTML.</returns> | ||||||
|  |         public static string ExportHtml() | ||||||
|  |         { | ||||||
|  |             if (_recorder == null) | ||||||
|  |             { | ||||||
|  |                 throw new InvalidOperationException("Cannot export HTML since a recording hasn't been started."); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return _recorder.ExportHtml(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Exports all recorded console output using a custom encoder. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="encoder">The encoder to use.</param> | ||||||
|  |         /// <returns>The recorded output.</returns> | ||||||
|  |         public static string ExportCustom(IAnsiConsoleEncoder encoder) | ||||||
|  |         { | ||||||
|  |             if (_recorder == null) | ||||||
|  |             { | ||||||
|  |                 throw new InvalidOperationException("Cannot export HTML since a recording hasn't been started."); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (encoder is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(encoder)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return _recorder.Export(encoder); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,7 +1,3 @@ | |||||||
| using System; |  | ||||||
| using System.IO; |  | ||||||
| using Spectre.Console.Internal; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console | namespace Spectre.Console | ||||||
| { | { | ||||||
|     /// <summary> |     /// <summary> | ||||||
| @@ -9,9 +5,6 @@ namespace Spectre.Console | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     public static partial class AnsiConsole |     public static partial class AnsiConsole | ||||||
|     { |     { | ||||||
|         private static ConsoleColor _defaultForeground; |  | ||||||
|         private static ConsoleColor _defaultBackground; |  | ||||||
|  |  | ||||||
|         internal static Style CurrentStyle { get; private set; } = Style.Plain; |         internal static Style CurrentStyle { get; private set; } = Style.Plain; | ||||||
|         internal static bool Created { get; private set; } |         internal static bool Created { get; private set; } | ||||||
|  |  | ||||||
| @@ -42,20 +35,6 @@ namespace Spectre.Console | |||||||
|             set => CurrentStyle = CurrentStyle.WithDecoration(value); |             set => CurrentStyle = CurrentStyle.WithDecoration(value); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         internal static void Initialize(TextWriter? @out) |  | ||||||
|         { |  | ||||||
|             if (@out?.IsStandardOut() ?? false) |  | ||||||
|             { |  | ||||||
|                 Foreground = _defaultForeground = System.Console.ForegroundColor; |  | ||||||
|                 Background = _defaultBackground = System.Console.BackgroundColor; |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 Foreground = _defaultForeground = Color.Silver; |  | ||||||
|                 Background = _defaultBackground = Color.Black; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Resets colors and text decorations. |         /// Resets colors and text decorations. | ||||||
|         /// </summary> |         /// </summary> | ||||||
| @@ -78,8 +57,7 @@ namespace Spectre.Console | |||||||
|         /// </summary> |         /// </summary> | ||||||
|         public static void ResetColors() |         public static void ResetColors() | ||||||
|         { |         { | ||||||
|             Foreground = _defaultForeground; |             CurrentStyle = Style.Plain; | ||||||
|             Background = _defaultBackground; |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -16,15 +16,16 @@ namespace Spectre.Console | |||||||
|                 ColorSystem = ColorSystemSupport.Detect, |                 ColorSystem = ColorSystemSupport.Detect, | ||||||
|                 Out = System.Console.Out, |                 Out = System.Console.Out, | ||||||
|             }); |             }); | ||||||
|             Initialize(System.Console.Out); |  | ||||||
|             Created = true; |             Created = true; | ||||||
|             return console; |             return console; | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|  |         private static Recorder? _recorder; | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Gets the underlying <see cref="IAnsiConsole"/>. |         /// Gets the underlying <see cref="IAnsiConsole"/>. | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public static IAnsiConsole Console => _console.Value; |         public static IAnsiConsole Console => _recorder ?? _console.Value; | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Gets the console's capabilities. |         /// Gets the console's capabilities. | ||||||
|   | |||||||
| @@ -1,85 +0,0 @@ | |||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Globalization; |  | ||||||
| using System.Linq; |  | ||||||
| using Spectre.Console.Rendering; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a border. |  | ||||||
|     /// </summary> |  | ||||||
|     public abstract partial class Border |  | ||||||
|     { |  | ||||||
|         private readonly Dictionary<BorderPart, string> _lookup; |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Gets a value indicating whether or not the border is visible. |  | ||||||
|         /// </summary> |  | ||||||
|         public virtual bool Visible { get; } = true; |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Gets the safe border for this border or <c>null</c> if none exist. |  | ||||||
|         /// </summary> |  | ||||||
|         public virtual Border? SafeBorder { get; } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Initializes a new instance of the <see cref="Border"/> class. |  | ||||||
|         /// </summary> |  | ||||||
|         protected Border() |  | ||||||
|         { |  | ||||||
|             _lookup = Initialize(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private Dictionary<BorderPart, string> Initialize() |  | ||||||
|         { |  | ||||||
|             var lookup = new Dictionary<BorderPart, string>(); |  | ||||||
|             foreach (BorderPart? part in Enum.GetValues(typeof(BorderPart))) |  | ||||||
|             { |  | ||||||
|                 if (part == null) |  | ||||||
|                 { |  | ||||||
|                     continue; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 var text = GetBoxPart(part.Value); |  | ||||||
|                 if (text.Length > 1) |  | ||||||
|                 { |  | ||||||
|                     throw new InvalidOperationException("A box part cannot contain more than one character."); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 lookup.Add(part.Value, GetBoxPart(part.Value)); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             return lookup; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Gets the string representation of a specific border part. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="part">The part to get a string representation for.</param> |  | ||||||
|         /// <param name="count">The number of repetitions.</param> |  | ||||||
|         /// <returns>A string representation of the specified border part.</returns> |  | ||||||
|         public string GetPart(BorderPart part, int count) |  | ||||||
|         { |  | ||||||
|             // TODO: This need some optimization... |  | ||||||
|             return string.Join(string.Empty, Enumerable.Repeat(GetBoxPart(part)[0], count)); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Gets the string representation of a specific border part. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="part">The part to get a string representation for.</param> |  | ||||||
|         /// <returns>A string representation of the specified border part.</returns> |  | ||||||
|         public string GetPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return _lookup[part].ToString(CultureInfo.InvariantCulture); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Gets the character representing the specified border part. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <param name="part">The part to get the character representation for.</param> |  | ||||||
|         /// <returns>A character representation of the specified border part.</returns> |  | ||||||
|         protected abstract string GetBoxPart(BorderPart part); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents another old school ASCII border. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class Ascii2Border : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => "+", |  | ||||||
|                 BorderPart.HeaderTop => "-", |  | ||||||
|                 BorderPart.HeaderTopSeparator => "+", |  | ||||||
|                 BorderPart.HeaderTopRight => "+", |  | ||||||
|                 BorderPart.HeaderLeft => "|", |  | ||||||
|                 BorderPart.HeaderSeparator => "|", |  | ||||||
|                 BorderPart.HeaderRight => "|", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "|", |  | ||||||
|                 BorderPart.HeaderBottom => "-", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "+", |  | ||||||
|                 BorderPart.HeaderBottomRight => "|", |  | ||||||
|                 BorderPart.CellLeft => "|", |  | ||||||
|                 BorderPart.CellSeparator => "|", |  | ||||||
|                 BorderPart.CellRight => "|", |  | ||||||
|                 BorderPart.FooterBottomLeft => "+", |  | ||||||
|                 BorderPart.FooterBottom => "-", |  | ||||||
|                 BorderPart.FooterBottomSeparator => "+", |  | ||||||
|                 BorderPart.FooterBottomRight => "+", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents an old school ASCII border. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class AsciiBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => "+", |  | ||||||
|                 BorderPart.HeaderTop => "-", |  | ||||||
|                 BorderPart.HeaderTopSeparator => "-", |  | ||||||
|                 BorderPart.HeaderTopRight => "+", |  | ||||||
|                 BorderPart.HeaderLeft => "|", |  | ||||||
|                 BorderPart.HeaderSeparator => "|", |  | ||||||
|                 BorderPart.HeaderRight => "|", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "|", |  | ||||||
|                 BorderPart.HeaderBottom => "-", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "+", |  | ||||||
|                 BorderPart.HeaderBottomRight => "|", |  | ||||||
|                 BorderPart.CellLeft => "|", |  | ||||||
|                 BorderPart.CellSeparator => "|", |  | ||||||
|                 BorderPart.CellRight => "|", |  | ||||||
|                 BorderPart.FooterBottomLeft => "+", |  | ||||||
|                 BorderPart.FooterBottom => "-", |  | ||||||
|                 BorderPart.FooterBottomSeparator => "-", |  | ||||||
|                 BorderPart.FooterBottomRight => "+", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents an old school ASCII border with a double header border. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class AsciiDoubleHeadBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => "+", |  | ||||||
|                 BorderPart.HeaderTop => "-", |  | ||||||
|                 BorderPart.HeaderTopSeparator => "+", |  | ||||||
|                 BorderPart.HeaderTopRight => "+", |  | ||||||
|                 BorderPart.HeaderLeft => "|", |  | ||||||
|                 BorderPart.HeaderSeparator => "|", |  | ||||||
|                 BorderPart.HeaderRight => "|", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "|", |  | ||||||
|                 BorderPart.HeaderBottom => "=", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "+", |  | ||||||
|                 BorderPart.HeaderBottomRight => "|", |  | ||||||
|                 BorderPart.CellLeft => "|", |  | ||||||
|                 BorderPart.CellSeparator => "|", |  | ||||||
|                 BorderPart.CellRight => "|", |  | ||||||
|                 BorderPart.FooterBottomLeft => "+", |  | ||||||
|                 BorderPart.FooterBottom => "-", |  | ||||||
|                 BorderPart.FooterBottomSeparator => "+", |  | ||||||
|                 BorderPart.FooterBottomRight => "+", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a double border. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class DoubleBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => "╔", |  | ||||||
|                 BorderPart.HeaderTop => "═", |  | ||||||
|                 BorderPart.HeaderTopSeparator => "╦", |  | ||||||
|                 BorderPart.HeaderTopRight => "╗", |  | ||||||
|                 BorderPart.HeaderLeft => "║", |  | ||||||
|                 BorderPart.HeaderSeparator => "║", |  | ||||||
|                 BorderPart.HeaderRight => "║", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "╠", |  | ||||||
|                 BorderPart.HeaderBottom => "═", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "╬", |  | ||||||
|                 BorderPart.HeaderBottomRight => "╣", |  | ||||||
|                 BorderPart.CellLeft => "║", |  | ||||||
|                 BorderPart.CellSeparator => "║", |  | ||||||
|                 BorderPart.CellRight => "║", |  | ||||||
|                 BorderPart.FooterBottomLeft => "╚", |  | ||||||
|                 BorderPart.FooterBottom => "═", |  | ||||||
|                 BorderPart.FooterBottomSeparator => "╩", |  | ||||||
|                 BorderPart.FooterBottomRight => "╝", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a border with a double edge. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class DoubleEdgeBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => "╔", |  | ||||||
|                 BorderPart.HeaderTop => "═", |  | ||||||
|                 BorderPart.HeaderTopSeparator => "╤", |  | ||||||
|                 BorderPart.HeaderTopRight => "╗", |  | ||||||
|                 BorderPart.HeaderLeft => "║", |  | ||||||
|                 BorderPart.HeaderSeparator => "│", |  | ||||||
|                 BorderPart.HeaderRight => "║", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "╟", |  | ||||||
|                 BorderPart.HeaderBottom => "─", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "┼", |  | ||||||
|                 BorderPart.HeaderBottomRight => "╢", |  | ||||||
|                 BorderPart.CellLeft => "║", |  | ||||||
|                 BorderPart.CellSeparator => "│", |  | ||||||
|                 BorderPart.CellRight => "║", |  | ||||||
|                 BorderPart.FooterBottomLeft => "╚", |  | ||||||
|                 BorderPart.FooterBottom => "═", |  | ||||||
|                 BorderPart.FooterBottomSeparator => "╧", |  | ||||||
|                 BorderPart.FooterBottomRight => "╝", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,40 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a heavy border. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class HeavyBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public override Border? SafeBorder => Border.Square; |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => "┏", |  | ||||||
|                 BorderPart.HeaderTop => "━", |  | ||||||
|                 BorderPart.HeaderTopSeparator => "┳", |  | ||||||
|                 BorderPart.HeaderTopRight => "┓", |  | ||||||
|                 BorderPart.HeaderLeft => "┃", |  | ||||||
|                 BorderPart.HeaderSeparator => "┃", |  | ||||||
|                 BorderPart.HeaderRight => "┃", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "┣", |  | ||||||
|                 BorderPart.HeaderBottom => "━", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "╋", |  | ||||||
|                 BorderPart.HeaderBottomRight => "┫", |  | ||||||
|                 BorderPart.CellLeft => "┃", |  | ||||||
|                 BorderPart.CellSeparator => "┃", |  | ||||||
|                 BorderPart.CellRight => "┃", |  | ||||||
|                 BorderPart.FooterBottomLeft => "┗", |  | ||||||
|                 BorderPart.FooterBottom => "━", |  | ||||||
|                 BorderPart.FooterBottomSeparator => "┻", |  | ||||||
|                 BorderPart.FooterBottomRight => "┛", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,40 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a border with a heavy edge. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class HeavyEdgeBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public override Border? SafeBorder => Border.Square; |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => "┏", |  | ||||||
|                 BorderPart.HeaderTop => "━", |  | ||||||
|                 BorderPart.HeaderTopSeparator => "┯", |  | ||||||
|                 BorderPart.HeaderTopRight => "┓", |  | ||||||
|                 BorderPart.HeaderLeft => "┃", |  | ||||||
|                 BorderPart.HeaderSeparator => "│", |  | ||||||
|                 BorderPart.HeaderRight => "┃", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "┠", |  | ||||||
|                 BorderPart.HeaderBottom => "─", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "┼", |  | ||||||
|                 BorderPart.HeaderBottomRight => "┨", |  | ||||||
|                 BorderPart.CellLeft => "┃", |  | ||||||
|                 BorderPart.CellSeparator => "│", |  | ||||||
|                 BorderPart.CellRight => "┃", |  | ||||||
|                 BorderPart.FooterBottomLeft => "┗", |  | ||||||
|                 BorderPart.FooterBottom => "━", |  | ||||||
|                 BorderPart.FooterBottomSeparator => "┷", |  | ||||||
|                 BorderPart.FooterBottomRight => "┛", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,40 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a border with a heavy header. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class HeavyHeadBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public override Border? SafeBorder => Border.Square; |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => "┏", |  | ||||||
|                 BorderPart.HeaderTop => "━", |  | ||||||
|                 BorderPart.HeaderTopSeparator => "┳", |  | ||||||
|                 BorderPart.HeaderTopRight => "┓", |  | ||||||
|                 BorderPart.HeaderLeft => "┃", |  | ||||||
|                 BorderPart.HeaderSeparator => "┃", |  | ||||||
|                 BorderPart.HeaderRight => "┃", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "┡", |  | ||||||
|                 BorderPart.HeaderBottom => "━", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "╇", |  | ||||||
|                 BorderPart.HeaderBottomRight => "┩", |  | ||||||
|                 BorderPart.CellLeft => "│", |  | ||||||
|                 BorderPart.CellSeparator => "│", |  | ||||||
|                 BorderPart.CellRight => "│", |  | ||||||
|                 BorderPart.FooterBottomLeft => "└", |  | ||||||
|                 BorderPart.FooterBottom => "─", |  | ||||||
|                 BorderPart.FooterBottomSeparator => "┴", |  | ||||||
|                 BorderPart.FooterBottomRight => "┘", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a horizontal border. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class HorizontalBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => "─", |  | ||||||
|                 BorderPart.HeaderTop => "─", |  | ||||||
|                 BorderPart.HeaderTopSeparator => "─", |  | ||||||
|                 BorderPart.HeaderTopRight => "─", |  | ||||||
|                 BorderPart.HeaderLeft => " ", |  | ||||||
|                 BorderPart.HeaderSeparator => " ", |  | ||||||
|                 BorderPart.HeaderRight => " ", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "─", |  | ||||||
|                 BorderPart.HeaderBottom => "─", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "─", |  | ||||||
|                 BorderPart.HeaderBottomRight => "─", |  | ||||||
|                 BorderPart.CellLeft => " ", |  | ||||||
|                 BorderPart.CellSeparator => " ", |  | ||||||
|                 BorderPart.CellRight => " ", |  | ||||||
|                 BorderPart.FooterBottomLeft => "─", |  | ||||||
|                 BorderPart.FooterBottom => "─", |  | ||||||
|                 BorderPart.FooterBottomSeparator => "─", |  | ||||||
|                 BorderPart.FooterBottomRight => "─", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a minimal border. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class MinimalBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => " ", |  | ||||||
|                 BorderPart.HeaderTop => " ", |  | ||||||
|                 BorderPart.HeaderTopSeparator => " ", |  | ||||||
|                 BorderPart.HeaderTopRight => " ", |  | ||||||
|                 BorderPart.HeaderLeft => " ", |  | ||||||
|                 BorderPart.HeaderSeparator => "│", |  | ||||||
|                 BorderPart.HeaderRight => " ", |  | ||||||
|                 BorderPart.HeaderBottomLeft => " ", |  | ||||||
|                 BorderPart.HeaderBottom => "─", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "┼", |  | ||||||
|                 BorderPart.HeaderBottomRight => " ", |  | ||||||
|                 BorderPart.CellLeft => " ", |  | ||||||
|                 BorderPart.CellSeparator => "│", |  | ||||||
|                 BorderPart.CellRight => " ", |  | ||||||
|                 BorderPart.FooterBottomLeft => " ", |  | ||||||
|                 BorderPart.FooterBottom => " ", |  | ||||||
|                 BorderPart.FooterBottomSeparator => " ", |  | ||||||
|                 BorderPart.FooterBottomRight => " ", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a minimal border with a double header border. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class MinimalDoubleHeadBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => " ", |  | ||||||
|                 BorderPart.HeaderTop => " ", |  | ||||||
|                 BorderPart.HeaderTopSeparator => " ", |  | ||||||
|                 BorderPart.HeaderTopRight => " ", |  | ||||||
|                 BorderPart.HeaderLeft => " ", |  | ||||||
|                 BorderPart.HeaderSeparator => "│", |  | ||||||
|                 BorderPart.HeaderRight => " ", |  | ||||||
|                 BorderPart.HeaderBottomLeft => " ", |  | ||||||
|                 BorderPart.HeaderBottom => "═", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "╪", |  | ||||||
|                 BorderPart.HeaderBottomRight => " ", |  | ||||||
|                 BorderPart.CellLeft => " ", |  | ||||||
|                 BorderPart.CellSeparator => "│", |  | ||||||
|                 BorderPart.CellRight => " ", |  | ||||||
|                 BorderPart.FooterBottomLeft => " ", |  | ||||||
|                 BorderPart.FooterBottom => " ", |  | ||||||
|                 BorderPart.FooterBottomSeparator => " ", |  | ||||||
|                 BorderPart.FooterBottomRight => " ", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,40 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a minimal border with a heavy header. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class MinimalHeavyHeadBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public override Border? SafeBorder => Border.Minimal; |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => " ", |  | ||||||
|                 BorderPart.HeaderTop => " ", |  | ||||||
|                 BorderPart.HeaderTopSeparator => " ", |  | ||||||
|                 BorderPart.HeaderTopRight => " ", |  | ||||||
|                 BorderPart.HeaderLeft => " ", |  | ||||||
|                 BorderPart.HeaderSeparator => "│", |  | ||||||
|                 BorderPart.HeaderRight => " ", |  | ||||||
|                 BorderPart.HeaderBottomLeft => " ", |  | ||||||
|                 BorderPart.HeaderBottom => "━", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "┿", |  | ||||||
|                 BorderPart.HeaderBottomRight => " ", |  | ||||||
|                 BorderPart.CellLeft => " ", |  | ||||||
|                 BorderPart.CellSeparator => "│", |  | ||||||
|                 BorderPart.CellRight => " ", |  | ||||||
|                 BorderPart.FooterBottomLeft => " ", |  | ||||||
|                 BorderPart.FooterBottom => " ", |  | ||||||
|                 BorderPart.FooterBottomSeparator => " ", |  | ||||||
|                 BorderPart.FooterBottomRight => " ", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,40 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a rounded border. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class RoundedBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public override Border? SafeBorder { get; } = Border.Square; |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => "╭", |  | ||||||
|                 BorderPart.HeaderTop => "─", |  | ||||||
|                 BorderPart.HeaderTopSeparator => "┬", |  | ||||||
|                 BorderPart.HeaderTopRight => "╮", |  | ||||||
|                 BorderPart.HeaderLeft => "│", |  | ||||||
|                 BorderPart.HeaderSeparator => "│", |  | ||||||
|                 BorderPart.HeaderRight => "│", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "├", |  | ||||||
|                 BorderPart.HeaderBottom => "─", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "┼", |  | ||||||
|                 BorderPart.HeaderBottomRight => "┤", |  | ||||||
|                 BorderPart.CellLeft => "│", |  | ||||||
|                 BorderPart.CellSeparator => "│", |  | ||||||
|                 BorderPart.CellRight => "│", |  | ||||||
|                 BorderPart.FooterBottomLeft => "╰", |  | ||||||
|                 BorderPart.FooterBottom => "─", |  | ||||||
|                 BorderPart.FooterBottomSeparator => "┴", |  | ||||||
|                 BorderPart.FooterBottomRight => "╯", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a simple border. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class SimpleBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => " ", |  | ||||||
|                 BorderPart.HeaderTop => " ", |  | ||||||
|                 BorderPart.HeaderTopSeparator => " ", |  | ||||||
|                 BorderPart.HeaderTopRight => " ", |  | ||||||
|                 BorderPart.HeaderLeft => " ", |  | ||||||
|                 BorderPart.HeaderSeparator => " ", |  | ||||||
|                 BorderPart.HeaderRight => " ", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "─", |  | ||||||
|                 BorderPart.HeaderBottom => "─", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "─", |  | ||||||
|                 BorderPart.HeaderBottomRight => "─", |  | ||||||
|                 BorderPart.CellLeft => " ", |  | ||||||
|                 BorderPart.CellSeparator => " ", |  | ||||||
|                 BorderPart.CellRight => " ", |  | ||||||
|                 BorderPart.FooterBottomLeft => " ", |  | ||||||
|                 BorderPart.FooterBottom => " ", |  | ||||||
|                 BorderPart.FooterBottomSeparator => " ", |  | ||||||
|                 BorderPart.FooterBottomRight => " ", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,40 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a simple border with heavy lines. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class SimpleHeavyBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         public override Border? SafeBorder => Border.Simple; |  | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => " ", |  | ||||||
|                 BorderPart.HeaderTop => " ", |  | ||||||
|                 BorderPart.HeaderTopSeparator => " ", |  | ||||||
|                 BorderPart.HeaderTopRight => " ", |  | ||||||
|                 BorderPart.HeaderLeft => " ", |  | ||||||
|                 BorderPart.HeaderSeparator => " ", |  | ||||||
|                 BorderPart.HeaderRight => " ", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "━", |  | ||||||
|                 BorderPart.HeaderBottom => "━", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "━", |  | ||||||
|                 BorderPart.HeaderBottomRight => "━", |  | ||||||
|                 BorderPart.CellLeft => " ", |  | ||||||
|                 BorderPart.CellSeparator => " ", |  | ||||||
|                 BorderPart.CellRight => " ", |  | ||||||
|                 BorderPart.FooterBottomLeft => " ", |  | ||||||
|                 BorderPart.FooterBottom => " ", |  | ||||||
|                 BorderPart.FooterBottomSeparator => " ", |  | ||||||
|                 BorderPart.FooterBottomRight => " ", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| using System; |  | ||||||
|  |  | ||||||
| namespace Spectre.Console.Rendering |  | ||||||
| { |  | ||||||
|     /// <summary> |  | ||||||
|     /// Represents a square border. |  | ||||||
|     /// </summary> |  | ||||||
|     public sealed class SquareBorder : Border |  | ||||||
|     { |  | ||||||
|         /// <inheritdoc/> |  | ||||||
|         protected override string GetBoxPart(BorderPart part) |  | ||||||
|         { |  | ||||||
|             return part switch |  | ||||||
|             { |  | ||||||
|                 BorderPart.HeaderTopLeft => "┌", |  | ||||||
|                 BorderPart.HeaderTop => "─", |  | ||||||
|                 BorderPart.HeaderTopSeparator => "┬", |  | ||||||
|                 BorderPart.HeaderTopRight => "┐", |  | ||||||
|                 BorderPart.HeaderLeft => "│", |  | ||||||
|                 BorderPart.HeaderSeparator => "│", |  | ||||||
|                 BorderPart.HeaderRight => "│", |  | ||||||
|                 BorderPart.HeaderBottomLeft => "├", |  | ||||||
|                 BorderPart.HeaderBottom => "─", |  | ||||||
|                 BorderPart.HeaderBottomSeparator => "┼", |  | ||||||
|                 BorderPart.HeaderBottomRight => "┤", |  | ||||||
|                 BorderPart.CellLeft => "│", |  | ||||||
|                 BorderPart.CellSeparator => "│", |  | ||||||
|                 BorderPart.CellRight => "│", |  | ||||||
|                 BorderPart.FooterBottomLeft => "└", |  | ||||||
|                 BorderPart.FooterBottom => "─", |  | ||||||
|                 BorderPart.FooterBottomSeparator => "┴", |  | ||||||
|                 BorderPart.FooterBottomRight => "┘", |  | ||||||
|                 _ => throw new InvalidOperationException("Unknown box part."), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
							
								
								
									
										42
									
								
								src/Spectre.Console/BoxBorder.Known.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/Spectre.Console/BoxBorder.Known.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | using System.Diagnostics.CodeAnalysis; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Represents a border. | ||||||
|  |     /// </summary> | ||||||
|  |     public abstract partial class BoxBorder | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets an invisible border. | ||||||
|  |         /// </summary> | ||||||
|  |         public static BoxBorder None { get; } = new NoBoxBorder(); | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets an ASCII border. | ||||||
|  |         /// </summary> | ||||||
|  |         public static BoxBorder Ascii { get; } = new AsciiBoxBorder(); | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets a double border. | ||||||
|  |         /// </summary> | ||||||
|  |         [SuppressMessage("Naming", "CA1720:Identifier contains type name")] | ||||||
|  |         public static BoxBorder Double { get; } = new DoubleBoxBorder(); | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets a heavy border. | ||||||
|  |         /// </summary> | ||||||
|  |         public static BoxBorder Heavy { get; } = new HeavyBoxBorder(); | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets a rounded border. | ||||||
|  |         /// </summary> | ||||||
|  |         public static BoxBorder Rounded { get; } = new RoundedBoxBorder(); | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets a square border. | ||||||
|  |         /// </summary> | ||||||
|  |         public static BoxBorder Square { get; } = new SquareBoxBorder(); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								src/Spectre.Console/BoxBorder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/Spectre.Console/BoxBorder.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Represents a border. | ||||||
|  |     /// </summary> | ||||||
|  |     public abstract partial class BoxBorder | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets the safe border for this border or <c>null</c> if none exist. | ||||||
|  |         /// </summary> | ||||||
|  |         public virtual BoxBorder? SafeBorder { get; } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets the string representation of the specified border part. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="part">The part to get the character representation for.</param> | ||||||
|  |         /// <returns>A character representation of the specified border part.</returns> | ||||||
|  |         public abstract string GetPart(BoxBorderPart part); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -60,6 +60,35 @@ namespace Spectre.Console | |||||||
|             Number = null; |             Number = null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Blends two colors. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="other">The other color.</param> | ||||||
|  |         /// <param name="factor">The blend factor.</param> | ||||||
|  |         /// <returns>The resulting color.</returns> | ||||||
|  |         public Color Blend(Color other, float factor) | ||||||
|  |         { | ||||||
|  |             // https://github.com/willmcgugan/rich/blob/f092b1d04252e6f6812021c0f415dd1d7be6a16a/rich/color.py#L494 | ||||||
|  |             return new Color( | ||||||
|  |                 (byte)(R + ((other.R - R) * factor)), | ||||||
|  |                 (byte)(G + ((other.G - G) * factor)), | ||||||
|  |                 (byte)(B + ((other.B - B) * factor))); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets the hexadecimal representation of the color. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns>The hexadecimal representation of the color.</returns> | ||||||
|  |         public string ToHex() | ||||||
|  |         { | ||||||
|  |             return string.Format( | ||||||
|  |                 CultureInfo.InvariantCulture, | ||||||
|  |                 "{0}{1}{2}", | ||||||
|  |                 R.ToString("X2", CultureInfo.InvariantCulture), | ||||||
|  |                 G.ToString("X2", CultureInfo.InvariantCulture), | ||||||
|  |                 B.ToString("X2", CultureInfo.InvariantCulture)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public override int GetHashCode() |         public override int GetHashCode() | ||||||
|         { |         { | ||||||
| @@ -216,9 +245,32 @@ namespace Spectre.Console | |||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Converts the color to a markup string. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns>A <see cref="string"/> representing the color as markup.</returns> | ||||||
|  |         public string ToMarkupString() | ||||||
|  |         { | ||||||
|  |             if (Number != null) | ||||||
|  |             { | ||||||
|  |                 var name = ColorTable.GetName(Number.Value); | ||||||
|  |                 if (!string.IsNullOrWhiteSpace(name)) | ||||||
|  |                 { | ||||||
|  |                     return name; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return string.Format(CultureInfo.InvariantCulture, "#{0:X2}{1:X2}{2:X2}", R, G, B); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         /// <inheritdoc/> |         /// <inheritdoc/> | ||||||
|         public override string ToString() |         public override string ToString() | ||||||
|         { |         { | ||||||
|  |             if (IsDefault) | ||||||
|  |             { | ||||||
|  |                 return "default"; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             if (Number != null) |             if (Number != null) | ||||||
|             { |             { | ||||||
|                 var name = ColorTable.GetName(Number.Value); |                 var name = ColorTable.GetName(Number.Value); | ||||||
|   | |||||||
| @@ -16,7 +16,17 @@ namespace Spectre.Console | |||||||
|         /// <returns>A string with emoji codes replaced with actual emoji.</returns> |         /// <returns>A string with emoji codes replaced with actual emoji.</returns> | ||||||
|         public static string Replace(string value) |         public static string Replace(string value) | ||||||
|         { |         { | ||||||
|             static string ReplaceEmoji(Match match) => _emojis[match.Groups[2].Value]; |             static string ReplaceEmoji(Match match) | ||||||
|  |             { | ||||||
|  |                 var key = match.Groups[2].Value; | ||||||
|  |                 if (_emojis.TryGetValue(key, out var emoji)) | ||||||
|  |                 { | ||||||
|  |                     return emoji; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 return match.Value; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             return _emojiCode.Replace(value, ReplaceEmoji); |             return _emojiCode.Replace(value, ReplaceEmoji); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
							
								
								
									
										41
									
								
								src/Spectre.Console/ExceptionFormat.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/Spectre.Console/ExceptionFormat.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | using System; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Represents how an exception is formatted. | ||||||
|  |     /// </summary> | ||||||
|  |     [Flags] | ||||||
|  |     public enum ExceptionFormats | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// The default formatting. | ||||||
|  |         /// </summary> | ||||||
|  |         None = 0, | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Whether or not paths should be shortened. | ||||||
|  |         /// </summary> | ||||||
|  |         ShortenPaths = 1, | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Whether or not types should be shortened. | ||||||
|  |         /// </summary> | ||||||
|  |         ShortenTypes = 2, | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Whether or not methods should be shortened. | ||||||
|  |         /// </summary> | ||||||
|  |         ShortenMethods = 4, | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Whether or not to show paths as links in the terminal. | ||||||
|  |         /// </summary> | ||||||
|  |         ShowLinks = 8, | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Shortens everything that can be shortened. | ||||||
|  |         /// </summary> | ||||||
|  |         ShortenEverything = ShortenMethods | ShortenTypes | ShortenPaths, | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,21 @@ | |||||||
|  | using System; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Contains extension methods for <see cref="IAnsiConsole"/>. | ||||||
|  |     /// </summary> | ||||||
|  |     public static partial class AnsiConsoleExtensions | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Writes an exception to the console. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="console">The console.</param> | ||||||
|  |         /// <param name="exception">The exception to write to the console.</param> | ||||||
|  |         /// <param name="format">The exception format options.</param> | ||||||
|  |         public static void WriteException(this IAnsiConsole console, Exception exception, ExceptionFormats format = ExceptionFormats.None) | ||||||
|  |         { | ||||||
|  |             Render(console, exception.GetRenderable(format)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -27,10 +27,9 @@ namespace Spectre.Console | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             var options = new RenderContext(console.Encoding, console.Capabilities.LegacyConsole); |             var options = new RenderContext(console.Encoding, console.Capabilities.LegacyConsole); | ||||||
|             var segments = renderable.Render(options, console.Width).Where(x => !(x.Text.Length == 0 && !x.IsLineBreak)).ToArray(); |             var segments = renderable.Render(options, console.Width).ToArray(); | ||||||
|             segments = Segment.Merge(segments).ToArray(); |             segments = Segment.Merge(segments).ToArray(); | ||||||
|  |  | ||||||
|             var current = Style.Plain; |  | ||||||
|             foreach (var segment in segments) |             foreach (var segment in segments) | ||||||
|             { |             { | ||||||
|                 if (string.IsNullOrEmpty(segment.Text)) |                 if (string.IsNullOrEmpty(segment.Text)) | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| using System; | using System; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
| namespace Spectre.Console | namespace Spectre.Console | ||||||
| { | { | ||||||
| @@ -7,6 +8,32 @@ namespace Spectre.Console | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     public static partial class AnsiConsoleExtensions |     public static partial class AnsiConsoleExtensions | ||||||
|     { |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Creates a recorder for the specified console. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="console">The console to record.</param> | ||||||
|  |         /// <returns>A recorder for the specified console.</returns> | ||||||
|  |         public static Recorder CreateRecorder(this IAnsiConsole console) | ||||||
|  |         { | ||||||
|  |             return new Recorder(console); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Writes the specified string value to the console. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="console">The console to write to.</param> | ||||||
|  |         /// <param name="text">The text to write.</param> | ||||||
|  |         /// <param name="style">The text style.</param> | ||||||
|  |         public static void Write(this IAnsiConsole console, string text, Style style) | ||||||
|  |         { | ||||||
|  |             if (console is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(console)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             console.Write(new Segment(text, style)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Writes an empty line to the console. |         /// Writes an empty line to the console. | ||||||
|         /// </summary> |         /// </summary> | ||||||
| @@ -34,7 +61,7 @@ namespace Spectre.Console | |||||||
|                 throw new ArgumentNullException(nameof(console)); |                 throw new ArgumentNullException(nameof(console)); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             console.Write(text, style); |             console.Write(new Segment(text, style)); | ||||||
|             console.WriteLine(); |             console.WriteLine(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ using System; | |||||||
| namespace Spectre.Console.Rendering | namespace Spectre.Console.Rendering | ||||||
| { | { | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// Contains extension methods for <see cref="Border"/>. |     /// Contains extension methods for <see cref="TableBorder"/>. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public static class BorderExtensions |     public static class BorderExtensions | ||||||
|     { |     { | ||||||
| @@ -13,7 +13,7 @@ namespace Spectre.Console.Rendering | |||||||
|         /// <param name="border">The border to get the safe border for.</param> |         /// <param name="border">The border to get the safe border for.</param> | ||||||
|         /// <param name="safe">Whether or not to return the safe border.</param> |         /// <param name="safe">Whether or not to return the safe border.</param> | ||||||
|         /// <returns>The safe border if one exist, otherwise the original border.</returns> |         /// <returns>The safe border if one exist, otherwise the original border.</returns> | ||||||
|         public static Border GetSafeBorder(this Border border, bool safe) |         public static TableBorder GetSafeBorder(this TableBorder border, bool safe) | ||||||
|         { |         { | ||||||
|             if (border is null) |             if (border is null) | ||||||
|             { |             { | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								src/Spectre.Console/Extensions/BoxExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/Spectre.Console/Extensions/BoxExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | using System; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console.Rendering | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Contains extension methods for <see cref="BoxBorder"/>. | ||||||
|  |     /// </summary> | ||||||
|  |     public static class BoxExtensions | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets the safe border for a border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="border">The border to get the safe border for.</param> | ||||||
|  |         /// <param name="safe">Whether or not to return the safe border.</param> | ||||||
|  |         /// <returns>The safe border if one exist, otherwise the original border.</returns> | ||||||
|  |         public static BoxBorder GetSafeBorder(this BoxBorder border, bool safe) | ||||||
|  |         { | ||||||
|  |             if (border is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(border)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (safe && border.SafeBorder != null) | ||||||
|  |             { | ||||||
|  |                 border = border.SafeBorder; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return border; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								src/Spectre.Console/Extensions/ExceptionExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/Spectre.Console/Extensions/ExceptionExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | using System; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Contains extension methods for <see cref="Exception"/>. | ||||||
|  |     /// </summary> | ||||||
|  |     public static class ExceptionExtensions | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets a <see cref="IRenderable"/> representation of the exception. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="exception">The exception to format.</param> | ||||||
|  |         /// <param name="format">The exception format options.</param> | ||||||
|  |         /// <returns>A <see cref="IRenderable"/> representing the exception.</returns> | ||||||
|  |         public static IRenderable GetRenderable(this Exception exception, ExceptionFormats format = ExceptionFormats.None) | ||||||
|  |         { | ||||||
|  |             return ExceptionFormatter.Format(exception, format); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -7,229 +7,6 @@ namespace Spectre.Console | |||||||
|     /// </summary> |     /// </summary> | ||||||
|     public static class HasBorderExtensions |     public static class HasBorderExtensions | ||||||
|     { |     { | ||||||
|         /// <summary> |  | ||||||
|         /// Do not display a border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T NoBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.None); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a square border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T SquareBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.Square); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display an ASCII border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T AsciiBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.Ascii); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display another ASCII border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T Ascii2Border<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.Ascii2); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display an ASCII border with a double header border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T AsciiDoubleHeadBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.AsciiDoubleHead); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a rounded border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T RoundedBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.Rounded); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a minimal border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T MinimalBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.Minimal); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a minimal border with a heavy head. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T MinimalHeavyHeadBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.MinimalHeavyHead); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a minimal border with a double header border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T MinimalDoubleHeadBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.MinimalDoubleHead); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a simple border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T SimpleBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.Simple); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a simple border with heavy lines. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T SimpleHeavyBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.SimpleHeavy); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a simple border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T HorizontalBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.Horizontal); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a heavy border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T HeavyBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.Heavy); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a border with a heavy edge. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T HeavyEdgeBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.HeavyEdge); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a border with a heavy header. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T HeavyHeadBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.HeavyHead); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a double border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T DoubleBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.Double); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Display a border with a double edge. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T DoubleEdgeBorder<T>(this T obj) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             return SetBorder(obj, Border.DoubleEdge); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Sets the border. |  | ||||||
|         /// </summary> |  | ||||||
|         /// <typeparam name="T">An object type with a border.</typeparam> |  | ||||||
|         /// <param name="obj">The object to set the border for.</param> |  | ||||||
|         /// <param name="border">The border to use.</param> |  | ||||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> |  | ||||||
|         public static T SetBorder<T>(this T obj, Border border) |  | ||||||
|             where T : class, IHasBorder |  | ||||||
|         { |  | ||||||
|             if (obj is null) |  | ||||||
|             { |  | ||||||
|                 throw new ArgumentNullException(nameof(obj)); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             obj.Border = border; |  | ||||||
|             return obj; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Disables the safe border. |         /// Disables the safe border. | ||||||
|         /// </summary> |         /// </summary> | ||||||
|   | |||||||
							
								
								
									
										101
									
								
								src/Spectre.Console/Extensions/HasBoxBorderExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								src/Spectre.Console/Extensions/HasBoxBorderExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | |||||||
|  | using System; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Contains extension methods for <see cref="IHasBoxBorder"/>. | ||||||
|  |     /// </summary> | ||||||
|  |     public static class HasBoxBorderExtensions | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Do not display a border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T NoBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasBoxBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, BoxBorder.None); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a square border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T SquareBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasBoxBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, BoxBorder.Square); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display an ASCII border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T AsciiBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasBoxBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, BoxBorder.Ascii); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a rounded border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T RoundedBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasBoxBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, BoxBorder.Rounded); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a heavy border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T HeavyBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasBoxBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, BoxBorder.Heavy); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a double border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T DoubleBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasBoxBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, BoxBorder.Double); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Sets the border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <param name="border">The border to use.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T SetBorder<T>(this T obj, BoxBorder border) | ||||||
|  |             where T : class, IHasBoxBorder | ||||||
|  |         { | ||||||
|  |             if (obj is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(obj)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             obj.Border = border; | ||||||
|  |             return obj; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										245
									
								
								src/Spectre.Console/Extensions/HasTableBorderExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								src/Spectre.Console/Extensions/HasTableBorderExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,245 @@ | |||||||
|  | using System; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Contains extension methods for <see cref="IHasTableBorder"/>. | ||||||
|  |     /// </summary> | ||||||
|  |     public static class HasTableBorderExtensions | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Do not display a border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T NoBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.None); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a square border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T SquareBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.Square); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display an ASCII border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T AsciiBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.Ascii); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display another ASCII border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T Ascii2Border<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.Ascii2); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display an ASCII border with a double header border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T AsciiDoubleHeadBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.AsciiDoubleHead); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a rounded border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T RoundedBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.Rounded); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a minimal border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T MinimalBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.Minimal); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a minimal border with a heavy head. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T MinimalHeavyHeadBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.MinimalHeavyHead); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a minimal border with a double header border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T MinimalDoubleHeadBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.MinimalDoubleHead); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a simple border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T SimpleBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.Simple); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a simple border with heavy lines. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T SimpleHeavyBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.SimpleHeavy); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a simple border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T HorizontalBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.Horizontal); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a heavy border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T HeavyBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.Heavy); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a border with a heavy edge. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T HeavyEdgeBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.HeavyEdge); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a border with a heavy header. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T HeavyHeadBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.HeavyHead); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a double border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T DoubleBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.Double); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a border with a double edge. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T DoubleEdgeBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.DoubleEdge); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Display a markdown border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T MarkdownBorder<T>(this T obj) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             return SetBorder(obj, TableBorder.Markdown); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Sets the border. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <typeparam name="T">An object type with a border.</typeparam> | ||||||
|  |         /// <param name="obj">The object to set the border for.</param> | ||||||
|  |         /// <param name="border">The border to use.</param> | ||||||
|  |         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||||
|  |         public static T SetBorder<T>(this T obj, TableBorder border) | ||||||
|  |             where T : class, IHasTableBorder | ||||||
|  |         { | ||||||
|  |             if (obj is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(obj)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             obj.Border = border; | ||||||
|  |             return obj; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										44
									
								
								src/Spectre.Console/Extensions/RecorderExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/Spectre.Console/Extensions/RecorderExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | using System; | ||||||
|  | using Spectre.Console.Internal; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Contains extension methods for <see cref="Recorder"/>. | ||||||
|  |     /// </summary> | ||||||
|  |     public static class RecorderExtensions | ||||||
|  |     { | ||||||
|  |         private static readonly TextEncoder _textEncoder = new TextEncoder(); | ||||||
|  |         private static readonly HtmlEncoder _htmlEncoder = new HtmlEncoder(); | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Exports the recorded content as text. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="recorder">The recorder.</param> | ||||||
|  |         /// <returns>The recorded content as text.</returns> | ||||||
|  |         public static string ExportText(this Recorder recorder) | ||||||
|  |         { | ||||||
|  |             if (recorder is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(recorder)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return recorder.Export(_textEncoder); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /// <summary> | ||||||
|  |         /// Exports the recorded content as HTML. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="recorder">The recorder.</param> | ||||||
|  |         /// <returns>The recorded content as HTML.</returns> | ||||||
|  |         public static string ExportHtml(this Recorder recorder) | ||||||
|  |         { | ||||||
|  |             if (recorder is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(recorder)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return recorder.Export(_htmlEncoder); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								src/Spectre.Console/Extensions/StringExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/Spectre.Console/Extensions/StringExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Contains extension methods for <see cref="string"/>. | ||||||
|  |     /// </summary> | ||||||
|  |     public static class StringExtensions | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Converts the string to something that is safe to | ||||||
|  |         /// use in a markup string. | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="text">The text to convert.</param> | ||||||
|  |         /// <returns>A string that is safe to use in a markup string.</returns> | ||||||
|  |         public static string SafeMarkup(this string text) | ||||||
|  |         { | ||||||
|  |             if (text == null) | ||||||
|  |             { | ||||||
|  |                 return string.Empty; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return text | ||||||
|  |                 .Replace("[", "[[") | ||||||
|  |                 .Replace("]", "]]"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,4 +1,5 @@ | |||||||
| using System.Text; | using System.Text; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
| namespace Spectre.Console | namespace Spectre.Console | ||||||
| { | { | ||||||
| @@ -30,8 +31,7 @@ namespace Spectre.Console | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Writes a string followed by a line terminator to the console. |         /// Writes a string followed by a line terminator to the console. | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="text">The string to write.</param> |         /// <param name="segment">The segment to write.</param> | ||||||
|         /// <param name="style">The style to use.</param> |         void Write(Segment segment); | ||||||
|         void Write(string text, Style style); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -13,12 +13,7 @@ namespace Spectre.Console | |||||||
|         bool UseSafeBorder { get; set; } |         bool UseSafeBorder { get; set; } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Gets or sets the border. |         /// Gets or sets the box style. | ||||||
|         /// </summary> |  | ||||||
|         public Border Border { get; set; } |  | ||||||
|  |  | ||||||
|         /// <summary> |  | ||||||
|         /// Gets or sets the border style. |  | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         public Style? BorderStyle { get; set; } |         public Style? BorderStyle { get; set; } | ||||||
|     } |     } | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								src/Spectre.Console/IHasBoxBorder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/Spectre.Console/IHasBoxBorder.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Represents something that has a box border. | ||||||
|  |     /// </summary> | ||||||
|  |     public interface IHasBoxBorder : IHasBorder | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets or sets the box. | ||||||
|  |         /// </summary> | ||||||
|  |         public BoxBorder Border { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								src/Spectre.Console/IHasTableBorder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/Spectre.Console/IHasTableBorder.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     /// Represents something that has a border. | ||||||
|  |     /// </summary> | ||||||
|  |     public interface IHasTableBorder : IHasBorder | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// Gets or sets the border. | ||||||
|  |         /// </summary> | ||||||
|  |         public TableBorder Border { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,6 +1,7 @@ | |||||||
| using System; | using System; | ||||||
| using System.IO; | using System.IO; | ||||||
| using System.Text; | using System.Text; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
| namespace Spectre.Console.Internal | namespace Spectre.Console.Internal | ||||||
| { | { | ||||||
| @@ -48,21 +49,14 @@ namespace Spectre.Console.Internal | |||||||
|             _ansiBuilder = new AnsiBuilder(Capabilities, linkHasher); |             _ansiBuilder = new AnsiBuilder(Capabilities, linkHasher); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void Write(string text, Style style) |         public void Write(Segment segment) | ||||||
|         { |         { | ||||||
|             if (string.IsNullOrEmpty(text)) |             var parts = segment.Text.NormalizeLineEndings().Split(new[] { '\n' }); | ||||||
|             { |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             style ??= Style.Plain; |  | ||||||
|  |  | ||||||
|             var parts = text.NormalizeLineEndings().Split(new[] { '\n' }); |  | ||||||
|             foreach (var (_, _, last, part) in parts.Enumerate()) |             foreach (var (_, _, last, part) in parts.Enumerate()) | ||||||
|             { |             { | ||||||
|                 if (!string.IsNullOrEmpty(part)) |                 if (!string.IsNullOrEmpty(part)) | ||||||
|                 { |                 { | ||||||
|                     _out.Write(_ansiBuilder.GetAnsi(part, style)); |                     _out.Write(_ansiBuilder.GetAnsi(part, segment.Style)); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (!last) |                 if (!last) | ||||||
|   | |||||||
							
								
								
									
										159
									
								
								src/Spectre.Console/Internal/ExceptionFormatter.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								src/Spectre.Console/Internal/ExceptionFormatter.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | |||||||
|  | using System; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using Spectre.Console.Internal; | ||||||
|  | using Spectre.Console.Rendering; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console | ||||||
|  | { | ||||||
|  |     internal static class ExceptionFormatter | ||||||
|  |     { | ||||||
|  |         private static readonly Color _typeColor = Color.White; | ||||||
|  |         private static readonly Color _methodColor = Color.Yellow; | ||||||
|  |         private static readonly Color _parameterColor = Color.Blue; | ||||||
|  |         private static readonly Color _pathColor = Color.Yellow; | ||||||
|  |         private static readonly Color _dimmedColor = Color.Grey; | ||||||
|  |  | ||||||
|  |         public static IRenderable Format(Exception exception, ExceptionFormats format) | ||||||
|  |         { | ||||||
|  |             if (exception is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(exception)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var info = ExceptionParser.Parse(exception.ToString()); | ||||||
|  |             if (info == null) | ||||||
|  |             { | ||||||
|  |                 return new Text(exception.ToString()); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return GetException(info, format); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static IRenderable GetException(ExceptionInfo info, ExceptionFormats format) | ||||||
|  |         { | ||||||
|  |             if (info is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(info)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return new Rows(new IRenderable[] | ||||||
|  |             { | ||||||
|  |                 GetMessage(info, format), | ||||||
|  |                 GetStackFrames(info, format), | ||||||
|  |             }).Expand(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static Markup GetMessage(ExceptionInfo ex, ExceptionFormats format) | ||||||
|  |         { | ||||||
|  |             var shortenTypes = (format & ExceptionFormats.ShortenTypes) != 0; | ||||||
|  |             var type = Emphasize(ex.Type, new[] { '.' }, _typeColor.ToMarkupString(), shortenTypes); | ||||||
|  |             var message = $"[b red]{ex.Message.SafeMarkup()}[/]"; | ||||||
|  |             return new Markup(string.Concat(type, ": ", message)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static Grid GetStackFrames(ExceptionInfo ex, ExceptionFormats format) | ||||||
|  |         { | ||||||
|  |             var grid = new Grid(); | ||||||
|  |             grid.AddColumn(new GridColumn().PadLeft(2).PadRight(0).NoWrap()); | ||||||
|  |             grid.AddColumn(new GridColumn().PadLeft(1).PadRight(0)); | ||||||
|  |  | ||||||
|  |             // Inner | ||||||
|  |             if (ex.Inner != null) | ||||||
|  |             { | ||||||
|  |                 grid.AddRow( | ||||||
|  |                     Text.Empty, | ||||||
|  |                     GetException(ex.Inner, format)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // Stack frames | ||||||
|  |             foreach (var frame in ex.Frames) | ||||||
|  |             { | ||||||
|  |                 var builder = new StringBuilder(); | ||||||
|  |  | ||||||
|  |                 // Method | ||||||
|  |                 var shortenMethods = (format & ExceptionFormats.ShortenMethods) != 0; | ||||||
|  |                 builder.Append(Emphasize(frame.Method, new[] { '.' }, _methodColor.ToMarkupString(), shortenMethods)); | ||||||
|  |                 builder.Append('('); | ||||||
|  |                 builder.Append(string.Join(", ", frame.Parameters.Select(x => $"[{_parameterColor.ToMarkupString()}]{x.Type.SafeMarkup()}[/] {x.Name}"))); | ||||||
|  |                 builder.Append(')'); | ||||||
|  |  | ||||||
|  |                 if (frame.Path != null) | ||||||
|  |                 { | ||||||
|  |                     builder.Append(" [").Append(_dimmedColor.ToMarkupString()).Append("]in[/] "); | ||||||
|  |  | ||||||
|  |                     // Path | ||||||
|  |                     AppendPath(builder, frame, format); | ||||||
|  |  | ||||||
|  |                     // Line number | ||||||
|  |                     if (frame.LineNumber != null) | ||||||
|  |                     { | ||||||
|  |                         builder.Append(':'); | ||||||
|  |                         builder.Append('[').Append(_parameterColor.ToMarkupString()).Append(']').Append(frame.LineNumber).Append("[/]"); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 grid.AddRow($"[{_dimmedColor.ToMarkupString()}]at[/]", builder.ToString()); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return grid; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static void AppendPath(StringBuilder builder, StackFrameInfo frame, ExceptionFormats format) | ||||||
|  |         { | ||||||
|  |             if (frame?.Path is null) | ||||||
|  |             { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             void RenderLink() | ||||||
|  |             { | ||||||
|  |                 var shortenPaths = (format & ExceptionFormats.ShortenPaths) != 0; | ||||||
|  |                 builder.Append(Emphasize(frame.Path, new[] { '/', '\\' }, $"b {_pathColor.ToMarkupString()}", shortenPaths)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if ((format & ExceptionFormats.ShowLinks) != 0) | ||||||
|  |             { | ||||||
|  |                 var hasLink = frame.TryGetUri(out var uri); | ||||||
|  |                 if (hasLink && uri != null) | ||||||
|  |                 { | ||||||
|  |                     builder.Append("[link=").Append(uri.AbsoluteUri).Append(']'); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 RenderLink(); | ||||||
|  |  | ||||||
|  |                 if (hasLink && uri != null) | ||||||
|  |                 { | ||||||
|  |                     builder.Append("[/]"); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 RenderLink(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static string Emphasize(string input, char[] separators, string color, bool compact) | ||||||
|  |         { | ||||||
|  |             var builder = new StringBuilder(); | ||||||
|  |  | ||||||
|  |             var type = input; | ||||||
|  |             var index = type.LastIndexOfAny(separators); | ||||||
|  |             if (index != -1) | ||||||
|  |             { | ||||||
|  |                 if (!compact) | ||||||
|  |                 { | ||||||
|  |                     builder.Append("[silver]").Append(type, 0, index + 1).Append("[/]"); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 builder.Append('[').Append(color).Append(']').Append(type, index + 1, type.Length - index - 1).Append("[/]"); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 builder.Append(type); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return builder.ToString(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										23
									
								
								src/Spectre.Console/Internal/ExceptionInfo.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/Spectre.Console/Internal/ExceptionInfo.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | using System.Collections.Generic; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console.Internal | ||||||
|  | { | ||||||
|  |     internal sealed class ExceptionInfo | ||||||
|  |     { | ||||||
|  |         public string Type { get; } | ||||||
|  |         public string Message { get; } | ||||||
|  |         public List<StackFrameInfo> Frames { get; } | ||||||
|  |         public ExceptionInfo? Inner { get; } | ||||||
|  |  | ||||||
|  |         public ExceptionInfo( | ||||||
|  |             string type, string message, | ||||||
|  |             List<StackFrameInfo> frames, | ||||||
|  |             ExceptionInfo? inner) | ||||||
|  |         { | ||||||
|  |             Type = type ?? string.Empty; | ||||||
|  |             Message = message ?? string.Empty; | ||||||
|  |             Frames = frames ?? new List<StackFrameInfo>(); | ||||||
|  |             Inner = inner; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										142
									
								
								src/Spectre.Console/Internal/ExceptionParser.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								src/Spectre.Console/Internal/ExceptionParser.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Globalization; | ||||||
|  | using System.Text.RegularExpressions; | ||||||
|  |  | ||||||
|  | namespace Spectre.Console.Internal | ||||||
|  | { | ||||||
|  |     internal static class ExceptionParser | ||||||
|  |     { | ||||||
|  |         private static readonly Regex _messageRegex = new Regex(@"^(?'type'.*):\s(?'message'.*)$"); | ||||||
|  |         private static readonly Regex _stackFrameRegex = new Regex(@"^\s*\w*\s(?'method'.*)\((?'params'.*)\)"); | ||||||
|  |         private static readonly Regex _fullStackFrameRegex = new Regex(@"^\s*(?'at'\w*)\s(?'method'.*)\((?'params'.*)\)\s(?'in'\w*)\s(?'path'.*)\:(?'line'\w*)\s(?'linenumber'\d*)$"); | ||||||
|  |  | ||||||
|  |         public static ExceptionInfo? Parse(string exception) | ||||||
|  |         { | ||||||
|  |             if (exception is null) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentNullException(nameof(exception)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var lines = exception.SplitLines(); | ||||||
|  |             return Parse(new Queue<string>(lines)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static ExceptionInfo? Parse(Queue<string> lines) | ||||||
|  |         { | ||||||
|  |             if (lines.Count == 0) | ||||||
|  |             { | ||||||
|  |                 // Error: No lines to parse | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var line = lines.Dequeue(); | ||||||
|  |             line = line.Replace(" ---> ", string.Empty); | ||||||
|  |  | ||||||
|  |             var match = _messageRegex.Match(line); | ||||||
|  |             if (!match.Success) | ||||||
|  |             { | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var inner = (ExceptionInfo?)null; | ||||||
|  |  | ||||||
|  |             // Stack frames | ||||||
|  |             var frames = new List<StackFrameInfo>(); | ||||||
|  |             while (lines.Count > 0) | ||||||
|  |             { | ||||||
|  |                 if (lines.Peek().TrimStart().StartsWith("---> ", StringComparison.OrdinalIgnoreCase)) | ||||||
|  |                 { | ||||||
|  |                     inner = Parse(lines); | ||||||
|  |                     if (inner == null) | ||||||
|  |                     { | ||||||
|  |                         // Error: Could not parse inner exception | ||||||
|  |                         return null; | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 line = lines.Dequeue(); | ||||||
|  |  | ||||||
|  |                 if (string.IsNullOrWhiteSpace(line)) | ||||||
|  |                 { | ||||||
|  |                     // Empty line | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (line.TrimStart().StartsWith("--- ", StringComparison.OrdinalIgnoreCase)) | ||||||
|  |                 { | ||||||
|  |                     // End of inner exception | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 var stackFrame = ParseStackFrame(line); | ||||||
|  |                 if (stackFrame == null) | ||||||
|  |                 { | ||||||
|  |                     // Error: Could not parse stack frame | ||||||
|  |                     return null; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 frames.Add(stackFrame); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return new ExceptionInfo( | ||||||
|  |                 match.Groups["type"].Value, | ||||||
|  |                 match.Groups["message"].Value, | ||||||
|  |                 frames, inner); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static StackFrameInfo? ParseStackFrame(string frame) | ||||||
|  |         { | ||||||
|  |             var match = _fullStackFrameRegex.Match(frame); | ||||||
|  |             if (match?.Success != true) | ||||||
|  |             { | ||||||
|  |                 match = _stackFrameRegex.Match(frame); | ||||||
|  |                 if (match?.Success != true) | ||||||
|  |                 { | ||||||
|  |                     return null; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var parameters = ParseMethodParameters(match.Groups["params"].Value); | ||||||
|  |             if (parameters == null) | ||||||
|  |             { | ||||||
|  |                 // Error: Could not parse parameters | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var method = match.Groups["method"].Value; | ||||||
|  |             var path = match.Groups["path"].Success ? match.Groups["path"].Value : null; | ||||||
|  |  | ||||||
|  |             var lineNumber = (int?)null; | ||||||
|  |             if (!string.IsNullOrWhiteSpace(match.Groups["linenumber"].Value)) | ||||||
|  |             { | ||||||
|  |                 lineNumber = int.Parse(match.Groups["linenumber"].Value, CultureInfo.InvariantCulture); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return new StackFrameInfo(method, parameters, path, lineNumber); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static List<(string Type, string Name)>? ParseMethodParameters(string parameters) | ||||||
|  |         { | ||||||
|  |             var result = new List<(string Type, string Name)>(); | ||||||
|  |             foreach (var parameterPart in parameters.Split(new[] { ", " }, StringSplitOptions.RemoveEmptyEntries)) | ||||||
|  |             { | ||||||
|  |                 var parameterNameIndex = parameterPart.LastIndexOf(' '); | ||||||
|  |                 if (parameterNameIndex == -1) | ||||||
|  |                 { | ||||||
|  |                     // Error: Could not parse parameter | ||||||
|  |                     return null; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 var type = parameterPart.Substring(0, parameterNameIndex); | ||||||
|  |                 var name = parameterPart.Substring(parameterNameIndex + 1, parameterPart.Length - parameterNameIndex - 1); | ||||||
|  |  | ||||||
|  |                 result.Add((type, name)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return result; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user