from __future__ import annotations from prompt_toolkit.formatted_text import ( ANSI, HTML, FormattedText, PygmentsTokens, Template, merge_formatted_text, to_formatted_text, ) from prompt_toolkit.formatted_text.utils import split_lines def test_basic_html(): html = HTML("hello") assert to_formatted_text(html) == [("class:i", "hello")] html = HTML("hello") assert to_formatted_text(html) == [("class:i,b", "hello")] html = HTML("helloworldtestafter") assert to_formatted_text(html) == [ ("class:i,b", "hello"), ("class:i", "world"), ("class:i,strong", "test"), ("", "after"), ] # It's important that `to_formatted_text` returns a `FormattedText` # instance. Otherwise, `print_formatted_text` won't recognize it and will # print a list literal instead. assert isinstance(to_formatted_text(html), FormattedText) def test_html_with_fg_bg(): html = HTML('') assert to_formatted_text(html) == [ ("bg:ansired", "hello"), ] html = HTML('') assert to_formatted_text(html) == [ ("fg:#ff0000 bg:ansired", "hello"), ] html = HTML( '' ) assert to_formatted_text(html) == [ ("fg:#ff0000 bg:ansired", "hello "), ("class:world fg:ansiblue bg:ansired", "world"), ] def test_ansi_formatting(): value = ANSI("\x1b[32mHe\x1b[45mllo") assert to_formatted_text(value) == [ ("ansigreen", "H"), ("ansigreen", "e"), ("ansigreen bg:ansimagenta", "l"), ("ansigreen bg:ansimagenta", "l"), ("ansigreen bg:ansimagenta", "o"), ] # Bold and italic. value = ANSI("\x1b[1mhe\x1b[0mllo") assert to_formatted_text(value) == [ ("bold", "h"), ("bold", "e"), ("", "l"), ("", "l"), ("", "o"), ] # Zero width escapes. value = ANSI("ab\001cd\002ef") assert to_formatted_text(value) == [ ("", "a"), ("", "b"), ("[ZeroWidthEscape]", "cd"), ("", "e"), ("", "f"), ] assert isinstance(to_formatted_text(value), FormattedText) def test_ansi_256_color(): assert to_formatted_text(ANSI("\x1b[38;5;124mtest")) == [ ("#af0000", "t"), ("#af0000", "e"), ("#af0000", "s"), ("#af0000", "t"), ] def test_ansi_true_color(): assert to_formatted_text(ANSI("\033[38;2;144;238;144m$\033[0;39;49m ")) == [ ("#90ee90", "$"), ("ansidefault bg:ansidefault", " "), ] def test_ansi_interpolation(): # %-style interpolation. value = ANSI("\x1b[1m%s\x1b[0m") % "hello\x1b" assert to_formatted_text(value) == [ ("bold", "h"), ("bold", "e"), ("bold", "l"), ("bold", "l"), ("bold", "o"), ("bold", "?"), ] value = ANSI("\x1b[1m%s\x1b[0m") % ("\x1bhello",) assert to_formatted_text(value) == [ ("bold", "?"), ("bold", "h"), ("bold", "e"), ("bold", "l"), ("bold", "l"), ("bold", "o"), ] value = ANSI("\x1b[32m%s\x1b[45m%s") % ("He", "\x1bllo") assert to_formatted_text(value) == [ ("ansigreen", "H"), ("ansigreen", "e"), ("ansigreen bg:ansimagenta", "?"), ("ansigreen bg:ansimagenta", "l"), ("ansigreen bg:ansimagenta", "l"), ("ansigreen bg:ansimagenta", "o"), ] # Format function. value = ANSI("\x1b[32m{0}\x1b[45m{1}").format("He\x1b", "llo") assert to_formatted_text(value) == [ ("ansigreen", "H"), ("ansigreen", "e"), ("ansigreen", "?"), ("ansigreen bg:ansimagenta", "l"), ("ansigreen bg:ansimagenta", "l"), ("ansigreen bg:ansimagenta", "o"), ] value = ANSI("\x1b[32m{a}\x1b[45m{b}").format(a="\x1bHe", b="llo") assert to_formatted_text(value) == [ ("ansigreen", "?"), ("ansigreen", "H"), ("ansigreen", "e"), ("ansigreen bg:ansimagenta", "l"), ("ansigreen bg:ansimagenta", "l"), ("ansigreen bg:ansimagenta", "o"), ] value = ANSI("\x1b[32m{:02d}\x1b[45m{:.3f}").format(3, 3.14159) assert to_formatted_text(value) == [ ("ansigreen", "0"), ("ansigreen", "3"), ("ansigreen bg:ansimagenta", "3"), ("ansigreen bg:ansimagenta", "."), ("ansigreen bg:ansimagenta", "1"), ("ansigreen bg:ansimagenta", "4"), ("ansigreen bg:ansimagenta", "2"), ] def test_interpolation(): value = Template(" {} ").format(HTML("hello")) assert to_formatted_text(value) == [ ("", " "), ("class:b", "hello"), ("", " "), ] value = Template("a{}b{}c").format(HTML("hello"), "world") assert to_formatted_text(value) == [ ("", "a"), ("class:b", "hello"), ("", "b"), ("", "world"), ("", "c"), ] def test_html_interpolation(): # %-style interpolation. value = HTML("%s") % "&hello" assert to_formatted_text(value) == [("class:b", "&hello")] value = HTML("%s") % ("",) assert to_formatted_text(value) == [("class:b", "")] value = HTML("%s%s") % ("", "") assert to_formatted_text(value) == [("class:b", ""), ("class:u", "")] # Format function. value = HTML("{0}{1}").format("'hello'", '"world"') assert to_formatted_text(value) == [("class:b", "'hello'"), ("class:u", '"world"')] value = HTML("{a}{b}").format(a="hello", b="world") assert to_formatted_text(value) == [("class:b", "hello"), ("class:u", "world")] value = HTML("{:02d}{:.3f}").format(3, 3.14159) assert to_formatted_text(value) == [("class:b", "03"), ("class:u", "3.142")] def test_merge_formatted_text(): html1 = HTML("hello") html2 = HTML("world") result = merge_formatted_text([html1, html2]) assert to_formatted_text(result) == [ ("class:u", "hello"), ("class:b", "world"), ] def test_pygments_tokens(): text = [ (("A", "B"), "hello"), # Token.A.B (("C", "D", "E"), "hello"), # Token.C.D.E ((), "world"), # Token ] assert to_formatted_text(PygmentsTokens(text)) == [ ("class:pygments.a.b", "hello"), ("class:pygments.c.d.e", "hello"), ("class:pygments", "world"), ] def test_split_lines(): lines = list(split_lines([("class:a", "line1\nline2\nline3")])) assert lines == [ [("class:a", "line1")], [("class:a", "line2")], [("class:a", "line3")], ] def test_split_lines_2(): lines = list( split_lines([("class:a", "line1"), ("class:b", "line2\nline3\nline4")]) ) assert lines == [ [("class:a", "line1"), ("class:b", "line2")], [("class:b", "line3")], [("class:b", "line4")], ] def test_split_lines_3(): "Edge cases: inputs ending with newlines." # -1- lines = list(split_lines([("class:a", "line1\nline2\n")])) assert lines == [ [("class:a", "line1")], [("class:a", "line2")], [("class:a", "")], ] # -2- lines = list(split_lines([("class:a", "\n")])) assert lines == [ [], [("class:a", "")], ] # -3- lines = list(split_lines([("class:a", "")])) assert lines == [ [("class:a", "")], ]