From 29799f493c5f30c782ecdfab1abdfb4624bd134b Mon Sep 17 00:00:00 2001 From: BDisp Date: Thu, 3 Oct 2024 15:50:09 +0100 Subject: [PATCH] Move necessary methods to the RuneCell class per https://github.com/gui-cs/Terminal.Gui/issues/3774#issuecomment-2391190526. --- .../Views/AutocompleteFilepathContext.cs | 2 +- Terminal.Gui/Views/TextField.cs | 10 +- Terminal.Gui/Views/TextView.cs | 217 +++++++++--------- UnitTests/Views/RuneCellTests.cs | 6 +- UnitTests/Views/TextViewTests.cs | 18 +- 5 files changed, 132 insertions(+), 121 deletions(-) diff --git a/Terminal.Gui/Views/AutocompleteFilepathContext.cs b/Terminal.Gui/Views/AutocompleteFilepathContext.cs index 96ce1dfae..a379f2001 100644 --- a/Terminal.Gui/Views/AutocompleteFilepathContext.cs +++ b/Terminal.Gui/Views/AutocompleteFilepathContext.cs @@ -30,7 +30,7 @@ internal class FilepathSuggestionGenerator : ISuggestionGenerator return Enumerable.Empty (); } - var path = TextModel.ToString (context.CurrentLine); + var path = RuneCell.ToString (context.CurrentLine); int last = path.LastIndexOfAny (FileDialog.Separators); if (string.IsNullOrWhiteSpace (path) || !Path.IsPathRooted (path)) diff --git a/Terminal.Gui/Views/TextField.cs b/Terminal.Gui/Views/TextField.cs index aa4322e2e..acbefdf9a 100644 --- a/Terminal.Gui/Views/TextField.cs +++ b/Terminal.Gui/Views/TextField.cs @@ -551,7 +551,7 @@ public class TextField : View ); _historyText.Add ( - new List> { TextModel.ToRuneCells (_text) }, + new List> { RuneCell.ToRuneCells (_text) }, new Point (_cursorPosition, 0), HistoryText.LineStatus.Replaced ); @@ -648,7 +648,7 @@ public class TextField : View } _historyText.Add ( - new List> { TextModel.ToRuneCells (_text) }, + new List> { RuneCell.ToRuneCells (_text) }, new Point (_cursorPosition, 0) ); @@ -702,7 +702,7 @@ public class TextField : View } _historyText.Add ( - new List> { TextModel.ToRuneCells (_text) }, + new List> { RuneCell.ToRuneCells (_text) }, new Point (_cursorPosition, 0) ); @@ -1390,7 +1390,7 @@ public class TextField : View return; } - Text = TextModel.ToString (obj?.Lines [obj.CursorPosition.Y]); + Text = RuneCell.ToString (obj?.Lines [obj.CursorPosition.Y]); CursorPosition = obj.CursorPosition.X; Adjust (); } @@ -1398,7 +1398,7 @@ public class TextField : View private void InsertText (Key a, bool usePreTextChangedCursorPos) { _historyText.Add ( - new List> { TextModel.ToRuneCells (_text) }, + new List> { RuneCell.ToRuneCells (_text) }, new Point (_cursorPosition, 0) ); diff --git a/Terminal.Gui/Views/TextView.cs b/Terminal.Gui/Views/TextView.cs index 5c4a82fd8..5223c210e 100644 --- a/Terminal.Gui/Views/TextView.cs +++ b/Terminal.Gui/Views/TextView.cs @@ -58,6 +58,109 @@ public class RuneCell : IEquatable return cells; } + + /// + /// Splits a string into a List that will contain a for each line. + /// + /// The string content. + /// The color scheme. + /// A for each line. + public static List> StringToLinesOfRuneCells (string content, ColorScheme? colorScheme = null) + { + List cells = content.EnumerateRunes () + .Select (x => new RuneCell { Rune = x, ColorScheme = colorScheme }) + .ToList (); + + return SplitNewLines (cells); + } + + /// Converts a generic collection into a string. + /// The enumerable cell to convert. + /// + public static string ToString (IEnumerable cells) + { + var str = string.Empty; + + foreach (RuneCell cell in cells) + { + str += cell.Rune.ToString (); + } + + return str; + } + + // Turns the string into cells, this does not split the contents on a newline if it is present. + internal static List StringToRuneCells (string str, ColorScheme? colorScheme = null) + { + List cells = new (); + + foreach (Rune rune in str.ToRunes ()) + { + cells.Add (new () { Rune = rune, ColorScheme = colorScheme }); + } + + return cells; + } + + internal static List ToRuneCells (IEnumerable runes, ColorScheme? colorScheme = null) + { + List cells = new (); + + foreach (Rune rune in runes) + { + cells.Add (new () { Rune = rune, ColorScheme = colorScheme }); + } + + return cells; + } + + private static List> SplitNewLines (List cells) + { + List> lines = new (); + int start = 0, i = 0; + var hasCR = false; + + // ASCII code 13 = Carriage Return. + // ASCII code 10 = Line Feed. + for (; i < cells.Count; i++) + { + if (cells [i].Rune.Value == 13) + { + hasCR = true; + + continue; + } + + if (cells [i].Rune.Value == 10) + { + if (i - start > 0) + { + lines.Add (cells.GetRange (start, hasCR ? i - 1 - start : i - start)); + } + else + { + lines.Add (StringToRuneCells (string.Empty)); + } + + start = i + 1; + hasCR = false; + } + } + + if (i - start >= 0) + { + lines.Add (cells.GetRange (start, i - start)); + } + + return lines; + } + + /// + /// Splits a rune cell list into a List that will contain a for each line. + /// + /// The cells list. + /// + public static List> ToRuneCells (List cells) { return SplitNewLines (cells); } } internal class TextModel @@ -157,7 +260,7 @@ internal class TextModel public void LoadRuneCells (List cells, ColorScheme? colorScheme) { - _lines = ToRuneCells (cells); + _lines = RuneCell.ToRuneCells (cells); SetColorSchemes (colorScheme); OnLinesLoaded (); } @@ -207,7 +310,7 @@ internal class TextModel public void LoadString (string content) { - _lines = StringToLinesOfRuneCells (content); + _lines = RuneCell.StringToLinesOfRuneCells (content); OnLinesLoaded (); } @@ -239,15 +342,7 @@ internal class TextModel } } - // Splits a string into a List that contains a List for each line - public static List> StringToLinesOfRuneCells (string content, ColorScheme? colorScheme = null) - { - List cells = content.EnumerateRunes () - .Select (x => new RuneCell { Rune = x, ColorScheme = colorScheme }) - .ToList (); - return SplitNewLines (cells); - } public override string ToString () { @@ -255,7 +350,7 @@ internal class TextModel for (var i = 0; i < _lines.Count; i++) { - sb.Append (ToString (_lines [i])); + sb.Append (RuneCell.ToString (_lines [i])); if (i + 1 < _lines.Count) { @@ -266,21 +361,6 @@ internal class TextModel return sb.ToString (); } - /// Converts a generic collection into a string. - /// The enumerable cell to convert. - /// - public static string ToString (IEnumerable cells) - { - var str = string.Empty; - - foreach (RuneCell cell in cells) - { - str += cell.Rune.ToString (); - } - - return str; - } - public (int col, int row)? WordBackward (int fromCol, int fromRow) { if (fromRow == 0 && fromCol == 0) @@ -873,7 +953,7 @@ internal class TextModel string GetText (List x) { - string txt = ToString (x); + string txt = RuneCell.ToString (x); if (!matchCase) { @@ -906,36 +986,10 @@ internal class TextModel return false; } - // Turns the string into cells, this does not split the - // contents on a newline if it is present. - internal static List StringToRuneCells (string str, ColorScheme? colorScheme = null) - { - List cells = new (); - - foreach (Rune rune in str.ToRunes ()) - { - cells.Add (new () { Rune = rune, ColorScheme = colorScheme }); - } - - return cells; - } - - internal static List ToRuneCells (IEnumerable runes, ColorScheme? colorScheme = null) - { - List cells = new (); - - foreach (Rune rune in runes) - { - cells.Add (new () { Rune = rune, ColorScheme = colorScheme }); - } - - return cells; - } - private void Append (List line) { var str = StringExtensions.ToString (line.ToArray ()); - _lines.Add (StringToRuneCells (str)); + _lines.Add (RuneCell.StringToRuneCells (str)); } private bool ApplyToFind ((Point current, bool found) foundPos) @@ -972,7 +1026,7 @@ internal class TextModel for (int i = start.Y; i < linesCount; i++) { List x = _lines [i]; - string txt = ToString (x); + string txt = RuneCell.ToString (x); if (!matchCase) { @@ -1012,7 +1066,7 @@ internal class TextModel for (int i = linesCount; i >= 0; i--) { List x = _lines [i]; - string txt = ToString (x); + string txt = RuneCell.ToString (x); if (!matchCase) { @@ -1175,7 +1229,7 @@ internal class TextModel private string ReplaceText (List source, string textToReplace, string matchText, int col) { - string origTxt = ToString (source); + string origTxt = RuneCell.ToString (source); (_, int len) = DisplaySize (source, 0, col, false); (_, int len2) = DisplaySize (source, col, col + matchText.Length, false); (_, int len3) = DisplaySize (source, col + matchText.Length, origTxt.GetRuneCount (), false); @@ -1206,49 +1260,6 @@ internal class TextModel } } - private static List> SplitNewLines (List cells) - { - List> lines = new (); - int start = 0, i = 0; - var hasCR = false; - - // ASCII code 13 = Carriage Return. - // ASCII code 10 = Line Feed. - for (; i < cells.Count; i++) - { - if (cells [i].Rune.Value == 13) - { - hasCR = true; - - continue; - } - - if (cells [i].Rune.Value == 10) - { - if (i - start > 0) - { - lines.Add (cells.GetRange (start, hasCR ? i - 1 - start : i - start)); - } - else - { - lines.Add (StringToRuneCells (string.Empty)); - } - - start = i + 1; - hasCR = false; - } - } - - if (i - start >= 0) - { - lines.Add (cells.GetRange (start, i - start)); - } - - return lines; - } - - private static List> ToRuneCells (List cells) { return SplitNewLines (cells); } - private enum RuneType { IsSymbol, @@ -1782,7 +1793,7 @@ internal class WordWrapManager List> wrappedLines = ToListRune ( TextFormatter.Format ( - TextModel.ToString (line), + RuneCell.ToString (line), width, Alignment.Start, true, @@ -2905,7 +2916,7 @@ public class TextView : View else { List currentLine = GetCurrentLine (); - SetClipboard (TextModel.ToString (currentLine)); + SetClipboard (RuneCell.ToString (currentLine)); _copyWithoutSelection = true; } @@ -4762,7 +4773,7 @@ public class TextView : View return; } - List> lines = TextModel.StringToLinesOfRuneCells (text); + List> lines = RuneCell.StringToLinesOfRuneCells (text); if (lines.Count == 0) { diff --git a/UnitTests/Views/RuneCellTests.cs b/UnitTests/Views/RuneCellTests.cs index 9b09b249d..ccbce08c9 100644 --- a/UnitTests/Views/RuneCellTests.cs +++ b/UnitTests/Views/RuneCellTests.cs @@ -218,10 +218,10 @@ ror "; List> text = new () { - TextModel.ToRuneCells ( + RuneCell.ToRuneCells ( "This is the first line.".ToRunes () ), - TextModel.ToRuneCells ( + RuneCell.ToRuneCells ( "This is the second line.".ToRunes () ) }; @@ -237,7 +237,7 @@ ror "; eventCount++; } - tv.Text = $"{TextModel.ToString (text [0])}\n{TextModel.ToString (text [1])}\n"; + tv.Text = $"{RuneCell.ToString (text [0])}\n{RuneCell.ToString (text [1])}\n"; Assert.False (tv.WordWrap); var top = new Toplevel (); top.Add (tv); diff --git a/UnitTests/Views/TextViewTests.cs b/UnitTests/Views/TextViewTests.cs index cdbde0448..84a0c931e 100644 --- a/UnitTests/Views/TextViewTests.cs +++ b/UnitTests/Views/TextViewTests.cs @@ -4717,7 +4717,7 @@ This is the second line. public void Internal_Tests () { var txt = "This is a text."; - List txtRunes = TextModel.StringToRuneCells (txt); + List txtRunes = RuneCell.StringToRuneCells (txt); Assert.Equal (txt.Length, txtRunes.Count); Assert.Equal ('T', txtRunes [0].Rune.Value); Assert.Equal ('h', txtRunes [1].Rune.Value); @@ -4757,8 +4757,8 @@ This is the second line. Assert.Equal (2, TextModel.CalculateLeftColumn (txtRunes, 0, 9, 8)); var tm = new TextModel (); - tm.AddLine (0, TextModel.StringToRuneCells ("This is first line.")); - tm.AddLine (1, TextModel.StringToRuneCells ("This is last line.")); + tm.AddLine (0, RuneCell.StringToRuneCells ("This is first line.")); + tm.AddLine (1, RuneCell.StringToRuneCells ("This is last line.")); Assert.Equal ((new Point (2, 0), true), tm.FindNextText ("is", out bool gaveFullTurn)); Assert.False (gaveFullTurn); Assert.Equal ((new Point (5, 0), true), tm.FindNextText ("is", out gaveFullTurn)); @@ -4782,14 +4782,14 @@ This is the second line. Assert.True (gaveFullTurn); Assert.Equal ((new Point (9, 1), true), tm.ReplaceAllText ("is", false, false, "really")); - Assert.Equal (TextModel.StringToRuneCells ("Threally really first line."), tm.GetLine (0)); - Assert.Equal (TextModel.StringToRuneCells ("Threally really last line."), tm.GetLine (1)); + Assert.Equal (RuneCell.StringToRuneCells ("Threally really first line."), tm.GetLine (0)); + Assert.Equal (RuneCell.StringToRuneCells ("Threally really last line."), tm.GetLine (1)); tm = new TextModel (); - tm.AddLine (0, TextModel.StringToRuneCells ("This is first line.")); - tm.AddLine (1, TextModel.StringToRuneCells ("This is last line.")); + tm.AddLine (0, RuneCell.StringToRuneCells ("This is first line.")); + tm.AddLine (1, RuneCell.StringToRuneCells ("This is last line.")); Assert.Equal ((new Point (5, 1), true), tm.ReplaceAllText ("is", false, true, "really")); - Assert.Equal (TextModel.StringToRuneCells ("This really first line."), tm.GetLine (0)); - Assert.Equal (TextModel.StringToRuneCells ("This really last line."), tm.GetLine (1)); + Assert.Equal (RuneCell.StringToRuneCells ("This really first line."), tm.GetLine (0)); + Assert.Equal (RuneCell.StringToRuneCells ("This really last line."), tm.GetLine (1)); } [Fact]