2 个版本
0.1.1 | 2024 年 3 月 2 日 |
---|---|
0.1.0 | 2024 年 2 月 29 日 |
#2521 in 命令行工具
48 每月下载次数
60KB
1.5K SLoC
tui-window
为 Ratatui 和 Crossterm 提供最简页面和焦点管理器(尽管它也支持 Ratatui 支持的其他后端)。
tui-window
提供一个非常简单的设置,让您可以快速构建简单、基于页面/页面的 TUI(基于文本的用户界面)应用程序。
其灵感来源于 HTML 的工作方式:声明一个小部件树,并由 tui-window 管理应用程序级别的关注点,如 焦点管理、将输入重定向到特定小部件等。
特性
- 声明性地构建 TUI 布局。定义一个组件树,仅在需要精细控制渲染过程时才计算布局。
- 具有观点的焦点管理:计算可聚焦小部件的顺序(例如,按
Tab
键聚焦到下一个元素)。 - 创建“页面”(小部件树集合)并在它们之间轻松导航。
- 支持原生的 Ratatui 小部件。
- 初始化 Ratatui 和 Crossterm 的实用程序,具有开箱即用的恐慌处理。
状态
此库正在积极开发中。请随时提出改进建议(请注意,此库的范围故意很小)。
入门
使用 Cargo 将 tui-window
安装到您的项目中
cargo add tuiwindow
通过实现 Render
构建 few 小部件(用于不接受焦点的组件)或 FocusableRender
(用于应接受焦点的组件)(不需要派生 Default
)
#[derive(Default)]
struct TestWidget {
text_content: String,
}
impl FocusableRender for TestWidget {
fn render(&mut self, render_props: &RenderProps, buff: &mut Buffer, area: Rect) {
if let Some(InputEvent::Key(c)) = render_props.event {
self.text_content.push(c)
}
Paragraph::new(format!(
"Hello world! Focused? {}: {}",
render_props.is_focused, self.text_content
))
.block(
Block::new()
.borders(Borders::all())
.style(if render_props.is_focused {
Style::new().fg(Color::Red)
} else {
Style::new()
}),
)
.wrap(Wrap { trim: false })
.render(area, buff)
}
}
#[derive(Default)]
struct StaticWidget {}
impl Render for StaticWidget {
fn render(&mut self, _render_props: &RenderProps, buff: &mut Buffer, area: Rect) {
Paragraph::new("I'm static")
.block(Block::new().borders(Borders::all()))
.render(area, buff)
}
}
定义您的应用程序结构(您可以设计整个页面)
let mut app = PageCollection::new(vec![
Page::new(
"Page 1", // the page's title
'1', // a shortcut for navigating to this page
row_widget!( // macro for evenly-distributing your widgets in rows
SlowWidget::default(),
column_widget!(StaticWidget {}, TestWidget::default())
),
),
Page::new(
"Page 2",
'2',
column_widget!( // macro for evenly-distributing your widgets in
AnotherWidget::default(), //columns
column_widget!(StaticWidget {}, TestWidget::default())
),
)
.with_style(Style::default().bg(Color::White).fg(Color::Black)),
]);
在您的 main
函数中将所有内容组合在一起,使用提供的辅助程序 TuiCrossterm
设置渲染
fn main() -> Result<(), Box<dyn Error>> {
let mut tui = TuiCrossterm::new()?;
let terminal = tui.setup()?;
// define the collection of pages:
let mut app = PageCollection::new(vec![
Page::new(
"Page 1",
'1',
row_widget!(
SlowWidget::default(),
column_widget!(StaticWidget {}, TestWidget::default())
),
),
Page::new(
"Page 2",
'2',
column_widget!(
AnotherWidget::default(),
column_widget!(StaticWidget {}, TestWidget::default())
),
)
.with_style(Style::default().bg(Color::White).fg(Color::Black)),
]);
let mut window = Window::new(&app, |ev| match ev {
// define the termination condition for the app:
tuiwindow::core::InputEvent::Key(c) => *c == 'q',
_ => false,
});
while !window.is_finished() {
terminal.draw(|f| {
let area = f.size();
let buff = f.buffer_mut();
let mut second_buff = buff.clone();
// draw
window.render::<DefaultEventMapper>(&mut app, &mut second_buff, area);
buff.merge(&second_buff);
})?;
}
Ok(())
}
依赖关系
~6–12MB
~120K SLoC