Skip to content

Commit 5be555a

Browse files
Patrick Carrollclaude
andcommitted
Replace ToZmk/ToQmk custom traits with standard Display and direct method calls
ToZmk was fully redundant — Display already outputs ZMK names and the ZMK renderer used format strings, never .to_zmk(). ToQmk had no stdlib equivalent, so its trait layer is removed and callers invoke qmk_name()/qmk_mod_name() directly. KeyExpr keeps a plain to_qmk() method for its recursive formatting logic. Adds Display for ModPrefix so KeyExpr::Display can use write!(f, "{prefix}({inner})"). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c5de14f commit 5be555a

2 files changed

Lines changed: 43 additions & 129 deletions

File tree

src/codes.rs

Lines changed: 37 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
//!
33
//! QMK and ZMK generally describe the same HID usages, but they often use
44
//! different symbolic names. Parsers normalize source spellings into the enums
5-
//! in this module, and renderers use [`ToQmk`] or [`ToZmk`] to write the target
6-
//! source format.
5+
//! in this module. Renderers write ZMK output via the standard [`fmt::Display`]
6+
//! impl (which uses ZMK spelling) and QMK output via each type's `qmk_name()`
7+
//! or `qmk_mod_name()` method.
78
//!
89
//! Examples of the most common spelling differences:
910
//!
@@ -17,18 +18,6 @@
1718
1819
use std::fmt;
1920

20-
/// Convert a typed domain value to ZMK source spelling.
21-
pub trait ToZmk {
22-
/// Return this value in ZMK syntax.
23-
fn to_zmk(&self) -> String;
24-
}
25-
26-
/// Convert a typed domain value to QMK source spelling.
27-
pub trait ToQmk {
28-
/// Return this value in QMK syntax.
29-
fn to_qmk(&self) -> String;
30-
}
31-
3221
macro_rules! keycodes {
3322
($(($variant:ident, $zmk:literal, $qmk:literal)),+ $(,)?) => {
3423
/// A modeled HID keycode in the converter's canonical domain.
@@ -303,18 +292,6 @@ fn keycode_from_qmk(qmk: &str) -> Option<KeyCode> {
303292
})
304293
}
305294

306-
impl ToZmk for KeyCode {
307-
fn to_zmk(&self) -> String {
308-
self.zmk_name().to_string()
309-
}
310-
}
311-
312-
impl ToQmk for KeyCode {
313-
fn to_qmk(&self) -> String {
314-
self.qmk_name().to_string()
315-
}
316-
}
317-
318295
impl fmt::Display for KeyCode {
319296
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
320297
f.write_str(self.zmk_name())
@@ -335,13 +312,24 @@ impl From<String> for KeyExpr {
335312

336313
impl PartialEq<&str> for KeyExpr {
337314
fn eq(&self, other: &&str) -> bool {
338-
self.to_zmk_string() == *other
315+
match self {
316+
Self::Key(code) => code.zmk_name() == *other,
317+
Self::Raw(raw) => raw.as_str() == *other,
318+
// Modified requires building the formatted string; allocation is unavoidable.
319+
#[allow(clippy::cmp_owned)]
320+
Self::Modified(_, _) => self.to_string() == *other,
321+
}
339322
}
340323
}
341324

342325
impl PartialEq<str> for KeyExpr {
343326
fn eq(&self, other: &str) -> bool {
344-
self.to_zmk_string() == other
327+
match self {
328+
Self::Key(code) => code.zmk_name() == other,
329+
Self::Raw(raw) => raw.as_str() == other,
330+
#[allow(clippy::cmp_owned)]
331+
Self::Modified(_, _) => self.to_string() == other,
332+
}
345333
}
346334
}
347335

@@ -442,18 +430,6 @@ impl Modifier {
442430
}
443431
}
444432

445-
impl ToZmk for Modifier {
446-
fn to_zmk(&self) -> String {
447-
self.zmk_name().to_string()
448-
}
449-
}
450-
451-
impl ToQmk for Modifier {
452-
fn to_qmk(&self) -> String {
453-
self.qmk_mod_name().to_string()
454-
}
455-
}
456-
457433
impl fmt::Display for Modifier {
458434
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
459435
f.write_str(self.zmk_name())
@@ -565,6 +541,12 @@ impl ModPrefix {
565541
}
566542
}
567543

544+
impl fmt::Display for ModPrefix {
545+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546+
f.write_str(self.zmk_name())
547+
}
548+
}
549+
568550
/// A typed key expression. Most expressions are a keycode, optionally wrapped in
569551
/// one or more modifier prefixes. `Raw` is reserved for source constructs that
570552
/// are not modeled yet but still need to round-trip visibly.
@@ -599,43 +581,24 @@ impl KeyExpr {
599581
}
600582

