Help: consume CommandNode.help_id — REGISTRY-driven in-app help
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.<id>`), 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.
This commit is contained in:
+38
-14
@@ -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<String> = 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Command, ValidationError>,
|
||||
#[allow(dead_code)]
|
||||
/// Catalog key (`help.<id>`) 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
|
||||
|
||||
+25
-1
@@ -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", &[]),
|
||||
(
|
||||
|
||||
@@ -208,46 +208,77 @@ help:
|
||||
import <zip> [as <t>] Unpack <zip> into a new project and
|
||||
switch to it. <t> 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 [<path>] — write a zip of project.yaml + data/ (excludes .db, history.log)
|
||||
import <zip> [as <t>] — unpack a zip and switch to the new project
|
||||
DSL data commands (in simple mode):
|
||||
create table <T> with pk [<col>:<type>...]
|
||||
drop table <T>
|
||||
add column [to] [table] <T>: <col> (<type>)
|
||||
(for serial/shortid on a non-empty table: existing rows auto-filled)
|
||||
drop column [from] [table] <T>: <col>
|
||||
rename column [in] [table] <T>: <old> to <new>
|
||||
change column [in] [table] <T>: <col> (<newtype>)
|
||||
[--force-conversion | --dont-convert]
|
||||
(to serial/shortid: null cells auto-filled with generated values)
|
||||
add 1:n relationship [as <name>] from <P>.<col> to <C>.<col>
|
||||
[on delete <action>] [on update <action>] [--create-fk]
|
||||
drop relationship <name>
|
||||
insert into <T> [(cols)] [values] (vals)
|
||||
update <T> set <c>=<v>... where <c>=<v> | --all-rows
|
||||
delete from <T> where <c>=<v> | --all-rows
|
||||
show table <T>
|
||||
show data <T>
|
||||
replay <path> — run each non-blank, non-`#`-comment line
|
||||
of <path> 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 [<path>] — write a zip of project.yaml + data/ (excludes the database file and history.log)
|
||||
import: |-
|
||||
import <zip> [as <target>] — 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 <T> with pk [<col>:<type>, ...] — create a table
|
||||
drop: |-
|
||||
drop table <T> — remove a table
|
||||
drop column [from] [table] <T>: <col> — remove a column
|
||||
drop relationship <name> — remove a relationship
|
||||
add: |-
|
||||
add column [to] [table] <T>: <col> (<type>) — add a column
|
||||
(for serial/shortid on a non-empty table: existing rows auto-filled)
|
||||
add 1:n relationship [as <name>] from <P>.<col> to <C>.<col>
|
||||
[on delete <action>] [on update <action>] [--create-fk] — declare a relationship
|
||||
rename: |-
|
||||
rename column [in] [table] <T>: <old> to <new> — rename a column
|
||||
change: |-
|
||||
change column [in] [table] <T>: <col> (<newtype>) [--force-conversion | --dont-convert]
|
||||
— change a column's type (to serial/shortid: null cells auto-filled with generated values)
|
||||
data:
|
||||
show: |-
|
||||
show table <T> — show a table's structure
|
||||
show data <T> — show a table's rows
|
||||
insert: |-
|
||||
insert into <T> [(cols)] [values] (vals) — add a row
|
||||
update: |-
|
||||
update <T> set <c>=<v>, ... where <c>=<v> | --all-rows — change matching rows
|
||||
delete: |-
|
||||
delete from <T> where <c>=<v> | --all-rows — remove matching rows
|
||||
replay: |-
|
||||
replay <path> — run each non-blank, non-`#`-comment line of <path>
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user