test_formatted_text.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. from prompt_toolkit.formatted_text import (
  2. ANSI,
  3. HTML,
  4. FormattedText,
  5. PygmentsTokens,
  6. Template,
  7. merge_formatted_text,
  8. to_formatted_text,
  9. )
  10. from prompt_toolkit.formatted_text.utils import split_lines
  11. def test_basic_html():
  12. html = HTML("<i>hello</i>")
  13. assert to_formatted_text(html) == [("class:i", "hello")]
  14. html = HTML("<i><b>hello</b></i>")
  15. assert to_formatted_text(html) == [("class:i,b", "hello")]
  16. html = HTML("<i><b>hello</b>world<strong>test</strong></i>after")
  17. assert to_formatted_text(html) == [
  18. ("class:i,b", "hello"),
  19. ("class:i", "world"),
  20. ("class:i,strong", "test"),
  21. ("", "after"),
  22. ]
  23. # It's important that `to_formatted_text` returns a `FormattedText`
  24. # instance. Otherwise, `print_formatted_text` won't recognise it and will
  25. # print a list literal instead.
  26. assert isinstance(to_formatted_text(html), FormattedText)
  27. def test_html_with_fg_bg():
  28. html = HTML('<style bg="ansired">hello</style>')
  29. assert to_formatted_text(html) == [
  30. ("bg:ansired", "hello"),
  31. ]
  32. html = HTML('<style bg="ansired" fg="#ff0000">hello</style>')
  33. assert to_formatted_text(html) == [
  34. ("fg:#ff0000 bg:ansired", "hello"),
  35. ]
  36. html = HTML(
  37. '<style bg="ansired" fg="#ff0000">hello <world fg="ansiblue">world</world></style>'
  38. )
  39. assert to_formatted_text(html) == [
  40. ("fg:#ff0000 bg:ansired", "hello "),
  41. ("class:world fg:ansiblue bg:ansired", "world"),
  42. ]
  43. def test_ansi_formatting():
  44. value = ANSI("\x1b[32mHe\x1b[45mllo")
  45. assert to_formatted_text(value) == [
  46. ("ansigreen", "H"),
  47. ("ansigreen", "e"),
  48. ("ansigreen bg:ansimagenta", "l"),
  49. ("ansigreen bg:ansimagenta", "l"),
  50. ("ansigreen bg:ansimagenta", "o"),
  51. ]
  52. # Bold and italic.
  53. value = ANSI("\x1b[1mhe\x1b[0mllo")
  54. assert to_formatted_text(value) == [
  55. ("bold", "h"),
  56. ("bold", "e"),
  57. ("", "l"),
  58. ("", "l"),
  59. ("", "o"),
  60. ]
  61. # Zero width escapes.
  62. value = ANSI("ab\001cd\002ef")
  63. assert to_formatted_text(value) == [
  64. ("", "a"),
  65. ("", "b"),
  66. ("[ZeroWidthEscape]", "cd"),
  67. ("", "e"),
  68. ("", "f"),
  69. ]
  70. assert isinstance(to_formatted_text(value), FormattedText)
  71. def test_ansi_256_color():
  72. assert to_formatted_text(ANSI("\x1b[38;5;124mtest")) == [
  73. ("#af0000", "t"),
  74. ("#af0000", "e"),
  75. ("#af0000", "s"),
  76. ("#af0000", "t"),
  77. ]
  78. def test_ansi_true_color():
  79. assert to_formatted_text(ANSI("\033[38;2;144;238;144m$\033[0;39;49m ")) == [
  80. ("#90ee90", "$"),
  81. ("ansidefault bg:ansidefault", " "),
  82. ]
  83. def test_interpolation():
  84. value = Template(" {} ").format(HTML("<b>hello</b>"))
  85. assert to_formatted_text(value) == [
  86. ("", " "),
  87. ("class:b", "hello"),
  88. ("", " "),
  89. ]
  90. value = Template("a{}b{}c").format(HTML("<b>hello</b>"), "world")
  91. assert to_formatted_text(value) == [
  92. ("", "a"),
  93. ("class:b", "hello"),
  94. ("", "b"),
  95. ("", "world"),
  96. ("", "c"),
  97. ]
  98. def test_html_interpolation():
  99. # %-style interpolation.
  100. value = HTML("<b>%s</b>") % "hello"
  101. assert to_formatted_text(value) == [("class:b", "hello")]
  102. value = HTML("<b>%s</b>") % ("hello",)
  103. assert to_formatted_text(value) == [("class:b", "hello")]
  104. value = HTML("<b>%s</b><u>%s</u>") % ("hello", "world")
  105. assert to_formatted_text(value) == [("class:b", "hello"), ("class:u", "world")]
  106. # Format function.
  107. value = HTML("<b>{0}</b><u>{1}</u>").format("hello", "world")
  108. assert to_formatted_text(value) == [("class:b", "hello"), ("class:u", "world")]
  109. value = HTML("<b>{a}</b><u>{b}</u>").format(a="hello", b="world")
  110. assert to_formatted_text(value) == [("class:b", "hello"), ("class:u", "world")]
  111. def test_merge_formatted_text():
  112. html1 = HTML("<u>hello</u>")
  113. html2 = HTML("<b>world</b>")
  114. result = merge_formatted_text([html1, html2])
  115. assert to_formatted_text(result) == [
  116. ("class:u", "hello"),
  117. ("class:b", "world"),
  118. ]
  119. def test_pygments_tokens():
  120. text = [
  121. (("A", "B"), "hello"), # Token.A.B
  122. (("C", "D", "E"), "hello"), # Token.C.D.E
  123. ((), "world"), # Token
  124. ]
  125. assert to_formatted_text(PygmentsTokens(text)) == [
  126. ("class:pygments.a.b", "hello"),
  127. ("class:pygments.c.d.e", "hello"),
  128. ("class:pygments", "world"),
  129. ]
  130. def test_split_lines():
  131. lines = list(split_lines([("class:a", "line1\nline2\nline3")]))
  132. assert lines == [
  133. [("class:a", "line1")],
  134. [("class:a", "line2")],
  135. [("class:a", "line3")],
  136. ]
  137. def test_split_lines_2():
  138. lines = list(
  139. split_lines([("class:a", "line1"), ("class:b", "line2\nline3\nline4")])
  140. )
  141. assert lines == [
  142. [("class:a", "line1"), ("class:b", "line2")],
  143. [("class:b", "line3")],
  144. [("class:b", "line4")],
  145. ]
  146. def test_split_lines_3():
  147. "Edge cases: inputs ending with newlines."
  148. # -1-
  149. lines = list(split_lines([("class:a", "line1\nline2\n")]))
  150. assert lines == [
  151. [("class:a", "line1")],
  152. [("class:a", "line2")],
  153. [("class:a", "")],
  154. ]
  155. # -2-
  156. lines = list(split_lines([("class:a", "\n")]))
  157. assert lines == [
  158. [],
  159. [("class:a", "")],
  160. ]
  161. # -3-
  162. lines = list(split_lines([("class:a", "")]))
  163. assert lines == [
  164. [("class:a", "")],
  165. ]