par_term/copy_mode/
cursor.rs1use super::types::CopyModeState;
4
5impl CopyModeState {
6 pub fn move_left(&mut self) {
12 let count = self.effective_count();
13 self.cursor_col = self.cursor_col.saturating_sub(count);
14 }
15
16 pub fn move_right(&mut self) {
18 let count = self.effective_count();
19 self.cursor_col = (self.cursor_col + count).min(self.cols.saturating_sub(1));
20 }
21
22 pub fn move_up(&mut self) {
24 let count = self.effective_count();
25 self.cursor_absolute_line = self.cursor_absolute_line.saturating_sub(count);
26 }
27
28 pub fn move_down(&mut self) {
30 let count = self.effective_count();
31 self.cursor_absolute_line = (self.cursor_absolute_line + count).min(self.max_line());
32 }
33
34 pub fn move_to_line_start(&mut self) {
36 self.cursor_col = 0;
37 }
38
39 pub fn move_to_line_end(&mut self) {
41 self.cursor_col = self.cols.saturating_sub(1);
42 }
43
44 pub fn move_to_first_non_blank(&mut self, line_text: &str) {
46 let first_non_blank = line_text
47 .chars()
48 .position(|c| !c.is_whitespace())
49 .unwrap_or(0);
50 self.cursor_col = first_non_blank.min(self.cols.saturating_sub(1));
51 }
52
53 pub fn half_page_up(&mut self) {
59 let half = self.rows / 2;
60 let count = self.effective_count();
61 self.cursor_absolute_line = self.cursor_absolute_line.saturating_sub(half * count);
62 }
63
64 pub fn half_page_down(&mut self) {
66 let half = self.rows / 2;
67 let count = self.effective_count();
68 self.cursor_absolute_line = (self.cursor_absolute_line + half * count).min(self.max_line());
69 }
70
71 pub fn page_up(&mut self) {
73 let count = self.effective_count();
74 self.cursor_absolute_line = self.cursor_absolute_line.saturating_sub(self.rows * count);
75 }
76
77 pub fn page_down(&mut self) {
79 let count = self.effective_count();
80 self.cursor_absolute_line =
81 (self.cursor_absolute_line + self.rows * count).min(self.max_line());
82 }
83
84 pub fn goto_top(&mut self) {
86 self.cursor_absolute_line = 0;
87 }
88
89 pub fn goto_bottom(&mut self) {
91 self.cursor_absolute_line = self.max_line();
92 }
93
94 pub fn goto_line(&mut self, line: usize) {
96 self.cursor_absolute_line = line.min(self.max_line());
97 }
98
99 pub fn screen_cursor_pos(&self, scroll_offset: usize) -> Option<(usize, usize)> {
108 let viewport_top = self.scrollback_len.saturating_sub(scroll_offset);
109 let viewport_bottom = viewport_top + self.rows;
110
111 if self.cursor_absolute_line >= viewport_top && self.cursor_absolute_line < viewport_bottom
112 {
113 let screen_row = self.cursor_absolute_line - viewport_top;
114 Some((self.cursor_col, screen_row))
115 } else {
116 None
117 }
118 }
119
120 pub fn required_scroll_offset(&self, current_offset: usize) -> Option<usize> {
124 let viewport_top = self.scrollback_len.saturating_sub(current_offset);
125 let viewport_bottom = viewport_top + self.rows;
126
127 if self.cursor_absolute_line < viewport_top {
128 let new_offset = self
130 .scrollback_len
131 .saturating_sub(self.cursor_absolute_line);
132 Some(new_offset)
133 } else if self.cursor_absolute_line >= viewport_bottom {
134 let lines_below = self.cursor_absolute_line - viewport_top;
136 let needed_offset = current_offset
137 .saturating_sub(lines_below.saturating_sub(self.rows.saturating_sub(1)));
138 let target_viewport_top = self
140 .cursor_absolute_line
141 .saturating_sub(self.rows.saturating_sub(1));
142 let new_offset = self.scrollback_len.saturating_sub(target_viewport_top);
143 let _ = needed_offset; Some(new_offset.min(self.scrollback_len))
146 } else {
147 None
148 }
149 }
150}