leetcode_tui_shared/
tui.rs1use crossterm::terminal::WindowSize;
2use crossterm::{
3 cursor,
4 terminal::{EnterAlternateScreen, LeaveAlternateScreen},
5};
6use std::mem;
7use std::{
8 io::Stdout,
9 ops::{Deref, DerefMut},
10};
11
12use color_eyre::eyre::Result;
13use ratatui::{prelude::CrosstermBackend as Backend, Terminal};
14
15pub type Frame<'a> = ratatui::Frame<'a>;
16
17pub struct Term {
18 pub terminal: Terminal<Backend<Stdout>>,
19}
20
21impl Term {
22 pub fn start() -> Result<Self> {
23 let terminal = Terminal::new(Backend::new(std::io::stdout()))?;
24 let mut term = Self { terminal };
25 term.enter()?;
26 Ok(term)
27 }
28
29 pub fn enter(&mut self) -> Result<()> {
30 crossterm::terminal::enable_raw_mode()?;
31 crossterm::execute!(std::io::stdout(), EnterAlternateScreen, cursor::Hide)?;
32 Ok(())
33 }
34
35 pub fn exit(&mut self) -> Result<()> {
36 if crossterm::terminal::is_raw_mode_enabled()? {
37 self.flush()?;
38 crossterm::execute!(std::io::stdout(), LeaveAlternateScreen, cursor::Show)?;
39 crossterm::terminal::disable_raw_mode()?;
40 }
41 Ok(())
42 }
43
44 pub fn suspend(&mut self) -> Result<()> {
45 self.exit()?;
46 Ok(())
47 }
48
49 pub fn resume(&mut self) -> Result<()> {
50 self.enter()?;
51 let size = self.size()?;
52 self.resize(ratatui::layout::Rect {
53 x: 0,
54 y: 0,
55 width: size.width,
56 height: size.height,
57 })?;
58 Ok(())
59 }
60
61 pub fn size() -> WindowSize {
62 let mut size = WindowSize {
63 rows: 0,
64 columns: 0,
65 width: 0,
66 height: 0,
67 };
68 if let Ok(s) = crossterm::terminal::window_size() {
69 let _ = mem::replace(&mut size, s);
70 }
71
72 if size.rows == 0 || size.columns == 0 {
73 if let Ok(s) = crossterm::terminal::size() {
74 size.columns = s.0;
75 size.rows = s.1;
76 }
77 }
78
79 size
83 }
84}
85
86impl Deref for Term {
87 type Target = ratatui::Terminal<Backend<std::io::Stdout>>;
88
89 fn deref(&self) -> &Self::Target {
90 &self.terminal
91 }
92}
93
94impl DerefMut for Term {
95 fn deref_mut(&mut self) -> &mut Self::Target {
96 &mut self.terminal
97 }
98}
99
100impl Drop for Term {
101 fn drop(&mut self) {
102 self.exit().unwrap();
103 }
104}