mirror of
				https://github.com/spectreconsole/spectre.console.git
				synced 2025-10-25 15:19:23 +00:00 
			
		
		
		
	Compare commits
	
		
			39 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | d7bbaf4a85 | ||
|  | 0119364728 | ||
|  | 1d74fb909c | ||
|  | 5d132220ba | ||
|  | a273f74758 | ||
|  | 717931f11c | ||
|  | bcfc495843 | ||
|  | 9aa36c4cf0 | ||
|  | 22d4af4482 | ||
|  | f4d1796e40 | ||
|  | 2dd0eb9f74 | ||
|  | fa85216554 | ||
|  | d475e3b30a | ||
|  | 9637066927 | ||
|  | 0b4321115a | ||
|  | 5cd9ece31a | ||
|  | b0341862cf | ||
|  | 2e7b3d520a | ||
|  | 646f51a628 | ||
|  | a0bd481255 | ||
|  | 6d197c5140 | ||
|  | 108e56c229 | ||
|  | 66994cd904 | ||
|  | f9bd936254 | ||
|  | a068fc68c3 | ||
|  | aa34c145b9 | ||
|  | 98cf63f485 | ||
|  | c3286a4842 | ||
|  | e5bf2bd498 | ||
|  | 5267ebda49 | ||
|  | f19202b427 | ||
|  | 8e4f33bba4 | ||
|  | e596e6eb4f | ||
|  | a80120babc | ||
|  | 214d510d6d | ||
|  | 0986a5f744 | ||
|  | b72a695c35 | ||
|  | 6a7733cabf | ||
|  | 36e2034a1c | 
							
								
								
									
										6
									
								
								.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -2,9 +2,7 @@ name: Continuous Integration | ||||
| on: pull_request | ||||
|  | ||||
| env: | ||||
|   # Set the DOTNET_SKIP_FIRST_TIME_EXPERIENCE environment variable to stop wasting time caching packages | ||||
|   DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true | ||||
|   # Disable sending usage data to Microsoft | ||||
|   DOTNET_CLI_TELEMETRY_OPTOUT: true | ||||
|  | ||||
| jobs: | ||||
| @@ -28,10 +26,6 @@ jobs: | ||||
|         with: | ||||
|           fetch-depth: 0 | ||||
|  | ||||
|       - name: 'Get Git tags' | ||||
|         run: git fetch --tags | ||||
|         shell: bash | ||||
|  | ||||
|       - name: Setup dotnet | ||||
|         uses: actions/setup-dotnet@v1 | ||||
|         with: | ||||
|   | ||||
							
								
								
									
										10
									
								
								.github/workflows/publish.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/workflows/publish.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -8,9 +8,7 @@ on: | ||||
