app
Adom Symbol
Public Made by Adomby adom
KiCad symbol creator with interactive viewer and delivery to KiCad/Fusion 360
← Commit history
1.1.10: Description = caller text + layout note; outline contract carries description + layout_note
6 files changed
+65−5
Cargo.lock+1−1@@ -4,7 +4,7 @@ version = 4 [[package]] name = "adom-symbol"-version = "1.1.9"+version = "1.1.10" dependencies = [ "anyhow", "clap",
Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "adom-symbol"-version = "1.1.9"+version = "1.1.10" edition = "2021" description = "Create and preview KiCad/Fusion 360 schematic symbols with interactive viewer"
VERSION+1−1@@ -1 +1 @@-1.1.9+1.1.10
bin/adom-symbol⋯ 1 unchanged line ⋯
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-symbol",- "version": "1.1.9",+ "version": "1.1.10", "type": "app", "description": "KiCad symbol creator with interactive viewer and delivery to KiCad/Fusion 360", "dependencies": {
src/main.rs+61−1@@ -253,6 +253,9 @@ fn run() -> Result<()> { render::build_outline_contract(&svg, &content, &ov, &src, &mm_name, frac) }) { Ok((mm_svg, json, segs)) => {+ // Carry the symbol's Description + a "chip outline in body" note+ // so the outline twins can explain themselves downstream.+ let json = annotate_contract(&json, &content, &name); fs::write(dir.join(&mm_name), &mm_svg) .with_context(|| format!("writing {mm_name}"))?; fs::write(dir.join(&json_name), &json)@@ -339,6 +342,58 @@ fn parse_outline_svg(path: &str) -> Result<Vec<Vec<(f64, f64)>>> { .collect()) } +/// One-line layout note for the Description property, so every variant+/// explains itself in Fusion's component tree and ADD dialog (John,+/// 2026-08-29: "always make sure there's a good description in here").+/// e.g. "4-side square symbol, pins grouped by function, chip name centred".+pub(crate) fn layout_note(pin_layout: &str, grouped: bool, explicit_sides: bool, centred: bool) -> String {+ let shape = match pin_layout {+ "square" => "4-side square symbol, pins in package order",+ "square-grouped" => "4-side square symbol",+ "all-sides" if !explicit_sides => "4-side square symbol",+ "all-sides" => "4-side symbol",+ _ => "2-column symbol",+ };+ let mut parts = vec![shape.to_string()];+ if grouped && pin_layout != "square" {+ parts.push("pins grouped by function".into());+ }+ if centred {+ parts.push("chip name centred".into());+ }+ parts.join(", ")+}++/// Caller description + layout note, as one sentence-terminated string.+/// Adds nothing if the note is already present (idempotent on re-create).+pub(crate) fn compose_description(desc: &str, note: &str) -> String {+ let d = desc.trim().trim_end_matches('.').trim();+ if note.is_empty() {+ return d.to_string();+ }+ if d.contains(note) {+ return desc.trim().to_string();+ }+ if d.is_empty() {+ format!("{note}.")+ } else {+ format!("{d}. {note}.")+ }+}++/// Add `description` (the symbol's Description property + "chip outline in+/// body") and `layout_note` to the outline-contract JSON.+fn annotate_contract(json: &str, kicad_sym: &str, name: &str) -> String {+ let mut v: serde_json::Value = match serde_json::from_str(json) { Ok(v) => v, Err(_) => return json.to_string() };+ let base = render::field_val(kicad_sym, name, "Description").unwrap_or_default();+ let note = "chip outline in body";+ if let Some(o) = v.as_object_mut() {+ o.insert("layout_note".into(), serde_json::Value::String(note.into()));+ o.insert("description".into(), serde_json::Value::String(compose_description(&base, note)));+ }+ serde_json::to_string_pretty(&v).unwrap_or_else(|_| json.to_string())+}+ fn cmd_create(file: Option<PathBuf>, out: Option<PathBuf>) -> Result<()> { let body = match file { Some(p) => fs::read_to_string(&p).with_context(|| format!("reading {}", p.display()))?,@@ -393,7 +448,12 @@ fn cmd_create(file: Option<PathBuf>, out: Option<PathBuf>) -> Result<()> { symbol_name: input.symbol_name.clone(), manufacturer: input.manufacturer.clone(), package: input.package.clone(),- description: input.description.clone(),+ description: compose_description(&input.description, &layout_note(+ input.preferences.pin_layout.as_deref().unwrap_or("left-right"),+ input.pins.iter().any(|p| p.group.is_some()),+ input.pins.iter().any(|p| p.side.is_some()),+ input.preferences.chip_name_centered,+ )), datasheet_url: input.datasheet_url.clone(), reference_prefix: input.reference_prefix.clone().unwrap_or_else(|| "U".to_string()), pins: input