1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//! # sdl-keybridge — universal Rosetta Stone for SDL keyboards
//!
//! A static correspondence table that exposes, for every key press, all
//! of its parallel representations — physical [`Scancode`], logical
//! [`Keycode`], textual or symbolic glyph, localized label — across
//! every layout × platform combination supported by SDL.
//!
//! Works with both SDL2 and SDL3 (the crate takes primitive `u32` /
//! `u16` values whose numeric assignments are identical between the two
//! versions); no `sdl2` or `sdl3` Cargo feature is needed.
//!
//! ## Philosophy: Rosette, not Champollion
//!
//! This crate is a static lookup table (the **Rosette**). It exposes
//! parallel data and individual labels. It **does not interpret** and
//! **does not package** presentation conventions.
//!
//! Anything that *interprets* — formatting a `Ctrl+Shift+A` combo,
//! serializing a binding to disk, rebasing a config from one layout to
//! another — is **Champollion territory**: the job of consuming
//! applications, which *use* the Rosette to accomplish their task.
//!
//! Concretely, the crate ships:
//! - the four lookup primitives (forward / reverse / modifier / name parser);
//! - one extension trait, [`KeyLocalizer`], for plugging in custom labels.
//!
//! It does *not* ship `format_combo()`, a binding serializer, or layout
//! auto-detection. The README documents the canonical patterns the
//! consumer assembles in 2–3 lines of glue code.
//!
//! ## The four public functions
//!
//! | Function | Purpose |
//! |----------|---------|
//! | [`resolve`][fn@resolve] | Forward lookup — every parallel representation in one pass |
//! | [`scancode_for`] | Reverse lookup — physical key for a given keycode in a layout |
//! | [`modifier_label`] | Platform-aware localized label for a held modifier |
//! | [`keycode_from_name`] | Inverse of `SDL_GetKeyName` — parse a textual name |
//!
//! ## The one extension trait
//!
//! [`KeyLocalizer`] is the single point of customization. Implementors
//! map a stable id (`"key_escape"`, `"mod_gui_mac"`, …) to a display
//! string. The crate already ships a [`MultiLocalizer`] that aggregates
//! every locale module enabled through Cargo features — most callers
//! never need to write their own.
//!
//! Add your own only when you want to override or extend the default
//! labels (e.g. brand-specific naming):
//!
//! ```
//! use std::borrow::Cow;
//! use sdl_keybridge::{KeyLocalizer, LabelStyle};
//!
//! /// A localizer that overrides the macOS Command label with "⌘ Cmd"
//! /// and falls through to the built-in lookup for everything else.
//! struct BrandedLocalizer;
//!
//! impl KeyLocalizer for BrandedLocalizer {
//! fn translate(&self, key_id: &str, _locale: &str, _style: LabelStyle)
//! -> Option<Cow<'static, str>>
//! {
//! match key_id {
//! "mod_gui_mac" => Some(Cow::Borrowed("⌘ Cmd")),
//! _ => None, // fall back to the runtime lookup chain
//! }
//! }
//! }
//! ```
//!
//! ## Cross-layout binding bridge
//!
//! Two lines of consumer code translate a binding from one layout to
//! another through scancode-as-pivot:
//!
//! ```no_run
//! use sdl_keybridge::{resolve, scancode_for, Keycode, KeyMod, LabelStyle, MultiLocalizer};
//! # let keycode_ru = Keycode::from('ф');
//! let loc = MultiLocalizer::new();
//! let sc = scancode_for(keycode_ru, "windows/ru-t-k0-jcuken").unwrap();
//! let r = resolve(sc, KeyMod::NONE, "windows/fr-t-k0-azerty", "fr", LabelStyle::Textual, &loc);
//! // r.glyph_local is what the user sees on their French AZERTY keyboard.
//! ```
//!
//! ## Module layout
//!
//! - [`scancode`] — [`Scancode`] newtype + USB HID / SDL constants
//! - [`keycode`] — [`Keycode`] newtype + `SDLK_*` constants + scancode-mask helpers
//! - [`keymod`] — [`KeyMod`] modifier bitmask (`KMOD_*`) + ergonomic predicates
//! - [`named_key`] — [`NamedKey`] taxonomy with stable `"key_*"` ids
//! - [`layout`] — [`Layout`] / [`LayoutKey`] structs + the static layout registry
//! - [`localizer`] — [`KeyLocalizer`] trait, [`MultiLocalizer`], [`Platform`], [`Modifier`], [`LabelStyle`]
//! - [`mod@resolve`] — the four public functions
//!
//! ## Cargo features
//!
//! Locales are feature-gated. The default feature is `en`. Pull only
//! what you ship for, or use the `all-locales` aggregate.
//!
//! ```toml
//! [dependencies]
//! sdl-keybridge = { version = "0.1", features = ["fr", "de", "ja"] }
//! ```
//!
//! Available codes: `ar`, `bn`, `cs`, `de`, `en`, `es`, `fi`, `fr`,
//! `hi`, `id`, `it`, `ja`, `ko`, `nl`, `pl`, `pt`, `ru`, `sk`, `sv`,
//! `sw`, `th`, `tr`, `ur`, `vi`, `zh-hans`, `zh-hant`.
//!
//! ## Bundled examples
//!
//! Two `examples/` binaries ship with the crate to validate the API
//! without writing your own driver:
//!
//! - `cargo run --example showcase --all-features` — non-interactive
//! walk-through of the eleven canonical scenarios (cross-layout char
//! resolution, locale fallback, Caps/NumLock correctness, platform
//! modifier glyphs, the bridge pattern, combo formatting).
//! - `cargo run --example inspect --all-features -- <layout> <kind> <value> [mods] [locale] [platform]`
//! — interactive inspector. Feed it a layout id and either a
//! `scancode N`, a `keycode N` (decimal or hex), or a `name "Esc"`
//! and it dumps the full [`Resolved`] in both styles, the four-level
//! layout glyph table, every [`modifier_label`] for the chosen
//! platform, and replays the same physical key on every other layout
//! (cross-layout bridge demo). Pass `?` as the layout id to list the
//! layouts compiled into the build.
//!
//! ## Non-goals
//!
//! Permanent — these will not land in this crate:
//!
//! - **Detecting the current OS layout.** No Rust solution reliably
//! covers all five SDL platforms; the caller supplies the BCP 47 id.
//! - **Dead keys / text composition.** A scancode + modifiers resolves
//! to *one* glyph. Composition (`^` + `e` → `ê`) is the OS/IME's job
//! via `SDL_StartTextInput`, not ours.
//! - **`format_combo()`.** Presentation conventions vary; the consumer
//! assembles labels with its preferred separator and ordering.
//! - **Binding serialization.** Config format is the consumer's choice
//! (JSON, INI, RON, binary, …).
//! - **`sdl2` / `sdl3` feature flags.** A single API on primitive types
//! covers both versions.
pub use ;
pub use KeyMod;
pub use ;
pub use ;
pub use NamedKey;
pub use ;
pub use Scancode;