Metadata-Version: 2.4
Name: termopy
Version: 0.2.0
Summary: Terminal UIs as pure functions from state to an immutable view tree
Keywords: terminal,tui,console,immediate-mode,widgets,ansi,curses
License-Expression: Apache-2.0
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: POSIX
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: User Interfaces
Classifier: Topic :: Terminals
Classifier: Typing :: Typed
Requires-Dist: rich>=13.0
Requires-Dist: pygments>=2.0 ; extra == 'syntax'
Requires-Python: >=3.12
Project-URL: Homepage, https://termopy.lab.abilian.com
Project-URL: Documentation, https://termopy.lab.abilian.com
Provides-Extra: syntax
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    # 19 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 one.py two.py    # a vi clone, built on the core alone
python examples/turbo_python        # Turbo Pascal 7.0's IDE, for Python
python examples/frogmouth README.md # a Markdown browser, ported from Textual
```

One dependency ([Rich](https://rich.readthedocs.io/), for glyph-width measurement and for drawing Rich renderables into a view), Python 3.12+, POSIX only.

Version 0.2. [What is stable](https://termopy.lab.abilian.com/stability/) says which parts of the API are safe to build on now and which are still moving.

## What's here

- `src/termopy/`: the core — views, styles, events, terminal, render loop, themes, layout arithmetic, overlapping windows, a command table, key naming, syntax spans, Markdown, ANSI parsing, clipboard
- `src/termopy/widgets/`: dialogs, button, checkbox, radio set, selection list, textbox, listbox, table, tabs, progress bar, spinner, rule, border, frame, scroller, tree, directory tree, menu bar, status line, charts, editor, ncdu, tmux pane
- `examples/`: all 17 bonsai_term examples, ported and running, plus demos, a vi clone, a Markdown browser and a Turbo Pascal IDE. **[Start here](examples/README.md)**, inventory, API and design notes.
- **[COMPONENTS.md](notes/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          # 2,401 — pure functions, no I/O, under a second
uv run pytest -m integration   #   598 — widgets and apps through a UI
uv run pytest -m e2e           #    10 — 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, and the pure
│                    halves of the two applications: vi's grammar, the IDE's
│                    ast walks, its debugger state and its settings files
├── b_integration/   the runtime, widgets, dialogs, every example, all three apps
├── c_e2e/           pty-driven: alternate screen, keys, vi saving, a modal, and
│                    the IDE editing, compiling and running a program
└── conftest.py      ui / render / screen / scratch_data_dir fixtures
```
