Repository: ajalt/mordant (kotlin)

Issue:
`Terminal.print()` ignores new line feeds at the end of Strings
I'm trying to interface Mordant with an existing logging structure by implementing the `Appendable` interface and forwarding the methods to Mordant using the `Terminal.print()` method, however I'm noticing that new line feeds at the end of `CharSequences/Strings` are getting ignored. Somehow Mordant is stripping them.

**Sample code:**
```
class TerminalAppendable(private val terminal: Terminal): Appendable {

    override fun append(charSequence: CharSequence): Appendable {
        terminal.print(charSequence)
        return this
    }

    override fun append(charSequence: CharSequence, start: Int, end: Int): Appendable {
        terminal.print(charSequence.subSequence(start, end))
        return this
    }

    override fun append(char: Char): Appendable {
        terminal.print(char.toString())
        return this
    }
}
```

```
val appendable = TerminalAppendable(Terminal())
appendable.appendLine("Foo Bar")
appendable.appendLine("Lorem Ipsum")
// Result:   `Foo BarLorem Ipsum`
// Expected: `Foo Bar\nLorem Ipsum\n`

appendable.append("Foo Bar\n")
appendable.append("Lorem Ipsum\n")
// Result:   `Foo BarLorem Ipsum`
// Expected: `Foo Bar\nLorem Ipsum\n`

appendable.append("Foo\nBar\n")
appendable.append("Lorem\nIpsum\n")
// Result:   `Foo\nBarLorem\nIpsum`
// Expected: `Foo\nBar\nLorem\nIpsum\n`
```

Pull request:
Fixes #75

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6f85a06b5..4639aabe1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # Changelog
 
+## 2.0.0-beta8
+### Changed
+- Stop stripping trailing newline from text when using `Whitespace.PRE` [(#75)](https://github.com/ajalt/mordant/issues/75)
+
+
 ## 2.0.0-beta8
 ### Added
 - Implemented `hideInput` for prompts on native targets [(#63)](https://github.com/ajalt/mordant/issues/63)
diff --git a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/internal/Parsing.kt b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/internal/Parsing.kt
index fad79fb9b..1ccb4343f 100644
--- a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/internal/Parsing.kt
+++ b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/internal/Parsing.kt
@@ -78,7 +78,7 @@ private fun splitWords(chunk: Chunk): List<Chunk> {
 }
 
 /** Split a flat list of chunks into a list of lines, removing linebreak chunks */
-private fun splitLines(words: Iterable<Chunk>): List<Line> {
+private fun splitLines(words: List<Chunk>): List<Line> {
     val lines = mutableListOf<Line>()
     var line = mutableListOf<Span>()
 
@@ -92,6 +92,11 @@ private fun splitLines(words: Iterable<Chunk>): List<Line> {
     }
 
     if (line.isNotEmpty()) lines += Line(line)
+    words.lastOrNull()?.let {
+        if (it.text.endsWith("\n")) {
+            lines.add(Line(listOf(), endStyle = it.style))
+        }
+    }
 
     return lines
 }
diff --git a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/markdown/MarkdownRenderer.kt b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/markdown/MarkdownRenderer.kt
index 9665bca43..f62581fbd 100644
--- a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/markdown/MarkdownRenderer.kt
+++ b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/markdown/MarkdownRenderer.kt
@@ -287,9 +287,8 @@ internal class MarkdownRenderer(
             }
 
             MarkdownTokenTypes.EOL -> {
-                // Add an extra linebreak, since the first one will get folded away by foldLines.
                 // Parse the text rather than hard coding the return value to support NEL and LS.
-                Lines(listOf(EMPTY_LINE) + parseText(node.nodeText(), DEFAULT_STYLE).lines)
+                Lines(parseText(node.nodeText(), DEFAULT_STYLE).lines)
             }
 
             else -> error("Unexpected token when parsing inlines: $node; [${node.type}:'${node.nodeText().take(10)}'}]")


Test patch:
diff --git a/mordant/src/commonTest/kotlin/com/github/ajalt/mordant/widgets/TextTest.kt b/mordant/src/commonTest/kotlin/com/github/ajalt/mordant/widgets/TextTest.kt
index 2acc2c1b6..eafc24b5e 100644
--- a/mordant/src/commonTest/kotlin/com/github/ajalt/mordant/widgets/TextTest.kt
+++ b/mordant/src/commonTest/kotlin/com/github/ajalt/mordant/widgets/TextTest.kt
@@ -2,9 +2,7 @@ package com.github.ajalt.mordant.widgets
 
 import com.github.ajalt.colormath.model.Ansi256
 import com.github.ajalt.colormath.model.RGB
-import com.github.ajalt.mordant.internal.CSI
-import com.github.ajalt.mordant.internal.OSC
-import com.github.ajalt.mordant.internal.ST
+import com.github.ajalt.mordant.internal.*
 import com.github.ajalt.mordant.rendering.*
 import com.github.ajalt.mordant.rendering.OverflowWrap.BREAK_WORD
 import com.github.ajalt.mordant.rendering.OverflowWrap.NORMAL
@@ -19,6 +17,12 @@ import kotlin.test.Test
 
 
 class TextTest : RenderingTest() {
+    @Test
+    @JsName("trailing_line_break")
+    fun `trailing line break`() {
+        checkRender(Text("x\n"), "x\n", trimMargin = false)
+    }
+
     @Test
     @JsName("override_width")
     fun `override width`() = checkRender(Text("""