From 03dd9003dfea154361fb95fa5ece0a787f6b9a1c Mon Sep 17 00:00:00 2001 From: "claude@clouddev1" Date: Fri, 15 May 2026 22:45:18 +0000 Subject: [PATCH] =?UTF-8?q?Help:=20consume=20CommandNode.help=5Fid=20?= =?UTF-8?q?=E2=80=94=20REGISTRY-driven=20in-app=20help?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every CommandNode declared a help_id that nothing read; the in-app `help` body was a single hand-kept catalog block that drifted from the command set (handoff-12 §2.1). note_help now iterates the command REGISTRY and translates each CommandNode's help_id (`help.`), framed by help.intro / help.dsl_section / help.types_reference. A newly-registered command appears in `help` automatically — no edit to note_help or a hand-kept list. Added 20 per-command help entries plus the 3 framing entries; removed help.in_app_body. Per-command entries use block scalars: a libyml 0.0.5 scanner bug panics on long internal space runs in double-quoted scalars, and the entries are space-aligned. --- src/app.rs | 52 +++++++++++---- src/dsl/grammar/mod.rs | 6 +- src/friendly/keys.rs | 26 +++++++- src/friendly/strings/en-US.yaml | 111 ++++++++++++++++++++------------ 4 files changed, 139 insertions(+), 56 deletions(-) diff --git a/src/app.rs b/src/app.rs index a8b6005..50d7c62 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1595,22 +1595,46 @@ impl App { } } - /// Note a flat list of currently-supported app-level - /// commands to the output panel. + /// Note the list of currently-supported commands to the + /// output panel. /// - /// This is the simple Iteration-4 stand-in for a richer - /// help system (H3 in the requirements doc); it gives the - /// user a quick "what can I type?" reference that's - /// always accurate against the build they're running. As - /// new commands land, append them here. + /// Assembled from the command REGISTRY (ADR-0024 §help_id): + /// the framing (`help.intro`, `help.dsl_section`, + /// `help.types_reference`) comes from the catalog, and each + /// command's body is the catalog entry named by its + /// `help_id`. A newly-registered command appears here + /// automatically — no edit to this function or a hand-kept + /// list. Each catalog line becomes its own `OutputLine` so + /// the scroll-position math (one logical line = one display + /// row) stays accurate per the renderer's invariant. fn note_help(&mut self) { - // Body lives in the i18n catalog (`help.in_app_body`). - // Each YAML line becomes its own `OutputLine` so the - // scroll-position math (one logical line = one display - // row) stays accurate per the renderer's invariant. - let body = crate::t!("help.in_app_body"); - for line in body.lines() { - self.note_system(line.to_string()); + use crate::dsl::grammar::REGISTRY; + + let mut lines: Vec = Vec::new(); + lines.push(crate::t!("help.intro")); + // REGISTRY is ordered app-commands first; emit the + // "DSL data commands" sub-header at the first command + // whose help_id leaves the `app.` namespace. + let mut dsl_header_done = false; + for command in REGISTRY { + let Some(help_id) = command.help_id else { + continue; + }; + if !dsl_header_done && !help_id.starts_with("app.") { + lines.push(crate::t!("help.dsl_section")); + dsl_header_done = true; + } + let key = format!("help.{help_id}"); + let body = crate::friendly::translate(&key, &[]); + lines.extend(body.lines().map(str::to_string)); + } + lines.extend( + crate::t!("help.types_reference") + .lines() + .map(str::to_string), + ); + for line in lines { + self.note_system(line); } } diff --git a/src/dsl/grammar/mod.rs b/src/dsl/grammar/mod.rs index 0a0ff7e..82bf6bb 100644 --- a/src/dsl/grammar/mod.rs +++ b/src/dsl/grammar/mod.rs @@ -351,7 +351,11 @@ pub struct CommandNode { /// as a per-node validator (Phase A: none — every app /// command's ast_builder is infallible). pub ast_builder: fn(&MatchedPath) -> Result, - #[allow(dead_code)] + /// Catalog key (`help.`) for this command's in-app + /// `help` entry. Consumed by `App::note_help`, which + /// iterates the REGISTRY and translates each `help_id` — + /// so a newly-registered command appears in `help` + /// automatically (ADR-0024 §help_id). pub help_id: Option<&'static str>, /// Catalog keys under `parse.usage.*` to render in the /// "usage:" block when a parse error fires for this command diff --git a/src/friendly/keys.rs b/src/friendly/keys.rs index f3c8f9b..c04c14d 100644 --- a/src/friendly/keys.rs +++ b/src/friendly/keys.rs @@ -120,7 +120,31 @@ pub const KEYS_AND_PLACEHOLDERS: &[(&str, &[&str])] = &[ ), // ---- Help text ---- ("help.cli_banner", &[]), - ("help.in_app_body", &[]), + // In-app `help` — framing + per-command entries keyed by + // each CommandNode's `help_id` (ADR-0024 §help_id). + ("help.intro", &[]), + ("help.dsl_section", &[]), + ("help.types_reference", &[]), + ("help.app.quit", &[]), + ("help.app.help", &[]), + ("help.app.rebuild", &[]), + ("help.app.save", &[]), + ("help.app.new", &[]), + ("help.app.load", &[]), + ("help.app.export", &[]), + ("help.app.import", &[]), + ("help.app.mode", &[]), + ("help.app.messages", &[]), + ("help.ddl.create", &[]), + ("help.ddl.drop", &[]), + ("help.ddl.add", &[]), + ("help.ddl.rename", &[]), + ("help.ddl.change", &[]), + ("help.data.show", &[]), + ("help.data.insert", &[]), + ("help.data.update", &[]), + ("help.data.delete", &[]), + ("help.data.replay", &[]), // ---- Hint panel ambient typing assistance (ADR-0022 §6) ---- ("hint.ambient_complete", &[]), ( diff --git a/src/friendly/strings/en-US.yaml b/src/friendly/strings/en-US.yaml index 9c7868c..1edc0c3 100644 --- a/src/friendly/strings/en-US.yaml +++ b/src/friendly/strings/en-US.yaml @@ -208,46 +208,77 @@ help: import [as ] Unpack into a new project and switch to it. overrides the target name (else taken from the zip). - # In-app `help` command output. Same shape as - # `cli_banner` — multi-line block, consumers iterate - # lines and emit each as its own output row so scroll - # math stays accurate. - in_app_body: | - Supported commands: - quit — exit - help — this list - mode simple|advanced — switch input mode - messages — show current verbosity - messages short|verbose— switch error wording (verbose is the default) - rebuild — rebuild .db from project.yaml + data/ (with confirmation) - save — save current temp project under a name - save as — copy current project to a new name/path - new — close current, start a fresh temp project - load — open the project picker - export [] — write a zip of project.yaml + data/ (excludes .db, history.log) - import [as ] — unpack a zip and switch to the new project - DSL data commands (in simple mode): - create table with pk [:...] - drop table - add column [to] [table] : () - (for serial/shortid on a non-empty table: existing rows auto-filled) - drop column [from] [table] : - rename column [in] [table] : to - change column [in] [table] : () - [--force-conversion | --dont-convert] - (to serial/shortid: null cells auto-filled with generated values) - add 1:n relationship [as ] from

