requestty_ui/backend/
mod.rs1use std::{fmt::Display, io};
4
5#[cfg(any(feature = "crossterm", feature = "termion"))]
7#[cfg_attr(docsrs, doc(cfg(any(feature = "crossterm", feature = "termion"))))]
8pub fn get_backend<W: io::Write>(buf: W) -> impl Backend {
9 #[cfg(feature = "crossterm")]
10 return CrosstermBackend::new(buf);
11
12 #[cfg(not(feature = "crossterm"))]
17 return TermionBackend::new(buf);
18}
19
20mod test_backend;
21pub use test_backend::TestBackend;
22
23#[cfg(feature = "termion")]
24mod termion;
25
26#[cfg(feature = "termion")]
27pub use self::termion::TermionBackend;
28
29#[cfg(feature = "crossterm")]
30mod crossterm;
31
32#[cfg(feature = "crossterm")]
33pub use self::crossterm::CrosstermBackend;
34
35use crate::style::{Attributes, Color, Styled};
36
37#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Default)]
39#[allow(missing_docs)]
40pub struct Size {
41 pub width: u16,
42 pub height: u16,
43}
44
45impl Size {
46 pub fn area(self) -> u16 {
48 self.width * self.height
49 }
50}
51
52impl From<(u16, u16)> for Size {
53 fn from((width, height): (u16, u16)) -> Self {
54 Size { width, height }
55 }
56}
57
58#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
60pub enum ClearType {
61 All,
63 FromCursorDown,
65 FromCursorUp,
67 CurrentLine,
69 UntilNewLine,
71}
72
73#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
75pub enum MoveDirection {
76 Up(u16),
78 Down(u16),
80 Left(u16),
82 Right(u16),
84 NextLine(u16),
86 PrevLine(u16),
88 Column(u16),
90}
91
92pub trait Backend: io::Write {
94 fn enable_raw_mode(&mut self) -> io::Result<()>;
96 fn disable_raw_mode(&mut self) -> io::Result<()>;
98 fn hide_cursor(&mut self) -> io::Result<()>;
100 fn show_cursor(&mut self) -> io::Result<()>;
102
103 fn get_cursor_pos(&mut self) -> io::Result<(u16, u16)>;
105 fn move_cursor_to(&mut self, x: u16, y: u16) -> io::Result<()>;
107 fn move_cursor(&mut self, direction: MoveDirection) -> io::Result<()> {
109 default_move_cursor(self, direction)
110 }
111 fn scroll(&mut self, dist: i16) -> io::Result<()>;
116
117 fn set_attributes(&mut self, attributes: Attributes) -> io::Result<()>;
119 fn set_fg(&mut self, color: Color) -> io::Result<()>;
121 fn set_bg(&mut self, color: Color) -> io::Result<()>;
123 fn write_styled(&mut self, styled: &Styled<dyn Display + '_>) -> io::Result<()> {
129 styled.write(self)
130 }
131
132 fn clear(&mut self, clear_type: ClearType) -> io::Result<()>;
134 fn size(&self) -> io::Result<Size>;
136}
137
138fn default_move_cursor<B: Backend + ?Sized>(
139 backend: &mut B,
140 direction: MoveDirection,
141) -> io::Result<()> {
142 let (mut x, mut y) = backend.get_cursor_pos()?;
143
144 match direction {
145 MoveDirection::Up(dy) => y = y.saturating_sub(dy),
146 MoveDirection::Down(dy) => y = y.saturating_add(dy),
147 MoveDirection::Left(dx) => x = x.saturating_sub(dx),
148 MoveDirection::Right(dx) => x = x.saturating_add(dx),
149 MoveDirection::NextLine(dy) => {
150 x = 0;
151 y = y.saturating_add(dy);
152 }
153 MoveDirection::Column(new_x) => x = new_x,
154 MoveDirection::PrevLine(dy) => {
155 x = 0;
156 y = y.saturating_sub(dy);
157 }
158 }
159
160 backend.move_cursor_to(x, y)
161}
162
163impl<'a, B: Backend> Backend for &'a mut B {
164 fn enable_raw_mode(&mut self) -> io::Result<()> {
165 (**self).enable_raw_mode()
166 }
167 fn disable_raw_mode(&mut self) -> io::Result<()> {
168 (**self).disable_raw_mode()
169 }
170 fn hide_cursor(&mut self) -> io::Result<()> {
171 (**self).hide_cursor()
172 }
173 fn show_cursor(&mut self) -> io::Result<()> {
174 (**self).show_cursor()
175 }
176 fn get_cursor_pos(&mut self) -> io::Result<(u16, u16)> {
177 (**self).get_cursor_pos()
178 }
179 fn move_cursor_to(&mut self, x: u16, y: u16) -> io::Result<()> {
180 (**self).move_cursor_to(x, y)
181 }
182 fn move_cursor(&mut self, direction: MoveDirection) -> io::Result<()> {
183 (**self).move_cursor(direction)
184 }
185 fn scroll(&mut self, dist: i16) -> io::Result<()> {
186 (**self).scroll(dist)
187 }
188 fn set_attributes(&mut self, attributes: Attributes) -> io::Result<()> {
189 (**self).set_attributes(attributes)
190 }
191 fn set_fg(&mut self, color: Color) -> io::Result<()> {
192 (**self).set_fg(color)
193 }
194 fn set_bg(&mut self, color: Color) -> io::Result<()> {
195 (**self).set_bg(color)
196 }
197 fn write_styled(&mut self, styled: &Styled<dyn Display + '_>) -> io::Result<()> {
198 (**self).write_styled(styled)
199 }
200 fn clear(&mut self, clear_type: ClearType) -> io::Result<()> {
201 (**self).clear(clear_type)
202 }
203 fn size(&self) -> io::Result<Size> {
204 (**self).size()
205 }
206}