ratatui_kit/terminal/
mod.rs1use futures::{StreamExt, stream::BoxStream};
2use ratatui::buffer::Buffer;
3use std::{fmt::Debug, io};
4
5mod cross_terminal;
6pub use cross_terminal::CrossTerminal;
7
8pub trait TerminalImpl: Send {
9 type Event: Clone + Debug;
10 fn event_stream(&mut self) -> io::Result<BoxStream<'static, Self::Event>>;
11 fn received_ctrl_c(event: Self::Event) -> bool;
12 fn draw<F>(&mut self, f: F) -> io::Result<()>
13 where
14 F: FnOnce(&mut ratatui::Frame);
15
16 fn insert_before<F>(&mut self, height: u16, draw_fn: F) -> io::Result<()>
17 where
18 F: FnOnce(&mut Buffer);
19}
20
21pub struct Terminal<T = CrossTerminal>
27where
28 T: TerminalImpl,
29{
30 inner: Box<T>,
31 event_stream: BoxStream<'static, T::Event>,
32}
33
34impl<T> Terminal<T>
35where
36 T: TerminalImpl,
37{
38 pub fn new(inner: T) -> io::Result<Self> {
39 let mut inner = Box::new(inner);
40 Ok(Self {
41 event_stream: inner.event_stream()?,
42 inner,
43 })
44 }
45
46 pub fn draw<F>(&mut self, f: F) -> io::Result<()>
47 where
48 F: FnOnce(&mut ratatui::Frame),
49 {
50 self.inner.draw(f)
51 }
52
53 pub fn insert_before<F>(&mut self, height: u16, draw_fn: F) -> io::Result<()>
54 where
55 F: FnOnce(&mut Buffer),
56 {
57 self.inner.insert_before(height, draw_fn)
58 }
59
60 pub async fn next_event(&mut self) -> Option<T::Event> {
64 self.event_stream.next().await
65 }
66}
67
68#[doc(hidden)]
77pub trait UpdaterTerminal {
78 fn insert_before(
79 &mut self,
80 height: u16,
81 draw_fn: Box<dyn FnOnce(&mut Buffer)>,
82 ) -> io::Result<()>;
83}
84
85impl<T> UpdaterTerminal for Terminal<T>
86where
87 T: TerminalImpl<Event = crossterm::event::Event>,
88{
89 fn insert_before(
90 &mut self,
91 height: u16,
92 draw_fn: Box<dyn FnOnce(&mut Buffer)>,
93 ) -> io::Result<()> {
94 Terminal::insert_before(self, height, draw_fn)
96 }
97}