diff --git a/src/Spectre.Console.Tests/Unit/TextTests.cs b/src/Spectre.Console.Tests/Unit/TextTests.cs
index ca1c495..da30d54 100644
--- a/src/Spectre.Console.Tests/Unit/TextTests.cs
+++ b/src/Spectre.Console.Tests/Unit/TextTests.cs
@@ -48,26 +48,14 @@ namespace Spectre.Console.Tests.Unit
.ShouldBe("Hello World");
}
- [Fact]
- public void Should_Write_Line_Breaks()
+ [Theory]
+ [InlineData("Hello\n\nWorld\n\n")]
+ [InlineData("Hello\r\n\r\nWorld\r\n\r\n")]
+ public void Should_Write_Line_Breaks(string input)
{
// 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");
- }
-
- [Fact]
- public void Should_Write_Line_Breaks_At_End()
- {
- // Given
- var fixture = new PlainConsole(width: 5);
- var text = new Text("Hello\n\nWorld\n\n");
+ var text = new Text(input);
// When
fixture.Render(text);
diff --git a/src/Spectre.Console/Composition/Segment.cs b/src/Spectre.Console/Composition/Segment.cs
index e270105..c9a02e0 100644
--- a/src/Spectre.Console/Composition/Segment.cs
+++ b/src/Spectre.Console/Composition/Segment.cs
@@ -39,7 +39,7 @@ namespace Spectre.Console.Composition
///
/// Gets a segment representing a line break.
///
- public static Segment LineBreak { get; } = new Segment("\n", Style.Plain, true);
+ public static Segment LineBreak { get; } = new Segment(Environment.NewLine, Style.Plain, true);
///
/// Gets an empty segment.
@@ -95,7 +95,7 @@ namespace Spectre.Console.Composition
/// A new segment without any trailing line endings.
public Segment StripLineEndings()
{
- return new Segment(Text.TrimEnd('\n'), Style);
+ return new Segment(Text.TrimEnd('\n').TrimEnd('\r'), Style);
}
///
diff --git a/src/Spectre.Console/Composition/Widgets/Panel.cs b/src/Spectre.Console/Composition/Widgets/Panel.cs
index a53445f..175bd2f 100644
--- a/src/Spectre.Console/Composition/Widgets/Panel.cs
+++ b/src/Spectre.Console/Composition/Widgets/Panel.cs
@@ -80,7 +80,7 @@ namespace Spectre.Console
new Segment(border.GetPart(BorderPart.HeaderTopLeft)),
new Segment(border.GetPart(BorderPart.HeaderTop, panelWidth)),
new Segment(border.GetPart(BorderPart.HeaderTopRight)),
- new Segment("\n"),
+ Segment.LineBreak,
};
// Render the child.
@@ -118,14 +118,14 @@ namespace Spectre.Console
}
result.Add(new Segment(border.GetPart(BorderPart.CellRight)));
- result.Add(new Segment("\n"));
+ result.Add(Segment.LineBreak);
}
// 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"));
+ result.Add(Segment.LineBreak);
return result;
}
diff --git a/src/Spectre.Console/Composition/Widgets/Text.cs b/src/Spectre.Console/Composition/Widgets/Text.cs
index 93d0828..afc5b2c 100644
--- a/src/Spectre.Console/Composition/Widgets/Text.cs
+++ b/src/Spectre.Console/Composition/Widgets/Text.cs
@@ -92,7 +92,7 @@ namespace Spectre.Console
var justification = context.Justification ?? Alignment;
foreach (var (_, _, last, line) in lines.Enumerate())
{
- var length = line.Sum(l => l.CellLength(context.Encoding));
+ var length = line.Sum(l => l.StripLineEndings().CellLength(context.Encoding));
if (length < maxWidth)
{
// Justify right side
diff --git a/src/Spectre.Console/Internal/Text/Cell.cs b/src/Spectre.Console/Internal/Text/Cell.cs
index aeec84d..89ef993 100644
--- a/src/Spectre.Console/Internal/Text/Cell.cs
+++ b/src/Spectre.Console/Internal/Text/Cell.cs
@@ -70,6 +70,11 @@ namespace Spectre.Console.Internal
public static int GetCellLength(Encoding encoding, char rune)
{
+ if (rune == '\r' || rune == '\n')
+ {
+ return 0;
+ }
+
// Is it represented by a single byte?
// In that case we don't have to calculate the
// actual cell width.