app
KiCad - the KiCad Bridge
Public Made by Adomby adom
Drive your own KiCad from an AI, in the background: open every editor, read the whole board as data (the EDA Bridge Standard board model), stack-up, part heights, netlists, place, route, pour, DRC and exports.
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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
"""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