Updated splash screen (ANSI art, CP437)

This commit is contained in:
Jean-Pierre Martineau committed 2026-08-25 01:47:52 -04:00
1 parent eb8ecb46c8
commit fae342c2bd
3 files changed
+64 -15

No files matched your search

Binary file not shown.
+44 -2
View File
@@ -48,6 +48,15 @@ _VARIANTS: tuple[str, ...] = ("logo.ans", "logo_53.ans")
#: a row only ever has to carry a *colour* across the seam — never a cursor move.
_SGR = re.compile(r"\x1b\[[0-9;]*m")
#: A foreground on the dim bank, said without a word about intensity. Bold *is* brightness
#: on the PicoCalc console, so a bare one inherits whatever the span before it left set and
#: lands a bank too high — the theme's own styles state their intent for the same reason.
_DIM_FG = re.compile(r"3[0-7]")
#: Parameters that settle the intensity question themselves, so a span carrying one needs
#: no help: a reset, bold, faint, or an explicit return to normal.
_SAYS_INTENSITY = frozenset({"", "0", "1", "2", "22"})
#: SAUCE rides on the end of an art file behind DOS's end-of-file mark: 128 bytes naming
#: the author, the canvas and the font. None of it is meant to reach the screen.
_EOF_MARK = b"\x1a"
@@ -121,6 +130,39 @@ def _rewrap(line: str, width: int) -> list[str]:
return rows
def _state_intensity(row: str) -> str:
"""Rewrite the row's colour changes so every one says whether it is bright.
An art editor spells brightness the DOS way — ``1m`` lifts the bank and each span after
it inherits that — which reads correctly only while the escapes stay one unbroken
stream. They don't here: a row is handed to Rich on its own, and the console draws bold
*as* the bright bank, so a span that never mentions intensity is read against whatever
happened to be set. Saying it outright changes no colour; it just stops one drifting.
"""
out: list[str] = []
bright = False
at = 0
while at < len(row):
found = _SGR.match(row, at)
if not found:
out.append(row[at])
at += 1
continue
params = found.group()[2:-1]
parts = params.split(";") if params else [""]
for part in parts: # what this sequence leaves the intensity set to
if part in ("", "0", "22"):
bright = False
elif part == "1":
bright = True
if any(_DIM_FG.fullmatch(p) for p in parts) and not any(p in _SAYS_INTENSITY for p in parts):
out.append("\x1b[" + ";".join(["1" if bright else "22"] + parts) + "m")
else:
out.append(found.group())
at = found.end()
return "".join(out)
def _rows(name: str) -> list[str]:
"""The named mark's rows, or ``[]`` when it can't be read."""
try:
@@ -133,8 +175,8 @@ def _rows(name: str) -> list[str]:
if lines and lines[-1] == "": # drop the trailing newline's empty row
lines.pop()
if width:
return [row for line in lines for row in _rewrap(line, width)]
return lines
lines = [row for line in lines for row in _rewrap(line, width)]
return [_state_intensity(row) for row in lines]
def logo_width(rows: list[str]) -> int:
+20 -13
View File
@@ -375,14 +375,16 @@ def test_specimen_renders_clean_on_picocalc() -> None:
assert ord(ch) in FONT_CODEPOINTS, f"line {i} char {ch!r} outside the font"
def test_narrow_wordmark_keeps_its_dim_row_off_the_bright_bank() -> None:
"""Every span of the wordmark's dim-slot row states its intensity.
def test_narrow_wordmark_keeps_its_dim_rows_off_the_bright_bank() -> None:
"""Every dim-bank span of the wordmark states its own intensity.
The mark alternates letter blocks with slate bevels, so a row painted on the dim bank
is a run of ``3N`` spans each following a ``90``. Bare, they inherit the console's
intensity bit and half the row renders a bank too bright — the narrow mark's fourth
row came out part red (slot 1), part light red (slot 9), split at every span that
followed a bevel.
An art editor spells brightness the DOS way — a ``1m`` lifts the bank and every span
after it inherits that — which only reads correctly while the escapes stay one unbroken
stream. A row reaches the console on its own, and bold *is* the bright bank there, so a
span that never mentions intensity is read against whatever happened to be set: the
narrow mark's letter row came out part red (slot 1), part light red (slot 9), splitting
at every span that followed a bevel. The art is redrawn from time to time, so this
pins the rule rather than the picture — no row index, no particular colour.
"""
from meshterm.ui.logo import load_logo
from meshterm.ui.tui.frame import _banner_lines
@@ -390,12 +392,17 @@ def test_narrow_wordmark_keeps_its_dim_row_off_the_bright_bank() -> None:
set_platform(PICOCALC)
rows = _banner_lines(load_logo(53), 53)
assert rows, "the 53-column mark should fit a 53-column console"
for i, row in enumerate(rows):
for sgr in re.findall(r"\x1b\[([0-9;]*)m", row):
assert not re.fullmatch(r"3[0-7]", sgr), f"bare dim-bank SGR on row {i}: {row!r}"
# The fourth row is the mark's only dim-slot row, and it is one colour throughout.
reds = set(re.findall(r"\x1b\[([0-9;]+)m(?=█)", rows[3]))
assert reds == {"22;31"}, reds
dim = [
sgr
for row in rows
for sgr in re.findall(r"\x1b\[([0-9;]*)m", row)
if any(re.fullmatch(r"3[0-7]", part) for part in sgr.split(";"))
]
# Without this the loop below would pass on a mark that never touches the dim bank.
assert dim, "the mark paints on the dim bank somewhere, or this check says nothing"
for sgr in dim:
parts = sgr.split(";")
assert any(p in {"0", "1", "2", "22"} for p in parts), f"unstated intensity: {sgr!r}"
# -- relocated marks stay importable from their old homes -----------------------------