Files
draugnorak/skills/nvgt-engine-dev/scripts/nvgt_api_report.py

97 lines
3.0 KiB
Python
Executable File

#!/usr/bin/env python3
"""Generate a signature-focused NVGT API evidence report for a symbol."""
from __future__ import annotations
import argparse
import re
import shutil
import subprocess
import sys
from pathlib import Path
def discover_nvgt_root(explicit_root: str) -> Path | None:
if explicit_root:
root = Path(explicit_root).expanduser().resolve()
return root if root.exists() else None
default_root = Path.home() / "git" / "nvgt"
default_resolved = default_root.expanduser().resolve()
if default_resolved.exists():
return default_resolved
return None
def run_rg(pattern: str, paths: list[Path], max_count: int) -> str:
existing = [str(path) for path in paths if path.exists()]
if not existing:
return ""
cmd = [
"rg",
"-n",
"--hidden",
"--no-ignore",
"--max-count",
str(max_count),
pattern,
*existing,
]
proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if proc.returncode in (0, 1):
return proc.stdout.strip()
raise RuntimeError(proc.stderr.strip() or "ripgrep failed")
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Create an NVGT API evidence report for a symbol.")
parser.add_argument("symbol", help="Function/object/symbol to inspect")
parser.add_argument("--root", default="", help="Path to NVGT root (default: ~/git/nvgt)")
parser.add_argument("--max-count", type=int, default=25, help="Max matches per section (default: 25)")
return parser.parse_args()
def main() -> int:
if shutil.which("rg") is None:
print("Error: ripgrep (rg) is required.", file=sys.stderr)
return 2
args = parse_args()
nvgt_root = discover_nvgt_root(args.root)
if nvgt_root is None:
print("Error: NVGT root not found at ~/git/nvgt. Pass --root to override.", file=sys.stderr)
return 2
escaped_symbol = re.escape(args.symbol)
docs_pattern = rf"\b{escaped_symbol}\b"
include_pattern = docs_pattern
bindings_pattern = rf"Register(GlobalFunction|ObjectMethod|ObjectProperty|Funcdef).*\b{escaped_symbol}\b"
sample_pattern = docs_pattern
sections = [
("docs-references", docs_pattern, [nvgt_root / "doc/src/references"]),
("include-wrappers", include_pattern, [nvgt_root / "release/include"]),
("bindings-signatures", bindings_pattern, [nvgt_root / "src"]),
("samples", sample_pattern, [nvgt_root / "extra/samples"]),
]
any_match = False
print(f"NVGT root: {nvgt_root}")
print(f"Symbol: {args.symbol}")
for title, pattern, paths in sections:
output = run_rg(pattern, paths, args.max_count)
if output:
any_match = True
print(f"\n== {title} ==")
print(output)
if not any_match:
print("\nNo matches found in evidence sections.")
return 1
return 0
if __name__ == "__main__":
raise SystemExit(main())