11 个版本
0.3.2 | 2022 年 4 月 22 日 |
---|---|
0.3.1 | 2022 年 4 月 10 日 |
0.2.0 | 2021 年 10 月 24 日 |
0.1.6 | 2021 年 5 月 1 日 |
0.1.3 | 2020 年 7 月 26 日 |
#299 在 命令行界面
56 每月下载量
在 2 crates 中使用
150KB
3.5K SLoC
Zi 是一个用于构建现代终端用户界面的库。
Zi 中的用户界面是以有状态的组件树的形式构建的。组件可以让您将 UI 划分为独立的、可重用的部分,并独立考虑每个部分。
App
运行时会跟踪组件的挂载、更新以及最终删除,并且只对需要重新渲染的已更改的 UI 组件调用 view()
。位于组件之下的终端后端将只增量重新绘制屏幕上已更改的部分。
基本示例
以下是一个 Zi 应用程序的完整示例,它实现了一个计数器。它应该提供了一个很好的示例,说明了不同的 Component
方法以及它们是如何结合在一起的。
一个包含样式的稍微复杂版本的示例可以在 examples/counter.rs
中找到。
熟悉 Yew、Elm 或 React + Redux 的人应该熟悉所有高级概念。此外,某些类型和函数的名称与 Yew
中的一致。
use zi::{
components::{
border::{Border, BorderProperties},
text::{Text, TextAlign, TextProperties},
},
prelude::*,
};
use zi_term::Result;
// Message type handled by the `Counter` component.
enum Message {
Increment,
Decrement,
}
// The `Counter` component.
struct Counter {
// The state of the component -- the current value of the counter.
count: usize,
// A `ComponentLink` allows us to send messages to the component in reaction
// to user input as well as to gracefully exit.
link: ComponentLink<Self>,
}
// Components implement the `Component` trait and are the building blocks of the
// UI in Zi. The trait describes stateful components and their lifecycle.
impl Component for Counter {
// Messages are used to make components dynamic and interactive. For simple
// or pure components, this will be `()`. Complex, stateful components will
// typically use an enum to declare multiple Message types. In this case, we
// will emit two kinds of message (`Increment` or `Decrement`) in reaction
// to user input.
type Message = Message;
// Properties are the inputs to a Component passed in by their parent.
type Properties = ();
// Creates ("mounts") a new `Counter` component.
fn create(
_properties: Self::Properties,
_frame: Rect,
link: ComponentLink<Self>,
) -> Self {
Self { count: 0, link }
}
// Returns the current visual layout of the component.
// - The `Border` component wraps a component and draws a border around it.
// - The `Text` component displays some text.
fn view(&self) -> Layout {
Border::with(BorderProperties::new(Text::with(
TextProperties::new()
.align(TextAlign::Centre)
.content(format!("Counter: {}", self.count)),
)))
}
// Components handle messages in their `update` method and commonly use this
// method to update their state and (optionally) re-render themselves.
fn update(&mut self, message: Self::Message) -> ShouldRender {
self.count = match message {
Message::Increment => self.count.saturating_add(1),
Message::Decrement => self.count.saturating_sub(1),
};
ShouldRender::Yes
}
// Updates the key bindings of the component.
//
// This method will be called after the component lifecycle methods. It is
// used to specify how to react in response to keyboard events, typically
// by sending a message.
fn bindings(&self, bindings: &mut Bindings<Self>) {
// If we already initialised the bindings, nothing to do -- they never
// change in this example
if !bindings.is_empty() {
return;
}
// Set focus to `true` in order to react to key presses
bindings.set_focus(true);
// Increment
bindings.add("increment", [Key::Char('+')], || Message::Increment);
bindings.add("increment", [Key::Char('=')], || Message::Increment);
// Decrement
bindings.add("decrement", [Key::Char('-')], || Message::Decrement);
// Exit
bindings.add("exit", [Key::Ctrl('c')], |this: &Self| this.link.exit());
bindings.add("exit", [Key::Esc], |this: &Self| this.link.exit());
}
}
fn main() -> zi_term::Result<()> {
zi_term::incremental()?.run_event_loop(Counter::with(()))
}
更多示例可以在 Git 仓库的 examples
目录中找到。
许可协议
该项目受以下任一协议的许可:
- Apache 许可证 2.0 版 (LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
任选其一。
贡献
除非您明确说明,否则根据Apache-2.0许可证定义的,您有意提交的任何贡献,应双授权如上所述,不附加任何其他条款或条件。
依赖项
~2.5MB
~39K SLoC