. to . - [on delete ] [on update ] [--create-fk] - drop relationship - insert into [(cols)] [values] (vals) - update set =... where = | --all-rows - delete from where = | --all-rows - show table - show data - replay — run each non-blank, non-`#`-comment line - of as a command. Stops at the first - error (no rollback). Relative paths resolve - under the current project's directory. + # In-app `help` command output (ADR-0024 §help_id). The + # renderer iterates the command REGISTRY and translates each + # CommandNode's `help_id` — so a newly-registered command + # appears in `help` automatically, with no edit here. `intro` + # and `dsl_section` frame the two command groups; each + # `app.*` / `ddl.*` / `data.*` entry is keyed by a command's + # `help_id`; `types_reference` closes the block. All entries + # are multi-line-capable — the renderer emits one output row + # per line so scroll math stays accurate. + intro: "Supported commands:" + dsl_section: "DSL data commands (in simple mode):" + # Per-command help, keyed by `CommandNode.help_id`. Block + # scalars (`|-`) so the column alignment survives — the + # double-quoted form trips a libyml scanner bug on long + # internal space runs. The renderer emits one output row per + # line, so multi-form commands list each form on its own line. + app: + quit: |- + quit — exit the app + help: |- + help — show this command list + rebuild: |- + rebuild — rebuild the project database from project.yaml + data/ (with confirmation) + save: |- + save — save the current temp project under a name + save as — copy the current project to a new name/path + new: |- + new — close the current project, start a fresh temp project + load: |- + load — open the project picker + export: |- + export [] — write a zip of project.yaml + data/ (excludes the database file and history.log) + import: |- + import [as ] — unpack a zip into a new project and switch to it + mode: |- + mode simple|advanced — switch input mode + messages: |- + messages [short|verbose] — show or switch error-message verbosity (verbose is the default) + ddl: + create: |- + create table with pk [:, ...] — create a table + drop: |- + drop table — remove a table + drop column [from] [table] : — remove a column + drop relationship — remove a relationship + add: |- + add column [to] [table] : () — add a column + (for serial/shortid on a non-empty table: existing rows auto-filled) + add 1:n relationship [as ] from

. to . + [on delete ] [on update ] [--create-fk] — declare a relationship + rename: |- + rename column [in] [table] : to — rename a column + change: |- + change column [in] [table] : () [--force-conversion | --dont-convert] + — change a column's type (to serial/shortid: null cells auto-filled with generated values) + data: + show: |- + show table — show a table's structure + show data — show a table's rows + insert: |- + insert into [(cols)] [values] (vals) — add a row + update: |- + update set =, ... where = | --all-rows — change matching rows + delete: |- + delete from where = | --all-rows — remove matching rows + replay: |- + replay — run each non-blank, non-`#`-comment line of + as a command. Stops at the first error (no rollback); + relative paths resolve under the project directory. + # Type reference, appended after the command list. + types_reference: | Types: text, int, real, decimal, bool, date, datetime, blob, serial, shortid Auto-generated types (serial, shortid): serial — integer that auto-fills with the next sequence value