601583
#[must_use]
602-
pub fn to_zmk_string(&self) -> String {
603-
match self {
604-
Self::Key(code) => code.zmk_name().to_string(),
605-
Self::Modified(prefix, inner) => {
606-
format!("{}({})", prefix.zmk_name(), inner.to_zmk_string())
607-
}
608-
Self::Raw(raw) => raw.clone(),
609-
}
610-
}
611-
612-
#[must_use]
613-
pub fn to_qmk_string(&self) -> String {
584+
pub fn to_qmk(&self) -> String {
614585
match self {
615586
Self::Key(code) => code.qmk_name().to_string(),
616587
Self::Modified(prefix, inner) => {
617-
format!("{}({})", prefix.qmk_fn_name(), inner.to_qmk_string())
588+
format!("{}({})", prefix.qmk_fn_name(), inner.to_qmk())
618589
}
619590
Self::Raw(raw) => raw.clone(),
620591
}
621592
}
622593
}
623594

624-
impl ToZmk for KeyExpr {
625-
fn to_zmk(&self) -> String {
626-
self.to_zmk_string()
627-
}
628-
}
629-
630-
impl ToQmk for KeyExpr {
631-
fn to_qmk(&self) -> String {
632-
self.to_qmk_string()
633-
}
634-
}
635-
636595
impl fmt::Display for KeyExpr {
637596
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
638-
f.write_str(&self.to_zmk_string())
597+
match self {
598+
Self::Key(code) => f.write_str(code.zmk_name()),
599+
Self::Modified(prefix, inner) => write!(f, "{prefix}({inner})"),
600+
Self::Raw(raw) => f.write_str(raw),
601+
}
639602
}
640603
}
641604

@@ -736,18 +699,6 @@ impl RgbAction {
736699
}
737700
}
738701

739-
impl ToZmk for RgbAction {
740-
fn to_zmk(&self) -> String {
741-
self.zmk_name().to_string()
742-
}
743-
}
744-
745-
impl ToQmk for RgbAction {
746-
fn to_qmk(&self) -> String {
747-
self.qmk_name().to_string()
748-
}
749-
}
750-
751702
impl fmt::Display for RgbAction {
752703
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
753704
f.write_str(self.zmk_name())
@@ -974,42 +925,6 @@ impl MouseScroll {
974925
}
975926
}
976927

