ratatui_core/terminal/
cursor.rs1use crate::backend::Backend;
2use crate::layout::Position;
3use crate::terminal::Terminal;
4
5impl<B: Backend> Terminal<B> {
6 pub fn hide_cursor(&mut self) -> Result<(), B::Error> {
16 self.backend.hide_cursor()?;
17 self.hidden_cursor = true;
18 Ok(())
19 }
20
21 pub fn show_cursor(&mut self) -> Result<(), B::Error> {
31 self.backend.show_cursor()?;
32 self.hidden_cursor = false;
33 Ok(())
34 }
35
36 #[deprecated = "use `get_cursor_position()` instead which returns `Result<Position>`"]
41 pub fn get_cursor(&mut self) -> Result<(u16, u16), B::Error> {
42 let Position { x, y } = self.get_cursor_position()?;
43 Ok((x, y))
44 }
45
46 #[deprecated = "use `set_cursor_position((x, y))` instead which takes `impl Into<Position>`"]
48 pub fn set_cursor(&mut self, x: u16, y: u16) -> Result<(), B::Error> {
49 self.set_cursor_position(Position { x, y })
50 }
51
52 pub fn get_cursor_position(&mut self) -> Result<Position, B::Error> {
64 self.backend.get_cursor_position()
65 }
66
67 pub fn set_cursor_position<P: Into<Position>>(&mut self, position: P) -> Result<(), B::Error> {
81 let position = position.into();
82 self.backend.set_cursor_position(position)?;
83 self.last_known_cursor_pos = position;
84 Ok(())
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use crate::backend::{Backend, TestBackend};
91 use crate::layout::Position;
92 use crate::terminal::Terminal;
93
94 #[test]
95 fn hide_cursor_updates_terminal_state() {
96 let backend = TestBackend::new(10, 5);
97 let mut terminal = Terminal::new(backend).unwrap();
98
99 terminal.hide_cursor().unwrap();
100
101 assert!(terminal.hidden_cursor);
102 assert!(!terminal.backend().cursor_visible());
103 }
104
105 #[test]
106 fn show_cursor_updates_terminal_state() {
107 let backend = TestBackend::new(10, 5);
108 let mut terminal = Terminal::new(backend).unwrap();
109
110 terminal.hide_cursor().unwrap();
111 terminal.show_cursor().unwrap();
112
113 assert!(!terminal.hidden_cursor);
114 assert!(terminal.backend().cursor_visible());
115 }
116
117 #[test]
118 fn set_cursor_position_updates_backend_and_tracking() {
119 let backend = TestBackend::new(10, 5);
120 let mut terminal = Terminal::new(backend).unwrap();
121
122 terminal.set_cursor_position((3, 4)).unwrap();
123
124 assert_eq!(terminal.last_known_cursor_pos, Position { x: 3, y: 4 });
125 terminal
126 .backend_mut()
127 .assert_cursor_position(Position { x: 3, y: 4 });
128 }
129
130 #[test]
131 fn get_cursor_position_queries_backend() {
132 let backend = TestBackend::new(10, 5);
133 let mut terminal = Terminal::new(backend).unwrap();
134
135 terminal
136 .backend_mut()
137 .set_cursor_position(Position { x: 7, y: 2 })
138 .unwrap();
139
140 assert_eq!(
141 terminal.get_cursor_position().unwrap(),
142 Position { x: 7, y: 2 }
143 );
144 }
145
146 #[test]
147 #[allow(deprecated)]
148 fn deprecated_cursor_wrappers_delegate_to_position_apis() {
149 let backend = TestBackend::new(10, 5);
150 let mut terminal = Terminal::new(backend).unwrap();
151
152 terminal.set_cursor(4, 1).unwrap();
153
154 assert_eq!(terminal.get_cursor().unwrap(), (4, 1));
155 assert_eq!(terminal.last_known_cursor_pos, Position { x: 4, y: 1 });
156 terminal
157 .backend_mut()
158 .assert_cursor_position(Position { x: 4, y: 1 });
159 }
160}