Skip to content

turbodesk

Terminal user interfaces as pure functions from state to an immutable view tree.

from turbodesk import UI, View, run


def app(ui: UI) -> View:
    count, set_count = ui.state(0)

    ui.on_event(lambda e: set_count(count + 1))

    return View.text(f"pressed {count} times").center(within=ui.size)


run(app)

Your app is a function. It runs again whenever something changes, and returns a picture of what should be on screen. There is no widget tree to keep in sync, because there is nothing kept between frames except the values you asked for by name.

Why you might want this

Rendering is a pure function. app(ui) -> View has no side effects on the screen. You can call it in a test, at any size, and assert on what came out. There is no event loop to start and no snapshot to approve.

from turbodesk.testing import render, to_text
from turbodesk.view import Size

assert "pressed 0 times" in to_text(render(app, size=Size(40, 10)))

A View is a value. It is an immutable grid of styled cells that composes with hcat, vcat and zcat. Two views side by side is a function call.

State is local and explicit. ui.state is a hook keyed by call order, like React's. A widget that needs to remember something asks for it; a widget that does not, does not.

No stylesheet. Styles are Style values in Python. Layout is arithmetic. Two real applications were ported to turbodesk without wanting a layout engine. See the comparison for what that cost and where it hurt.

Why you might not

turbodesk is small on purpose, and that is a real constraint:

  • POSIX only. It uses termios and tty; there is no Windows support.
  • Far fewer widgets than Textual. About twenty, against Textual's several dozen. No tree-with-checkboxes, no tabbed content, no data table with sorting.
  • No CSS, devtools, or web target. To restyle an app without touching Python, or serve it over HTTP, use Textual.
  • Young. Two applications have been ported to it. That is enough to have found real bugs, and not enough to have found all of them.

If you want the largest, most featureful terminal framework in Python, use Textual. turbodesk is for people who want a small core they can hold in their head, and whose UI code is testable without a harness.

Where to go next

The four tabs across the top, in the order most people want them:

  • Getting started: install it and build something.
  • Guides: views, state and input are the model; widgets, modals, Rich, passthrough and testing are the parts.
  • Developers: how the render loop works inside, how to write a component, and what a change has to pass.
  • About: what is stable, and how it compares with Textual, Rich, urwid and prompt_toolkit.