write!(f, "{}.{}", self.0 >> 32, self.0 & 0xffffffff)
   }
 }
-impl Debug for VisiblePieceId {
-  fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-    <Self as Display>::fmt(self, f)
-  }
-}
-impl From<VisiblePieceId> for String {
-  fn from(p: VisiblePieceId) -> String { format!("{}",p) }
-}
+display_consequential_impls!{VisiblePieceId}
 
 impl TryFrom<&str> for VisiblePieceId {
   type Error = AE;
 
 pub use crate::global::*;
 pub use crate::gamestate::*;
 pub use crate::pieces::*;
+pub use crate::keydata::*;
 
 pub type E = anyhow::Error;
 pub type AE = anyhow::Error;
 
--- /dev/null
+
+#[macro_export]
+macro_rules! display_consequential_impls {
+  ( $x:path ) => {
+    impl From<$x> for String {
+      fn from(p : $x) -> String { format!("{}",p) }
+    }
+    impl Debug for $x {
+      fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        <Self as Display>::fmt(self, f)
+      }
+    }
+  }
+}
+
+pub use crate::display_consequential_impls; // this is madness!
 
 pub mod global;
 pub mod pieces;
 pub mod gamestate;
+pub mod keydata;