Signal-type popup, NC pin tagging, interactive viewer hygiene.
- Enter on a signal entry (net / explore) opens a modal popup to pick power / gnd / other. Recording is deduped: a sequence of toggles on the same signal collapses to a single `set-signal-type` line; no-op selections record nothing. - Bare interactive commands (the ones that open a full-screen mode) are no longer recorded by `script-save`. Their inline forms still are. Mutating actions inside a screen record their own canonical line. - Mentor importer treats signals whose name starts with `unconnected` as no-connect — the pin is kept on the part without a signal and tagged `ImportedUnconnected`. - `drop_singleton_signals` runs at the end of `load`: any signal with exactly one pin is detached (singletons are NC by definition); the pin is tagged `DroppedSingleton`. Count is reported inline. - `verify` gains a one-line orphan summary (imported NC / dropped singleton totals). Pins materialised by `FillIdentityNCs` are excluded via a `pin_map` filter — they are bridged to a real signal on the peer module and are not real NCs at system level. - NcOrigin tag is serialized in save snapshots as an optional 4th field on N records (backward-compatible). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
#include "tui/tui.hpp"
|
||||
#include "tui/tui_helpers.hpp"
|
||||
|
||||
#include "system/modules.hpp"
|
||||
#include "system/signals.hpp"
|
||||
#include "system/system.hpp"
|
||||
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <ostream>
|
||||
@@ -11,6 +16,55 @@
|
||||
#include <system_error>
|
||||
#include <thread>
|
||||
|
||||
void Tui::OpenSignalTypeDialog(const std::string &mod_name,
|
||||
const std::string &sig_name) {
|
||||
if (!sys) return;
|
||||
Signal *sig = nullptr;
|
||||
try {
|
||||
Module *m = sys->modules()->get(mod_name);
|
||||
sig = m->signals->get(sig_name);
|
||||
} catch (const std::exception &) { return; }
|
||||
|
||||
sigtype_dialog_mod = mod_name;
|
||||
sigtype_dialog_sig = sig_name;
|
||||
switch (sig->type) {
|
||||
case SignalType::Power: sigtype_dialog_choice = 0; break;
|
||||
case SignalType::GndShield: sigtype_dialog_choice = 1; break;
|
||||
default: sigtype_dialog_choice = 2; break;
|
||||
}
|
||||
sigtype_dialog_open = true;
|
||||
}
|
||||
|
||||
void Tui::ApplySignalTypeChoice() {
|
||||
sigtype_dialog_open = false;
|
||||
if (!sys) return;
|
||||
SignalType t;
|
||||
switch (sigtype_dialog_choice) {
|
||||
case 0: t = SignalType::Power; break;
|
||||
case 1: t = SignalType::GndShield; break;
|
||||
default: t = SignalType::Other; break;
|
||||
}
|
||||
Signal *sig = nullptr;
|
||||
try {
|
||||
Module *m = sys->modules()->get(sigtype_dialog_mod);
|
||||
sig = m->signals->get(sigtype_dialog_sig);
|
||||
} catch (const std::exception &) { return; }
|
||||
if (sig->type == t) return; // no-op, no record
|
||||
sig->type = t;
|
||||
if (in_source) return;
|
||||
|
||||
// Dedup: if the immediately previous recorded line targets the same
|
||||
// signal, replace it so a sequence of toggles collapses to one line.
|
||||
std::string line = "set-signal-type " + sigtype_dialog_mod + " "
|
||||
+ sigtype_dialog_sig + " " + signal_type_name(t);
|
||||
std::string prefix = "set-signal-type " + sigtype_dialog_mod + " "
|
||||
+ sigtype_dialog_sig + " ";
|
||||
if (!recorded.empty() && recorded.back().rfind(prefix, 0) == 0)
|
||||
recorded.back() = std::move(line);
|
||||
else
|
||||
recorded.push_back(std::move(line));
|
||||
}
|
||||
|
||||
void Tui::Print(const std::string &line) {
|
||||
output.push_back(line);
|
||||
scroll_offset = 0; // any new line snaps the view back to the tail
|
||||
@@ -136,7 +190,12 @@ void Tui::Finalize(const std::string &name,
|
||||
static const std::set<std::string> no_record = {
|
||||
"clear", "help", "quit", "exit", "source", "script-save",
|
||||
};
|
||||
if (spec.scriptable && !no_record.count(name)) recorded.push_back(canonical);
|
||||
// A bare invocation of an `interactive` command opens a full-screen mode
|
||||
// rather than mutating state — skip it. Any mutating action taken inside
|
||||
// that screen records its own canonical line via the action callbacks.
|
||||
bool opens_screen = spec.interactive && args.empty();
|
||||
if (spec.scriptable && !opens_screen && !no_record.count(name))
|
||||
recorded.push_back(canonical);
|
||||
}
|
||||
|
||||
std::string Tui::ExpandVars(const std::string &s) const {
|
||||
|
||||
Reference in New Issue
Block a user