050b36391e
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
64 lines
2.3 KiB
Rust
64 lines
2.3 KiB
Rust
//! Friendly error layer and i18n message catalog (ADR-0019).
|
|
//!
|
|
//! Single chokepoint for user-visible message text. Engine
|
|
//! errors flow through `translate()` into a structured
|
|
//! [`FriendlyError`] payload that the renderer (in
|
|
//! `output_render`) composes into final output. Every other
|
|
//! user-visible string in the codebase migrates to this
|
|
//! catalog over time via the [`t!`] macro (ADR-0019 §9).
|
|
//!
|
|
//! ## Catalog
|
|
//!
|
|
//! The catalog lives in `strings/<locale>.yaml`, embedded at
|
|
//! compile time and parsed once on first access. Today the only
|
|
//! locale is `en-US`; runtime selection is deferred (ADR-0019
|
|
//! §8.2). Hierarchical YAML keys flatten to dot-paths
|
|
//! internally — `error.unique.insert.verbose` is the path the
|
|
//! `t!()` macro and the translator look up.
|
|
//!
|
|
//! ## The `t!()` macro
|
|
//!
|
|
//! ```ignore
|
|
//! use rdbms_playground::t;
|
|
//! let s = t!("error.unique.insert.verbose",
|
|
//! table = "Customers", column = "id");
|
|
//! ```
|
|
//!
|
|
//! Placeholder values implement `Display`. Format specifiers
|
|
//! (`{name:08.2}`, `{name:>10}`, …) are explicitly rejected at
|
|
//! substitution time — see ADR-0019 §8.4.
|
|
|
|
pub mod error;
|
|
pub mod format;
|
|
pub mod keys;
|
|
pub mod translate;
|
|
|
|
pub use error::{DiagnosticTable, FriendlyError};
|
|
pub use format::{catalog, Catalog};
|
|
pub use translate::{error_hint_class, FailureContext, Operation, TranslateContext, Verbosity};
|
|
|
|
// `translate::translate` and `format::translate` are different
|
|
// callables — the former is the structured DbError → FriendlyError
|
|
// classifier (the H1 entry point); the latter is the lower-level
|
|
// catalog lookup the `t!()` macro expands to. Re-export both
|
|
// under non-conflicting names.
|
|
pub use format::translate;
|
|
pub use translate::translate as translate_error;
|
|
|
|
/// Look up `key` in the catalog and substitute named arguments.
|
|
///
|
|
/// Panics if the key is missing, if the template has malformed
|
|
/// placeholders, or if the args don't supply every name the
|
|
/// template references. The catalog validator unit test (Step 7,
|
|
/// ADR-0019 §8.6) catches these at build time so they should
|
|
/// never fire at runtime.
|
|
#[macro_export]
|
|
macro_rules! t {
|
|
($key:literal $(, $name:ident = $value:expr)* $(,)?) => {{
|
|
$crate::friendly::translate(
|
|
$key,
|
|
&[$( (stringify!($name), &$value as &dyn ::std::fmt::Display) ),*],
|
|
)
|
|
}};
|
|
}
|