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>
This commit is contained in:
parent
ce20c1abff
commit
7497cf5416
3 changed files with 10205 additions and 0 deletions
7948
l4d2web/l4d2web/static/data/srccfg-vocab.json
Normal file
7948
l4d2web/l4d2web/static/data/srccfg-vocab.json
Normal file
File diff suppressed because it is too large
Load diff
59
l4d2web/scripts/build-vocab.py
Executable file
59
l4d2web/scripts/build-vocab.py
Executable file
|
|
@ -0,0 +1,59 @@
|
|||
#!/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())
|
||||
Loading…
Reference in a new issue