cont/scripts/render_demo.py

76 lines
3.4 KiB
Python
Raw Normal View History

2026-09-15 13:13:22 +00:00
#!/usr/bin/env python3
"""Render the real Ratatui layout with fictional sessions. Never reads user history.
uv run --with 'pillow==11.3.0' python scripts/render_demo.py
Use --font /path/to/monospace.ttf to override the locally available font.
The font is rasterized into the PNG, not bundled or redistributed.
"""
import argparse
import json
from pathlib import Path
import subprocess
from PIL import Image, ImageDraw, ImageFont
ROOT = Path(__file__).resolve().parents[1]
PALETTE = {
"Black": "#11151e", "White": "#eef2fa", "DarkGray": "#7c879d",
"Gray": "#b8c1d4", "Cyan": "#65d9df", "Magenta": "#b89cff",
"Yellow": "#edbd80", "Green": "#9bd39f", "Blue": "#8fb9ff",
"LightMagenta": "#e2a1dc",
}
BG = "#11151e"
FG = "#dbe2ef"
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--font", type=Path)
args = parser.parse_args()
candidates = [args.font, Path("/System/Library/Fonts/Menlo.ttc"),
Path("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf")]
font_path = next((p for p in candidates if p and p.is_file()), None)
if not font_path:
parser.error("Provide a monospace font using --font")
font = ImageFont.truetype(str(font_path), 28)
small = ImageFont.truetype(str(font_path), 23)
subprocess.run(["cargo", "test", "--locked", "--release", "ui::demo::render_demo",
"--", "--ignored", "--exact"], cwd=ROOT, check=True)
data = json.loads((ROOT / "target/demo-screen.json").read_text())
columns, rows = data["width"], data["height"]
cell_w, cell_h = round(font.getlength("M")), 42
margin, padding, chrome = 48, 32, 78
window_w = columns * cell_w + padding * 2
window_h = rows * cell_h + padding * 2 + chrome
image = Image.new("RGB", (window_w + margin * 2, window_h + margin * 2), "#090c13")
draw = ImageDraw.Draw(image)
box = (margin, margin, margin + window_w, margin + window_h)
draw.rounded_rectangle(box, radius=22, fill=BG, outline="#2b3344", width=2)
for i, color in enumerate(["#ef7474", "#e6be68", "#83c995"]):
x, y = margin + 32 + i * 31, margin + 35
draw.ellipse((x, y - 9, x + 18, y + 9), fill=color)
title = "cont — one picker, five agents"
draw.text((image.width / 2, margin + 35), title, font=small, fill="#929db3", anchor="mm")
draw.line((margin + 1, margin + chrome, margin + window_w - 1, margin + chrome), fill="#252c3c", width=2)
left, top = margin + padding, margin + chrome + padding
for i, cell in enumerate(data["cells"]):
x, y = left + (i % columns) * cell_w, top + (i // columns) * cell_h
# ANSI colors are terminal-theme dependent. Use a readable dark palette;
# selection background is a darker rendition of the terminal's gray.
bg = "#303b50" if cell["bg"] == "DarkGray" else PALETTE.get(cell["bg"], BG)
fg = PALETTE.get(cell["fg"], FG)
if bg != BG:
draw.rectangle((x, y, x + cell_w - 1, y + cell_h - 1), fill=bg)
if cell["text"].strip():
draw.text((x, y + cell_h / 2), cell["text"], font=font, fill=fg, anchor="lm",
stroke_width=1 if cell["bold"] else 0)
destination = ROOT / "docs/assets/resume.png"
destination.parent.mkdir(parents=True, exist_ok=True)
image.save(destination, optimize=True)
print(f"Wrote {destination.relative_to(ROOT)} ({image.width}×{image.height}); all session data is fictional.")
if __name__ == "__main__":
main()