From 4bdfce62505c0f1d455c863eaf12198a08475fde Mon Sep 17 00:00:00 2001 From: "claude@clouddev1" Date: Mon, 15 Jun 2026 16:01:39 +0000 Subject: [PATCH] =?UTF-8?q?feat(hint):=20H2=20Phase=20C=20batch=201=20?= =?UTF-8?q?=E2=80=94=20app-command=20tier-3=20hints=20(ADR-0053)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per-form hints for the 14 app-lifecycle commands (quit/help/hint/ rebuild/save/new/load/export/import/mode/messages/undo/redo/copy), reference-leaning what/example with concept where it teaches (rebuild, mode, messages, undo, export, help). hint_ids wired, catalogue + keys.rs registered. +1 spot test; 2489 pass / 1 ignored, clippy clean. --- src/app.rs | 13 +++++++++ src/dsl/grammar/app.rs | 28 +++++++++--------- src/friendly/keys.rs | 35 +++++++++++++++++++++++ src/friendly/strings/en-US.yaml | 50 +++++++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 14 deletions(-) diff --git a/src/app.rs b/src/app.rs index cf22c16..4ad235f 100644 --- a/src/app.rs +++ b/src/app.rs @@ -5849,6 +5849,19 @@ mod tests { ); } + // ── Phase C batch 1: app-command hints render ─────────────── + + #[test] + fn f1_on_an_app_command_renders_its_hint_block() { + let mut app = App::new(); + type_str(&mut app, "mode advanced"); + f1(&mut app); + assert!( + output_contains(&app, "Switch between simple mode"), + "expected the `mode` tier-3 block" + ); + } + #[test] fn messages_command_toggles_verbosity_and_reports() { let mut app = App::new(); diff --git a/src/dsl/grammar/app.rs b/src/dsl/grammar/app.rs index 1deaea7..814151a 100644 --- a/src/dsl/grammar/app.rs +++ b/src/dsl/grammar/app.rs @@ -266,7 +266,7 @@ pub static QUIT: CommandNode = CommandNode { shape: EMPTY_SEQ, ast_builder: build_quit, help_id: Some("app.quit"), - hint_ids: &[], + hint_ids: &["quit"], usage_ids: &["parse.usage.quit"],}; pub static HELP: CommandNode = CommandNode { @@ -274,7 +274,7 @@ pub static HELP: CommandNode = CommandNode { shape: HELP_TOPIC_OPT, ast_builder: build_help, help_id: Some("app.help"), - hint_ids: &[], + hint_ids: &["help"], usage_ids: &["parse.usage.help"],}; pub static HINT: CommandNode = CommandNode { @@ -283,7 +283,7 @@ pub static HINT: CommandNode = CommandNode { ast_builder: build_hint, help_id: Some("app.hint"), // hint_id assigned in Phase C with the tier-3 corpus (ADR-0053). - hint_ids: &[], + hint_ids: &["hint"], usage_ids: &["parse.usage.hint"],}; pub static REBUILD: CommandNode = CommandNode { @@ -291,7 +291,7 @@ pub static REBUILD: CommandNode = CommandNode { shape: EMPTY_SEQ, ast_builder: build_rebuild, help_id: Some("app.rebuild"), - hint_ids: &[], + hint_ids: &["rebuild"], usage_ids: &["parse.usage.rebuild"],}; pub static SAVE: CommandNode = CommandNode { @@ -299,7 +299,7 @@ pub static SAVE: CommandNode = CommandNode { shape: SAVE_AS_OPT, ast_builder: build_save, help_id: Some("app.save"), - hint_ids: &[], + hint_ids: &["save"], usage_ids: &["parse.usage.save"],}; pub static NEW: CommandNode = CommandNode { @@ -307,7 +307,7 @@ pub static NEW: CommandNode = CommandNode { shape: EMPTY_SEQ, ast_builder: build_new, help_id: Some("app.new"), - hint_ids: &[], + hint_ids: &["new"], usage_ids: &["parse.usage.new"],}; pub static LOAD: CommandNode = CommandNode { @@ -315,7 +315,7 @@ pub static LOAD: CommandNode = CommandNode { shape: EMPTY_SEQ, ast_builder: build_load, help_id: Some("app.load"), - hint_ids: &[], + hint_ids: &["load"], usage_ids: &["parse.usage.load"],}; pub static EXPORT: CommandNode = CommandNode { @@ -323,7 +323,7 @@ pub static EXPORT: CommandNode = CommandNode { shape: EXPORT_PATH_OPT, ast_builder: build_export, help_id: Some("app.export"), - hint_ids: &[], + hint_ids: &["export"], usage_ids: &["parse.usage.export"],}; pub static IMPORT: CommandNode = CommandNode { @@ -331,7 +331,7 @@ pub static IMPORT: CommandNode = CommandNode { shape: IMPORT_BODY_OPT, ast_builder: build_import, help_id: Some("app.import"), - hint_ids: &[], + hint_ids: &["import"], usage_ids: &["parse.usage.import"],}; pub static MODE: CommandNode = CommandNode { @@ -339,7 +339,7 @@ pub static MODE: CommandNode = CommandNode { shape: MODE_VALUE, ast_builder: build_mode, help_id: Some("app.mode"), - hint_ids: &[], + hint_ids: &["mode"], usage_ids: &["parse.usage.mode"],}; pub static MESSAGES: CommandNode = CommandNode { @@ -347,7 +347,7 @@ pub static MESSAGES: CommandNode = CommandNode { shape: MESSAGES_VALUE_OPT, ast_builder: build_messages, help_id: Some("app.messages"), - hint_ids: &[], + hint_ids: &["messages"], usage_ids: &["parse.usage.messages"],}; pub static UNDO: CommandNode = CommandNode { @@ -355,7 +355,7 @@ pub static UNDO: CommandNode = CommandNode { shape: EMPTY_SEQ, ast_builder: build_undo, help_id: Some("app.undo"), - hint_ids: &[], + hint_ids: &["undo"], usage_ids: &["parse.usage.undo"],}; pub static REDO: CommandNode = CommandNode { @@ -363,7 +363,7 @@ pub static REDO: CommandNode = CommandNode { shape: EMPTY_SEQ, ast_builder: build_redo, help_id: Some("app.redo"), - hint_ids: &[], + hint_ids: &["redo"], usage_ids: &["parse.usage.redo"],}; pub static COPY: CommandNode = CommandNode { @@ -371,5 +371,5 @@ pub static COPY: CommandNode = CommandNode { shape: COPY_VALUE_OPT, ast_builder: build_copy, help_id: Some("app.copy"), - hint_ids: &[], + hint_ids: &["copy"], usage_ids: &["parse.usage.copy"],}; diff --git a/src/friendly/keys.rs b/src/friendly/keys.rs index 989876d..3edaaf3 100644 --- a/src/friendly/keys.rs +++ b/src/friendly/keys.rs @@ -234,6 +234,41 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[ ("hint.err.foreign_key.child_side.what", &[]), ("hint.err.foreign_key.child_side.example", &[]), ("hint.err.foreign_key.child_side.concept", &[]), + // Phase C batch 1 — app-lifecycle command hints. + ("hint.cmd.quit.what", &[]), + ("hint.cmd.quit.example", &[]), + ("hint.cmd.help.what", &[]), + ("hint.cmd.help.example", &[]), + ("hint.cmd.help.concept", &[]), + ("hint.cmd.hint.what", &[]), + ("hint.cmd.hint.example", &[]), + ("hint.cmd.rebuild.what", &[]), + ("hint.cmd.rebuild.example", &[]), + ("hint.cmd.rebuild.concept", &[]), + ("hint.cmd.save.what", &[]), + ("hint.cmd.save.example", &[]), + ("hint.cmd.new.what", &[]), + ("hint.cmd.new.example", &[]), + ("hint.cmd.load.what", &[]), + ("hint.cmd.load.example", &[]), + ("hint.cmd.export.what", &[]), + ("hint.cmd.export.example", &[]), + ("hint.cmd.export.concept", &[]), + ("hint.cmd.import.what", &[]), + ("hint.cmd.import.example", &[]), + ("hint.cmd.mode.what", &[]), + ("hint.cmd.mode.example", &[]), + ("hint.cmd.mode.concept", &[]), + ("hint.cmd.messages.what", &[]), + ("hint.cmd.messages.example", &[]), + ("hint.cmd.messages.concept", &[]), + ("hint.cmd.undo.what", &[]), + ("hint.cmd.undo.example", &[]), + ("hint.cmd.undo.concept", &[]), + ("hint.cmd.redo.what", &[]), + ("hint.cmd.redo.example", &[]), + ("hint.cmd.copy.what", &[]), + ("hint.cmd.copy.example", &[]), ( "hint.ambient_invalid_ident", &["kind", "found"], diff --git a/src/friendly/strings/en-US.yaml b/src/friendly/strings/en-US.yaml index 27ae330..c785a81 100644 --- a/src/friendly/strings/en-US.yaml +++ b/src/friendly/strings/en-US.yaml @@ -406,6 +406,56 @@ hint: what: "Link two tables so a parent row can own many child rows." example: "add 1:n relationship from Customers.id to Orders.customer_id" concept: "The \"1:n\" means one parent, many children. The child column holds the foreign key; add `--create-fk` to create that column if it doesn't exist yet." + # App-lifecycle commands (Phase C batch 1). Reference-leaning, so + # `concept` appears only where there's a real idea to teach. + quit: + what: "Leave the playground. Your project is already saved to disk." + example: "quit" + help: + what: "List every command, or show the detail for one." + example: "help insert" + concept: "`help` is the reference; press F1 while typing for a hint about the command you're building right now." + hint: + what: "Explain the most recent error — or, pressing F1 while typing, the command you're building." + example: "hint" + rebuild: + what: "Rebuild the project database from its saved text files." + example: "rebuild" + concept: "The text files (project.yaml + the data folder) are the source of truth; the database is derived and can always be rebuilt from them." + save: + what: "Save the current project under a name; `save as` copies it to a new one." + example: "save as my-shop" + new: + what: "Close the current project and start a fresh temporary one." + example: "new" + load: + what: "Open the project picker to switch to a saved project." + example: "load" + export: + what: "Write a shareable zip of the project — its text files only, never the database." + example: "export my-shop.zip" + concept: "The zip carries the schema and data as text, so anyone can rebuild the very same database from it." + import: + what: "Unpack a project zip into a new project and switch to it." + example: "import my-shop.zip as shop-copy" + mode: + what: "Switch between simple mode (the guided teaching commands) and advanced mode (raw SQL)." + example: "mode advanced" + concept: "Simple mode uses keyword commands; advanced mode lets you write SQL directly. A leading `:` runs a single advanced command without switching modes." + messages: + what: "Show or set how much detail error messages give." + example: "messages short" + concept: "Verbose (the default) adds a fix-it hint under each error headline; short shows just the headline." + undo: + what: "Undo the most recent change, after a confirmation." + example: "undo" + concept: "Every data or schema change is snapshotted first, so you can step back; `redo` re-applies what you undid." + redo: + what: "Re-apply the most recently undone change." + example: "redo" + copy: + what: "Copy the output panel to the clipboard — all of it, or just the last command's output." + example: "copy last" err: foreign_key: child_side: