A script using `duplicate` failed with "unsupported command 'duplicate'"
because the clone logic was still inline in the tui command. Extract it to
core/app/edit.hpp::duplicate_module(System*, src, dst) -> {ok, error, parts,
signals}: a deep clone of a module (parts, pins with spec + nc_origin, signals
with type overrides, pin→signal wiring; no connections), refusing on an unknown
source or an already-taken destination name.
- the tui `duplicate` command renders the result (output unchanged);
- the script engine dispatches `duplicate` to it — the failing script now runs;
- the wx GUI gains Edit ▸ Duplicate module… (PickModule + a name prompt).
tests/test_edit.cpp: deep clone wires to the clone's own signal (not the
source's) and preserves the type; unknown source / existing destination
refused. 412 core assertions green; tui + wx build clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
74 lines
2.9 KiB
C++
74 lines
2.9 KiB
C++
#ifndef _APP_EDIT_HPP_
|
|
#define _APP_EDIT_HPP_
|
|
|
|
#include "core/domain/signal_type.hpp" // SignalType
|
|
|
|
#include <string>
|
|
|
|
class Part;
|
|
class Signal;
|
|
class System;
|
|
|
|
// Application layer: UI-independent part-editing operations any frontend can
|
|
// call. No console, no dialogs, no FTXUI — Part in, result struct out.
|
|
namespace app {
|
|
|
|
// Outcome of tagging a part's connector type. The op validates the kind, sets
|
|
// the type and applies the connector model (which may materialise the layout's
|
|
// missing NC pins); the caller renders the result.
|
|
struct SetConnectorTypeResult {
|
|
bool ok = false;
|
|
std::string error; ///< set when refused (kind invalid for the part)
|
|
int materialised = 0; ///< NC pins created from the connector layout
|
|
};
|
|
|
|
// Tag `part`'s connector type and apply the matching connector model. Refuses
|
|
// (ok=false, error set, no mutation) when the kind is invalid for the part.
|
|
SetConnectorTypeResult set_connector_type(Part *part, const std::string &kind);
|
|
|
|
// Outcome of attaching a BSDL model to a part. On success the part's pin specs
|
|
// are filled from the model and its bsdl_path is recorded.
|
|
struct AttachBsdlResult {
|
|
bool ok = false;
|
|
std::string error; ///< set when the .bsd cannot be parsed
|
|
std::string entity; ///< the BSDL entity name
|
|
int bound = 0; ///< ports matched to a pin
|
|
int unbound = 0; ///< ports with no matching pin
|
|
int ports_total = 0; ///< ports declared in the model
|
|
};
|
|
|
|
// Parse the BSDL file at `path` and apply it to `part` (fills each pin's role
|
|
// and direction; records bsdl_path). Fails (ok=false, error set, no mutation)
|
|
// when the file cannot be parsed.
|
|
AttachBsdlResult attach_bsdl(Part *part, const std::string &path);
|
|
|
|
// Outcome of overriding a signal's type from a user-supplied name.
|
|
struct SetSignalTypeResult {
|
|
bool ok = false;
|
|
std::string error; ///< set when the name isn't power/gnd/other
|
|
SignalType type = SignalType::Other; ///< the resolved type (for rendering)
|
|
};
|
|
|
|
// Set `sig`'s type from `type_name` (power | gnd | other, case-insensitive).
|
|
// Fails (ok=false, error set, no mutation) on an unrecognised name.
|
|
SetSignalTypeResult set_signal_type(Signal *sig, const std::string &type_name);
|
|
|
|
// Outcome of cloning a module under a new name.
|
|
struct DuplicateResult {
|
|
bool ok = false;
|
|
std::string error; ///< unknown source, or destination name already taken
|
|
int parts = 0;
|
|
int signals = 0;
|
|
};
|
|
|
|
// Deep-clone module `src_name` as `dst_name`: parts, pins (spec + nc_origin),
|
|
// signals (with type overrides) and the pin→signal wiring — but not the
|
|
// system's connections. Fails (ok=false, error set, no change) when the source
|
|
// is unknown or the destination name already exists.
|
|
DuplicateResult duplicate_module(System *sys, const std::string &src_name,
|
|
const std::string &dst_name);
|
|
|
|
} // namespace app
|
|
|
|
#endif // _APP_EDIT_HPP_
|