kisch 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +170 -0
- package/lab/kish-test.js +35 -0
- package/lab/kitest-org/kitest-backups/kitest-2026-02-03_180334.zip +0 -0
- package/lab/kitest-org/kitest.kicad_pcb +2 -0
- package/lab/kitest-org/kitest.kicad_prl +98 -0
- package/lab/kitest-org/kitest.kicad_pro +418 -0
- package/lab/kitest-org/kitest.kicad_sch +663 -0
- package/package.json +22 -0
- package/spec/Entity.spec.js +31 -0
- package/spec/Schematic.spec.js +115 -0
- package/spec/SymbolLibrary.spec.js +17 -0
- package/spec/cartesian-math.spec.js +25 -0
- package/spec/kitest.kicad_sch +663 -0
- package/spec/manhattan-router.spec.js +152 -0
- package/spec/sexp.spec.js +14 -0
- package/spec/support/jasmine.mjs +14 -0
- package/src/Entity.js +232 -0
- package/src/LibrarySymbol.js +100 -0
- package/src/Schematic.js +329 -0
- package/src/SymbolLibrary.js +101 -0
- package/src/cartesian-math.js +127 -0
- package/src/kisch-cli.js +33 -0
- package/src/manhattan-router.js +176 -0
- package/src/place-rect.js +45 -0
- package/src/sexp.js +178 -0
package/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# KISCH(1)
|
|
2
|
+
|
|
3
|
+
## NAME
|
|
4
|
+
|
|
5
|
+
kisch - schema‑transformation tool for KiCad schematics
|
|
6
|
+
|
|
7
|
+
## SYNOPSIS
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
kisch <schema.kicad_sch> [options]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## DESCRIPTION
|
|
14
|
+
|
|
15
|
+
**kisch** is a command‑line tool for transforming KiCad schematic files.
|
|
16
|
+
|
|
17
|
+
Rather than treating schematics as static drawings edited exclusively through a GUI, kisch treats a `.kicad_sch` file as a *schema* that can be programmatically rewritten.
|
|
18
|
+
|
|
19
|
+
The intended workflow is to let KiCad do what it is good at (symbol placement and visual inspection), and let kisch do what GUIs are bad at: repetitive edits, precise connectivity, and large‑scale structural changes.
|
|
20
|
+
|
|
21
|
+
kisch operates directly on KiCad 9 schematic files. It does not use netlists and does not rely on KiCad’s internal APIs; it reads and rewrites `.kicad_sch` files as data.
|
|
22
|
+
|
|
23
|
+
## PHILOSOPHY
|
|
24
|
+
|
|
25
|
+
KiCad used to treat netlists as a first‑class artifact. In modern KiCad, the schematic file itself *is* the source of truth.
|
|
26
|
+
|
|
27
|
+
kisch embraces this shift.
|
|
28
|
+
|
|
29
|
+
Instead of exporting, regenerating, or synchronizing netlists, kisch transforms the schematic directly. This enables workflows where:
|
|
30
|
+
|
|
31
|
+
* Symbols are placed manually in KiCad
|
|
32
|
+
* Connectivity is defined programmatically
|
|
33
|
+
* Large schematics can be refactored safely and repeatably
|
|
34
|
+
* Accidental GUI‑level wiring mistakes are avoided
|
|
35
|
+
|
|
36
|
+
Think of kisch as a schema transformation pass over a KiCad schematic.
|
|
37
|
+
|
|
38
|
+
## COMMAND LINE INTERFACE
|
|
39
|
+
|
|
40
|
+
The schematic file is the only positional argument.
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
kisch schema.kicad_sch --script=<file> [options]
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Options
|
|
47
|
+
|
|
48
|
+
* `--script=<file>`
|
|
49
|
+
|
|
50
|
+
JavaScript file that defines the transformation logic applied to the schematic.
|
|
51
|
+
|
|
52
|
+
* `--symbol-library-path=<path>`
|
|
53
|
+
|
|
54
|
+
Path to a KiCad symbol library used when adding or resolving symbols.
|
|
55
|
+
|
|
56
|
+
(Additional options may be added over time.)
|
|
57
|
+
|
|
58
|
+
## SCRIPTING MODEL
|
|
59
|
+
|
|
60
|
+
kisch is implemented as a Node.js CLI and executes user‑provided JavaScript to perform transformations.
|
|
61
|
+
|
|
62
|
+
A script typically:
|
|
63
|
+
|
|
64
|
+
* Loads the schematic structure
|
|
65
|
+
* Adds or modifies symbols
|
|
66
|
+
* Connects pins and nets explicitly
|
|
67
|
+
* Writes the transformed schematic back to disk
|
|
68
|
+
|
|
69
|
+
The exact scripting API is intentionally minimal and focused on structural operations, not rendering or layout aesthetics.
|
|
70
|
+
|
|
71
|
+
### Example
|
|
72
|
+
|
|
73
|
+
The following example hooks up an ESP32-C3 supermini with a CAN transceiver.
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
export default async function (sch) {
|
|
77
|
+
await sch.use([
|
|
78
|
+
"Connector_Generic:Conn_01x04",
|
|
79
|
+
"Connector_Generic:Conn_02x02_Counter_Clockwise",
|
|
80
|
+
"Connector_Generic:Conn_02x08_Counter_Clockwise",
|
|
81
|
+
"Connector_Generic:Conn_02x04_Counter_Clockwise"
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
let screw1 = sch.declare("J1", {
|
|
85
|
+
symbol: "Connector_Generic:Conn_01x04",
|
|
86
|
+
footprint: "Peabrain:ScrewTerminals_4P",
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
let screw2 = sch.declare("J2", {
|
|
90
|
+
symbol: "Connector_Generic:Conn_01x04",
|
|
91
|
+
footprint: "Peabrain:ScrewTerminals_4P",
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
let vreg = sch.declare("U1", {
|
|
95
|
+
symbol: "Connector_Generic:Conn_02x02_Counter_Clockwise",
|
|
96
|
+
footprint: "Peabrain:VoltageRegulator",
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
let esp32 = sch.declare("U2", {
|
|
100
|
+
symbol: "Connector_Generic:Conn_02x08_Counter_Clockwise",
|
|
101
|
+
footprint: "Peabrain:ESP32",
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
let tja1050 = sch.declare("U3", {
|
|
105
|
+
symbol: "Connector_Generic:Conn_02x04_Counter_Clockwise",
|
|
106
|
+
footprint: "Peabrain:TJA1050",
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
screw1.pin(1).connect("GND");
|
|
110
|
+
screw1.pin(2).connect("12V");
|
|
111
|
+
screw1.pin(3).connect("CANH");
|
|
112
|
+
screw1.pin(4).connect("CANL");
|
|
113
|
+
|
|
114
|
+
screw2.pin(1).connect("GND");
|
|
115
|
+
screw2.pin(2).connect("12V");
|
|
116
|
+
screw2.pin(3).connect("CANH");
|
|
117
|
+
screw2.pin(4).connect("CANL");
|
|
118
|
+
|
|
119
|
+
tja1050.pin(1).connect("5V");
|
|
120
|
+
tja1050.pin(2).connect(esp32.pin(1)); // TX
|
|
121
|
+
tja1050.pin(3).connect(esp32.pin(13)); // RX
|
|
122
|
+
tja1050.pin(4).connect("GND");
|
|
123
|
+
tja1050.pin(6).connect("CANL");
|
|
124
|
+
tja1050.pin(7).connect("CANH");
|
|
125
|
+
|
|
126
|
+
esp32.pin(16).connect("5V");
|
|
127
|
+
esp32.pin(15).connect("GND");
|
|
128
|
+
|
|
129
|
+
vreg.pin(1).connect("12V");
|
|
130
|
+
vreg.pin(2).connect("GND");
|
|
131
|
+
vreg.pin(3).connect("GND");
|
|
132
|
+
vreg.pin(4).connect("5V");
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## SUPPORTED FILES
|
|
137
|
+
|
|
138
|
+
* KiCad 9 schematic files (`.kicad_sch`)
|
|
139
|
+
|
|
140
|
+
## UNSUPPORTED FILES
|
|
141
|
+
|
|
142
|
+
* PCB files (`.kicad_pcb`)
|
|
143
|
+
* Netlists (deprecated by design)
|
|
144
|
+
|
|
145
|
+
## LIMITATIONS
|
|
146
|
+
|
|
147
|
+
* kisch targets **KiCad 9 only**
|
|
148
|
+
* Only schematic files are supported
|
|
149
|
+
* kisch cares about schematic geometry just enough to be correct, but not enough to be pretty
|
|
150
|
+
* It can place new symbols so that they function correctly (e.g. without overlapping other symbols), but it does not attempt to find the best or most readable placement
|
|
151
|
+
* Graphical placement quality remains the responsibility of the user
|
|
152
|
+
|
|
153
|
+
## USE CASES
|
|
154
|
+
|
|
155
|
+
* Programmatic net and wire generation
|
|
156
|
+
* Repetitive schematic patterns
|
|
157
|
+
* Safe refactoring of large schematics
|
|
158
|
+
* Hybrid GUI + code‑driven design workflows
|
|
159
|
+
|
|
160
|
+
## INSTALLATION
|
|
161
|
+
|
|
162
|
+
kisch is a Node.js‑based CLI. Install with:
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
npm install -g kisch
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## LICENSE
|
|
169
|
+
|
|
170
|
+
GPL v3 for now... Haven't thought about it... :)
|
package/lab/kish-test.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {openSchematic} from "../src/Schematic.js";
|
|
2
|
+
import fs, {promises as fsp} from "fs";
|
|
3
|
+
|
|
4
|
+
await fsp.rm("lab/kitest",{force: true, recursive: true});
|
|
5
|
+
await fsp.cp("lab/kitest-org","lab/kitest",{recursive: true});
|
|
6
|
+
|
|
7
|
+
let schematic=await openSchematic("lab/kitest/kitest.kicad_sch",{
|
|
8
|
+
symbolLibraryPath: "/home/micke/Repo.ext/kicad-symbols"
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
await schematic.use(
|
|
12
|
+
"Connector_Generic:Conn_01x08"
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
schematic.sym("J1").pin(1).connect(schematic.sym("J3").pin(2));
|
|
16
|
+
schematic.sym("J3").pin(1).connect("GND");
|
|
17
|
+
schematic.sym("J1").pin(1).connect(schematic.sym("J3").pin(1));
|
|
18
|
+
|
|
19
|
+
let r=schematic.sym("J3").getBoundingRect();
|
|
20
|
+
|
|
21
|
+
/*for (let i=4; i<20; i++) {
|
|
22
|
+
schematic.declare("J"+i,{
|
|
23
|
+
symbol: "Connector_Generic:Conn_01x08",
|
|
24
|
+
});
|
|
25
|
+
}*/
|
|
26
|
+
|
|
27
|
+
schematic.declare("J4",{
|
|
28
|
+
symbol: "Connector_Generic:Conn_01x04",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
schematic.sym("J4").pin(1).connect("GND");
|
|
32
|
+
schematic.sym("J4").pin(4).connect(schematic.sym("J3").pin(3));
|
|
33
|
+
schematic.sym("J1").pin(1).connect(schematic.sym("J4").pin(1));
|
|
34
|
+
|
|
35
|
+
await schematic.save();
|
|
Binary file
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"board": {
|
|
3
|
+
"active_layer": 0,
|
|
4
|
+
"active_layer_preset": "",
|
|
5
|
+
"auto_track_width": true,
|
|
6
|
+
"hidden_netclasses": [],
|
|
7
|
+
"hidden_nets": [],
|
|
8
|
+
"high_contrast_mode": 0,
|
|
9
|
+
"net_color_mode": 1,
|
|
10
|
+
"opacity": {
|
|
11
|
+
"images": 0.6,
|
|
12
|
+
"pads": 1.0,
|
|
13
|
+
"shapes": 1.0,
|
|
14
|
+
"tracks": 1.0,
|
|
15
|
+
"vias": 1.0,
|
|
16
|
+
"zones": 0.6
|
|
17
|
+
},
|
|
18
|
+
"selection_filter": {
|
|
19
|
+
"dimensions": true,
|
|
20
|
+
"footprints": true,
|
|
21
|
+
"graphics": true,
|
|
22
|
+
"keepouts": true,
|
|
23
|
+
"lockedItems": false,
|
|
24
|
+
"otherItems": true,
|
|
25
|
+
"pads": true,
|
|
26
|
+
"text": true,
|
|
27
|
+
"tracks": true,
|
|
28
|
+
"vias": true,
|
|
29
|
+
"zones": true
|
|
30
|
+
},
|
|
31
|
+
"visible_items": [
|
|
32
|
+
"vias",
|
|
33
|
+
"footprint_text",
|
|
34
|
+
"footprint_anchors",
|
|
35
|
+
"ratsnest",
|
|
36
|
+
"grid",
|
|
37
|
+
"footprints_front",
|
|
38
|
+
"footprints_back",
|
|
39
|
+
"footprint_values",
|
|
40
|
+
"footprint_references",
|
|
41
|
+
"tracks",
|
|
42
|
+
"drc_errors",
|
|
43
|
+
"drawing_sheet",
|
|
44
|
+
"bitmaps",
|
|
45
|
+
"pads",
|
|
46
|
+
"zones",
|
|
47
|
+
"drc_warnings",
|
|
48
|
+
"drc_exclusions",
|
|
49
|
+
"locked_item_shadows",
|
|
50
|
+
"conflict_shadows",
|
|
51
|
+
"shapes"
|
|
52
|
+
],
|
|
53
|
+
"visible_layers": "ffffffff_ffffffff_ffffffff_ffffffff",
|
|
54
|
+
"zone_display_mode": 0
|
|
55
|
+
},
|
|
56
|
+
"git": {
|
|
57
|
+
"repo_type": "",
|
|
58
|
+
"repo_username": "",
|
|
59
|
+
"ssh_key": ""
|
|
60
|
+
},
|
|
61
|
+
"meta": {
|
|
62
|
+
"filename": "kitest.kicad_prl",
|
|
63
|
+
"version": 5
|
|
64
|
+
},
|
|
65
|
+
"net_inspector_panel": {
|
|
66
|
+
"col_hidden": [],
|
|
67
|
+
"col_order": [],
|
|
68
|
+
"col_widths": [],
|
|
69
|
+
"custom_group_rules": [],
|
|
70
|
+
"expanded_rows": [],
|
|
71
|
+
"filter_by_net_name": true,
|
|
72
|
+
"filter_by_netclass": true,
|
|
73
|
+
"filter_text": "",
|
|
74
|
+
"group_by_constraint": false,
|
|
75
|
+
"group_by_netclass": false,
|
|
76
|
+
"show_unconnected_nets": false,
|
|
77
|
+
"show_zero_pad_nets": false,
|
|
78
|
+
"sort_ascending": true,
|
|
79
|
+
"sorting_column": -1
|
|
80
|
+
},
|
|
81
|
+
"open_jobsets": [],
|
|
82
|
+
"project": {
|
|
83
|
+
"files": []
|
|
84
|
+
},
|
|
85
|
+
"schematic": {
|
|
86
|
+
"selection_filter": {
|
|
87
|
+
"graphics": true,
|
|
88
|
+
"images": true,
|
|
89
|
+
"labels": true,
|
|
90
|
+
"lockedItems": false,
|
|
91
|
+
"otherItems": true,
|
|
92
|
+
"pins": true,
|
|
93
|
+
"symbols": true,
|
|
94
|
+
"text": true,
|
|
95
|
+
"wires": true
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|