"""Terminal output, prompts, and formatting.""" import os import sys _PLAIN_MAP = {"✓": "[OK]", "✗": "[ERR]", "⚠": "[WARN]", "→": ">", "↳": "->", "·": "-", "…": "...", "─": "-", "—": "-", "←": "<-", "↔": "<->"} def _plain(): return os.environ.get("VOICE_PLAIN") == "1" def _transform(msg): if not _plain(): return msg for k, v in _PLAIN_MAP.items(): msg = msg.replace(k, v) return msg def _now_iso(): from datetime import datetime, timezone return datetime.now(timezone.utc).isoformat() def _say(msg): print(_transform(msg), flush=True) def _quiet(): try: from vlib import ctx as _ctx return bool(getattr(_ctx, "QUIET", False)) except Exception: return False def _ok(msg): if _quiet(): return _say(f" ✓ {msg}") def _warn(msg): _say(f" ⚠ {msg}") def _step(msg): if _quiet(): return _say(f" → {msg}") def _note(msg): if _quiet(): return _say(f" ↳ {msg}") def _fail(msg): sys.stdout.flush() msg = str(msg).lstrip() if msg.startswith("✗"): msg = msg[1:].lstrip() _say(f" ✗ {msg}") sys.exit(1) def _noninteractive(args): if getattr(args, "non_interactive", False) or getattr(args, "yes", False): return True try: return not sys.stdin.isatty() except Exception: return True def _progress_pref(): if _plain() or os.environ.get("REDUCE_MOTION") == "1": return True try: return not sys.stdout.isatty() except Exception: return True def _confirm(question, args): if getattr(args, "yes", False): return True if _noninteractive(args): return False try: ans = input(question).strip().lower() except (EOFError, KeyboardInterrupt): _say(" ⚠ Cancelled.") sys.exit(1) return ans in ("y", "yes") def _trunc(s, w): s = str(s) return s[: w - 1] + "…" if len(s) > w else s def _term_width(): try: import shutil return shutil.get_terminal_size().columns except Exception: return 80