Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/prompt_toolkit/formatted_text/utils.py: 37%

27 statements  

« prev     ^ index     » next       coverage.py v7.2.2, created at 2023-03-26 06:07 +0000

1""" 

2Utilities for manipulating formatted text. 

3 

4When ``to_formatted_text`` has been called, we get a list of ``(style, text)`` 

5tuples. This file contains functions for manipulating such a list. 

6""" 

7from __future__ import annotations 

8 

9from typing import Iterable, cast 

10 

11from prompt_toolkit.utils import get_cwidth 

12 

13from .base import ( 

14 AnyFormattedText, 

15 OneStyleAndTextTuple, 

16 StyleAndTextTuples, 

17 to_formatted_text, 

18) 

19 

20__all__ = [ 

21 "to_plain_text", 

22 "fragment_list_len", 

23 "fragment_list_width", 

24 "fragment_list_to_text", 

25 "split_lines", 

26] 

27 

28 

29def to_plain_text(value: AnyFormattedText) -> str: 

30 """ 

31 Turn any kind of formatted text back into plain text. 

32 """ 

33 return fragment_list_to_text(to_formatted_text(value)) 

34 

35 

36def fragment_list_len(fragments: StyleAndTextTuples) -> int: 

37 """ 

38 Return the amount of characters in this text fragment list. 

39 

40 :param fragments: List of ``(style_str, text)`` or 

41 ``(style_str, text, mouse_handler)`` tuples. 

42 """ 

43 ZeroWidthEscape = "[ZeroWidthEscape]" 

44 return sum(len(item[1]) for item in fragments if ZeroWidthEscape not in item[0]) 

45 

46 

47def fragment_list_width(fragments: StyleAndTextTuples) -> int: 

48 """ 

49 Return the character width of this text fragment list. 

50 (Take double width characters into account.) 

51 

52 :param fragments: List of ``(style_str, text)`` or 

53 ``(style_str, text, mouse_handler)`` tuples. 

54 """ 

55 ZeroWidthEscape = "[ZeroWidthEscape]" 

56 return sum( 

57 get_cwidth(c) 

58 for item in fragments 

59 for c in item[1] 

60 if ZeroWidthEscape not in item[0] 

61 ) 

62 

63 

64def fragment_list_to_text(fragments: StyleAndTextTuples) -> str: 

65 """ 

66 Concatenate all the text parts again. 

67 

68 :param fragments: List of ``(style_str, text)`` or 

69 ``(style_str, text, mouse_handler)`` tuples. 

70 """ 

71 ZeroWidthEscape = "[ZeroWidthEscape]" 

72 return "".join(item[1] for item in fragments if ZeroWidthEscape not in item[0]) 

73 

74 

75def split_lines(fragments: StyleAndTextTuples) -> Iterable[StyleAndTextTuples]: 

76 """ 

77 Take a single list of (style_str, text) tuples and yield one such list for each 

78 line. Just like str.split, this will yield at least one item. 

79 

80 :param fragments: List of (style_str, text) or (style_str, text, mouse_handler) 

81 tuples. 

82 """ 

83 line: StyleAndTextTuples = [] 

84 

85 for style, string, *mouse_handler in fragments: 

86 parts = string.split("\n") 

87 

88 for part in parts[:-1]: 

89 if part: 

90 line.append(cast(OneStyleAndTextTuple, (style, part, *mouse_handler))) 

91 yield line 

92 line = [] 

93 

94 line.append(cast(OneStyleAndTextTuple, (style, parts[-1], *mouse_handler))) 

95 

96 # Always yield the last line, even when this is an empty line. This ensures 

97 # that when `fragments` ends with a newline character, an additional empty 

98 # line is yielded. (Otherwise, there's no way to differentiate between the 

99 # cases where `fragments` does and doesn't end with a newline.) 

100 yield line