Metadata-Version: 2.4
Name: termopy
Version: 0.1.0
Summary: Terminal UIs as pure functions from state to an immutable view tree
License-Expression: Apache-2.0
Requires-Dist: rich>=13.0
Requires-Python: >=3.12
Project-URL: Homepage, https://termopy.lab.abilian.com
Project-URL: Documentation, https://termopy.lab.abilian.com
Description-Content-Type: text/markdown

# termopy

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

```python
from termopy import View, run

def app(ui):
    return View.text("Hello world!").center(within=ui.size)

run(app)
```

An app is a function `(UI) -> View`. It re-runs whenever a frame is marked dirty (state changed, an event arrived, the terminal resized, a timer fired), and the renderer diffs by row before writing escape codes. State lives in hooks on the `ui` handle.

```sh
uv sync            # or: pip install -e .
python examples/hello_world.py
python examples/theme_gallery.py         # 18 colour flavours, ← → to browse
python examples/charts.py                # line, scatter and bar charts
python examples/focus.py                 # three key-hungry widgets, one keyboard
python examples/filter.py                # type to filter a list
python examples/logs.py                  # colourised output, tail -f style
python examples/embed.py htop            # another TUI, embedded (needs tmux)
python examples/vi somefile.py           # a vi clone, built on the core alone
python examples/frogmouth README.md      # a Markdown browser, ported from Textual
```

No dependencies, Python 3.12+.

## What's here

- `src/termopy/`: the core, views, styles, events, terminal, render loop, themes, Markdown, ANSI parsing, clipboard
- `src/termopy/widgets/`: dialogs, button, checkbox, textbox, listbox, tabs, progress bar, spinner, border, scroller, tree, charts, editor, ncdu, tmux pane
- `examples/`: all 17 bonsai_term examples, ported and running, plus demos, a vi clone and a Markdown browser. **[Start here](examples/README.md)**, inventory, API and design notes.
- **[COMPONENTS.md](COMPONENTS.md)**: the bonsai_term_components port, what moved, what changed shape, what was left out.

## Documentation

```bash
make docs-serve      # live reload
make docs            # build to docs/site/
make docs-check      # strict: a broken cross-reference fails the build
```

The docs are their own project under `docs/`, with their own Makefile (`cd docs && make`
works too).

Built with [Zensical](https://pypi.org/project/zensical/). `docs/` has a guide, a
comparison with Textual and other frameworks grounded in two real ports, and notes on
the internals.

## Tests

A pyramid, run with `make test` or `uv run pytest`:

```sh
uv run pytest -m unit          # 286 — pure functions, no I/O, 0.3s
uv run pytest -m integration   # 127 — widgets and apps through a UI
uv run pytest -m e2e           #   7 — real programs on a pty
uv run pytest -m "not slow"    # skips the pty and tmux tests
```

```
tests/
├── a_unit/          views, styles, events, markdown, typography, vi's pure core
├── b_integration/   the runtime, widgets, dialogs, every example, both apps
├── c_e2e/           pty-driven: alternate screen, keys, vi saving, a modal
└── conftest.py      ui / render / screen / scratch_data_dir fixtures
```
