ratatui_kit/terminal/
cross_terminal.rs

1use super::TerminalImpl;
2use crossterm::event::{self, EventStream};
3use futures::{StreamExt, stream::BoxStream};
4use ratatui::{Frame, TerminalOptions};
5use std::io::{self};
6
7// ================== 终端核心功能实现 ==================
8
9// 跨平台终端结构体
10// input_is_terminal: 标记标准输入是否为终端设备
11// dest: 标准输出流(用于终端操作)
12// raw_mode_enabled: 原始模式启用状态
13// enabled_keyboard_enhancement: 键盘增强功能状态
14// fullscreen: 是否启用全屏模式
15pub struct CrossTerminal {
16    terminal: ratatui::DefaultTerminal,
17}
18
19impl CrossTerminal {
20    // 创建终端实例
21    // fullscreen: 是否启用备用屏幕(全屏模式)
22    pub fn new() -> io::Result<Self> {
23        Ok(Self {
24            terminal: ratatui::init(),
25        })
26    }
27
28    // 启用/禁用原始模式
29    pub fn with_options(options: TerminalOptions) -> io::Result<Self> {
30        Ok(Self {
31            terminal: ratatui::init_with_options(options),
32        })
33    }
34}
35
36// ================== 生命周期管理 ==================
37
38impl Drop for CrossTerminal {
39    // 析构函数:自动恢复终端原始状态
40    fn drop(&mut self) {
41        ratatui::restore();
42    }
43}
44
45// ================== 终端接口实现 ==================
46
47impl TerminalImpl for CrossTerminal {
48    type Event = event::Event;
49
50    // 创建事件流
51    fn event_stream(&mut self) -> io::Result<BoxStream<'static, Self::Event>> {
52        // 创建事件流并过滤错误
53        Ok(EventStream::new()
54            .filter_map(|event| async move { event.ok() })
55            .boxed())
56    }
57
58    // 检测Ctrl+C组合键
59    fn received_ctrl_c(event: Self::Event) -> bool {
60        matches!(
61            event,
62            event::Event::Key(event::KeyEvent {
63                code: event::KeyCode::Char('c'),
64                modifiers: event::KeyModifiers::CONTROL,
65                kind: event::KeyEventKind::Press,
66                ..
67            })
68        )
69    }
70
71    fn draw<F>(&mut self, f: F) -> io::Result<()>
72    where
73        F: FnOnce(&mut Frame),
74    {
75        self.terminal.draw(f)?;
76        Ok(())
77    }
78
79    fn insert_before<F>(&mut self, height: u16, draw_fn: F) -> io::Result<()>
80    where
81        F: FnOnce(&mut ratatui::prelude::Buffer),
82    {
83        self.terminal.insert_before(height, draw_fn)?;
84        Ok(())
85    }
86}