68 lines
2.1 KiB
Python
68 lines
2.1 KiB
Python
"""
|
|
Source code feed — reads engine/*.py and emits non-blank, non-comment lines
|
|
as scroll items. Used by --code mode.
|
|
Depends on: nothing (stdlib only).
|
|
"""
|
|
|
|
import ast
|
|
from pathlib import Path
|
|
|
|
_ENGINE_DIR = Path(__file__).resolve().parent
|
|
|
|
|
|
def _scope_map(source: str) -> dict[int, str]:
|
|
"""Return {line_number: scope_label} for every line in source.
|
|
|
|
Nodes are sorted by range size descending so inner scopes overwrite
|
|
outer ones, guaranteeing the narrowest enclosing scope wins.
|
|
"""
|
|
try:
|
|
tree = ast.parse(source)
|
|
except SyntaxError:
|
|
return {}
|
|
|
|
nodes = []
|
|
for node in ast.walk(tree):
|
|
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
|
|
end = getattr(node, "end_lineno", node.lineno)
|
|
span = end - node.lineno
|
|
nodes.append((span, node))
|
|
|
|
# Largest range first → inner scopes overwrite on second pass
|
|
nodes.sort(key=lambda x: x[0], reverse=True)
|
|
|
|
scope = {}
|
|
for _, node in nodes:
|
|
end = getattr(node, "end_lineno", node.lineno)
|
|
if isinstance(node, ast.ClassDef):
|
|
label = node.name
|
|
else:
|
|
label = f"{node.name}()"
|
|
for ln in range(node.lineno, end + 1):
|
|
scope[ln] = label
|
|
|
|
return scope
|
|
|
|
|
|
def fetch_code():
|
|
"""Read engine/*.py and return (items, line_count, 0).
|
|
|
|
Each item is (text, src, ts) where:
|
|
text = the code line (rstripped, indentation preserved)
|
|
src = enclosing function/class name, e.g. 'stream()' or '<module>'
|
|
ts = dotted module path, e.g. 'engine.scroll'
|
|
"""
|
|
items = []
|
|
for path in sorted(_ENGINE_DIR.glob("*.py")):
|
|
module = f"engine.{path.stem}"
|
|
source = path.read_text(encoding="utf-8")
|
|
scope = _scope_map(source)
|
|
for lineno, raw in enumerate(source.splitlines(), start=1):
|
|
stripped = raw.strip()
|
|
if not stripped or stripped.startswith("#"):
|
|
continue
|
|
label = scope.get(lineno, "<module>")
|
|
items.append((raw.rstrip(), label, module))
|
|
|
|
return items, len(items), 0
|