using TinyTUI.Text; var measurer = new TerminalTextMeasurer(); AssertEqual(5, measurer.GetWidth("\t\e[31mη•Œ\e[0m"), "tab and ansi width"); AssertEqual(2, measurer.GetWidth("πŸ‡¨"), "single regional indicator width"); AssertEqual(2, measurer.GetWidth("πŸ‡¨πŸ‡³"), "regional indicator pair width"); AssertEqual(2, measurer.GetWidth("πŸ‘¨β€πŸ’»"), "zwj emoji width"); AssertEqual(2, measurer.GetWidth("⚑️"), "variation selector emoji width"); var strictTabSlice = measurer.Slice("out 192M\t.pi/skill-tests/results-ha", 0, 10, strict: true); AssertEqual("out 192M", strictTabSlice.Text, "strict tab slice text"); AssertEqual(8, strictTabSlice.Width, "strict tab slice width"); AssertEqual(measurer.GetWidth(strictTabSlice.Text), strictTabSlice.Width, "strict tab slice measured width"); var afterTabSlice = measurer.Slice("out 192M\t.pi/skill-tests/results-ha", 13, 10, strict: true); AssertEqual("i/skill-te", afterTabSlice.Text, "slice after tab text"); AssertEqual(measurer.GetWidth(afterTabSlice.Text), afterTabSlice.Width, "slice after tab measured width"); var ansiText = $"\e[31m{"hello ".Repeat(100)}\e[0m"; var truncated = measurer.Truncate(ansiText, 20, "…"); AssertTrue(measurer.GetWidth(truncated) <= 20, "ansi truncate width"); AssertTrue(truncated.Contains("\e[31m", StringComparison.Ordinal), "ansi truncate keeps style prefix"); AssertTrue(truncated.EndsWith("\e[0m…\e[0m", StringComparison.Ordinal), "ansi truncate brackets ellipsis"); var wideEllipsis = measurer.Truncate("abcdef", 2, "πŸ™‚"); AssertEqual("\e[0mπŸ™‚\e[0m", wideEllipsis, "wide ellipsis clipping"); AssertEqual(string.Empty, measurer.Truncate("abcdef", 1, "πŸ™‚"), "wide ellipsis too narrow"); var plainWrapped = measurer.Wrap("hello world this is a test", 10); AssertTrue(plainWrapped.Count > 1, "plain wrap line count"); AssertTrue(plainWrapped.All(line => measurer.GetWidth(line) <= 10), "plain wrap width"); var redWrapped = measurer.Wrap($"\e[31mhello world this is red\e[0m", 10); AssertTrue(redWrapped.Skip(1).All(line => line.StartsWith("\e[31m", StringComparison.Ordinal)), "ansi wrap restores red"); AssertTrue(redWrapped.Take(redWrapped.Count - 1).All(line => !line.EndsWith("\e[0m", StringComparison.Ordinal)), "ansi wrap avoids full reset before final"); var underlinedUrl = measurer.Wrap($"read this thread \e[4mhttps://example.com/very/long/path/that/will/definitely/wrap\e[24m", 40); AssertEqual("read this thread", underlinedUrl[0], "underline wrap keeps prefix unstyled"); AssertTrue(underlinedUrl[1].StartsWith("\e[4m", StringComparison.Ordinal), "underline wrap starts style on url line"); AssertTrue(underlinedUrl.Take(underlinedUrl.Count - 1).Any(line => line.EndsWith("\e[24m", StringComparison.Ordinal)), "underline wrap closes line"); var hyperlink = "\e]8;;https://example.com\a0123456789\e]8;;\a"; var hyperlinkWrapped = measurer.Wrap(hyperlink, 6); AssertTrue(hyperlinkWrapped.Count > 1, "osc8 wrap line count"); AssertTrue(hyperlinkWrapped.All(line => line.Contains("\e]8;;https://example.com\a", StringComparison.Ordinal)), "osc8 wrap reopens hyperlink with bel"); AssertTrue(hyperlinkWrapped.Take(hyperlinkWrapped.Count - 1).All(line => line.EndsWith("\e]8;;\a", StringComparison.Ordinal)), "osc8 wrap closes hyperlink with bel"); Console.WriteLine("TinyTUI text checks passed"); static void AssertEqual(T expected, T actual, string name) { if (!EqualityComparer.Default.Equals(expected, actual)) throw new InvalidOperationException($"{name}: expected '{expected}', actual '{actual}'"); } static void AssertTrue(bool condition, string name) { if (!condition) throw new InvalidOperationException($"{name}: assertion failed"); } internal static class StringExtensions { /// /// ι‡ε€ε­—η¬¦δΈ²η”¨δΊŽζž„ι€ ι•Ώζ–‡ζœ¬ζ΅‹θ―•θΎ“ε…₯ /// public static string Repeat(this string value, int count) => string.Concat(Enumerable.Repeat(value, count)); }