|       - main | ||||
|  | ||||
| env: | ||||
|   # Set the DOTNET_SKIP_FIRST_TIME_EXPERIENCE environment variable to stop wasting time caching packages | ||||
|   DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true | ||||
|   # Disable sending usage data to Microsoft | ||||
|   DOTNET_CLI_TELEMETRY_OPTOUT: true | ||||
|  | ||||
| jobs: | ||||
| @@ -39,10 +37,6 @@ jobs: | ||||
|         with: | ||||
|           fetch-depth: 0 | ||||
|  | ||||
|       - name: 'Get Git tags' | ||||
|         run: git fetch --tags | ||||
|         shell: bash | ||||
|  | ||||
|       - name: Setup dotnet | ||||
|         uses: actions/setup-dotnet@v1 | ||||
|         with: | ||||
| @@ -69,10 +63,6 @@ jobs: | ||||
|         with: | ||||
|           fetch-depth: 0 | ||||
|  | ||||
|       - name: 'Get Git tags' | ||||
|         run: git fetch --tags | ||||
|         shell: bash | ||||
|  | ||||
|       - name: Setup dotnet | ||||
|         uses: actions/setup-dotnet@v1 | ||||
|         with: | ||||
|   | ||||
							
								
								
									
										336
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										336
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,9 +1,22 @@ | ||||
| # `Spectre.Console` | ||||
|  | ||||
| _[](https://www.nuget.org/packages/spectre.console)_ | ||||
|  | ||||
| A .NET Standard 2.0 library that makes it easier to create beautiful console applications.   | ||||
| It is heavily inspired by the excellent [Rich library](https://github.com/willmcgugan/rich)  | ||||
| for Python. | ||||
|  | ||||
| ## Table of Contents | ||||
|  | ||||
| 1. [Features](#features) | ||||
| 2. [Example](#example) | ||||
| 3. [Usage](#usage)   | ||||
|    3.1. [Using the static API](#using-the-static-api)   | ||||
|    3.2. [Creating a console](#creating-a-console) | ||||
| 4. [Running examples](#running-examples) | ||||
| 5. [Available styles](#available-styles) | ||||
| 6. [Predefined colors](#predefined-colors) | ||||
|  | ||||
| ## Features | ||||
|  | ||||
| * Written with unit testing in mind. | ||||
| @@ -38,12 +51,11 @@ like you usually do with the `System.Console` API, but prettier. | ||||
|  | ||||
| ```csharp | ||||
| AnsiConsole.Foreground = Color.CornflowerBlue; | ||||
| AnsiConsole.Style = Styles.Underline | Styles.Bold; | ||||
| AnsiConsole.Decoration = Decoration.Underline | Decoration.Bold; | ||||
| AnsiConsole.WriteLine("Hello World!"); | ||||
|  | ||||
| AnsiConsole.Reset(); | ||||
| AnsiConsole.WriteLine("Good bye!"); | ||||
| AnsiConsole.WriteLine(); | ||||
| AnsiConsole.MarkupLine("[bold yellow on red]{0}[/] [underline]world[/]!", "Goodbye"); | ||||
| ``` | ||||
|  | ||||
| If you want to get a reference to the default `IAnsiConsole`,  | ||||
| @@ -53,7 +65,10 @@ you can access it via `AnsiConsole.Console`. | ||||
|  | ||||
| Sometimes it's useful to explicitly create a console with specific  | ||||
| capabilities, such as during unit testing when you want control  | ||||
| over the environment your code runs in. | ||||
| over the environment your code runs in.  | ||||
|  | ||||
| It's recommended to not use `AnsiConsole` in code that run as  | ||||
| part of a unit test. | ||||
|  | ||||
| ```csharp | ||||
| IAnsiConsole console = AnsiConsole.Create( | ||||
| @@ -69,3 +84,316 @@ _NOTE: Even if you can specify a specific color system to use | ||||
| when manually creating a console, remember that the user's terminal  | ||||
| might not be able to use it, so unless you're creating an IAnsiConsole  | ||||
| for testing, always use `ColorSystemSupport.Detect` and `AnsiSupport.Detect`._ | ||||
|  | ||||
| ## Running examples | ||||
|  | ||||
| To see Spectre.Console in action, install the  | ||||
| [dotnet-example](https://github.com/patriksvensson/dotnet-example) | ||||
| global tool. | ||||
|  | ||||
| ``` | ||||
| > dotnet tool install -g dotnet-example | ||||
| ``` | ||||
|  | ||||
| Now you can list available examples in this repository: | ||||
|  | ||||
| ``` | ||||
| > dotnet example | ||||
|  | ||||
| Examples | ||||
|  | ||||
| Colors    Demonstrates how to use colors in the console. | ||||
| Grid      Demonstrates how to render grids in a console. | ||||
| Panel     Demonstrates how to render items in panels. | ||||
| Table     Demonstrates how to render tables in a console. | ||||
| ``` | ||||
|  | ||||
| And to run an example: | ||||
|  | ||||
| ``` | ||||
| > dotnet example table | ||||
| ┌──────────┬──────────┬────────┐ | ||||
| │ Foo      │ Bar      │ Baz    │ | ||||
| ├──────────┼──────────┼────────┤ | ||||
| │ Hello    │ World!   │        │ | ||||
| │ Bounjour │ le       │ monde! │ | ||||
| │ Hej      │ Världen! │        │ | ||||
| └──────────┴──────────┴────────┘ | ||||
| ``` | ||||
|  | ||||
| ## Available styles | ||||
|  | ||||
| _NOTE: Not all styles are supported in every terminal._ | ||||
|  | ||||
| Name | Description | ||||
| --- | --- | ||||
| `bold` | Bold text | ||||
| `dim` | Dim or faint text | ||||
| `italic` | Italic text | ||||
| `underline` | Underlined text | ||||
| `invert` | Swaps the foreground and background colors | ||||
| `conceal` | Hides the text | ||||
| `slowblink` | Makes text blink slowly | ||||
| `rapidblink` | Makes text blink | ||||
| `strikethrough` | Shows text with a horizontal line through the center | ||||
|  | ||||
| ## Predefined colors | ||||
|  | ||||
| Number | Name | RGB | Hex | System.ConsoleColor | ||||
| --- | --- | --- | --- | --- | ||||
| `0` | `black` | `0,0,0` | `#000000` | `Black` | ||||
| `1` | `maroon` | `128,0,0` | `#800000` | `DarkRed` | ||||
| `2` | `green` | `0,128,0` | `#008000` | `DarkGreen` | ||||
| `3` | `olive` | `128,128,0` | `#808000` | `DarkYellow` | ||||
| `4` | `navy` | `0,0,128` | `#000080` | `DarkBlue` | ||||
| `5` | `purple` | `128,0,128` | `#800080` | `DarkMagenta` | ||||
| `6` | `teal` | `0,128,128` | `#008080` | `DarkCyan` | ||||
| `7` | `silver` | `192,192,192` | `#c0c0c0` | `Gray` | ||||
| `8` | `grey` | `128,128,128` | `#808080` | `DarkGray` | ||||
| `9` | `red` | `255,0,0` | `#ff0000` | `Red` | ||||
| `10` | `lime` | `0,255,0` | `#00ff00` | `Green` | ||||
| `11` | `yellow` | `255,255,0` | `#ffff00` | `Yellow` | ||||
| `12` | `blue` | `0,0,255` | `#0000ff` | `Blue` | ||||
| `13` | `fuchsia` | `255,0,255` | `#ff00ff` | `Magenta` | ||||
| `14` | `aqua` | `0,255,255` | `#00ffff` | `Cyan` | ||||
| `15` | `white` | `255,255,255` | `#ffffff` | `White` | ||||
| `16` | `grey0` | `0,0,0` | `#000000` | ||||
| `17` | `navyblue` | `0,0,95` | `#00005f` | ||||
| `18` | `darkblue` | `0,0,135` | `#000087` | ||||
| `19` | `blue3` | `0,0,175` | `#0000af` | ||||
| `20` | `blue3_1` | `0,0,215` | `#0000d7` | ||||
| `21` | `blue1` | `0,0,255` | `#0000ff` | ||||
| `22` | `darkgreen` | `0,95,0` | `#005f00` | ||||
| `23` | `deepskyblue4` | `0,95,95` | `#005f5f` | ||||
| `24` | `deepskyblue4_1` | `0,95,135` | `#005f87` | ||||
| `25` | `deepskyblue4_2` | `0,95,175` | `#005faf` | ||||
| `26` | `dodgerblue3` | `0,95,215` | `#005fd7` | ||||
| `27` | `dodgerblue2` | `0,95,255` | `#005fff` | ||||
| `28` | `green4` | `0,135,0` | `#008700` | ||||
| `29` | `springgreen4` | `0,135,95` | `#00875f` | ||||
| `30` | `turquoise4` | `0,135,135` | `#008787` | ||||
| `31` | `deepskyblue3` | `0,135,175` | `#0087af` | ||||
| `32` | `deepskyblue3_1` | `0,135,215` | `#0087d7` | ||||
| `33` | `dodgerblue1` | `0,135,255` | `#0087ff` | ||||
| `34` | `green3` | `0,175,0` | `#00af00` | ||||
| `35` | `springgreen3` | `0,175,95` | `#00af5f` | ||||
| `36` | `darkcyan` | `0,175,135` | `#00af87` | ||||
| `37` | `lightseagreen` | `0,175,175` | `#00afaf` | ||||
| `38` | `deepskyblue2` | `0,175,215` | `#00afd7` | ||||
| `39` | `deepskyblue1` | `0,175,255` | `#00afff` | ||||
| `40` | `green3_1` | `0,215,0` | `#00d700` | ||||
| `41` | `springgreen3_1` | `0,215,95` | `#00d75f` | ||||
| `42` | `springgreen2` | `0,215,135` | `#00d787` | ||||
| `43` | `cyan3` | `0,215,175` | `#00d7af` | ||||
| `44` | `darkturquoise` | `0,215,215` | `#00d7d7` | ||||
| `45` | `turquoise2` | `0,215,255` | `#00d7ff` | ||||
| `46` | `green1` | `0,255,0` | `#00ff00` | ||||
| `47` | `springgreen2_1` | `0,255,95` | `#00ff5f` | ||||
| `48` | `springgreen1` | `0,255,135` | `#00ff87` | ||||
| `49` | `mediumspringgreen` | `0,255,175` | `#00ffaf` | ||||
| `50` | `cyan2` | `0,255,215` | `#00ffd7` | ||||
| `51` | `cyan1` | `0,255,255` | `#00ffff` | ||||
| `52` | `darkred` | `95,0,0` | `#5f0000` | ||||
| `53` | `deeppink4` | `95,0,95` | `#5f005f` | ||||
| `54` | `purple4` | `95,0,135` | `#5f0087` | ||||
| `55` | `purple4_1` | `95,0,175` | `#5f00af` | ||||
| `56` | `purple3` | `95,0,215` | `#5f00d7` | ||||
| `57` | `blueviolet` | `95,0,255` | `#5f00ff` | ||||
| `58` | `orange4` | `95,95,0` | `#5f5f00` | ||||
| `59` | `grey37` | `95,95,95` | `#5f5f5f` | ||||
| `60` | `mediumpurple4` | `95,95,135` | `#5f5f87` | ||||
| `61` | `slateblue3` | `95,95,175` | `#5f5faf` | ||||
| `62` | `slateblue3_1` | `95,95,215` | `#5f5fd7` | ||||
| `63` | `royalblue1` | `95,95,255` | `#5f5fff` | ||||
| `64` | `chartreuse4` | `95,135,0` | `#5f8700` | ||||
| `65` | `darkseagreen4` | `95,135,95` | `#5f875f` | ||||
| `66` | `paleturquoise4` | `95,135,135` | `#5f8787` | ||||
| `67` | `steelblue` | `95,135,175` | `#5f87af` | ||||
| `68` | `steelblue3` | `95,135,215` | `#5f87d7` | ||||
| `69` | `cornflowerblue` | `95,135,255` | `#5f87ff` | ||||
| `70` | `chartreuse3` | `95,175,0` | `#5faf00` | ||||
| `71` | `darkseagreen4_1` | `95,175,95` | `#5faf5f` | ||||
| `72` | `cadetblue` | `95,175,135` | `#5faf87` | ||||
| `73` | `cadetblue_1` | `95,175,175` | `#5fafaf` | ||||
| `74` | `skyblue3` | `95,175,215` | `#5fafd7` | ||||
| `75` | `steelblue1` | `95,175,255` | `#5fafff` | ||||
| `76` | `chartreuse3_1` | `95,215,0` | `#5fd700` | ||||
| `77` | `palegreen3` | `95,215,95` | `#5fd75f` | ||||
| `78` | `seagreen3` | `95,215,135` | `#5fd787` | ||||
| `79` | `aquamarine3` | `95,215,175` | `#5fd7af` | ||||
| `80` | `mediumturquoise` | `95,215,215` | `#5fd7d7` | ||||
| `81` | `steelblue1_1` | `95,215,255` | `#5fd7ff` | ||||
| `82` | `chartreuse2` | `95,255,0` | `#5fff00` | ||||
| `83` | `seagreen2` | `95,255,95` | `#5fff5f` | ||||
| `84` | `seagreen1` | `95,255,135` | `#5fff87` | ||||
| `85` | `seagreen1_1` | `95,255,175` | `#5fffaf` | ||||
| `86` | `aquamarine1` | `95,255,215` | `#5fffd7` | ||||
| `87` | `darkslategray2` | `95,255,255` | `#5fffff` | ||||
| `88` | `darkred_1` | `135,0,0` | `#870000` | ||||
| `89` | `deeppink4_1` | `135,0,95` | `#87005f` | ||||
| `90` | `darkmagenta` | `135,0,135` | `#870087` | ||||
| `91` | `darkmagenta_1` | `135,0,175` | `#8700af` | ||||
| `92` | `darkviolet` | `135,0,215` | `#8700d7` | ||||
| `93` | `purple_1` | `135,0,255` | `#8700ff` | ||||
| `94` | `orange4_1` | `135,95,0` | `#875f00` | ||||
| `95` | `lightpink4` | `135,95,95` | `#875f5f` | ||||
| `96` | `plum4` | `135,95,135` | `#875f87` | ||||
| `97` | `mediumpurple3` | `135,95,175` | `#875faf` | ||||
| `98` | `mediumpurple3_1` | `135,95,215` | `#875fd7` | ||||
| `99` | `slateblue1` | `135,95,255` | `#875fff` | ||||
| `100` | `yellow4` | `135,135,0` | `#878700` | ||||
| `101` | `wheat4` | `135,135,95` | `#87875f` | ||||
| `102` | `grey53` | `135,135,135` | `#878787` | ||||
| `103` | `lightslategrey` | `135,135,175` | `#8787af` | ||||
| `104` | `mediumpurple` | `135,135,215` | `#8787d7` | ||||
| `105` | `lightslateblue` | `135,135,255` | `#8787ff` | ||||
| `106` | `yellow4_1` | `135,175,0` | `#87af00` | ||||
| `107` | `darkolivegreen3` | `135,175,95` | `#87af5f` | ||||
| `108` | `darkseagreen` | `135,175,135` | `#87af87` | ||||
| `109` | `lightskyblue3` | `135,175,175` | `#87afaf` | ||||
| `110` | `lightskyblue3_1` | `135,175,215` | `#87afd7` | ||||
| `111` | `skyblue2` | `135,175,255` | `#87afff` | ||||
| `112` | `chartreuse2_1` | `135,215,0` | `#87d700` | ||||
| `113` | `darkolivegreen3_1` | `135,215,95` | `#87d75f` | ||||
| `114` | `palegreen3_1` | `135,215,135` | `#87d787` | ||||
| `115` | `darkseagreen3` | `135,215,175` | `#87d7af` | ||||
| `116` | `darkslategray3` | `135,215,215` | `#87d7d7` | ||||
| `117` | `skyblue1` | `135,215,255` | `#87d7ff` | ||||
| `118` | `chartreuse1` | `135,255,0` | `#87ff00` | ||||
| `119` | `lightgreen` | `135,255,95` | `#87ff5f` | ||||
| `120` | `lightgreen_1` | `135,255,135` | `#87ff87` | ||||
| `121` | `palegreen1` | `135,255,175` | `#87ffaf` | ||||
| `122` | `aquamarine1_1` | `135,255,215` | `#87ffd7` | ||||
| `123` | `darkslategray1` | `135,255,255` | `#87ffff` | ||||
| `124` | `red3` | `175,0,0` | `#af0000` | ||||
| `125` | `deeppink4_2` | `175,0,95` | `#af005f` | ||||
| `126` | `mediumvioletred` | `175,0,135` | `#af0087` | ||||
| `127` | `magenta3` | `175,0,175` | `#af00af` | ||||
| `128` | `darkviolet_1` | `175,0,215` | `#af00d7` | ||||
| `129` | `purple_2` | `175,0,255` | `#af00ff` | ||||
| `130` | `darkorange3` | `175,95,0` | `#af5f00` | ||||
| `131` | `indianred` | `175,95,95` | `#af5f5f` | ||||
| `132` | `hotpink3` | `175,95,135` | `#af5f87` | ||||
| `133` | `mediumorchid3` | `175,95,175` | `#af5faf` | ||||
| `134` | `mediumorchid` | `175,95,215` | `#af5fd7` | ||||
| `135` | `mediumpurple2` | `175,95,255` | `#af5fff` | ||||
| `136` | `darkgoldenrod` | `175,135,0` | `#af8700` | ||||
| `137` | `lightsalmon3` | `175,135,95` | `#af875f` | ||||
| `138` | `rosybrown` | `175,135,135` | `#af8787` | ||||
| `139` | `grey63` | `175,135,175` | `#af87af` | ||||
| `140` | `mediumpurple2_1` | `175,135,215` | `#af87d7` | ||||
| `141` | `mediumpurple1` | `175,135,255` | `#af87ff` | ||||
| `142` | `gold3` | `175,175,0` | `#afaf00` | ||||
| `143` | `darkkhaki` | `175,175,95` | `#afaf5f` | ||||
| `144` | `navajowhite3` | `175,175,135` | `#afaf87` | ||||
| `145` | `grey69` | `175,175,175` | `#afafaf` | ||||
| `146` | `lightsteelblue3` | `175,175,215` | `#afafd7` | ||||
| `147` | `lightsteelblue` | `175,175,255` | `#afafff` | ||||
| `148` | `yellow3` | `175,215,0` | `#afd700` | ||||
| `149` | `darkolivegreen3_2` | `175,215,95` | `#afd75f` | ||||
| `150` | `darkseagreen3_1` | `175,215,135` | `#afd787` | ||||
| `151` | `darkseagreen2` | `175,215,175` | `#afd7af` | ||||
| `152` | `lightcyan3` | `175,215,215` | `#afd7d7` | ||||
| `153` | `lightskyblue1` | `175,215,255` | `#afd7ff` | ||||
| `154` | `greenyellow` | `175,255,0` | `#afff00` | ||||
| `155` | `darkolivegreen2` | `175,255,95` | `#afff5f` | ||||
| `156` | `palegreen1_1` | `175,255,135` | `#afff87` | ||||
| `157` | `darkseagreen2_1` | `175,255,175` | `#afffaf` | ||||
| `158` | `darkseagreen1` | `175,255,215` | `#afffd7` | ||||
| `159` | `paleturquoise1` | `175,255,255` | `#afffff` | ||||
| `160` | `red3_1` | `215,0,0` | `#d70000` | ||||
| `161` | `deeppink3` | `215,0,95` | `#d7005f` | ||||
| `162` | `deeppink3_1` | `215,0,135` | `#d70087` | ||||
| `163` | `magenta3_1` | `215,0,175` | `#d700af` | ||||
| `164` | `magenta3_2` | `215,0,215` | `#d700d7` | ||||
| `165` | `magenta2` | `215,0,255` | `#d700ff` | ||||
| `166` | `darkorange3_1` | `215,95,0` | `#d75f00` | ||||
| `167` | `indianred_1` | `215,95,95` | `#d75f5f` | ||||
| `168` | `hotpink3_1` | `215,95,135` | `#d75f87` | ||||
| `169` | `hotpink2` | `215,95,175` | `#d75faf` | ||||
| `170` | `orchid` | `215,95,215` | `#d75fd7` | ||||
| `171` | `mediumorchid1` | `215,95,255` | `#d75fff` | ||||
| `172` | `orange3` | `215,135,0` | `#d78700` | ||||
| `173` | `lightsalmon3_1` | `215,135,95` | `#d7875f` | ||||
| `174` | `lightpink3` | `215,135,135` | `#d78787` | ||||
| `175` | `pink3` | `215,135,175` | `#d787af` | ||||
| `176` | `plum3` | `215,135,215` | `#d787d7` | ||||
| `177` | `violet` | `215,135,255` | `#d787ff` | ||||
| `178` | `gold3_1` | `215,175,0` | `#d7af00` | ||||
| `179` | `lightgoldenrod3` | `215,175,95` | `#d7af5f` | ||||
| `180` | `tan` | `215,175,135` | `#d7af87` | ||||
| `181` | `mistyrose3` | `215,175,175` | `#d7afaf` | ||||
| `182` | `thistle3` | `215,175,215` | `#d7afd7` | ||||
| `183` | `plum2` | `215,175,255` | `#d7afff` | ||||
| `184` | `yellow3_1` | `215,215,0` | `#d7d700` | ||||
| `185` | `khaki3` | `215,215,95` | `#d7d75f` | ||||
| `186` | `lightgoldenrod2` | `215,215,135` | `#d7d787` | ||||
| `187` | `lightyellow3` | `215,215,175` | `#d7d7af` | ||||
| `188` | `grey84` | `215,215,215` | `#d7d7d7` | ||||
| `189` | `lightsteelblue1` | `215,215,255` | `#d7d7ff` | ||||
| `190` | `yellow2` | `215,255,0` | `#d7ff00` | ||||
| `191` | `darkolivegreen1` | `215,255,95` | `#d7ff5f` | ||||
| `192` | `darkolivegreen1_1` | `215,255,135` | `#d7ff87` | ||||
| `193` | `darkseagreen1_1` | `215,255,175` | `#d7ffaf` | ||||
| `194` | `honeydew2` | `215,255,215` | `#d7ffd7` | ||||
| `195` | `lightcyan1` | `215,255,255` | `#d7ffff` | ||||
| `196` | `red1` | `255,0,0` | `#ff0000` | ||||
| `197` | `deeppink2` | `255,0,95` | `#ff005f` | ||||
| `198` | `deeppink1` | `255,0,135` | `#ff0087` | ||||
| `199` | `deeppink1_1` | `255,0,175` | `#ff00af` | ||||
| `200` | `magenta2_1` | `255,0,215` | `#ff00d7` | ||||
| `201` | `magenta1` | `255,0,255` | `#ff00ff` | ||||
| `202` | `orangered1` | `255,95,0` | `#ff5f00` | ||||
| `203` | `indianred1` | `255,95,95` | `#ff5f5f` | ||||
| `204` | `indianred1_1` | `255,95,135` | `#ff5f87` | ||||
| `205` | `hotpink` | `255,95,175` | `#ff5faf` | ||||
| `206` | `hotpink_1` | `255,95,215` | `#ff5fd7` | ||||
| `207` | `mediumorchid1_1` | `255,95,255` | `#ff5fff` | ||||
| `208` | `darkorange` | `255,135,0` | `#ff8700` | ||||
| `209` | `salmon1` | `255,135,95` | `#ff875f` | ||||
| `210` | `lightcoral` | `255,135,135` | `#ff8787` | ||||
| `211` | `palevioletred1` | `255,135,175` | `#ff87af` | ||||
| `212` | `orchid2` | `255,135,215` | `#ff87d7` | ||||
| `213` | `orchid1` | `255,135,255` | `#ff87ff` | ||||
| `214` | `orange1` | `255,175,0` | `#ffaf00` | ||||
| `215` | `sandybrown` | `255,175,95` | `#ffaf5f` | ||||
| `216` | `lightsalmon1` | `255,175,135` | `#ffaf87` | ||||
| `217` | `lightpink1` | `255,175,175` | `#ffafaf` | ||||
| `218` | `pink1` | `255,175,215` | `#ffafd7` | ||||
| `219` | `plum1` | `255,175,255` | `#ffafff` | ||||
| `220` | `gold1` | `255,215,0` | `#ffd700` | ||||
| `221` | `lightgoldenrod2_1` | `255,215,95` | `#ffd75f` | ||||
| `222` | `lightgoldenrod2_2` | `255,215,135` | `#ffd787` | ||||
| `223` | `navajowhite1` | `255,215,175` | `#ffd7af` | ||||
| `224` | `mistyrose1` | `255,215,215` | `#ffd7d7` | ||||
| `225` | `thistle1` | `255,215,255` | `#ffd7ff` | ||||
| `226` | `yellow1` | `255,255,0` | `#ffff00` | ||||
| `227` | `lightgoldenrod1` | `255,255,95` | `#ffff5f` | ||||
| `228` | `khaki1` | `255,255,135` | `#ffff87` | ||||
| `229` | `wheat1` | `255,255,175` | `#ffffaf` | ||||
| `230` | `cornsilk1` | `255,255,215` | `#ffffd7` | ||||
| `231` | `grey100` | `255,255,255` | `#ffffff` | ||||
| `232` | `grey3` | `8,8,8` | `#080808` | ||||
| `233` | `grey7` | `18,18,18` | `#121212` | ||||
| `234` | `grey11` | `28,28,28` | `#1c1c1c` | ||||
| `235` | `grey15` | `38,38,38` | `#262626` | ||||
| `236` | `grey19` | `48,48,48` | `#303030` | ||||
| `237` | `grey23` | `58,58,58` | `#3a3a3a` | ||||
| `238` | `grey27` | `68,68,68` | `#444444` | ||||
| `239` | `grey30` | `78,78,78` | `#4e4e4e` | ||||
| `240` | `grey35` | `88,88,88` | `#585858` | ||||
| `241` | `grey39` | `98,98,98` | `#626262` | ||||
| `242` | `grey42` | `108,108,108` | `#6c6c6c` | ||||
| `243` | `grey46` | `118,118,118` | `#767676` | ||||
| `244` | `grey50` | `128,128,128` | `#808080` | ||||
| `245` | `grey54` | `138,138,138` | `#8a8a8a` | ||||
| `246` | `grey58` | `148,148,148` | `#949494` | ||||
| `247` | `grey62` | `158,158,158` | `#9e9e9e` | ||||
| `248` | `grey66` | `168,168,168` | `#a8a8a8` | ||||
| `249` | `grey70` | `178,178,178` | `#b2b2b2` | ||||
| `250` | `grey74` | `188,188,188` | `#bcbcbc` | ||||
| `251` | `grey78` | `198,198,198` | `#c6c6c6` | ||||
| `252` | `grey82` | `208,208,208` | `#d0d0d0` | ||||
| `253` | `grey85` | `218,218,218` | `#dadada` | ||||
| `254` | `grey89` | `228,228,228` | `#e4e4e4` | ||||
| `255` | `grey93` | `238,238,238` | `#eeeeee` | ||||
|   | ||||
							
								
								
									
										14
									
								
								examples/Colors/Colors.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								examples/Colors/Colors.csproj
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|  | ||||
|   <PropertyGroup> | ||||
|     <OutputType>Exe</OutputType> | ||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
|     <IsPackable>false</IsPackable> | ||||
|     <Description>Demonstrates how to use [yellow]c[/][red]o[/][green]l[/][blue]o[/][aqua]r[/][lime]s[/] in the console.</Description> | ||||
|   </PropertyGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
| </Project> | ||||
							
								
								
									
										78
									
								
								examples/Colors/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								examples/Colors/Program.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| using Spectre.Console; | ||||
|  | ||||
| namespace ColorExample | ||||
| { | ||||
|     class Program | ||||
|     { | ||||
|         static void Main(string[] args) | ||||
|         { | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             // 4-BIT | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|  | ||||
|             AnsiConsole.ResetColors(); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.MarkupLine("[bold underline]4-bit Colors[/]"); | ||||
|             AnsiConsole.WriteLine(); | ||||
|  | ||||
|             for (var i = 0; i < 16; i++) | ||||
|             { | ||||
|                 AnsiConsole.Background = Color.FromInt32(i); | ||||
|                 AnsiConsole.Write(string.Format(" {0,-9}", AnsiConsole.Background.ToString())); | ||||
|                 AnsiConsole.ResetColors(); | ||||
|                 if ((i + 1) % 8 == 0) | ||||
|                 { | ||||
|                     AnsiConsole.WriteLine(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             // 8-BIT | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|  | ||||
|             AnsiConsole.ResetColors(); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.MarkupLine("[bold underline]8-bit Colors[/]"); | ||||
|             AnsiConsole.WriteLine(); | ||||
|  | ||||
|             for (var i = 0; i < 16; i++) | ||||
|             { | ||||
|                 for (var j = 0; j < 16; j++) | ||||
|                 { | ||||
|                     var number = i * 16 + j; | ||||
|                     AnsiConsole.Background = Color.FromInt32(number); | ||||
|                     AnsiConsole.Write(string.Format(" {0,-4}", number)); | ||||
|                     AnsiConsole.ResetColors(); | ||||
|                     if ((number + 1) % 16 == 0) | ||||
|                     { | ||||
|                         AnsiConsole.WriteLine(); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|             // 24-BIT | ||||
|             ///////////////////////////////////////////////////////////////// | ||||
|  | ||||
|             AnsiConsole.ResetColors(); | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.MarkupLine("[bold underline]24-bit Colors[/]"); | ||||
|             AnsiConsole.WriteLine(); | ||||
|  | ||||
|             var index = 0; | ||||
|             for (var i = 0.0005; i < 1; i += 0.0025) | ||||
|             { | ||||
|                 index++; | ||||
|  | ||||
|                 var color = Utilities.HSL2RGB(i, 0.5, 0.5); | ||||
|                 AnsiConsole.Background = new Color(color.R, color.G, color.B); | ||||
|                 AnsiConsole.Write(" "); | ||||
|  | ||||
|                 if (index % 50 == 0) | ||||
|                 { | ||||
|                     AnsiConsole.WriteLine(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										77
									
								
								examples/Colors/Utilities.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								examples/Colors/Utilities.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| using System; | ||||
| using Spectre.Console; | ||||
|  | ||||
| namespace ColorExample | ||||
| { | ||||
|     public static class Utilities | ||||
|     { | ||||
|         // Borrowed from https://geekymonkey.com/Programming/CSharp/RGB2HSL_HSL2RGB.htm | ||||
|         public static Color HSL2RGB(double h, double sl, double l) | ||||
|         { | ||||
|             double v; | ||||
|             double r, g, b; | ||||
|  | ||||
|             r = l;   // default to gray | ||||
|             g = l; | ||||
|             b = l; | ||||
|             v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl); | ||||
|  | ||||
|             if (v > 0) | ||||
|             { | ||||
|                 double m; | ||||
|                 double sv; | ||||
|                 int sextant; | ||||
|                 double fract, vsf, mid1, mid2; | ||||
|  | ||||
|                 m = l + l - v; | ||||
|                 sv = (v - m) / v; | ||||
|                 h *= 6.0; | ||||
|  | ||||
|                 sextant = (int)h; | ||||
|                 fract = h - sextant; | ||||
|                 vsf = v * sv * fract; | ||||
|                 mid1 = m + vsf; | ||||
|                 mid2 = v - vsf; | ||||
|  | ||||
|                 switch (sextant) | ||||
|                 { | ||||
|                     case 0: | ||||
|                         r = v; | ||||
|                         g = mid1; | ||||
|                         b = m; | ||||
|                         break; | ||||
|                     case 1: | ||||
|                         r = mid2; | ||||
|                         g = v; | ||||
|                         b = m; | ||||
|                         break; | ||||
|                     case 2: | ||||
|                         r = m; | ||||
|                         g = v; | ||||
|                         b = mid1; | ||||
|                         break; | ||||
|                     case 3: | ||||
|                         r = m; | ||||
|                         g = mid2; | ||||
|                         b = v; | ||||
|                         break; | ||||
|                     case 4: | ||||
|                         r = mid1; | ||||
|                         g = m; | ||||
|                         b = v; | ||||
|                         break; | ||||
|                     case 5: | ||||
|                         r = v; | ||||
|                         g = m; | ||||
|                         b = mid2; | ||||
|                         break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return new Color( | ||||
|                 Convert.ToByte(r * 255.0f), | ||||
|                 Convert.ToByte(g * 255.0f), | ||||
|                 Convert.ToByte(b * 255.0f)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										14
									
								
								examples/Grid/Grid.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								examples/Grid/Grid.csproj
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|  | ||||
|   <PropertyGroup> | ||||
|     <OutputType>Exe</OutputType> | ||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
|     <IsPackable>false</IsPackable> | ||||
|     <Description>Demonstrates how to render grids in a console.</Description> | ||||
|   </PropertyGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
| </Project> | ||||
							
								
								
									
										26
									
								
								examples/Grid/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								examples/Grid/Program.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| using System; | ||||
| using Spectre.Console; | ||||
|  | ||||
| namespace GridExample | ||||
| { | ||||
|     public sealed class Program | ||||
|     { | ||||
|         static void Main(string[] args) | ||||
|         { | ||||
|             AnsiConsole.WriteLine(); | ||||
|             AnsiConsole.MarkupLine("Usage: [grey]dotnet [blue]run[/] [[options] [[[[--] <additional arguments>...]][/]"); | ||||
|             AnsiConsole.WriteLine(); | ||||
|  | ||||
|             var grid = new Grid(); | ||||
|             grid.AddColumn(new GridColumn { NoWrap = true }); | ||||
|             grid.AddColumn(new GridColumn { NoWrap = true, Width = 2 }); | ||||
|             grid.AddColumn(); | ||||
|             grid.AddRow("Options:", "", ""); | ||||
|             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]-v[/], [blue]--verbosity[/] <LEVEL>", "", "Set the [grey]MSBuild[/] verbosity level."); | ||||
|  | ||||
|             AnsiConsole.Render(grid); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -3,12 +3,12 @@ | ||||
|   <PropertyGroup> | ||||
|     <OutputType>Exe</OutputType> | ||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
|     <RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild> | ||||
|     <IsPackable>false</IsPackable> | ||||
|     <Description>Demonstrates how to render items in panels.</Description> | ||||
|   </PropertyGroup> | ||||
| 
 | ||||
|   <ItemGroup> | ||||
|     <ProjectReference Include="..\Spectre.Console\Spectre.Console.csproj" /> | ||||
|     <ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" /> | ||||
|   </ItemGroup> | ||||
| 
 | ||||
| </Project> | ||||
							
								
								
									
										50
									
								
								examples/Panel/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								examples/Panel/Program.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| using System; | ||||
| using Spectre.Console; | ||||
|  | ||||
| namespace PanelExample | ||||
| { | ||||
|     class Program | ||||
|     { | ||||
|         static void Main(string[] args) | ||||
|         { | ||||
|             var content = Text.Markup( | ||||
|                 "[underline]I[/] heard [underline on blue]you[/] like 📦\n\n\n\n" + | ||||
|                 "So I put a 📦 in a 📦\n\n" + | ||||
|                 "😅"); | ||||
|  | ||||
|             AnsiConsole.Render( | ||||
|                 new Panel( | ||||
|                     new Panel(content) | ||||
|                     { | ||||
|                         Alignment = Justify.Center, | ||||
|                         Border = BorderKind.Rounded | ||||
|                     })); | ||||
|  | ||||
|             // Left adjusted panel with text | ||||
|             AnsiConsole.Render(new Panel( | ||||
|                 new Text("Left adjusted\nLeft")) | ||||
|             { | ||||
|                 Expand = true, | ||||
|                 Alignment = Justify.Left, | ||||
|             }); | ||||
|  | ||||
|             // Centered ASCII panel with text | ||||
|             AnsiConsole.Render(new Panel( | ||||
|                 new Text("Centered\nCenter")) | ||||
|             { | ||||
|                 Expand = true, | ||||
|                 Alignment = Justify.Center, | ||||
|                 Border = BorderKind.Ascii, | ||||
|             }); | ||||
|  | ||||
|             // Right adjusted, rounded panel with text | ||||
|             AnsiConsole.Render(new Panel( | ||||
|                 new Text("Right adjusted\nRight")) | ||||
|             { | ||||
|                 Expand = true, | ||||
|                 Alignment = Justify.Right, | ||||
|                 Border = BorderKind.Rounded, | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										55
									
								
								examples/Table/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								examples/Table/Program.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| using System; | ||||
| using Spectre.Console; | ||||
|  | ||||
| namespace TableExample | ||||
| { | ||||
|     class Program | ||||
|     { | ||||
|         static void Main(string[] args) | ||||
|         { | ||||
|             // A simple table§ | ||||
|             RenderSimpleTable(); | ||||
|  | ||||
|             // A big table | ||||
|             RenderBigTable(); | ||||
|         } | ||||
|  | ||||
|         private static void RenderSimpleTable() | ||||
|         { | ||||
|             // Create the table. | ||||
|             var table = new Table(); | ||||
|             table.AddColumn(new TableColumn("[u]Foo[/]")); | ||||
|             table.AddColumn(new TableColumn("[u]Bar[/]")); | ||||
|             table.AddColumn(new TableColumn("[u]Baz[/]")); | ||||
|  | ||||
|             // Add some rows | ||||
|             table.AddRow("Hello", "[red]World![/]", ""); | ||||
|             table.AddRow("[blue]Bounjour[/]", "[white]le[/]", "[red]monde![/]"); | ||||
|             table.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", ""); | ||||
|  | ||||
|             AnsiConsole.Render(table); | ||||
|         } | ||||
|  | ||||
|         private static void RenderBigTable() | ||||
|         { | ||||
|             // Create the table. | ||||
|             var table = new Table { Border = BorderKind.Rounded }; | ||||
|             table.AddColumn("[red underline]Foo[/]"); | ||||
|             table.AddColumn(new TableColumn("[blue]Bar[/]") { Alignment = Justify.Right, NoWrap = true }); | ||||
|  | ||||
|             // Add some rows | ||||
|             table.AddRow("[blue][underline]Hell[/]o[/]", "World 🌍"); | ||||
|             table.AddRow("[yellow]Patrik [green]\"Hello World\"[/] Svensson[/]", "Was [underline]here[/]!"); | ||||
|             table.AddEmptyRow(); | ||||
|             table.AddRow( | ||||
|                 "Lorem ipsum dolor sit amet, consectetur adipiscing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " + | ||||
|                 "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure " + | ||||
|                 "dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat " + | ||||
|                 "non proident, sunt in culpa qui officia deserunt mollit anim id est laborum", "◀ Strange language"); | ||||
|             table.AddEmptyRow(); | ||||
|             table.AddRow("Hej 👋", "[green]Världen[/]"); | ||||
|  | ||||
|             AnsiConsole.Render(table); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										14
									
								
								examples/Table/Table.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								examples/Table/Table.csproj
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|  | ||||
|   <PropertyGroup> | ||||
|     <OutputType>Exe</OutputType> | ||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
|     <IsPackable>false</IsPackable> | ||||
|     <Description>Demonstrates how to render tables in a console.</Description> | ||||
|   </PropertyGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
| </Project> | ||||
							
								
								
									
										
											BIN
										
									
								
								gfx/large-logo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gfx/large-logo.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 600 KiB | 
							
								
								
									
										
											BIN
										
									
								
								gfx/medium-logo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gfx/medium-logo.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 30 KiB | 
							
								
								
									
										
											BIN
										
									
								
								gfx/small-logo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gfx/small-logo.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 9.5 KiB | 
							
								
								
									
										2
									
								
								scripts/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								scripts/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| Generated | ||||
| Temp | ||||
							
								
								
									
										24
									
								
								scripts/Generate-Colors.ps1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								scripts/Generate-Colors.ps1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| ########################################################## | ||||
| # Script that generates known colors and lookup tables. | ||||
| ########################################################## | ||||
|  | ||||
| $Output = Join-Path $PSScriptRoot "Temp" | ||||
| $Source = Join-Path $PSScriptRoot "/../src/Spectre.Console" | ||||
|  | ||||
| if(!(Test-Path $Output -PathType Container)) { | ||||
|     New-Item -ItemType Directory -Path $Output | Out-Null | ||||
| } | ||||
|  | ||||
| # Generate the files | ||||
| Push-Location Generator | ||||
| &dotnet run -- colors "$Output" | ||||
| if(!$?) {  | ||||
|     Pop-Location | ||||
|     Throw "An error occured when generating code." | ||||
| } | ||||
| Pop-Location | ||||
|  | ||||
| # Copy the files to the correct location | ||||
| Copy-Item  (Join-Path "$Output" "Color.Generated.cs") -Destination "$Source/Color.Generated.cs" | ||||
| Copy-Item  (Join-Path "$Output" "ColorPalette.Generated.cs") -Destination "$Source/Internal/Colors/ColorPalette.Generated.cs" | ||||
| Copy-Item  (Join-Path "$Output" "ColorTable.Generated.cs") -Destination "$Source/Internal/Colors/ColorTable.Generated.cs" | ||||
							
								
								
									
										59
									
								
								scripts/Generator/Commands/ColorGeneratorCommand.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								scripts/Generator/Commands/ColorGeneratorCommand.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
| using Generator.Models; | ||||
| using Scriban; | ||||
| using Spectre.Cli; | ||||
| using Spectre.IO; | ||||
|  | ||||
| namespace Generator.Commands | ||||
| { | ||||
|     public sealed class ColorGeneratorCommand : Command<GeneratorCommandSettings> | ||||
|     { | ||||
|         private readonly IFileSystem _fileSystem; | ||||
|  | ||||
|         public ColorGeneratorCommand() | ||||
|         { | ||||
|             _fileSystem = new FileSystem(); | ||||
|         } | ||||
|  | ||||
|         public override int Execute(CommandContext context, GeneratorCommandSettings settings) | ||||
|         { | ||||
|             var templates = new FilePath[] | ||||
|             { | ||||
|                 "Templates/ColorPalette.Generated.template", | ||||
|                 "Templates/Color.Generated.template", | ||||
|                 "Templates/ColorTable.Generated.template" | ||||
|             }; | ||||
|  | ||||
|             // Read the color model. | ||||
|             var model = Color.Parse(File.ReadAllText("Data/colors.json")); | ||||
|  | ||||
|             var output = new DirectoryPath(settings.Output); | ||||
|             if (!_fileSystem.Directory.Exists(settings.Output)) | ||||
|             { | ||||
|                 _fileSystem.Directory.Create(settings.Output); | ||||
|             } | ||||
|  | ||||
|             foreach (var templatePath in templates) | ||||
|             { | ||||
|                 // Parse the Scriban template. | ||||
|                 var template = Template.Parse(File.ReadAllText(templatePath.FullPath)); | ||||
|  | ||||
|                 // Render the template with the model. | ||||
|                 var result = template.Render(new { Colors = model }); | ||||
|  | ||||
|                 // Write output to file | ||||
|                 var file = output.CombineWithFilePath(templatePath.GetFilename().ChangeExtension(".cs")); | ||||
|                 File.WriteAllText(file.FullPath, result); | ||||
|             } | ||||
|  | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public sealed class GeneratorCommandSettings : CommandSettings | ||||
|     { | ||||
|         [CommandArgument(0, "<OUTPUT>")] | ||||
|         public string Output { get; set; } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3842
									
								
								scripts/Generator/Data/colors.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3842
									
								
								scripts/Generator/Data/colors.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										36
									
								
								scripts/Generator/Generator.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								scripts/Generator/Generator.csproj
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|  | ||||
|   <PropertyGroup> | ||||
|     <OutputType>Exe</OutputType> | ||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
|   </PropertyGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <Compile Remove="out\**" /> | ||||
|     <EmbeddedResource Remove="out\**" /> | ||||
|     <None Remove="out\**" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <None Update="Data\colors.json"> | ||||
|       <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
|     </None> | ||||
|     <None Update="Templates\ColorTable.Generated.template"> | ||||
|       <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
|     </None> | ||||
|     <None Update="Templates\Color.Generated.template"> | ||||
|       <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
|     </None> | ||||
|     <None Update="Templates\ColorPalette.Generated.template"> | ||||
|       <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
|     </None> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> | ||||
|     <PackageReference Include="Scriban" Version="2.1.3" /> | ||||
|     <PackageReference Include="Spectre.Cli" Version="0.36.1-preview.0.6" /> | ||||
|     <PackageReference Include="Spectre.IO" Version="0.1.0" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
| </Project> | ||||
							
								
								
									
										37
									
								
								scripts/Generator/Generator.sln
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								scripts/Generator/Generator.sln
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
|  | ||||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||||
| # Visual Studio Version 16 | ||||
| VisualStudioVersion = 16.0.30320.27 | ||||
| MinimumVisualStudioVersion = 15.0.26124.0 | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Generator", "Generator.csproj", "{5668D267-53E3-4B99-97AE-59AA597D22ED}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|Any CPU = Debug|Any CPU | ||||
| 		Debug|x64 = Debug|x64 | ||||
| 		Debug|x86 = Debug|x86 | ||||
| 		Release|Any CPU = Release|Any CPU | ||||
| 		Release|x64 = Release|x64 | ||||
| 		Release|x86 = Release|x86 | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||
| 		{5668D267-53E3-4B99-97AE-59AA597D22ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{5668D267-53E3-4B99-97AE-59AA597D22ED}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{5668D267-53E3-4B99-97AE-59AA597D22ED}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{5668D267-53E3-4B99-97AE-59AA597D22ED}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{5668D267-53E3-4B99-97AE-59AA597D22ED}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{5668D267-53E3-4B99-97AE-59AA597D22ED}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{5668D267-53E3-4B99-97AE-59AA597D22ED}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{5668D267-53E3-4B99-97AE-59AA597D22ED}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{5668D267-53E3-4B99-97AE-59AA597D22ED}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{5668D267-53E3-4B99-97AE-59AA597D22ED}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{5668D267-53E3-4B99-97AE-59AA597D22ED}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{5668D267-53E3-4B99-97AE-59AA597D22ED}.Release|x86.Build.0 = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ExtensibilityGlobals) = postSolution | ||||
| 		SolutionGuid = {5F37FDE3-D591-4D43-8DDE-2ED6BAB0A7B4} | ||||
| 	EndGlobalSection | ||||
| EndGlobal | ||||
							
								
								
									
										62
									
								
								scripts/Generator/Models/Color.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								scripts/Generator/Models/Color.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Newtonsoft.Json; | ||||
|  | ||||
| namespace Generator.Models | ||||
| { | ||||
|     public sealed class Color | ||||
|     { | ||||
|         public int Number { get; set; } | ||||
|         public string Hex { get; set; } | ||||
|         public string Name { get; set; } | ||||
|         public Rgb Rgb { get; set; } | ||||
|  | ||||
|         public int R => Rgb.R; | ||||
|         public int G => Rgb.G; | ||||
|         public int B => Rgb.B; | ||||
|  | ||||
|         public static IEnumerable<Color> Parse(string json) | ||||
|         { | ||||
|             var source = JsonConvert.DeserializeObject<List<Color>>(json); | ||||
|  | ||||
|             var check = new Dictionary<string, Color>(StringComparer.OrdinalIgnoreCase); | ||||
|             foreach (var color in source.OrderBy(c => c.Number)) | ||||
|             { | ||||
|                 if (!check.ContainsKey(color.Name)) | ||||
|                 { | ||||
|                     check.Add(color.Name, color); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     var newName = (string)null; | ||||
|                     for (int i = 1; i < 100; i++) | ||||
|                     { | ||||
|                         if (!check.ContainsKey($"{color.Name}_{i}")) | ||||
|                         { | ||||
|                             newName = $"{color.Name}_{i}"; | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     if (newName == null) | ||||
|                     { | ||||
|                         throw new InvalidOperationException("Impossible!"); | ||||
|                     } | ||||
|  | ||||
|                     check.Add(newName, color); | ||||
|                     color.Name = newName; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return source; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public sealed class Rgb | ||||
|     { | ||||
|         public int R { get; set; } | ||||
|         public int G { get; set; } | ||||
|         public int B { get; set; } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										14
									
								
								scripts/Generator/Models/ColorModel.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								scripts/Generator/Models/ColorModel.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Generator.Models | ||||
| { | ||||
|     public sealed class ColorModel | ||||
|     { | ||||
|         public List<Color> Colors { get; set; } | ||||
|  | ||||
|         public ColorModel(IEnumerable<Color> colors) | ||||
|         { | ||||
|             Colors = new List<Color>(colors); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										6
									
								
								scripts/Generator/Models/Palette.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								scripts/Generator/Models/Palette.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| namespace Generator.Models | ||||
| { | ||||
|     public sealed class Palette | ||||
|     { | ||||
|     } | ||||
| } | ||||
							
								
								
									
										19
									
								
								scripts/Generator/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								scripts/Generator/Program.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| using Generator.Commands; | ||||
| using Spectre.Cli; | ||||
|  | ||||
| namespace Generator | ||||
| { | ||||
|     public static class Program | ||||
|     { | ||||
|         public static int Main(string[] args) | ||||
|         { | ||||
|             var app = new CommandApp(); | ||||
|             app.Configure(config => | ||||
|             { | ||||
|                 config.AddCommand<ColorGeneratorCommand>("colors"); | ||||
|             }); | ||||
|  | ||||
|             return app.Run(args); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										36
									
								
								scripts/Generator/Templates/Color.Generated.template
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								scripts/Generator/Templates/Color.Generated.template
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| // <auto-generated> | ||||
| //     This code was generated by a tool. | ||||
| //     Generated {{ date.now | date.to_string `%Y-%m-%d %k:%M` }} | ||||
| // | ||||
| //     Changes to this file may cause incorrect behavior and will be lost if | ||||
| //     the code is regenerated. | ||||
| // </auto-generated> | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a color. | ||||
|     /// </summary> | ||||
|     public partial struct Color | ||||
|     { | ||||
|         internal Color(byte number, byte red, byte green, byte blue, bool isDefault = false) | ||||
|             : this(red, green, blue) | ||||
|         { | ||||
|             Number = number; | ||||
|             IsDefault = isDefault; | ||||
|         } | ||||
|         {{~ for color in colors }} | ||||
|         /// <summary> | ||||
|         /// Gets the color "{{ color.name }}" (RGB {{ color.r }},{{ color.g }},{{ color.b }}). | ||||
|         /// </summary> | ||||
|         {{- if string.contains color.name "_" }} | ||||
|         [SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores")] | ||||
|         {{- end}} | ||||
|         public static Color {{ color.name }} { get; } = new Color({{ color.number }}, {{ color.r }}, {{ color.g }}, {{ color.b }}); | ||||
|         {{~ end ~}} | ||||
|     } | ||||
| } | ||||
							
								
								
									
										47
									
								
								scripts/Generator/Templates/ColorPalette.Generated.template
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								scripts/Generator/Templates/ColorPalette.Generated.template
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| // <auto-generated> | ||||
| //     This code was generated by a tool. | ||||
| //     Generated {{ date.now | date.to_string `%Y-%m-%d %k:%M` }} | ||||
| // | ||||
| //     Changes to this file may cause incorrect behavior and will be lost if | ||||
| //     the code is regenerated. | ||||
| // </auto-generated> | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static partial class ColorPalette | ||||
|     { | ||||
|         private static List<Color> GenerateLegacyPalette() | ||||
|         { | ||||
|             return new List<Color> | ||||
|             { | ||||
|                 {{~ for number in 0..7 ~}} | ||||
|                 Color.{{ colors[number].name }}, | ||||
|                 {{~ end ~}} | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         private static List<Color> GenerateStandardPalette(IReadOnlyList<Color> legacy) | ||||
|         { | ||||
|             return new List<Color>(legacy) | ||||
|             { | ||||
|                 {{~ for number in 8..15 ~}} | ||||
|                 Color.{{ colors[number].name }}, | ||||
|                 {{~ end ~}} | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         private static List<Color> GenerateEightBitPalette(IReadOnlyList<Color> standard) | ||||
|         { | ||||
|             return new List<Color>(standard) | ||||
|             { | ||||
|                 {{~ for number in 16..255 ~}} | ||||
|                 Color.{{ colors[number].name }}, | ||||
|                 {{~ end ~}} | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										28
									
								
								scripts/Generator/Templates/ColorTable.Generated.template
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								scripts/Generator/Templates/ColorTable.Generated.template
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| // <auto-generated> | ||||
| //     This code was generated by a tool. | ||||
| //     Generated {{ date.now | date.to_string `%Y-%m-%d %k:%M` }} | ||||
| // | ||||
| //     Changes to this file may cause incorrect behavior and will be lost if | ||||
| //     the code is regenerated. | ||||
| // </auto-generated> | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static partial class ColorTable | ||||
|     { | ||||
|         private static Dictionary<string, int> GenerateTable() | ||||
|         { | ||||
|             return new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase) | ||||
|             { | ||||
|                 {{~ for color in colors ~}} | ||||
|                 { "{{ string.downcase color.name }}", {{ color.number }} }, | ||||
|                 {{~ end ~}} | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -75,3 +75,9 @@ dotnet_diagnostic.CA1032.severity = none | ||||
|  | ||||
| # CA1826: Do not use Enumerable methods on indexable collections. Instead use the collection directly | ||||
| dotnet_diagnostic.CA1826.severity = none | ||||
|  | ||||
| # RCS1079: Throwing of new NotImplementedException. | ||||
| dotnet_diagnostic.RCS1079.severity = warning | ||||
|  | ||||
| # RCS1057: Add empty line between declarations. | ||||
| dotnet_diagnostic.RCS1057.severity = none | ||||
|   | ||||
| @@ -18,6 +18,7 @@ | ||||
|     <Authors>Patrik Svensson</Authors> | ||||
|     <RepositoryType>git</RepositoryType> | ||||
|     <RepositoryUrl>https://github.com/spectresystems/spectre.console</RepositoryUrl> | ||||
|     <PackageIcon>small-logo.png</PackageIcon> | ||||
|     <PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance> | ||||
|     <PackageProjectUrl>https://github.com/spectresystems/spectre.console</PackageProjectUrl> | ||||
|     <PackageLicenseExpression>MIT</PackageLicenseExpression> | ||||
| @@ -33,7 +34,7 @@ | ||||
|   <ItemGroup Label="Package References"> | ||||
|     <PackageReference Include="MinVer" PrivateAssets="All" Version="2.3.0" /> | ||||
|     <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="1.0.0" /> | ||||
|     <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8"> | ||||
|     <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0"> | ||||
|       <PrivateAssets>all</PrivateAssets> | ||||
|       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||||
|     </PackageReference> | ||||
|   | ||||
| @@ -1,8 +0,0 @@ | ||||
| root = false | ||||
| [*.cs] | ||||
|  | ||||
| # Default severity for all analyzer diagnostics | ||||
| dotnet_analyzer_diagnostic.severity = none | ||||
|  | ||||
| # CS1591: Missing XML comment for publicly visible type or member | ||||
| dotnet_diagnostic.CS1591.severity = none | ||||
| @@ -1,53 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Reflection; | ||||
| using System.Runtime.InteropServices; | ||||
| using Spectre.Console; | ||||
|  | ||||
| namespace Sample | ||||
| { | ||||
|     public static class Program | ||||
|     { | ||||
|         public static void Main(string[] args) | ||||
|         { | ||||
|             // Use the static API to write some things to the console. | ||||
|             AnsiConsole.Foreground = Color.Chartreuse2; | ||||
|             AnsiConsole.Style = Styles.Underline | Styles.Bold; | ||||
|             AnsiConsole.WriteLine("Hello World!"); | ||||
|             AnsiConsole.Reset(); | ||||
|             AnsiConsole.WriteLine($"Capabilities: {AnsiConsole.Capabilities}"); | ||||
|             AnsiConsole.WriteLine($"Width={AnsiConsole.Width}, Height={AnsiConsole.Height}"); | ||||
|             AnsiConsole.WriteLine("Good bye!"); | ||||
|             AnsiConsole.WriteLine(); | ||||
|  | ||||
|             // We can get the default console via the static API. | ||||
|             var console = AnsiConsole.Console; | ||||
|  | ||||
|             // Or you can build it yourself the old fashion way. | ||||
|             console = AnsiConsole.Create( | ||||
|                 new AnsiConsoleSettings() | ||||
|                 { | ||||
|                     Ansi = AnsiSupport.Yes, | ||||
|                     ColorSystem = ColorSystemSupport.Standard, | ||||
|                     Out = Console.Out, | ||||
|                 }); | ||||
|  | ||||
|             // In this case, we will find the closest colors | ||||
|             // and downgrade them to the specified color system. | ||||
|             console.Foreground = Color.Chartreuse2; | ||||
|             console.Style = Styles.Underline | Styles.Bold; | ||||
|             console.WriteLine("Hello World!"); | ||||
|             console.ResetColors(); | ||||
|             console.ResetStyle(); | ||||
|             console.WriteLine($"Capabilities: {console.Capabilities}"); | ||||
|             console.WriteLine($"Width={AnsiConsole.Width}, Height={AnsiConsole.Height}"); | ||||
|             console.WriteLine("Good bye!"); | ||||
|             console.WriteLine(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -21,3 +21,6 @@ dotnet_diagnostic.CA1034.severity = none | ||||
|  | ||||
| # CA2000: Dispose objects before losing scope | ||||
| dotnet_diagnostic.CA2000.severity = none | ||||
|  | ||||
| # SA1118: Parameter should not span multiple lines | ||||
| dotnet_diagnostic.SA1118.severity = none | ||||
|   | ||||
| @@ -1,47 +0,0 @@ | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests | ||||
| { | ||||
|     public partial class AnsiConsoleTests | ||||
|     { | ||||
|         [Theory] | ||||
|         [InlineData(Styles.Bold, "\u001b[1mHello World[0m")] | ||||
|         [InlineData(Styles.Dim, "\u001b[2mHello World[0m")] | ||||
|         [InlineData(Styles.Italic, "\u001b[3mHello World[0m")] | ||||
|         [InlineData(Styles.Underline, "\u001b[4mHello World[0m")] | ||||
|         [InlineData(Styles.Invert, "\u001b[7mHello World[0m")] | ||||
|         [InlineData(Styles.Conceal, "\u001b[8mHello World[0m")] | ||||
|         [InlineData(Styles.SlowBlink, "\u001b[5mHello World[0m")] | ||||
|         [InlineData(Styles.RapidBlink, "\u001b[6mHello World[0m")] | ||||
|         [InlineData(Styles.Strikethrough, "\u001b[9mHello World[0m")] | ||||
|         public void Should_Write_Style_Correctly(Styles style, string expected) | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.TrueColor); | ||||
|             fixture.Console.Style = style; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello World"); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output.ShouldBe(expected); | ||||
|         } | ||||
|  | ||||
|         [Theory] | ||||
|         [InlineData(Styles.Bold | Styles.Underline, "\u001b[1;4mHello World[0m")] | ||||
|         [InlineData(Styles.Bold | Styles.Underline | Styles.Conceal, "\u001b[1;4;8mHello World[0m")] | ||||
|         public void Should_Write_Combined_Styles_Correctly(Styles style, string expected) | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.TrueColor); | ||||
|             fixture.Console.Style = style; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello World"); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output.ShouldBe(expected); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,72 +0,0 @@ | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests | ||||
| { | ||||
|     public partial class AnsiConsoleTests | ||||
|     { | ||||
|         [Fact] | ||||
|         public void Should_Combine_Style_And_Colors() | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.Standard); | ||||
|             fixture.Console.Foreground = Color.RoyalBlue1; | ||||
|             fixture.Console.Background = Color.NavajoWhite1; | ||||
|             fixture.Console.Style = Styles.Italic; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello"); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output.ShouldBe("\u001b[3;90;47mHello\u001b[0m"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Not_Include_Foreground_If_Set_To_Default_Color() | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.Standard); | ||||
|             fixture.Console.Foreground = Color.Default; | ||||
|             fixture.Console.Background = Color.NavajoWhite1; | ||||
|             fixture.Console.Style = Styles.Italic; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello"); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output.ShouldBe("\u001b[3;47mHello\u001b[0m"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Not_Include_Background_If_Set_To_Default_Color() | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.Standard); | ||||
|             fixture.Console.Foreground = Color.RoyalBlue1; | ||||
|             fixture.Console.Background = Color.Default; | ||||
|             fixture.Console.Style = Styles.Italic; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello"); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output.ShouldBe("\u001b[3;90mHello\u001b[0m"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Not_Include_Style_If_Set_To_None() | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.Standard); | ||||
|             fixture.Console.Foreground = Color.RoyalBlue1; | ||||
|             fixture.Console.Background = Color.NavajoWhite1; | ||||
|             fixture.Console.Style = Styles.None; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello"); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output.ShouldBe("\u001b[90;47mHello\u001b[0m"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										13
									
								
								src/Spectre.Console.Tests/Extensions/StringExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/Spectre.Console.Tests/Extensions/StringExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console.Tests | ||||
| { | ||||
|     public static class StringExtensions | ||||
|     { | ||||
|         public static string NormalizeLineEndings(this string text) | ||||
|         { | ||||
|             return text?.Replace("\r\n", "\n", StringComparison.OrdinalIgnoreCase) | ||||
|                 ?.Replace("\r", string.Empty, StringComparison.OrdinalIgnoreCase); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -11,16 +11,17 @@ namespace Spectre.Console.Tests | ||||
| 
 | ||||
|         public string Output => _writer.ToString(); | ||||
| 
 | ||||
|         public AnsiConsoleFixture(ColorSystem system) | ||||
|         public AnsiConsoleFixture(ColorSystem system, AnsiSupport ansi = AnsiSupport.Yes, int width = 80) | ||||
|         { | ||||
|             _writer = new StringWriter(); | ||||
| 
 | ||||
|             Console = AnsiConsole.Create(new AnsiConsoleSettings | ||||
|             { | ||||
|                 Ansi = AnsiSupport.Yes, | ||||
|                 ColorSystem = (ColorSystemSupport)system, | ||||
|                 Out = _writer, | ||||
|             }); | ||||
|             Console = new ConsoleWithWidth( | ||||
|                 AnsiConsole.Create(new AnsiConsoleSettings | ||||
|                 { | ||||
|                     Ansi = ansi, | ||||
|                     ColorSystem = (ColorSystemSupport)system, | ||||
|                     Out = _writer, | ||||
|                 }), width); | ||||
|         } | ||||
| 
 | ||||
|         public void Dispose() | ||||
							
								
								
									
										31
									
								
								src/Spectre.Console.Tests/Fixtures/ConsoleWithWidth.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/Spectre.Console.Tests/Fixtures/ConsoleWithWidth.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| using System.Text; | ||||
|  | ||||
| namespace Spectre.Console.Tests | ||||
| { | ||||
|     public sealed class ConsoleWithWidth : IAnsiConsole | ||||
|     { | ||||
|         private readonly IAnsiConsole _console; | ||||
|  | ||||
|         public Capabilities Capabilities => _console.Capabilities; | ||||
|  | ||||
|         public int Width { get; } | ||||
|         public int Height => _console.Height; | ||||
|  | ||||
|         public Encoding Encoding => _console.Encoding; | ||||
|  | ||||
|         public Decoration Decoration { get => _console.Decoration; set => _console.Decoration = value; } | ||||
|         public Color Foreground { get => _console.Foreground; set => _console.Foreground = value; } | ||||
|         public Color Background { get => _console.Background; set => _console.Background = value; } | ||||
|  | ||||
|         public ConsoleWithWidth(IAnsiConsole console, int width) | ||||
|         { | ||||
|             _console = console; | ||||
|             Width = width; | ||||
|         } | ||||
|  | ||||
|         public void Write(string text) | ||||
|         { | ||||
|             _console.Write(text); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										47
									
								
								src/Spectre.Console.Tests/Fixtures/PlainConsole.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/Spectre.Console.Tests/Fixtures/PlainConsole.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
|  | ||||
| namespace Spectre.Console.Tests | ||||
| { | ||||
|     public sealed class PlainConsole : IAnsiConsole, IDisposable | ||||
|     { | ||||
|         public Capabilities Capabilities { get; } | ||||
|         public Encoding Encoding { get; } | ||||
|  | ||||
|         public int Width { get; } | ||||
|         public int Height { get; } | ||||
|  | ||||
|         public Decoration Decoration { get; set; } | ||||
|         public Color Foreground { get; set; } | ||||
|         public Color Background { get; set; } | ||||
|  | ||||
|         public StringWriter Writer { get; } | ||||
|         public string RawOutput => Writer.ToString(); | ||||
|         public string Output => Writer.ToString().TrimEnd('\n'); | ||||
|         public IReadOnlyList<string> Lines => Output.Split(new char[] { '\n' }); | ||||
|  | ||||
|         public PlainConsole( | ||||
|             int width = 80, int height = 9000, Encoding encoding = null, | ||||
|             bool supportsAnsi = true, ColorSystem colorSystem = ColorSystem.Standard, | ||||
|             bool legacyConsole = false) | ||||
|         { | ||||
|             Capabilities = new Capabilities(supportsAnsi, colorSystem, legacyConsole); | ||||
|             Encoding = encoding ?? Encoding.UTF8; | ||||
|             Width = width; | ||||
|             Height = height; | ||||
|             Writer = new StringWriter(); | ||||
|         } | ||||
|  | ||||
|         public void Dispose() | ||||
|         { | ||||
|             Writer.Dispose(); | ||||
|         } | ||||
|  | ||||
|         public void Write(string text) | ||||
|         { | ||||
|             Writer.Write(text); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -2,16 +2,17 @@ | ||||
|  | ||||
|   <PropertyGroup> | ||||
|     <TargetFramework>netcoreapp3.1</TargetFramework> | ||||
|  | ||||
|     <IsPackable>false</IsPackable> | ||||
|   </PropertyGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" /> | ||||
|     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" /> | ||||
|     <PackageReference Include="Shouldly" Version="4.0.0-beta0002" /> | ||||
|     <PackageReference Include="xunit" Version="2.4.0" /> | ||||
|     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> | ||||
|     <PackageReference Include="coverlet.collector" Version="1.2.0" /> | ||||
|     <PackageReference Include="xunit" Version="2.4.1" /> | ||||
|     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> | ||||
|       <PrivateAssets>all</PrivateAssets> | ||||
|       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||||
|     </PackageReference> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
| 
 | ||||
| namespace Spectre.Console.Tests | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public partial class AnsiConsoleTests | ||||
|     { | ||||
							
								
								
									
										89
									
								
								src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Markup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Markup.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| using System; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public partial class AnsiConsoleTests | ||||
|     { | ||||
|         [SuppressMessage("Naming", "CA1724:Type names should not match namespaces")] | ||||
|         public sealed class Markup | ||||
|         { | ||||
|             [Theory] | ||||
|             [InlineData("[yellow]Hello[/]", "[93mHello[0m")] | ||||
|             [InlineData("[yellow]Hello [italic]World[/]![/]", "[93mHello[0m[93m [0m[3;93mWorld[0m[93m![0m")] | ||||
|             public void Should_Output_Expected_Ansi_For_Markup(string markup, string expected) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, AnsiSupport.Yes); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Markup(markup); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe(expected); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData("[yellow]Hello [[ World[/]", "[93mHello[0m[93m [0m[93m[[0m[93m [0m[93mWorld[0m")] | ||||
|             public void Should_Be_Able_To_Escape_Tags(string markup, string expected) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, AnsiSupport.Yes); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Markup(markup); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe(expected); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData("[yellow]Hello[", "Encountered malformed markup tag at position 14.")] | ||||
|             [InlineData("[yellow]Hello[/", "Encountered malformed markup tag at position 15.")] | ||||
|             [InlineData("[yellow]Hello[/foo", "Encountered malformed markup tag at position 15.")] | ||||
|             [InlineData("[yellow Hello", "Encountered malformed markup tag at position 13.")] | ||||
|             public void Should_Throw_If_Encounters_Malformed_Tag(string markup, string expected) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, AnsiSupport.Yes); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => fixture.Console.Markup(markup)); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>() | ||||
|                     .Message.ShouldBe(expected); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Tags_Are_Unbalanced() | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, AnsiSupport.Yes); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => fixture.Console.Markup("[yellow][blue]Hello[/]")); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>() | ||||
|                     .Message.ShouldBe("Unbalanced markup stack. Did you forget to close a tag?"); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Encounters_Closing_Tag() | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, AnsiSupport.Yes); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => fixture.Console.Markup("Hello[/]World")); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>() | ||||
|                     .Message.ShouldBe("Encountered closing tag when none was expected near position 5."); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										47
									
								
								src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Style.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/Spectre.Console.Tests/Unit/AnsiConsoleTests.Style.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public partial class AnsiConsoleTests | ||||
|     { | ||||
|         [Theory] | ||||
|         [InlineData(Decoration.Bold, "\u001b[1mHello World[0m")] | ||||
|         [InlineData(Decoration.Dim, "\u001b[2mHello World[0m")] | ||||
|         [InlineData(Decoration.Italic, "\u001b[3mHello World[0m")] | ||||
|         [InlineData(Decoration.Underline, "\u001b[4mHello World[0m")] | ||||
|         [InlineData(Decoration.Invert, "\u001b[7mHello World[0m")] | ||||
|         [InlineData(Decoration.Conceal, "\u001b[8mHello World[0m")] | ||||
|         [InlineData(Decoration.SlowBlink, "\u001b[5mHello World[0m")] | ||||
|         [InlineData(Decoration.RapidBlink, "\u001b[6mHello World[0m")] | ||||
|         [InlineData(Decoration.Strikethrough, "\u001b[9mHello World[0m")] | ||||
|         public void Should_Write_Decorated_Text_Correctly(Decoration decoration, string expected) | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.TrueColor); | ||||
|             fixture.Console.Decoration = decoration; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello World"); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output.ShouldBe(expected); | ||||
|         } | ||||
|  | ||||
|         [Theory] | ||||
|         [InlineData(Decoration.Bold | Decoration.Underline, "\u001b[1;4mHello World[0m")] | ||||
|         [InlineData(Decoration.Bold | Decoration.Underline | Decoration.Conceal, "\u001b[1;4;8mHello World[0m")] | ||||
|         public void Should_Write_Text_With_Multiple_Decorations_Correctly(Decoration decoration, string expected) | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.TrueColor); | ||||
|             fixture.Console.Decoration = decoration; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello World"); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output.ShouldBe(expected); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										452
									
								
								src/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										452
									
								
								src/Spectre.Console.Tests/Unit/AnsiConsoleTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,452 @@ | ||||
| using System; | ||||
| using System.Globalization; | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public partial class AnsiConsoleTests | ||||
|     { | ||||
|         [Fact] | ||||
|         public void Should_Combine_Decoration_And_Colors() | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.Standard); | ||||
|             fixture.Console.Foreground = Color.RoyalBlue1; | ||||
|             fixture.Console.Background = Color.NavajoWhite1; | ||||
|             fixture.Console.Decoration = Decoration.Italic; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello"); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output.ShouldBe("\u001b[3;90;47mHello\u001b[0m"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Not_Include_Foreground_If_Set_To_Default_Color() | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.Standard); | ||||
|             fixture.Console.Foreground = Color.Default; | ||||
|             fixture.Console.Background = Color.NavajoWhite1; | ||||
|             fixture.Console.Decoration = Decoration.Italic; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello"); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output.ShouldBe("\u001b[3;47mHello\u001b[0m"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Not_Include_Background_If_Set_To_Default_Color() | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.Standard); | ||||
|             fixture.Console.Foreground = Color.RoyalBlue1; | ||||
|             fixture.Console.Background = Color.Default; | ||||
|             fixture.Console.Decoration = Decoration.Italic; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello"); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output.ShouldBe("\u001b[3;90mHello\u001b[0m"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Not_Include_Decoration_If_Set_To_None() | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.Standard); | ||||
|             fixture.Console.Foreground = Color.RoyalBlue1; | ||||
|             fixture.Console.Background = Color.NavajoWhite1; | ||||
|             fixture.Console.Decoration = Decoration.None; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello"); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output.ShouldBe("\u001b[90;47mHello\u001b[0m"); | ||||
|         } | ||||
|  | ||||
|         public sealed class Write | ||||
|         { | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Int32_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Write(CultureInfo.InvariantCulture, 32); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32"); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_UInt32_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Write(CultureInfo.InvariantCulture, 32U); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32"); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Int64_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Write(CultureInfo.InvariantCulture, 32L); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32"); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_UInt64_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Write(CultureInfo.InvariantCulture, 32UL); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32"); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Single_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Write(CultureInfo.InvariantCulture, 32.432F); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32.432"); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Double_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Write(CultureInfo.InvariantCulture, (double)32.432); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32.432"); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Decimal_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Write(CultureInfo.InvariantCulture, 32.432M); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32.432"); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Boolean_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Write(CultureInfo.InvariantCulture, true); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("True"); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Char_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Write(CultureInfo.InvariantCulture, 'P'); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("P"); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Char_Array_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Write( | ||||
|                     CultureInfo.InvariantCulture, | ||||
|                     new[] { 'P', 'a', 't', 'r', 'i', 'k' }); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("Patrik"); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Formatted_String_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Write( | ||||
|                     CultureInfo.InvariantCulture, | ||||
|                     "Hello {0}! {1}", | ||||
|                     "World", 32); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("Hello World! 32"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class WriteLine | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Reset_Colors_Correctly_After_Line_Break() | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, AnsiSupport.Yes); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Background = ConsoleColor.Red; | ||||
|                 fixture.Console.WriteLine("Hello"); | ||||
|                 fixture.Console.Background = ConsoleColor.Green; | ||||
|                 fixture.Console.WriteLine("World"); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.NormalizeLineEndings() | ||||
|                     .ShouldBe("[101mHello[0m\n[102mWorld[0m\n"); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Reset_Colors_Correctly_After_Line_Break_In_Text() | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, AnsiSupport.Yes); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Background = ConsoleColor.Red; | ||||
|                 fixture.Console.WriteLine("Hello\nWorld"); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.NormalizeLineEndings() | ||||
|                     .ShouldBe("[101mHello[0m\n[101mWorld[0m\n"); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Int32_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.WriteLine(CultureInfo.InvariantCulture, 32); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32" + Environment.NewLine); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_UInt32_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.WriteLine(CultureInfo.InvariantCulture, 32U); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32" + Environment.NewLine); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Int64_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.WriteLine(CultureInfo.InvariantCulture, 32L); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32" + Environment.NewLine); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_UInt64_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.WriteLine(CultureInfo.InvariantCulture, 32UL); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32" + Environment.NewLine); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Single_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.WriteLine(CultureInfo.InvariantCulture, 32.432F); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32.432" + Environment.NewLine); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Double_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.WriteLine(CultureInfo.InvariantCulture, (double)32.432); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32.432" + Environment.NewLine); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Decimal_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.WriteLine(CultureInfo.InvariantCulture, 32.432M); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("32.432" + Environment.NewLine); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Boolean_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.WriteLine(CultureInfo.InvariantCulture, true); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("True" + Environment.NewLine); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Char_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.WriteLine(CultureInfo.InvariantCulture, 'P'); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("P" + Environment.NewLine); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Char_Array_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.WriteLine( | ||||
|                     CultureInfo.InvariantCulture, | ||||
|                     new[] { 'P', 'a', 't', 'r', 'i', 'k' }); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("Patrik" + Environment.NewLine); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(AnsiSupport.Yes)] | ||||
|             [InlineData(AnsiSupport.No)] | ||||
|             public void Should_Write_Formatted_String_With_Format_Provider(AnsiSupport ansi) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, ansi); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.WriteLine( | ||||
|                     CultureInfo.InvariantCulture, | ||||
|                     "Hello {0}! {1}", | ||||
|                     "World", 32); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output.ShouldBe("Hello World! 32" + Environment.NewLine); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										42
									
								
								src/Spectre.Console.Tests/Unit/BorderTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/Spectre.Console.Tests/Unit/BorderTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| using System; | ||||
| using Shouldly; | ||||
| using Spectre.Console.Composition; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public sealed class BorderTests | ||||
|     { | ||||
|         public sealed class TheGetBorderMethod | ||||
|         { | ||||
|             [Theory] | ||||
|             [InlineData(BorderKind.None, false, typeof(NoBorder))] | ||||
|             [InlineData(BorderKind.Ascii, false, typeof(AsciiBorder))] | ||||
|             [InlineData(BorderKind.Square, false, typeof(SquareBorder))] | ||||
|             [InlineData(BorderKind.Rounded, false, typeof(RoundedBorder))] | ||||
|             [InlineData(BorderKind.None, true, typeof(NoBorder))] | ||||
|             [InlineData(BorderKind.Ascii, true, typeof(AsciiBorder))] | ||||
|             [InlineData(BorderKind.Square, true, typeof(SquareBorder))] | ||||
|             [InlineData(BorderKind.Rounded, true, typeof(SquareBorder))] | ||||
|             public void Should_Return_Correct_Border_For_Specified_Kind(BorderKind kind, bool safe, Type expected) | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Border.GetBorder(kind, safe); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType(expected); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Unknown_Border_Kind_Is_Specified() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Record.Exception(() => Border.GetBorder((BorderKind)int.MaxValue, false)); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>(); | ||||
|                 result.Message.ShouldBe("Unknown border kind"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										254
									
								
								src/Spectre.Console.Tests/Unit/ColorTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								src/Spectre.Console.Tests/Unit/ColorTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,254 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public sealed class ColorTests | ||||
|     { | ||||
|         public sealed class TheEqualsMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Consider_Color_And_Non_Color_Equal() | ||||
|             { | ||||
|                 // Given | ||||
|                 var color1 = new Color(128, 0, 128); | ||||
|  | ||||
|                 // When | ||||
|                 var result = color1.Equals("Foo"); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeFalse(); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Consider_Same_Colors_Equal_By_Component() | ||||
|             { | ||||
|                 // Given | ||||
|                 var color1 = new Color(128, 0, 128); | ||||
|                 var color2 = new Color(128, 0, 128); | ||||
|  | ||||
|                 // When | ||||
|                 var result = color1.Equals(color2); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeTrue(); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Consider_Same_Known_Colors_Equal() | ||||
|             { | ||||
|                 // Given | ||||
|                 var color1 = Color.Cyan1; | ||||
|                 var color2 = Color.Cyan1; | ||||
|  | ||||
|                 // When | ||||
|                 var result = color1.Equals(color2); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeTrue(); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Consider_Known_Color_And_Color_With_Same_Components_Equal() | ||||
|             { | ||||
|                 // Given | ||||
|                 var color1 = Color.Cyan1; | ||||
|                 var color2 = new Color(0, 255, 255); | ||||
|  | ||||
|                 // When | ||||
|                 var result = color1.Equals(color2); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeTrue(); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Not_Consider_Different_Colors_Equal() | ||||
|             { | ||||
|                 // Given | ||||
|                 var color1 = new Color(128, 0, 128); | ||||
|                 var color2 = new Color(128, 128, 128); | ||||
|  | ||||
|                 // When | ||||
|                 var result = color1.Equals(color2); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeFalse(); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Shourd_Not_Consider_Black_And_Default_Colors_Equal() | ||||
|             { | ||||
|                 // Given | ||||
|                 var color1 = Color.Default; | ||||
|                 var color2 = Color.Black; | ||||
|  | ||||
|                 // When | ||||
|                 var result = color1.Equals(color2); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeFalse(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class TheGetHashCodeMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Return_Same_HashCode_For_Same_Colors() | ||||
|             { | ||||
|                 // Given | ||||
|                 var color1 = new Color(128, 0, 128); | ||||
|                 var color2 = new Color(128, 0, 128); | ||||
|  | ||||
|                 // When | ||||
|                 var hash1 = color1.GetHashCode(); | ||||
|                 var hash2 = color2.GetHashCode(); | ||||
|  | ||||
|                 // Then | ||||
|                 hash1.ShouldBe(hash2); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Return_Different_HashCode_For_Different_Colors() | ||||
|             { | ||||
|                 // Given | ||||
|                 var color1 = new Color(128, 0, 128); | ||||
|                 var color2 = new Color(128, 128, 128); | ||||
|  | ||||
|                 // When | ||||
|                 var hash1 = color1.GetHashCode(); | ||||
|                 var hash2 = color2.GetHashCode(); | ||||
|  | ||||
|                 // Then | ||||
|                 hash1.ShouldNotBe(hash2); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class ImplicitConversions | ||||
|         { | ||||
|             public sealed class Int32ToColor | ||||
|             { | ||||
|                 public static IEnumerable<object[]> Data => | ||||
|                     Enumerable.Range(0, 255) | ||||
|                         .Select(number => new object[] { number }); | ||||
|  | ||||
|                 [Theory] | ||||
|                 [MemberData(nameof(Data))] | ||||
|                 public void Should_Return_Expected_Color(int number) | ||||
|                 { | ||||
|                     // Given, When | ||||
|                     var result = (Color)number; | ||||
|  | ||||
|                     // Then | ||||
|                     result.ShouldBe(Color.FromInt32(number)); | ||||
|                 } | ||||
|  | ||||
|                 [Fact] | ||||
|                 public void Should_Throw_If_Integer_Is_Lower_Than_Zero() | ||||
|                 { | ||||
|                     // Given, When | ||||
|                     var result = Record.Exception(() => (Color)(-1)); | ||||
|  | ||||
|                     // Then | ||||
|                     result.ShouldBeOfType<InvalidOperationException>(); | ||||
|                     result.Message.ShouldBe("Color number must be between 0 and 255"); | ||||
|                 } | ||||
|  | ||||
|                 [Fact] | ||||
|                 public void Should_Throw_If_Integer_Is_Higher_Than_255() | ||||
|                 { | ||||
|                     // Given, When | ||||
|                     var result = Record.Exception(() => (Color)256); | ||||
|  | ||||
|                     // Then | ||||
|                     result.ShouldBeOfType<InvalidOperationException>(); | ||||
|                     result.Message.ShouldBe("Color number must be between 0 and 255"); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             public sealed class ConsoleColorToColor | ||||
|             { | ||||
|                 [Theory] | ||||
|                 [InlineData(ConsoleColor.Black, 0)] | ||||
|                 [InlineData(ConsoleColor.DarkRed, 1)] | ||||
|                 [InlineData(ConsoleColor.DarkGreen, 2)] | ||||
|                 [InlineData(ConsoleColor.DarkYellow, 3)] | ||||
|                 [InlineData(ConsoleColor.DarkBlue, 4)] | ||||
|                 [InlineData(ConsoleColor.DarkMagenta, 5)] | ||||
|                 [InlineData(ConsoleColor.DarkCyan, 6)] | ||||
|                 [InlineData(ConsoleColor.Gray, 7)] | ||||
|                 [InlineData(ConsoleColor.DarkGray, 8)] | ||||
|                 [InlineData(ConsoleColor.Red, 9)] | ||||
|                 [InlineData(ConsoleColor.Green, 10)] | ||||
|                 [InlineData(ConsoleColor.Yellow, 11)] | ||||
|                 [InlineData(ConsoleColor.Blue, 12)] | ||||
|                 [InlineData(ConsoleColor.Magenta, 13)] | ||||
|                 [InlineData(ConsoleColor.Cyan, 14)] | ||||
|                 [InlineData(ConsoleColor.White, 15)] | ||||
|                 public void Should_Return_Expected_Color(ConsoleColor color, int expected) | ||||
|                 { | ||||
|                     // Given, When | ||||
|                     var result = (Color)color; | ||||
|  | ||||
|                     // Then | ||||
|                     result.ShouldBe(Color.FromInt32(expected)); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             public sealed class ColorToConsoleColor | ||||
|             { | ||||
|                 [Theory] | ||||
|                 [InlineData(0, ConsoleColor.Black)] | ||||
|                 [InlineData(1, ConsoleColor.DarkRed)] | ||||
|                 [InlineData(2, ConsoleColor.DarkGreen)] | ||||
|                 [InlineData(3, ConsoleColor.DarkYellow)] | ||||
|                 [InlineData(4, ConsoleColor.DarkBlue)] | ||||
|                 [InlineData(5, ConsoleColor.DarkMagenta)] | ||||
|                 [InlineData(6, ConsoleColor.DarkCyan)] | ||||
|                 [InlineData(7, ConsoleColor.Gray)] | ||||
|                 [InlineData(8, ConsoleColor.DarkGray)] | ||||
|                 [InlineData(9, ConsoleColor.Red)] | ||||
|                 [InlineData(10, ConsoleColor.Green)] | ||||
|                 [InlineData(11, ConsoleColor.Yellow)] | ||||
|                 [InlineData(12, ConsoleColor.Blue)] | ||||
|                 [InlineData(13, ConsoleColor.Magenta)] | ||||
|                 [InlineData(14, ConsoleColor.Cyan)] | ||||
|                 [InlineData(15, ConsoleColor.White)] | ||||
|                 public void Should_Return_Expected_ConsoleColor_For_Known_Color(int color, ConsoleColor expected) | ||||
|                 { | ||||
|                     // Given, When | ||||
|                     var result = (ConsoleColor)Color.FromInt32(color); | ||||
|  | ||||
|                     // Then | ||||
|                     result.ShouldBe(expected); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class TheToStringMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Return_Color_Name_For_Known_Colors() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var name = Color.Fuchsia.ToString(); | ||||
|  | ||||
|                 // Then | ||||
|                 name.ShouldBe("fuchsia"); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Return_Hex_String_For_Unknown_Colors() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var name = new Color(128, 0, 128).ToString(); | ||||
|  | ||||
|                 // Then | ||||
|                 name.ShouldBe("#800080 (RGB=128,0,128)"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										210
									
								
								src/Spectre.Console.Tests/Unit/GridTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								src/Spectre.Console.Tests/Unit/GridTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | ||||
| using System; | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public sealed class GridTests | ||||
|     { | ||||
|         public sealed class TheAddColumnMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Rows_Are_Not_Empty() | ||||
|             { | ||||
|                 // Given | ||||
|                 var grid = new Grid(); | ||||
|                 grid.AddColumn(); | ||||
|                 grid.AddRow("Hello World!"); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => grid.AddColumn()); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>() | ||||
|                     .Message.ShouldBe("Cannot add new columns to grid with existing rows."); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class TheAddRowMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Rows_Are_Null() | ||||
|             { | ||||
|                 // Given | ||||
|                 var grid = new Grid(); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => grid.AddRow(null)); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<ArgumentNullException>() | ||||
|                     .ParamName.ShouldBe("columns"); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Row_Columns_Is_Less_Than_Number_Of_Columns() | ||||
|             { | ||||
|                 // Given | ||||
|                 var grid = new Grid(); | ||||
|                 grid.AddColumn(); | ||||
|                 grid.AddColumn(); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => grid.AddRow("Foo")); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>(); | ||||
|                 result.Message.ShouldBe("The number of row columns are less than the number of grid columns."); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Row_Columns_Are_Greater_Than_Number_Of_Columns() | ||||
|             { | ||||
|                 // Given | ||||
|                 var grid = new Grid(); | ||||
|                 grid.AddColumn(); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => grid.AddRow("Foo", "Bar")); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>(); | ||||
|                 result.Message.ShouldBe("The number of row columns are greater than the number of grid columns."); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class TheAddEmptyRowMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Add_Empty_Row() | ||||
|             { | ||||
|                 // Given | ||||
|                 var console = new PlainConsole(width: 80); | ||||
|                 var grid = new Grid(); | ||||
|                 grid.AddColumns(2); | ||||
|                 grid.AddRow("Foo", "Bar"); | ||||
|                 grid.AddEmptyRow(); | ||||
|                 grid.AddRow("Qux", "Corgi"); | ||||
|  | ||||
|                 // When | ||||
|                 console.Render(grid); | ||||
|  | ||||
|                 // Then | ||||
|                 console.Lines.Count.ShouldBe(3); | ||||
|                 console.Lines[0].ShouldBe("Foo  Bar  "); | ||||
|                 console.Lines[1].ShouldBe("          "); | ||||
|                 console.Lines[2].ShouldBe("Qux  Corgi"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Grid_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var grid = new Grid(); | ||||
|             grid.AddColumn(); | ||||
|             grid.AddColumn(); | ||||
|             grid.AddColumn(); | ||||
|             grid.AddRow("Qux", "Corgi", "Waldo"); | ||||
|             grid.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|             // When | ||||
|             console.Render(grid); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(2); | ||||
|             console.Lines[0].ShouldBe("Qux     Corgi   Waldo"); | ||||
|             console.Lines[1].ShouldBe("Grault  Garply  Fred "); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Grid_Column_Alignment_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var grid = new Grid(); | ||||
|             grid.AddColumn(new GridColumn { Alignment = Justify.Right }); | ||||
|             grid.AddColumn(new GridColumn { Alignment = Justify.Center }); | ||||
|             grid.AddColumn(new GridColumn { Alignment = Justify.Left }); | ||||
|             grid.AddRow("Foo", "Bar", "Baz"); | ||||
|             grid.AddRow("Qux", "Corgi", "Waldo"); | ||||
|             grid.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|             // When | ||||
|             console.Render(grid); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(3); | ||||
|             console.Lines[0].ShouldBe("   Foo   Bar    Baz  "); | ||||
|             console.Lines[1].ShouldBe("   Qux  Corgi   Waldo"); | ||||
|             console.Lines[2].ShouldBe("Grault  Garply  Fred "); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Use_Default_Padding() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var grid = new Grid(); | ||||
|             grid.AddColumns(3); | ||||
|             grid.AddRow("Foo", "Bar", "Baz"); | ||||
|             grid.AddRow("Qux", "Corgi", "Waldo"); | ||||
|             grid.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|             // When | ||||
|             console.Render(grid); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(3); | ||||
|             console.Lines[0].ShouldBe("Foo     Bar     Baz  "); | ||||
|             console.Lines[1].ShouldBe("Qux     Corgi   Waldo"); | ||||
|             console.Lines[2].ShouldBe("Grault  Garply  Fred "); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Explicit_Grid_Column_Padding_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var grid = new Grid(); | ||||
|             grid.AddColumn(new GridColumn { Padding = new Padding(3, 0) }); | ||||
|             grid.AddColumn(new GridColumn { Padding = new Padding(0, 0) }); | ||||
|             grid.AddColumn(new GridColumn { Padding = new Padding(0, 3) }); | ||||
|             grid.AddRow("Foo", "Bar", "Baz"); | ||||
|             grid.AddRow("Qux", "Corgi", "Waldo"); | ||||
|             grid.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|             // When | ||||
|             console.Render(grid); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(3); | ||||
|             console.Lines[0].ShouldBe("   Foo   Bar   Baz     "); | ||||
|             console.Lines[1].ShouldBe("   Qux   Corgi Waldo   "); | ||||
|             console.Lines[2].ShouldBe("   GraultGarplyFred    "); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Grid() | ||||
|         { | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var grid = new Grid(); | ||||
|             grid.AddColumn(new GridColumn { NoWrap = true }); | ||||
|             grid.AddColumn(new GridColumn { Padding = new Padding(2, 0) }); | ||||
|             grid.AddRow("[bold]Options[/]", string.Empty); | ||||
|             grid.AddRow("  [blue]-h[/], [blue]--help[/]", "Show command line help."); | ||||
|             grid.AddRow("  [blue]-c[/], [blue]--configuration[/]", "The configuration to run for.\nThe default for most projects is [green]Debug[/]."); | ||||
|  | ||||
|             // When | ||||
|             console.Render(grid); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(4); | ||||
|             console.Lines[0].ShouldBe("Options                                                         "); | ||||
|             console.Lines[1].ShouldBe("  -h, --help             Show command line help.                "); | ||||
|             console.Lines[2].ShouldBe("  -c, --configuration    The configuration to run for.          "); | ||||
|             console.Lines[3].ShouldBe("                         The default for most projects is Debug."); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										180
									
								
								src/Spectre.Console.Tests/Unit/PanelTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								src/Spectre.Console.Tests/Unit/PanelTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,180 @@ | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public sealed class PanelTests | ||||
|     { | ||||
|         [Fact] | ||||
|         public void Should_Render_Panel() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|  | ||||
|             // When | ||||
|             console.Render(new Panel(new Text("Hello World"))); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(3); | ||||
|             console.Lines[0].ShouldBe("┌─────────────┐"); | ||||
|             console.Lines[1].ShouldBe("│ Hello World │"); | ||||
|             console.Lines[2].ShouldBe("└─────────────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Panel_With_Padding() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|  | ||||
|             // When | ||||
|             console.Render(new Panel(new Text("Hello World")) | ||||
|             { | ||||
|                 Padding = new Padding(3, 5), | ||||
|             }); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(3); | ||||
|             console.Lines[0].ShouldBe("┌───────────────────┐"); | ||||
|             console.Lines[1].ShouldBe("│   Hello World     │"); | ||||
|             console.Lines[2].ShouldBe("└───────────────────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Panel_With_Unicode_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|  | ||||
|             // When | ||||
|             console.Render(new Panel(new Text(" \n💩\n "))); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(5); | ||||
|             console.Lines[0].ShouldBe("┌────┐"); | ||||
|             console.Lines[1].ShouldBe("│    │"); | ||||
|             console.Lines[2].ShouldBe("│ 💩 │"); | ||||
|             console.Lines[3].ShouldBe("│    │"); | ||||
|             console.Lines[4].ShouldBe("└────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Panel_With_Multiple_Lines() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|  | ||||
|             // When | ||||
|             console.Render(new Panel(new Text("Hello World\nFoo Bar"))); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(4); | ||||
|             console.Lines[0].ShouldBe("┌─────────────┐"); | ||||
|             console.Lines[1].ShouldBe("│ Hello World │"); | ||||
|             console.Lines[2].ShouldBe("│ Foo Bar     │"); | ||||
|             console.Lines[3].ShouldBe("└─────────────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Preserve_Explicit_Line_Ending() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var text = new Panel( | ||||
|                 Text.Markup("I heard [underline on blue]you[/] like 📦\n\n\n\nSo I put a 📦 in a 📦")); | ||||
|  | ||||
|             // When | ||||
|             console.Render(text); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(7); | ||||
|             console.Lines[0].ShouldBe("┌───────────────────────┐"); | ||||
|             console.Lines[1].ShouldBe("│ I heard you like 📦   │"); | ||||
|             console.Lines[2].ShouldBe("│                       │"); | ||||
|             console.Lines[3].ShouldBe("│                       │"); | ||||
|             console.Lines[4].ShouldBe("│                       │"); | ||||
|             console.Lines[5].ShouldBe("│ So I put a 📦 in a 📦 │"); | ||||
|             console.Lines[6].ShouldBe("└───────────────────────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Expand_Panel_If_Enabled() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|  | ||||
|             // When | ||||
|             console.Render(new Panel(new Text("Hello World")) | ||||
|             { | ||||
|                 Expand = true, | ||||
|             }); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(3); | ||||
|             console.Lines[0].Length.ShouldBe(80); | ||||
|             console.Lines[0].ShouldBe("┌──────────────────────────────────────────────────────────────────────────────┐"); | ||||
|             console.Lines[1].ShouldBe("│ Hello World                                                                  │"); | ||||
|             console.Lines[2].ShouldBe("└──────────────────────────────────────────────────────────────────────────────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Justify_Child_To_Right() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 25); | ||||
|  | ||||
|             // When | ||||
|             console.Render( | ||||
|                 new Panel( | ||||
|                     new Text("Hello World").WithAlignment(Justify.Right)) | ||||
|                 { | ||||
|                     Expand = true, | ||||
|                 }); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(3); | ||||
|             console.Lines[0].ShouldBe("┌───────────────────────┐"); | ||||
|             console.Lines[1].ShouldBe("│           Hello World │"); | ||||
|             console.Lines[2].ShouldBe("└───────────────────────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Justify_Child_To_Center() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 25); | ||||
|  | ||||
|             // When | ||||
|             console.Render( | ||||
|                 new Panel( | ||||
|                     new Text("Hello World").WithAlignment(Justify.Center)) | ||||
|                 { | ||||
|                     Expand = true, | ||||
|                 }); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(3); | ||||
|             console.Lines[0].ShouldBe("┌───────────────────────┐"); | ||||
|             console.Lines[1].ShouldBe("│      Hello World      │"); | ||||
|             console.Lines[2].ShouldBe("└───────────────────────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Panel_Inside_Panel_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|  | ||||
|             // When | ||||
|             console.Render(new Panel(new Panel(new Text("Hello World")))); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(5); | ||||
|             console.Lines[0].ShouldBe("┌─────────────────┐"); | ||||
|             console.Lines[1].ShouldBe("│ ┌─────────────┐ │"); | ||||
|             console.Lines[2].ShouldBe("│ │ Hello World │ │"); | ||||
|             console.Lines[3].ShouldBe("│ └─────────────┘ │"); | ||||
|             console.Lines[4].ShouldBe("└─────────────────┘"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										92
									
								
								src/Spectre.Console.Tests/Unit/SegmentTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/Spectre.Console.Tests/Unit/SegmentTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| using Shouldly; | ||||
| using Spectre.Console.Composition; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public sealed class SegmentTests | ||||
|     { | ||||
|         public sealed class TheSplitMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Split_Segment_Correctly() | ||||
|             { | ||||
|                 // Given | ||||
|                 var style = new Style(Color.Red, Color.Green, Decoration.Bold); | ||||
|                 var segment = new Segment("Foo Bar", style); | ||||
|  | ||||
|                 // When | ||||
|                 var (first, second) = segment.Split(3); | ||||
|  | ||||
|                 // Then | ||||
|                 first.Text.ShouldBe("Foo"); | ||||
|                 first.Style.ShouldBe(style); | ||||
|                 second.Text.ShouldBe(" Bar"); | ||||
|                 second.Style.ShouldBe(style); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class TheSplitLinesMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Split_Segment() | ||||
|             { | ||||
|                 var lines = Segment.SplitLines( | ||||
|                     new[] | ||||
|                     { | ||||
|                         new Segment("Foo"), | ||||
|                         new Segment("Bar"), | ||||
|                         new Segment("\n"), | ||||
|                         new Segment("Baz"), | ||||
|                         new Segment("Qux"), | ||||
|                         new Segment("\n"), | ||||
|                         new Segment("Corgi"), | ||||
|                     }); | ||||
|  | ||||
|                 // Then | ||||
|                 lines.Count.ShouldBe(3); | ||||
|  | ||||
|                 lines[0].Count.ShouldBe(2); | ||||
|                 lines[0][0].Text.ShouldBe("Foo"); | ||||
|                 lines[0][1].Text.ShouldBe("Bar"); | ||||
|  | ||||
|                 lines[1].Count.ShouldBe(2); | ||||
|                 lines[1][0].Text.ShouldBe("Baz"); | ||||
|                 lines[1][1].Text.ShouldBe("Qux"); | ||||
|  | ||||
|                 lines[2].Count.ShouldBe(1); | ||||
|                 lines[2][0].Text.ShouldBe("Corgi"); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Split_Segments_With_Linebreak_In_Text() | ||||
|             { | ||||
|                 var lines = Segment.SplitLines( | ||||
|                     new[] | ||||
|                     { | ||||
|                         new Segment("Foo\n"), | ||||
|                         new Segment("Bar\n"), | ||||
|                         new Segment("Baz"), | ||||
|                         new Segment("Qux\n"), | ||||
|                         new Segment("Corgi"), | ||||
|                     }); | ||||
|  | ||||
|                 // Then | ||||
|                 lines.Count.ShouldBe(4); | ||||
|  | ||||
|                 lines[0].Count.ShouldBe(1); | ||||
|                 lines[0][0].Text.ShouldBe("Foo"); | ||||
|  | ||||
|                 lines[1].Count.ShouldBe(1); | ||||
|                 lines[1][0].Text.ShouldBe("Bar"); | ||||
|  | ||||
|                 lines[2].Count.ShouldBe(2); | ||||
|                 lines[2][0].Text.ShouldBe("Baz"); | ||||
|                 lines[2][1].Text.ShouldBe("Qux"); | ||||
|  | ||||
|                 lines[3].Count.ShouldBe(1); | ||||
|                 lines[3][0].Text.ShouldBe("Corgi"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										216
									
								
								src/Spectre.Console.Tests/Unit/StyleTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								src/Spectre.Console.Tests/Unit/StyleTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,216 @@ | ||||
| using System; | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public sealed class StyleTests | ||||
|     { | ||||
|         [Fact] | ||||
|         public void Should_Combine_Two_Styles_As_Expected() | ||||
|         { | ||||
|             // Given | ||||
|             var first = new Style(Color.White, Color.Yellow, Decoration.Bold | Decoration.Italic); | ||||
|             var other = new Style(Color.Green, Color.Silver, Decoration.Underline); | ||||
|  | ||||
|             // When | ||||
|             var result = first.Combine(other); | ||||
|  | ||||
|             // Then | ||||
|             result.Foreground.ShouldBe(Color.Green); | ||||
|             result.Background.ShouldBe(Color.Silver); | ||||
|             result.Decoration.ShouldBe(Decoration.Bold | Decoration.Italic | Decoration.Underline); | ||||
|         } | ||||
|  | ||||
|         public sealed class TheParseMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Default_Keyword_Should_Return_Default_Style() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.Parse("default"); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldNotBeNull(); | ||||
|                 result.Foreground.ShouldBe(Color.Default); | ||||
|                 result.Background.ShouldBe(Color.Default); | ||||
|                 result.Decoration.ShouldBe(Decoration.None); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData("bold", Decoration.Bold)] | ||||
|             [InlineData("b", Decoration.Bold)] | ||||
|             [InlineData("dim", Decoration.Dim)] | ||||
|             [InlineData("i", Decoration.Italic)] | ||||
|             [InlineData("italic", Decoration.Italic)] | ||||
|             [InlineData("underline", Decoration.Underline)] | ||||
|             [InlineData("u", Decoration.Underline)] | ||||
|             [InlineData("invert", Decoration.Invert)] | ||||
|             [InlineData("conceal", Decoration.Conceal)] | ||||
|             [InlineData("slowblink", Decoration.SlowBlink)] | ||||
|             [InlineData("rapidblink", Decoration.RapidBlink)] | ||||
|             [InlineData("strikethrough", Decoration.Strikethrough)] | ||||
|             [InlineData("s", Decoration.Strikethrough)] | ||||
|             public void Should_Parse_Decoration(string text, Decoration decoration) | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.Parse(text); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldNotBeNull(); | ||||
|                 result.Decoration.ShouldBe(decoration); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Parse_Text_And_Decoration() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.Parse("bold underline blue on green"); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldNotBeNull(); | ||||
|                 result.Decoration.ShouldBe(Decoration.Bold | Decoration.Underline); | ||||
|                 result.Foreground.ShouldBe(Color.Blue); | ||||
|                 result.Background.ShouldBe(Color.Green); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Parse_Background_If_Foreground_Is_Set_To_Default() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.Parse("default on green"); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldNotBeNull(); | ||||
|                 result.Decoration.ShouldBe(Decoration.None); | ||||
|                 result.Foreground.ShouldBe(Color.Default); | ||||
|                 result.Background.ShouldBe(Color.Green); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Foreground_Is_Set_Twice() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Record.Exception(() => Style.Parse("green yellow")); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>(); | ||||
|                 result.Message.ShouldBe("A foreground color has already been set."); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Background_Is_Set_Twice() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Record.Exception(() => Style.Parse("green on blue yellow")); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>(); | ||||
|                 result.Message.ShouldBe("A background color has already been set."); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Color_Name_Could_Not_Be_Found() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Record.Exception(() => Style.Parse("bold lol")); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>(); | ||||
|                 result.Message.ShouldBe("Could not find color or style 'lol'."); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Background_Color_Name_Could_Not_Be_Found() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Record.Exception(() => Style.Parse("blue on lol")); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>(); | ||||
|                 result.Message.ShouldBe("Could not find color 'lol'."); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData("#FF0000 on #0000FF")] | ||||
|             [InlineData("#F00 on #00F")] | ||||
|             public void Should_Parse_Hex_Colors_Correctly(string style) | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.Parse(style); | ||||
|  | ||||
|                 // Then | ||||
|                 result.Foreground.ShouldBe(Color.Red); | ||||
|                 result.Background.ShouldBe(Color.Blue); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData("#", "Invalid hex color '#'.")] | ||||
|             [InlineData("#FF00FF00FF", "Invalid hex color '#FF00FF00FF'.")] | ||||
|             [InlineData("#FOO", "Invalid hex color '#FOO'. Could not find any recognizable digits.")] | ||||
|             public void Should_Return_Error_If_Hex_Color_Is_Invalid(string style, string expected) | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Record.Exception(() => Style.Parse(style)); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldNotBeNull(); | ||||
|                 result.Message.ShouldBe(expected); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData("rgb(255,0,0) on rgb(0,0,255)")] | ||||
|             public void Should_Parse_Rgb_Colors_Correctly(string style) | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.Parse(style); | ||||
|  | ||||
|                 // Then | ||||
|                 result.Foreground.ShouldBe(Color.Red); | ||||
|                 result.Background.ShouldBe(Color.Blue); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData("rgb()", "Invalid RGB color 'rgb()'.")] | ||||
|             [InlineData("rgb(", "Invalid RGB color 'rgb('.")] | ||||
|             [InlineData("rgb(255)", "Invalid RGB color 'rgb(255)'.")] | ||||
|             [InlineData("rgb(255,255)", "Invalid RGB color 'rgb(255,255)'.")] | ||||
|             [InlineData("rgb(255,255,255", "Invalid RGB color 'rgb(255,255,255'.")] | ||||
|             [InlineData("rgb(A,B,C)", "Invalid RGB color 'rgb(A,B,C)'. Input string was not in a correct format.")] | ||||
|             public void Should_Return_Error_If_Rgb_Color_Is_Invalid(string style, string expected) | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Record.Exception(() => Style.Parse(style)); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldNotBeNull(); | ||||
|                 result.Message.ShouldBe(expected); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class TheTryParseMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Return_True_If_Parsing_Succeeded() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.TryParse("bold", out var style); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeTrue(); | ||||
|                 style.ShouldNotBeNull(); | ||||
|                 style.Decoration.ShouldBe(Decoration.Bold); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Return_False_If_Parsing_Failed() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.TryParse("lol", out _); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeFalse(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										374
									
								
								src/Spectre.Console.Tests/Unit/TableTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										374
									
								
								src/Spectre.Console.Tests/Unit/TableTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,374 @@ | ||||
| using System; | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public sealed class TableTests | ||||
|     { | ||||
|         public sealed class TheAddColumnMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Column_Is_Null() | ||||
|             { | ||||
|                 // Given | ||||
|                 var table = new Table(); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => table.AddColumn((string)null)); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<ArgumentNullException>() | ||||
|                     .ParamName.ShouldBe("column"); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Rows_Are_Not_Empty() | ||||
|             { | ||||
|                 // Given | ||||
|                 var grid = new Table(); | ||||
|                 grid.AddColumn("Foo"); | ||||
|                 grid.AddRow("Hello World"); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => grid.AddColumn("Bar")); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>() | ||||
|                     .Message.ShouldBe("Cannot add new columns to table with existing rows."); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class TheAddColumnsMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Columns_Are_Null() | ||||
|             { | ||||
|                 // Given | ||||
|                 var table = new Table(); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => table.AddColumns((string[])null)); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<ArgumentNullException>() | ||||
|                     .ParamName.ShouldBe("columns"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class TheAddRowMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Rows_Are_Null() | ||||
|             { | ||||
|                 // Given | ||||
|                 var table = new Table(); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => table.AddRow(null)); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<ArgumentNullException>() | ||||
|                     .ParamName.ShouldBe("columns"); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Row_Columns_Is_Less_Than_Number_Of_Columns() | ||||
|             { | ||||
|                 // Given | ||||
|                 var table = new Table(); | ||||
|                 table.AddColumn("Hello"); | ||||
|                 table.AddColumn("World"); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => table.AddRow("Foo")); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>(); | ||||
|                 result.Message.ShouldBe("The number of row columns are less than the number of table columns."); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Row_Columns_Are_Greater_Than_Number_Of_Columns() | ||||
|             { | ||||
|                 // Given | ||||
|                 var table = new Table(); | ||||
|                 table.AddColumn("Hello"); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => table.AddRow("Foo", "Bar")); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<InvalidOperationException>(); | ||||
|                 result.Message.ShouldBe("The number of row columns are greater than the number of table columns."); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class TheAddEmptyRowMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Render_Table_Correctly() | ||||
|             { | ||||
|                 // Given | ||||
|                 var console = new PlainConsole(width: 80); | ||||
|                 var table = new Table(); | ||||
|                 table.AddColumns("Foo", "Bar", "Baz"); | ||||
|                 table.AddRow("Qux", "Corgi", "Waldo"); | ||||
|                 table.AddEmptyRow(); | ||||
|                 table.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|                 // When | ||||
|                 console.Render(table); | ||||
|  | ||||
|                 // Then | ||||
|                 console.Lines.Count.ShouldBe(7); | ||||
|                 console.Lines[0].ShouldBe("┌────────┬────────┬───────┐"); | ||||
|                 console.Lines[1].ShouldBe("│ Foo    │ Bar    │ Baz   │"); | ||||
|                 console.Lines[2].ShouldBe("├────────┼────────┼───────┤"); | ||||
|                 console.Lines[3].ShouldBe("│ Qux    │ Corgi  │ Waldo │"); | ||||
|                 console.Lines[4].ShouldBe("│        │        │       │"); | ||||
|                 console.Lines[5].ShouldBe("│ Grault │ Garply │ Fred  │"); | ||||
|                 console.Lines[6].ShouldBe("└────────┴────────┴───────┘"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Table_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var table = new Table(); | ||||
|             table.AddColumns("Foo", "Bar", "Baz"); | ||||
|             table.AddRow("Qux", "Corgi", "Waldo"); | ||||
|             table.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|             // When | ||||
|             console.Render(table); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(6); | ||||
|             console.Lines[0].ShouldBe("┌────────┬────────┬───────┐"); | ||||
|             console.Lines[1].ShouldBe("│ Foo    │ Bar    │ Baz   │"); | ||||
|             console.Lines[2].ShouldBe("├────────┼────────┼───────┤"); | ||||
|             console.Lines[3].ShouldBe("│ Qux    │ Corgi  │ Waldo │"); | ||||
|             console.Lines[4].ShouldBe("│ Grault │ Garply │ Fred  │"); | ||||
|             console.Lines[5].ShouldBe("└────────┴────────┴───────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Table_Nested_In_Panels_Correctly() | ||||
|         { | ||||
|             // A simple table | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var table = new Table() { Border = BorderKind.Rounded }; | ||||
|             table.AddColumn("Foo"); | ||||
|             table.AddColumn("Bar"); | ||||
|             table.AddColumn(new TableColumn("Baz") { Alignment = Justify.Right }); | ||||
|             table.AddRow("Qux\nQuuuuuux", "[blue]Corgi[/]", "Waldo"); | ||||
|             table.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|             // Render a table in some panels. | ||||
|             console.Render(new Panel(new Panel(table) | ||||
|             { | ||||
|                 Border = BorderKind.Ascii, | ||||
|             })); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(11); | ||||
|             console.Lines[00].ShouldBe("┌───────────────────────────────────┐"); | ||||
|             console.Lines[01].ShouldBe("│ +-------------------------------+ │"); | ||||
|             console.Lines[02].ShouldBe("│ | ╭──────────┬────────┬───────╮ | │"); | ||||
|             console.Lines[03].ShouldBe("│ | │ Foo      │ Bar    │   Baz │ | │"); | ||||
|             console.Lines[04].ShouldBe("│ | ├──────────┼────────┼───────┤ | │"); | ||||
|             console.Lines[05].ShouldBe("│ | │ Qux      │ Corgi  │ Waldo │ | │"); | ||||
|             console.Lines[06].ShouldBe("│ | │ Quuuuuux │        │       │ | │"); | ||||
|             console.Lines[07].ShouldBe("│ | │ Grault   │ Garply │  Fred │ | │"); | ||||
|             console.Lines[08].ShouldBe("│ | ╰──────────┴────────┴───────╯ | │"); | ||||
|             console.Lines[09].ShouldBe("│ +-------------------------------+ │"); | ||||
|             console.Lines[10].ShouldBe("└───────────────────────────────────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Table_With_Column_Justification_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var table = new Table(); | ||||
|             table.AddColumn(new TableColumn("Foo") { Alignment = Justify.Left }); | ||||
|             table.AddColumn(new TableColumn("Bar") { Alignment = Justify.Right }); | ||||
|             table.AddColumn(new TableColumn("Baz") { Alignment = Justify.Center }); | ||||
|             table.AddRow("Qux", "Corgi", "Waldo"); | ||||
|             table.AddRow("Grault", "Garply", "Lorem ipsum dolor sit amet"); | ||||
|  | ||||
|             // When | ||||
|             console.Render(table); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(6); | ||||
|             console.Lines[0].ShouldBe("┌────────┬────────┬────────────────────────────┐"); | ||||
|             console.Lines[1].ShouldBe("│ Foo    │    Bar │            Baz             │"); | ||||
|             console.Lines[2].ShouldBe("├────────┼────────┼────────────────────────────┤"); | ||||
|             console.Lines[3].ShouldBe("│ Qux    │  Corgi │           Waldo            │"); | ||||
|             console.Lines[4].ShouldBe("│ Grault │ Garply │ Lorem ipsum dolor sit amet │"); | ||||
|             console.Lines[5].ShouldBe("└────────┴────────┴────────────────────────────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Expand_Table_To_Available_Space_If_Specified() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var table = new Table() { Expand = true }; | ||||
|             table.AddColumns("Foo", "Bar", "Baz"); | ||||
|             table.AddRow("Qux", "Corgi", "Waldo"); | ||||
|             table.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|             // When | ||||
|             console.Render(table); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(6); | ||||
|             console.Lines[0].Length.ShouldBe(80); | ||||
|             console.Lines[0].ShouldBe("┌───────────────────────────┬───────────────────────────┬──────────────────────┐"); | ||||
|             console.Lines[1].ShouldBe("│ Foo                       │ Bar                       │ Baz                  │"); | ||||
|             console.Lines[2].ShouldBe("├───────────────────────────┼───────────────────────────┼──────────────────────┤"); | ||||
|             console.Lines[3].ShouldBe("│ Qux                       │ Corgi                     │ Waldo                │"); | ||||
|             console.Lines[4].ShouldBe("│ Grault                    │ Garply                    │ Fred                 │"); | ||||
|             console.Lines[5].ShouldBe("└───────────────────────────┴───────────────────────────┴──────────────────────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Table_With_Ascii_Border_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var table = new Table { Border = BorderKind.Ascii }; | ||||
|             table.AddColumns("Foo", "Bar", "Baz"); | ||||
|             table.AddRow("Qux", "Corgi", "Waldo"); | ||||
|             table.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|             // When | ||||
|             console.Render(table); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(6); | ||||
|             console.Lines[0].ShouldBe("+-------------------------+"); | ||||
|             console.Lines[1].ShouldBe("| Foo    | Bar    | Baz   |"); | ||||
|             console.Lines[2].ShouldBe("|--------+--------+-------|"); | ||||
|             console.Lines[3].ShouldBe("| Qux    | Corgi  | Waldo |"); | ||||
|             console.Lines[4].ShouldBe("| Grault | Garply | Fred  |"); | ||||
|             console.Lines[5].ShouldBe("+-------------------------+"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Table_With_Rounded_Border_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var table = new Table { Border = BorderKind.Rounded }; | ||||
|             table.AddColumns("Foo", "Bar", "Baz"); | ||||
|             table.AddRow("Qux", "Corgi", "Waldo"); | ||||
|             table.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|             // When | ||||
|             console.Render(table); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(6); | ||||
|             console.Lines[0].ShouldBe("╭────────┬────────┬───────╮"); | ||||
|             console.Lines[1].ShouldBe("│ Foo    │ Bar    │ Baz   │"); | ||||
|             console.Lines[2].ShouldBe("├────────┼────────┼───────┤"); | ||||
|             console.Lines[3].ShouldBe("│ Qux    │ Corgi  │ Waldo │"); | ||||
|             console.Lines[4].ShouldBe("│ Grault │ Garply │ Fred  │"); | ||||
|             console.Lines[5].ShouldBe("╰────────┴────────┴───────╯"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Table_With_No_Border_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var table = new Table { Border = BorderKind.None }; | ||||
|             table.AddColumns("Foo", "Bar", "Baz"); | ||||
|             table.AddRow("Qux", "Corgi", "Waldo"); | ||||
|             table.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|             // When | ||||
|             console.Render(table); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(3); | ||||
|             console.Lines[0].ShouldBe("Foo    Bar    Baz  "); | ||||
|             console.Lines[1].ShouldBe("Qux    Corgi  Waldo"); | ||||
|             console.Lines[2].ShouldBe("Grault Garply Fred "); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Table_With_Multiple_Rows_In_Cell_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var table = new Table(); | ||||
|             table.AddColumns("Foo", "Bar", "Baz"); | ||||
|             table.AddRow("Qux\nQuuux", "Corgi", "Waldo"); | ||||
|             table.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|             // When | ||||
|             console.Render(table); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(7); | ||||
|             console.Lines[0].ShouldBe("┌────────┬────────┬───────┐"); | ||||
|             console.Lines[1].ShouldBe("│ Foo    │ Bar    │ Baz   │"); | ||||
|             console.Lines[2].ShouldBe("├────────┼────────┼───────┤"); | ||||
|             console.Lines[3].ShouldBe("│ Qux    │ Corgi  │ Waldo │"); | ||||
|             console.Lines[4].ShouldBe("│ Quuux  │        │       │"); | ||||
|             console.Lines[5].ShouldBe("│ Grault │ Garply │ Fred  │"); | ||||
|             console.Lines[6].ShouldBe("└────────┴────────┴───────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Table_With_Cell_Padding_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var table = new Table(); | ||||
|             table.AddColumns("Foo", "Bar"); | ||||
|             table.AddColumn(new TableColumn("Baz") { Padding = new Padding(3, 2) }); | ||||
|             table.AddRow("Qux\nQuuux", "Corgi", "Waldo"); | ||||
|             table.AddRow("Grault", "Garply", "Fred"); | ||||
|  | ||||
|             // When | ||||
|             console.Render(table); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(7); | ||||
|             console.Lines[0].ShouldBe("┌────────┬────────┬──────────┐"); | ||||
|             console.Lines[1].ShouldBe("│ Foo    │ Bar    │   Baz    │"); | ||||
|             console.Lines[2].ShouldBe("├────────┼────────┼──────────┤"); | ||||
|             console.Lines[3].ShouldBe("│ Qux    │ Corgi  │   Waldo  │"); | ||||
|             console.Lines[4].ShouldBe("│ Quuux  │        │          │"); | ||||
|             console.Lines[5].ShouldBe("│ Grault │ Garply │   Fred   │"); | ||||
|             console.Lines[6].ShouldBe("└────────┴────────┴──────────┘"); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Render_Table_Without_Footer_If_No_Rows_Are_Added() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|             var table = new Table(); | ||||
|             table.AddColumns("Foo", "Bar"); | ||||
|             table.AddColumn(new TableColumn("Baz") { Padding = new Padding(3, 2) }); | ||||
|  | ||||
|             // When | ||||
|             console.Render(table); | ||||
|  | ||||
|             // Then | ||||
|             console.Lines.Count.ShouldBe(3); | ||||
|             console.Lines[0].ShouldBe("┌─────┬─────┬────────┐"); | ||||
|             console.Lines[1].ShouldBe("│ Foo │ Bar │   Baz  │"); | ||||
|             console.Lines[2].ShouldBe("└─────┴─────┴────────┘"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										85
									
								
								src/Spectre.Console.Tests/Unit/TextTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/Spectre.Console.Tests/Unit/TextTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| using System.Text; | ||||
| using Shouldly; | ||||
| using Spectre.Console.Composition; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public sealed class TextTests | ||||
|     { | ||||
|         public sealed class Measuring | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Return_The_Longest_Word_As_Minimum_Width() | ||||
|             { | ||||
|                 var text = new Text("Foo Bar Baz\nQux\nLol mobile"); | ||||
|  | ||||
|                 var result = text.Measure(new RenderContext(Encoding.Unicode, false), 80); | ||||
|  | ||||
|                 result.Min.ShouldBe(6); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Return_The_Longest_Line_As_Maximum_Width() | ||||
|             { | ||||
|                 var text = new Text("Foo Bar Baz\nQux\nLol mobile"); | ||||
|  | ||||
|                 var result = text.Measure(new RenderContext(Encoding.Unicode, false), 80); | ||||
|  | ||||
|                 result.Max.ShouldBe(11); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class Rendering | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Render_Unstyled_Text_As_Expected() | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new PlainConsole(width: 80); | ||||
|                 var text = new Text("Hello World"); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Render(text); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output | ||||
|                     .NormalizeLineEndings() | ||||
|                     .ShouldBe("Hello World"); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Write_Line_Breaks() | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new PlainConsole(width: 5); | ||||
|                 var text = new Text("Hello\n\nWorld"); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Render(text); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.RawOutput.ShouldBe("Hello\n\nWorld"); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(5, "Hello World", "Hello\nWorld")] | ||||
|             [InlineData(10, "Hello Sweet Nice World", "Hello \nSweet Nice\nWorld")] | ||||
|             public void Should_Split_Unstyled_Text_To_New_Lines_If_Width_Exceeds_Console_Width( | ||||
|                 int width, string input, string expected) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new PlainConsole(width); | ||||
|                 var text = new Text(input); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Render(text); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output | ||||
|                     .NormalizeLineEndings() | ||||
|                     .ShouldBe(expected); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spectre.Console", "Spectre. | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spectre.Console.Tests", "Spectre.Console.Tests\Spectre.Console.Tests.csproj", "{9F1AC4C1-766E-4421-8A78-B28F5BCDD94F}" | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample", "Sample\Sample.csproj", "{272E6092-BD31-4EB6-A9FF-F4179F91958F}" | ||||
| EndProject | ||||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{20595AD4-8D75-4AF8-B6BC-9C38C160423F}" | ||||
| 	ProjectSection(SolutionItems) = preProject | ||||
| 		.editorconfig = .editorconfig | ||||
| @@ -17,6 +15,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution | ||||
| 		stylecop.json = stylecop.json | ||||
| 	EndProjectSection | ||||
| EndProject | ||||
| Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{F0575243-121F-4DEE-9F6B-246E26DC0844}" | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Table", "..\examples\Table\Table.csproj", "{94ECCBA8-7EBF-4B53-8379-52EB2327417E}" | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Panel", "..\examples\Panel\Panel.csproj", "{BFF37228-B376-4ADD-9657-4E501F929713}" | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grid", "..\examples\Grid\Grid.csproj", "{C7FF6FDB-FB59-4517-8669-521C96AB7323}" | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Colors", "..\examples\Colors\Colors.csproj", "{1F51C55C-BA4C-4856-9001-0F7924FFB179}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|Any CPU = Debug|Any CPU | ||||
| @@ -51,22 +59,64 @@ Global | ||||
| 		{9F1AC4C1-766E-4421-8A78-B28F5BCDD94F}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{9F1AC4C1-766E-4421-8A78-B28F5BCDD94F}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{9F1AC4C1-766E-4421-8A78-B28F5BCDD94F}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{272E6092-BD31-4EB6-A9FF-F4179F91958F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{272E6092-BD31-4EB6-A9FF-F4179F91958F}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{272E6092-BD31-4EB6-A9FF-F4179F91958F}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{272E6092-BD31-4EB6-A9FF-F4179F91958F}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{272E6092-BD31-4EB6-A9FF-F4179F91958F}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{272E6092-BD31-4EB6-A9FF-F4179F91958F}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{272E6092-BD31-4EB6-A9FF-F4179F91958F}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{272E6092-BD31-4EB6-A9FF-F4179F91958F}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{272E6092-BD31-4EB6-A9FF-F4179F91958F}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{272E6092-BD31-4EB6-A9FF-F4179F91958F}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{272E6092-BD31-4EB6-A9FF-F4179F91958F}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{272E6092-BD31-4EB6-A9FF-F4179F91958F}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Release|x86.Build.0 = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(NestedProjects) = preSolution | ||||
| 		{94ECCBA8-7EBF-4B53-8379-52EB2327417E} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | ||||
| 		{BFF37228-B376-4ADD-9657-4E501F929713} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | ||||
| 		{C7FF6FDB-FB59-4517-8669-521C96AB7323} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | ||||
| 		{1F51C55C-BA4C-4856-9001-0F7924FFB179} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ExtensibilityGlobals) = postSolution | ||||
| 		SolutionGuid = {5729B071-67A0-48FB-8B1B-275E6822086C} | ||||
| 	EndGlobalSection | ||||
|   | ||||
							
								
								
									
										52
									
								
								src/Spectre.Console/AnsiConsole.Markup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/Spectre.Console/AnsiConsole.Markup.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void Markup(string format, params object[] args) | ||||
|         { | ||||
|             Console.Markup(format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void Markup(IFormatProvider provider, string format, params object[] args) | ||||
|         { | ||||
|             Console.Markup(provider, format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void MarkupLine(string format, params object[] args) | ||||
|         { | ||||
|             Console.MarkupLine(format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void MarkupLine(IFormatProvider provider, string format, params object[] args) | ||||
|         { | ||||
|             Console.MarkupLine(provider, format, args); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										19
									
								
								src/Spectre.Console/AnsiConsole.Rendering.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/Spectre.Console/AnsiConsole.Rendering.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| using Spectre.Console.Composition; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Renders the specified object to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="renderable">The object to render.</param> | ||||
|         public static void Render(IRenderable renderable) | ||||
|         { | ||||
|             Console.Render(renderable); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										245
									
								
								src/Spectre.Console/AnsiConsole.Write.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								src/Spectre.Console/AnsiConsole.Write.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,245 @@ | ||||
| using System; | ||||
| using System.Globalization; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Writes the specified string value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(string value) | ||||
|         { | ||||
|             Console.Write(value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit | ||||
|         /// signed integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(int value) | ||||
|         { | ||||
|             Console.Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit | ||||
|         /// signed integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, int value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit | ||||
|         /// unsigned integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(uint value) | ||||
|         { | ||||
|             Console.Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit | ||||
|         /// unsigned integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, uint value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit | ||||
|         /// signed integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(long value) | ||||
|         { | ||||
|             Console.Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit | ||||
|         /// signed integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, long value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit | ||||
|         /// unsigned integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(ulong value) | ||||
|         { | ||||
|             Console.Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit | ||||
|         /// unsigned integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, ulong value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified single-precision | ||||
|         /// floating-point value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(float value) | ||||
|         { | ||||
|             Console.Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified single-precision | ||||
|         /// floating-point value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, float value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified double-precision | ||||
|         /// floating-point value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(double value) | ||||
|         { | ||||
|             Console.Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified double-precision | ||||
|         /// floating-point value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, double value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified decimal value, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(decimal value) | ||||
|         { | ||||
|             Console.Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified decimal value, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, decimal value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified boolean value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(bool value) | ||||
|         { | ||||
|             Console.Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified boolean value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, bool value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified Unicode character to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(char value) | ||||
|         { | ||||
|             Console.Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified Unicode character to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, char value) | ||||
|         { | ||||
|             Console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified array of Unicode characters to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(char[] value) | ||||
|         { | ||||
|             Console.Write(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified array of Unicode characters to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(IFormatProvider provider, char[] value) | ||||
|         { | ||||
|             Console.Write(provider, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified array of objects, | ||||
|         /// to the console using the specified format information. | ||||
|         /// </summary> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void Write(string format, params object[] args) | ||||
|         { | ||||
|             Console.Write(CultureInfo.CurrentCulture, format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified array of objects, | ||||
|         /// to the console using the specified format information. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void Write(IFormatProvider provider, string format, params object[] args) | ||||
|         { | ||||
|             Console.Write(string.Format(provider, format, args)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										263
									
								
								src/Spectre.Console/AnsiConsole.WriteLine.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								src/Spectre.Console/AnsiConsole.WriteLine.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,263 @@ | ||||
| using System; | ||||
| using System.Globalization; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Writes an empty line to the console. | ||||
|         /// </summary> | ||||
|         public static void WriteLine() | ||||
|         { | ||||
|             Console.WriteLine(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified string value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(string value) | ||||
|         { | ||||
|             Console.WriteLine(value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit signed integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(int value) | ||||
|         { | ||||
|             Console.WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit signed integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, int value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit unsigned integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(uint value) | ||||
|         { | ||||
|             Console.WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit unsigned integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, uint value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit signed integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(long value) | ||||
|         { | ||||
|             Console.WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit signed integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, long value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit unsigned integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(ulong value) | ||||
|         { | ||||
|             Console.WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit unsigned integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, ulong value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified single-precision floating-point | ||||
|         /// value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(float value) | ||||
|         { | ||||
|             Console.WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified single-precision floating-point | ||||
|         /// value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, float value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified double-precision floating-point | ||||
|         /// value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(double value) | ||||
|         { | ||||
|             Console.WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified double-precision floating-point | ||||
|         /// value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, double value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified decimal value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(decimal value) | ||||
|         { | ||||
|             Console.WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified decimal value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, decimal value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified boolean value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(bool value) | ||||
|         { | ||||
|             Console.WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified boolean value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, bool value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified Unicode character, followed by the current | ||||
|         /// line terminator, value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(char value) | ||||
|         { | ||||
|             Console.WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified Unicode character, followed by the current | ||||
|         /// line terminator, value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, char value) | ||||
|         { | ||||
|             Console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified array of Unicode characters, followed by the current | ||||
|         /// line terminator, value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(char[] value) | ||||
|         { | ||||
|             Console.WriteLine(CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified array of Unicode characters, followed by the current | ||||
|         /// line terminator, value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, char[] value) | ||||
|         { | ||||
|             Console.WriteLine(provider, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified array of objects, | ||||
|         /// followed by the current line terminator, to the console | ||||
|         /// using the specified format information. | ||||
|         /// </summary> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void WriteLine(string format, params object[] args) | ||||
|         { | ||||
|             Console.WriteLine(CultureInfo.CurrentCulture, format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified array of objects, | ||||
|         /// followed by the current line terminator, to the console | ||||
|         /// using the specified format information. | ||||
|         /// </summary> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void WriteLine(IFormatProvider provider, string format, params object[] args) | ||||
|         { | ||||
|             Console.WriteLine(string.Format(provider, format, args)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -6,16 +6,18 @@ namespace Spectre.Console | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// </summary> | ||||
|     public static class AnsiConsole | ||||
|     public static partial class AnsiConsole | ||||
|     { | ||||
|         private static readonly Lazy<IAnsiConsole> _console = new Lazy<IAnsiConsole>(() => | ||||
|         { | ||||
|             return Create(new AnsiConsoleSettings | ||||
|             var console = Create(new AnsiConsoleSettings | ||||
|             { | ||||
|                 Ansi = AnsiSupport.Detect, | ||||
|                 ColorSystem = ColorSystemSupport.Detect, | ||||
|                 Out = System.Console.Out, | ||||
|             }); | ||||
|             Created = true; | ||||
|             return console; | ||||
|         }); | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -26,7 +28,9 @@ namespace Spectre.Console | ||||
|         /// <summary> | ||||
|         /// Gets the console's capabilities. | ||||
|         /// </summary> | ||||
|         public static AnsiConsoleCapabilities Capabilities => Console.Capabilities; | ||||
|         public static Capabilities Capabilities => Console.Capabilities; | ||||
|  | ||||
|         internal static bool Created { get; private set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the buffer width of the console. | ||||
| @@ -63,12 +67,12 @@ namespace Spectre.Console | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the style. | ||||
|         /// Gets or sets the text decoration. | ||||
|         /// </summary> | ||||
|         public static Styles Style | ||||
|         public static Decoration Decoration | ||||
|         { | ||||
|             get => Console.Style; | ||||
|             set => Console.Style = value; | ||||
|             get => Console.Decoration; | ||||
|             set => Console.Decoration = value; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -83,7 +87,7 @@ namespace Spectre.Console | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Resets colors and styles to the default ones. | ||||
|         /// Resets colors and text decorations. | ||||
|         /// </summary> | ||||
|         public static void Reset() | ||||
|         { | ||||
| @@ -91,45 +95,19 @@ namespace Spectre.Console | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Resets the current style back to the default one. | ||||
|         /// Resets the current applied text decorations. | ||||
|         /// </summary> | ||||
|         public static void ResetStyle() | ||||
|         public static void ResetDecoration() | ||||
|         { | ||||
|             Console.ResetStyle(); | ||||
|             Console.ResetDecoration(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Resets the foreground and background colors to the default ones. | ||||
|         /// Resets the current applied foreground and background colors. | ||||
|         /// </summary> | ||||
|         public static void ResetColors() | ||||
|         { | ||||
|             Console.ResetColors(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the content to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="content">The content to write.</param> | ||||
|         public static void Write(string content) | ||||
|         { | ||||
|             Console.Write(content); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes an empty line to the console. | ||||
|         /// </summary> | ||||
|         public static void WriteLine() | ||||
|         { | ||||
|             Console.WriteLine(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes a line to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="content">The content to write.</param> | ||||
|         public static void WriteLine(string content) | ||||
|         { | ||||
|             Console.WriteLine(content); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,42 +0,0 @@ | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents console capabilities. | ||||
|     /// </summary> | ||||
|     public sealed class AnsiConsoleCapabilities | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets a value indicating whether or not | ||||
|         /// the console supports Ansi. | ||||
|         /// </summary> | ||||
|         public bool SupportsAnsi { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the color system. | ||||
|         /// </summary> | ||||
|         public ColorSystem ColorSystem { get; } | ||||
|  | ||||
|         internal AnsiConsoleCapabilities(bool supportsAnsi, ColorSystem colorSystem) | ||||
|         { | ||||
|             SupportsAnsi = supportsAnsi; | ||||
|             ColorSystem = colorSystem; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override string ToString() | ||||
|         { | ||||
|             var supportsAnsi = SupportsAnsi ? "Yes" : "No"; | ||||
|             var bits = ColorSystem switch | ||||
|             { | ||||
|                 ColorSystem.NoColors => "1 bit", | ||||
|                 ColorSystem.Legacy => "3 bits", | ||||
|                 ColorSystem.Standard => "4 bits", | ||||
|                 ColorSystem.EightBit => "8 bits", | ||||
|                 ColorSystem.TrueColor => "24 bits", | ||||
|                 _ => "?" | ||||
|             }; | ||||
|  | ||||
|             return $"ANSI={supportsAnsi}, Colors={ColorSystem} ({bits})"; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -3,8 +3,7 @@ using System.IO; | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Settings used by <see cref="ConsoleBuilder"/> | ||||
|     /// when building a <see cref="IAnsiConsole"/>. | ||||
|     /// Settings used when building a <see cref="IAnsiConsole"/>. | ||||
|     /// </summary> | ||||
|     public sealed class AnsiConsoleSettings | ||||
|     { | ||||
| @@ -22,6 +21,6 @@ namespace Spectre.Console | ||||
|         /// <summary> | ||||
|         /// Gets or sets the out buffer. | ||||
|         /// </summary> | ||||
|         public TextWriter Out { get; set; } | ||||
|         public TextWriter? Out { get; set; } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										59
									
								
								src/Spectre.Console/Capabilities.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/Spectre.Console/Capabilities.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents console capabilities. | ||||
|     /// </summary> | ||||
|     public sealed class Capabilities | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets a value indicating whether or not | ||||
|         /// the console supports Ansi. | ||||
|         /// </summary> | ||||
|         public bool SupportsAnsi { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the color system. | ||||
|         /// </summary> | ||||
|         public ColorSystem ColorSystem { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets a value indicating whether or not | ||||
|         /// this is a legacy console (cmd.exe). | ||||
|         /// </summary> | ||||
|         /// <remarks> | ||||
|         /// Only relevant when running on Microsoft Windows. | ||||
|         /// </remarks> | ||||
|         public bool LegacyConsole { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Capabilities"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="supportsAnsi">Whether or not ANSI escape sequences are supported.</param> | ||||
|         /// <param name="colorSystem">The color system that is supported.</param> | ||||
|         /// <param name="legacyConsole">Whether or not this is a legacy console.</param> | ||||
|         public Capabilities(bool supportsAnsi, ColorSystem colorSystem, bool legacyConsole) | ||||
|         { | ||||
|             SupportsAnsi = supportsAnsi; | ||||
|             ColorSystem = colorSystem; | ||||
|             LegacyConsole = legacyConsole; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override string ToString() | ||||
|         { | ||||
|             var supportsAnsi = SupportsAnsi ? "Yes" : "No"; | ||||
|             var legacyConsole = LegacyConsole ? "Legacy" : "Modern"; | ||||
|             var bits = ColorSystem switch | ||||
|             { | ||||
|                 ColorSystem.NoColors => "1 bit", | ||||
|                 ColorSystem.Legacy => "3 bits", | ||||
|                 ColorSystem.Standard => "4 bits", | ||||
|                 ColorSystem.EightBit => "8 bits", | ||||
|                 ColorSystem.TrueColor => "24 bits", | ||||
|                 _ => "?", | ||||
|             }; | ||||
|  | ||||
|             return $"ANSI={supportsAnsi}, Colors={ColorSystem}, Kind={legacyConsole} ({bits})"; | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,6 +1,6 @@ | ||||
| using System; | ||||
| using System.Diagnostics; | ||||
| using System.Linq; | ||||
| using System.Globalization; | ||||
| using Spectre.Console.Internal; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| @@ -17,7 +17,7 @@ namespace Spectre.Console | ||||
|  | ||||
|         static Color() | ||||
|         { | ||||
|             Default = new Color(0, "default", 0, 0, 0, true); | ||||
|             Default = new Color(0, 0, 0, 0, true); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -35,11 +35,6 @@ namespace Spectre.Console | ||||
|         /// </summary> | ||||
|         public byte B { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the name of the color, if any. | ||||
|         /// </summary> | ||||
|         public string Name { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the number of the color, if any. | ||||
|         /// </summary> | ||||
| @@ -62,7 +57,6 @@ namespace Spectre.Console | ||||
|             G = green; | ||||
|             B = blue; | ||||
|             IsDefault = false; | ||||
|             Name = null; | ||||
|             Number = null; | ||||
|         } | ||||
|  | ||||
| @@ -80,7 +74,7 @@ namespace Spectre.Console | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override bool Equals(object obj) | ||||
|         public override bool Equals(object? obj) | ||||
|         { | ||||
|             return obj is Color color && Equals(color); | ||||
|         } | ||||
| @@ -88,7 +82,8 @@ namespace Spectre.Console | ||||
|         /// <inheritdoc/> | ||||
|         public bool Equals(Color other) | ||||
|         { | ||||
|             return Number == other.Number || (R == other.R && G == other.G && B == other.B); | ||||
|             return (IsDefault && other.IsDefault) || | ||||
|                    (IsDefault == other.IsDefault && R == other.R && G == other.G && B == other.B); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -113,6 +108,15 @@ namespace Spectre.Console | ||||
|             return !(left == right); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Convers a <see cref="int"/> to a <see cref="Color"/>. | ||||
|         /// </summary> | ||||
|         /// <param name="number">The color number to convert.</param> | ||||
|         public static implicit operator Color(int number) | ||||
|         { | ||||
|             return FromInt32(number); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Convers a <see cref="ConsoleColor"/> to a <see cref="Color"/>. | ||||
|         /// </summary> | ||||
| @@ -123,18 +127,12 @@ namespace Spectre.Console | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Convers a color number into a <see cref="Color"/>. | ||||
|         /// Convers a <see cref="Color"/> to a <see cref="ConsoleColor"/>. | ||||
|         /// </summary> | ||||
|         /// <param name="number">The color number.</param> | ||||
|         /// <returns>The color representing the specified color number.</returns> | ||||
|         public static Color FromColorNumber(int number) | ||||
|         /// <param name="color">The console color to convert.</param> | ||||
|         public static implicit operator ConsoleColor(Color color) | ||||
|         { | ||||
|             if (number < 0 || number > 255) | ||||
|             { | ||||
|                 throw new InvalidOperationException("Color number must be between 0 and 255"); | ||||
|             } | ||||
|  | ||||
|             return ColorPalette.EightBit.First(x => x.Number == number); | ||||
|             return ToConsoleColor(color); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -179,6 +177,16 @@ namespace Spectre.Console | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Convers a color number into a <see cref="Color"/>. | ||||
|         /// </summary> | ||||
|         /// <param name="number">The color number.</param> | ||||
|         /// <returns>The color representing the specified color number.</returns> | ||||
|         public static Color FromInt32(int number) | ||||
|         { | ||||
|             return ColorTable.GetColor(number); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Convers a <see cref="ConsoleColor"/> to a <see cref="Color"/>. | ||||
|         /// </summary> | ||||
| @@ -207,5 +215,20 @@ namespace Spectre.Console | ||||
|                 _ => Default, | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override string ToString() | ||||
|         { | ||||
|             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} (RGB={0},{1},{2})", R, G, B); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										108
									
								
								src/Spectre.Console/Composition/Border.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/Spectre.Console/Composition/Border.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Globalization; | ||||
| using System.Linq; | ||||
|  | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a border used by tables. | ||||
|     /// </summary> | ||||
|     public abstract class Border | ||||
|     { | ||||
|         private readonly Dictionary<BorderPart, string> _lookup; | ||||
|  | ||||
|         private static readonly Dictionary<BorderKind, Border> _borders = new Dictionary<BorderKind, Border> | ||||
|         { | ||||
|             { BorderKind.None, new NoBorder() }, | ||||
|             { BorderKind.Ascii, new AsciiBorder() }, | ||||
|             { BorderKind.Square, new SquareBorder() }, | ||||
|             { BorderKind.Rounded, new RoundedBorder() }, | ||||
|         }; | ||||
|  | ||||
|         private static readonly Dictionary<BorderKind, BorderKind> _safeLookup = new Dictionary<BorderKind, BorderKind> | ||||
|         { | ||||
|             { BorderKind.Rounded, BorderKind.Square }, | ||||
|         }; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Border"/> class. | ||||
|         /// </summary> | ||||
|         protected Border() | ||||
|         { | ||||
|             _lookup = Initialize(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets a <see cref="Border"/> represented by the specified <see cref="BorderKind"/>. | ||||
|         /// </summary> | ||||
|         /// <param name="kind">The kind of border to get.</param> | ||||
|         /// <param name="safe">Whether or not to get a "safe" border that can be rendered in a legacy console.</param> | ||||
|         /// <returns>A <see cref="Border"/> instance representing the specified <see cref="BorderKind"/>.</returns> | ||||
|         public static Border GetBorder(BorderKind kind, bool safe) | ||||
|         { | ||||
|             if (safe && _safeLookup.TryGetValue(kind, out var safeKind)) | ||||
|             { | ||||
|                 kind = safeKind; | ||||
|             } | ||||
|  | ||||
|             if (!_borders.TryGetValue(kind, out var border)) | ||||
|             { | ||||
|                 throw new InvalidOperationException("Unknown border kind"); | ||||
|             } | ||||
|  | ||||
|             return border; | ||||
|         } | ||||
|  | ||||
|         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); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										28
									
								
								src/Spectre.Console/Composition/BorderKind.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/Spectre.Console/Composition/BorderKind.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents different kinds of borders. | ||||
|     /// </summary> | ||||
|     public enum BorderKind | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// No border. | ||||
|         /// </summary> | ||||
|         None = 0, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// A square border. | ||||
|         /// </summary> | ||||
|         Square = 1, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// An old school ASCII border. | ||||
|         /// </summary> | ||||
|         Ascii = 2, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// A rounded border. | ||||
|         /// </summary> | ||||
|         Rounded = 3, | ||||
|     } | ||||
| } | ||||
							
								
								
									
										98
									
								
								src/Spectre.Console/Composition/BorderPart.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/Spectre.Console/Composition/BorderPart.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents the different border parts. | ||||
|     /// </summary> | ||||
|     public enum BorderPart | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// The top left part of a header. | ||||
|         /// </summary> | ||||
|         HeaderTopLeft, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The top part of a header. | ||||
|         /// </summary> | ||||
|         HeaderTop, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The top separator part of a header. | ||||
|         /// </summary> | ||||
|         HeaderTopSeparator, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The top right part of a header. | ||||
|         /// </summary> | ||||
|         HeaderTopRight, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The left part of a header. | ||||
|         /// </summary> | ||||
|         HeaderLeft, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// A header separator. | ||||
|         /// </summary> | ||||
|         HeaderSeparator, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The right part of a header. | ||||
|         /// </summary> | ||||
|         HeaderRight, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The bottom left part of a header. | ||||
|         /// </summary> | ||||
|         HeaderBottomLeft, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The bottom part of a header. | ||||
|         /// </summary> | ||||
|         HeaderBottom, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The bottom separator part of a header. | ||||
|         /// </summary> | ||||
|         HeaderBottomSeparator, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The bottom right part of a header. | ||||
|         /// </summary> | ||||
|         HeaderBottomRight, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The left part of a cell. | ||||
|         /// </summary> | ||||
|         CellLeft, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// A cell separator. | ||||
|         /// </summary> | ||||
|         CellSeparator, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The right part of a cell. | ||||
|         /// </summary> | ||||
|         CellRight, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The bottom left part of a footer. | ||||
|         /// </summary> | ||||
|         FooterBottomLeft, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The bottom part of a footer. | ||||
|         /// </summary> | ||||
|         FooterBottom, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The bottom separator part of a footer. | ||||
|         /// </summary> | ||||
|         FooterBottomSeparator, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// The bottom right part of a footer. | ||||
|         /// </summary> | ||||
|         FooterBottomRight, | ||||
|     } | ||||
| } | ||||
							
								
								
									
										37
									
								
								src/Spectre.Console/Composition/Borders/AsciiBorder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/Spectre.Console/Composition/Borders/AsciiBorder.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     /// <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."), | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										14
									
								
								src/Spectre.Console/Composition/Borders/NoBorder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/Spectre.Console/Composition/Borders/NoBorder.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents an invisible border. | ||||
|     /// </summary> | ||||
|     public sealed class NoBorder : Border | ||||
|     { | ||||
|         /// <inheritdoc/> | ||||
|         protected override string GetBoxPart(BorderPart part) | ||||
|         { | ||||
|             return " "; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										37
									
								
								src/Spectre.Console/Composition/Borders/RoundedBorder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/Spectre.Console/Composition/Borders/RoundedBorder.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a rounded border. | ||||
|     /// </summary> | ||||
|     public sealed class RoundedBorder : 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."), | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										37
									
								
								src/Spectre.Console/Composition/Borders/SquareBorder.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/Spectre.Console/Composition/Borders/SquareBorder.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     /// <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."), | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										26
									
								
								src/Spectre.Console/Composition/IRenderable.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/Spectre.Console/Composition/IRenderable.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents something that can be rendered to the console. | ||||
|     /// </summary> | ||||
|     public interface IRenderable | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Measures the renderable object. | ||||
|         /// </summary> | ||||
|         /// <param name="context">The render context.</param> | ||||
|         /// <param name="maxWidth">The maximum allowed width.</param> | ||||
|         /// <returns>The minimum and maximum width of the object.</returns> | ||||
|         Measurement Measure(RenderContext context, int maxWidth); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Renders the object. | ||||
|         /// </summary> | ||||
|         /// <param name="context">The render context.</param> | ||||
|         /// <param name="maxWidth">The maximum allowed width.</param> | ||||
|         /// <returns>A collection of segments.</returns> | ||||
|         IEnumerable<Segment> Render(RenderContext context, int maxWidth); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										23
									
								
								src/Spectre.Console/Composition/Justify.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/Spectre.Console/Composition/Justify.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents text justification. | ||||
|     /// </summary> | ||||
|     public enum Justify | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Left aligned. | ||||
|         /// </summary> | ||||
|         Left = 0, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Right aligned. | ||||
|         /// </summary> | ||||
|         Right = 1, | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Centered. | ||||
|         /// </summary> | ||||
|         Center = 2, | ||||
|     } | ||||
| } | ||||
							
								
								
									
										77
									
								
								src/Spectre.Console/Composition/Measurement.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/Spectre.Console/Composition/Measurement.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a measurement. | ||||
|     /// </summary> | ||||
|     public struct Measurement : IEquatable<Measurement> | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the minimum width. | ||||
|         /// </summary> | ||||
|         public int Min { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the maximum width. | ||||
|         /// </summary> | ||||
|         public int Max { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Measurement"/> struct. | ||||
|         /// </summary> | ||||
|         /// <param name="min">The minimum width.</param> | ||||
|         /// <param name="max">The maximum width.</param> | ||||
|         public Measurement(int min, int max) | ||||
|         { | ||||
|             Min = min; | ||||
|             Max = max; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override bool Equals(object? obj) | ||||
|         { | ||||
|             return obj is Measurement measurement && Equals(measurement); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override int GetHashCode() | ||||
|         { | ||||
|             unchecked | ||||
|             { | ||||
|                 var hash = (int)2166136261; | ||||
|                 hash = (hash * 16777619) ^ Min.GetHashCode(); | ||||
|                 hash = (hash * 16777619) ^ Max.GetHashCode(); | ||||
|                 return hash; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool Equals(Measurement other) | ||||
|         { | ||||
|             return Min == other.Min && Max == other.Max; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Checks if two <see cref="Measurement"/> instances are equal. | ||||
|         /// </summary> | ||||
|         /// <param name="left">The first measurement instance to compare.</param> | ||||
|         /// <param name="right">The second measurement instance to compare.</param> | ||||
|         /// <returns><c>true</c> if the two measurements are equal, otherwise <c>false</c>.</returns> | ||||
|         public static bool operator ==(Measurement left, Measurement right) | ||||
|         { | ||||
|             return left.Equals(right); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Checks if two <see cref="Measurement"/> instances are not equal. | ||||
|         /// </summary> | ||||
|         /// <param name="left">The first measurement instance to compare.</param> | ||||
|         /// <param name="right">The second measurement instance to compare.</param> | ||||
|         /// <returns><c>true</c> if the two measurements are not equal, otherwise <c>false</c>.</returns> | ||||
|         public static bool operator !=(Measurement left, Measurement right) | ||||
|         { | ||||
|             return !(left == right); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										86
									
								
								src/Spectre.Console/Composition/Padding.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/Spectre.Console/Composition/Padding.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a measurement. | ||||
|     /// </summary> | ||||
|     public struct Padding : IEquatable<Padding> | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the left padding. | ||||
|         /// </summary> | ||||
|         public int Left { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the right padding. | ||||
|         /// </summary> | ||||
|         public int Right { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Padding"/> struct. | ||||
|         /// </summary> | ||||
|         /// <param name="left">The left padding.</param> | ||||
|         /// <param name="right">The right padding.</param> | ||||
|         public Padding(int left, int right) | ||||
|         { | ||||
|             Left = left; | ||||
|             Right = right; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override bool Equals(object? obj) | ||||
|         { | ||||
|             return obj is Padding padding && Equals(padding); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override int GetHashCode() | ||||
|         { | ||||
|             unchecked | ||||
|             { | ||||
|                 var hash = (int)2166136261; | ||||
|                 hash = (hash * 16777619) ^ Left.GetHashCode(); | ||||
|                 hash = (hash * 16777619) ^ Right.GetHashCode(); | ||||
|                 return hash; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool Equals(Padding other) | ||||
|         { | ||||
|             return Left == other.Left && Right == other.Right; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Checks if two <see cref="Padding"/> instances are equal. | ||||
|         /// </summary> | ||||
|         /// <param name="left">The first <see cref="Padding"/> instance to compare.</param> | ||||
|         /// <param name="right">The second <see cref="Padding"/> instance to compare.</param> | ||||
|         /// <returns><c>true</c> if the two instances are equal, otherwise <c>false</c>.</returns> | ||||
|         public static bool operator ==(Padding left, Padding right) | ||||
|         { | ||||
|             return left.Equals(right); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Checks if two <see cref="Padding"/> instances are not equal. | ||||
|         /// </summary> | ||||
|         /// <param name="left">The first <see cref="Padding"/> instance to compare.</param> | ||||
|         /// <param name="right">The second <see cref="Padding"/> instance to compare.</param> | ||||
|         /// <returns><c>true</c> if the two instances are not equal, otherwise <c>false</c>.</returns> | ||||
|         public static bool operator !=(Padding left, Padding right) | ||||
|         { | ||||
|             return !(left == right); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the horizontal padding. | ||||
|         /// </summary> | ||||
|         /// <returns>The horizontal padding.</returns> | ||||
|         public int GetHorizontalPadding() | ||||
|         { | ||||
|             return Left + Right; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										54
									
								
								src/Spectre.Console/Composition/RenderContext.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/Spectre.Console/Composition/RenderContext.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| using System.Text; | ||||
|  | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a render context. | ||||
|     /// </summary> | ||||
|     public sealed class RenderContext | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the console's output encoding. | ||||
|         /// </summary> | ||||
|         public Encoding Encoding { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets a value indicating whether or not this a legacy console (i.e. cmd.exe). | ||||
|         /// </summary> | ||||
|         public bool LegacyConsole { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets a value indicating whether or not unicode is supported. | ||||
|         /// </summary> | ||||
|         public bool Unicode { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the current justification. | ||||
|         /// </summary> | ||||
|         public Justify? Justification { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="RenderContext"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="encoding">The console's output encoding.</param> | ||||
|         /// <param name="legacyConsole">A value indicating whether or not this a legacy console (i.e. cmd.exe).</param> | ||||
|         /// <param name="justification">The justification to use when rendering.</param> | ||||
|         public RenderContext(Encoding encoding, bool legacyConsole, Justify? justification = null) | ||||
|         { | ||||
|             Encoding = encoding ?? throw new System.ArgumentNullException(nameof(encoding)); | ||||
|             LegacyConsole = legacyConsole; | ||||
|             Justification = justification; | ||||
|             Unicode = Encoding == Encoding.UTF8 || Encoding == Encoding.Unicode; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a new context with the specified justification. | ||||
|         /// </summary> | ||||
|         /// <param name="justification">The justification.</param> | ||||
|         /// <returns>A new <see cref="RenderContext"/> instance with the specified justification.</returns> | ||||
|         public RenderContext WithJustification(Justify? justification) | ||||
|         { | ||||
|             return new RenderContext(Encoding, LegacyConsole, justification); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										245
									
								
								src/Spectre.Console/Composition/Segment.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								src/Spectre.Console/Composition/Segment.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,245 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Diagnostics; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using Spectre.Console.Internal; | ||||
|  | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a renderable segment. | ||||
|     /// </summary> | ||||
|     [DebuggerDisplay("{Text,nq}")] | ||||
|     public class Segment | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the segment text. | ||||
|         /// </summary> | ||||
|         public string Text { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets a value indicating whether or not this is an expicit line break | ||||
|         /// that should be preserved. | ||||
|         /// </summary> | ||||
|         public bool IsLineBreak { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets a value indicating whether or not this is a whitespace | ||||
|         /// that should be preserved but not taken into account when | ||||
|         /// layouting text. | ||||
|         /// </summary> | ||||
|         public bool IsWhiteSpace { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the segment style. | ||||
|         /// </summary> | ||||
|         public Style Style { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets a segment representing a line break. | ||||
|         /// </summary> | ||||
|         public static Segment LineBreak { get; } = new Segment("\n", Style.Plain, true); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets an empty segment. | ||||
|         /// </summary> | ||||
|         public static Segment Empty { get; } = new Segment(string.Empty, Style.Plain); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Segment"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="text">The segment text.</param> | ||||
|         public Segment(string text) | ||||
|             : this(text, Style.Plain) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Segment"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="text">The segment text.</param> | ||||
|         /// <param name="style">The segment style.</param> | ||||
|         public Segment(string text, Style style) | ||||
|             : this(text, style, false) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         private Segment(string text, Style style, bool lineBreak) | ||||
|         { | ||||
|             if (text is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(text)); | ||||
|             } | ||||
|  | ||||
|             Text = text.NormalizeLineEndings(); | ||||
|             Style = style; | ||||
|             IsLineBreak = lineBreak; | ||||
|             IsWhiteSpace = string.IsNullOrWhiteSpace(text); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the number of cells that this segment | ||||
|         /// occupies in the console. | ||||
|         /// </summary> | ||||
|         /// <param name="encoding">The encoding to use.</param> | ||||
|         /// <returns>The number of cells that this segment occupies in the console.</returns> | ||||
|         public int CellLength(Encoding encoding) | ||||
|         { | ||||
|             return Text.CellLength(encoding); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Returns a new segment without any trailing line endings. | ||||
|         /// </summary> | ||||
|         /// <returns>A new segment without any trailing line endings.</returns> | ||||
|         public Segment StripLineEndings() | ||||
|         { | ||||
|             return new Segment(Text.TrimEnd('\n'), Style); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Splits the segment at the offset. | ||||
|         /// </summary> | ||||
|         /// <param name="offset">The offset where to split the segment.</param> | ||||
|         /// <returns>One or two new segments representing the split.</returns> | ||||
|         public (Segment First, Segment? Second) Split(int offset) | ||||
|         { | ||||
|             if (offset < 0) | ||||
|             { | ||||
|                 return (this, null); | ||||
|             } | ||||
|  | ||||
|             if (offset >= Text.Length) | ||||
|             { | ||||
|                 return (this, null); | ||||
|             } | ||||
|  | ||||
|             return ( | ||||
|                 new Segment(Text.Substring(0, offset), Style), | ||||
|                 new Segment(Text.Substring(offset, Text.Length - offset), Style)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Splits the provided segments into lines. | ||||
|         /// </summary> | ||||
|         /// <param name="segments">The segments to split.</param> | ||||
|         /// <returns>A collection of lines.</returns> | ||||
|         public static List<SegmentLine> SplitLines(IEnumerable<Segment> segments) | ||||
|         { | ||||
|             return SplitLines(segments, int.MaxValue); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Splits the provided segments into lines with a maximum width. | ||||
|         /// </summary> | ||||
|         /// <param name="segments">The segments to split into lines.</param> | ||||
|         /// <param name="maxWidth">The maximum width.</param> | ||||
|         /// <returns>A list of lines.</returns> | ||||
|         public static List<SegmentLine> SplitLines(IEnumerable<Segment> segments, int maxWidth) | ||||
|         { | ||||
|             if (segments is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(segments)); | ||||
|             } | ||||
|  | ||||
|             var lines = new List<SegmentLine>(); | ||||
|             var line = new SegmentLine(); | ||||
|  | ||||
|             var stack = new Stack<Segment>(segments.Reverse()); | ||||
|  | ||||
|             while (stack.Count > 0) | ||||
|             { | ||||
|                 var segment = stack.Pop(); | ||||
|  | ||||
|                 if (line.Width + segment.Text.Length > maxWidth) | ||||
|                 { | ||||
|                     var diff = -(maxWidth - (line.Width + segment.Text.Length)); | ||||
|                     var offset = segment.Text.Length - diff; | ||||
|  | ||||
|                     var (first, second) = segment.Split(offset); | ||||
|  | ||||
|                     line.Add(first); | ||||
|                     lines.Add(line); | ||||
|                     line = new SegmentLine(); | ||||
|  | ||||
|                     if (second != null) | ||||
|                     { | ||||
|                         stack.Push(second); | ||||
|                     } | ||||
|  | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 if (segment.Text.Contains("\n")) | ||||
|                 { | ||||
|                     if (segment.Text == "\n") | ||||
|                     { | ||||
|                         if (line.Width > 0 || segment.IsLineBreak) | ||||
|                         { | ||||
|                             lines.Add(line); | ||||
|                             line = new SegmentLine(); | ||||
|                         } | ||||
|  | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     var text = segment.Text; | ||||
|                     while (text != null) | ||||
|                     { | ||||
|                         var parts = text.SplitLines(); | ||||
|                         if (parts.Length > 0) | ||||
|                         { | ||||
|                             if (parts[0].Length > 0) | ||||
|                             { | ||||
|                                 line.Add(new Segment(parts[0], segment.Style)); | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         if (parts.Length > 1) | ||||
|                         { | ||||
|                             if (line.Width > 0) | ||||
|                             { | ||||
|                                 lines.Add(line); | ||||
|                                 line = new SegmentLine(); | ||||
|                             } | ||||
|  | ||||
|                             text = string.Concat(parts.Skip(1).Take(parts.Length - 1)); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             text = null; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     line.Add(segment); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (line.Count > 0) | ||||
|             { | ||||
|                 lines.Add(line); | ||||
|             } | ||||
|  | ||||
|             return lines; | ||||
|         } | ||||
|  | ||||
|         internal static List<List<SegmentLine>> MakeSameHeight(int cellHeight, List<List<SegmentLine>> cells) | ||||
|         { | ||||
|             foreach (var cell in cells) | ||||
|             { | ||||
|                 if (cell.Count < cellHeight) | ||||
|                 { | ||||
|                     while (cell.Count != cellHeight) | ||||
|                     { | ||||
|                         cell.Add(new SegmentLine()); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return cells; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										38
									
								
								src/Spectre.Console/Composition/SegmentLine.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/Spectre.Console/Composition/SegmentLine.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
|  | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a collection of segments. | ||||
|     /// </summary> | ||||
|     [SuppressMessage("Naming", "CA1710:Identifiers should have correct suffix")] | ||||
|     public sealed class SegmentLine : List<Segment> | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the width of the line. | ||||
|         /// </summary> | ||||
|         public int Width => this.Sum(line => line.Text.Length); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the cell width of the segment line. | ||||
|         /// </summary> | ||||
|         /// <param name="encoding">The encoding to use.</param> | ||||
|         /// <returns>The cell width of the segment line.</returns> | ||||
|         public int CellWidth(Encoding encoding) | ||||
|         { | ||||
|             return this.Sum(line => line.CellLength(encoding)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Preprends a segment to the line. | ||||
|         /// </summary> | ||||
|         /// <param name="segment">The segment to prepend.</param> | ||||
|         public void Prepend(Segment segment) | ||||
|         { | ||||
|             Insert(0, segment); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										25
									
								
								src/Spectre.Console/Composition/SegmentLineEnumerator.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/Spectre.Console/Composition/SegmentLineEnumerator.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     internal sealed class SegmentLineEnumerator : IEnumerable<Segment> | ||||
|     { | ||||
|         private readonly List<SegmentLine> _lines; | ||||
|  | ||||
|         public SegmentLineEnumerator(List<SegmentLine> lines) | ||||
|         { | ||||
|             _lines = lines; | ||||
|         } | ||||
|  | ||||
|         public IEnumerator<Segment> GetEnumerator() | ||||
|         { | ||||
|             return new SegmentLineIterator(_lines); | ||||
|         } | ||||
|  | ||||
|         IEnumerator IEnumerable.GetEnumerator() | ||||
|         { | ||||
|             return GetEnumerator(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										99
									
								
								src/Spectre.Console/Composition/SegmentLineIterator.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/Spectre.Console/Composition/SegmentLineIterator.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Composition | ||||
| { | ||||
|     internal sealed class SegmentLineIterator : IEnumerator<Segment> | ||||
|     { | ||||
|         private readonly List<SegmentLine> _lines; | ||||
|         private int _currentLine; | ||||
|         private int _currentIndex; | ||||
|         private bool _lineBreakEmitted; | ||||
|  | ||||
|         public Segment Current { get; private set; } | ||||
|         object? IEnumerator.Current => Current; | ||||
|  | ||||
|         public SegmentLineIterator(List<SegmentLine> lines) | ||||
|         { | ||||
|             _currentLine = 0; | ||||
|             _currentIndex = -1; | ||||
|             _lines = lines; | ||||
|  | ||||
|             Current = Segment.Empty; | ||||
|         } | ||||
|  | ||||
|         public void Dispose() | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         public bool MoveNext() | ||||
|         { | ||||
|             if (_currentLine > _lines.Count - 1) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             _currentIndex += 1; | ||||
|  | ||||
|             // Did we go past the end of the line? | ||||
|             if (_currentIndex > _lines[_currentLine].Count - 1) | ||||
|             { | ||||
|                 // We haven't just emitted a line break? | ||||
|                 if (!_lineBreakEmitted) | ||||
|                 { | ||||
|                     // Got any more lines? | ||||
|                     if (_currentIndex + 1 > _lines[_currentLine].Count - 1) | ||||
|                     { | ||||
|                         // Only emit a line break if the next one isn't a line break. | ||||
|                         if ((_currentLine + 1 <= _lines.Count - 1) | ||||
|                             && _lines[_currentLine + 1].Count > 0 | ||||
|                             && !_lines[_currentLine + 1][0].IsLineBreak) | ||||
|                         { | ||||
|                             _lineBreakEmitted = true; | ||||
|                             Current = Segment.LineBreak; | ||||
|                             return true; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 // Increase the line and reset the index. | ||||
|                 _currentLine += 1; | ||||
|                 _currentIndex = 0; | ||||
|  | ||||
|                 _lineBreakEmitted = false; | ||||
|  | ||||
|                 // No more lines? | ||||
|                 if (_currentLine > _lines.Count - 1) | ||||
|                 { | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 // Nothing on the line? | ||||
|                 while (_currentIndex > _lines[_currentLine].Count - 1) | ||||
|                 { | ||||
|                     _currentLine += 1; | ||||
|                     _currentIndex = 0; | ||||
|  | ||||
|                     if (_currentLine > _lines.Count - 1) | ||||
|                     { | ||||
|                         return false; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Reset the flag | ||||
|             _lineBreakEmitted = false; | ||||
|  | ||||
|             Current = _lines[_currentLine][_currentIndex]; | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         public void Reset() | ||||
|         { | ||||
|             _currentLine = 0; | ||||
|             _currentIndex = -1; | ||||
|  | ||||
|             Current = Segment.Empty; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										141
									
								
								src/Spectre.Console/Composition/Widgets/Grid.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								src/Spectre.Console/Composition/Widgets/Grid.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Internal; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a grid. | ||||
|     /// </summary> | ||||
|     public sealed class Grid : IRenderable | ||||
|     { | ||||
|         private readonly Table _table; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Grid"/> class. | ||||
|         /// </summary> | ||||
|         public Grid() | ||||
|         { | ||||
|             _table = new Table | ||||
|             { | ||||
|                 Border = BorderKind.None, | ||||
|                 ShowHeaders = false, | ||||
|                 IsGrid = true, | ||||
|                 PadRightCell = false, | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public Measurement Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             return ((IRenderable)_table).Measure(context, maxWidth); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IEnumerable<Segment> Render(RenderContext context, int width) | ||||
|         { | ||||
|             return ((IRenderable)_table).Render(context, width); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds a column to the grid. | ||||
|         /// </summary> | ||||
|         public void AddColumn() | ||||
|         { | ||||
|             AddColumn(new GridColumn()); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds a column to the grid. | ||||
|         /// </summary> | ||||
|         /// <param name="column">The column to add.</param> | ||||
|         public void AddColumn(GridColumn column) | ||||
|         { | ||||
|             if (column is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(column)); | ||||
|             } | ||||
|  | ||||
|             if (_table.RowCount > 0) | ||||
|             { | ||||
|                 throw new InvalidOperationException("Cannot add new columns to grid with existing rows."); | ||||
|             } | ||||
|  | ||||
|             // Only pad the most right cell if we've explicitly set a padding. | ||||
|             _table.PadRightCell = column.Padding != null; | ||||
|  | ||||
|             _table.AddColumn(new TableColumn(string.Empty) | ||||
|             { | ||||
|                 Width = column.Width, | ||||
|                 NoWrap = column.NoWrap, | ||||
|                 Padding = column.Padding ?? new Padding(0, 2), | ||||
|                 Alignment = column.Alignment, | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds a column to the grid. | ||||
|         /// </summary> | ||||
|         /// <param name="count">The number of columns to add.</param> | ||||
|         public void AddColumns(int count) | ||||
|         { | ||||
|             for (var index = 0; index < count; index++) | ||||
|             { | ||||
|                 AddColumn(new GridColumn()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds a column to the grid. | ||||
|         /// </summary> | ||||
|         /// <param name="columns">The columns to add.</param> | ||||
|         public void AddColumns(params GridColumn[] columns) | ||||
|         { | ||||
|             if (columns is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(columns)); | ||||
|             } | ||||
|  | ||||
|             foreach (var column in columns) | ||||
|             { | ||||
|                 AddColumn(column); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds an empty row to the grid. | ||||
|         /// </summary> | ||||
|         public void AddEmptyRow() | ||||
|         { | ||||
|             var columns = new string[_table.ColumnCount]; | ||||
|             Enumerable.Range(0, _table.ColumnCount).ForEach(index => columns[index] = string.Empty); | ||||
|             AddRow(columns); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds a new row to the grid. | ||||
|         /// </summary> | ||||
|         /// <param name="columns">The columns to add.</param> | ||||
|         public void AddRow(params string[] columns) | ||||
|         { | ||||
|             if (columns is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(columns)); | ||||
|             } | ||||
|  | ||||
|             if (columns.Length < _table.ColumnCount) | ||||
|             { | ||||
|                 throw new InvalidOperationException("The number of row columns are less than the number of grid columns."); | ||||
|             } | ||||
|  | ||||
|             if (columns.Length > _table.ColumnCount) | ||||
|             { | ||||
|                 throw new InvalidOperationException("The number of row columns are greater than the number of grid columns."); | ||||
|             } | ||||
|  | ||||
|             _table.AddRow(columns); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										30
									
								
								src/Spectre.Console/Composition/Widgets/GridColumn.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/Spectre.Console/Composition/Widgets/GridColumn.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a grid column. | ||||
|     /// </summary> | ||||
|     public sealed class GridColumn | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets or sets the width of the column. | ||||
|         /// If <c>null</c>, the column will adapt to it's contents. | ||||
|         /// </summary> | ||||
|         public int? Width { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether wrapping of | ||||
|         /// text within the column should be prevented. | ||||
|         /// </summary> | ||||
|         public bool NoWrap { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the padding of the column. | ||||
|         /// </summary> | ||||
|         public Padding? Padding { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the alignment of the column. | ||||
|         /// </summary> | ||||
|         public Justify? Alignment { get; set; } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										133
									
								
								src/Spectre.Console/Composition/Widgets/Panel.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								src/Spectre.Console/Composition/Widgets/Panel.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Spectre.Console.Composition; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a panel which contains another renderable item. | ||||
|     /// </summary> | ||||
|     public sealed class Panel : IRenderable | ||||
|     { | ||||
|         private const int EdgeWidth = 2; | ||||
|  | ||||
|         private readonly IRenderable _child; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether or not to use | ||||
|         /// a "safe" border on legacy consoles that might not be able | ||||
|         /// to render non-ASCII characters. Defaults to <c>true</c>. | ||||
|         /// </summary> | ||||
|         public bool SafeBorder { get; set; } = true; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the kind of border to use. | ||||
|         /// </summary> | ||||
|         public BorderKind Border { get; set; } = BorderKind.Square; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the alignment of the panel contents. | ||||
|         /// </summary> | ||||
|         public Justify? Alignment { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether or not the panel should | ||||
|         /// fit the available space. If <c>false</c>, the panel width will be | ||||
|         /// auto calculated. Defaults to <c>false</c>. | ||||
|         /// </summary> | ||||
|         public bool Expand { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the padding. | ||||
|         /// </summary> | ||||
|         public Padding Padding { get; set; } = new Padding(1, 1); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Panel"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="content">The panel content.</param> | ||||
|         public Panel(IRenderable content) | ||||
|         { | ||||
|             _child = content ?? throw new System.ArgumentNullException(nameof(content)); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         Measurement IRenderable.Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             var childWidth = _child.Measure(context, maxWidth); | ||||
|             return new Measurement(childWidth.Min + 2 + Padding.GetHorizontalPadding(), childWidth.Max + 2 + Padding.GetHorizontalPadding()); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         IEnumerable<Segment> IRenderable.Render(RenderContext context, int width) | ||||
|         { | ||||
|             var border = Composition.Border.GetBorder(Border, (context.LegacyConsole || !context.Unicode) && SafeBorder); | ||||
|  | ||||
|             var paddingWidth = Padding.GetHorizontalPadding(); | ||||
|             var childWidth = width - EdgeWidth - paddingWidth; | ||||
|  | ||||
|             if (!Expand) | ||||
|             { | ||||
|                 var measurement = _child.Measure(context, width - EdgeWidth - paddingWidth); | ||||
|                 childWidth = measurement.Max; | ||||
|             } | ||||
|  | ||||
|             var panelWidth = childWidth + paddingWidth; | ||||
|  | ||||
|             // Panel top | ||||
|             var result = new List<Segment> | ||||
|             { | ||||
|                 new Segment(border.GetPart(BorderPart.HeaderTopLeft)), | ||||
|                 new Segment(border.GetPart(BorderPart.HeaderTop, panelWidth)), | ||||
|                 new Segment(border.GetPart(BorderPart.HeaderTopRight)), | ||||
|                 new Segment("\n"), | ||||
|             }; | ||||
|  | ||||
|             // Render the child. | ||||
|             var childContext = context.WithJustification(Alignment); | ||||
|             var childSegments = _child.Render(childContext, childWidth); | ||||
|  | ||||
|             // Split the child segments into lines. | ||||
|             foreach (var line in Segment.SplitLines(childSegments, panelWidth)) | ||||
|             { | ||||
|                 result.Add(new Segment(border.GetPart(BorderPart.CellLeft))); | ||||
|  | ||||
|                 // Left padding | ||||
|                 if (Padding.Left > 0) | ||||
|                 { | ||||
|                     result.Add(new Segment(new string(' ', Padding.Left))); | ||||
|                 } | ||||
|  | ||||
|                 var content = new List<Segment>(); | ||||
|                 content.AddRange(line); | ||||
|  | ||||
|                 // Do we need to pad the panel? | ||||
|                 var length = line.Sum(segment => segment.CellLength(context.Encoding)); | ||||
|                 if (length < childWidth) | ||||
|                 { | ||||
|                     var diff = childWidth - length; | ||||
|                     content.Add(new Segment(new string(' ', diff))); | ||||
|                 } | ||||
|  | ||||
|                 result.AddRange(content); | ||||
|  | ||||
|                 // Right padding | ||||
|                 if (Padding.Right > 0) | ||||
|                 { | ||||
|                     result.Add(new Segment(new string(' ', Padding.Right))); | ||||
|                 } | ||||
|  | ||||
|                 result.Add(new Segment(border.GetPart(BorderPart.CellRight))); | ||||
|                 result.Add(new Segment("\n")); | ||||
|             } | ||||
|  | ||||
|             // Panel bottom | ||||
|             result.Add(new Segment(border.GetPart(BorderPart.FooterBottomLeft))); | ||||
|             result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, panelWidth))); | ||||
|             result.Add(new Segment(border.GetPart(BorderPart.FooterBottomRight))); | ||||
|             result.Add(new Segment("\n")); | ||||
|  | ||||
|             return result; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										125
									
								
								src/Spectre.Console/Composition/Widgets/Table.Calculations.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								src/Spectre.Console/Composition/Widgets/Table.Calculations.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Internal; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a table. | ||||
|     /// </summary> | ||||
|     public sealed partial class Table | ||||
|     { | ||||
|         private const int EdgeCount = 2; | ||||
|  | ||||
|         // Calculate the widths of each column, including padding, not including borders. | ||||
|         // Ported from Rich by Will McGugan, licensed under MIT. | ||||
|         // https://github.com/willmcgugan/rich/blob/527475837ebbfc427530b3ee0d4d0741d2d0fc6d/rich/table.py#L394 | ||||
|         private List<int> CalculateColumnWidths(RenderContext options, int maxWidth) | ||||
|         { | ||||
|             var width_ranges = _columns.Select(column => MeasureColumn(column, options, maxWidth)); | ||||
|             var widths = width_ranges.Select(range => range.Max).ToList(); | ||||
|  | ||||
|             var tableWidth = widths.Sum(); | ||||
|  | ||||
|             if (tableWidth > maxWidth) | ||||
|             { | ||||
|                 var wrappable = _columns.Select(c => !c.NoWrap).ToList(); | ||||
|                 widths = CollapseWidths(widths, wrappable, maxWidth); | ||||
|                 tableWidth = widths.Sum(); | ||||
|  | ||||
|                 // last resort, reduce columns evenly | ||||
|                 if (tableWidth > maxWidth) | ||||
|                 { | ||||
|                     var excessWidth = tableWidth - maxWidth; | ||||
|                     widths = Ratio.Reduce(excessWidth, widths.Select(_ => 1).ToList(), widths, widths); | ||||
|                     tableWidth = widths.Sum(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (tableWidth < maxWidth && ShouldExpand()) | ||||
|             { | ||||
|                 var padWidths = Ratio.Distribute(maxWidth - tableWidth, widths); | ||||
|                 widths = widths.Zip(padWidths, (a, b) => (a, b)).Select(f => f.a + f.b).ToList(); | ||||
|             } | ||||
|  | ||||
|             return widths; | ||||
|         } | ||||
|  | ||||
|         // Reduce widths so that the total is less or equal to the max width. | ||||
|         // Ported from Rich by Will McGugan, licensed under MIT. | ||||
|         // https://github.com/willmcgugan/rich/blob/527475837ebbfc427530b3ee0d4d0741d2d0fc6d/rich/table.py#L442 | ||||
|         private static List<int> CollapseWidths(List<int> widths, List<bool> wrappable, int maxWidth) | ||||
|         { | ||||
|             var totalWidth = widths.Sum(); | ||||
|             var excessWidth = totalWidth - maxWidth; | ||||
|  | ||||
|             if (wrappable.AnyTrue()) | ||||
|             { | ||||
|                 while (totalWidth != 0 && excessWidth > 0) | ||||
|                 { | ||||
|                     var maxColumn = widths.Zip(wrappable, (first, second) => (width: first, allowWrap: second)) | ||||
|                         .Where(x => x.allowWrap) | ||||
|                         .Max(x => x.width); | ||||
|  | ||||
|                     var secondMaxColumn = widths.Zip(wrappable, (width, allowWrap) => allowWrap && width != maxColumn ? width : 1).Max(); | ||||
|                     var columnDifference = maxColumn - secondMaxColumn; | ||||
|  | ||||
|                     var ratios = widths.Zip(wrappable, (width, allowWrap) => width == maxColumn && allowWrap ? 1 : 0).ToList(); | ||||
|                     if (!ratios.Any(x => x != 0) || columnDifference == 0) | ||||
|                     { | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                     var maxReduce = widths.Select(_ => Math.Min(excessWidth, columnDifference)).ToList(); | ||||
|                     widths = Ratio.Reduce(excessWidth, ratios, maxReduce, widths); | ||||
|  | ||||
|                     totalWidth = widths.Sum(); | ||||
|                     excessWidth = totalWidth - maxWidth; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return widths; | ||||
|         } | ||||
|  | ||||
|         private (int Min, int Max) MeasureColumn(TableColumn column, RenderContext options, int maxWidth) | ||||
|         { | ||||
|             var padding = column.Padding.GetHorizontalPadding(); | ||||
|  | ||||
|             // Predetermined width? | ||||
|             if (column.Width != null) | ||||
|             { | ||||
|                 return (column.Width.Value + padding, column.Width.Value + padding); | ||||
|             } | ||||
|  | ||||
|             var columnIndex = _columns.IndexOf(column); | ||||
|             var rows = _rows.Select(row => row[columnIndex]); | ||||
|  | ||||
|             var minWidths = new List<int>(); | ||||
|             var maxWidths = new List<int>(); | ||||
|  | ||||
|             // Include columns in measurement | ||||
|             var measure = ((IRenderable)column.Text).Measure(options, maxWidth); | ||||
|             minWidths.Add(measure.Min); | ||||
|             maxWidths.Add(measure.Max); | ||||
|  | ||||
|             foreach (var row in rows) | ||||
|             { | ||||
|                 measure = ((IRenderable)row).Measure(options, maxWidth); | ||||
|                 minWidths.Add(measure.Min); | ||||
|                 maxWidths.Add(measure.Max); | ||||
|             } | ||||
|  | ||||
|             return (minWidths.Count > 0 ? minWidths.Max() : padding, | ||||
|                     maxWidths.Count > 0 ? maxWidths.Max() : maxWidth); | ||||
|         } | ||||
|  | ||||
|         private int GetExtraWidth(bool includePadding) | ||||
|         { | ||||
|             var separators = _columns.Count - 1; | ||||
|             var padding = includePadding ? _columns.Select(x => x.Padding.GetHorizontalPadding()).Sum() : 0; | ||||
|             return separators + EdgeCount + padding; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										386
									
								
								src/Spectre.Console/Composition/Widgets/Table.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										386
									
								
								src/Spectre.Console/Composition/Widgets/Table.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,386 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Internal; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a table. | ||||
|     /// </summary> | ||||
|     public sealed partial class Table : IRenderable | ||||
|     { | ||||
|         private readonly List<TableColumn> _columns; | ||||
|         private readonly List<List<Text>> _rows; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the number of columns in the table. | ||||
|         /// </summary> | ||||
|         public int ColumnCount => _columns.Count; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the number of rows in the table. | ||||
|         /// </summary> | ||||
|         public int RowCount => _rows.Count; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the kind of border to use. | ||||
|         /// </summary> | ||||
|         public BorderKind Border { get; set; } = BorderKind.Square; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether or not table headers should be shown. | ||||
|         /// </summary> | ||||
|         public bool ShowHeaders { get; set; } = true; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether or not the table should | ||||
|         /// fit the available space. If <c>false</c>, the table width will be | ||||
|         /// auto calculated. Defaults to <c>false</c>. | ||||
|         /// </summary> | ||||
|         public bool Expand { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the width of the table. | ||||
|         /// </summary> | ||||
|         public int? Width { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether or not to use | ||||
|         /// a "safe" border on legacy consoles that might not be able | ||||
|         /// to render non-ASCII characters. Defaults to <c>true</c>. | ||||
|         /// </summary> | ||||
|         public bool SafeBorder { get; set; } = true; | ||||
|  | ||||
|         // Whether this is a grid or not. | ||||
|         internal bool IsGrid { get; set; } | ||||
|  | ||||
|         // Whether or not the most right cell should be padded. | ||||
|         // This is almost always the case, unless we're rendering | ||||
|         // a grid without explicit padding in the last cell. | ||||
|         internal bool PadRightCell { get; set; } = true; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Table"/> class. | ||||
|         /// </summary> | ||||
|         public Table() | ||||
|         { | ||||
|             _columns = new List<TableColumn>(); | ||||
|             _rows = new List<List<Text>>(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds a column to the table. | ||||
|         /// </summary> | ||||
|         /// <param name="column">The column to add.</param> | ||||
|         public void AddColumn(string column) | ||||
|         { | ||||
|             if (column is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(column)); | ||||
|             } | ||||
|  | ||||
|             AddColumn(new TableColumn(column)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds a column to the table. | ||||
|         /// </summary> | ||||
|         /// <param name="column">The column to add.</param> | ||||
|         public void AddColumn(TableColumn column) | ||||
|         { | ||||
|             if (column is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(column)); | ||||
|             } | ||||
|  | ||||
|             if (_rows.Count > 0) | ||||
|             { | ||||
|                 throw new InvalidOperationException("Cannot add new columns to table with existing rows."); | ||||
|             } | ||||
|  | ||||
|             _columns.Add(column); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds multiple columns to the table. | ||||
|         /// </summary> | ||||
|         /// <param name="columns">The columns to add.</param> | ||||
|         public void AddColumns(params string[] columns) | ||||
|         { | ||||
|             if (columns is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(columns)); | ||||
|             } | ||||
|  | ||||
|             foreach (var column in columns) | ||||
|             { | ||||
|                 AddColumn(column); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds multiple columns to the table. | ||||
|         /// </summary> | ||||
|         /// <param name="columns">The columns to add.</param> | ||||
|         public void AddColumns(params TableColumn[] columns) | ||||
|         { | ||||
|             if (columns is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(columns)); | ||||
|             } | ||||
|  | ||||
|             foreach (var column in columns) | ||||
|             { | ||||
|                 AddColumn(column); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds an empty row to the table. | ||||
|         /// </summary> | ||||
|         public void AddEmptyRow() | ||||
|         { | ||||
|             var columns = new string[ColumnCount]; | ||||
|             Enumerable.Range(0, ColumnCount).ForEach(index => columns[index] = string.Empty); | ||||
|             AddRow(columns); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds a row to the table. | ||||
|         /// </summary> | ||||
|         /// <param name="columns">The row columns to add.</param> | ||||
|         public void AddRow(params string[] columns) | ||||
|         { | ||||
|             if (columns is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(columns)); | ||||
|             } | ||||
|  | ||||
|             if (columns.Length < _columns.Count) | ||||
|             { | ||||
|                 throw new InvalidOperationException("The number of row columns are less than the number of table columns."); | ||||
|             } | ||||
|  | ||||
|             if (columns.Length > _columns.Count) | ||||
|             { | ||||
|                 throw new InvalidOperationException("The number of row columns are greater than the number of table columns."); | ||||
|             } | ||||
|  | ||||
|             _rows.Add(columns.Select(column => Text.Markup(column)).ToList()); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         Measurement IRenderable.Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             if (context is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(context)); | ||||
|             } | ||||
|  | ||||
|             if (Width != null) | ||||
|             { | ||||
|                 maxWidth = Math.Min(Width.Value, maxWidth); | ||||
|             } | ||||
|  | ||||
|             maxWidth -= GetExtraWidth(includePadding: true); | ||||
|  | ||||
|             var measurements = _columns.Select(column => MeasureColumn(column, context, maxWidth)).ToList(); | ||||
|             var min = measurements.Sum(x => x.Min) + GetExtraWidth(includePadding: true); | ||||
|             var max = Width ?? measurements.Sum(x => x.Max) + GetExtraWidth(includePadding: true); | ||||
|  | ||||
|             return new Measurement(min, max); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         IEnumerable<Segment> IRenderable.Render(RenderContext context, int width) | ||||
|         { | ||||
|             if (context is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(context)); | ||||
|             } | ||||
|  | ||||
|             var border = Composition.Border.GetBorder(Border, (context.LegacyConsole || !context.Unicode) && SafeBorder); | ||||
|  | ||||
|             var showBorder = Border != BorderKind.None; | ||||
|             var hideBorder = Border == BorderKind.None; | ||||
|             var hasRows = _rows.Count > 0; | ||||
|  | ||||
|             var maxWidth = width; | ||||
|             if (Width != null) | ||||
|             { | ||||
|                 maxWidth = Math.Min(Width.Value, maxWidth); | ||||
|             } | ||||
|  | ||||
|             maxWidth -= GetExtraWidth(includePadding: true); | ||||
|  | ||||
|             // Calculate the column and table widths | ||||
|             var columnWidths = CalculateColumnWidths(context, maxWidth); | ||||
|  | ||||
|             // Update the table width. | ||||
|             width = columnWidths.Sum() + GetExtraWidth(includePadding: true); | ||||
|  | ||||
|             var rows = new List<List<Text>>(); | ||||
|             if (ShowHeaders) | ||||
|             { | ||||
|                 // Add columns to top of rows | ||||
|                 rows.Add(new List<Text>(_columns.Select(c => c.Text))); | ||||
|             } | ||||
|  | ||||
|             // Add rows. | ||||
|             rows.AddRange(_rows); | ||||
|  | ||||
|             // Iterate all rows | ||||
|             var result = new List<Segment>(); | ||||
|             foreach (var (index, firstRow, lastRow, row) in rows.Enumerate()) | ||||
|             { | ||||
|                 var cellHeight = 1; | ||||
|  | ||||
|                 // Get the list of cells for the row and calculate the cell height | ||||
|                 var cells = new List<List<SegmentLine>>(); | ||||
|                 foreach (var (columnIndex, _, _, (rowWidth, cell)) in columnWidths.Zip(row).Enumerate()) | ||||
|                 { | ||||
|                     var justification = _columns[columnIndex].Alignment; | ||||
|                     var childContext = context.WithJustification(justification); | ||||
|  | ||||
|                     var lines = Segment.SplitLines(((IRenderable)cell).Render(childContext, rowWidth)); | ||||
|                     cellHeight = Math.Max(cellHeight, lines.Count); | ||||
|                     cells.Add(lines); | ||||
|                 } | ||||
|  | ||||
|                 // Show top of header? | ||||
|                 if (firstRow && showBorder) | ||||
|                 { | ||||
|                     result.Add(new Segment(border.GetPart(BorderPart.HeaderTopLeft))); | ||||
|                     foreach (var (columnIndex, _, lastColumn, columnWidth) in columnWidths.Enumerate()) | ||||
|                     { | ||||
|                         var padding = _columns[columnIndex].Padding; | ||||
|  | ||||
|                         result.Add(new Segment(border.GetPart(BorderPart.HeaderTop, padding.Left))); // Left padding | ||||
|                         result.Add(new Segment(border.GetPart(BorderPart.HeaderTop, columnWidth))); | ||||
|                         result.Add(new Segment(border.GetPart(BorderPart.HeaderTop, padding.Right))); // Right padding | ||||
|  | ||||
|                         if (!lastColumn) | ||||
|                         { | ||||
|                             result.Add(new Segment(border.GetPart(BorderPart.HeaderTopSeparator))); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     result.Add(new Segment(border.GetPart(BorderPart.HeaderTopRight))); | ||||
|                     result.Add(Segment.LineBreak); | ||||
|                 } | ||||
|  | ||||
|                 // Iterate through each cell row | ||||
|                 foreach (var cellRowIndex in Enumerable.Range(0, cellHeight)) | ||||
|                 { | ||||
|                     // Make cells the same shape | ||||
|                     cells = Segment.MakeSameHeight(cellHeight, cells); | ||||
|  | ||||
|                     foreach (var (cellIndex, firstCell, lastCell, cell) in cells.Enumerate()) | ||||
|                     { | ||||
|                         if (firstCell && showBorder) | ||||
|                         { | ||||
|                             // Show left column edge | ||||
|                             result.Add(new Segment(border.GetPart(BorderPart.CellLeft))); | ||||
|                         } | ||||
|  | ||||
|                         // Pad column on left side. | ||||
|                         if (showBorder || IsGrid) | ||||
|                         { | ||||
|                             var leftPadding = _columns[cellIndex].Padding.Left; | ||||
|                             if (leftPadding > 0) | ||||
|                             { | ||||
|                                 result.Add(new Segment(new string(' ', leftPadding))); | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         // Add content | ||||
|                         result.AddRange(cell[cellRowIndex]); | ||||
|  | ||||
|                         // Pad cell content right | ||||
|                         var length = cell[cellRowIndex].Sum(segment => segment.CellLength(context.Encoding)); | ||||
|                         if (length < columnWidths[cellIndex]) | ||||
|                         { | ||||
|                             result.Add(new Segment(new string(' ', columnWidths[cellIndex] - length))); | ||||
|                         } | ||||
|  | ||||
|                         // Pad column on the right side | ||||
|                         if (showBorder || (hideBorder && !lastCell) || (hideBorder && lastCell && IsGrid && PadRightCell)) | ||||
|                         { | ||||
|                             var rightPadding = _columns[cellIndex].Padding.Right; | ||||
|                             if (rightPadding > 0) | ||||
|                             { | ||||
|                                 result.Add(new Segment(new string(' ', rightPadding))); | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         if (lastCell && showBorder) | ||||
|                         { | ||||
|                             // Add right column edge | ||||
|                             result.Add(new Segment(border.GetPart(BorderPart.CellRight))); | ||||
|                         } | ||||
|                         else if (showBorder) | ||||
|                         { | ||||
|                             // Add column separator | ||||
|                             result.Add(new Segment(border.GetPart(BorderPart.CellSeparator))); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     result.Add(Segment.LineBreak); | ||||
|                 } | ||||
|  | ||||
|                 // Show header separator? | ||||
|                 if (firstRow && showBorder && ShowHeaders && hasRows) | ||||
|                 { | ||||
|                     result.Add(new Segment(border.GetPart(BorderPart.HeaderBottomLeft))); | ||||
|                     foreach (var (columnIndex, first, lastColumn, columnWidth) in columnWidths.Enumerate()) | ||||
|                     { | ||||
|                         var padding = _columns[columnIndex].Padding; | ||||
|  | ||||
|                         result.Add(new Segment(border.GetPart(BorderPart.HeaderBottom, padding.Left))); // Left padding | ||||
|                         result.Add(new Segment(border.GetPart(BorderPart.HeaderBottom, columnWidth))); | ||||
|                         result.Add(new Segment(border.GetPart(BorderPart.HeaderBottom, padding.Right))); // Right padding | ||||
|  | ||||
|                         if (!lastColumn) | ||||
|                         { | ||||
|                             result.Add(new Segment(border.GetPart(BorderPart.HeaderBottomSeparator))); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     result.Add(new Segment(border.GetPart(BorderPart.HeaderBottomRight))); | ||||
|                     result.Add(Segment.LineBreak); | ||||
|                 } | ||||
|  | ||||
|                 // Show bottom of footer? | ||||
|                 if (lastRow && showBorder) | ||||
|                 { | ||||
|                     result.Add(new Segment(border.GetPart(BorderPart.FooterBottomLeft))); | ||||
|                     foreach (var (columnIndex, first, lastColumn, columnWidth) in columnWidths.Enumerate()) | ||||
|                     { | ||||
|                         var padding = _columns[columnIndex].Padding; | ||||
|  | ||||
|                         result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, padding.Left))); // Left padding | ||||
|                         result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, columnWidth))); | ||||
|                         result.Add(new Segment(border.GetPart(BorderPart.FooterBottom, padding.Right))); // Right padding | ||||
|  | ||||
|                         if (!lastColumn) | ||||
|                         { | ||||
|                             result.Add(new Segment(border.GetPart(BorderPart.FooterBottomSeparator))); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     result.Add(new Segment(border.GetPart(BorderPart.FooterBottomRight))); | ||||
|                     result.Add(Segment.LineBreak); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return result; | ||||
|         } | ||||
|  | ||||
|         private bool ShouldExpand() | ||||
|         { | ||||
|             return Expand || Width != null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										50
									
								
								src/Spectre.Console/Composition/Widgets/TableColumn.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/Spectre.Console/Composition/Widgets/TableColumn.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a table column. | ||||
|     /// </summary> | ||||
|     public sealed class TableColumn | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the text associated with the column. | ||||
|         /// </summary> | ||||
|         public Text Text { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the width of the column. | ||||
|         /// If <c>null</c>, the column will adapt to it's contents. | ||||
|         /// </summary> | ||||
|         public int? Width { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the padding of the column. | ||||
|         /// </summary> | ||||
|         public Padding Padding { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether wrapping of | ||||
|         /// text within the column should be prevented. | ||||
|         /// </summary> | ||||
|         public bool NoWrap { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the alignment of the column. | ||||
|         /// </summary> | ||||
|         public Justify? Alignment { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="TableColumn"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="text">The table column text.</param> | ||||
|         public TableColumn(string text) | ||||
|         { | ||||
|             Text = Text.Markup(text ?? throw new ArgumentNullException(nameof(text))); | ||||
|             Width = null; | ||||
|             Padding = new Padding(1, 1); | ||||
|             NoWrap = false; | ||||
|             Alignment = null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										270
									
								
								src/Spectre.Console/Composition/Widgets/Text.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										270
									
								
								src/Spectre.Console/Composition/Widgets/Text.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,270 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Diagnostics; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
| using System.Linq; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Internal; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a piece of text. | ||||
|     /// </summary> | ||||
|     [DebuggerDisplay("{_text,nq}")] | ||||
|     [SuppressMessage("Naming", "CA1724:Type names should not match namespaces")] | ||||
|     public sealed class Text : IRenderable | ||||
|     { | ||||
|         private readonly List<SegmentLine> _lines; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the text alignment. | ||||
|         /// </summary> | ||||
|         public Justify Alignment { get; set; } = Justify.Left; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Text"/> class. | ||||
|         /// </summary> | ||||
|         public Text() | ||||
|         { | ||||
|             _lines = new List<SegmentLine>(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Text"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="text">The text.</param> | ||||
|         /// <param name="style">The style of the text.</param> | ||||
|         public Text(string text, Style? style = null) | ||||
|             : this() | ||||
|         { | ||||
|             if (text is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(text)); | ||||
|             } | ||||
|  | ||||
|             Append(text, style); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a <see cref="Text"/> instance representing | ||||
|         /// the specified markup text. | ||||
|         /// </summary> | ||||
|         /// <param name="text">The markup text.</param> | ||||
|         /// <param name="style">The text style.</param> | ||||
|         /// <returns>a <see cref="Text"/> instance representing the specified markup text.</returns> | ||||
|         public static Text Markup(string text, Style? style = null) | ||||
|         { | ||||
|             var result = MarkupParser.Parse(text, style ?? Style.Plain); | ||||
|             return result; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public Measurement Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             if (_lines.Count == 0) | ||||
|             { | ||||
|                 return new Measurement(0, 0); | ||||
|             } | ||||
|  | ||||
|             var min = _lines.Max(line => line.Max(segment => segment.CellLength(context.Encoding))); | ||||
|             var max = _lines.Max(x => x.CellWidth(context.Encoding)); | ||||
|  | ||||
|             return new Measurement(min, max); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public IEnumerable<Segment> Render(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             if (context is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(context)); | ||||
|             } | ||||
|  | ||||
|             if (_lines.Count == 0) | ||||
|             { | ||||
|                 return Array.Empty<Segment>(); | ||||
|             } | ||||
|  | ||||
|             var justification = context.Justification ?? Alignment; | ||||
|  | ||||
|             var lines = SplitLines(context, maxWidth); | ||||
|             foreach (var (_, _, last, line) in lines.Enumerate()) | ||||
|             { | ||||
|                 var length = line.Sum(l => l.StripLineEndings().CellLength(context.Encoding)); | ||||
|                 if (length < maxWidth) | ||||
|                 { | ||||
|                     // Justify right side | ||||
|                     if (justification == Justify.Right) | ||||
|                     { | ||||
|                         var diff = maxWidth - length; | ||||
|                         line.Prepend(new Segment(new string(' ', diff))); | ||||
|                     } | ||||
|                     else if (justification == Justify.Center) | ||||
|                     { | ||||
|                         // Left side. | ||||
|                         var diff = (maxWidth - length) / 2; | ||||
|                         line.Prepend(new Segment(new string(' ', diff))); | ||||
|  | ||||
|                         // Right side | ||||
|                         line.Add(new Segment(new string(' ', diff))); | ||||
|                         var remainder = (maxWidth - length) % 2; | ||||
|                         if (remainder != 0) | ||||
|                         { | ||||
|                             line.Add(new Segment(new string(' ', remainder))); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return new SegmentLineEnumerator(lines); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Appends a piece of text. | ||||
|         /// </summary> | ||||
|         /// <param name="text">The text to append.</param> | ||||
|         /// <param name="style">The style of the appended text.</param> | ||||
|         public void Append(string text, Style? style = null) | ||||
|         { | ||||
|             if (text is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(text)); | ||||
|             } | ||||
|  | ||||
|             foreach (var (_, first, last, part) in text.SplitLines().Enumerate()) | ||||
|             { | ||||
|                 var current = part; | ||||
|                 if (string.IsNullOrEmpty(current) && last) | ||||
|                 { | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 if (first) | ||||
|                 { | ||||
|                     var line = _lines.LastOrDefault(); | ||||
|                     if (line == null) | ||||
|                     { | ||||
|                         _lines.Add(new SegmentLine()); | ||||
|                         line = _lines.Last(); | ||||
|                     } | ||||
|  | ||||
|                     if (string.IsNullOrEmpty(current)) | ||||
|                     { | ||||
|                         line.Add(Segment.Empty); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         foreach (var span in current.SplitWords()) | ||||
|                         { | ||||
|                             line.Add(new Segment(span, style ?? Style.Plain)); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     var line = new SegmentLine(); | ||||
|  | ||||
|                     if (string.IsNullOrEmpty(current)) | ||||
|                     { | ||||
|                         line.Add(Segment.Empty); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         foreach (var span in current.SplitWords()) | ||||
|                         { | ||||
|                             line.Add(new Segment(span, style ?? Style.Plain)); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     _lines.Add(line); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private List<SegmentLine> Clone() | ||||
|         { | ||||
|             var result = new List<SegmentLine>(); | ||||
|  | ||||
|             foreach (var line in _lines) | ||||
|             { | ||||
|                 var newLine = new SegmentLine(); | ||||
|                 foreach (var segment in line) | ||||
|                 { | ||||
|                     newLine.Add(segment); | ||||
|                 } | ||||
|  | ||||
|                 result.Add(newLine); | ||||
|             } | ||||
|  | ||||
|             return result; | ||||
|         } | ||||
|  | ||||
|         private List<SegmentLine> SplitLines(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             if (_lines.Max(x => x.CellWidth(context.Encoding)) <= maxWidth) | ||||
|             { | ||||
|                 return Clone(); | ||||
|             } | ||||
|  | ||||
|             var lines = new List<SegmentLine>(); | ||||
|             var line = new SegmentLine(); | ||||
|  | ||||
|             var newLine = true; | ||||
|             using (var iterator = new SegmentLineIterator(_lines)) | ||||
|             { | ||||
|                 while (iterator.MoveNext()) | ||||
|                 { | ||||
|                     var current = iterator.Current; | ||||
|                     if (current == null) | ||||
|                     { | ||||
|                         throw new InvalidOperationException("Iterator returned empty segment."); | ||||
|                     } | ||||
|  | ||||
|                     if (newLine && current.IsWhiteSpace && !current.IsLineBreak) | ||||
|                     { | ||||
|                         newLine = false; | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     newLine = false; | ||||
|  | ||||
|                     if (current.IsLineBreak) | ||||
|                     { | ||||
|                         line.Add(current); | ||||
|                         lines.Add(line); | ||||
|                         line = new SegmentLine(); | ||||
|                         newLine = true; | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     var length = current.CellLength(context.Encoding); | ||||
|                     if (line.CellWidth(context.Encoding) + length > maxWidth) | ||||
|                     { | ||||
|                         line.Add(Segment.Empty); | ||||
|                         lines.Add(line); | ||||
|                         line = new SegmentLine(); | ||||
|                         newLine = true; | ||||
|                     } | ||||
|  | ||||
|                     if (newLine && current.IsWhiteSpace) | ||||
|                     { | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     newLine = false; | ||||
|  | ||||
|                     line.Add(current); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Flush remaining. | ||||
|             if (line.Count > 0) | ||||
|             { | ||||
|                 lines.Add(line); | ||||
|             } | ||||
|  | ||||
|             return lines; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										27
									
								
								src/Spectre.Console/Composition/Widgets/TextExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/Spectre.Console/Composition/Widgets/TextExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="Text"/>. | ||||
|     /// </summary> | ||||
|     public static class TextExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Sets the text alignment. | ||||
|         /// </summary> | ||||
|         /// <param name="text">The <see cref="Text"/> instance.</param> | ||||
|         /// <param name="alignment">The text alignment.</param> | ||||
|         /// <returns>The same <see cref="Text"/> instance.</returns> | ||||
|         public static Text WithAlignment(this Text text, Justify alignment) | ||||
|         { | ||||
|             if (text is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(text)); | ||||
|             } | ||||
|  | ||||
|             text.Alignment = alignment; | ||||
|             return text; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										59
									
								
								src/Spectre.Console/ConsoleExtensions.Markup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/Spectre.Console/ConsoleExtensions.Markup.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| using System; | ||||
| using System.Globalization; | ||||
| using Spectre.Console.Internal; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="IAnsiConsole"/>. | ||||
|     /// </summary> | ||||
|     public static partial class ConsoleExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void Markup(this IAnsiConsole console, string format, params object[] args) | ||||
|         { | ||||
|             Markup(console, CultureInfo.CurrentCulture, format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void Markup(this IAnsiConsole console, IFormatProvider provider, string format, params object[] args) | ||||
|         { | ||||
|             console.Render(MarkupParser.Parse(string.Format(provider, format, args))); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void MarkupLine(this IAnsiConsole console, string format, params object[] args) | ||||
|         { | ||||
|             MarkupLine(console, CultureInfo.CurrentCulture, format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified markup, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void MarkupLine(this IAnsiConsole console, IFormatProvider provider, string format, params object[] args) | ||||
|         { | ||||
|             Markup(console, provider, format, args); | ||||
|             console.WriteLine(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										54
									
								
								src/Spectre.Console/ConsoleExtensions.Rendering.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/Spectre.Console/ConsoleExtensions.Rendering.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| using System; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Internal; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="IAnsiConsole"/>. | ||||
|     /// </summary> | ||||
|     public static partial class ConsoleExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Renders the specified object to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to render to.</param> | ||||
|         /// <param name="renderable">The object to render.</param> | ||||
|         public static void Render(this IAnsiConsole console, IRenderable renderable) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             if (renderable is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(renderable)); | ||||
|             } | ||||
|  | ||||
|             var options = new RenderContext(console.Encoding, console.Capabilities.LegacyConsole); | ||||
|  | ||||
|             using (console.PushStyle(Style.Plain)) | ||||
|             { | ||||
|                 var current = Style.Plain; | ||||
|                 foreach (var segment in renderable.Render(options, console.Width)) | ||||
|                 { | ||||
|                     if (string.IsNullOrEmpty(segment.Text)) | ||||
|                     { | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     if (!segment.Style.Equals(current)) | ||||
|                     { | ||||
|                         console.Foreground = segment.Style.Foreground; | ||||
|                         console.Background = segment.Style.Background; | ||||
|                         console.Decoration = segment.Style.Decoration; | ||||
|                         current = segment.Style; | ||||
|                     } | ||||
|  | ||||
|                     console.Write(segment.Text); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										339
									
								
								src/Spectre.Console/ConsoleExtensions.Write.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										339
									
								
								src/Spectre.Console/ConsoleExtensions.Write.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,339 @@ | ||||
| using System; | ||||
| using System.Globalization; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="IAnsiConsole"/>. | ||||
|     /// </summary> | ||||
|     public static partial class ConsoleExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Writes the specified string value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, string value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             if (value != null) | ||||
|             { | ||||
|                 console.Write(value); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit | ||||
|         /// signed integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, int value) | ||||
|         { | ||||
|             Write(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit | ||||
|         /// signed integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, IFormatProvider provider, int value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit | ||||
|         /// unsigned integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, uint value) | ||||
|         { | ||||
|             Write(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit | ||||
|         /// unsigned integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, IFormatProvider provider, uint value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit | ||||
|         /// signed integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, long value) | ||||
|         { | ||||
|             Write(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit | ||||
|         /// signed integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, IFormatProvider provider, long value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit | ||||
|         /// unsigned integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, ulong value) | ||||
|         { | ||||
|             Write(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit | ||||
|         /// unsigned integer value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, IFormatProvider provider, ulong value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified single-precision | ||||
|         /// floating-point value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, float value) | ||||
|         { | ||||
|             Write(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified single-precision | ||||
|         /// floating-point value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, IFormatProvider provider, float value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified double-precision | ||||
|         /// floating-point value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, double value) | ||||
|         { | ||||
|             Write(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified double-precision | ||||
|         /// floating-point value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, IFormatProvider provider, double value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.Write(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified decimal value, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, decimal value) | ||||
|         { | ||||
|             Write(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified decimal value, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, IFormatProvider provider, decimal value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             Write(console, value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified boolean value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, bool value) | ||||
|         { | ||||
|             Write(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified boolean value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, IFormatProvider provider, bool value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             Write(console, value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified Unicode character to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, char value) | ||||
|         { | ||||
|             Write(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified Unicode character to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, IFormatProvider provider, char value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             Write(console, value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified array of Unicode characters to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, char[] value) | ||||
|         { | ||||
|             Write(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified array of Unicode characters to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, IFormatProvider provider, char[] value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             if (value is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(value)); | ||||
|             } | ||||
|  | ||||
|             for (var index = 0; index < value.Length; index++) | ||||
|             { | ||||
|                 console.Write(value[index].ToString(provider)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified array of objects, | ||||
|         /// to the console using the specified format information. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, string format, params object[] args) | ||||
|         { | ||||
|             Write(console, CultureInfo.CurrentCulture, format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified array of objects, | ||||
|         /// to the console using the specified format information. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void Write(this IAnsiConsole console, IFormatProvider provider, string format, params object[] args) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             Write(console, string.Format(provider, format, args)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										368
									
								
								src/Spectre.Console/ConsoleExtensions.WriteLine.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										368
									
								
								src/Spectre.Console/ConsoleExtensions.WriteLine.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,368 @@ | ||||
| using System; | ||||
| using System.Globalization; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="IAnsiConsole"/>. | ||||
|     /// </summary> | ||||
|     public static partial class ConsoleExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Writes an empty line to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.Write(Environment.NewLine); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified string value, followed by the | ||||
|         /// current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, string value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             if (value != null) | ||||
|             { | ||||
|                 console.Write(value); | ||||
|             } | ||||
|  | ||||
|             console.WriteLine(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit signed integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, int value) | ||||
|         { | ||||
|             WriteLine(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit signed integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, int value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit unsigned integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, uint value) | ||||
|         { | ||||
|             WriteLine(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 32-bit unsigned integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, uint value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit signed integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, long value) | ||||
|         { | ||||
|             WriteLine(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit signed integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, long value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit unsigned integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, ulong value) | ||||
|         { | ||||
|             WriteLine(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified 64-bit unsigned integer value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, ulong value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified single-precision floating-point | ||||
|         /// value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, float value) | ||||
|         { | ||||
|             WriteLine(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified single-precision floating-point | ||||
|         /// value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, float value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified double-precision floating-point | ||||
|         /// value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, double value) | ||||
|         { | ||||
|             WriteLine(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified double-precision floating-point | ||||
|         /// value, followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, double value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.WriteLine(value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified decimal value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, decimal value) | ||||
|         { | ||||
|             WriteLine(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified decimal value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, decimal value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             WriteLine(console, value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified boolean value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, bool value) | ||||
|         { | ||||
|             WriteLine(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified boolean value, | ||||
|         /// followed by the current line terminator, to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, bool value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             WriteLine(console, value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified Unicode character, followed by the current | ||||
|         /// line terminator, value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, char value) | ||||
|         { | ||||
|             WriteLine(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified Unicode character, followed by the current | ||||
|         /// line terminator, value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, char value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             WriteLine(console, value.ToString(provider)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified array of Unicode characters, followed by the current | ||||
|         /// line terminator, value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, char[] value) | ||||
|         { | ||||
|             WriteLine(console, CultureInfo.CurrentCulture, value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the specified array of Unicode characters, followed by the current | ||||
|         /// line terminator, value to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="value">The value to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, char[] value) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             if (value is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(value)); | ||||
|             } | ||||
|  | ||||
|             for (var index = 0; index < value.Length; index++) | ||||
|             { | ||||
|                 console.Write(value[index].ToString(provider)); | ||||
|             } | ||||
|  | ||||
|             console.WriteLine(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified array of objects, | ||||
|         /// followed by the current line terminator, to the console | ||||
|         /// using the specified format information. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, string format, params object[] args) | ||||
|         { | ||||
|             WriteLine(console, CultureInfo.CurrentCulture, format, args); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes the text representation of the specified array of objects, | ||||
|         /// followed by the current line terminator, to the console | ||||
|         /// using the specified format information. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="provider">An object that supplies culture-specific formatting information.</param> | ||||
|         /// <param name="format">A composite format string.</param> | ||||
|         /// <param name="args">An array of objects to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, string format, params object[] args) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             WriteLine(console, string.Format(provider, format, args)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -5,10 +5,10 @@ namespace Spectre.Console | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="IAnsiConsole"/>. | ||||
|     /// </summary> | ||||
|     public static class ConsoleExtensions | ||||
|     public static partial class ConsoleExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Resets both colors and style for the console. | ||||
|         /// Resets colors and text decorations. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to reset.</param> | ||||
|         public static void Reset(this IAnsiConsole console) | ||||
| @@ -19,25 +19,25 @@ namespace Spectre.Console | ||||
|             } | ||||
|  | ||||
|             console.ResetColors(); | ||||
|             console.ResetStyle(); | ||||
|             console.ResetDecoration(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Resets the current style back to the default one. | ||||
|         /// Resets the current applied text decorations. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to reset the style for.</param> | ||||
|         public static void ResetStyle(this IAnsiConsole console) | ||||
|         /// <param name="console">The console to reset the text decorations for.</param> | ||||
|         public static void ResetDecoration(this IAnsiConsole console) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.Style = Styles.None; | ||||
|             console.Decoration = Decoration.None; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Resets the foreground and background colors to the default ones. | ||||
|         /// Resets the current applied foreground and background colors. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to reset colors for.</param> | ||||
|         public static void ResetColors(this IAnsiConsole console) | ||||
| @@ -50,34 +50,5 @@ namespace Spectre.Console | ||||
|             console.Foreground = Color.Default; | ||||
|             console.Background = Color.Default; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes an empty line to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.WriteLine(null); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes a line to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console to write to.</param> | ||||
|         /// <param name="content">The content to write.</param> | ||||
|         public static void WriteLine(this IAnsiConsole console, string content) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             console.WriteLine(content); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,18 +1,20 @@ | ||||
| using System; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
| 
 | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a style. | ||||
|     /// Represents text decoration. | ||||
|     /// </summary> | ||||
|     /// <remarks> | ||||
|     /// Support for different styles is up to the terminal. | ||||
|     /// Support for text decorations is up to the terminal. | ||||
|     /// </remarks> | ||||
|     [Flags] | ||||
|     public enum Styles | ||||
|     [SuppressMessage("Naming", "CA1714:Flags enums should have plural names")] | ||||
|     public enum Decoration | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// No style. | ||||
|         /// No text decoration. | ||||
|         /// </summary> | ||||
|         None = 0, | ||||
| 
 | ||||
| @@ -1,3 +1,5 @@ | ||||
| using System.Text; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
| @@ -8,22 +10,27 @@ namespace Spectre.Console | ||||
|         /// <summary> | ||||
|         /// Gets the console's capabilities. | ||||
|         /// </summary> | ||||
|         public AnsiConsoleCapabilities Capabilities { get; } | ||||
|         Capabilities Capabilities { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the buffer width of the console. | ||||
|         /// </summary> | ||||
|         public int Width { get; } | ||||
|         int Width { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the buffer height of the console. | ||||
|         /// </summary> | ||||
|         public int Height { get; } | ||||
|         int Height { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the current style. | ||||
|         /// Gets the console output encoding. | ||||
|         /// </summary> | ||||
|         Styles Style { get; set; } | ||||
|         Encoding Encoding { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the current text decoration. | ||||
|         /// </summary> | ||||
|         Decoration Decoration { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the current foreground. | ||||
| @@ -40,13 +47,5 @@ namespace Spectre.Console | ||||
|         /// </summary> | ||||
|         /// <param name="text">The string to write.</param> | ||||
|         void Write(string text); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Writes a string followed by a line terminator to the console. | ||||
|         /// </summary> | ||||
|         /// <param name="text"> | ||||
|         /// The string to write. If value is null, only the line terminator is written. | ||||
|         /// </param> | ||||
|         void WriteLine(string text); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -7,11 +7,11 @@ namespace Spectre.Console.Internal | ||||
|         public static string GetAnsi( | ||||
|             ColorSystem system, | ||||
|             string text, | ||||
|             Styles style, | ||||
|             Decoration decoration, | ||||
|             Color foreground, | ||||
|             Color background) | ||||
|         { | ||||
|             var codes = AnsiStyleBuilder.GetAnsiCodes(style); | ||||
|             var codes = AnsiDecorationBuilder.GetAnsiCodes(decoration); | ||||
|  | ||||
|             // Got foreground? | ||||
|             if (foreground != Color.Default) | ||||
|   | ||||
| @@ -2,52 +2,52 @@ using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static class AnsiStyleBuilder | ||||
|     internal static class AnsiDecorationBuilder | ||||
|     { | ||||
|         // TODO: Rewrite this to not yield | ||||
|         public static IEnumerable<byte> GetAnsiCodes(Styles style) | ||||
|         public static IEnumerable<byte> GetAnsiCodes(Decoration decoration) | ||||
|         { | ||||
|             if ((style & Styles.Bold) != 0) | ||||
|             if ((decoration & Decoration.Bold) != 0) | ||||
|             { | ||||
|                 yield return 1; | ||||
|             } | ||||
| 
 | ||||
|             if ((style & Styles.Dim) != 0) | ||||
|             if ((decoration & Decoration.Dim) != 0) | ||||
|             { | ||||
|                 yield return 2; | ||||
|             } | ||||
| 
 | ||||
|             if ((style & Styles.Italic) != 0) | ||||
|             if ((decoration & Decoration.Italic) != 0) | ||||
|             { | ||||
|                 yield return 3; | ||||
|             } | ||||
| 
 | ||||
|             if ((style & Styles.Underline) != 0) | ||||
|             if ((decoration & Decoration.Underline) != 0) | ||||
|             { | ||||
|                 yield return 4; | ||||
|             } | ||||
| 
 | ||||
|             if ((style & Styles.SlowBlink) != 0) | ||||
|             if ((decoration & Decoration.SlowBlink) != 0) | ||||
|             { | ||||
|                 yield return 5; | ||||
|             } | ||||
| 
 | ||||
|             if ((style & Styles.RapidBlink) != 0) | ||||
|             if ((decoration & Decoration.RapidBlink) != 0) | ||||
|             { | ||||
|                 yield return 6; | ||||
|             } | ||||
| 
 | ||||
|             if ((style & Styles.Invert) != 0) | ||||
|             if ((decoration & Decoration.Invert) != 0) | ||||
|             { | ||||
|                 yield return 7; | ||||
|             } | ||||
| 
 | ||||
|             if ((style & Styles.Conceal) != 0) | ||||
|             if ((decoration & Decoration.Conceal) != 0) | ||||
|             { | ||||
|                 yield return 8; | ||||
|             } | ||||
| 
 | ||||
|             if ((style & Styles.Strikethrough) != 0) | ||||
|             if ((decoration & Decoration.Strikethrough) != 0) | ||||
|             { | ||||
|                 yield return 9; | ||||
|             } | ||||
| @@ -13,7 +13,7 @@ namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static class AnsiDetector | ||||
|     { | ||||
|         private static readonly Regex[] Regexes = new[] | ||||
|         private static readonly Regex[] _regexes = new[] | ||||
|         { | ||||
|             new Regex("^xterm"), // xterm, PuTTY, Mintty | ||||
|             new Regex("^rxvt"), // RXVT | ||||
| @@ -32,12 +32,12 @@ namespace Spectre.Console.Internal | ||||
|             new Regex("bvterm"), // Bitvise SSH Client | ||||
|         }; | ||||
|  | ||||
|         public static bool SupportsAnsi(bool upgrade) | ||||
|         public static (bool SupportsAnsi, bool LegacyConsole) Detect(bool upgrade) | ||||
|         { | ||||
|             // Github action doesn't setup a correct PTY but supports ANSI. | ||||
|             if (!string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("GITHUB_ACTION"))) | ||||
|             { | ||||
|                 return true; | ||||
|                 return (true, false); | ||||
|             } | ||||
|  | ||||
|             // Running on Windows? | ||||
| @@ -47,23 +47,24 @@ namespace Spectre.Console.Internal | ||||
|                 var conEmu = Environment.GetEnvironmentVariable("ConEmuANSI"); | ||||
|                 if (!string.IsNullOrEmpty(conEmu) && conEmu.Equals("On", StringComparison.OrdinalIgnoreCase)) | ||||
|                 { | ||||
|                     return true; | ||||
|                     return (true, false); | ||||
|                 } | ||||
|  | ||||
|                 return Windows.SupportsAnsi(upgrade); | ||||
|                 var supportsAnsi = Windows.SupportsAnsi(upgrade, out var legacyConsole); | ||||
|                 return (supportsAnsi, legacyConsole); | ||||
|             } | ||||
|  | ||||
|             // Check if the terminal is of type ANSI/VT100/xterm compatible. | ||||
|             var term = Environment.GetEnvironmentVariable("TERM"); | ||||
|             if (!string.IsNullOrWhiteSpace(term)) | ||||
|             { | ||||
|                 if (Regexes.Any(regex => regex.IsMatch(term))) | ||||
|                 if (_regexes.Any(regex => regex.IsMatch(term))) | ||||
|                 { | ||||
|                     return true; | ||||
|                     return (true, false); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
|             return (false, true); | ||||
|         } | ||||
|  | ||||
|         [SuppressMessage("Design", "CA1060:Move pinvokes to native methods class")] | ||||
| @@ -71,8 +72,10 @@ namespace Spectre.Console.Internal | ||||
|         { | ||||
|             [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore")] | ||||
|             private const int STD_OUTPUT_HANDLE = -11; | ||||
|  | ||||
|             [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore")] | ||||
|             private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004; | ||||
|  | ||||
|             [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore")] | ||||
|             private const uint DISABLE_NEWLINE_AUTO_RETURN = 0x0008; | ||||
|  | ||||
| @@ -89,12 +92,14 @@ namespace Spectre.Console.Internal | ||||
|             public static extern uint GetLastError(); | ||||
|  | ||||
|             [SuppressMessage("Design", "CA1031:Do not catch general exception types")] | ||||
|             public static bool SupportsAnsi(bool upgrade) | ||||
|             public static bool SupportsAnsi(bool upgrade, out bool isLegacy) | ||||
|             { | ||||
|                 isLegacy = false; | ||||
|  | ||||
|                 try | ||||
|                 { | ||||
|                     var @out = GetStdHandle(STD_OUTPUT_HANDLE); | ||||
|                     if (!GetConsoleMode(@out, out uint mode)) | ||||
|                     if (!GetConsoleMode(@out, out var mode)) | ||||
|                     { | ||||
|                         // Could not get console mode. | ||||
|                         return false; | ||||
| @@ -102,6 +107,8 @@ namespace Spectre.Console.Internal | ||||
|  | ||||
|                     if ((mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0) | ||||
|                     { | ||||
|                         isLegacy = true; | ||||
|  | ||||
|                         if (!upgrade) | ||||
|                         { | ||||
|                             return false; | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
| using System.Text; | ||||
| 
 | ||||
| namespace Spectre.Console.Internal | ||||
| { | ||||
| @@ -8,8 +9,9 @@ namespace Spectre.Console.Internal | ||||
|         private readonly TextWriter _out; | ||||
|         private readonly ColorSystem _system; | ||||
| 
 | ||||
|         public AnsiConsoleCapabilities Capabilities { get; } | ||||
|         public Styles Style { get; set; } | ||||
|         public Capabilities Capabilities { get; } | ||||
|         public Encoding Encoding { get; } | ||||
|         public Decoration Decoration { get; set; } | ||||
|         public Color Foreground { get; set; } | ||||
|         public Color Background { get; set; } | ||||
| 
 | ||||
| @@ -39,29 +41,16 @@ namespace Spectre.Console.Internal | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public AnsiConsoleRenderer(TextWriter @out, ColorSystem system) | ||||
|         public AnsiConsoleRenderer(TextWriter @out, ColorSystem system, bool legacyConsole) | ||||
|         { | ||||
|             _out = @out ?? throw new ArgumentNullException(nameof(@out)); | ||||
|             _system = system; | ||||
| 
 | ||||
|             Capabilities = new AnsiConsoleCapabilities(true, system); | ||||
|             Capabilities = new Capabilities(true, system, legacyConsole); | ||||
|             Encoding = @out.IsStandardOut() ? System.Console.OutputEncoding : Encoding.UTF8; | ||||
|             Foreground = Color.Default; | ||||
|             Background = Color.Default; | ||||
|             Style = Styles.None; | ||||
|         } | ||||
| 
 | ||||
|         public void Reset(bool colors, bool styles) | ||||
|         { | ||||
|             if (colors) | ||||
|             { | ||||
|                 Foreground = Color.Default; | ||||
|                 Background = Color.Default; | ||||
|             } | ||||
| 
 | ||||
|             if (styles) | ||||
|             { | ||||
|                 Style = Styles.None; | ||||
|             } | ||||
|             Decoration = Decoration.None; | ||||
|         } | ||||
| 
 | ||||
|         public void Write(string text) | ||||
| @@ -71,29 +60,18 @@ namespace Spectre.Console.Internal | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             _out.Write(AnsiBuilder.GetAnsi( | ||||
|                 _system, | ||||
|                 text, | ||||
|                 Style, | ||||
|                 Foreground, | ||||
|                 Background)); | ||||
|         } | ||||
|             var parts = text.NormalizeLineEndings().Split(new[] { '\n' }); | ||||
|             foreach (var (_, _, last, part) in parts.Enumerate()) | ||||
|             { | ||||
|                 if (!string.IsNullOrEmpty(part)) | ||||
|                 { | ||||
|                     _out.Write(AnsiBuilder.GetAnsi(_system, part, Decoration, Foreground, Background)); | ||||
|                 } | ||||
| 
 | ||||
|         public void WriteLine(string text) | ||||
|         { | ||||
|             if (text == null) | ||||
|             { | ||||
|                 _out.WriteLine(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _out.WriteLine( | ||||
|                     AnsiBuilder.GetAnsi( | ||||
|                         _system, | ||||
|                         text, | ||||
|                         Style, | ||||
|                         Foreground, | ||||
|                         Background)); | ||||
|                 if (!last) | ||||
|                 { | ||||
|                     _out.Write(Environment.NewLine); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
							
								
								
									
										294
									
								
								src/Spectre.Console/Internal/Colors/ColorPalette.Generated.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										294
									
								
								src/Spectre.Console/Internal/Colors/ColorPalette.Generated.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,294 @@ | ||||
| //------------------------------------------------------------------------------ | ||||
| // <auto-generated> | ||||
| //     This code was generated by a tool. | ||||
| //     Generated 2020-08-03 15:17 | ||||
| // | ||||
| //     Changes to this file may cause incorrect behavior and will be lost if | ||||
| //     the code is regenerated. | ||||
| // </auto-generated> | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static partial class ColorPalette | ||||
|     { | ||||
|         private static List<Color> GenerateLegacyPalette() | ||||
|         { | ||||
|             return new List<Color> | ||||
|             { | ||||
|                 Color.Black, | ||||
|                 Color.Maroon, | ||||
|                 Color.Green, | ||||
|                 Color.Olive, | ||||
|                 Color.Navy, | ||||
|                 Color.Purple, | ||||
|                 Color.Teal, | ||||
|                 Color.Silver, | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         private static List<Color> GenerateStandardPalette(IReadOnlyList<Color> legacy) | ||||
|         { | ||||
|             return new List<Color>(legacy) | ||||
|             { | ||||
|                 Color.Grey, | ||||
|                 Color.Red, | ||||
|                 Color.Lime, | ||||
|                 Color.Yellow, | ||||
|                 Color.Blue, | ||||
|                 Color.Fuchsia, | ||||
|                 Color.Aqua, | ||||
|                 Color.White, | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         private static List<Color> GenerateEightBitPalette(IReadOnlyList<Color> standard) | ||||
|         { | ||||
|             return new List<Color>(standard) | ||||
|             { | ||||
|                 Color.Grey0, | ||||
|                 Color.NavyBlue, | ||||
|                 Color.DarkBlue, | ||||
|                 Color.Blue3, | ||||
|                 Color.Blue3_1, | ||||
|                 Color.Blue1, | ||||
|                 Color.DarkGreen, | ||||
|                 Color.DeepSkyBlue4, | ||||
|                 Color.DeepSkyBlue4_1, | ||||
|                 Color.DeepSkyBlue4_2, | ||||
|                 Color.DodgerBlue3, | ||||
|                 Color.DodgerBlue2, | ||||
|                 Color.Green4, | ||||
|                 Color.SpringGreen4, | ||||
|                 Color.Turquoise4, | ||||
|                 Color.DeepSkyBlue3, | ||||
|                 Color.DeepSkyBlue3_1, | ||||
|                 Color.DodgerBlue1, | ||||
|                 Color.Green3, | ||||
|                 Color.SpringGreen3, | ||||
|                 Color.DarkCyan, | ||||
|                 Color.LightSeaGreen, | ||||
|                 Color.DeepSkyBlue2, | ||||
|                 Color.DeepSkyBlue1, | ||||
|                 Color.Green3_1, | ||||
|                 Color.SpringGreen3_1, | ||||
|                 Color.SpringGreen2, | ||||
|                 Color.Cyan3, | ||||
|                 Color.DarkTurquoise, | ||||
|                 Color.Turquoise2, | ||||
|                 Color.Green1, | ||||
|                 Color.SpringGreen2_1, | ||||
|                 Color.SpringGreen1, | ||||
|                 Color.MediumSpringGreen, | ||||
|                 Color.Cyan2, | ||||
|                 Color.Cyan1, | ||||
|                 Color.DarkRed, | ||||
|                 Color.DeepPink4, | ||||
|                 Color.Purple4, | ||||
|                 Color.Purple4_1, | ||||
|                 Color.Purple3, | ||||
|                 Color.BlueViolet, | ||||
|                 Color.Orange4, | ||||
|                 Color.Grey37, | ||||
|                 Color.MediumPurple4, | ||||
|                 Color.SlateBlue3, | ||||
|                 Color.SlateBlue3_1, | ||||
|                 Color.RoyalBlue1, | ||||
|                 Color.Chartreuse4, | ||||
|                 Color.DarkSeaGreen4, | ||||
|                 Color.PaleTurquoise4, | ||||
|                 Color.SteelBlue, | ||||
|                 Color.SteelBlue3, | ||||
|                 Color.CornflowerBlue, | ||||
|                 Color.Chartreuse3, | ||||
|                 Color.DarkSeaGreen4_1, | ||||
|                 Color.CadetBlue, | ||||
|                 Color.CadetBlue_1, | ||||
|                 Color.SkyBlue3, | ||||
|                 Color.SteelBlue1, | ||||
|                 Color.Chartreuse3_1, | ||||
|                 Color.PaleGreen3, | ||||
|                 Color.SeaGreen3, | ||||
|                 Color.Aquamarine3, | ||||
|                 Color.MediumTurquoise, | ||||
|                 Color.SteelBlue1_1, | ||||
|                 Color.Chartreuse2, | ||||
|                 Color.SeaGreen2, | ||||
|                 Color.SeaGreen1, | ||||
|                 Color.SeaGreen1_1, | ||||
|                 Color.Aquamarine1, | ||||
|                 Color.DarkSlateGray2, | ||||
|                 Color.DarkRed_1, | ||||
|                 Color.DeepPink4_1, | ||||
|                 Color.DarkMagenta, | ||||
|                 Color.DarkMagenta_1, | ||||
|                 Color.DarkViolet, | ||||
|                 Color.Purple_1, | ||||
|                 Color.Orange4_1, | ||||
|                 Color.LightPink4, | ||||
|                 Color.Plum4, | ||||
|                 Color.MediumPurple3, | ||||
|                 Color.MediumPurple3_1, | ||||
|                 Color.SlateBlue1, | ||||
|                 Color.Yellow4, | ||||
|                 Color.Wheat4, | ||||
|                 Color.Grey53, | ||||
|                 Color.LightSlateGrey, | ||||
|                 Color.MediumPurple, | ||||
|                 Color.LightSlateBlue, | ||||
|                 Color.Yellow4_1, | ||||
|                 Color.DarkOliveGreen3, | ||||
|                 Color.DarkSeaGreen, | ||||
|                 Color.LightSkyBlue3, | ||||
|                 Color.LightSkyBlue3_1, | ||||
|                 Color.SkyBlue2, | ||||
|                 Color.Chartreuse2_1, | ||||
|                 Color.DarkOliveGreen3_1, | ||||
|                 Color.PaleGreen3_1, | ||||
|                 Color.DarkSeaGreen3, | ||||
|                 Color.DarkSlateGray3, | ||||
|                 Color.SkyBlue1, | ||||
|                 Color.Chartreuse1, | ||||
|                 Color.LightGreen, | ||||
|                 Color.LightGreen_1, | ||||
|                 Color.PaleGreen1, | ||||
|                 Color.Aquamarine1_1, | ||||
|                 Color.DarkSlateGray1, | ||||
|                 Color.Red3, | ||||
|                 Color.DeepPink4_2, | ||||
|                 Color.MediumVioletRed, | ||||
|                 Color.Magenta3, | ||||
|                 Color.DarkViolet_1, | ||||
|                 Color.Purple_2, | ||||
|                 Color.DarkOrange3, | ||||
|                 Color.IndianRed, | ||||
|                 Color.HotPink3, | ||||
|                 Color.MediumOrchid3, | ||||
|                 Color.MediumOrchid, | ||||
|                 Color.MediumPurple2, | ||||
|                 Color.DarkGoldenrod, | ||||
|                 Color.LightSalmon3, | ||||
|                 Color.RosyBrown, | ||||
|                 Color.Grey63, | ||||
|                 Color.MediumPurple2_1, | ||||
|                 Color.MediumPurple1, | ||||
|                 Color.Gold3, | ||||
|                 Color.DarkKhaki, | ||||
|                 Color.NavajoWhite3, | ||||
|                 Color.Grey69, | ||||
|                 Color.LightSteelBlue3, | ||||
|                 Color.LightSteelBlue, | ||||
|                 Color.Yellow3, | ||||
|                 Color.DarkOliveGreen3_2, | ||||
|                 Color.DarkSeaGreen3_1, | ||||
|                 Color.DarkSeaGreen2, | ||||
|                 Color.LightCyan3, | ||||
|                 Color.LightSkyBlue1, | ||||
|                 Color.GreenYellow, | ||||
|                 Color.DarkOliveGreen2, | ||||
|                 Color.PaleGreen1_1, | ||||
|                 Color.DarkSeaGreen2_1, | ||||
|                 Color.DarkSeaGreen1, | ||||
|                 Color.PaleTurquoise1, | ||||
|                 Color.Red3_1, | ||||
|                 Color.DeepPink3, | ||||
|                 Color.DeepPink3_1, | ||||
|                 Color.Magenta3_1, | ||||
|                 Color.Magenta3_2, | ||||
|                 Color.Magenta2, | ||||
|                 Color.DarkOrange3_1, | ||||
|                 Color.IndianRed_1, | ||||
|                 Color.HotPink3_1, | ||||
|                 Color.HotPink2, | ||||
|                 Color.Orchid, | ||||
|                 Color.MediumOrchid1, | ||||
|                 Color.Orange3, | ||||
|                 Color.LightSalmon3_1, | ||||
|                 Color.LightPink3, | ||||
|                 Color.Pink3, | ||||
|                 Color.Plum3, | ||||
|                 Color.Violet, | ||||
|                 Color.Gold3_1, | ||||
|                 Color.LightGoldenrod3, | ||||
|                 Color.Tan, | ||||
|                 Color.MistyRose3, | ||||
|                 Color.Thistle3, | ||||
|                 Color.Plum2, | ||||
|                 Color.Yellow3_1, | ||||
|                 Color.Khaki3, | ||||
|                 Color.LightGoldenrod2, | ||||
|                 Color.LightYellow3, | ||||
|                 Color.Grey84, | ||||
|                 Color.LightSteelBlue1, | ||||
|                 Color.Yellow2, | ||||
|                 Color.DarkOliveGreen1, | ||||
|                 Color.DarkOliveGreen1_1, | ||||
|                 Color.DarkSeaGreen1_1, | ||||
|                 Color.Honeydew2, | ||||
|                 Color.LightCyan1, | ||||
|                 Color.Red1, | ||||
|                 Color.DeepPink2, | ||||
|                 Color.DeepPink1, | ||||
|                 Color.DeepPink1_1, | ||||
|                 Color.Magenta2_1, | ||||
|                 Color.Magenta1, | ||||
|                 Color.OrangeRed1, | ||||
|                 Color.IndianRed1, | ||||
|                 Color.IndianRed1_1, | ||||
|                 Color.HotPink, | ||||
|                 Color.HotPink_1, | ||||
|                 Color.MediumOrchid1_1, | ||||
|                 Color.DarkOrange, | ||||
|                 Color.Salmon1, | ||||
|                 Color.LightCoral, | ||||
|                 Color.PaleVioletRed1, | ||||
|                 Color.Orchid2, | ||||
|                 Color.Orchid1, | ||||
|                 Color.Orange1, | ||||
|                 Color.SandyBrown, | ||||
|                 Color.LightSalmon1, | ||||
|                 Color.LightPink1, | ||||
|                 Color.Pink1, | ||||
|                 Color.Plum1, | ||||
|                 Color.Gold1, | ||||
|                 Color.LightGoldenrod2_1, | ||||
|                 Color.LightGoldenrod2_2, | ||||
|                 Color.NavajoWhite1, | ||||
|                 Color.MistyRose1, | ||||
|                 Color.Thistle1, | ||||
|                 Color.Yellow1, | ||||
|                 Color.LightGoldenrod1, | ||||
|                 Color.Khaki1, | ||||
|                 Color.Wheat1, | ||||
|                 Color.Cornsilk1, | ||||
|                 Color.Grey100, | ||||
|                 Color.Grey3, | ||||
|                 Color.Grey7, | ||||
|                 Color.Grey11, | ||||
|                 Color.Grey15, | ||||
|                 Color.Grey19, | ||||
|                 Color.Grey23, | ||||
|                 Color.Grey27, | ||||
|                 Color.Grey30, | ||||
|                 Color.Grey35, | ||||
|                 Color.Grey39, | ||||
|                 Color.Grey42, | ||||
|                 Color.Grey46, | ||||
|                 Color.Grey50, | ||||
|                 Color.Grey54, | ||||
|                 Color.Grey58, | ||||
|                 Color.Grey62, | ||||
|                 Color.Grey66, | ||||
|                 Color.Grey70, | ||||
|                 Color.Grey74, | ||||
|                 Color.Grey78, | ||||
|                 Color.Grey82, | ||||
|                 Color.Grey85, | ||||
|                 Color.Grey89, | ||||
|                 Color.Grey93, | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -4,7 +4,7 @@ using System.Linq; | ||||
|  | ||||
| namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static class ColorPalette | ||||
|     internal static partial class ColorPalette | ||||
|     { | ||||
|         public static IReadOnlyList<Color> Legacy { get; } | ||||
|         public static IReadOnlyList<Color> Standard { get; } | ||||
| @@ -12,92 +12,15 @@ namespace Spectre.Console.Internal | ||||
|  | ||||
|         static ColorPalette() | ||||
|         { | ||||
|             Legacy = new List<Color> | ||||
|             { | ||||
|                 Color.Black, Color.Maroon, Color.Green, Color.Olive, | ||||
|                 Color.Navy, Color.Purple, Color.Teal, Color.Silver, | ||||
|             }; | ||||
|  | ||||
|             Standard = new List<Color>(Legacy) | ||||
|             { | ||||
|                 Color.Grey, Color.Red, Color.Lime, Color.Yellow, | ||||
|                 Color.Blue, Color.Fuchsia, Color.Aqua, Color.White, | ||||
|             }; | ||||
|  | ||||
|             EightBit = new List<Color>(Standard) | ||||
|             { | ||||
|                 Color.Grey0, Color.NavyBlue, Color.DarkBlue, Color.Blue3, | ||||
|                 Color.Blue3_1, Color.Blue1, Color.DarkGreen, Color.DeepSkyBlue4, | ||||
|                 Color.DeepSkyBlue4_1, Color.DeepSkyBlue4_2, Color.DodgerBlue3, Color.DodgerBlue2, | ||||
|                 Color.Green4, Color.SpringGreen4, Color.Turquoise4, Color.DeepSkyBlue3, | ||||
|                 Color.DeepSkyBlue3_1, Color.DodgerBlue1, Color.Green3, Color.SpringGreen3, | ||||
|                 Color.DarkCyan, Color.LightSeaGreen, Color.DeepSkyBlue2, Color.DeepSkyBlue1, | ||||
|                 Color.Green3_1, Color.SpringGreen3_1, Color.SpringGreen2, Color.Cyan3, | ||||
|                 Color.DarkTurquoise, Color.Turquoise2, Color.Green1, Color.SpringGreen2_1, | ||||
|                 Color.SpringGreen1, Color.MediumSpringGreen, Color.Cyan2, Color.Cyan1, | ||||
|                 Color.DarkRed, Color.DeepPink4, Color.Purple4, Color.Purple4_1, | ||||
|                 Color.Purple3, Color.BlueViolet, Color.Orange4, Color.Grey37, | ||||
|                 Color.MediumPurple4, Color.SlateBlue3, Color.SlateBlue3_1, Color.RoyalBlue1, | ||||
|                 Color.Chartreuse4, Color.DarkSeaGreen4, Color.PaleTurquoise4, Color.SteelBlue, | ||||
|                 Color.SteelBlue3, Color.CornflowerBlue, Color.Chartreuse3, Color.DarkSeaGreen4_1, | ||||
|                 Color.CadetBlue, Color.CadetBlue_1, Color.SkyBlue3, Color.SteelBlue1, | ||||
|                 Color.Chartreuse3_1, Color.PaleGreen3, Color.SeaGreen3, Color.Aquamarine3, | ||||
|                 Color.MediumTurquoise, Color.SteelBlue1_1, Color.Chartreuse2, Color.SeaGreen2, | ||||
|                 Color.SeaGreen1, Color.SeaGreen1_1, Color.Aquamarine1, Color.DarkSlateGray2, | ||||
|                 Color.DarkRed_1, Color.DeepPink4_1, Color.DarkMagenta, Color.DarkMagenta_1, | ||||
|                 Color.DarkViolet, Color.Purple_1, Color.Orange4_1, Color.LightPink4, | ||||
|                 Color.Plum4, Color.MediumPurple3, Color.MediumPurple3_1, Color.SlateBlue1, | ||||
|                 Color.Yellow4, Color.Wheat4, Color.Grey53, Color.LightSlateGrey, | ||||
|                 Color.MediumPurple, Color.LightSlateBlue, Color.Yellow4_1, Color.DarkOliveGreen3, | ||||
|                 Color.DarkSeaGreen, Color.LightSkyBlue3, Color.LightSkyBlue3_1, Color.SkyBlue2, | ||||
|                 Color.Chartreuse2_1, Color.DarkOliveGreen3_1, Color.PaleGreen3_1, Color.DarkSeaGreen3, | ||||
|                 Color.DarkSlateGray3, Color.SkyBlue1, Color.Chartreuse1, Color.LightGreen, | ||||
|                 Color.LightGreen_1, Color.PaleGreen1, Color.Aquamarine1_1, Color.DarkSlateGray1, | ||||
|                 Color.Red3, Color.DeepPink4_2, Color.MediumVioletRed, Color.Magenta3, | ||||
|                 Color.DarkViolet_1, Color.Purple_2, Color.DarkOrange3, Color.IndianRed, | ||||
|                 Color.HotPink3, Color.MediumOrchid3, Color.MediumOrchid, Color.MediumPurple2, | ||||
|                 Color.DarkGoldenrod, Color.LightSalmon3, Color.RosyBrown, Color.Grey63, | ||||
|                 Color.MediumPurple2_1, Color.MediumPurple1, Color.Gold3, Color.DarkKhaki, | ||||
|                 Color.NavajoWhite3, Color.Grey69, Color.LightSteelBlue3, Color.LightSteelBlue, | ||||
|                 Color.Yellow3, Color.DarkOliveGreen3_2, Color.DarkSeaGreen3_1, Color.DarkSeaGreen2, | ||||
|                 Color.LightCyan3, Color.LightSkyBlue1, Color.GreenYellow, Color.DarkOliveGreen2, | ||||
|                 Color.PaleGreen1_1, Color.DarkSeaGreen2_1, Color.DarkSeaGreen1, Color.PaleTurquoise1, | ||||
|                 Color.Red3_1, Color.DeepPink3, Color.DeepPink3_1, Color.Magenta3_1, | ||||
|                 Color.Magenta3_2, Color.Magenta2, Color.DarkOrange3_1, Color.IndianRed_1, | ||||
|                 Color.HotPink3_1, Color.HotPink2, Color.Orchid, Color.MediumOrchid1, | ||||
|                 Color.Orange3, Color.LightSalmon3_1, Color.LightPink3, Color.Pink3, | ||||
|                 Color.Plum3, Color.Violet, Color.Gold3_1, Color.LightGoldenrod3, | ||||
|                 Color.Tan, Color.MistyRose3, Color.Thistle3, Color.Plum2, | ||||
|                 Color.Yellow3_1, Color.Khaki3, Color.LightGoldenrod2, Color.LightYellow3, | ||||
|                 Color.Grey84, Color.LightSteelBlue1, Color.Yellow2, Color.DarkOliveGreen1, | ||||
|                 Color.DarkOliveGreen1_1, Color.DarkSeaGreen1_1, Color.Honeydew2, Color.LightCyan1, | ||||
|                 Color.Red1, Color.DeepPink2, Color.DeepPink1, Color.DeepPink1_1, | ||||
|                 Color.Magenta2_1, Color.Magenta1, Color.OrangeRed1, Color.IndianRed1, | ||||
|                 Color.IndianRed1_1, Color.HotPink, Color.HotPink_1, Color.MediumOrchid1_1, | ||||
|                 Color.DarkOrange, Color.Salmon1, Color.LightCoral, Color.PaleVioletRed1, | ||||
|                 Color.Orchid2, Color.Orchid1, Color.Orange1, Color.SandyBrown, | ||||
|                 Color.LightSalmon1, Color.LightPink1, Color.Pink1, Color.Plum1, | ||||
|                 Color.Gold1, Color.LightGoldenrod2_1, Color.LightGoldenrod2_2, Color.NavajoWhite1, | ||||
|                 Color.MistyRose1, Color.Thistle1, Color.Yellow1, Color.LightGoldenrod1, | ||||
|                 Color.Khaki1, Color.Wheat1, Color.Cornsilk1, Color.Grey100, | ||||
|                 Color.Grey3, Color.Grey7, Color.Grey11, Color.Grey15, | ||||
|                 Color.Grey19, Color.Grey23, Color.Grey27, Color.Grey30, | ||||
|                 Color.Grey35, Color.Grey39, Color.Grey42, Color.Grey46, | ||||
|                 Color.Grey50, Color.Grey54, Color.Grey58, Color.Grey62, | ||||
|                 Color.Grey66, Color.Grey70, Color.Grey74, Color.Grey78, | ||||
|                 Color.Grey82, Color.Grey85, Color.Grey89, Color.Grey93, | ||||
|             }; | ||||
|             Legacy = GenerateLegacyPalette(); | ||||
|             Standard = GenerateStandardPalette(Legacy); | ||||
|             EightBit = GenerateEightBitPalette(Standard); | ||||
|         } | ||||
|  | ||||
|         internal static Color ExactOrClosest(ColorSystem system, Color color) | ||||
|         { | ||||
|             var exact = Exact(system, color); | ||||
|             if (exact != null) | ||||
|             { | ||||
|                 return exact.Value; | ||||
|             } | ||||
|  | ||||
|             return Closest(system, color); | ||||
|             return exact ?? Closest(system, color); | ||||
|         } | ||||
|  | ||||
|         private static Color? Exact(ColorSystem system, Color color) | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user