977-
impl ToZmk for MouseMovement {
978-
fn to_zmk(&self) -> String {
979-
self.zmk_name().to_string()
980-
}
981-
}
982-
983-
impl ToQmk for MouseMovement {
984-
fn to_qmk(&self) -> String {
985-
self.qmk_name().to_string()
986-
}
987-
}
988-
989-
impl ToZmk for MouseButton {
990-
fn to_zmk(&self) -> String {
991-
self.zmk_name().to_string()
992-
}
993-
}
994-
995-
impl ToQmk for MouseButton {
996-
fn to_qmk(&self) -> String {
997-
self.qmk_name().to_string()
998-
}
999-
}
1000-
1001-
impl ToZmk for MouseScroll {
1002-
fn to_zmk(&self) -> String {
1003-
self.zmk_name().to_string()
1004-
}
1005-
}
1006-
1007-
impl ToQmk for MouseScroll {
1008-
fn to_qmk(&self) -> String {
1009-
self.qmk_name().to_string()
1010-
}
1011-
}
1012-
1013928
impl fmt::Display for MouseMovement {
1014929
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1015930
f.write_str(self.zmk_name())
@@ -1172,10 +1087,10 @@ mod tests {
11721087

11731088
#[test]
11741089
fn keycodes_render_to_both_domains() {
1175-
assert_eq!(KeyCode::Lbkt.to_zmk(), "LBKT");
1176-
assert_eq!(KeyCode::Lbkt.to_qmk(), "KC_LBRC");
1177-
assert_eq!(KeyCode::Ret.to_zmk(), "RET");
1178-
assert_eq!(KeyCode::Ret.to_qmk(), "KC_ENTER");
1090+
assert_eq!(KeyCode::Lbkt.to_string(), "LBKT");
1091+
assert_eq!(KeyCode::Lbkt.qmk_name(), "KC_LBRC");
1092+
assert_eq!(KeyCode::Ret.to_string(), "RET");
1093+
assert_eq!(KeyCode::Ret.qmk_name(), "KC_ENTER");
11791094
}
11801095

11811096
#[test]
@@ -1190,8 +1105,8 @@ mod tests {
11901105
fn modifiers_parse_and_render() {
11911106
assert_eq!(Modifier::from_qmk("MOD_LSFT"), Some(Modifier::LShft));
11921107
assert_eq!(Modifier::from_zmk("LCTRL"), Some(Modifier::LCtrl));
1193-
assert_eq!(Modifier::LGui.to_zmk(), "LGUI");
1194-
assert_eq!(Modifier::LGui.to_qmk(), "MOD_LGUI");
1108+
assert_eq!(Modifier::LGui.to_string(), "LGUI");
1109+
assert_eq!(Modifier::LGui.qmk_mod_name(), "MOD_LGUI");
11951110
}
11961111

11971112
#[test]
@@ -1208,8 +1123,8 @@ mod tests {
12081123
assert_eq!(RgbAction::from_qmk("RGB_MOD"), Some(RgbAction::EffectNext));
12091124
assert_eq!(RgbAction::from_qmk("RGB_RMOD"), Some(RgbAction::EffectPrev));
12101125
assert_eq!(RgbAction::from_zmk("RGB_SPI"), Some(RgbAction::SpeedInc));
1211-
assert_eq!(RgbAction::EffectNext.to_zmk(), "RGB_EFF");
1212-
assert_eq!(RgbAction::EffectNext.to_qmk(), "RGB_MODE_FORWARD");
1126+
assert_eq!(RgbAction::EffectNext.to_string(), "RGB_EFF");
1127+
assert_eq!(RgbAction::EffectNext.qmk_name(), "RGB_MODE_FORWARD");
12131128
assert_eq!(RgbAction::from_qmk("NOT_RGB"), None);
12141129
}
12151130

src/qmk/mod.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ pub mod parse_json;
1111

1212
use std::fmt::Write as _;
1313

14-
use crate::codes::ToQmk as _;
1514
use crate::ir::{Key, Keyboard, TapDanceDef};
1615

1716
/// Render a `Keyboard` as a QMK Configurator JSON string.
@@ -155,16 +154,16 @@ fn key_to_qmk_str(key: &Key, tap_dances: &[TapDanceDef]) -> String {
155154
Key::Kp(key) => key.to_qmk(),
156155
Key::Mo(n) => format!("MO({n})"),
157156
Key::Tog(n) => format!("TG({n})"),
158-
Key::Sk(m) => format!("OSM({})", m.to_qmk()),
157+
Key::Sk(m) => format!("OSM({})", m.qmk_mod_name()),
159158
Key::Sl(n) => format!("OSL({n})"),
160159
Key::To(n) => format!("TO({n})"),
161160
Key::Df(n) => format!("DF({n})"),
162-
Key::Mmv(d) => d.to_qmk(),
163-
Key::Mkp(b) => b.to_qmk(),
164-
Key::Msc(d) => d.to_qmk(),
161+
Key::Mmv(d) => d.qmk_name().to_string(),
162+
Key::Mkp(b) => b.qmk_name().to_string(),
163+
Key::Msc(d) => d.qmk_name().to_string(),
165164
Key::Lt(n, k) => format!("LT({n},{})", k.to_qmk()),
166-
Key::Mt(m, k) => format!("MT({},{})", m.to_qmk(), k.to_qmk()),
167-
Key::RgbUg(a) => a.to_qmk(),
165+
Key::Mt(m, k) => format!("MT({},{})", m.qmk_mod_name(), k.to_qmk()),
166+
Key::RgbUg(a) => a.qmk_name().to_string(),
168167
Key::Macro(name) => name.clone(),
169168
Key::TapDance(n) => tap_dances.get(*n).map_or_else(
170169
|| format!("TD(DANCE_{n})"),

0 commit comments

Comments
 (0)