ratatui_toolkit/vt100_term/
copy_mode.rs1use super::Screen;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
11pub struct Pos {
12 pub x: i32,
13 pub y: i32,
14}
15
16impl Pos {
17 pub fn new(x: i32, y: i32) -> Self {
19 Self { x, y }
20 }
21
22 pub fn within(start: &Pos, end: &Pos, pos: &Pos) -> bool {
24 let (low, high) = Self::to_low_high(start, end);
25
26 if pos.y < low.y || pos.y > high.y {
27 return false;
28 }
29
30 if pos.y == low.y && pos.y == high.y {
31 pos.x >= low.x && pos.x <= high.x
33 } else if pos.y == low.y {
34 pos.x >= low.x
36 } else if pos.y == high.y {
37 pos.x <= high.x
39 } else {
40 true
42 }
43 }
44
45 pub fn to_low_high(a: &Pos, b: &Pos) -> (Pos, Pos) {
47 if a.y < b.y || (a.y == b.y && a.x <= b.x) {
48 (*a, *b)
49 } else {
50 (*b, *a)
51 }
52 }
53}
54
55#[derive(Debug, Clone)]
61pub enum CopyMode {
62 None,
64
65 Active {
67 screen: Screen,
69
70 start: Pos,
72
73 end: Option<Pos>,
75 },
76}
77
78impl CopyMode {
79 pub fn is_active(&self) -> bool {
81 matches!(self, CopyMode::Active { .. })
82 }
83
84 pub fn get_selection(&self) -> Option<(Pos, Pos)> {
86 match self {
87 CopyMode::Active { start, end, .. } => Some((*start, end.unwrap_or(*start))),
88 CopyMode::None => None,
89 }
90 }
91
92 pub fn screen(&self) -> Option<&Screen> {
94 match self {
95 CopyMode::Active { screen, .. } => Some(screen),
96 CopyMode::None => None,
97 }
98 }
99
100 pub fn enter(screen: Screen, start: Pos) -> Self {
102 CopyMode::Active {
103 screen,
104 start,
105 end: None,
106 }
107 }
108
109 pub fn exit() -> Self {
111 CopyMode::None
112 }
113
114 pub fn move_cursor(&mut self, dx: i32, dy: i32) {
116 if let CopyMode::Active { screen, start, end } = self {
117 let pos = end.as_mut().unwrap_or(start);
118
119 pos.x = (pos.x + dx).max(0).min(screen.size().cols as i32 - 1);
121 pos.y = (pos.y + dy)
122 .max(-(screen.scrollback_len() as i32))
123 .min(screen.size().rows as i32 - 1);
124 }
125 }
126
127 pub fn set_end(&mut self) {
129 if let CopyMode::Active { start, end, .. } = self {
130 if end.is_none() {
131 *end = Some(*start);
132 }
133 }
134 }
135
136 pub fn get_selected_text(&self) -> Option<String> {
138 match self {
139 CopyMode::Active { screen, start, end } => {
140 let end_pos = end.unwrap_or(*start);
141 let (low, high) = Pos::to_low_high(start, &end_pos);
142 Some(screen.get_selected_text(low.x, low.y, high.x, high.y))
143 }
144 CopyMode::None => None,
145 }
146 }
147}
148
149#[derive(Debug, Clone, Copy)]
151pub enum CopyMoveDir {
152 Up,
153 Down,
154 Left,
155 Right,
156}
157
158impl CopyMoveDir {
159 pub fn delta(&self) -> (i32, i32) {
161 match self {
162 CopyMoveDir::Up => (0, -1),
163 CopyMoveDir::Down => (0, 1),
164 CopyMoveDir::Left => (-1, 0),
165 CopyMoveDir::Right => (1, 0),
166 }
167 }
168}