From 482f9db7da24db1de041ab8cd33978b83fd869fb Mon Sep 17 00:00:00 2001 From: BDisp Date: Tue, 23 Mar 2021 17:53:02 +0000 Subject: [PATCH] Fixes #1148. TextFormatter.Format does not keep the end spaces on wrapped text. (#1149) * Fixes #1148. TextFormatter.Format does not keep the end spaces on wrapped text. * Added comments. * Changing keepEndSapces to preserveTrailingSpaces. --- Terminal.Gui/Core/TextFormatter.cs | 19 +++-- UnitTests/TextFormatterTests.cs | 120 +++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 7 deletions(-) diff --git a/Terminal.Gui/Core/TextFormatter.cs b/Terminal.Gui/Core/TextFormatter.cs index e8ce1dbb4..384544534 100644 --- a/Terminal.Gui/Core/TextFormatter.cs +++ b/Terminal.Gui/Core/TextFormatter.cs @@ -113,7 +113,7 @@ namespace Terminal.Gui { /// /// /// Upon a 'get' of this property, if the text needs to be formatted (if is true) - /// will be called internally. + /// will be called internally. /// /// public List Lines { @@ -203,6 +203,8 @@ namespace Terminal.Gui { /// /// The text to word wrap /// The width to contain the text to + /// If true, the wrapped text will keep the trailing spaces. + /// If false, the trailing spaces will be trimmed. /// Returns a list of word wrapped lines. /// /// @@ -212,7 +214,7 @@ namespace Terminal.Gui { /// This method strips Newline ('\n' and '\r\n') sequences before processing. /// /// - public static List WordWrap (ustring text, int width) + public static List WordWrap (ustring text, int width, bool preserveTrailingSpaces = false) { if (width < 0) { throw new ArgumentOutOfRangeException ("Width cannot be negative."); @@ -234,7 +236,7 @@ namespace Terminal.Gui { end = start + width; lines.Add (ustring.Make (runes.GetRange (start, end - start))); start = end; - if (runes[end] == ' ') { + if (runes [end] == ' ' && !preserveTrailingSpaces) { start++; } } @@ -321,6 +323,7 @@ namespace Terminal.Gui { /// The width to bound the text to for word wrapping and clipping. /// Specifies how the text will be aligned horizontally. /// If true, the text will be wrapped to new lines as need. If false, forces text to fit a single line. Line breaks are converted to spaces. The text will be clipped to width + /// If true and 'wordWrap' also true, the wrapped text will keep the trailing spaces. If false, the trailing spaces will be trimmed. /// A list of word wrapped lines. /// /// @@ -333,12 +336,14 @@ namespace Terminal.Gui { /// If width is int.MaxValue, the text will be formatted to the maximum width possible. /// /// - public static List Format (ustring text, int width, TextAlignment talign, bool wordWrap) + public static List Format (ustring text, int width, TextAlignment talign, bool wordWrap, bool preserveTrailingSpaces = false) { if (width < 0) { throw new ArgumentOutOfRangeException ("width cannot be negative"); } - + if (preserveTrailingSpaces && !wordWrap) { + throw new ArgumentException ("if 'preserveTrailingSpaces' is true, then 'wordWrap' must be true either."); + } List lineResult = new List (); if (ustring.IsNullOrEmpty (text) || width == 0) { @@ -358,7 +363,7 @@ namespace Terminal.Gui { for (int i = 0; i < runeCount; i++) { Rune c = runes [i]; if (c == '\n') { - var wrappedLines = WordWrap (ustring.Make (runes.GetRange (lp, i - lp)), width); + var wrappedLines = WordWrap (ustring.Make (runes.GetRange (lp, i - lp)), width, preserveTrailingSpaces); foreach (var line in wrappedLines) { lineResult.Add (ClipAndJustify (line, width, talign)); } @@ -368,7 +373,7 @@ namespace Terminal.Gui { lp = i + 1; } } - foreach (var line in WordWrap (ustring.Make (runes.GetRange (lp, runeCount - lp)), width)) { + foreach (var line in WordWrap (ustring.Make (runes.GetRange (lp, runeCount - lp)), width, preserveTrailingSpaces)) { lineResult.Add (ClipAndJustify (line, width, talign)); } diff --git a/UnitTests/TextFormatterTests.cs b/UnitTests/TextFormatterTests.cs index 0c8fa1978..582ba758e 100644 --- a/UnitTests/TextFormatterTests.cs +++ b/UnitTests/TextFormatterTests.cs @@ -2306,5 +2306,125 @@ namespace Terminal.Gui { c = new System.Text.Rune (127); Assert.Equal (1, c.Utf8SequenceLength); // non printable character } + + [Fact] + public void Format_WordWrap_Keep_End_Spaces () + { + ustring text = " A sentence has words. \n This is the second Line - 2. "; + + // With preserveTrailingSpaces = false by default. + var list1 = TextFormatter.Format (text, 4, TextAlignment.Left, true); + ustring wrappedText1 = ustring.Empty; + var idx = 0; + foreach (var txt in list1) { + wrappedText1 += txt; + switch (idx) { + case 0: + Assert.Equal (" A", txt); + break; + case 1: + Assert.Equal ("sent", txt); + break; + case 2: + Assert.Equal ("ence", txt); + break; + case 3: + Assert.Equal ("has", txt); + break; + case 4: + Assert.Equal ("word", txt); + break; + case 5: + Assert.Equal ("s. ", txt); + break; + case 6: + Assert.Equal (" Thi", txt); + break; + case 7: + Assert.Equal ("s is", txt); + break; + case 8: + Assert.Equal ("the", txt); + break; + case 9: + Assert.Equal ("seco", txt); + break; + case 10: + Assert.Equal ("nd", txt); + break; + case 11: + Assert.Equal ("Line", txt); + break; + case 12: + Assert.Equal ("- 2.", txt); + break; + } + idx++; + } + Assert.Equal (" Asentencehaswords. This isthesecondLine- 2.", wrappedText1); + + // With preserveTrailingSpaces = true. + var list2 = TextFormatter.Format (text, 4, TextAlignment.Left, true, true); + ustring wrappedText2 = ustring.Empty; + idx = 0; + foreach (var txt in list2) { + wrappedText2 += txt; + switch (idx) { + case 0: + Assert.Equal (" A", txt); + break; + case 1: + Assert.Equal (" sen", txt); + break; + case 2: + Assert.Equal ("tenc", txt); + break; + case 3: + Assert.Equal ("e", txt); + break; + case 4: + Assert.Equal (" has", txt); + break; + case 5: + Assert.Equal (" wor", txt); + break; + case 6: + Assert.Equal ("ds. ", txt); + break; + case 7: + Assert.Equal (" Thi", txt); + break; + case 8: + Assert.Equal ("s is", txt); + break; + case 9: + Assert.Equal (" the", txt); + break; + case 10: + Assert.Equal (" sec", txt); + break; + case 11: + Assert.Equal ("ond", txt); + break; + case 12: + Assert.Equal (" Lin", txt); + break; + case 13: + Assert.Equal ("e -", txt); + break; + case 14: + Assert.Equal (" 2. ", txt); + break; + } + idx++; + } + Assert.Equal (" A sentence has words. This is the second Line - 2. ", wrappedText2); + } + + [Fact] + public void Format_Throw_ArgumentException_With_WordWrap_As_False_And_Keep_End_Spaces_As_True () + { + Assert.Throws (() => TextFormatter.Format ("Some text", 4, TextAlignment.Left, false, true)); + } } } \ No newline at end of file