Skip to content
This repository has been archived by the owner on May 11, 2023. It is now read-only.

terminal-tui: library w/ tui-realm #171

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

erak
Copy link
Contributor

@erak erak commented Jul 8, 2022

Description

This PR introduces a thin layer on top of tui-realm and provides some common components that can be re-used across multiple TUI applications in the Radicle project.

It's meant to be an alternative implementation of #151, providing the same functionality, but being based on an exising library instead of an own solution / library.

Motivation

After building a few smaller prototypes (e.g. #147) based on #151, it turned out to have some shortcomings:

  • input handling is global which leads to large(r) state machines updating application state
  • components / widgets hard to re-use / compose because of application state's global nature and little separation of concerns:
    • property-store can be accessed from everywhere, making it hard to enforce a certain design of components (API only defined by string-based properties instead of e.g. traits)
    • do not separate properties used while drawing / and properties reflecting application state
  • no focus system, global state needs to be queried in order to select target component of user input

Some research on how to solve these shortcomings led to the discovery of tui-realm. Since tui-realm makes use of some concepts that were also considered (or even partially used) while developing the initial TUI library (input subscriptions), it seemed to make sense to use tui-realm instead in order to save the effort of implementing and maintaining our own library.

tui-realm

The library follows an Elm / React inspired design approach that solves the shortcomings mentioned above:

  • input-handling is local to components and can be composed using the built-in messaging system
  • separation of concerns in components: properties for drawing, states (w/ update traits) for input handling
  • focus system for components (w/ subscriptions)
  • standard library that implements tui-realm components for almost every tui-rs component
  • interesting components such as radio buttons / checkboxes
  • very good documentation

What should be added next?

  • Themes
  • Support for user-defined key-bindings

@erak erak mentioned this pull request Jul 8, 2022
@erak erak marked this pull request as ready for review July 20, 2022 19:42
@erak erak requested a review from cloudhead as a code owner July 20, 2022 19:43
@cloudhead
Copy link
Contributor

Nice, makes sense!

{
/// Returns the tui-realm application held by this tui-application.
/// Used to poll new events in main loop.
fn app(&mut self) -> &mut Application<Id, Message, NoUserEvent>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaks the abstraction?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've now added wrapper functions to the base App such that client applications do not need to know about the tuirealm::Applicaiton anymore.

/// aligned and separated by a divider.
pub struct Tabs {
props: Props,
pub states: TabsState,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

selected: usize
len: usize

self.tabs = Tabs::default().spans(&titles);
self
}
}
Copy link
Contributor

@cloudhead cloudhead Oct 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tabbed_ui
   .child("comments", CommentComponent::new())
   .child("issues", IssueComponent::new())

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took this into account in the rework.

pub enum TabId {
Welcome,
List,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TabContainer::child(title: impl ToString, ...)
impl Display for TabId

container.child(TabId::Welcome, WelcomeScreen::new())

.borders(Borders::default().sides(BorderSides::NONE))
.text_rows(&welcome),
),
),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

child(child: impl MockComponent) { Box::new(child) }

}) => return Some(Message::Quit),
_ => CmdResult::None,
};
Some(Message::None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

/// List of items that keeps track of the selection.
pub struct Items<T> {
values: Vec<T>,
index: usize,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

selected: usize

@erak erak force-pushed the erak/terminal-tui-realm branch 2 times, most recently from 3e056dc to 076d15c Compare November 6, 2022 09:48
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants