Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/prompt_toolkit/key_binding/bindings/scroll.py: 16%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

82 statements  

1""" 

2Key bindings, for scrolling up and down through pages. 

3 

4This are separate bindings, because GNU readline doesn't have them, but 

5they are very useful for navigating through long multiline buffers, like in 

6Vi, Emacs, etc... 

7""" 

8 

9from __future__ import annotations 

10 

11from prompt_toolkit.key_binding.key_processor import KeyPressEvent 

12 

13__all__ = [ 

14 "scroll_forward", 

15 "scroll_backward", 

16 "scroll_half_page_up", 

17 "scroll_half_page_down", 

18 "scroll_one_line_up", 

19 "scroll_one_line_down", 

20] 

21 

22E = KeyPressEvent 

23 

24 

25def scroll_forward(event: E, half: bool = False) -> None: 

26 """ 

27 Scroll window down. 

28 """ 

29 w = event.app.layout.current_window 

30 b = event.app.current_buffer 

31 

32 if w and w.render_info: 

33 info = w.render_info 

34 ui_content = info.ui_content 

35 

36 # Height to scroll. 

37 scroll_height = info.window_height 

38 if half: 

39 scroll_height //= 2 

40 

41 # Calculate how many lines is equivalent to that vertical space. 

42 y = b.document.cursor_position_row + 1 

43 height = 0 

44 while y < ui_content.line_count: 

45 line_height = info.get_height_for_line(y) 

46 

47 if height + line_height < scroll_height: 

48 height += line_height 

49 y += 1 

50 else: 

51 break 

52 

53 b.cursor_position = b.document.translate_row_col_to_index(y, 0) 

54 

55 

56def scroll_backward(event: E, half: bool = False) -> None: 

57 """ 

58 Scroll window up. 

59 """ 

60 w = event.app.layout.current_window 

61 b = event.app.current_buffer 

62 

63 if w and w.render_info: 

64 info = w.render_info 

65 

66 # Height to scroll. 

67 scroll_height = info.window_height 

68 if half: 

69 scroll_height //= 2 

70 

71 # Calculate how many lines is equivalent to that vertical space. 

72 y = max(0, b.document.cursor_position_row - 1) 

73 height = 0 

74 while y > 0: 

75 line_height = info.get_height_for_line(y) 

76 

77 if height + line_height < scroll_height: 

78 height += line_height 

79 y -= 1 

80 else: 

81 break 

82 

83 b.cursor_position = b.document.translate_row_col_to_index(y, 0) 

84 

85 

86def scroll_half_page_down(event: E) -> None: 

87 """ 

88 Same as ControlF, but only scroll half a page. 

89 """ 

90 scroll_forward(event, half=True) 

91 

92 

93def scroll_half_page_up(event: E) -> None: 

94 """ 

95 Same as ControlB, but only scroll half a page. 

96 """ 

97 scroll_backward(event, half=True) 

98 

99 

100def scroll_one_line_down(event: E) -> None: 

101 """ 

102 scroll_offset += 1 

103 """ 

104 w = event.app.layout.current_window 

105 b = event.app.current_buffer 

106 

107 if w: 

108 # When the cursor is at the top, move to the next line. (Otherwise, only scroll.) 

109 if w.render_info: 

110 info = w.render_info 

111 

112 if w.vertical_scroll < info.content_height - info.window_height: 

113 if info.cursor_position.y <= info.configured_scroll_offsets.top: 

114 b.cursor_position += b.document.get_cursor_down_position() 

115 

116 w.vertical_scroll += 1 

117 

118 

119def scroll_one_line_up(event: E) -> None: 

120 """ 

121 scroll_offset -= 1 

122 """ 

123 w = event.app.layout.current_window 

124 b = event.app.current_buffer 

125 

126 if w: 

127 # When the cursor is at the bottom, move to the previous line. (Otherwise, only scroll.) 

128 if w.render_info: 

129 info = w.render_info 

130 

131 if w.vertical_scroll > 0: 

132 first_line_height = info.get_height_for_line(info.first_visible_line()) 

133 

134 cursor_up = info.cursor_position.y - ( 

135 info.window_height 

136 - 1 

137 - first_line_height 

138 - info.configured_scroll_offsets.bottom 

139 ) 

140 

141 # Move cursor up, as many steps as the height of the first line. 

142 # TODO: not entirely correct yet, in case of line wrapping and many long lines. 

143 for _ in range(max(0, cursor_up)): 

144 b.cursor_position += b.document.get_cursor_up_position() 

145 

146 # Scroll window 

147 w.vertical_scroll -= 1 

148 

149 

150def scroll_page_down(event: E) -> None: 

151 """ 

152 Scroll page down. (Prefer the cursor at the top of the page, after scrolling.) 

153 """ 

154 w = event.app.layout.current_window 

155 b = event.app.current_buffer 

156 

157 if w and w.render_info: 

158 # Scroll down one page. 

159 line_index = max(w.render_info.last_visible_line(), w.vertical_scroll + 1) 

160 w.vertical_scroll = line_index 

161 

162 b.cursor_position = b.document.translate_row_col_to_index(line_index, 0) 

163 b.cursor_position += b.document.get_start_of_line_position( 

164 after_whitespace=True 

165 ) 

166 

167 

168def scroll_page_up(event: E) -> None: 

169 """ 

170 Scroll page up. (Prefer the cursor at the bottom of the page, after scrolling.) 

171 """ 

172 w = event.app.layout.current_window 

173 b = event.app.current_buffer 

174 

175 if w and w.render_info: 

176 # Put cursor at the first visible line. (But make sure that the cursor 

177 # moves at least one line up.) 

178 line_index = max( 

179 0, 

180 min(w.render_info.first_visible_line(), b.document.cursor_position_row - 1), 

181 ) 

182 

183 b.cursor_position = b.document.translate_row_col_to_index(line_index, 0) 

184 b.cursor_position += b.document.get_start_of_line_position( 

185 after_whitespace=True 

186 ) 

187 

188 # Set the scroll offset. We can safely set it to zero; the Window will 

189 # make sure that it scrolls at least until the cursor becomes visible. 

190 w.vertical_scroll = 0