feat: H3 help <command> per-command detail + general reference
HELP node takes an optional single-word topic (BarePath);
AppCommand::Help { topic }. note_help_topic renders the help
block(s) of every command sharing that entry word (so `help
create` covers both create forms), plus `help types` and a
friendly "no help for X" pointer for unknown topics. Full help
gains a detail-hint footer. Catalogued help.detail_hint /
help.unknown_topic; parse-error matrix updated (help now takes a
topic, so the near-miss is the multi-word case). 9 integration
tests in tests/it/help_command.rs. Mark H3 [x].
This commit is contained in:
+48
-2
@@ -1321,8 +1321,11 @@ impl App {
|
||||
use crate::dsl::{AppCommand, MessagesValue, ModeValue};
|
||||
match cmd {
|
||||
AppCommand::Quit => vec![Action::Quit],
|
||||
AppCommand::Help => {
|
||||
self.note_help();
|
||||
AppCommand::Help { topic } => {
|
||||
match &topic {
|
||||
Some(t) => self.note_help_topic(t),
|
||||
None => self.note_help(),
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
AppCommand::Rebuild => vec![Action::PrepareRebuild],
|
||||
@@ -2405,6 +2408,49 @@ impl App {
|
||||
.lines()
|
||||
.map(str::to_string),
|
||||
);
|
||||
// H3: point at the focused per-command form.
|
||||
lines.push(crate::t!("help.detail_hint"));
|
||||
for line in lines {
|
||||
self.note_system(line);
|
||||
}
|
||||
}
|
||||
|
||||
/// Focused per-command help (H3): `help <topic>`, where `topic`
|
||||
/// is a command entry word (`insert`, `create`, `show`, …) or
|
||||
/// the special `types`. Renders the help block(s) of every
|
||||
/// command sharing that entry word — so `help create` covers
|
||||
/// both the DSL and SQL create forms — or a friendly pointer
|
||||
/// back to `help` when nothing matches.
|
||||
fn note_help_topic(&mut self, topic: &str) {
|
||||
use crate::dsl::grammar::REGISTRY;
|
||||
|
||||
let topic = topic.trim();
|
||||
// `help types` re-shows just the type reference.
|
||||
if topic.eq_ignore_ascii_case("types") {
|
||||
for line in crate::t!("help.types_reference").lines() {
|
||||
self.note_system(line.to_string());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let mut lines: Vec<String> = Vec::new();
|
||||
for (command, _category) in REGISTRY {
|
||||
let Some(help_id) = command.help_id else {
|
||||
continue;
|
||||
};
|
||||
if command.entry.matches(topic) {
|
||||
let key = format!("help.{help_id}");
|
||||
let body = crate::friendly::translate(&key, &[]);
|
||||
lines.extend(body.lines().map(str::to_string));
|
||||
}
|
||||
}
|
||||
|
||||
if lines.is_empty() {
|
||||
// No command owns that entry word — name it and point
|
||||
// back at the full list rather than failing silently.
|
||||
self.note_system(crate::t!("help.unknown_topic", topic = topic));
|
||||
return;
|
||||
}
|
||||
for line in lines {
|
||||
self.note_system(line);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user