feat(hint): H2 Phase A — hint command + F1 keybinding skeleton (ADR-0053)

The mechanism for the contextual hint, with tier-2 fallback; the
tier-3 corpus lands in later phases.

- new CommandNode `hint_id` field (all None for now)
- AppCommand::Hint + HINT grammar node + REGISTRY + dispatch
- F1 read-only overlay in handle_key (buffer/cursor/memo untouched)
- note_hint* renderers; hint_id_for_input_in_mode (shared selection
  helper refactored out of usage_keys_for_input_in_mode)
- last_error_hint_key + friendly::error_hint_class classifier
- catalogue: help.app.hint / parse.usage.hint / hint.getting_started
- +12 tests; 2483 pass / 1 ignored, clippy clean
This commit is contained in:
claude@clouddev1
2026-06-15 10:36:51 +00:00
parent 9868442889
commit 050b36391e
12 changed files with 550 additions and 32 deletions
+13
View File
@@ -1790,6 +1790,7 @@ pub static SHOW: CommandNode = CommandNode {
shape: SHOW_SHAPE,
ast_builder: build_show,
help_id: Some("data.show"),
hint_id: None,
usage_ids: &[
"parse.usage.show_data",
"parse.usage.show_table",
@@ -1805,6 +1806,7 @@ pub static SEED: CommandNode = CommandNode {
shape: SEED_SHAPE,
ast_builder: build_seed,
help_id: Some("data.seed"),
hint_id: None,
usage_ids: &["parse.usage.seed"],
};
@@ -1813,6 +1815,7 @@ pub static INSERT: CommandNode = CommandNode {
shape: INSERT_SHAPE,
ast_builder: build_insert,
help_id: Some("data.insert"),
hint_id: None,
usage_ids: &["parse.usage.insert"],};
pub static UPDATE: CommandNode = CommandNode {
@@ -1820,6 +1823,7 @@ pub static UPDATE: CommandNode = CommandNode {
shape: UPDATE_SHAPE,
ast_builder: build_update,
help_id: Some("data.update"),
hint_id: None,
usage_ids: &["parse.usage.update"],};
pub static DELETE: CommandNode = CommandNode {
@@ -1827,6 +1831,7 @@ pub static DELETE: CommandNode = CommandNode {
shape: DELETE_SHAPE,
ast_builder: build_delete,
help_id: Some("data.delete"),
hint_id: None,
usage_ids: &["parse.usage.delete"],};
pub static REPLAY: CommandNode = CommandNode {
@@ -1834,6 +1839,7 @@ pub static REPLAY: CommandNode = CommandNode {
shape: REPLAY_PATH,
ast_builder: build_replay,
help_id: Some("data.replay"),
hint_id: None,
usage_ids: &["parse.usage.replay"],};
pub static EXPLAIN: CommandNode = CommandNode {
@@ -1841,6 +1847,7 @@ pub static EXPLAIN: CommandNode = CommandNode {
shape: EXPLAIN_SHAPE,
ast_builder: build_explain,
help_id: Some("data.explain"),
hint_id: None,
usage_ids: &["parse.usage.explain"],};
/// `explain` over advanced-mode SQL (ADR-0039).
@@ -1860,6 +1867,7 @@ pub static EXPLAIN_SQL: CommandNode = CommandNode {
// too). Mirrors the `SQL_INSERT`/`SQL_UPDATE`/`SQL_DELETE`
// precedent; otherwise `note_help` would print `explain` twice.
help_id: None,
hint_id: None,
usage_ids: &[],};
/// SQL `SELECT` (ADR-0030 §6, ADR-0031, ADR-0032).
@@ -1875,6 +1883,7 @@ pub static SELECT: CommandNode = CommandNode {
shape: Node::Subgrammar(&sql_select::SQL_SELECT_TAIL),
ast_builder: build_select,
help_id: None,
hint_id: None,
usage_ids: &["parse.usage.select"],};
/// `WITH …` top-level statement (ADR-0032 §4 / sub-phase 2c).
@@ -1889,6 +1898,7 @@ pub static WITH: CommandNode = CommandNode {
shape: Node::Subgrammar(&sql_select::SQL_WITH_TAIL),
ast_builder: build_select,
help_id: None,
hint_id: None,
usage_ids: &["parse.usage.with"],};
/// SQL `INSERT` — the `Advanced`-category node of the shared
@@ -1906,6 +1916,7 @@ pub static SQL_INSERT: CommandNode = CommandNode {
shape: Node::Subgrammar(&sql_insert::SQL_INSERT_SHAPE),
ast_builder: build_sql_insert,
help_id: None,
hint_id: None,
usage_ids: &[],
};
@@ -1919,6 +1930,7 @@ pub static SQL_UPDATE: CommandNode = CommandNode {
shape: Node::Subgrammar(&sql_update::SQL_UPDATE_SHAPE),
ast_builder: build_sql_update,
help_id: None,
hint_id: None,
usage_ids: &[],
};
@@ -1934,6 +1946,7 @@ pub static SQL_DELETE: CommandNode = CommandNode {
shape: Node::Subgrammar(&sql_delete::SQL_DELETE_SHAPE),
ast_builder: build_sql_delete,
help_id: None,
hint_id: None,
usage_ids: &[],
};