[][src]Crate zi

Zi is a library for building modern terminal user interfaces.

A user interface in Zi is built as a tree of stateful components. Components let you split the UI into independent, reusable pieces, and think about each piece in isolation.

The App runtime keeps track of components as they are mounted, updated and eventually removed and only calls view() on those UI components that have changed and have to be re-rendered. Lower level and independent of the components, the terminal frontend will incrementally redraw only those parts of the screen that have changed.

A Basic Example

The following is a complete example of a Zi application which implements a counter. It should provide a good sample of the different Component methods and how they fit together.

Anyone familiar with Yew, Elm or React + Redux should be familiar with all the high-level concepts. Moreover, the names of some types and functions are the same as in Yew.

use zi::{
    components::{
        border::{Border, BorderProperties},
        text::{Text, TextAlign, TextProperties},
    },
    prelude::*,
};

// 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 ones 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.
    fn view(&self) -> Layout {
        layout::component::<Border>(
            BorderProperties::new(layout::component::<Text>(
                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
    }

    // Whether the component is currently focused which will caused
    // `input_binding` to be called on user input.
    fn has_focus(&self) -> bool {
        true
    }

    // Send messages in reaction to user input.
    fn input_binding(&self, pressed: &[Key]) -> BindingMatch<Self::Message> {
        BindingMatch::clear(match pressed {
            &[Key::Char('+')]  => Some(Message::Increment),
            &[Key::Char('-')] => Some(Message::Decrement),
            &[Key::Esc] => {
                self.link.exit();
                None
            }
            _ => None,
        })
    }
}

fn main() -> zi::Result<()> {
    let mut app = App::new(layout::component::<Counter>(()));
    app.run_event_loop(zi::frontend::default()?)
}

More examples can be found in the examples directory of the git repository.

Re-exports

pub use terminal::Position;
pub use terminal::Rect;
pub use terminal::Size;

Modules

components

A collection of reusable components useful as building blocks.

frontend

This module contains the Frontend trait and provided implementations.

layout

The Layout type and flexbox-like utilities for laying out components.

prelude

The Zi prelude.

terminal

An abstract specification of a lightweight terminal.

Structs

App

The App application runtime, which runs the event loop and draws your components.

BindingMatch
Callback

Callback wrapper. Useful for passing callbacks in child components Properties. An Rc wrapper is used to make it cloneable.

Canvas

A lightweight abstract terminal. All components in Zi ultimately draw to a Canvas, typically via their child components or directly in the case of lower level components.

Colour

An RGB encoded colour, 1-byte per channel.

ComponentLink

A context for sending messages to a component or the runtime.

Item

An item inside a container.

Layout

A layout tree.

Style

Specifies how content should be styled. This represents a subset of the ANSI available styles which is widely supported by terminal emulators.

Enums

BindingTransition
Error

A representation of a runtime error encountered by Zi.

FlexBasis

Enum to control the size of an item inside a container.

FlexDirection

Enum to control how items are placed in a container. It defines the main axis and the direction (normal or reversed).

Key
ShouldRender

Type to indicate whether a component should be rendered again.

Traits

Component

Components are the building blocks of the UI in Zi.

Functions

auto

Creates an item that will share the available space equally with other sibling items with FlexBasis::auto.

column

Creates a container with vertical layout. Child components are laid out from top to bottom. Pass in the children as an array of items.

component

Create a component definition from Properties.

container

Creates a container from an array of items.

fixed

Creates an item that will have a fixed size.

row

Creates a container with horizontal layout. Child components are laid out from left to right. Pass in the children as an array of items.

Type Definitions

Background

Type alias for background colours.

Foreground

Type alias for foreground colours.

Result