cont/scripts/render_demo.py
2026-09-15 14:15:55 +01:00

75 lines
3.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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()