master
John Lauer 0.9.283: Wiki #73: kicad_list_design_rules and kicad_set_design_rules consume adom/pcb-design-rules at call time (fab,… 96aab8e 2mo ago
"""kicad_list_symbols: the names in a registered symbol library (wiki #62 finding 2).

A caller who only knows the MPN (the file name) has no way to learn the symbol
name inside the file without parsing s-expressions. This verb answers with the
bridge's own inventory AND KiCad's (kicadParser), because the two disagreed
once (wiki #71): a library the bridge counted fine was one KiCad refused.
"""

from __future__ import annotations

from pathlib import Path


def handle_list_symbols(kicad_info: dict, args: dict) -> dict:
    if not kicad_info.get("installed"):
        return {"success": False, "error": "KiCad not installed",
                "_hint": "Report to the user and ask them to install KiCad from https://www.kicad.org/download/, then retry."}
    lib_name = (args.get("libraryName") or args.get("library") or "Adom").strip()
    explicit = (args.get("libraryPath") or "").strip()

    lib_path: Path | None = None
    how = ""
    if explicit:
        lib_path, how = Path(explicit), "libraryPath argument"
    elif lib_name.lower() == "adom":
        try:
            from adom_library import _get_paths
            got = _get_paths(kicad_info)
            if got:
                lib_path, how = Path(got[1]), "sym-lib-table row 'Adom' (the file KiCad reads)"  # _get_paths -> (table, lib)
        except Exception as e:  # pylint: disable=broad-except
            return {"success": False, "error": f"Could not resolve the Adom library: {e}"}
    else:
        try:
            from lib_table import LibTable
            from adom_library import _expand_kicad_uri
            cfg = kicad_info.get("config_dir")
            table = LibTable.parse_file(str(Path(cfg) / "sym-lib-table")) if cfg else None
            row = next((e for e in (table.entries if table else []) if e.name == lib_name), None)
            if row is None:
                names = [e.name for e in (table.entries if table else [])]
                return {"success": False, "errorCode": "library_not_registered",
                        "error": f"No '{lib_name}' row in sym-lib-table", "registeredLibraries": names[:60],
                        "_hint": "Pick one of registeredLibraries, or pass libraryPath for a file that is not registered."}
            p = _expand_kicad_uri(row.uri, kicad_info)
            lib_path, how = (Path(p) if p else None), f"sym-lib-table row '{lib_name}' ({row.uri})"
        except Exception as e:  # pylint: disable=broad-except
            return {"success": False, "error": f"Could not read sym-lib-table: {e}"}

    if not lib_path or not lib_path.exists():
        return {"success": False, "errorCode": "library_file_missing", "error": f"Library file not found: {lib_path}",
                "resolvedVia": how}

    from adom_library import list_symbols
    names = list_symbols(lib_path) or []
    out = {"success": True, "libraryName": lib_name, "libraryPath": str(lib_path), "resolvedVia": how,
           "symbolCount": len(names), "symbols": names}

    try:
        from handlers import kicad_parse_check as _kpc
        v = _kpc.verdict_file(kicad_info, str(lib_path))
        out["kicadParser"] = v
        if v.get("available") and not v.get("ok"):
            out["_hint"] = (f"KiCad REFUSES this library ('{v.get('error')}'); the Symbol Editor shows it empty regardless of the "
                            f"{len(names)} name(s) above. kicad_adom_library_heal {{\"mode\":\"prune\"}} names the refused symbol(s).")
        elif v.get("available"):
            ks = set(v.get("symbols") or [])
            missing = [n for n in names if n not in ks]
            if missing:
                out["_hint"] = f"KiCad lists {len(ks)} symbol(s) but not {missing[:5]}; trust kicadParser.symbols for what the editor can show."
    except Exception:  # pylint: disable=broad-except
        pass
    out.setdefault("_hint", "Use one of `symbols` as symbolName for kicad_show_library; the file name is often an MPN and not the symbol name (wiki #62).")
    return out