diff --git a/src/SharpMUTerm.Core/Session/WorldSession.cs b/src/SharpMUTerm.Core/Session/WorldSession.cs index 2135679..87f7a92 100644 --- a/src/SharpMUTerm.Core/Session/WorldSession.cs +++ b/src/SharpMUTerm.Core/Session/WorldSession.cs @@ -312,15 +312,22 @@ private void OnOutputReceived(object? sender, TelnetOutputEventArgs e) return; } + var emitted = false; foreach (var completed in _parser.Feed(e.Text)) { ProcessOutputLine(completed); + emitted = true; } var tail = _parser.Flush(); if (tail is not null) { ProcessOutputLine(tail); + emitted = true; + } + else if (!emitted) + { + ProcessOutputLine(StyledLine.Empty); } } diff --git a/tests/SharpMUTerm.Core.Tests/Session/WorldSessionTests.cs b/tests/SharpMUTerm.Core.Tests/Session/WorldSessionTests.cs index 8cffdaa..4efdc8f 100644 --- a/tests/SharpMUTerm.Core.Tests/Session/WorldSessionTests.cs +++ b/tests/SharpMUTerm.Core.Tests/Session/WorldSessionTests.cs @@ -34,6 +34,36 @@ public async Task OutputLine_IsAppendedToScrollbackAndRaisesEvent() await Assert.That(printed).IsNotNull(); } + [Test] + public async Task EmptyOutputLine_IsAppendedAsBlankLine() + { + var (session, telnet) = Create(World()); + await session.ConnectAsync(); + var before = session.Scrollback.Snapshot().Count; + + telnet.EmitLine(string.Empty); + + var after = session.Scrollback.Snapshot(); + await Assert.That(after.Count).IsEqualTo(before + 1); + await Assert.That(after[^1].IsEmpty).IsTrue(); + } + + [Test] + public async Task SameFrame_OutputPreservesAnEmptyMiddleLine() + { + var (session, telnet) = Create(World()); + await session.ConnectAsync(); + var before = session.Scrollback.Snapshot().Count; + + telnet.EmitLine("Line one\n\nThis line three, previous line was empty, this is valid output. It came from the same received frame."); + + var after = session.Scrollback.Snapshot(); + await Assert.That(after.Count).IsEqualTo(before + 3); + await Assert.That(after[before].Text).IsEqualTo("Line one"); + await Assert.That(after[before + 1].IsEmpty).IsTrue(); + await Assert.That(after[before + 2].Text).IsEqualTo("This line three, previous line was empty, this is valid output. It came from the same received frame."); + } + [Test] public async Task AnsiColor_InOutput_IsParsedIntoStyledSpans() {