1use anyhow::Result;
4use crossterm::event::{DisableMouseCapture, EnableMouseCapture};
5use crossterm::execute;
6use crossterm::terminal::{
7 disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen,
8};
9use ratatui::backend::CrosstermBackend;
10use ratatui::Terminal;
11
12#[derive(Debug, Clone, Copy, Default)]
14pub struct RuntimeOptions {
15 pub bracketed_paste: bool,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum LoopControl {
21 Continue,
22 Break,
23}
24
25pub struct TuiSession {
27 terminal: Terminal<CrosstermBackend<std::io::Stdout>>,
28 options: RuntimeOptions,
29}
30
31impl TuiSession {
32 pub fn enter(options: RuntimeOptions) -> Result<Self> {
33 enable_raw_mode()?;
34 let mut stdout = std::io::stdout();
35 if options.bracketed_paste {
36 execute!(
37 stdout,
38 EnterAlternateScreen,
39 EnableMouseCapture,
40 crossterm::event::EnableBracketedPaste
41 )?;
42 } else {
43 execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
44 }
45 let backend = CrosstermBackend::new(stdout);
46 let terminal = Terminal::new(backend)?;
47 Ok(Self { terminal, options })
48 }
49
50 pub fn terminal_mut(&mut self) -> &mut Terminal<CrosstermBackend<std::io::Stdout>> {
51 &mut self.terminal
52 }
53
54 pub fn leave(mut self) -> Result<()> {
55 disable_raw_mode()?;
56 if self.options.bracketed_paste {
57 execute!(
58 self.terminal.backend_mut(),
59 crossterm::event::DisableBracketedPaste,
60 LeaveAlternateScreen,
61 DisableMouseCapture
62 )?;
63 } else {
64 execute!(
65 self.terminal.backend_mut(),
66 LeaveAlternateScreen,
67 DisableMouseCapture
68 )?;
69 }
70 self.terminal.show_cursor()?;
71 Ok(())
72 }
73}