tankslab.com/recall/source
bin/console.py
64 lines, exactly as they ship in the download.
"""
console.py - print without crashing on a Windows console.
WHY THIS EXISTS
---------------
Windows terminals commonly run code page 437 or 1252. Printing a check mark to one
does not produce an ugly character — it raises UnicodeEncodeError and kills the
command. `recall search` and `recall timeline` both print status icons, so on a
default Windows 10/11 console they crashed on their first result.
Two defences, because either alone is not enough:
1. stdout/stderr are reconfigured to replace unencodable characters instead of
raising. Nothing can crash on output after that, whatever we print later.
2. Icons fall back to ASCII when the console genuinely cannot represent them, so
the output stays READABLE rather than a row of question marks. Degrading to
legible is the point; not crashing is only the floor.
"""
from __future__ import annotations
import sys
UNICODE_ICONS = {"change": "✓", "discovery": "○", "verification": "✓",
"operation": "⛯", "bugfix": "●", "feature": "◆",
"refactor": "↻", "decision": "⚖",
"security_alert": "⚠", "security_note": "⚷"}
ASCII_ICONS = {"change": "+", "discovery": "?", "verification": "v",
"operation": "*", "bugfix": "!", "feature": "#",
"refactor": "~", "decision": "=",
"security_alert": "!!", "security_note": "$"}
def _harden() -> None:
for stream in (sys.stdout, sys.stderr):
try:
stream.reconfigure(errors="replace")
except Exception:
pass
def _can_encode(sample: str) -> bool:
enc = getattr(sys.stdout, "encoding", None) or "ascii"
try:
sample.encode(enc)
return True
except Exception:
return False
_harden()
UNICODE_OK = _can_encode("".join(UNICODE_ICONS.values()))
ICONS = UNICODE_ICONS if UNICODE_OK else ASCII_ICONS
def icon(kind: str) -> str:
return ICONS.get(kind, "-" if not UNICODE_OK else "·")
def dash() -> str:
return "--" if not UNICODE_OK else "—"
def rule(n: int = 40) -> str:
return ("-" if not UNICODE_OK else "─") * n