From 6549436356cc88237b56f31d66a361528645e383 Mon Sep 17 00:00:00 2001 From: Patrik Svensson Date: Mon, 10 May 2021 23:20:35 +0200 Subject: [PATCH] Fix line break regression In commit d1d94cd, we accidentally introduced a regression since conhost requires all line breaks to be `\r\n`. --- .../Extensions/StringExtensions.cs | 3 +- .../Expectations/Segment.Split.verified.txt | 43 --------------- .../Segment.Split_Linebreak.verified.txt | 45 ---------------- .../Unit/SegmentTests.cs | 53 ++++++++++++++++--- src/Spectre.Console/Cli/Internal/Composer.cs | 2 +- .../Cli/Internal/HelpWriter.cs | 12 ++--- .../AnsiConsoleExtensions.Markup.cs | 4 +- .../Extensions/AnsiConsoleExtensions.cs | 4 +- .../Extensions/StringExtensions.cs | 11 ++++ .../Internal/Backends/Ansi/AnsiBuilder.cs | 2 +- src/Spectre.Console/Rendering/Segment.cs | 2 +- .../Renderers/FallbackStatusRenderer.cs | 2 +- 12 files changed, 73 insertions(+), 110 deletions(-) delete mode 100644 src/Spectre.Console.Tests/Expectations/Segment.Split.verified.txt delete mode 100644 src/Spectre.Console.Tests/Expectations/Segment.Split_Linebreak.verified.txt diff --git a/src/Spectre.Console.Testing/Extensions/StringExtensions.cs b/src/Spectre.Console.Testing/Extensions/StringExtensions.cs index 6eec20f..5f12b72 100644 --- a/src/Spectre.Console.Testing/Extensions/StringExtensions.cs +++ b/src/Spectre.Console.Testing/Extensions/StringExtensions.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Text.RegularExpressions; namespace Spectre.Console.Testing { @@ -21,7 +20,7 @@ namespace Spectre.Console.Testing } var result = new List(); - foreach (var line in value.Split(new[] { '\n' })) + foreach (var line in value.NormalizeLineEndings().Split(new[] { '\n' })) { result.Add(line.TrimEnd()); } diff --git a/src/Spectre.Console.Tests/Expectations/Segment.Split.verified.txt b/src/Spectre.Console.Tests/Expectations/Segment.Split.verified.txt deleted file mode 100644 index 7fb65eb..0000000 --- a/src/Spectre.Console.Tests/Expectations/Segment.Split.verified.txt +++ /dev/null @@ -1,43 +0,0 @@ -[ - [ - { - Text: Foo, - Style: { - Foreground: {}, - Background: {} - } - }, - { - Text: Bar, - Style: { - Foreground: {}, - Background: {} - } - } - ], - [ - { - Text: Baz, - Style: { - Foreground: {}, - Background: {} - } - }, - { - Text: Qux, - Style: { - Foreground: {}, - Background: {} - } - } - ], - [ - { - Text: Corgi, - Style: { - Foreground: {}, - Background: {} - } - } - ] -] \ No newline at end of file diff --git a/src/Spectre.Console.Tests/Expectations/Segment.Split_Linebreak.verified.txt b/src/Spectre.Console.Tests/Expectations/Segment.Split_Linebreak.verified.txt deleted file mode 100644 index 626d3e6..0000000 --- a/src/Spectre.Console.Tests/Expectations/Segment.Split_Linebreak.verified.txt +++ /dev/null @@ -1,45 +0,0 @@ -[ - [ - { - Text: Foo, - Style: { - Foreground: {}, - Background: {} - } - } - ], - [ - { - Text: Bar, - Style: { - Foreground: {}, - Background: {} - } - } - ], - [ - { - Text: Baz, - Style: { - Foreground: {}, - Background: {} - } - }, - { - Text: Qux, - Style: { - Foreground: {}, - Background: {} - } - } - ], - [ - { - Text: Corgi, - Style: { - Foreground: {}, - Background: {} - } - } - ] -] \ No newline at end of file diff --git a/src/Spectre.Console.Tests/Unit/SegmentTests.cs b/src/Spectre.Console.Tests/Unit/SegmentTests.cs index cc66575..554e738 100644 --- a/src/Spectre.Console.Tests/Unit/SegmentTests.cs +++ b/src/Spectre.Console.Tests/Unit/SegmentTests.cs @@ -55,8 +55,7 @@ namespace Spectre.Console.Tests.Unit public sealed class TheSplitLinesMethod { [Fact] - [Expectation("Segment", "Split")] - public Task Should_Split_Segment() + public void Should_Split_Segment() { // Given, When var lines = Segment.SplitLines( @@ -84,12 +83,41 @@ namespace Spectre.Console.Tests.Unit lines[2].Count.ShouldBe(1); lines[2][0].Text.ShouldBe("Corgi"); - return Verifier.Verify(lines); } [Fact] - [Expectation("Segment", "Split_Linebreak")] - public Task Should_Split_Segments_With_Linebreak_In_Text() + public void Should_Split_Segment_With_Windows_LineBreak() + { + // Given, When + var lines = Segment.SplitLines( + new[] + { + new Segment("Foo"), + new Segment("Bar"), + new Segment("\r\n"), + new Segment("Baz"), + new Segment("Qux"), + new Segment("\r\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() { // Given, Given var lines = Segment.SplitLines( @@ -103,7 +131,20 @@ namespace Spectre.Console.Tests.Unit }); // Then - return Verifier.Verify(lines); + 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"); } } } diff --git a/src/Spectre.Console/Cli/Internal/Composer.cs b/src/Spectre.Console/Cli/Internal/Composer.cs index 962c1a1..abdb3a3 100644 --- a/src/Spectre.Console/Cli/Internal/Composer.cs +++ b/src/Spectre.Console/Cli/Internal/Composer.cs @@ -71,7 +71,7 @@ namespace Spectre.Console.Cli { for (var i = 0; i < count; i++) { - _content.Append('\n'); + _content.Append(Environment.NewLine); } return this; diff --git a/src/Spectre.Console/Cli/Internal/HelpWriter.cs b/src/Spectre.Console/Cli/Internal/HelpWriter.cs index 573e5b1..927a1e8 100644 --- a/src/Spectre.Console/Cli/Internal/HelpWriter.cs +++ b/src/Spectre.Console/Cli/Internal/HelpWriter.cs @@ -230,9 +230,9 @@ namespace Spectre.Console.Cli var result = new List { - new Markup("\n"), + new Markup(Environment.NewLine), new Markup("[yellow]ARGUMENTS:[/]"), - new Markup("\n"), + new Markup(Environment.NewLine), }; var grid = new Grid(); @@ -269,9 +269,9 @@ namespace Spectre.Console.Cli var result = new List { - new Markup("\n"), + new Markup(Environment.NewLine), new Markup("[yellow]OPTIONS:[/]"), - new Markup("\n"), + new Markup(Environment.NewLine), }; var grid = new Grid(); @@ -346,9 +346,9 @@ namespace Spectre.Console.Cli var result = new List { - new Markup("\n"), + new Markup(Environment.NewLine), new Markup("[yellow]COMMANDS:[/]"), - new Markup("\n"), + new Markup(Environment.NewLine), }; var grid = new Grid(); diff --git a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Markup.cs b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Markup.cs index 5e9000d..1f2f8a9 100644 --- a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Markup.cs +++ b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.Markup.cs @@ -59,7 +59,7 @@ namespace Spectre.Console /// The value to write. public static void MarkupLine(this IAnsiConsole console, string value) { - Markup(console, value + "\n"); + Markup(console, value + Environment.NewLine); } /// @@ -71,7 +71,7 @@ namespace Spectre.Console /// An array of objects to write. public static void MarkupLine(this IAnsiConsole console, IFormatProvider provider, string format, params object[] args) { - Markup(console, provider, format + "\n", args); + Markup(console, provider, format + Environment.NewLine, args); } } } \ No newline at end of file diff --git a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.cs b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.cs index 0f7c1be..b91b813 100644 --- a/src/Spectre.Console/Extensions/AnsiConsoleExtensions.cs +++ b/src/Spectre.Console/Extensions/AnsiConsoleExtensions.cs @@ -73,7 +73,7 @@ namespace Spectre.Console throw new ArgumentNullException(nameof(console)); } - console.Write(new Text("\n", Style.Plain)); + console.Write(new Text(Environment.NewLine, Style.Plain)); } /// @@ -104,7 +104,7 @@ namespace Spectre.Console throw new ArgumentNullException(nameof(text)); } - console.Write(text + "\n", style); + console.Write(text + Environment.NewLine, style); } } } diff --git a/src/Spectre.Console/Extensions/StringExtensions.cs b/src/Spectre.Console/Extensions/StringExtensions.cs index 4a08881..d7db267 100644 --- a/src/Spectre.Console/Extensions/StringExtensions.cs +++ b/src/Spectre.Console/Extensions/StringExtensions.cs @@ -11,6 +11,11 @@ namespace Spectre.Console /// public static class StringExtensions { + // Cache whether or not internally normalized line endings + // already are normalized. No reason to do yet another replace if it is. + private static readonly bool _alreadyNormalized + = Environment.NewLine.Equals("\n", StringComparison.OrdinalIgnoreCase); + /// /// Escapes text so that it won’t be interpreted as markup. /// @@ -86,6 +91,12 @@ namespace Spectre.Console { text = text?.ReplaceExact("\r\n", "\n"); text ??= string.Empty; + + if (native && !_alreadyNormalized) + { + text = text.ReplaceExact("\n", Environment.NewLine); + } + return text; } diff --git a/src/Spectre.Console/Internal/Backends/Ansi/AnsiBuilder.cs b/src/Spectre.Console/Internal/Backends/Ansi/AnsiBuilder.cs index ef8267a..e30923a 100644 --- a/src/Spectre.Console/Internal/Backends/Ansi/AnsiBuilder.cs +++ b/src/Spectre.Console/Internal/Backends/Ansi/AnsiBuilder.cs @@ -36,7 +36,7 @@ namespace Spectre.Console if (!last) { - builder.Append('\n'); + builder.Append(Environment.NewLine); } } } diff --git a/src/Spectre.Console/Rendering/Segment.cs b/src/Spectre.Console/Rendering/Segment.cs index 1984f8a..ad2fb63 100644 --- a/src/Spectre.Console/Rendering/Segment.cs +++ b/src/Spectre.Console/Rendering/Segment.cs @@ -44,7 +44,7 @@ namespace Spectre.Console.Rendering /// /// Gets a segment representing a line break. /// - public static Segment LineBreak { get; } = new Segment("\n", Style.Plain, true, false); + public static Segment LineBreak { get; } = new Segment(Environment.NewLine, Style.Plain, true, false); /// /// Gets an empty segment. diff --git a/src/Spectre.Console/Widgets/Progress/Renderers/FallbackStatusRenderer.cs b/src/Spectre.Console/Widgets/Progress/Renderers/FallbackStatusRenderer.cs index f5a380b..4b10c10 100644 --- a/src/Spectre.Console/Widgets/Progress/Renderers/FallbackStatusRenderer.cs +++ b/src/Spectre.Console/Widgets/Progress/Renderers/FallbackStatusRenderer.cs @@ -29,7 +29,7 @@ namespace Spectre.Console if (_lastStatus != task.Description) { _lastStatus = task.Description; - _renderable = new Markup(task.Description + "\n"); + _renderable = new Markup(task.Description + Environment.NewLine); return; } }