Files
soleprint/soleprint/atlas2/docgen/extractors/code_main.py
buenosairesam 160ee31b8c docgen: drop the superseded first pass, port the style harvester
The IR supersedes both intermediate designs (requirements D6, D7):
station/tools/docgen and the graph model that briefly lived in graphgen.
Shipping them beside atlas2/docgen would mean two graph models, which is the
thing the architecture argues against.

Carried across rather than lost:
  - style/extract.py and tokens.py, the offline theme harvester (R31). Rewritten
    to emit a *theme* — a slot-to-hex binding — rather than a whole style file,
    since what harvesting recovers is which colour a slot should be, not what a
    kind should look like.
  - graphgen/README.md, rewritten for what graphgen actually is now: the
    schema explorer. It fixes the blank station-index entry at run.py:304.

Two bugs found while doing it:
  - Canvas and ink are the two lightness extremes, not the two most common
    values. In a Graphviz SVG every label carries a fill, so the ink outnumbers
    the canvas 87 to 43 and the old rule produced a theme whose text was
    invisible against its own background.
  - A name defined in both branches of an if/else produced a duplicate id, which
    failed validation on docgen's own source. Disambiguated by line.
2026-09-13 21:41:29 -03:00

40 lines
1.4 KiB
Python

""" python3 -m docgen.extractors code --root src/ [--ext .cs] [-o ir.json]"""
import argparse
import json
import sys
from pathlib import Path
def main(argv=None):
p = argparse.ArgumentParser(prog="python3 -m docgen.extractors code")
p.add_argument("--root", "-s", required=True, type=Path)
p.add_argument("--output", "-o", type=Path)
p.add_argument("--ext", action="append", default=[],
help="Limit to these extensions. Default: every registered one.")
p.add_argument("--exclude", action="append", default=[])
args = p.parse_args(argv)
from .code import LANGUAGES, MissingParser, extract
try:
ir = extract(args.root, suffixes=args.ext or None, exclude=tuple(args.exclude))
except MissingParser as e:
print(f"Error: {e}", file=sys.stderr)
return 1
except (NotADirectoryError, OSError) as e:
print(f"Error: {e}", file=sys.stderr)
return 1
text = json.dumps(ir.to_dict(), indent=2) + "\n"
if args.output:
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(text)
from collections import Counter
c = Counter(n.kind for n in ir.nodes)
print(f"{len(ir.nodes)} nodes -> {args.output} "
+ " · ".join(f"{v} {k}" for k, v in sorted(c.items(), key=lambda kv: -kv[1])))
else:
sys.stdout.write(text)
return 0