feat(hint): H2 Phase B — per-form keying + the three exemplars (ADR-0053)
The first exemplar (`add 1:n relationship`) showed per-node keying is too coarse for multi-form commands, so revise the mechanism to per-form. - CommandNode `hint_id: Option<&str>` -> `hint_ids: &[&str]` (mirrors usage_ids); hint_key_for_input_in_mode reuses a factored-out pick_form_key (shared digit/m:n/suffix form disambiguation with usage_key_for_input_in_mode) - wire INSERT + ADD (all four forms) with hint_ids - author the three approved exemplars: hint.cmd.insert, hint.cmd.add_relationship, hint.err.foreign_key.child_side (what/example/concept) + keys.rs registration - revise ADR-0053 D3 to per-form; record clause-concept hints as a deferred extension (issue #37); update README + plan - +5 tests; 2488 pass / 1 ignored, clippy clean
This commit is contained in:
+50
-1
@@ -3152,7 +3152,7 @@ impl App {
|
||||
let (view, cursor, _off) = self.feedback_view();
|
||||
let probe = view.to_string();
|
||||
let mode = self.effective_mode().as_mode();
|
||||
if let Some(id) = crate::dsl::grammar::hint_id_for_input_in_mode(&probe, mode)
|
||||
if let Some(id) = crate::dsl::grammar::hint_key_for_input_in_mode(&probe, mode)
|
||||
&& self.emit_tier3_block(&format!("hint.cmd.{id}"))
|
||||
{
|
||||
return;
|
||||
@@ -5800,6 +5800,55 @@ mod tests {
|
||||
assert!(output_contains(&app, "explain the most recent error"));
|
||||
}
|
||||
|
||||
// ── Phase B: tier-3 exemplar content renders ────────────────
|
||||
|
||||
#[test]
|
||||
fn f1_on_insert_input_renders_the_insert_hint_block() {
|
||||
let mut app = App::new();
|
||||
type_str(&mut app, "insert into Customers ");
|
||||
f1(&mut app);
|
||||
assert!(
|
||||
output_contains(&app, "Add one or more rows to a table"),
|
||||
"expected the insert tier-3 block"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f1_on_add_relationship_renders_the_relationship_block() {
|
||||
let mut app = App::new();
|
||||
type_str(&mut app, "add 1:n relationship from Customers.id to Orders.cust ");
|
||||
f1(&mut app);
|
||||
assert!(
|
||||
output_contains(&app, "one parent, many children"),
|
||||
"expected the add-relationship tier-3 block"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f1_on_add_column_does_not_render_the_relationship_block() {
|
||||
// Per-form disambiguation (ADR-0053 D3): `add column` resolves
|
||||
// to `add_column` (no tier-3 block yet → tier-2 fallback), NOT
|
||||
// the relationship block — proving the multi-form node keys
|
||||
// per form, not per node.
|
||||
let mut app = App::new();
|
||||
type_str(&mut app, "add column Note text to Customers");
|
||||
f1(&mut app);
|
||||
assert!(!output_contains(&app, "one parent, many children"));
|
||||
assert!(!output_contains(&app, "1:n"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hint_renders_the_foreign_key_error_block() {
|
||||
let mut app = App::new();
|
||||
app.last_error_hint_key = Some("foreign_key.child_side".to_string());
|
||||
type_str(&mut app, "hint");
|
||||
submit(&mut app);
|
||||
assert!(
|
||||
output_contains(&app, "doesn't match any parent row"),
|
||||
"expected the FK child-side tier-3 block"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn messages_command_toggles_verbosity_and_reports() {
|
||||
let mut app = App::new();
|
||||
|
||||
Reference in New Issue
Block a user