feat: show relationship <name> renders a styled two-table diagram (ADR-0044)
The first wired slice of relationship visualization (V1). `show relationship <name>` now renders the relationship as two full structure boxes joined by a width-jogging connector (child-left / parent-right, n…1 cardinality, on delete/update actions), styled App-side, with a vertical-stack fallback for narrow terminals. - db.rs: RelationshipDiagramData + show_relationship worker path (structured data: the relationship + both endpoint TableDescriptions) - runtime.rs: named relationships route to the structured outcome (boxed); other show <kind> forms stay prose - app.rs/event.rs/ui.rs: DslShowRelationshipSucceeded rendered App-side; new diagram OutputStyleClass variants; App::last_output_width from ui.rs - output_render.rs: styled Seg layout engine (boxes, connector routing, side-by-side + vertical), composing the ADR-0016 box primitives Tests: 4 unit + 4 integration; full suite 2201 pass / 0 fail / 1 ignored; clippy nursery clean. requirements.md V1 stays [/] (show table diagrams, compound routing, DDL-echo wiring remain).
This commit is contained in:
+52
@@ -76,6 +76,19 @@ pub enum OutputStyleClass {
|
||||
/// every `[client-side]` category-3 prose note (ADR-0038 §6).
|
||||
/// Resolves to `theme.muted`.
|
||||
Hint,
|
||||
/// A relationship-diagram box's title row — the table name
|
||||
/// (ADR-0044 §2.1). Bold accent so it cannot read as a column.
|
||||
DiagramTableName,
|
||||
/// A relationship-diagram key marker — `(PK)` / `●` on the
|
||||
/// participating columns (ADR-0044 §2.2).
|
||||
DiagramKey,
|
||||
/// A relationship-diagram cardinality label — `1` / `n`
|
||||
/// (ADR-0044 §2).
|
||||
DiagramCardinality,
|
||||
/// A relationship-diagram connector — box-drawing line, elbows
|
||||
/// and arrowhead between the two boxes (ADR-0044 §2.3). Muted so
|
||||
/// the structure, not the wiring, leads.
|
||||
DiagramConnector,
|
||||
}
|
||||
|
||||
/// A styled span of an output line: a byte range over the
|
||||
@@ -268,6 +281,11 @@ pub struct App {
|
||||
/// logical OutputLines. Required for accurate scroll capping
|
||||
/// when long lines wrap to multiple display rows.
|
||||
pub last_output_total_wrapped: usize,
|
||||
/// The most recent inner width (in columns) of the output panel,
|
||||
/// recorded by the renderer (ADR-0044 §3). Drives the relationship
|
||||
/// diagram's side-by-side vs vertical layout choice. Defaults to
|
||||
/// `80` until the first render measures the real width.
|
||||
pub last_output_width: u16,
|
||||
/// Prettified display name of the currently-open project,
|
||||
/// rendered in the status bar (P-NAME-3, ADR-0015 §2). `None`
|
||||
/// during very-early startup before the runtime has opened a
|
||||
@@ -432,6 +450,7 @@ impl App {
|
||||
output_scroll: 0,
|
||||
last_output_visible: 0,
|
||||
last_output_total_wrapped: 0,
|
||||
last_output_width: 80,
|
||||
project_name: None,
|
||||
project_is_temp: false,
|
||||
fatal_message: None,
|
||||
@@ -614,6 +633,10 @@ impl App {
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
AppEvent::DslShowRelationshipSucceeded { command, data } => {
|
||||
self.handle_dsl_show_relationship_success(&command, data.as_ref());
|
||||
Vec::new()
|
||||
}
|
||||
AppEvent::DslInsertSucceeded { command, result } => {
|
||||
self.handle_dsl_insert_success(&command, &result);
|
||||
Vec::new()
|
||||
@@ -1694,6 +1717,35 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
/// `show relationship <name>` (ADR-0044): render the relationship
|
||||
/// as a styled two-table diagram, App-side, sized to the current
|
||||
/// output-panel width. `None` is the friendly not-found line.
|
||||
fn handle_dsl_show_relationship_success(
|
||||
&mut self,
|
||||
command: &Command,
|
||||
data: Option<&crate::db::RelationshipDiagramData>,
|
||||
) {
|
||||
self.note_ok_summary(command);
|
||||
match data {
|
||||
Some(data) => {
|
||||
for line in crate::output_render::render_relationship_diagram(
|
||||
data,
|
||||
self.last_output_width,
|
||||
self.mode,
|
||||
) {
|
||||
self.push_output(line);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let name = match command {
|
||||
Command::ShowList { name: Some(n), .. } => n.as_str(),
|
||||
_ => "",
|
||||
};
|
||||
self.note_system(format!("No relationship named `{name}`."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_dsl_insert_success(&mut self, command: &Command, result: &InsertResult) {
|
||||
self.note_ok_summary(command);
|
||||
self.note_system(crate::t!("ok.rows_inserted", count = result.rows_affected));
|
||||
|
||||
Reference in New Issue
Block a user