From 0a334281e5f7e3d7b2b3c07dddb0fb3ccfcdd95d Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Tue, 7 Jul 2020 15:18:25 -0600 Subject: [PATCH 1/7] merge --- demo.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 demo.txt diff --git a/demo.txt b/demo.txt new file mode 100644 index 000000000..b23c047cf --- /dev/null +++ b/demo.txt @@ -0,0 +1,2 @@ +Hello world. +This is a test of the Emergency Broadcast System. From c3395f41abf8b085f13d74b8aed3e438572d5500 Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Mon, 13 Jul 2020 17:48:41 -0700 Subject: [PATCH 2/7] fixed word wrapping to not strip spaces; ended up fixing other ww bugs too! --- Terminal.Gui/Core/TextFormatter.cs | 11 +++- UICatalog/Scenarios/TextFormatterDemo.cs | 65 ++++++++++++++++-------- UnitTests/TextFormatterTests.cs | 33 +++++------- 3 files changed, 65 insertions(+), 44 deletions(-) diff --git a/Terminal.Gui/Core/TextFormatter.cs b/Terminal.Gui/Core/TextFormatter.cs index 53db10452..724e84f41 100644 --- a/Terminal.Gui/Core/TextFormatter.cs +++ b/Terminal.Gui/Core/TextFormatter.cs @@ -162,6 +162,8 @@ namespace Terminal.Gui { runes.RemoveAt (i); runes.RemoveAt (i + 1); i++; + } else { + runes.RemoveAt (i); } break; } @@ -182,6 +184,8 @@ namespace Terminal.Gui { runes [i] = (Rune)' '; runes.RemoveAt (i + 1); i++; + } else { + runes [i] = (Rune)' '; } break; } @@ -223,12 +227,15 @@ namespace Terminal.Gui { end -= 1; if (end == start) end = start + width; - lines.Add (ustring.Make (runes.GetRange (start, end - start)).TrimSpace ()); + lines.Add (ustring.Make (runes.GetRange (start, end - start))); //.TrimStart ((rune) => rune == ' ')); start = end; + if (runes[end] == ' ') { + start++; + } } if (start < text.RuneCount) { - lines.Add (ustring.Make (runes.GetRange (start, runes.Count - start)).TrimSpace ()); + lines.Add (ustring.Make (runes.GetRange (start, runes.Count - start))); //.TrimStart ((rune) => rune == ' ')); } return lines; diff --git a/UICatalog/Scenarios/TextFormatterDemo.cs b/UICatalog/Scenarios/TextFormatterDemo.cs index 05f11f10e..1c733df99 100644 --- a/UICatalog/Scenarios/TextFormatterDemo.cs +++ b/UICatalog/Scenarios/TextFormatterDemo.cs @@ -1,40 +1,60 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using Terminal.Gui; +using Rune = System.Rune; namespace UICatalog { [ScenarioMetadata (Name: "TextFormatter Demo", Description: "Demos and tests the TextFormatter class.")] [ScenarioCategory ("Text")] [ScenarioCategory ("POC")] class TextFormatterDemo : Scenario { - public override void Init (Toplevel top, ColorScheme colorScheme) - { - Application.Init (); + //public override void Init (Toplevel top, ColorScheme colorScheme) + //{ + // Application.Init (); - Top = top; - if (Top == null) { - Top = Application.Top; - } - Win = null; - } + // Top = top; + // if (Top == null) { + // Top = Application.Top; + // } + // Win = null; + //} public override void Setup () { - Top.Text = "Press CTRL-Q to Quit. This is the Text for the TopLevel View. TextAlignment.Centered was specified. It is intentionally very long to illustrate word wrap.\n" + - "<-- There is a new line here to show a hard line break. You should see this text bleed underneath the subviews, which start at Y = 3."; - Top.TextAlignment = TextAlignment.Centered; - Top.ColorScheme = Colors.Base; + //Top.Text = "Press CTRL-Q to Quit. This is the Text for the TopLevel View. TextAlignment.Centered was specified. It is intentionally very long to illustrate word wrap.\n" + + // "<-- There is a new line here to show a hard line break. You should see this text bleed underneath the subviews, which start at Y = 3."; + //Top.TextAlignment = TextAlignment.Centered; + //Top.ColorScheme = Colors.Base; + + // Make Win smaller so sizing the window horizontally will make the + // labels shrink to zero-width + Win.X = 10; + Win.Width = Dim.Fill (10); string text = "Hello world, how are you today? Pretty neat!\nSecond line\n\nFourth Line."; string unicode = "Τὴ γλῶσσα μοῦ ἔδωσαν ἑλληνικὴ\nτὸ σπίτι φτωχικὸ στὶς ἀμμουδιὲς τοῦ Ὁμήρου.\nΜονάχη ἔγνοια ἡ γλῶσσα μου στὶς ἀμμουδιὲς τοῦ Ὁμήρου."; + Label blockText = new Label () { ColorScheme = Colors.TopLevel, X = 0, Y = 3, Height = 7, Width = Dim.Fill (0) }; + + var block = new StringBuilder (); + block.AppendLine (" _/ "); + block.AppendLine (" _/_/_/ _/ _/ _/_/_/ _/_/_/"); + block.AppendLine (" _/ _/ _/ _/ _/ _/ _/_/ "); + block.AppendLine (" _/ _/ _/ _/ _/ _/ _/_/ "); + block.AppendLine (" _/_/_/ _/_/_/ _/ _/ _/_/_/ _/_/_/ "); + block.AppendLine (" _/ "); + block.AppendLine ("_ /_/ "); + blockText.Text = block.ToString (); + Win.Add (blockText); + var unicodeCheckBox = new CheckBox ("Unicode", Top.HotKeySpecifier == (Rune)' ') { X = 0, - Y = 3, + Y = Pos.Bottom (blockText) + 1, }; - Top.Add (unicodeCheckBox); + Win.Add (unicodeCheckBox); var alignments = Enum.GetValues (typeof (Terminal.Gui.TextAlignment)).Cast ().ToList (); var singleLines = new Label [alignments.Count]; @@ -48,22 +68,22 @@ namespace UICatalog { } var label = new Label ($"Demonstrating single-line (should clip):") { Y = Pos.Bottom (unicodeCheckBox) + 1 }; - Top.Add (label); + Win.Add (label); foreach (var alignment in alignments) { label = new Label ($"{alignment}:") { Y = Pos.Bottom (label) }; - Top.Add (label); + Win.Add (label); singleLines [(int)alignment].Y = Pos.Bottom (label); - Top.Add (singleLines [(int)alignment]); + Win.Add (singleLines [(int)alignment]); label = singleLines [(int)alignment]; } label = new Label ($"Demonstrating multi-line and word wrap:") { Y = Pos.Bottom (label) }; - Top.Add (label); + Win.Add (label); foreach (var alignment in alignments) { label = new Label ($"{alignment}:") { Y = Pos.Bottom (label) }; - Top.Add (label); + Win.Add (label); multipleLines [(int)alignment].Y = Pos.Bottom (label); - Top.Add (multipleLines [(int)alignment]); + Win.Add (multipleLines [(int)alignment]); label = multipleLines [(int)alignment]; } @@ -75,4 +95,5 @@ namespace UICatalog { }; } } -} \ No newline at end of file +} + diff --git a/UnitTests/TextFormatterTests.cs b/UnitTests/TextFormatterTests.cs index ed795c5b0..1b20ff744 100644 --- a/UnitTests/TextFormatterTests.cs +++ b/UnitTests/TextFormatterTests.cs @@ -1674,16 +1674,12 @@ namespace Terminal.Gui { //Assert.True (wrappedLines.Count == ); Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount)); Assert.Equal ("A", wrappedLines [0].ToString ()); - // BUGBUG: WordWrap breaks down with small widths. It should not - // the following line should be "sen"... - Assert.Equal ("se", wrappedLines [1].ToString ()); - Assert.Equal ("nte", wrappedLines [2].ToString ()); - Assert.Equal ("nce", wrappedLines [3].ToString ()); - Assert.Equal ("ha", wrappedLines [4].ToString ()); - Assert.Equal ("s", wrappedLines [5].ToString ()); - Assert.Equal ("wo", wrappedLines [6].ToString ()); - Assert.Equal ("rds", wrappedLines [7].ToString ()); - Assert.Equal (".", wrappedLines [^1].ToString ()); + Assert.Equal ("sen", wrappedLines [1].ToString ()); + Assert.Equal ("ten", wrappedLines [2].ToString ()); + Assert.Equal ("ce", wrappedLines [3].ToString ()); + Assert.Equal ("has", wrappedLines [4].ToString ()); + Assert.Equal ("wor", wrappedLines [5].ToString ()); + Assert.Equal ("ds.", wrappedLines [6].ToString ()); maxWidth = 2; expectedClippedWidth = 2; @@ -1691,10 +1687,10 @@ namespace Terminal.Gui { //Assert.True (wrappedLines.Count == ); Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount)); Assert.Equal ("A", wrappedLines [0].ToString ()); - Assert.Equal ("s", wrappedLines [1].ToString ()); - Assert.Equal ("en", wrappedLines [2].ToString ()); - Assert.Equal ("te", wrappedLines [3].ToString ()); - Assert.Equal (".", wrappedLines [^1].ToString ()); + Assert.Equal ("se", wrappedLines [1].ToString ()); + Assert.Equal ("nt", wrappedLines [2].ToString ()); + Assert.Equal ("en", wrappedLines [3].ToString ()); + Assert.Equal ("s.", wrappedLines [^1].ToString ()); maxWidth = 1; expectedClippedWidth = 1; @@ -1702,12 +1698,9 @@ namespace Terminal.Gui { //Assert.True (wrappedLines.Count == ); Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount)); Assert.Equal ("A", wrappedLines [0].ToString ()); - // BUGBUG: WordWrap breaks down with a width of one. It should not - // provide blank lines like it does. - Assert.Equal ("", wrappedLines [1].ToString ()); - Assert.Equal ("s", wrappedLines [2].ToString ()); - Assert.Equal ("e", wrappedLines [3].ToString ()); - Assert.Equal ("n", wrappedLines [4].ToString ()); + Assert.Equal ("s", wrappedLines [1].ToString ()); + Assert.Equal ("e", wrappedLines [2].ToString ()); + Assert.Equal ("n", wrappedLines [3].ToString ()); Assert.Equal (".", wrappedLines [^1].ToString ()); } From 856287d6ddd841e8b7ccb6fc2e89d1930581f3f4 Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Mon, 13 Jul 2020 17:53:21 -0700 Subject: [PATCH 3/7] removed comments --- Terminal.Gui/Core/TextFormatter.cs | 9 +++------ UICatalog/Scenarios/TextFormatterDemo.cs | 12 +----------- demo.txt | 2 -- 3 files changed, 4 insertions(+), 19 deletions(-) delete mode 100644 demo.txt diff --git a/Terminal.Gui/Core/TextFormatter.cs b/Terminal.Gui/Core/TextFormatter.cs index 724e84f41..6a8512272 100644 --- a/Terminal.Gui/Core/TextFormatter.cs +++ b/Terminal.Gui/Core/TextFormatter.cs @@ -227,7 +227,7 @@ namespace Terminal.Gui { end -= 1; if (end == start) end = start + width; - lines.Add (ustring.Make (runes.GetRange (start, end - start))); //.TrimStart ((rune) => rune == ' ')); + lines.Add (ustring.Make (runes.GetRange (start, end - start))); start = end; if (runes[end] == ' ') { start++; @@ -235,7 +235,7 @@ namespace Terminal.Gui { } if (start < text.RuneCount) { - lines.Add (ustring.Make (runes.GetRange (start, runes.Count - start))); //.TrimStart ((rune) => rune == ' ')); + lines.Add (ustring.Make (runes.GetRange (start, runes.Count - start))); } return lines; @@ -286,15 +286,13 @@ namespace Terminal.Gui { return text; } - // TODO: Use ustring - var words = text.Split (ustring.Make (' '));// whitespace, StringSplitOptions.RemoveEmptyEntries); + var words = text.Split (ustring.Make (' ')); int textCount = words.Sum (arg => arg.RuneCount); var spaces = words.Length > 1 ? (width - textCount) / (words.Length - 1) : 0; var extras = words.Length > 1 ? (width - textCount) % words.Length : 0; var s = new System.Text.StringBuilder (); - //s.Append ($"tc={textCount} sp={spaces},x={extras} - "); for (int w = 0; w < words.Length; w++) { var x = words [w]; s.Append (x); @@ -302,7 +300,6 @@ namespace Terminal.Gui { for (int i = 0; i < spaces; i++) s.Append (spaceChar); if (extras > 0) { - //s.Append ('_'); extras--; } } diff --git a/UICatalog/Scenarios/TextFormatterDemo.cs b/UICatalog/Scenarios/TextFormatterDemo.cs index 1c733df99..f665f8b4a 100644 --- a/UICatalog/Scenarios/TextFormatterDemo.cs +++ b/UICatalog/Scenarios/TextFormatterDemo.cs @@ -10,19 +10,9 @@ namespace UICatalog { [ScenarioCategory ("Text")] [ScenarioCategory ("POC")] class TextFormatterDemo : Scenario { - //public override void Init (Toplevel top, ColorScheme colorScheme) - //{ - // Application.Init (); - - // Top = top; - // if (Top == null) { - // Top = Application.Top; - // } - // Win = null; - //} - public override void Setup () { + // TODO: Move this to another Scenario that specifically tests `Views` that have no subviews. //Top.Text = "Press CTRL-Q to Quit. This is the Text for the TopLevel View. TextAlignment.Centered was specified. It is intentionally very long to illustrate word wrap.\n" + // "<-- There is a new line here to show a hard line break. You should see this text bleed underneath the subviews, which start at Y = 3."; //Top.TextAlignment = TextAlignment.Centered; diff --git a/demo.txt b/demo.txt deleted file mode 100644 index b23c047cf..000000000 --- a/demo.txt +++ /dev/null @@ -1,2 +0,0 @@ -Hello world. -This is a test of the Emergency Broadcast System. From 9d088f87ec8a8b97e10f6c623642f4e4ec753b3c Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Mon, 13 Jul 2020 22:03:17 -0700 Subject: [PATCH 4/7] fixed a wide-unicode bug --- Terminal.Gui/Core/TextFormatter.cs | 6 +- UICatalog/Scenarios/TextFormatterDemo.cs | 23 +-- UnitTests/TextFormatterTests.cs | 209 ++++++++++++++++++++++- 3 files changed, 217 insertions(+), 21 deletions(-) diff --git a/Terminal.Gui/Core/TextFormatter.cs b/Terminal.Gui/Core/TextFormatter.cs index 6a8512272..1cfaf62d7 100644 --- a/Terminal.Gui/Core/TextFormatter.cs +++ b/Terminal.Gui/Core/TextFormatter.cs @@ -196,7 +196,7 @@ namespace Terminal.Gui { /// /// Formats the provided text to fit within the width provided using word wrapping. /// - /// The text to word warp + /// The text to word wrap /// The width to contrain the text to /// Returns a list of word wrapped lines. /// @@ -204,7 +204,7 @@ namespace Terminal.Gui { /// This method does not do any justification. /// /// - /// Newlines ('\n' and '\r\n') sequences are honored, adding the appropriate lines to the output. + /// This method strips Newline ('\n' and '\r\n') sequences before processing. /// /// public static List WordWrap (ustring text, int width) @@ -351,7 +351,7 @@ namespace Terminal.Gui { int runeCount = runes.Count; int lp = 0; for (int i = 0; i < runeCount; i++) { - Rune c = text [i]; + Rune c = runes [i]; if (c == '\n') { var wrappedLines = WordWrap (ustring.Make (runes.GetRange (lp, i - lp)), width); foreach (var line in wrappedLines) { diff --git a/UICatalog/Scenarios/TextFormatterDemo.cs b/UICatalog/Scenarios/TextFormatterDemo.cs index f665f8b4a..dcadba536 100644 --- a/UICatalog/Scenarios/TextFormatterDemo.cs +++ b/UICatalog/Scenarios/TextFormatterDemo.cs @@ -1,4 +1,5 @@ -using System; +using NStack; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -26,17 +27,19 @@ namespace UICatalog { string text = "Hello world, how are you today? Pretty neat!\nSecond line\n\nFourth Line."; string unicode = "Τὴ γλῶσσα μοῦ ἔδωσαν ἑλληνικὴ\nτὸ σπίτι φτωχικὸ στὶς ἀμμουδιὲς τοῦ Ὁμήρου.\nΜονάχη ἔγνοια ἡ γλῶσσα μου στὶς ἀμμουδιὲς τοῦ Ὁμήρου."; - Label blockText = new Label () { ColorScheme = Colors.TopLevel, X = 0, Y = 3, Height = 7, Width = Dim.Fill (0) }; + Label blockText = new Label () { ColorScheme = Colors.TopLevel, X = 0, Y = 0, Height = 10, Width = Dim.Fill (0) }; var block = new StringBuilder (); - block.AppendLine (" _/ "); - block.AppendLine (" _/_/_/ _/ _/ _/_/_/ _/_/_/"); - block.AppendLine (" _/ _/ _/ _/ _/ _/ _/_/ "); - block.AppendLine (" _/ _/ _/ _/ _/ _/ _/_/ "); - block.AppendLine (" _/_/_/ _/_/_/ _/ _/ _/_/_/ _/_/_/ "); - block.AppendLine (" _/ "); - block.AppendLine ("_ /_/ "); - blockText.Text = block.ToString (); + block.AppendLine (" ▄████ █ ██ ██▓ ▄████▄ ██████ "); + block.AppendLine (" ██▒ ▀█▒ ██ ▓██▒▓██▒ ▒██▀ ▀█ ▒██ ▒ "); + block.AppendLine ("▒██░▄▄▄░▓██ ▒██░▒██▒ ▒▓█ ▄ ░ ▓██▄ "); + block.AppendLine ("░▓█ ██▓▓▓█ ░██░░██░ ▒▓▓▄ ▄██▒ ▒ ██▒"); + block.AppendLine ("░▒▓███▀▒▒▒█████▓ ░██░ ██▓ ▒ ▓███▀ ░▒██████▒▒"); + block.AppendLine (" ░▒ ▒ ░▒▓▒ ▒ ▒ ░▓ ▒▓▒ ░ ░▒ ▒ ░▒ ▒▓▒ ▒ ░"); + block.AppendLine (" ░ ░ ░░▒░ ░ ░ ▒ ░ ░▒ ░ ▒ ░ ░▒ ░ ░"); + block.AppendLine ("░ ░ ░ ░░░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ "); + block.AppendLine (" ░ ░ ░ ░ ░ ░ ░ "); + block.AppendLine (" ░ ░ "); blockText.Text = ustring.Make (block.ToString ()); // .Replace(" ", "\u00A0"); // \u00A0 is 'non-breaking space Win.Add (blockText); var unicodeCheckBox = new CheckBox ("Unicode", Top.HotKeySpecifier == (Rune)' ') { diff --git a/UnitTests/TextFormatterTests.cs b/UnitTests/TextFormatterTests.cs index 1b20ff744..17200127b 100644 --- a/UnitTests/TextFormatterTests.cs +++ b/UnitTests/TextFormatterTests.cs @@ -1559,6 +1559,84 @@ namespace Terminal.Gui { Assert.Equal ("ำ", wrappedLines [^1].ToString ()); } + [Fact] + public void WordWrap_Unicode_LineWithNonBreakingSpace () + { + var text = ustring.Empty; + int width = 0; + List wrappedLines; + + text = "This\u00A0is\u00A0a\u00A0sentence."; + width = text.RuneCount; + wrappedLines = TextFormatter.WordWrap (text, width); + Assert.True (wrappedLines.Count == 1); + + width = text.RuneCount - 1; + wrappedLines = TextFormatter.WordWrap (text, width); + Assert.Equal (2, wrappedLines.Count); + Assert.Equal (ustring.Make (text.ToRunes () [0..(text.RuneCount - 1)]).ToString (), wrappedLines [0].ToString ()); + Assert.Equal (".", wrappedLines [1].ToString ()); + + width = text.RuneCount - 2; + wrappedLines = TextFormatter.WordWrap (text, width); + Assert.Equal (2, wrappedLines.Count); + Assert.Equal (ustring.Make (text.ToRunes () [0..(text.RuneCount - 2)]).ToString (), wrappedLines [0].ToString ()); + + width = text.RuneCount - 5; + wrappedLines = TextFormatter.WordWrap (text, width); + Assert.Equal (2, wrappedLines.Count); + + width = (int)Math.Ceiling ((double)(text.RuneCount / 2F)); + wrappedLines = TextFormatter.WordWrap (text, width); + Assert.Equal (2, wrappedLines.Count); + Assert.Equal ("This\u00A0is\u00A0a\u00A0", wrappedLines [0].ToString ()); + Assert.Equal ("sentence.", wrappedLines [1].ToString ()); + + width = (int)Math.Ceiling ((double)(text.RuneCount / 3F)); + wrappedLines = TextFormatter.WordWrap (text, width); + Assert.Equal (3, wrappedLines.Count); + Assert.Equal ("This\u00A0is", wrappedLines [0].ToString ()); + Assert.Equal ("\u00a0a\u00a0sent", wrappedLines [1].ToString ()); + Assert.Equal ("ence.", wrappedLines [2].ToString ()); + + width = (int)Math.Ceiling ((double)(text.RuneCount / 4F)); + wrappedLines = TextFormatter.WordWrap (text, width); + Assert.Equal (4, wrappedLines.Count); + + width = (int)Math.Ceiling ((double)text.RuneCount / text.RuneCount); + wrappedLines = TextFormatter.WordWrap (text, width); + Assert.Equal (text.RuneCount, wrappedLines.Count); + Assert.Equal ("T", wrappedLines [0].ToString ()); + Assert.Equal ("h", wrappedLines [1].ToString ()); + Assert.Equal ("i", wrappedLines [2].ToString ()); + Assert.Equal (".", wrappedLines [^1].ToString ()); + } + + [Fact] + public void WordWrap_Unicode_2LinesWithNonBreakingSpace () + { + var text = ustring.Empty; + int width = 0; + List wrappedLines; + + text = "This\u00A0is\n\u00A0a\u00A0sentence."; + width = text.RuneCount; + wrappedLines = TextFormatter.WordWrap (text, width); + Assert.True (wrappedLines.Count == 1); + + width = text.RuneCount - 1; + wrappedLines = TextFormatter.WordWrap (text, width); +#pragma warning disable xUnit2013 // Do not use equality check to check for collection size. + Assert.Equal (1, wrappedLines.Count); +#pragma warning restore xUnit2013 // Do not use equality check to check for collection size. + Assert.Equal ("This\u00A0is\u00A0a\u00A0sentence.", wrappedLines [0].ToString ()); + + text = "\u00A0\u00A0\u00A0\u00A0\u00A0test\u00A0sentence."; + width = text.RuneCount; + wrappedLines = TextFormatter.WordWrap (text, width); + Assert.True (wrappedLines.Count == 1); + } + [Fact] public void WordWrap_NoNewLines () { @@ -1658,6 +1736,87 @@ namespace Terminal.Gui { Assert.Equal ("(пÑивеÑ) has words.", wrappedLines [1].ToString ()); } + /// + /// WordWrap strips CRLF + /// + [Fact] + public void WordWrap_WithNewLines () + { + var text = ustring.Empty; + int maxWidth = 0; + int expectedClippedWidth = 0; + + List wrappedLines; + + text = "A sentence has words.\nA paragraph has lines."; + maxWidth = text.RuneCount; + expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); + wrappedLines = TextFormatter.WordWrap (text, maxWidth); +#pragma warning disable xUnit2013 // Do not use equality check to check for collection size. + Assert.Equal (1, wrappedLines.Count); +#pragma warning restore xUnit2013 // Do not use equality check to check for collection size. + Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount)); + Assert.Equal ("A sentence has words.A paragraph has lines.", wrappedLines [0].ToString ()); + + maxWidth = text.RuneCount - 1; + expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); + wrappedLines = TextFormatter.WordWrap (text, maxWidth); +#pragma warning disable xUnit2013 // Do not use equality check to check for collection size. + Assert.Equal (1, wrappedLines.Count); +#pragma warning restore xUnit2013 // Do not use equality check to check for collection size. + Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount)); + Assert.Equal ("A sentence has words.A paragraph has lines.", wrappedLines [0].ToString ()); + + maxWidth = text.RuneCount - "words.".Length; + expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); + wrappedLines = TextFormatter.WordWrap (text, maxWidth); + Assert.Equal (2, wrappedLines.Count); + Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount)); + Assert.Equal ("A sentence has words.A paragraph has", wrappedLines [0].ToString ()); + Assert.Equal ("lines.", wrappedLines [1].ToString ()); + + // Unicode + text = "A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has Линии."; + maxWidth = text.RuneCount; + expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); + wrappedLines = TextFormatter.WordWrap (text, maxWidth); + Assert.True (wrappedLines.Count == 1); + Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount)); + Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has Линии.", wrappedLines [0].ToString ()); + + maxWidth = text.RuneCount - 1; + expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); + wrappedLines = TextFormatter.WordWrap (text, maxWidth); + Assert.Equal (2, wrappedLines.Count); + Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount)); + Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has", wrappedLines [0].ToString ()); + Assert.Equal ("Линии.", wrappedLines [1].ToString ()); + + maxWidth = text.RuneCount - "words.".Length; + expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); + wrappedLines = TextFormatter.WordWrap (text, maxWidth); + Assert.Equal (2, wrappedLines.Count); + Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount)); + Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has", wrappedLines [0].ToString ()); + Assert.Equal ("Линии.", wrappedLines [1].ToString ()); + + maxWidth = text.RuneCount - "s words.".Length; + expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); + wrappedLines = TextFormatter.WordWrap (text, maxWidth); + Assert.Equal (2, wrappedLines.Count); + Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount)); + Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт", wrappedLines [0].ToString ()); + Assert.Equal ("has Линии.", wrappedLines [1].ToString ()); + + maxWidth = text.RuneCount - "веÑ) has words.".Length; + expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); + wrappedLines = TextFormatter.WordWrap (text, maxWidth); + Assert.Equal (2, wrappedLines.Count); + Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount)); + Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode", wrappedLines [0].ToString ()); + Assert.Equal ("Пункт has Линии.", wrappedLines [1].ToString ()); + } + [Fact] public void WordWrap_Narrow () { @@ -2001,13 +2160,13 @@ namespace Terminal.Gui { // Unicode // Even # of chars // 0123456789 - text = "пÑРвРÑ"; + text = "\u2660пÑРвРÑ"; maxWidth = text.RuneCount - 1; expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap); Assert.True (list.Count == 2); - Assert.Equal ("пÑРвÐ", list [0]); + Assert.Equal ("\u2660пÑРвÐ", list [0]); Assert.Equal ("Ñ", list [1]); // no clip @@ -2015,24 +2174,24 @@ namespace Terminal.Gui { expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap); Assert.True (list.Count == 1); - Assert.Equal ("пÑРвРÑ", list [0]); + Assert.Equal ("\u2660пÑРвРÑ", list [0]); maxWidth = text.RuneCount + 1; expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap); Assert.True (list.Count == 1); - Assert.Equal ("пÑРвРÑ", list [0]); + Assert.Equal ("\u2660пÑРвРÑ", list [0]); // Unicode // Odd # of chars // 0123456789 - text = "Ð ÑРвРÑ"; + text = "\u2660 ÑРвРÑ"; maxWidth = text.RuneCount - 1; expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap); Assert.True (list.Count == 2); - Assert.Equal ("Ð ÑРвÐ", list [0]); + Assert.Equal ("\u2660 ÑРвÐ", list [0]); Assert.Equal ("Ñ", list [1]); // no clip @@ -2040,14 +2199,48 @@ namespace Terminal.Gui { expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap); Assert.True (list.Count == 1); - Assert.Equal ("Ð ÑРвРÑ", list [0]); + Assert.Equal ("\u2660 ÑРвРÑ", list [0]); maxWidth = text.RuneCount + 1; expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap); Assert.True (list.Count == 1); - Assert.Equal ("Ð ÑРвРÑ", list [0]); + Assert.Equal ("\u2660 ÑРвРÑ", list [0]); + } + [Fact] + public void Reformat_Unicode_Wrap_Spaces_NewLines () + { + var text = ustring.Empty; + var list = new List (); + var maxWidth = 0; + var expectedClippedWidth = 0; + var wrap = true; + + // Unicode + text = "\u2460\u2461\u2462\n\u2460\u2461\u2462\u2463\u2464"; + + maxWidth = text.RuneCount - 1; + expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); + list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap); + Assert.Equal (2, list.Count); + Assert.Equal ("\u2460\u2461\u2462", list [0]); + Assert.Equal ("\u2460\u2461\u2462\u2463\u2464", list [1]); + + // no clip + maxWidth = text.RuneCount + 0; + expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); + list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap); + Assert.Equal (2, list.Count); + Assert.Equal ("\u2460\u2461\u2462", list [0]); + Assert.Equal ("\u2460\u2461\u2462\u2463\u2464", list [1]); + + maxWidth = text.RuneCount + 1; + expectedClippedWidth = Math.Min (text.RuneCount, maxWidth); + list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap); + Assert.Equal (2, list.Count); + Assert.Equal ("\u2460\u2461\u2462", list [0]); + Assert.Equal ("\u2460\u2461\u2462\u2463\u2464", list [1]); } } } \ No newline at end of file From 2ac385ec81b0d23aa4070b8553f0df2259a0dec8 Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Mon, 13 Jul 2020 22:06:46 -0700 Subject: [PATCH 5/7] formatting error and a little fun --- UICatalog/Scenarios/TextFormatterDemo.cs | 3 ++- UICatalog/UICatalog.cs | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/UICatalog/Scenarios/TextFormatterDemo.cs b/UICatalog/Scenarios/TextFormatterDemo.cs index dcadba536..ee76c871a 100644 --- a/UICatalog/Scenarios/TextFormatterDemo.cs +++ b/UICatalog/Scenarios/TextFormatterDemo.cs @@ -39,7 +39,8 @@ namespace UICatalog { block.AppendLine (" ░ ░ ░░▒░ ░ ░ ▒ ░ ░▒ ░ ▒ ░ ░▒ ░ ░"); block.AppendLine ("░ ░ ░ ░░░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ "); block.AppendLine (" ░ ░ ░ ░ ░ ░ ░ "); - block.AppendLine (" ░ ░ "); blockText.Text = ustring.Make (block.ToString ()); // .Replace(" ", "\u00A0"); // \u00A0 is 'non-breaking space + block.AppendLine (" ░ ░ "); + blockText.Text = ustring.Make (block.ToString ()); // .Replace(" ", "\u00A0"); // \u00A0 is 'non-breaking space Win.Add (blockText); var unicodeCheckBox = new CheckBox ("Unicode", Top.HotKeySpecifier == (Rune)' ') { diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 8015a1a6b..37537549f 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -133,6 +133,17 @@ namespace UICatalog { StringBuilder aboutMessage = new StringBuilder (); aboutMessage.AppendLine ("UI Catalog is a comprehensive sample library for Terminal.Gui"); aboutMessage.AppendLine (""); + aboutMessage.AppendLine (" ▄████ █ ██ ██▓ ▄████▄ ██████ "); + aboutMessage.AppendLine (" ██▒ ▀█▒ ██ ▓██▒▓██▒ ▒██▀ ▀█ ▒██ ▒ "); + aboutMessage.AppendLine ("▒██░▄▄▄░▓██ ▒██░▒██▒ ▒▓█ ▄ ░ ▓██▄ "); + aboutMessage.AppendLine ("░▓█ ██▓▓▓█ ░██░░██░ ▒▓▓▄ ▄██▒ ▒ ██▒"); + aboutMessage.AppendLine ("░▒▓███▀▒▒▒█████▓ ░██░ ██▓ ▒ ▓███▀ ░▒██████▒▒"); + aboutMessage.AppendLine (" ░▒ ▒ ░▒▓▒ ▒ ▒ ░▓ ▒▓▒ ░ ░▒ ▒ ░▒ ▒▓▒ ▒ ░"); + aboutMessage.AppendLine (" ░ ░ ░░▒░ ░ ░ ▒ ░ ░▒ ░ ▒ ░ ░▒ ░ ░"); + aboutMessage.AppendLine ("░ ░ ░ ░░░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ "); + aboutMessage.AppendLine (" ░ ░ ░ ░ ░ ░ ░ "); + aboutMessage.AppendLine (" ░ ░ "); + aboutMessage.AppendLine (""); aboutMessage.AppendLine ($"Version: {typeof (UICatalogApp).Assembly.GetName ().Version}"); aboutMessage.AppendLine ($"Using Terminal.Gui Version: {typeof (Terminal.Gui.Application).Assembly.GetName ().Version}"); aboutMessage.AppendLine (""); From 677ead51dbe2db6b5f018c1e0b4bc17bf2281d3d Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Mon, 13 Jul 2020 22:10:30 -0700 Subject: [PATCH 6/7] about box as anotehr test --- UICatalog/UICatalog.cs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 37537549f..8f995c441 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -132,17 +132,12 @@ namespace UICatalog { StringBuilder aboutMessage = new StringBuilder (); aboutMessage.AppendLine ("UI Catalog is a comprehensive sample library for Terminal.Gui"); - aboutMessage.AppendLine (""); - aboutMessage.AppendLine (" ▄████ █ ██ ██▓ ▄████▄ ██████ "); - aboutMessage.AppendLine (" ██▒ ▀█▒ ██ ▓██▒▓██▒ ▒██▀ ▀█ ▒██ ▒ "); - aboutMessage.AppendLine ("▒██░▄▄▄░▓██ ▒██░▒██▒ ▒▓█ ▄ ░ ▓██▄ "); - aboutMessage.AppendLine ("░▓█ ██▓▓▓█ ░██░░██░ ▒▓▓▄ ▄██▒ ▒ ██▒"); - aboutMessage.AppendLine ("░▒▓███▀▒▒▒█████▓ ░██░ ██▓ ▒ ▓███▀ ░▒██████▒▒"); - aboutMessage.AppendLine (" ░▒ ▒ ░▒▓▒ ▒ ▒ ░▓ ▒▓▒ ░ ░▒ ▒ ░▒ ▒▓▒ ▒ ░"); - aboutMessage.AppendLine (" ░ ░ ░░▒░ ░ ░ ▒ ░ ░▒ ░ ▒ ░ ░▒ ░ ░"); - aboutMessage.AppendLine ("░ ░ ░ ░░░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ "); - aboutMessage.AppendLine (" ░ ░ ░ ░ ░ ░ ░ "); - aboutMessage.AppendLine (" ░ ░ "); + aboutMessage.AppendLine (@" _ "); + aboutMessage.AppendLine (@" __ _ _ _(_) ___ ___ "); + aboutMessage.AppendLine (@" / _` | | | | | / __/ __|"); + aboutMessage.AppendLine (@" | (_| | |_| | || (__\__ \"); + aboutMessage.AppendLine (@" \__, |\__,_|_(_)___|___/"); + aboutMessage.AppendLine (@" |___/ "); aboutMessage.AppendLine (""); aboutMessage.AppendLine ($"Version: {typeof (UICatalogApp).Assembly.GetName ().Version}"); aboutMessage.AppendLine ($"Using Terminal.Gui Version: {typeof (Terminal.Gui.Application).Assembly.GetName ().Version}"); From 6f840d7d2120755c719fb8601c79506b7d851398 Mon Sep 17 00:00:00 2001 From: Charlie Kindel Date: Mon, 13 Jul 2020 22:11:19 -0700 Subject: [PATCH 7/7] spacing --- UICatalog/UICatalog.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 8f995c441..2bb3866c0 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -132,12 +132,12 @@ namespace UICatalog { StringBuilder aboutMessage = new StringBuilder (); aboutMessage.AppendLine ("UI Catalog is a comprehensive sample library for Terminal.Gui"); - aboutMessage.AppendLine (@" _ "); - aboutMessage.AppendLine (@" __ _ _ _(_) ___ ___ "); - aboutMessage.AppendLine (@" / _` | | | | | / __/ __|"); - aboutMessage.AppendLine (@" | (_| | |_| | || (__\__ \"); - aboutMessage.AppendLine (@" \__, |\__,_|_(_)___|___/"); - aboutMessage.AppendLine (@" |___/ "); + aboutMessage.AppendLine (@" _ "); + aboutMessage.AppendLine (@" __ _ _ _(_) ___ ___ "); + aboutMessage.AppendLine (@" / _` | | | | | / __/ __|"); + aboutMessage.AppendLine (@"| (_| | |_| | || (__\__ \"); + aboutMessage.AppendLine (@" \__, |\__,_|_(_)___|___/"); + aboutMessage.AppendLine (@" |___/ "); aboutMessage.AppendLine (""); aboutMessage.AppendLine ($"Version: {typeof (UICatalogApp).Assembly.GetName ().Version}"); aboutMessage.AppendLine ($"Using Terminal.Gui Version: {typeof (Terminal.Gui.Application).Assembly.GetName ().Version}");