left4me/l4d2web/scripts/build-vocab.py
mwiegand 7497cf5416
feat(editor-v2): vocab generator + cvar_list-derived JSON
build-vocab.py parses ./cvar_list (live L4D2 cvarlist dump, 2196 entries)
into static/data/srccfg-vocab.json — 1523 cvars + 671 commands.
Idempotent. Records the source-file SHA256 in the JSON header so
regenerations are auditable.

cvar_list is committed as a tracked data file so the generation is
reproducible from the repo alone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 01:55:33 +02:00

59 lines
1.9 KiB
Python
Executable file

#!/usr/bin/env python3
"""Convert ./cvar_list (cvarlist dump) to static/data/srccfg-vocab.json.
Usage: ./l4d2web/scripts/build-vocab.py
Reads from the repo root (auto-detected via this script's path).
Writes idempotently. Run after regenerating cvar_list."""
from __future__ import annotations
import hashlib
import json
import pathlib
import re
import sys
HERE = pathlib.Path(__file__).resolve().parent
REPO_ROOT = HERE.parent.parent
SOURCE = REPO_ROOT / "cvar_list"
DEST = REPO_ROOT / "l4d2web" / "l4d2web" / "static" / "data" / "srccfg-vocab.json"
def parse(text: str) -> tuple[list[dict], list[dict]]:
cvars: list[dict] = []
commands: list[dict] = []
for raw in text.splitlines()[2:]: # skip "cvar list" + "--------…"
if not raw.strip():
continue
parts = [p.strip() for p in re.split(r"\s*:\s*", raw, maxsplit=3)]
if len(parts) < 3:
continue
name = parts[0]
value = parts[1]
desc = parts[3] if len(parts) >= 4 else ""
target = commands if value == "cmd" else cvars
target.append({"name": name, "desc": desc} if desc else {"name": name})
return cvars, commands
def main() -> int:
if not SOURCE.exists():
print(f"ERROR: {SOURCE} not found", file=sys.stderr)
return 1
text = SOURCE.read_text(encoding="utf-8", errors="replace")
cvars, commands = parse(text)
src_sha = hashlib.sha256(text.encode("utf-8")).hexdigest()
payload = {
"version": 1,
"generated_from": "cvar_list",
"source_sha256": src_sha,
"cvars": cvars,
"commands": commands,
}
DEST.parent.mkdir(parents=True, exist_ok=True)
DEST.write_text(json.dumps(payload, indent=2, sort_keys=False) + "\n", encoding="utf-8")
print(f"wrote {DEST}: {len(cvars)} cvars + {len(commands)} commands")
return 0
if __name__ == "__main__":
raise SystemExit(main())