Files
MeshTerm/scripts/cardputer/fetch-terminus.py
T
Jean-Pierre MartineauandClaude Opus 5.5 b3bf5a6160 The Cardputer Zero gets a console host, and a desktop simulator built on it
The stock image gives an app no text console, so MeshTerm draws its own: the TUI
runs in-process with prompt_toolkit's output feeding a small VT parser, the cells
are drawn in Terminus 6x12 with MeshTerm's marks over it, and keys go in through a
pipe in xterm's spelling. The front end is the only part that differs: framebuffer
and evdev on the device (written ahead of the hardware), a Tk window on the desktop.

Each handheld's glyph inventory is now named by Platform.font, which replaces
ascii_fold; the render-boundary fold derives its accents, emoji, and fallback from
that inventory and quantizes colour only where truecolor is off.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 21:08:30 -04:00

75 lines
2.7 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Fetch the Terminus 12-pixel BDF fonts the Cardputer console host draws in.
Terminus is licensed under the SIL Open Font License, so MeshTerm never ships it: this
downloads the upstream release, checks it is the archive it should be, and extracts
``ter-u12n.bdf``, ``ter-u12b.bdf`` and the licence beside them into the directory the host
reads (``$MESHTERM_HOST_FONTS``, else ``fonts`` under the MeshTerm config directory).
Run it once on a machine that will run the host or its desktop simulator:
python scripts/cardputer/fetch-terminus.py
Where Python can't fetch it (a certificate store that rejects the mirror), download the
archive any other way and hand it over; it is checked against the same digest:
python scripts/cardputer/fetch-terminus.py --archive terminus-font-4.49.1.tar.gz
"""
from __future__ import annotations
import hashlib
import io
import sys
import tarfile
import urllib.request
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
from meshterm.host.font import BOLD_BDF, REGULAR_BDF, font_dir # noqa: E402
URL = (
"https://sourceforge.net/projects/terminus-font/files/terminus-font-4.49/"
"terminus-font-4.49.1.tar.gz/download"
)
#: The release archive's SHA-256, so a mirror can't hand back something else.
SHA256 = "d961c1b781627bf417f9b340693d64fc219e0113ad3a3af1a3424c7aa373ef79"
ROOT = "terminus-font-4.49.1/"
WANTED = (REGULAR_BDF, BOLD_BDF, "OFL.TXT")
def main(argv: list[str]) -> int:
"""Fetch (or take) the archive, verify it, and extract the fonts and their licence."""
target = font_dir()
if argv[:1] == ["--archive"] and len(argv) == 2:
print(f"installing Terminus 4.49.1 from {argv[1]} into {target}")
data = Path(argv[1]).read_bytes()
elif not argv:
print(f"fetching Terminus 4.49.1 into {target}")
with urllib.request.urlopen(URL, timeout=60) as response:
data = response.read()
else:
print(__doc__)
return 2
digest = hashlib.sha256(data).hexdigest()
if digest != SHA256:
print(f"refusing the download: sha256 {digest} is not the release's {SHA256}")
return 1
target.mkdir(parents=True, exist_ok=True)
with tarfile.open(fileobj=io.BytesIO(data), mode="r:gz") as archive:
for name in WANTED:
member = archive.extractfile(ROOT + name)
if member is None:
print(f"the archive has no {name}")
return 1
(target / name).write_bytes(member.read())
print(f" {name}")
print("done")
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))