mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-10-31 09:09:25 +08:00 
			
		
		
		
	Rename Style and Appearance
				
					
				
			* Renames Style -> Decoration * Renames Appearance -> Style * Adds Style.Parse and Style.TryParse
This commit is contained in:
		 Patrik Svensson
					Patrik Svensson
				
			
				
					committed by
					
						 Patrik Svensson
						Patrik Svensson
					
				
			
			
				
	
			
			
			 Patrik Svensson
						Patrik Svensson
					
				
			
						parent
						
							c3286a4842
						
					
				
				
					commit
					98cf63f485
				
			| @@ -50,11 +50,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.MarkupLine("[yellow]{0}[/] [underline]world[/]!", "Goodbye"); | ||||
| AnsiConsole.MarkupLine("[bold yellow on red]{0}[/] [underline]world[/]!", "Goodbye"); | ||||
| ``` | ||||
|  | ||||
| If you want to get a reference to the default `IAnsiConsole`,  | ||||
| @@ -64,7 +64,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( | ||||
|   | ||||
| @@ -9,7 +9,7 @@ namespace Sample | ||||
|         { | ||||
|             // Use the static API to write some things to the console. | ||||
|             AnsiConsole.Foreground = Color.Chartreuse2; | ||||
|             AnsiConsole.Style = Styles.Underline | Styles.Bold; | ||||
|             AnsiConsole.Decoration = Decoration.Underline | Decoration.Bold; | ||||
|             AnsiConsole.WriteLine("Hello World!"); | ||||
|             AnsiConsole.Reset(); | ||||
|             AnsiConsole.MarkupLine("Capabilities: [yellow underline]{0}[/]", AnsiConsole.Capabilities); | ||||
| @@ -40,10 +40,10 @@ namespace Sample | ||||
|             // and downgrade them to the specified color system. | ||||
|             console.WriteLine(); | ||||
|             console.Foreground = Color.Chartreuse2; | ||||
|             console.Style = Styles.Underline | Styles.Bold; | ||||
|             console.Decoration = Decoration.Underline | Decoration.Bold; | ||||
|             console.WriteLine("Hello World!"); | ||||
|             console.ResetColors(); | ||||
|             console.ResetStyle(); | ||||
|             console.ResetDecoration(); | ||||
|             console.MarkupLine("Capabilities: [yellow underline]{0}[/]", console.Capabilities); | ||||
|             console.MarkupLine("Width=[yellow]{0}[/], Height=[yellow]{1}[/]", console.Width, console.Height); | ||||
|             console.MarkupLine("[white on red]Good[/] [red]bye[/]!"); | ||||
|   | ||||
| @@ -13,7 +13,7 @@ namespace Spectre.Console.Tests | ||||
|  | ||||
|         public Encoding Encoding => _console.Encoding; | ||||
|  | ||||
|         public Styles Style { get => _console.Style; set => _console.Style = value; } | ||||
|         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; } | ||||
|  | ||||
|   | ||||
| @@ -13,7 +13,7 @@ namespace Spectre.Console.Tests | ||||
|         public int Width { get; } | ||||
|         public int Height { get; } | ||||
|  | ||||
|         public Styles Style { get; set; } | ||||
|         public Decoration Decoration { get; set; } | ||||
|         public Color Foreground { get; set; } | ||||
|         public Color Background { get; set; } | ||||
|  | ||||
|   | ||||
| @@ -6,20 +6,20 @@ namespace Spectre.Console.Tests.Unit | ||||
|     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) | ||||
|         [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.Style = style; | ||||
|             fixture.Console.Decoration = decoration; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello World"); | ||||
| @@ -29,13 +29,13 @@ namespace Spectre.Console.Tests.Unit | ||||
|         } | ||||
|  | ||||
|         [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) | ||||
|         [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.Style = style; | ||||
|             fixture.Console.Decoration = decoration; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello World"); | ||||
|   | ||||
| @@ -8,13 +8,13 @@ namespace Spectre.Console.Tests.Unit | ||||
|     public partial class AnsiConsoleTests | ||||
|     { | ||||
|         [Fact] | ||||
|         public void Should_Combine_Style_And_Colors() | ||||
|         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.Style = Styles.Italic; | ||||
|             fixture.Console.Decoration = Decoration.Italic; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello"); | ||||
| @@ -30,7 +30,7 @@ namespace Spectre.Console.Tests.Unit | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.Standard); | ||||
|             fixture.Console.Foreground = Color.Default; | ||||
|             fixture.Console.Background = Color.NavajoWhite1; | ||||
|             fixture.Console.Style = Styles.Italic; | ||||
|             fixture.Console.Decoration = Decoration.Italic; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello"); | ||||
| @@ -46,7 +46,7 @@ namespace Spectre.Console.Tests.Unit | ||||
|             var fixture = new AnsiConsoleFixture(ColorSystem.Standard); | ||||
|             fixture.Console.Foreground = Color.RoyalBlue1; | ||||
|             fixture.Console.Background = Color.Default; | ||||
|             fixture.Console.Style = Styles.Italic; | ||||
|             fixture.Console.Decoration = Decoration.Italic; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello"); | ||||
| @@ -56,13 +56,13 @@ namespace Spectre.Console.Tests.Unit | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Not_Include_Style_If_Set_To_None() | ||||
|         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.Style = Styles.None; | ||||
|             fixture.Console.Decoration = Decoration.None; | ||||
|  | ||||
|             // When | ||||
|             fixture.Console.Write("Hello"); | ||||
|   | ||||
| @@ -1,24 +0,0 @@ | ||||
| using Shouldly; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public sealed class AppearanceTests | ||||
|     { | ||||
|         [Fact] | ||||
|         public void Should_Combine_Two_Appearances_As_Expected() | ||||
|         { | ||||
|             // Given | ||||
|             var first = new Appearance(Color.White, Color.Yellow, Styles.Bold | Styles.Italic); | ||||
|             var other = new Appearance(Color.Green, Color.Silver, Styles.Underline); | ||||
|  | ||||
|             // When | ||||
|             var result = first.Combine(other); | ||||
|  | ||||
|             // Then | ||||
|             result.Foreground.ShouldBe(Color.Green); | ||||
|             result.Background.ShouldBe(Color.Silver); | ||||
|             result.Style.ShouldBe(Styles.Bold | Styles.Italic | Styles.Underline); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -12,17 +12,17 @@ namespace Spectre.Console.Tests.Unit | ||||
|             public void Should_Split_Segment_Correctly() | ||||
|             { | ||||
|                 // Given | ||||
|                 var appearance = new Appearance(Color.Red, Color.Green, Styles.Bold); | ||||
|                 var segment = new Segment("Foo Bar", appearance); | ||||
|                 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.Appearance.ShouldBe(appearance); | ||||
|                 first.Style.ShouldBe(style); | ||||
|                 second.Text.ShouldBe(" Bar"); | ||||
|                 second.Appearance.ShouldBe(appearance); | ||||
|                 second.Style.ShouldBe(style); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -45,7 +45,7 @@ namespace Spectre.Console.Tests.Unit | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard); | ||||
|                 var text = Text.New("Hello World"); | ||||
|                 text.Stylize(start: 3, end: 8, new Appearance(style: Styles.Underline)); | ||||
|                 text.Stylize(start: 3, end: 8, new Style(decoration: Decoration.Underline)); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Render(text); | ||||
| @@ -62,7 +62,7 @@ namespace Spectre.Console.Tests.Unit | ||||
|                 // Given | ||||
|                 var fixture = new AnsiConsoleFixture(ColorSystem.Standard, width: 5); | ||||
|                 var text = Text.New("Hello World"); | ||||
|                 text.Stylize(start: 3, end: 8, new Appearance(style: Styles.Underline)); | ||||
|                 text.Stylize(start: 3, end: 8, new Style(decoration: Decoration.Underline)); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Console.Render(text); | ||||
|   | ||||
							
								
								
									
										237
									
								
								src/Spectre.Console.Tests/Unit/StyleTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								src/Spectre.Console.Tests/Unit/StyleTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,237 @@ | ||||
| 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("dim", Decoration.Dim)] | ||||
|             [InlineData("italic", Decoration.Italic)] | ||||
|             [InlineData("underline", Decoration.Underline)] | ||||
|             [InlineData("invert", Decoration.Invert)] | ||||
|             [InlineData("conceal", Decoration.Conceal)] | ||||
|             [InlineData("slowblink", Decoration.SlowBlink)] | ||||
|             [InlineData("rapidblink", Decoration.RapidBlink)] | ||||
|             [InlineData("strikethrough", 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'."); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public sealed class TheTryParseMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Default_Keyword_Should_Return_Default_Style() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.TryParse("default", out var style); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeTrue(); | ||||
|                 style.ShouldNotBeNull(); | ||||
|                 style.Foreground.ShouldBe(Color.Default); | ||||
|                 style.Background.ShouldBe(Color.Default); | ||||
|                 style.Decoration.ShouldBe(Decoration.None); | ||||
|             } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData("bold", Decoration.Bold)] | ||||
|             [InlineData("dim", Decoration.Dim)] | ||||
|             [InlineData("italic", Decoration.Italic)] | ||||
|             [InlineData("underline", Decoration.Underline)] | ||||
|             [InlineData("invert", Decoration.Invert)] | ||||
|             [InlineData("conceal", Decoration.Conceal)] | ||||
|             [InlineData("slowblink", Decoration.SlowBlink)] | ||||
|             [InlineData("rapidblink", Decoration.RapidBlink)] | ||||
|             [InlineData("strikethrough", Decoration.Strikethrough)] | ||||
|             public void Should_Parse_Decoration(string text, Decoration decoration) | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.TryParse(text, out var style); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeTrue(); | ||||
|                 style.ShouldNotBeNull(); | ||||
|                 style.Decoration.ShouldBe(decoration); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Parse_Text_And_Decoration() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.TryParse("bold underline blue on green", out var style); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeTrue(); | ||||
|                 style.ShouldNotBeNull(); | ||||
|                 style.Decoration.ShouldBe(Decoration.Bold | Decoration.Underline); | ||||
|                 style.Foreground.ShouldBe(Color.Blue); | ||||
|                 style.Background.ShouldBe(Color.Green); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Parse_Background_If_Foreground_Is_Set_To_Default() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.TryParse("default on green", out var style); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeTrue(); | ||||
|                 style.ShouldNotBeNull(); | ||||
|                 style.Decoration.ShouldBe(Decoration.None); | ||||
|                 style.Foreground.ShouldBe(Color.Default); | ||||
|                 style.Background.ShouldBe(Color.Green); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Foreground_Is_Set_Twice() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.TryParse("green yellow", out var style); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeFalse(); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Background_Is_Set_Twice() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.TryParse("green on blue yellow", out var style); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeFalse(); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Color_Name_Could_Not_Be_Found() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.TryParse("bold lol", out var style); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeFalse(); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Background_Color_Name_Could_Not_Be_Found() | ||||
|             { | ||||
|                 // Given, When | ||||
|                 var result = Style.TryParse("blue on lol", out var style); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeFalse(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -63,12 +63,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 +83,7 @@ namespace Spectre.Console | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Resets colors and styles to the default ones. | ||||
|         /// Resets colors and text decorations. | ||||
|         /// </summary> | ||||
|         public static void Reset() | ||||
|         { | ||||
| @@ -91,15 +91,15 @@ 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() | ||||
|         { | ||||
|   | ||||
| @@ -1,108 +0,0 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents color and style. | ||||
|     /// </summary> | ||||
|     public sealed class Appearance : IEquatable<Appearance> | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the foreground color. | ||||
|         /// </summary> | ||||
|         public Color Foreground { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the background color. | ||||
|         /// </summary> | ||||
|         public Color Background { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the style. | ||||
|         /// </summary> | ||||
|         public Styles Style { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets an <see cref="Appearance"/> with the | ||||
|         /// default color and without style. | ||||
|         /// </summary> | ||||
|         public static Appearance Plain { get; } = new Appearance(); | ||||
|  | ||||
|         private Appearance() | ||||
|             : this(null, null, null) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Appearance"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="foreground">The foreground color.</param> | ||||
|         /// <param name="background">The background color.</param> | ||||
|         /// <param name="style">The style.</param> | ||||
|         public Appearance(Color? foreground = null, Color? background = null, Styles? style = null) | ||||
|         { | ||||
|             Foreground = foreground ?? Color.Default; | ||||
|             Background = background ?? Color.Default; | ||||
|             Style = style ?? Styles.None; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Combines this appearance with another one. | ||||
|         /// </summary> | ||||
|         /// <param name="other">The item to combine with this.</param> | ||||
|         /// <returns>A new appearance representing a combination of this and the other one.</returns> | ||||
|         public Appearance Combine(Appearance other) | ||||
|         { | ||||
|             if (other is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(other)); | ||||
|             } | ||||
|  | ||||
|             var foreground = Foreground; | ||||
|             if (!other.Foreground.IsDefault) | ||||
|             { | ||||
|                 foreground = other.Foreground; | ||||
|             } | ||||
|  | ||||
|             var background = Background; | ||||
|             if (!other.Background.IsDefault) | ||||
|             { | ||||
|                 background = other.Background; | ||||
|             } | ||||
|  | ||||
|             return new Appearance(foreground, background, Style | other.Style); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override int GetHashCode() | ||||
|         { | ||||
|             unchecked | ||||
|             { | ||||
|                 var hash = (int)2166136261; | ||||
|                 hash = (hash * 16777619) ^ Foreground.GetHashCode(); | ||||
|                 hash = (hash * 16777619) ^ Background.GetHashCode(); | ||||
|                 hash = (hash * 16777619) ^ Style.GetHashCode(); | ||||
|                 return hash; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override bool Equals(object obj) | ||||
|         { | ||||
|             return Equals(obj as Appearance); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool Equals(Appearance other) | ||||
|         { | ||||
|             if (other == null) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             return Foreground.Equals(other.Foreground) && | ||||
|                 Background.Equals(other.Background) && | ||||
|                 Style == other.Style; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -25,16 +25,16 @@ namespace Spectre.Console.Composition | ||||
|         public bool IsLineBreak { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the appearance of the segment. | ||||
|         /// Gets the segment style. | ||||
|         /// </summary> | ||||
|         public Appearance Appearance { get; } | ||||
|         public Style Style { get; } | ||||
|  | ||||
|         /// <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, Appearance.Plain) | ||||
|             : this(text, Style.Plain) | ||||
|         { | ||||
|         } | ||||
|  | ||||
| @@ -42,16 +42,16 @@ namespace Spectre.Console.Composition | ||||
|         /// Initializes a new instance of the <see cref="Segment"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="text">The segment text.</param> | ||||
|         /// <param name="appearance">The segment appearance.</param> | ||||
|         public Segment(string text, Appearance appearance) | ||||
|             : this(text, appearance, false) | ||||
|         /// <param name="style">The segment style.</param> | ||||
|         public Segment(string text, Style style) | ||||
|             : this(text, style, false) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         private Segment(string text, Appearance appearance, bool lineBreak) | ||||
|         private Segment(string text, Style style, bool lineBreak) | ||||
|         { | ||||
|             Text = text?.NormalizeLineEndings() ?? throw new ArgumentNullException(nameof(text)); | ||||
|             Appearance = appearance; | ||||
|             Style = style; | ||||
|             IsLineBreak = lineBreak; | ||||
|         } | ||||
|  | ||||
| @@ -61,7 +61,7 @@ namespace Spectre.Console.Composition | ||||
|         /// <returns>A segment that represents an implicit line break.</returns> | ||||
|         public static Segment LineBreak() | ||||
|         { | ||||
|             return new Segment("\n", Appearance.Plain, true); | ||||
|             return new Segment("\n", Style.Plain, true); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -81,7 +81,7 @@ namespace Spectre.Console.Composition | ||||
|         /// <returns>A new segment without any trailing line endings.</returns> | ||||
|         public Segment StripLineEndings() | ||||
|         { | ||||
|             return new Segment(Text.TrimEnd('\n'), Appearance); | ||||
|             return new Segment(Text.TrimEnd('\n'), Style); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -102,8 +102,8 @@ namespace Spectre.Console.Composition | ||||
|             } | ||||
|  | ||||
|             return ( | ||||
|                 new Segment(Text.Substring(0, offset), Appearance), | ||||
|                 new Segment(Text.Substring(offset, Text.Length - offset), Appearance)); | ||||
|                 new Segment(Text.Substring(0, offset), Style), | ||||
|                 new Segment(Text.Substring(offset, Text.Length - offset), Style)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -178,7 +178,7 @@ namespace Spectre.Console.Composition | ||||
|                         { | ||||
|                             if (parts[0].Length > 0) | ||||
|                             { | ||||
|                                 line.Add(new Segment(parts[0], segment.Appearance)); | ||||
|                                 line.Add(new Segment(parts[0], segment.Style)); | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,7 @@ using Spectre.Console.Internal; | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents text with color and style. | ||||
|     /// Represents text with color and decorations. | ||||
|     /// </summary> | ||||
|     [SuppressMessage("Naming", "CA1724:Type names should not match namespaces")] | ||||
|     public sealed class Text : IRenderable | ||||
| @@ -21,13 +21,13 @@ namespace Spectre.Console | ||||
|         { | ||||
|             public int Start { get; } | ||||
|             public int End { get; } | ||||
|             public Appearance Appearance { get; } | ||||
|             public Style Style { get; } | ||||
|  | ||||
|             public Span(int start, int end, Appearance appearance) | ||||
|             public Span(int start, int end, Style style) | ||||
|             { | ||||
|                 Start = start; | ||||
|                 End = end; | ||||
|                 Appearance = appearance ?? Appearance.Plain; | ||||
|                 Style = style ?? Style.Plain; | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -47,21 +47,21 @@ namespace Spectre.Console | ||||
|         /// <param name="text">The text.</param> | ||||
|         /// <param name="foreground">The foreground.</param> | ||||
|         /// <param name="background">The background.</param> | ||||
|         /// <param name="style">The style.</param> | ||||
|         /// <param name="decoration">The text decoration.</param> | ||||
|         /// <returns>A <see cref="Text"/> instance.</returns> | ||||
|         public static Text New( | ||||
|             string text, Color? foreground = null, Color? background = null, Styles? style = null) | ||||
|             string text, Color? foreground = null, Color? background = null, Decoration? decoration = null) | ||||
|         { | ||||
|             var result = MarkupParser.Parse(text, new Appearance(foreground, background, style)); | ||||
|             var result = MarkupParser.Parse(text, new Style(foreground, background, decoration)); | ||||
|             return result; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Appends some text with a style. | ||||
|         /// Appends some text with the specified color and decorations. | ||||
|         /// </summary> | ||||
|         /// <param name="text">The text to append.</param> | ||||
|         /// <param name="appearance">The appearance of the text.</param> | ||||
|         public void Append(string text, Appearance appearance) | ||||
|         /// <param name="style">The text style.</param> | ||||
|         public void Append(string text, Style style) | ||||
|         { | ||||
|             if (text == null) | ||||
|             { | ||||
| @@ -73,7 +73,7 @@ namespace Spectre.Console | ||||
|  | ||||
|             _text += text; | ||||
|  | ||||
|             Stylize(start, end, appearance); | ||||
|             Stylize(start, end, style); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -81,8 +81,8 @@ namespace Spectre.Console | ||||
|         /// </summary> | ||||
|         /// <param name="start">The start position.</param> | ||||
|         /// <param name="end">The end position.</param> | ||||
|         /// <param name="appearance">The color and style to apply.</param> | ||||
|         public void Stylize(int start, int end, Appearance appearance) | ||||
|         /// <param name="style">The style to apply.</param> | ||||
|         public void Stylize(int start, int end, Style style) | ||||
|         { | ||||
|             if (start >= end) | ||||
|             { | ||||
| @@ -92,7 +92,7 @@ namespace Spectre.Console | ||||
|             start = Math.Max(start, 0); | ||||
|             end = Math.Min(end, _text.Length); | ||||
|  | ||||
|             _spans.Add(new Span(start, end, appearance)); | ||||
|             _spans.Add(new Span(start, end, style)); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
| @@ -149,7 +149,7 @@ namespace Spectre.Console | ||||
|                     } | ||||
|  | ||||
|                     result.Add(Segment.LineBreak()); | ||||
|                     queue.Enqueue(new Segment(second.Text.Substring(1), second.Appearance)); | ||||
|                     queue.Enqueue(new Segment(second.Text.Substring(1), second.Style)); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
| @@ -162,8 +162,8 @@ namespace Spectre.Console | ||||
|             // https://github.com/willmcgugan/rich/blob/eb2f0d5277c159d8693636ec60c79c5442fd2e43/rich/text.py#L492 | ||||
|  | ||||
|             // Create the style map. | ||||
|             var styleMap = _spans.SelectIndex((span, index) => (span, index)).ToDictionary(x => x.index + 1, x => x.span.Appearance); | ||||
|             styleMap[0] = Appearance.Plain; | ||||
|             var styleMap = _spans.SelectIndex((span, index) => (span, index)).ToDictionary(x => x.index + 1, x => x.span.Style); | ||||
|             styleMap[0] = Style.Plain; | ||||
|  | ||||
|             // Create a span list. | ||||
|             var spans = new List<(int Offset, bool Leaving, int Style)>(); | ||||
| @@ -173,7 +173,7 @@ namespace Spectre.Console | ||||
|             spans.Add((_text.Length, true, 0)); | ||||
|             spans = spans.OrderBy(x => x.Offset).ThenBy(x => !x.Leaving).ToList(); | ||||
|  | ||||
|             // Keep track of applied appearances using a stack | ||||
|             // Keep track of applied styles using a stack | ||||
|             var styleStack = new Stack<int>(); | ||||
|  | ||||
|             // Now build the segments. | ||||
| @@ -195,7 +195,7 @@ namespace Spectre.Console | ||||
|                 { | ||||
|                     // Build the current style from the stack | ||||
|                     var styleIndices = styleStack.OrderBy(index => index).ToArray(); | ||||
|                     var currentStyle = Appearance.Plain.Combine(styleIndices.Select(index => styleMap[index])); | ||||
|                     var currentStyle = Style.Plain.Combine(styleIndices.Select(index => styleMap[index])); | ||||
|  | ||||
|                     // Create segment | ||||
|                     var text = _text.Substring(offset, Math.Min(_text.Length - offset, nextOffset - offset)); | ||||
|   | ||||
| @@ -28,9 +28,9 @@ namespace Spectre.Console | ||||
|  | ||||
|             foreach (var segment in renderable.Render(console.Encoding, console.Width)) | ||||
|             { | ||||
|                 if (!segment.Appearance.Equals(Appearance.Plain)) | ||||
|                 if (!segment.Style.Equals(Style.Plain)) | ||||
|                 { | ||||
|                     using (var appearance = console.PushAppearance(segment.Appearance)) | ||||
|                     using (var style = console.PushStyle(segment.Style)) | ||||
|                     { | ||||
|                         console.Write(segment.Text); | ||||
|                     } | ||||
|   | ||||
| @@ -8,7 +8,7 @@ namespace Spectre.Console | ||||
|     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) | ||||
|   | ||||
| @@ -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, | ||||
| 
 | ||||
| @@ -28,9 +28,9 @@ namespace Spectre.Console | ||||
|         Encoding Encoding { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the current style. | ||||
|         /// Gets or sets the current text decoration. | ||||
|         /// </summary> | ||||
|         Styles Style { get; set; } | ||||
|         Decoration Decoration { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the current foreground. | ||||
|   | ||||
| @@ -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; | ||||
|             } | ||||
| @@ -11,7 +11,7 @@ namespace Spectre.Console.Internal | ||||
|  | ||||
|         public Capabilities Capabilities { get; } | ||||
|         public Encoding Encoding { get; } | ||||
|         public Styles Style { get; set; } | ||||
|         public Decoration Decoration { get; set; } | ||||
|         public Color Foreground { get; set; } | ||||
|         public Color Background { get; set; } | ||||
|  | ||||
| @@ -50,21 +50,7 @@ namespace Spectre.Console.Internal | ||||
|             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) | ||||
| @@ -77,7 +63,7 @@ namespace Spectre.Console.Internal | ||||
|             _out.Write(AnsiBuilder.GetAnsi( | ||||
|                 _system, | ||||
|                 text.NormalizeLineEndings(native: true), | ||||
|                 Style, | ||||
|                 Decoration, | ||||
|                 Foreground, | ||||
|                 Background)); | ||||
|         } | ||||
|   | ||||
| @@ -25,7 +25,7 @@ namespace Spectre.Console.Internal | ||||
|             { | ||||
|                 return new AnsiConsoleRenderer(buffer, colorSystem) | ||||
|                 { | ||||
|                     Style = Styles.None, | ||||
|                     Decoration = Decoration.None, | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|   | ||||
							
								
								
									
										35
									
								
								src/Spectre.Console/Internal/DecorationTable.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/Spectre.Console/Internal/DecorationTable.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
|  | ||||
| namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static class DecorationTable | ||||
|     { | ||||
|         private static readonly Dictionary<string, Decoration?> _lookup; | ||||
|  | ||||
|         [SuppressMessage("Performance", "CA1810:Initialize reference type static fields inline")] | ||||
|         static DecorationTable() | ||||
|         { | ||||
|             _lookup = new Dictionary<string, Decoration?>(StringComparer.OrdinalIgnoreCase) | ||||
|             { | ||||
|                 { "none", Decoration.None }, | ||||
|                 { "bold", Decoration.Bold }, | ||||
|                 { "dim", Decoration.Dim }, | ||||
|                 { "italic", Decoration.Italic }, | ||||
|                 { "underline", Decoration.Underline }, | ||||
|                 { "invert", Decoration.Invert }, | ||||
|                 { "conceal", Decoration.Conceal }, | ||||
|                 { "slowblink", Decoration.SlowBlink }, | ||||
|                 { "rapidblink", Decoration.RapidBlink }, | ||||
|                 { "strikethrough", Decoration.Strikethrough }, | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         public static Decoration? GetDecoration(string name) | ||||
|         { | ||||
|             _lookup.TryGetValue(name, out var result); | ||||
|             return result; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,18 +0,0 @@ | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static class AppearanceExtensions | ||||
|     { | ||||
|         public static Appearance Combine(this Appearance appearance, IEnumerable<Appearance> source) | ||||
|         { | ||||
|             var current = appearance; | ||||
|             foreach (var item in source) | ||||
|             { | ||||
|                 current = current.Combine(item); | ||||
|             } | ||||
|  | ||||
|             return current; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -5,18 +5,23 @@ namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static class ConsoleExtensions | ||||
|     { | ||||
|         public static IDisposable PushAppearance(this IAnsiConsole console, Appearance appearance) | ||||
|         public static IDisposable PushStyle(this IAnsiConsole console, Style style) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             var current = new Appearance(console.Foreground, console.Background, console.Style); | ||||
|             console.SetColor(appearance.Foreground, true); | ||||
|             console.SetColor(appearance.Background, false); | ||||
|             console.Style = appearance.Style; | ||||
|             return new AppearanceScope(console, current); | ||||
|             if (style is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(style)); | ||||
|             } | ||||
|  | ||||
|             var current = new Style(console.Foreground, console.Background, console.Decoration); | ||||
|             console.SetColor(style.Foreground, true); | ||||
|             console.SetColor(style.Background, false); | ||||
|             console.Decoration = style.Decoration; | ||||
|             return new StyleScope(console, current); | ||||
|         } | ||||
|  | ||||
|         public static IDisposable PushColor(this IAnsiConsole console, Color color, bool foreground) | ||||
| @@ -31,16 +36,16 @@ namespace Spectre.Console.Internal | ||||
|             return new ColorScope(console, current, foreground); | ||||
|         } | ||||
|  | ||||
|         public static IDisposable PushStyle(this IAnsiConsole console, Styles style) | ||||
|         public static IDisposable PushDecoration(this IAnsiConsole console, Decoration decoration) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             var current = console.Style; | ||||
|             console.Style = style; | ||||
|             return new StyleScope(console, current); | ||||
|             var current = console.Decoration; | ||||
|             console.Decoration = decoration; | ||||
|             return new DecorationScope(console, current); | ||||
|         } | ||||
|  | ||||
|         public static void SetColor(this IAnsiConsole console, Color color, bool foreground) | ||||
| @@ -61,30 +66,30 @@ namespace Spectre.Console.Internal | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     internal sealed class AppearanceScope : IDisposable | ||||
|     internal sealed class StyleScope : IDisposable | ||||
|     { | ||||
|         private readonly IAnsiConsole _console; | ||||
|         private readonly Appearance _apperance; | ||||
|         private readonly Style _style; | ||||
|  | ||||
|         public AppearanceScope(IAnsiConsole console, Appearance appearance) | ||||
|         public StyleScope(IAnsiConsole console, Style style) | ||||
|         { | ||||
|             _console = console ?? throw new ArgumentNullException(nameof(console)); | ||||
|             _apperance = appearance; | ||||
|             _style = style ?? throw new ArgumentNullException(nameof(style)); | ||||
|         } | ||||
|  | ||||
|         [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations")] | ||||
|         [SuppressMessage("Performance", "CA1821:Remove empty Finalizers")] | ||||
|         ~AppearanceScope() | ||||
|         ~StyleScope() | ||||
|         { | ||||
|             throw new InvalidOperationException("Appearance scope was not disposed."); | ||||
|             throw new InvalidOperationException("Style scope was not disposed."); | ||||
|         } | ||||
|  | ||||
|         public void Dispose() | ||||
|         { | ||||
|             GC.SuppressFinalize(this); | ||||
|             _console.SetColor(_apperance.Foreground, true); | ||||
|             _console.SetColor(_apperance.Background, false); | ||||
|             _console.Style = _apperance.Style; | ||||
|             _console.SetColor(_style.Foreground, true); | ||||
|             _console.SetColor(_style.Background, false); | ||||
|             _console.Decoration = _style.Decoration; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -115,28 +120,28 @@ namespace Spectre.Console.Internal | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     internal sealed class StyleScope : IDisposable | ||||
|     internal sealed class DecorationScope : IDisposable | ||||
|     { | ||||
|         private readonly IAnsiConsole _console; | ||||
|         private readonly Styles _style; | ||||
|         private readonly Decoration _decoration; | ||||
|  | ||||
|         public StyleScope(IAnsiConsole console, Styles color) | ||||
|         public DecorationScope(IAnsiConsole console, Decoration decoration) | ||||
|         { | ||||
|             _console = console ?? throw new ArgumentNullException(nameof(console)); | ||||
|             _style = color; | ||||
|             _decoration = decoration; | ||||
|         } | ||||
|  | ||||
|         [SuppressMessage("Design", "CA1065:Do not raise exceptions in unexpected locations")] | ||||
|         [SuppressMessage("Performance", "CA1821:Remove empty Finalizers")] | ||||
|         ~StyleScope() | ||||
|         ~DecorationScope() | ||||
|         { | ||||
|             throw new InvalidOperationException("Style scope was not disposed."); | ||||
|             throw new InvalidOperationException("Decoration scope was not disposed."); | ||||
|         } | ||||
|  | ||||
|         public void Dispose() | ||||
|         { | ||||
|             GC.SuppressFinalize(this); | ||||
|             _console.Style = _style; | ||||
|             _console.Decoration = _decoration; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										29
									
								
								src/Spectre.Console/Internal/Extensions/StyleExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/Spectre.Console/Internal/Extensions/StyleExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static class StyleExtensions | ||||
|     { | ||||
|         public static Style Combine(this Style style, IEnumerable<Style> source) | ||||
|         { | ||||
|             if (style is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(style)); | ||||
|             } | ||||
|  | ||||
|             if (source is null) | ||||
|             { | ||||
|                 return style; | ||||
|             } | ||||
|  | ||||
|             var current = style; | ||||
|             foreach (var item in source) | ||||
|             { | ||||
|                 current = current.Combine(item); | ||||
|             } | ||||
|  | ||||
|             return current; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -44,7 +44,7 @@ namespace Spectre.Console.Internal | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public Styles Style { get; set; } | ||||
|         public Decoration Decoration { get; set; } | ||||
|  | ||||
|         public Color Foreground | ||||
|         { | ||||
|   | ||||
| @@ -1,34 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
|  | ||||
| namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static class StyleTable | ||||
|     { | ||||
|         private static readonly Dictionary<string, Styles?> _styles; | ||||
|  | ||||
|         [SuppressMessage("Performance", "CA1810:Initialize reference type static fields inline")] | ||||
|         static StyleTable() | ||||
|         { | ||||
|             _styles = new Dictionary<string, Styles?>(StringComparer.OrdinalIgnoreCase) | ||||
|             { | ||||
|                 { "bold", Styles.Bold }, | ||||
|                 { "dim", Styles.Dim }, | ||||
|                 { "italic", Styles.Italic }, | ||||
|                 { "underline", Styles.Underline }, | ||||
|                 { "invert", Styles.Invert }, | ||||
|                 { "conceal", Styles.Conceal }, | ||||
|                 { "slowblink", Styles.SlowBlink }, | ||||
|                 { "rapidblink", Styles.RapidBlink }, | ||||
|                 { "strikethrough", Styles.Strikethrough }, | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         public static Styles? GetStyle(string name) | ||||
|         { | ||||
|             _styles.TryGetValue(name, out var style); | ||||
|             return style; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -5,14 +5,14 @@ namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static class MarkupParser | ||||
|     { | ||||
|         public static Text Parse(string text, Appearance appearance = null) | ||||
|         public static Text Parse(string text, Style style = null) | ||||
|         { | ||||
|             appearance ??= Appearance.Plain; | ||||
|             style ??= Style.Plain; | ||||
|  | ||||
|             var result = new Text(string.Empty); | ||||
|             using var tokenizer = new MarkupTokenizer(text); | ||||
|  | ||||
|             var stack = new Stack<Appearance>(); | ||||
|             var stack = new Stack<Style>(); | ||||
|  | ||||
|             while (tokenizer.MoveNext()) | ||||
|             { | ||||
| @@ -20,8 +20,8 @@ namespace Spectre.Console.Internal | ||||
|  | ||||
|                 if (token.Kind == MarkupTokenKind.Open) | ||||
|                 { | ||||
|                     var (style, foreground, background) = MarkupStyleParser.Parse(token.Value); | ||||
|                     stack.Push(new Appearance(foreground, background, style)); | ||||
|                     var parsedStyle = StyleParser.Parse(token.Value); | ||||
|                     stack.Push(parsedStyle); | ||||
|                 } | ||||
|                 else if (token.Kind == MarkupTokenKind.Close) | ||||
|                 { | ||||
| @@ -35,8 +35,8 @@ namespace Spectre.Console.Internal | ||||
|                 else if (token.Kind == MarkupTokenKind.Text) | ||||
|                 { | ||||
|                     // Get the effecive style. | ||||
|                     var style = appearance.Combine(stack); | ||||
|                     result.Append(token.Value, style); | ||||
|                     var effectiveStyle = style.Combine(stack); | ||||
|                     result.Append(token.Value, effectiveStyle); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|   | ||||
| @@ -1,65 +0,0 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static class MarkupStyleParser | ||||
|     { | ||||
|         public static (Styles? Style, Color? Foreground, Color? Background) Parse(string text) | ||||
|         { | ||||
|             var effectiveStyle = (Styles?)null; | ||||
|             var effectiveForeground = (Color?)null; | ||||
|             var effectiveBackground = (Color?)null; | ||||
|  | ||||
|             var parts = text.Split(new[] { ' ' }); | ||||
|             var foreground = true; | ||||
|             foreach (var part in parts) | ||||
|             { | ||||
|                 if (part.Equals("on", StringComparison.OrdinalIgnoreCase)) | ||||
|                 { | ||||
|                     foreground = false; | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 var style = StyleTable.GetStyle(part); | ||||
|                 if (style != null) | ||||
|                 { | ||||
|                     if (effectiveStyle == null) | ||||
|                     { | ||||
|                         effectiveStyle = Styles.None; | ||||
|                     } | ||||
|  | ||||
|                     effectiveStyle |= style.Value; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     var color = ColorTable.GetColor(part); | ||||
|                     if (color == null) | ||||
|                     { | ||||
|                         throw new InvalidOperationException("Could not find color.."); | ||||
|                     } | ||||
|  | ||||
|                     if (foreground) | ||||
|                     { | ||||
|                         if (effectiveForeground != null) | ||||
|                         { | ||||
|                             throw new InvalidOperationException("A foreground has already been set."); | ||||
|                         } | ||||
|  | ||||
|                         effectiveForeground = color; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         if (effectiveBackground != null) | ||||
|                         { | ||||
|                             throw new InvalidOperationException("A background has already been set."); | ||||
|                         } | ||||
|  | ||||
|                         effectiveBackground = color; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return (effectiveStyle, effectiveForeground, effectiveBackground); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										104
									
								
								src/Spectre.Console/Internal/Text/StyleParser.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								src/Spectre.Console/Internal/Text/StyleParser.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console.Internal | ||||
| { | ||||
|     internal static class StyleParser | ||||
|     { | ||||
|         public static Style Parse(string text) | ||||
|         { | ||||
|             var style = Parse(text, out var error); | ||||
|             if (error != null) | ||||
|             { | ||||
|                 throw new InvalidOperationException(error); | ||||
|             } | ||||
|  | ||||
|             return style; | ||||
|         } | ||||
|  | ||||
|         public static bool TryParse(string text, out Style style) | ||||
|         { | ||||
|             style = Parse(text, out var error); | ||||
|             if (error != null) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         private static Style Parse(string text, out string error) | ||||
|         { | ||||
|             var effectiveDecoration = (Decoration?)null; | ||||
|             var effectiveForeground = (Color?)null; | ||||
|             var effectiveBackground = (Color?)null; | ||||
|  | ||||
|             var parts = text.Split(new[] { ' ' }); | ||||
|             var foreground = true; | ||||
|             foreach (var part in parts) | ||||
|             { | ||||
|                 if (part.Equals("default", StringComparison.OrdinalIgnoreCase)) | ||||
|                 { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 if (part.Equals("on", StringComparison.OrdinalIgnoreCase)) | ||||
|                 { | ||||
|                     foreground = false; | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 var decoration = DecorationTable.GetDecoration(part); | ||||
|                 if (decoration != null) | ||||
|                 { | ||||
|                     if (effectiveDecoration == null) | ||||
|                     { | ||||
|                         effectiveDecoration = Decoration.None; | ||||
|                     } | ||||
|  | ||||
|                     effectiveDecoration |= decoration.Value; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     var color = ColorTable.GetColor(part); | ||||
|                     if (color == null) | ||||
|                     { | ||||
|                         if (!foreground) | ||||
|                         { | ||||
|                             error = $"Could not find color '{part}'."; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             error = $"Could not find color or style '{part}'."; | ||||
|                         } | ||||
|  | ||||
|                         return null; | ||||
|                     } | ||||
|  | ||||
|                     if (foreground) | ||||
|                     { | ||||
|                         if (effectiveForeground != null) | ||||
|                         { | ||||
|                             error = "A foreground color has already been set."; | ||||
|                             return null; | ||||
|                         } | ||||
|  | ||||
|                         effectiveForeground = color; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         if (effectiveBackground != null) | ||||
|                         { | ||||
|                             error = "A background color has already been set."; | ||||
|                             return null; | ||||
|                         } | ||||
|  | ||||
|                         effectiveBackground = color; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             error = null; | ||||
|             return new Style(effectiveForeground, effectiveBackground, effectiveDecoration); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										134
									
								
								src/Spectre.Console/Style.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								src/Spectre.Console/Style.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| using System; | ||||
| using Spectre.Console.Internal; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents color and text decoration. | ||||
|     /// </summary> | ||||
|     public sealed class Style : IEquatable<Style> | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the foreground color. | ||||
|         /// </summary> | ||||
|         public Color Foreground { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the background color. | ||||
|         /// </summary> | ||||
|         public Color Background { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the text decoration. | ||||
|         /// </summary> | ||||
|         public Decoration Decoration { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets an <see cref="Style"/> with the | ||||
|         /// default colors and without text decoration. | ||||
|         /// </summary> | ||||
|         public static Style Plain { get; } = new Style(); | ||||
|  | ||||
|         private Style() | ||||
|             : this(null, null, null) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Style"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="foreground">The foreground color.</param> | ||||
|         /// <param name="background">The background color.</param> | ||||
|         /// <param name="decoration">The text decoration.</param> | ||||
|         public Style(Color? foreground = null, Color? background = null, Decoration? decoration = null) | ||||
|         { | ||||
|             Foreground = foreground ?? Color.Default; | ||||
|             Background = background ?? Color.Default; | ||||
|             Decoration = decoration ?? Decoration.None; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Converts the string representation of a style to its <see cref="Style"/> equivalent. | ||||
|         /// </summary> | ||||
|         /// <param name="text">A string containing a style to parse.</param> | ||||
|         /// <returns>A <see cref="Style"/> equivalent of the text contained in <paramref name="text"/>.</returns> | ||||
|         public static Style Parse(string text) | ||||
|         { | ||||
|             return StyleParser.Parse(text); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Converts the string representation of a style to its <see cref="Style"/> equivalent. | ||||
|         /// A return value indicates whether the operation succeeded. | ||||
|         /// </summary> | ||||
|         /// <param name="text">A string containing a style to parse.</param> | ||||
|         /// <param name="result"> | ||||
|         /// When this method returns, contains the <see cref="Style"/> equivalent of the text contained in <paramref name="text"/>, | ||||
|         /// if the conversion succeeded, or <c>null</c> if the conversion failed. | ||||
|         /// </param> | ||||
|         /// <returns><c>true</c> if s was converted successfully; otherwise, <c>false</c>.</returns> | ||||
|         public static bool TryParse(string text, out Style result) | ||||
|         { | ||||
|             return StyleParser.TryParse(text, out result); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Combines this style with another one. | ||||
|         /// </summary> | ||||
|         /// <param name="other">The item to combine with this.</param> | ||||
|         /// <returns>A new style representing a combination of this and the other one.</returns> | ||||
|         public Style Combine(Style other) | ||||
|         { | ||||
|             if (other is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(other)); | ||||
|             } | ||||
|  | ||||
|             var foreground = Foreground; | ||||
|             if (!other.Foreground.IsDefault) | ||||
|             { | ||||
|                 foreground = other.Foreground; | ||||
|             } | ||||
|  | ||||
|             var background = Background; | ||||
|             if (!other.Background.IsDefault) | ||||
|             { | ||||
|                 background = other.Background; | ||||
|             } | ||||
|  | ||||
|             return new Style(foreground, background, Decoration | other.Decoration); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override int GetHashCode() | ||||
|         { | ||||
|             unchecked | ||||
|             { | ||||
|                 var hash = (int)2166136261; | ||||
|                 hash = (hash * 16777619) ^ Foreground.GetHashCode(); | ||||
|                 hash = (hash * 16777619) ^ Background.GetHashCode(); | ||||
|                 hash = (hash * 16777619) ^ Decoration.GetHashCode(); | ||||
|                 return hash; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public override bool Equals(object obj) | ||||
|         { | ||||
|             return Equals(obj as Style); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool Equals(Style other) | ||||
|         { | ||||
|             if (other == null) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             return Foreground.Equals(other.Foreground) && | ||||
|                 Background.Equals(other.Background) && | ||||
|                 Decoration == other.Decoration; | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user