Print styled output
Replace print() one call at a time. Auto-detects TTY.
from painted import Block, Style, print_block
block = Block.text("deploy OK", Style(fg="green", bold=True))
print_block(block)
Compose
Blocks are immutable rectangles. Compose them with functions.
from painted import border, join_vertical, ROUNDED
header = Block.text(" api-gateway ", Style(bold=True, reverse=True))
status = join_vertical(
Block.text(" replicas: 2/3 ready", Style(fg="yellow")),
Block.text(" /health: 200 12ms", Style(fg="green")),
)
card = border(join_vertical(header, status), chars=ROUNDED)
print_block(card)
CLI harness
One render function, three output modes.
from painted import run_cli, CliContext, Block
def render(ctx: CliContext, data: dict) -> Block:
... # your render logic
def fetch() -> dict:
return {"status": "ok", "replicas": 3}
run_cli(sys.argv[1:], render=render, fetch=fetch)
myapp # auto-detect
myapp -q # quiet
myapp -v # verbose
myapp -i # interactive TUI
myapp --json # JSON output
myapp | grep ok # plain text, no ANSI
Full TUI
Alt screen, keyboard input, diff-flush render loop.
import asyncio
from painted import Block, Style, border
from painted.tui import Surface
class MyApp(Surface):
def render(self):
block = Block.text("Hello!", Style(fg="green"))
border(block, title="Demo").paint(self._buf)
def on_key(self, key: str):
if key == "q":
self.quit()
asyncio.run(MyApp().run())
$ pip install painted
One dependency: wcwidth