Rename set-type to set-connector-type; help-panel & types-glossary polish.

- Command renamed from `set-type` to `set-connector-type` for
  clarity (the previous name was ambiguous — "type" of what?). No
  legacy alias kept; old scripts that still used `set-type` must be
  migrated. `test/system.essim` and all user/design docs updated.
- Help panel (RenderHelpPanel) now wraps in borderRounded with a
  centred bold title, so it is visually distinct from the main
  content on every screen. Width bumped from 30 to 32 to include
  the border.
- Analyze screen's Types tab gains a sibling "type glossary" panel
  (also borderRounded, only visible when the Types tab is focused)
  that explains Power / Suspect Power / Hard floor / Gnd in plain
  language using `paragraph()` for clean word-wrap.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-14 20:41:35 +02:00
parent 90502c0762
commit 516149cdae
17 changed files with 90 additions and 87 deletions

View File

@@ -15,7 +15,7 @@
// NOTE: real VITA 46 pin roles are connector-/profile-specific (data lanes,
// power planes, GND chassis, etc.). The placeholders below are intentionally
// minimal — fill in the actual per-(col,row) roles for your design when the
// reference is available; the rest of the chain (set-type → verify) is
// reference is available; the rest of the chain (set-connector-type → verify) is
// already wired through this single function.
namespace {

View File

@@ -9,7 +9,7 @@
class Part;
// For a given connector type and pin position, return the expected SignalType
// (Power / GndShield / Other). Used at `set-type` to populate each pin's
// (Power / GndShield / Other). Used at `set-connector-type` to populate each pin's
// `expected_signal_type`, then later by `verify` to flag mismatches between
// the connector's expectation and the actual signal's inferred/declared type.
//
@@ -23,7 +23,7 @@ SignalType pin_role(const std::string &connector_type,
// vector for connector types that don't have a registered layout — callers
// must treat that as "unknown, do not auto-fill".
//
// Used at `set-type` to materialise NC pins for positions absent from the
// Used at `set-connector-type` to materialise NC pins for positions absent from the
// imported netlist (Altium drops NC, Mentor doesn't). Stub today: every
// known kind returns {} — populate alongside `vpx_3u_role`.
std::vector<std::string> pin_layout(const std::string &connector_type);

View File

@@ -29,7 +29,7 @@ class Pin : public SystemElement
public:
Pin(std::string name);
Part *prnt; ///< Pointer to the parent part.
SignalType expected_signal_type; ///< Set from connector_type at set-type.
SignalType expected_signal_type; ///< Set from connector_type at set-connector-type.
NcOrigin nc_origin = NcOrigin::None;
bool connected();
Signal *signal() const { return sig; }

View File

@@ -19,7 +19,7 @@
// instances are registered at startup, under the type pairs
// (vpx-3u-bkp-N, vpx-3u-payload-N)
// for N in {0, 1, 2}. Tag each Part with the correct connector_type via
// `set-type`, then `connect` will pick the right transform automatically.
// `set-connector-type`, then `connect` will pick the right transform automatically.
class VpxTransform : public Transform
{
public:

View File

@@ -431,7 +431,7 @@ void Tui::RegisterCommands() {
"override the auto-detected signal type (power | gnd | other)",
};
commands["set-type"] = {
commands["set-connector-type"] = {
{{"module", Completion::None},
{"part (name or pattern)", Completion::None},
{"connector type (free string, e.g. vpx-bp, vpx-payload)", Completion::None}},
@@ -454,7 +454,7 @@ void Tui::RegisterCommands() {
}
if (args.size() != 3) {
Print("usage: set-type <module> <part> <kind> (or no args for interactive)");
Print("usage: set-connector-type <module> <part> <kind> (or no args for interactive)");
return;
}
@@ -480,7 +480,7 @@ void Tui::RegisterCommands() {
}
std::string err = ValidatePartForKind(prt, args[2]);
if (!err.empty()) {
Print("set-type refused: " + err);
Print("set-connector-type refused: " + err);
return;
}
prt->connector_type = args[2];
@@ -490,7 +490,7 @@ void Tui::RegisterCommands() {
Print(mod->name + "/" + prt->name + ": connector_type = "
+ (args[2].empty() ? "(none)" : args[2]));
if (filled > 0)
Print("set-type: materialised " + std::to_string(filled)
Print("set-connector-type: materialised " + std::to_string(filled)
+ " NC pin(s) from connector layout");
},
/*prompt_for_missing=*/ false,
@@ -498,7 +498,6 @@ void Tui::RegisterCommands() {
/*scriptable=*/ true,
/*interactive=*/ true,
};
commands["connect"] = {
{{"module1", Completion::None},
{"part1 (name or pattern)", Completion::None},
@@ -596,7 +595,7 @@ void Tui::RegisterCommands() {
+ (p1->connector_type.empty() ? "(none)" : p1->connector_type)
+ "' ↔ '"
+ (p2->connector_type.empty() ? "(none)" : p2->connector_type)
+ "'. Set matching types via 'set-type' first.");
+ "'. Set matching types via 'set-connector-type' first.");
return;
}
std::string info;

View File

@@ -244,34 +244,35 @@ Component Tui::BuildAnalyzeScreen() {
{"Esc", "dashboard"},
});
// Glossary: only relevant on the Types tab. Same width as the help
// panel for visual coherence.
// Glossary: shown only when the Types tab is focused. Same border
// styling as the help panel (borderRounded) for visual coherence;
// text uses `paragraph` so lines wrap cleanly to the panel width.
auto term = [](const std::string &name, const std::string &desc) {
return vbox({
text(name) | bold,
paragraph(desc) | dim,
text(""),
});
};
Element types_glossary = vbox({
text(" types ") | bold,
text(" type glossary ") | bold | center,
separator(),
hbox({text(" Power ") | bold | size(WIDTH, EQUAL, 12),
text("name + structure") | flex}),
hbox({text(" ") | dim | size(WIDTH, EQUAL, 12),
text("(fan-out ≥ 4 or") | dim | flex}),
hbox({text(" ") | dim | size(WIDTH, EQUAL, 12),
text(" voltage in name)") | dim | flex}),
text(""),
hbox({text(" Suspect ") | bold | size(WIDTH, EQUAL, 12),
text("name only,") | flex}),
hbox({text(" ") | dim | size(WIDTH, EQUAL, 12),
text("weak evidence") | dim | flex}),
text(""),
hbox({text(" hard ") | bold | size(WIDTH, EQUAL, 12),
text("fan-out < 3 →") | flex}),
hbox({text(" floor ") | bold | size(WIDTH, EQUAL, 12),
text("never Power") | flex}),
text(""),
hbox({text(" Gnd ") | bold | size(WIDTH, EQUAL, 12),
text("name only") | flex}),
}) | size(WIDTH, EQUAL, 30);
term("Power",
"Name suggests Power AND structure agrees: fan-out ≥ 4 pins, "
"or a voltage pattern in the name (e.g. 3V3, 5V, 12V)."),
term("Suspect Power",
"Name suggests Power but the structural check failed — "
"fan-out too low and no voltage in the name."),
term("Hard floor",
"Fan-out below 3 pins forces Other regardless of the name. "
"A real rail physically cannot live on 1-2 pads."),
term("Gnd",
"Name matches GND, SHIELD, CHASSIS or EARTH. Name alone is "
"enough — false positives are essentially nil."),
}) | borderRounded | size(WIDTH, EQUAL, 32);
Element side = (analyze_focus_idx == 2)
? vbox({help, text(""), types_glossary}) | size(WIDTH, EQUAL, 30)
? vbox({help, text(""), types_glossary}) | size(WIDTH, EQUAL, 32)
: help;
return vbox({

View File

@@ -76,7 +76,7 @@ Component Tui::BuildConnectScreen() {
+ (p1->connector_type.empty() ? "(none)" : p1->connector_type)
+ "' ↔ '"
+ (p2->connector_type.empty() ? "(none)" : p2->connector_type)
+ "'. Set matching types via 'set-type' first.");
+ "'. Set matching types via 'set-connector-type' first.");
screen_idx = 0;
return;
}

View File

@@ -296,7 +296,7 @@ Component Tui::BuildDashboardScreen() {
{"c", "console"},
{"s", "search"},
{"p", "plug"},
{"t", "set-type"},
{"t", "set-connector-type"},
{"e", "explore"},
{"n", "net"},
{"a", "analyze (verify + groups)"},

View File

@@ -58,7 +58,7 @@ Component Tui::BuildSettypeScreen() {
std::string msg = mod->name + "/" + prt->name + " = "
+ (settype_type.empty() ? "(none)" : settype_type);
settype_status = "applied: " + msg;
Print("set-type " + msg);
Print("set-connector-type " + msg);
} catch (const std::exception &e) {
settype_status = std::string("failed: ") + e.what();
}
@@ -129,11 +129,11 @@ Component Tui::BuildSettypeScreen() {
auto title = hbox({
text(" essim ") | bold,
text("") | dim,
text("set-type") | bold,
text("set-connector-type") | bold,
text(" — tag a part with its connector kind (drives transforms + pin roles)") | dim,
});
Element help = RenderHelpPanel("set-type", {
Element help = RenderHelpPanel("set-connector-type", {
{"Tab", "cycle focus"},
{"↑/↓", "navigate menu"},
{"Enter", "on [Apply] → tag"},

View File

@@ -100,7 +100,7 @@ void Tui::Run() {
if (e == Event::Character("c")) { screen_idx = 0; return true; }
if (e == Event::Character("p")) { Dispatch("connect"); return true; }
if (e == Event::Character("s")) { Dispatch("search"); return true; }
if (e == Event::Character("t")) { Dispatch("set-type"); return true; }
if (e == Event::Character("t")) { Dispatch("set-connector-type"); return true; }
if (e == Event::Character("e")) { Dispatch("explore"); return true; }
if (e == Event::Character("n")) { Dispatch("net"); return true; }
// [a]nalyze is the unified verify + analyze screen (issues +
@@ -121,7 +121,7 @@ void Tui::Run() {
if (e == Event::TabReverse) { explore_focus_idx = (explore_focus_idx + 5) % 6; return true; }
return false;
case 3: // set-type
case 3: // set-connector-type
if (e == Event::Escape) { screen_idx = 6; return true; }
if (e == Event::Tab) { settype_focus_idx = (settype_focus_idx + 1) % 5; return true; }
if (e == Event::TabReverse) { settype_focus_idx = (settype_focus_idx + 4) % 5; return true; }

View File

@@ -188,7 +188,7 @@ private:
// and close the popup.
void ApplySignalTypeChoice();
// Filtered part list rebuild (used by connect & set-type screens)
// Filtered part list rebuild (used by connect & set-connector-type screens)
void RefreshFilteredPartList(const std::vector<std::string> &modules,
int m_idx,
const std::string &filter,

View File

@@ -14,15 +14,18 @@ Element RenderHelpPanel(const std::string &title,
Elements rows;
for (const auto &e : entries) {
rows.push_back(hbox({
text(" " + e.key) | bold | size(WIDTH, EQUAL, KEY_W),
text(e.key) | bold | size(WIDTH, EQUAL, KEY_W),
text(e.desc) | flex,
}));
}
// borderRounded gives the panel a distinct visual boundary, so the
// user can find it without ambiguity even when the main content is
// dense (e.g. the analyze screen).
return vbox({
text(" " + title + " ") | bold,
text(" " + title + " ") | bold | center,
separator(),
vbox(std::move(rows)),
}) | size(WIDTH, EQUAL, 30);
}) | borderRounded | size(WIDTH, EQUAL, 32);
}