]> git.donarmstrong.com Git - qmk_firmware.git/commitdiff
ergodox: Update algernon's keymap to v1.6
authorGergely Nagy <algernon@madhouse-project.org>
Wed, 24 Aug 2016 11:17:01 +0000 (13:17 +0200)
committerGergely Nagy <algernon@madhouse-project.org>
Wed, 24 Aug 2016 21:22:57 +0000 (23:22 +0200)
Major changes include:

Base layer changes
------------------

* The parentheses & bracket keys have been merged: tapping them results
  in `[` or `{` (if it was shifted), double tapping leads to `(`.
* The `:;` and `-_` keys are now available on the base layer, on
  their **ADORE** location, too, just below `[{(`/`]})`.
* The `Apps` key has been replaced by `F12`.
* The `-`/`_` is no longer a tap-dance key.

ADORE layer changes
-------------------

* Adjustments were made to the **ADORE** layer, to separate some
  inconvenient combinations.

Miscellaneous changes
---------------------

* `LEAD u` now starts the symbolic unicode input system, instead of the
  OS-one.
* The mouse acceleration keys on the **Navigation and Media* layer have
  been turned into toggles: tap them once to turn them on, until tapped
  again. Tapping an accelerator button will turn all the others off.
* When the **ARROW** layer is on, the *red* and *blue* LEDs light up
  now.

Heatmap
-------

* The built-in keylogger has been greatly enhanced, it now outputs the
  pressed state, and the layer (Dvorak or ADORE). As such, the
  `ADORE_AUTOLOG` option has been removed, instead there is
  `AUTOLOG_ENABLE` now, which when enabled, makes the keylogger start
  when the keyboard boots. It defaults to off.
* The heatmap generator received a lot of updates.

Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
keyboards/ergodox/keymaps/algernon/Makefile
keyboards/ergodox/keymaps/algernon/images/adore-layer.png
keyboards/ergodox/keymaps/algernon/images/base-layer.png
keyboards/ergodox/keymaps/algernon/keymap.c
keyboards/ergodox/keymaps/algernon/readme.md
keyboards/ergodox/keymaps/algernon/tools/heatmap-adore-layout.json [deleted file]
keyboards/ergodox/keymaps/algernon/tools/heatmap-base-layout.json [deleted file]
keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.ADORE.json [new file with mode: 0644]
keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.Dvorak.json [new file with mode: 0644]
keyboards/ergodox/keymaps/algernon/tools/log-to-heatmap.py

index 00194857ac30f284826d371c3b16f8ada1be8448..7c2b3ad97cee6dacd04117eca7102c4bc2c9c43f 100644 (file)
@@ -1,22 +1,23 @@
 BOOTMAGIC_ENABLE=no
 COMMAND_ENABLE=no
 SLEEP_LED_ENABLE=no
-UNICODE_ENABLE=no
 FORCE_NKRO ?= yes
 DEBUG_ENABLE = no
 CONSOLE_ENABLE = no
 TAP_DANCE_ENABLE = yes
 KEYLOGGER_ENABLE ?= yes
+UCIS_ENABLE = yes
+MOUSEKEY_ENABLE ?= yes
 
-ADORE_AUTOLOG ?= no
+AUTOLOG_ENABLE ?= no
 
 ifeq (${FORCE_NKRO},yes)
 OPT_DEFS += -DFORCE_NKRO
 endif
 
-ifeq (${ADORE_AUTOLOG},yes)
+ifeq (${AUTOLOG_ENABLE},yes)
 KEYLOGGER_ENABLE = yes
-OPT_DEFS += -DADORE_AUTOLOG
+OPT_DEFS += -DAUTOLOG_ENABLE
 endif
 
 ifeq (${KEYLOGGER_ENABLE},yes)
index 44ad8a1eb7560b552aa6010b2051fcabb00f01cd..3d0a5fb20cd426a3a79d1b581b1a84d1cd71a8c1 100644 (file)
Binary files a/keyboards/ergodox/keymaps/algernon/images/adore-layer.png and b/keyboards/ergodox/keymaps/algernon/images/adore-layer.png differ
index da159fbe2ec5e8e084fee3b9ae934b8c1f5aadab..7ea57aae38e3833b2f8932cc83f3063b95785588 100644 (file)
Binary files a/keyboards/ergodox/keymaps/algernon/images/base-layer.png and b/keyboards/ergodox/keymaps/algernon/images/base-layer.png differ
index 144030e2e98e5bca7a555c3b581331315872e73d..9f476d8a6b5b71c58fb4622816cc6d5c98c7db89 100644 (file)
@@ -2,6 +2,7 @@
  * algernon's ErgoDox EZ layout, please see the readme.md file!
  */
 
+#include <stdarg.h>
 #include "ergodox.h"
 #include "led.h"
 #include "debug.h"
@@ -33,7 +34,6 @@ enum {
   // Buttons that do extra stuff
   A_GUI,
   A_PLVR,
-  A_ESC,
   A_MPN,
 
   // Function / number keys
@@ -47,7 +47,6 @@ enum {
   KF_8,
   KF_9,
   KF_10,
-  KF_11, // =, F11
 
   // Application select keys
   APP_SLK, // Slack
@@ -62,6 +61,11 @@ enum {
   A_MDL,
   A_MDR,
 
+  // Mouse acceleration
+  A_ACL0,
+  A_ACL1,
+  A_ACL2,
+
   // Hungarian layer keys
   HU_AA, // Á
   HU_OO, // Ó
@@ -89,7 +93,6 @@ enum {
 
 enum {
   CT_CLN = 0,
-  CT_MNS,
   CT_TA,
   CT_LBP,
   CT_RBP
@@ -102,7 +105,11 @@ uint16_t gui_timer = 0;
 uint16_t kf_timers[12];
 
 #if KEYLOGGER_ENABLE
+# ifdef AUTOLOG_ENABLE
+bool log_enable = true;
+# else
 bool log_enable = false;
+# endif
 #endif
 
 bool time_travel = false;
@@ -114,12 +121,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 /* Keymap 0: Base Layer
  *
  * ,-----------------------------------------------------.           ,-----------------------------------------------------.
- * | Next/Prev | 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr |           | Apps | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10|       F11 |
+ * | Next/Prev | 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr |           |  F12 | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10|       F11 |
  * |-----------+------+------+------+------+-------------|           |------+------+------+------+------+------+-----------|
- * |         ~ |   '  |   ,  |   .  |   P  |   Y  |   [  |           |  ]   |   F  |   G  |   C  |   R  |  L   | \         |
- * |-----------+------+------+------+------+------|      |           |      |------+------+------+------+------+-----------|
+ * |         ~ |   '  |   ,  |   .  |   P  |   Y  |   (  |           |  )   |   F  |   G  |   C  |   R  |  L   | \         |
+ * |-----------+------+------+------+------+------|   [  |           |  ]   |------+------+------+------+------+-----------|
  * | Tab/ARROW |   A  |   O  |   E  |   U  |   I  |------|           |------|   D  |   H  |   T  |   N  |  S   | = / Arrow |
- * |-----------+------+------+------+------+------|   (  |           |  )   |------+------+------+------+------+-----------|
+ * |-----------+------+------+------+------+------|   :  |           |  -   |------+------+------+------+------+-----------|
  * | Play/Pause|   /  |   Q  |   J  |   K  |   X  |      |           |      |   B  |   M  |   W  |   V  |  Z   |      Stop |
  * `-----------+------+------+------+------+-------------'           `-------------+------+------+------+------+-----------'
  *     |       |      |      |      |   :  |                                       |   -  |      |      |      |       |
@@ -135,21 +142,21 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 [BASE] = KEYMAP(
 // left hand
  M(A_MPN)           ,M(KF_1)     ,M(KF_2)     ,M(KF_3),M(KF_4),M(KF_5),M(A_PLVR)
-,KC_GRV             ,KC_QUOT     ,KC_COMM     ,KC_DOT ,KC_P   ,KC_Y   ,KC_LBRC
+,KC_GRV             ,KC_QUOT     ,KC_COMM     ,KC_DOT ,KC_P   ,KC_Y   ,TD(CT_LBP)
 ,TD(CT_TA)          ,KC_A        ,KC_O        ,KC_E   ,KC_U   ,KC_I
-,KC_MPLY            ,KC_SLSH     ,KC_Q        ,KC_J   ,KC_K   ,KC_X   ,KC_LPRN
+,KC_MPLY            ,KC_SLSH     ,KC_Q        ,KC_J   ,KC_K   ,KC_X   ,TD(CT_CLN)
 ,KC_NO              ,KC_NO       ,KC_NO       ,KC_NO  ,TD(CT_CLN)
 
                                                             ,F(F_ALT),F(F_GUI)
                                                                      ,F(F_CTRL)
-                                                    ,KC_BSPC,F(F_SFT),M(A_ESC)
+                                                    ,KC_BSPC,F(F_SFT),KC_ESC
 
                                                                 // right hand
-                                                               ,KC_APP    ,M(KF_6),M(KF_7)   ,M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11
-                                                               ,KC_RBRC   ,KC_F   ,KC_G      ,KC_C   ,KC_R    ,KC_L     ,KC_BSLS
+                                                               ,KC_F12    ,M(KF_6),M(KF_7)   ,M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11
+                                                               ,TD(CT_RBP),KC_F   ,KC_G      ,KC_C   ,KC_R    ,KC_L     ,KC_BSLS
                                                                           ,KC_D   ,KC_H      ,KC_T   ,KC_N    ,KC_S     ,KC_EQL
-                                                               ,KC_RPRN   ,KC_B   ,KC_M      ,KC_W   ,KC_V    ,KC_Z     ,KC_MSTP
-                                                                                  ,TD(CT_MNS),KC_NO  ,KC_NO   ,KC_NO    ,KC_NO
+                                                               ,KC_MINS   ,KC_B   ,KC_M      ,KC_W   ,KC_V    ,KC_Z     ,KC_MSTP
+                                                                                  ,KC_MINS   ,KC_NO  ,KC_NO   ,KC_NO    ,KC_NO
 
                                                                ,OSL(NMDIA),KC_DEL
                                                                ,KC_LEAD
@@ -159,13 +166,13 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 /* Keymap 1: Adore layer
  *
  * ,-----------------------------------------------------.           ,-----------------------------------------------------.
- * | Play/Pause| 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr |           | Apps | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10|       F11 |
+ * | Play/Pause| 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr |           |  F12 | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10|       F11 |
  * |-----------+------+------+------+------+-------------|           |------+------+------+------+------+------+-----------|
- * |        `~ |   X  |   W  |   K  |   L  |   M  |   (  |           |  )   |   F  |   H  |   C  |   P  |  Y   | \         |
+ * |        `~ |   Y  |   W  |   G  |   L  |   M  |   (  |           |  )   |   F  |   H  |   C  |   P  |  X   | \         |
  * |-----------+------+------+------+------+------|   [  |           |  ]   |------+------+------+------+------+-----------|
  * | Tab/Arrow |   A  |   O  |   E  |   I  |   U  |------|           |------|   D  |   R  |   T  |   N  |  S   | =         |
  * |-----------+------+------+------+------+------|      |           |      |------+------+------+------+------+-----------|
- * |           |   Z  |   Q  |   '  |   ,  |   .  |   :  |           |  -   |   B  |   G  |   V  |   J  |  /   |           |
+ * |           |   Z  |   Q  |   '  |   ,  |   .  |   :  |           |  -   |   B  |   K  |   V  |   J  |  /   |           |
  * `-----------+------+------+------+------+-------------'           `-------------+------+------+------+------+-----------'
  *     |       |      |      |      |      |                                       |      |      |      |      |       |
  *     `-----------------------------------'                                       `-----------------------------------'
@@ -180,20 +187,20 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 [ADORE] = KEYMAP(
 // left hand
  KC_MPLY            ,M(KF_1)     ,M(KF_2)     ,M(KF_3),M(KF_4),M(KF_5),M(A_PLVR)
-,KC_GRV             ,KC_X        ,KC_W        ,KC_K   ,KC_L   ,KC_M   ,TD(CT_LBP)
+,KC_GRV             ,KC_Y        ,KC_W        ,KC_G   ,KC_L   ,KC_M   ,TD(CT_LBP)
 ,TD(CT_TA)          ,KC_A        ,KC_O        ,KC_E   ,KC_I   ,KC_U
 ,KC_NO              ,KC_Z        ,KC_Q        ,KC_QUOT,KC_COMM,KC_DOT ,TD(CT_CLN)
 ,KC_NO              ,KC_NO       ,KC_NO       ,KC_NO  ,KC_NO
 
                                                             ,F(F_ALT),F(F_GUI)
                                                                      ,F(F_CTRL)
-                                                    ,KC_BSPC,F(F_SFT),M(A_ESC)
+                                                    ,KC_BSPC,F(F_SFT),KC_ESC
 
                                                                 // right hand
-                                                               ,KC_APP    ,M(KF_6),M(KF_7),M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11
-                                                               ,TD(CT_RBP),KC_F   ,KC_H   ,KC_C   ,KC_P    ,KC_Y     ,KC_BSLS
+                                                               ,KC_F12    ,M(KF_6),M(KF_7),M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11
+                                                               ,TD(CT_RBP),KC_F   ,KC_H   ,KC_C   ,KC_P    ,KC_X     ,KC_BSLS
                                                                           ,KC_D   ,KC_R   ,KC_T   ,KC_N    ,KC_S     ,KC_EQL
-                                                               ,TD(CT_MNS),KC_B   ,KC_G   ,KC_V   ,KC_J    ,KC_SLSH  ,KC_NO
+                                                               ,KC_MINS   ,KC_B   ,KC_K   ,KC_V   ,KC_J    ,KC_SLSH  ,KC_NO
                                                                                   ,KC_NO  ,KC_NO  ,KC_NO   ,KC_NO    ,KC_NO
 
                                                                ,OSL(NMDIA),KC_DEL
@@ -363,14 +370,14 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  */
 [NMDIA] = KEYMAP(
 // left hand
KC_ACL0    ,KC_NO       ,KC_NO      ,KC_NO   ,KC_NO   ,KC_NO   ,LGUI(KC_L)
-,KC_ACL1    ,KC_NO       ,KC_HOME    ,KC_UP   ,KC_PGUP ,KC_NO   ,KC_NO
-,KC_ACL2    ,KC_NO       ,KC_LEFT    ,KC_DOWN ,KC_RIGHT,KC_NO
M(A_ACL0)  ,KC_NO       ,KC_NO      ,KC_NO   ,KC_NO   ,KC_NO   ,LGUI(KC_L)
+,M(A_ACL1)  ,KC_NO       ,KC_HOME    ,KC_UP   ,KC_PGUP ,KC_NO   ,KC_NO
+,M(A_ACL2)  ,KC_NO       ,KC_LEFT    ,KC_DOWN ,KC_RIGHT,KC_NO
 ,KC_MPLY    ,KC_NO       ,KC_END     ,KC_DOWN ,KC_PGDN ,KC_NO   ,KC_NO
 ,KC_NO      ,KC_NO       ,KC_NO      ,KC_NO   ,KC_NO
                                                         ,KC_MUTE ,KC_VOLU
                                                                  ,KC_VOLD
-                                                 ,KC_SPC,KC_ENTER,M(A_ESC)
+                                                 ,KC_SPC,KC_ENTER,KC_ESC
 
                                                                      // right hand
                                                                      ,LGUI(KC_L),KC_NO   ,KC_NO   ,KC_NO   ,KC_NO   ,KC_NO    ,KC_NO
@@ -439,7 +446,7 @@ const uint16_t PROGMEM fn_actions[] = {
   ,[F_CTRL] = ACTION_MODS_ONESHOT (MOD_LCTL)
 };
 
-void toggle_steno(int pressed)
+static void toggle_steno(int pressed)
 {
   uint8_t layer = biton32(layer_state);
 
@@ -462,7 +469,7 @@ void toggle_steno(int pressed)
   }
 }
 
-macro_t *ang_do_hun (keyrecord_t *record, uint16_t accent, uint16_t hun_char)
+static macro_t *ang_do_hun (keyrecord_t *record, uint16_t accent, uint16_t hun_char)
 {
   uint8_t need_shift = 0;
   uint8_t hold_shift = 0;
@@ -507,46 +514,43 @@ macro_t *ang_do_hun (keyrecord_t *record, uint16_t accent, uint16_t hun_char)
   return MACRO_NONE;
 }
 
-void ang_handle_kf (keyrecord_t *record, uint8_t id)
+static bool from_appsel;
+
+static void ang_handle_kf (keyrecord_t *record, uint8_t id)
 {
   uint8_t code = id - KF_1;
 
   if (record->event.pressed) {
     kf_timers[code] = timer_read ();
   } else {
-    uint8_t kc;
+    uint8_t kc_base;
 
-    if (timer_elapsed (kf_timers[code]) > TAPPING_TERM) {
+    if (from_appsel) {
+      from_appsel = false;
+      return;
+    }
+
+    if (kf_timers[code] && timer_elapsed (kf_timers[code]) > TAPPING_TERM) {
       // Long press
-      kc = KC_F1 + code;
+      kc_base = KC_F1;
     } else {
-      if (id == KF_11)
-        kc = KC_EQL;
-      else
-        kc = KC_1 + code;
+      kc_base = KC_1;
     }
+    kf_timers[code] = 0;
+    code += kc_base;
 
-    register_code (kc);
-    unregister_code (kc);
+    register_code (code);
+    unregister_code (code);
   }
 }
 
+static struct {
+  uint8_t idx;
+} m_accel_state;
+
 const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
 {
       switch(id) {
-      case A_ESC:
-        if (record->event.pressed) {
-          if ((get_oneshot_mods ()) && !has_oneshot_mods_timed_out ()) {
-            clear_oneshot_mods ();
-          } else {
-            register_code (KC_ESC);
-          }
-          layer_off (HUN);
-        } else {
-          unregister_code (KC_ESC);
-        }
-        break;
-
       case A_MPN:
         if (record->event.pressed) {
           if (keyboard_report->mods & MOD_BIT(KC_LSFT) ||
@@ -588,6 +592,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
       case HU_UEE:
         return ang_do_hun (record, KC_EQL, KC_U);
 
+#if MOUSEKEY_ENABLE
         /* Mouse movement */
       case A_MUL:
         if (record->event.pressed) {
@@ -633,6 +638,24 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
         mousekey_send();
         break;
 
+      case A_ACL0 ... A_ACL2:
+        if (record->event.pressed) {
+          uint8_t idx = id - A_ACL0;
+          if (m_accel_state.idx == id) {
+            mousekey_off(m_accel_state.idx - A_ACL0 + KC_ACL0);
+            m_accel_state.idx = 0;
+          } else {
+            if (m_accel_state.idx) {
+              mousekey_off(m_accel_state.idx - A_ACL0 + KC_ACL0);
+              m_accel_state.idx = 0;
+            }
+            mousekey_on(KC_ACL0 + idx);
+            m_accel_state.idx = id;
+          }
+        }
+        break;
+#endif
+
         /* Plover base */
       case A_PLVR:
         toggle_steno(record->event.pressed);
@@ -663,22 +686,34 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
         break;
 
       case APP_SLK:
+        from_appsel = true;
         return MACRODOWN(T(S), T(L), T(A), T(C), T(K), T(ENT), END);
 
       case APP_EMCS:
+        from_appsel = true;
         return MACRODOWN(T(G), T(N), T(U), T(SPC), T(E), T(M), T(A), T(C), T(S), T(SPC), T(2), T(4), T(ENT), END);
 
       case APP_TERM:
-        return MACRODOWN(T(T), T(E), T(R), T(M), T(ENT), END);
+        from_appsel = true;
+        if (!record->event.pressed) {
+          register_code(KC_ESC);
+          unregister_code(KC_ESC);
+          wait_ms(TAPPING_TERM + 25);
+          register_code(KC_DEL);
+          unregister_code(KC_DEL);
+        }
+        break;
 
       case APP_CHRM:
+        from_appsel = true;
         return MACRODOWN(T(C), T(H), T(R), T(O), T(M), T(ENT), END);
 
       case APP_MSIC:
+        from_appsel = true;
         return MACRODOWN(T(R), T(H), T(Y), T(T), T(H), T(M), T(B), T(O), T(X), T(ENT), END);
 
         /* Function keys */
-      case KF_1 ... KF_11:
+      case KF_1 ... KF_10:
         ang_handle_kf (record, id);
         break;
       }
@@ -686,12 +721,14 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
       return MACRO_NONE;
 };
 
-uint8_t is_adore = 0;
+static uint8_t is_adore = 0;
 
 // Runs just one time when the keyboard initializes.
 void matrix_init_user(void) {
   uint8_t dl;
 
+  set_unicode_input_mode(UC_LNX);
+
   ergodox_led_all_on();
   for (int i = LED_BRIGHTNESS_HI; i > LED_BRIGHTNESS_LO; i--) {
     ergodox_led_all_set (i);
@@ -709,120 +746,38 @@ void matrix_init_user(void) {
   dl = eeconfig_read_default_layer ();
   if (dl == (1UL << ADORE)) {
     is_adore = 1;
-#if ADORE_AUTOLOG
-    log_enable = true;
-#endif
   }
 };
 
 LEADER_EXTERNS();
 
-void ang_do_unicode (void) {
-  register_code (KC_RCTL);
-  register_code (KC_RSFT);
-  register_code (KC_U);
-  unregister_code (KC_U);
-  unregister_code (KC_RSFT);
-  unregister_code (KC_RCTL);
-  wait_ms (100);
-}
+static void ang_tap (uint8_t code, ...) {
+  uint8_t kc = code;
+  va_list ap;
 
-void ang_tap (uint16_t codes[]) {
-  for (int i = 0; codes[i] != 0; i++) {
-    register_code (codes[i]);
-    unregister_code (codes[i]);
-    wait_ms (50);
-  }
+  va_start(ap, code);
+
+  do {
+    register_code(kc);
+    unregister_code(kc);
+    wait_ms(50);
+    kc = va_arg(ap, int);
+  } while (kc != 0);
+  va_end(ap);
 }
 
 #define TAP_ONCE(code)  \
   register_code (code); \
   unregister_code (code)
 
-void ang_tap_dance_bp_finished (qk_tap_dance_state_t *state, void *user_data) {
-  bool left, parens;
-
-  if (state->count > 2) {
-    state->count = 0;
-    return;
-  }
-
-  if (state->keycode == TD(CT_LBP))
-    left = true;
-  else
-    left = false;
-
-  if (state->count == 1)
-    parens = false;
-  else
-    parens = true;
-
-  if (parens) {
-    register_code (KC_RSFT);
-    if (left) {
-      TAP_ONCE(KC_9);
-    } else {
-      TAP_ONCE(KC_0);
-    }
-    unregister_code (KC_RSFT);
-  } else {
-    if (left) {
-      TAP_ONCE (KC_LBRC);
-    } else {
-      TAP_ONCE (KC_RBRC);
-    }
-  }
-}
-
-void ang_tap_dance_cln_finished (qk_tap_dance_state_t *state, void *user_data) {
-  if (state->count == 1) {
-    register_code (KC_RSFT);
-    register_code (KC_SCLN);
-  } else if (state->count == 2) {
-    register_code (KC_SCLN);
-  }
-}
-
-void ang_tap_dance_cln_reset (qk_tap_dance_state_t *state, void *user_data) {
-  if (state->count == 1) {
-    unregister_code (KC_SCLN);
-    unregister_code (KC_RSFT);
-  } else if (state->count == 2) {
-    unregister_code (KC_SCLN);
-  }
-}
-
-void ang_tap_dance_mns_finished (qk_tap_dance_state_t *state, void *user_data) {
-  if (state->count == 1) {
-    register_code (KC_MINS);
-  } else if (state->count == 2) {
-    register_code (KC_RSFT);
-    register_code (KC_MINS);
-  }
-}
-
-void ang_tap_dance_mns_reset (qk_tap_dance_state_t *state, void *user_data) {
-  if (state->count == 1) {
-    unregister_code (KC_MINS);
-  } else if (state->count == 2) {
-    unregister_code (KC_RSFT);
-    unregister_code (KC_MINS);
-  }
-}
-
 typedef struct {
   bool layer_toggle;
   bool sticky;
-  bool finished_once;
 } td_ta_state_t;
 
-void ang_tap_dance_ta_finished (qk_tap_dance_state_t *state, void *user_data) {
+static void ang_tap_dance_ta_finished (qk_tap_dance_state_t *state, void *user_data) {
   td_ta_state_t *td_ta = (td_ta_state_t *) user_data;
 
-  if (td_ta->finished_once) {
-    return;
-  }
-
   if (td_ta->sticky) {
     td_ta->sticky = false;
     td_ta->layer_toggle = false;
@@ -830,7 +785,6 @@ void ang_tap_dance_ta_finished (qk_tap_dance_state_t *state, void *user_data) {
     return;
   }
 
-  td_ta->finished_once = true;
   if (state->count == 1 && !state->pressed) {
     register_code (KC_TAB);
     td_ta->sticky = false;
@@ -842,35 +796,29 @@ void ang_tap_dance_ta_finished (qk_tap_dance_state_t *state, void *user_data) {
   }
 }
 
-void ang_tap_dance_ta_reset (qk_tap_dance_state_t *state, void *user_data) {
+static void ang_tap_dance_ta_reset (qk_tap_dance_state_t *state, void *user_data) {
   td_ta_state_t *td_ta = (td_ta_state_t *) user_data;
 
   if (!td_ta->layer_toggle)
     unregister_code (KC_TAB);
   if (!td_ta->sticky)
     layer_off (ARRW);
-
-  td_ta->finished_once = false;
 }
 
 qk_tap_dance_action_t tap_dance_actions[] = {
-   [CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, ang_tap_dance_cln_finished, ang_tap_dance_cln_reset)
-  ,[CT_MNS] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, ang_tap_dance_mns_finished, ang_tap_dance_mns_reset)
+   [CT_CLN] = ACTION_TAP_DANCE_DOUBLE (KC_COLN, KC_SCLN)
   ,[CT_TA]  = {
      .fn = { NULL, ang_tap_dance_ta_finished, ang_tap_dance_ta_reset },
-     .user_data = (void *)&((td_ta_state_t) { false, false, false })
+     .user_data = (void *)&((td_ta_state_t) { false, false })
    }
-  ,[CT_LBP] = ACTION_TAP_DANCE_FN (ang_tap_dance_bp_finished)
-  ,[CT_RBP] = ACTION_TAP_DANCE_FN (ang_tap_dance_bp_finished)
+  ,[CT_LBP] = ACTION_TAP_DANCE_DOUBLE (KC_LBRC, KC_LPRN)
+  ,[CT_RBP] = ACTION_TAP_DANCE_DOUBLE (KC_RBRC, KC_RPRN)
 };
 
-static uint16_t uni[32];
-static uint8_t unicnt;
-static bool unimagic = false;
-
 // Runs constantly in the background, in a loop.
 void matrix_scan_user(void) {
   uint8_t layer = biton32(layer_state);
+  bool is_arrow = false;
 
   if (gui_timer && timer_elapsed (gui_timer) > TAPPING_TERM)
     unregister_code (KC_LGUI);
@@ -893,13 +841,19 @@ void matrix_scan_user(void) {
     ergodox_right_led_2_set (LED_BRIGHTNESS_HI);
   }
 
+  if (layer_state & (1UL << ARRW)) {
+    ergodox_right_led_1_on ();
+    ergodox_right_led_3_on ();
+    is_arrow = true;
+  }
+
   if (keyboard_report->mods & MOD_BIT(KC_LSFT) ||
       ((get_oneshot_mods() & MOD_BIT(KC_LSFT)) && !has_oneshot_mods_timed_out())) {
     ergodox_right_led_1_set (LED_BRIGHTNESS_HI);
     ergodox_right_led_1_on ();
   } else {
     ergodox_right_led_1_set (LED_BRIGHTNESS_LO);
-    if (layer != NMDIA && layer != PLVR && layer != ADORE)
+    if (layer != NMDIA && layer != PLVR && layer != ADORE && !is_arrow)
       ergodox_right_led_1_off ();
   }
 
@@ -919,7 +873,7 @@ void matrix_scan_user(void) {
     ergodox_right_led_3_on ();
   } else {
     ergodox_right_led_3_set (LED_BRIGHTNESS_LO);
-    if (layer != HUN && layer != PLVR && layer != ADORE)
+    if (layer != HUN && layer != PLVR && layer != ADORE && !is_arrow)
       ergodox_right_led_3_off ();
   }
 
@@ -936,20 +890,17 @@ void matrix_scan_user(void) {
     }
 #endif
 
+    SEQ_ONE_KEY (KC_Q) {
+      register_code16 (LCTL(KC_1));
+      unregister_code16 (LCTL(KC_1));
+    }
+
     SEQ_ONE_KEY (KC_T) {
       time_travel = !time_travel;
     }
 
     SEQ_ONE_KEY (KC_U) {
-      ang_do_unicode ();
-    }
-
-    SEQ_TWO_KEYS (KC_LEAD, KC_U) {
-      unicnt = 0;
-      unimagic = true;
-      register_code(KC_RSFT);
-      TAP_ONCE(KC_U);
-      unregister_code(KC_RSFT);
+      qk_ucis_start();
     }
 
     SEQ_ONE_KEY (KC_V) {
@@ -958,25 +909,23 @@ void matrix_scan_user(void) {
 
     SEQ_ONE_KEY (KC_L) {
       /* λ */
-      ang_do_unicode ();
-
-      uint16_t codes[] = {KC_0, KC_3, KC_B, KC_B, KC_ENT, 0};
-      ang_tap (codes);
+      unicode_input_start();
+      register_hex(0x03bb);
+      unicode_input_finish();
     }
 
     SEQ_ONE_KEY (KC_Y) {
-      uint16_t codes[] = {KC_BSLS, KC_O, KC_SLSH, 0};
-      ang_tap (codes);
+      ang_tap (KC_BSLS, KC_O, KC_SLSH, 0);
     }
 
     SEQ_ONE_KEY (KC_S) {
-      ang_do_unicode (); TAP_ONCE (KC_A); TAP_ONCE (KC_F); TAP_ONCE (KC_SPC);
+      unicode_input_start(); register_hex(0xaf); unicode_input_finish();
       TAP_ONCE (KC_BSLS);
       register_code (KC_RSFT); TAP_ONCE (KC_MINS); TAP_ONCE (KC_9); unregister_code (KC_RSFT);
-      ang_do_unicode (); TAP_ONCE (KC_3); TAP_ONCE (KC_0); TAP_ONCE (KC_C); TAP_ONCE (KC_4); TAP_ONCE (KC_SPC);
+      unicode_input_start (); register_hex(0x30c4); unicode_input_finish();
       register_code (KC_RSFT); TAP_ONCE (KC_0); TAP_ONCE (KC_MINS); unregister_code (KC_RSFT);
       TAP_ONCE (KC_SLSH);
-      ang_do_unicode (); TAP_ONCE (KC_A); TAP_ONCE (KC_F); TAP_ONCE (KC_SPC);
+      unicode_input_start (); register_hex(0xaf); unicode_input_finish();
     }
 
     SEQ_TWO_KEYS (KC_W, KC_M) {
@@ -987,8 +936,7 @@ void matrix_scan_user(void) {
 
       wait_ms (1000);
 
-      uint16_t codes[] = {KC_M, KC_A, KC_X, KC_MINS, KC_F, KC_O, KC_C, KC_U, KC_S, KC_E, KC_D, KC_ENT, 0};
-      ang_tap (codes);
+      ang_tap (KC_M, KC_A, KC_X, KC_MINS, KC_F, KC_O, KC_C, KC_U, KC_S, KC_E, KC_D, KC_ENT, 0);
       register_code (KC_LGUI);
       register_code (KC_UP);
       unregister_code (KC_UP);
@@ -1013,13 +961,7 @@ void matrix_scan_user(void) {
         ergodox_right_led_2_off ();
         wait_ms (100);
         ergodox_right_led_1_off ();
-#if ADORE_AUTOLOG
-        log_enable = true;
-#endif
       } else {
-#if ADORE_AUTOLOG
-        log_enable = false;
-#endif
         is_adore = 0;
         default_layer_and (0);
         default_layer_or (1UL << BASE);
@@ -1043,140 +985,38 @@ void matrix_scan_user(void) {
 
 static uint16_t last4[4];
 
-bool is_uni_seq(char *seq) {
-  uint8_t i;
-
-  for (i = 0; seq[i]; i++) {
-    uint16_t code;
-    if (('1' <= seq[i]) && (seq[i] <= '9'))
-      code = seq[i] - '1' + KC_1;
-    else if (seq[i] == '0')
-      code = KC_0;
-    else
-      code = seq[i] - 'a' + KC_A;
-
-    if (i > unicnt)
-      return false;
-    if (uni[i] != code)
-      return false;
-  }
-
-  if (uni[i] == KC_ENT || uni[i] == KC_SPC)
-    return true;
-
-  return false;
-}
-
-uint16_t hex_to_keycode(uint8_t hex)
-{
-  if (hex == 0x0) {
-    return KC_0;
-  } else if (hex < 0xA) {
-    return KC_1 + (hex - 0x1);
-  } else {
-    return KC_A + (hex - 0xA);
-  }
-}
-
-void register_hex(uint16_t hex) {
-  bool leading_zeros = true;
-
-  for(int i = 3; i >= 0; i--) {
-    uint8_t digit = ((hex >> (i*4)) & 0xF);
-    if (digit != 0)
-      leading_zeros = false;
-    else if (leading_zeros)
-      continue;
-    register_code(hex_to_keycode(digit));
-    unregister_code(hex_to_keycode(digit));
-    wait_ms(10);
-  }
-}
-
-typedef struct {
-  char *symbol;
-  uint16_t codes[4];
-} qk_ucis_symbol_t;
-
-static qk_ucis_symbol_t ucis_symbol_table[] = {
-  {"poop", {0x1, 0xf4a9, 0}},
-  {"rofl", {0x1, 0xf923, 0}},
-  {"kiss", {0x1, 0xf619, 0}},
-  {"snowman", {0x2603, 0}},
-  {NULL, {}}
-};
-
-bool process_record_ucis (uint16_t keycode, keyrecord_t *record) {
-  uint8_t i;
-
-  if (!unimagic)
-    return true;
-
-  if (!record->event.pressed)
-    return true;
-
-  uni[unicnt] = keycode;
-  unicnt++;
-
-  if (keycode == KC_BSPC) {
-    if (unicnt >= 2) {
-      unicnt-= 2;
-      return true;
-    } else {
-      unicnt--;
-      return false;
-    }
-  }
-
-  if (keycode == KC_ENT || keycode == KC_SPC) {
-    bool symbol_found = false;
-
-    for (i = unicnt; i > 0; i--) {
-      register_code (KC_BSPC);
-      unregister_code (KC_BSPC);
-      wait_ms(10);
-    }
-
-    ang_do_unicode();
-    wait_ms(10);
-    for (i = 0; ucis_symbol_table[i].symbol; i++) {
-      if (is_uni_seq (ucis_symbol_table[i].symbol)) {
-        symbol_found = true;
-        for (uint8_t j = 0; ucis_symbol_table[i].codes[j]; j++) {
-          register_hex(ucis_symbol_table[i].codes[j]);
-        }
-        break;
-      }
-    }
-    if (!symbol_found) {
-      for (i = 0; i < unicnt - 1; i++) {
-        uint8_t code;
-
-        if (uni[i] > KF_1)
-          code = uni[i] - KF_1 + KC_1;
-        else
-          code = uni[i];
-        TAP_ONCE(code);
-        wait_ms (10);
-      }
-    }
-
-    unimagic = false;
-    return true;
-  }
-  return true;
-}
+const qk_ucis_symbol_t ucis_symbol_table[] = UCIS_TABLE
+(
+ UCIS_SYM("poop", 0x1f4a9),
+ UCIS_SYM("rofl", 0x1f923),
+ UCIS_SYM("kiss", 0x1f619),
+ UCIS_SYM("snowman", 0x2603),
+ UCIS_SYM("coffee", 0x2615),
+ UCIS_SYM("heart", 0x2764),
+ UCIS_SYM("bolt", 0x26a1)
+);
 
 bool process_record_user (uint16_t keycode, keyrecord_t *record) {
 #if KEYLOGGER_ENABLE
   if (log_enable) {
-    xprintf ("KL: col=%d, row=%d\n", record->event.key.col,
-             record->event.key.row);
+    xprintf ("KL: col=%02d, row=%02d, pressed=%d, layer=%s\n", record->event.key.col,
+             record->event.key.row, record->event.pressed, (is_adore) ? "ADORE" : "Dvorak");
   }
 #endif
 
-  if (!process_record_ucis (keycode, record))
-    return false;
+  if (keycode == KC_ESC && record->event.pressed) {
+    bool queue = true;
+
+    if ((get_oneshot_mods ()) && !has_oneshot_mods_timed_out ()) {
+      clear_oneshot_mods ();
+      queue = false;
+    }
+    if (layer_state & (1UL<<HUN)) {
+      layer_off (HUN);
+      queue = false;
+    }
+    return queue;
+  }
 
   if (time_travel && !record->event.pressed) {
     uint8_t p;
@@ -1188,15 +1028,13 @@ bool process_record_user (uint16_t keycode, keyrecord_t *record) {
     last4[3] = keycode;
 
     if (last4[0] == KC_D && last4[1] == KC_A && last4[2] == KC_T && last4[3] == KC_E) {
-      uint16_t codes[] = {KC_E, KC_SPC, KC_MINS, KC_D, KC_SPC, KC_QUOT, 0};
-      ang_tap (codes);
+      ang_tap (KC_E, KC_SPC, KC_MINS, KC_D, KC_SPC, KC_QUOT, 0);
       register_code (KC_RSFT);
       register_code (KC_EQL);
       unregister_code (KC_EQL);
       unregister_code (KC_RSFT);
 
-      uint16_t codes2[] = {KC_4, KC_SPC, KC_D, KC_A, KC_Y, KC_S, KC_QUOT, 0};
-      ang_tap (codes2);
+      ang_tap (KC_4, KC_SPC, KC_D, KC_A, KC_Y, KC_S, KC_QUOT, 0);
 
       return false;
     }
@@ -1204,3 +1042,17 @@ bool process_record_user (uint16_t keycode, keyrecord_t *record) {
 
   return true;
 }
+
+void qk_ucis_symbol_fallback (void) {
+  for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
+    uint8_t code;
+
+    if (qk_ucis_state.codes[i] > KF_1)
+      code = qk_ucis_state.codes[i] - KF_1 + KC_1;
+    else
+      code = qk_ucis_state.codes[i];
+    register_code(code);
+    unregister_code(code);
+    wait_ms (10);
+  }
+}
index 26dfddbe6a25ca64740af56112acc7cb6cd6afeb..5e7adb3320854bda5ebbbb27b789261a7ea96d07 100644 (file)
@@ -3,11 +3,15 @@
 algernon's layout
 =======================
 
-This is an unconventional layout for the ErgoDox EZ. For more details about the history of the layout, see my [blog posts about my ErgoDox journey][blog-ergodox].
+This is an unconventional layout for the [ErgoDox EZ][ez]. For more details about the history of the layout, see my [blog posts about my ErgoDox journey][blog-ergodox].
 
+ [ez]: https://ergodox-ez.com/
  [blog-ergodox]: https://asylum.madhouse-project.org/blog/tags/ergodox/
 
-Some of the things in the layout only work when one uses Spacemacs and GNOME under Linux. Your mileage may vary.
+Some of the things in the layout only work when one uses [Spacemacs][spacemacs] and [GNOME][gnome] under Linux. Your mileage may vary.
+
+ [spacemacs]: http://spacemacs.org/
+ [gnome]: https://www.gnome.org/
 
 ## Table of Contents
 
@@ -40,10 +44,10 @@ At its core, this is a Dvorak layout, with some minor changes. The more interest
 * The `GUI` key is special, because when I double-tap it, it sends `GUI + w`, which pops up an application selector. It also switches to a one-shot layer, where the number row on the left half turns into app selector macros, for the most common things I usually want to switch to. Otherwise it behaves as on a normal layout.
 * The `ESC` key also doubles as a one-shot cancel key: if tapped while any of the one-shot modifiers are in-flight (as in, single-tapped, and not expired yet), it cancels all one-shot modifiers. It also cancels the **Hun** layer, if active. Otherwise it sends the usual keycode.
 * The **Media** and **Hun** layer keys are one-shot, the **STENO** key is a toggle.
-* When holding any of the **Arrow** layer keys, the arrow layer activates while the layer key is held. Tapping the key produces the normal key.
+* When holding the `Tab`/**Arrow** key, the arrow layer activates while the key is held. Tapping the key produces the normal, `Tab` key. Double-tapping it toggles the **Arrow** layer on until a third tap.
 * Tapping the `:` key once yields `:`, tapping it twice yields `;`.
+* Tapping the `[{(`/`)}]` keys once yields `[` (or `{` when shifted), tapping them twice yields `(`.
 * The **Lead** key allows me to type in a sequence of keys, and trigger some actions:
-    - `LEAD u` enters unicode input mode, by sending the GTK+ key sequence that does this.
     - `LEAD l` uses the unicode input method to enter a `λ`.
     - `LEAD s` does a lot of magic to type in a shruggie: `¯\_(ツ)_/¯`
     - `LEAD y` types `\o/`.
@@ -52,7 +56,7 @@ At its core, this is a Dvorak layout, with some minor changes. The more interest
     - `LEAD v` prints the firmware version, the keyboard and the keymap.
     - `LEAD d` toggles logging keypress positions to the HID console.
     - `LEAD t` toggles time travel. Figuring out the current `date` is left as an exercise to the reader.
-    - `LEAD LEAD u` enters the [Unicode symbol input][#unicode-symbol-input] mode.
+    - `LEAD u` enters the [Unicode symbol input](#unicode-symbol-input) mode.
 
 ## ADORE layer
 
@@ -91,6 +95,7 @@ For the layers, the following rules apply:
 * When the [ADORE layer](#adore-layer) is toggled on, LEDs will light up from left to right in a sequence, then turn off. When the layer is toggled off, the LEDs light up and turn off in the other direction. No LEDs are on while the layer is active.
 * When the [Hungarian layer](#hungarian-layer) is active, the *green* and *blue* LEDs are on.
 * When the [Navigation and media layer](#navigation-and-media-layer) is active, the *red* and *green* ones are on.
+* When the **ARROW** layer is active, the *red* and *blue* ones are on.
 * For the [Steno layer](#steno-layer), all LEDs will be turned on.
 
 Unless noted otherwise, the layers use a dim light for the LEDs, while modifiers use a stronger one, and modifiers override any layer preferences. For example, when on the one-handed layer, with the left side active (*red* light blinking), if `Shift` is on, the *red* light will be constantly on.
@@ -116,7 +121,7 @@ This is an experimental feature, and may or may not work reliably.
 
 When the keypress logging functionality is enabled (by `LEAD d`), the keyboard will output a line every time a key is pressed, containing the position of the key in the matrix. This allows one to collect this information, and build analytics over it, such as a heat map, including dead keys too.
 
-Included with the firmware is a small tool that can parse these logs, and create a heatmap that one can import into [KLE][kle]. To use it, simply point `tools/log-to-heatmap.py` to a base layout file (one is included in the `tools/` directory), and the key position log. The latter one can create by running `hid-listen`, and redirecting its output to a file.
+Included with the firmware is a small tool that can parse these logs, and create a heatmap that one can import into [KLE][kle]. To use it, either pipe the output of `hid_listen` into it, or pipe it an already saved log, and it will save the results into files in an output directory (given on the command-line). See the output of `tools/log-to-heatmap.py --help` for more information.
 
  [kle]: http://www.keyboard-layout-editor.com/
 
@@ -151,7 +156,35 @@ The keymap default to forcing NKRO, which seems to upset Windows, and except the
 
 # Changelog
 
-## v1.5 - 2016-08-12
+## v1.6
+
+*2016-08-24*
+
+### Base layer changes
+
+* The parentheses & bracket keys have been merged: tapping them results in `[` or `{` (if it was shifted), double tapping leads to `(`.
+* The `:;` and `-_` keys are now available on the base layer, on their [ADORE](#adore-layer) location, too, just below `[{(`/`]})`.
+* The `Apps` key has been replaced by `F12`.
+* The `-`/`_` is no longer a tap-dance key.
+
+### ADORE layer changes
+
+* Adjustments were made to the [ADORE](#adore-layer) layer, to separate some inconvenient combinations.
+
+### Miscellaneous changes
+
+* `LEAD u` now starts the symbolic unicode input system, instead of the OS-one.
+* The mouse acceleration keys on the [Navigation and Media](#navigation-and-media-layer) layer have been turned into toggles: tap them once to turn them on, until tapped again. Tapping an accelerator button will turn all the others off.
+* When the **ARROW** layer is on, the *red* and *blue* LEDs light up now.
+
+### Heatmap
+
+* The built-in keylogger has been greatly enhanced, it now outputs the pressed state, and the layer (Dvorak or ADORE). As such, the `ADORE_AUTOLOG` option has been removed, instead there is `AUTOLOG_ENABLE` now, which when enabled, makes the keylogger start when the keyboard boots. It defaults to off.
+* The heatmap generator received a lot of updates.
+
+## v1.5
+
+*2016-08-12*
 
 * The **1HAND** layer has been removed.
 * A `Delete` key is now available on the right thumb cluster.
@@ -161,7 +194,9 @@ The keymap default to forcing NKRO, which seems to upset Windows, and except the
 * On the **ARROW** layer, `Backspace` has been replaced by `Enter`.
 * There is some experimental support for entering Unicode symbols.
 
-## v1.4 - 2016-07-29
+## v1.4
+
+*2016-07-29*
 
 * When toggling the key logging on or off, the LEDs will do a little dance.
 * The keylogger is now optional, but enabled by default. Use `KEYLOGGER_ENABLE=no` on the `make` command line to disable it.
@@ -169,14 +204,18 @@ The keymap default to forcing NKRO, which seems to upset Windows, and except the
 * The `-`/`_` key was turned into a tap-dance key too.
 * There is now a way to travel time with the keyboard, toggle the feature on by hitting `LEAD t`.
 
-## v1.3 - 2016-07-06
+## v1.3
+
+*2016-07-06*
 
 * Added support for logging keys, by pressing `LEAD d`. Also included is a tool to generate a [heatmap](#heatmap) out of the logs.
 * The arrow and navigation keys were rearranged again, and now require an additional key being held to activate. See the [base layer](#base-layer) for an image that shows where arrows are.
 * The **experimental** layer has been redone, and is now called [ADORE](#adore-layer), and as such, can be enabled by `LEAD a` now.
 * Switching between Dvorak and ADORE is now persisted into EEPROM, and survives a reboot.
 
-## v1.2 - 2016-06-22
+## v1.2
+
+*2016-06-22*
 
 * The forced NKRO mode can be easily toggled off at compile-time, to make the firmware compatible with [certain operating systems](#using-on-windows).
 * The `:;` key has changed behaviour: to access the `;` symbol, the key needs to be double-tapped, instead of shifted.
@@ -187,7 +226,9 @@ The keymap default to forcing NKRO, which seems to upset Windows, and except the
 * On the **experimental** layer, the `L` and `Q`, and the `K` and `G` keys were swapped.
 * The [Steno](#steno-layer) layer gained a few more `#` and `*` keys, to make it easier on my fingers.
 
-## v1.1 - 2016-06-14
+## v1.1
+
+*2016-06-14*
 
 * The keyboard starts in NKRO mode, bootmagic and other things are disabled.
 * A [Steno](#steno-layer) layer was added, to be used with Plover.
@@ -201,7 +242,9 @@ The keymap default to forcing NKRO, which seems to upset Windows, and except the
     - `:` now inputs `;` when shifted.
 * `ESC` cancels the [Hungarian](#hungarian-layer) layer too, not just modifiers.
 
-## v1.0 - 2016-05-26
+## v1.0
+
+*2016-05-26*
 
 Initial version.
 
diff --git a/keyboards/ergodox/keymaps/algernon/tools/heatmap-adore-layout.json b/keyboards/ergodox/keymaps/algernon/tools/heatmap-adore-layout.json
deleted file mode 100644 (file)
index 544f61c..0000000
+++ /dev/null
@@ -1,533 +0,0 @@
-[
-  {
-    "backcolor": "#ffffff",
-    "name": "ErgoDox - algernon's layout: Heatmap",
-    "author": "Gergely Nagy <kbd@gergo.csillger.hu>",
-    "notes": "See [here](https://github.com/algernon/ergodox-layout#readme) for the QMK keymap source.",
-    "switchMount": "cherry",
-    "switchBrand": "gateron",
-    "switchType": "KS-3-Tea",
-    "pcb": true,
-    "css": ".keyborder { -webkit-filter: blur(5px); filter: blur(5px); } .keytop { -webkit-filter: blur(10px); } .keylabels { border: 1px solid black; }"
-  },
-  [
-    {
-      "x": 3.5,
-      "c": "#a7d0db",
-      "fa": [
-        0,
-        0,
-        2
-      ]
-    },
-    "#\n3\nF3",
-    {
-      "x": 10.5,
-      "c": "#a7d0db",
-      "t": "#000000",
-      "a": 4,
-      "fa": [
-        0,
-        0,
-        2
-      ]
-    },
-    "*\n8\nF8"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 2.5,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "@\n2\nF2",
-    {
-      "x": 1,
-      "c": "#7adabd",
-      "t": "#000000"
-    },
-    "$\n4\nF4",
-    {
-      "x": 8.5
-    },
-    "&\n7\nF7",
-    {
-      "x": 1,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "(\n9\nF9"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 5.5,
-      "c": "#7adabd",
-      "t": "#000000"
-    },
-    "%\n5\nF5",
-    {
-      "c": "#f9cd31",
-      "a": 7,
-      "f": 2
-    },
-    "STENO",
-    {
-      "x": 4.5,
-      "f": 6
-    },
-    "<i class='mss mss-Unicode-Option-3'></i>",
-    {
-      "c": "#7adabd",
-      "a": 4,
-      "f": 3,
-      "fa": [
-        0,
-        0,
-        2
-      ]
-    },
-    "^\n6\nF6"
-  ],
-  [
-    {
-      "y": -0.875,
-      "c": "#ffb2d2",
-      "f": 3,
-      "w": 1.5
-    },
-    "\n\n~\n`",
-    {
-      "t": "#0d0d0b"
-    },
-    "!\n1\nF1",
-    {
-      "x": 14.5
-    },
-    ")\n0\nF10",
-    {
-      "a": 7,
-      "w": 1.5
-    },
-    "F11"
-  ],
-  [
-    {
-      "y": -0.375,
-      "x": 3.5,
-      "c": "#a7d0db",
-      "t": "#000000",
-      "a": 6
-    },
-    "L",
-    {
-      "x": 10.5
-    },
-    "C"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 2.5,
-      "c": "#bfbad1",
-      "t": "#0d0d0b",
-      "a": 4
-    },
-    ">\n.",
-    {
-      "x": 1,
-      "c": "#7adabd",
-      "t": "#000000",
-      "a": 6
-    },
-    "W",
-    {
-      "x": 8.5
-    },
-    "H",
-    {
-      "x": 1,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "P"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 5.5,
-      "c": "#7adabd",
-      "t": "#000000"
-    },
-    "M",
-    {
-      "c": "#93c9b7",
-      "a": 4,
-      "h": 1.5
-    },
-    "{\n[",
-    {
-      "x": 4.5,
-      "h": 1.5
-    },
-    "}\n]",
-    {
-      "c": "#7adabd",
-      "a": 6
-    },
-    "F"
-  ],
-  [
-    {
-      "y": -0.875,
-      "c": "#ffb07b",
-      "t": "#0d0d0b",
-      "f": 6,
-      "w": 1.5
-    },
-    "<i class='fa fa-fast-backward'></i>\n\n<i class='fa fa-fast-forward'></i>",
-    {
-      "c": "#ffb2d2",
-      "a": 4,
-      "f": 3
-    },
-    "<\n,",
-    {
-      "x": 14.5,
-      "a": 6
-    },
-    "Y",
-    {
-      "a": 4,
-      "w": 1.5
-    },
-    "|\n\\"
-  ],
-  [
-    {
-      "y": -0.375,
-      "x": 3.5,
-      "c": "#a7d0db",
-      "t": "#000000",
-      "a": 6
-    },
-    "E",
-    {
-      "x": 10.5
-    },
-    "T"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 2.5,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "O",
-    {
-      "x": 1,
-      "c": "#7adabd",
-      "t": "#000000",
-      "n": true
-    },
-    "I",
-    {
-      "x": 8.5,
-      "n": true
-    },
-    "R",
-    {
-      "x": 1,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "N"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 5.5,
-      "c": "#7adabd",
-      "t": "#000000"
-    },
-    "U",
-    {
-      "x": 6.5
-    },
-    "D"
-  ],
-  [
-    {
-      "y": -0.875,
-      "c": "#ffb2d2",
-      "t": "#0d0d0b",
-      "fa": [
-        6
-      ],
-      "w": 1.5
-    },
-    "<i class='fa fa-arrows'></i>\n\nTab",
-    {
-      "f": 3
-    },
-    "A",
-    {
-      "x": 14.5,
-      "f": 3
-    },
-    "S",
-    {
-      "a": 4,
-      "fa": [
-        0,
-        0,
-        0,
-        0,
-        0,
-        0,
-        0,
-        6
-      ],
-      "w": 1.5
-    },
-    "+\n="
-  ],
-  [
-    {
-      "y": -0.625,
-      "x": 6.5,
-      "c": "#93c9b7",
-      "t": "#000000",
-      "a": 7,
-      "h": 1.5
-    },
-    "(",
-    {
-      "x": 4.5,
-      "h": 1.5
-    },
-    ")"
-  ],
-  [
-    {
-      "y": -0.75,
-      "x": 3.5,
-      "c": "#a7d0db",
-      "a": 4,
-      "f": 3
-    },
-    "\"\n'",
-    {
-      "x": 10.5
-    },
-    "V"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 2.5,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "Z",
-    {
-      "x": 1,
-      "c": "#7adabd",
-      "t": "#000000"
-    },
-    "K",
-    {
-      "x": 8.5
-    },
-    "G",
-    {
-      "x": 1,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "J"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 5.5,
-      "c": "#7adabd",
-      "t": "#000000"
-    },
-    "X",
-    {
-      "x": 6.5
-    },
-    "B"
-  ],
-  [
-    {
-      "y": -0.875,
-      "c": "#ffb07b",
-      "f": 9,
-      "w": 1.5
-    },
-    "\n\n<i class='kb kb-Multimedia-Play-Pause'></i>",
-    {
-      "c": "#ffb2d2",
-      "t": "#0d0d0b",
-      "a": 4,
-      "f": 3
-    },
-    "?\n/",
-    {
-      "x": 14.5,
-      "a": 6
-    },
-    "Q",
-    {
-      "c": "#ffb07b",
-      "t": "#000000",
-      "f": 9,
-      "w": 1.5
-    },
-    "<i class='kb kb-Multimedia-Stop'></i>"
-  ],
-  [
-    {
-      "y": -0.375,
-      "x": 3.5,
-      "c": "#d9dae0",
-      "g": true,
-      "a": 7,
-      "f": 3
-    },
-    "",
-    {
-      "x": 10.5
-    },
-    ""
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 2.5
-    },
-    "",
-    {
-      "x": 1,
-      "c": "#d4872a",
-      "g": false,
-      "a": 5
-    },
-    ";\n:",
-    {
-      "x": 8.5
-    },
-    "_\n-",
-    {
-      "x": 1,
-      "c": "#d9dae0",
-      "g": true,
-      "a": 7
-    },
-    ""
-  ],
-  [
-    {
-      "y": -0.75,
-      "x": 0.5
-    },
-    "",
-    {},
-    "",
-    {
-      "x": 14.5
-    },
-    "",
-    {},
-    ""
-  ],
-  [
-    {
-      "r": 30,
-      "rx": 6.5,
-      "ry": 4.25,
-      "y": -1,
-      "x": 1,
-      "c": "#f9cd31",
-      "g": false
-    },
-    "Alt",
-    {
-      "a": 4,
-      "fa": [
-        0,
-        0,
-        0,
-        9
-      ]
-    },
-    "\n\n\n<i class='kb kb-logo-linux-debian fa-large'></i>"
-  ],
-  [
-    {
-      "c": "#d4872a",
-      "a": 7,
-      "f": 9,
-      "h": 2
-    },
-    "<i class='kb kb-Unicode-BackSpace-DeleteLeft-Big'></i>",
-    {
-      "h": 2
-    },
-    "<i class='fa fa-angle-double-up'></i>",
-    {
-      "c": "#f9cd31",
-      "f": 3
-    },
-    "Ctrl"
-  ],
-  [
-    {
-      "x": 2,
-      "c": "#e26757"
-    },
-    "ESC"
-  ],
-  [
-    {
-      "r": -30,
-      "rx": 13,
-      "y": -1,
-      "x": -3,
-      "c": "#f9cd31",
-      "f": 2
-    },
-    "MEDIA",
-    {},
-    "1HAND"
-  ],
-  [
-    {
-      "x": -3
-    },
-    "LEAD",
-    {
-      "c": "#d4872a",
-      "f": 9,
-      "h": 2
-    },
-    "<i class='kb kb-Return-2'></i>",
-    {
-      "f": 3,
-      "h": 2
-    },
-    "SPC"
-  ],
-  [
-    {
-      "x": -3,
-      "c": "#f9cd31",
-      "f": 2
-    },
-    "HUN"
-  ]
-]
diff --git a/keyboards/ergodox/keymaps/algernon/tools/heatmap-base-layout.json b/keyboards/ergodox/keymaps/algernon/tools/heatmap-base-layout.json
deleted file mode 100644 (file)
index 148bb1f..0000000
+++ /dev/null
@@ -1,533 +0,0 @@
-[
-  {
-    "backcolor": "#ffffff",
-    "name": "ErgoDox - algernon's layout: Heatmap",
-    "author": "Gergely Nagy <kbd@gergo.csillger.hu>",
-    "notes": "See [here](https://github.com/algernon/ergodox-layout#readme) for the QMK keymap source.",
-    "switchMount": "cherry",
-    "switchBrand": "gateron",
-    "switchType": "KS-3-Tea",
-    "pcb": true,
-    "css": ".keyborder { -webkit-filter: blur(5px); filter: blur(5px); } .keytop { -webkit-filter: blur(10px); } .keylabels { border: 1px solid black; }"
-  },
-  [
-    {
-      "x": 3.5,
-      "c": "#a7d0db",
-      "fa": [
-        0,
-        0,
-        2
-      ]
-    },
-    "#\n3\nF3",
-    {
-      "x": 10.5,
-      "c": "#a7d0db",
-      "t": "#000000",
-      "a": 4,
-      "fa": [
-        0,
-        0,
-        2
-      ]
-    },
-    "*\n8\nF8"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 2.5,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "@\n2\nF2",
-    {
-      "x": 1,
-      "c": "#7adabd",
-      "t": "#000000"
-    },
-    "$\n4\nF4",
-    {
-      "x": 8.5
-    },
-    "&\n7\nF7",
-    {
-      "x": 1,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "(\n9\nF9"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 5.5,
-      "c": "#7adabd",
-      "t": "#000000"
-    },
-    "%\n5\nF5",
-    {
-      "c": "#f9cd31",
-      "a": 7,
-      "f": 2
-    },
-    "STENO",
-    {
-      "x": 4.5,
-      "f": 6
-    },
-    "<i class='mss mss-Unicode-Option-3'></i>",
-    {
-      "c": "#7adabd",
-      "a": 4,
-      "f": 3,
-      "fa": [
-        0,
-        0,
-        2
-      ]
-    },
-    "^\n6\nF6"
-  ],
-  [
-    {
-      "y": -0.875,
-      "c": "#ffb2d2",
-      "f": 3,
-      "w": 1.5
-    },
-    "\n\n~\n`",
-    {
-      "t": "#0d0d0b"
-    },
-    "!\n1\nF1",
-    {
-      "x": 14.5
-    },
-    ")\n0\nF10",
-    {
-      "a": 7,
-      "w": 1.5
-    },
-    "F11"
-  ],
-  [
-    {
-      "y": -0.375,
-      "x": 3.5,
-      "c": "#a7d0db",
-      "t": "#000000",
-      "a": 4
-    },
-    ">\n.",
-    {
-      "x": 10.5,
-      "a": 6
-    },
-    "C"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 2.5,
-      "c": "#bfbad1",
-      "t": "#0d0d0b",
-      "a": 4
-    },
-    "<\n,",
-    {
-      "x": 1,
-      "c": "#7adabd",
-      "t": "#000000",
-      "a": 6
-    },
-    "P",
-    {
-      "x": 8.5
-    },
-    "G",
-    {
-      "x": 1,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "R"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 5.5,
-      "c": "#7adabd",
-      "t": "#000000"
-    },
-    "Y",
-    {
-      "c": "#93c9b7",
-      "a": 4,
-      "h": 1.5
-    },
-    "{\n[",
-    {
-      "x": 4.5,
-      "h": 1.5
-    },
-    "}\n]",
-    {
-      "c": "#7adabd",
-      "a": 6
-    },
-    "F"
-  ],
-  [
-    {
-      "y": -0.875,
-      "c": "#ffb07b",
-      "t": "#0d0d0b",
-      "f": 6,
-      "w": 1.5
-    },
-    "<i class='fa fa-fast-backward'></i>\n\n<i class='fa fa-fast-forward'></i>",
-    {
-      "c": "#ffb2d2",
-      "a": 4,
-      "f": 3
-    },
-    "\"\n'",
-    {
-      "x": 14.5,
-      "a": 6
-    },
-    "L",
-    {
-      "a": 4,
-      "w": 1.5
-    },
-    "|\n\\"
-  ],
-  [
-    {
-      "y": -0.375,
-      "x": 3.5,
-      "c": "#a7d0db",
-      "t": "#000000",
-      "a": 6
-    },
-    "E",
-    {
-      "x": 10.5
-    },
-    "T"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 2.5,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "O",
-    {
-      "x": 1,
-      "c": "#7adabd",
-      "t": "#000000",
-      "n": true
-    },
-    "U",
-    {
-      "x": 8.5,
-      "n": true
-    },
-    "H",
-    {
-      "x": 1,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "N"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 5.5,
-      "c": "#7adabd",
-      "t": "#000000"
-    },
-    "I",
-    {
-      "x": 6.5
-    },
-    "D"
-  ],
-  [
-    {
-      "y": -0.875,
-      "c": "#ffb2d2",
-      "t": "#0d0d0b",
-      "fa": [
-        6
-      ],
-      "w": 1.5
-    },
-    "<i class='fa fa-arrows'></i>\n\nTab",
-    {
-      "f": 3
-    },
-    "A",
-    {
-      "x": 14.5,
-      "f": 3
-    },
-    "S",
-    {
-      "a": 4,
-      "fa": [
-        0,
-        0,
-        0,
-        0,
-        0,
-        0,
-        0,
-        6
-      ],
-      "w": 1.5
-    },
-    "+\n="
-  ],
-  [
-    {
-      "y": -0.625,
-      "x": 6.5,
-      "c": "#93c9b7",
-      "t": "#000000",
-      "a": 7,
-      "h": 1.5
-    },
-    "(",
-    {
-      "x": 4.5,
-      "h": 1.5
-    },
-    ")"
-  ],
-  [
-    {
-      "y": -0.75,
-      "x": 3.5,
-      "c": "#a7d0db",
-      "a": 6
-    },
-    "J",
-    {
-      "x": 10.5
-    },
-    "W"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 2.5,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "Q",
-    {
-      "x": 1,
-      "c": "#7adabd",
-      "t": "#000000"
-    },
-    "K",
-    {
-      "x": 8.5
-    },
-    "M",
-    {
-      "x": 1,
-      "c": "#bfbad1",
-      "t": "#0d0d0b"
-    },
-    "V"
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 5.5,
-      "c": "#7adabd",
-      "t": "#000000"
-    },
-    "X",
-    {
-      "x": 6.5
-    },
-    "B"
-  ],
-  [
-    {
-      "y": -0.875,
-      "c": "#ffb07b",
-      "f": 9,
-      "w": 1.5
-    },
-    "\n\n<i class='kb kb-Multimedia-Play-Pause'></i>",
-    {
-      "c": "#ffb2d2",
-      "t": "#0d0d0b",
-      "a": 4,
-      "f": 3
-    },
-    "?\n/",
-    {
-      "x": 14.5,
-      "a": 6
-    },
-    "Z",
-    {
-      "c": "#ffb07b",
-      "t": "#000000",
-      "f": 9,
-      "w": 1.5
-    },
-    "<i class='kb kb-Multimedia-Stop'></i>"
-  ],
-  [
-    {
-      "y": -0.375,
-      "x": 3.5,
-      "c": "#d9dae0",
-      "g": true,
-      "a": 7,
-      "f": 3
-    },
-    "",
-    {
-      "x": 10.5
-    },
-    ""
-  ],
-  [
-    {
-      "y": -0.875,
-      "x": 2.5
-    },
-    "",
-    {
-      "x": 1,
-      "c": "#d4872a",
-      "g": false,
-      "a": 5
-    },
-    ";\n:",
-    {
-      "x": 8.5
-    },
-    "_\n-",
-    {
-      "x": 1,
-      "c": "#d9dae0",
-      "g": true,
-      "a": 7
-    },
-    ""
-  ],
-  [
-    {
-      "y": -0.75,
-      "x": 0.5
-    },
-    "",
-    {},
-    "",
-    {
-      "x": 14.5
-    },
-    "",
-    {},
-    ""
-  ],
-  [
-    {
-      "r": 30,
-      "rx": 6.5,
-      "ry": 4.25,
-      "y": -1,
-      "x": 1,
-      "c": "#f9cd31",
-      "g": false
-    },
-    "Alt",
-    {
-      "a": 4,
-      "fa": [
-        0,
-        0,
-        0,
-        9
-      ]
-    },
-    "\n\n\n<i class='kb kb-logo-linux-debian fa-large'></i>"
-  ],
-  [
-    {
-      "c": "#d4872a",
-      "a": 7,
-      "f": 9,
-      "h": 2
-    },
-    "<i class='kb kb-Unicode-BackSpace-DeleteLeft-Big'></i>",
-    {
-      "h": 2
-    },
-    "<i class='fa fa-angle-double-up'></i>",
-    {
-      "c": "#f9cd31",
-      "f": 3
-    },
-    "Ctrl"
-  ],
-  [
-    {
-      "x": 2,
-      "c": "#e26757"
-    },
-    "ESC"
-  ],
-  [
-    {
-      "r": -30,
-      "rx": 13,
-      "y": -1,
-      "x": -3,
-      "c": "#f9cd31",
-      "f": 2
-    },
-    "MEDIA",
-    {},
-    "1HAND"
-  ],
-  [
-    {
-      "x": -3
-    },
-    "LEAD",
-    {
-      "c": "#d4872a",
-      "f": 9,
-      "h": 2
-    },
-    "<i class='kb kb-Return-2'></i>",
-    {
-      "f": 3,
-      "h": 2
-    },
-    "SPC"
-  ],
-  [
-    {
-      "x": -3,
-      "c": "#f9cd31",
-      "f": 2
-    },
-    "HUN"
-  ]
-]
diff --git a/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.ADORE.json b/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.ADORE.json
new file mode 100644 (file)
index 0000000..4dfa877
--- /dev/null
@@ -0,0 +1,553 @@
+[
+  {
+    "backcolor": "#ffffff",
+    "name": "ErgoDox - algernon's layout: Heatmap",
+    "author": "Gergely Nagy <kbd@gergo.csillger.hu>",
+    "notes": "See [here](https://github.com/algernon/ergodox-layout#readme) for the QMK keymap source.",
+    "switchMount": "cherry",
+    "switchBrand": "gateron",
+    "switchType": "KS-3-Tea",
+    "pcb": true,
+    "css": ".keyborder { -webkit-filter: blur(5px); filter: blur(5px); } .keytop { -webkit-filter: blur(10px); } .keylabels { border: 1px solid black; }"
+  },
+  [
+    {
+      "x": 3.5,
+      "c": "#a7d0db",
+      "fa": [
+        0,
+        0,
+        2
+      ]
+    },
+    "#\n3\nF3",
+    {
+      "x": 10.5,
+      "c": "#a7d0db",
+      "t": "#000000",
+      "a": 4,
+      "fa": [
+        0,
+        0,
+        2
+      ]
+    },
+    "*\n8\nF8"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 2.5,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "@\n2\nF2",
+    {
+      "x": 1,
+      "c": "#7adabd",
+      "t": "#000000"
+    },
+    "$\n4\nF4",
+    {
+      "x": 8.5
+    },
+    "&\n7\nF7",
+    {
+      "x": 1,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "(\n9\nF9"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 5.5,
+      "c": "#7adabd",
+      "t": "#000000"
+    },
+    "%\n5\nF5",
+    {
+      "c": "#f9cd31",
+      "a": 7,
+      "f": 2
+    },
+    "STENO",
+    {
+      "x": 4.5,
+      "f": 3
+    },
+    "F12",
+    {
+      "c": "#7adabd",
+      "a": 4,
+      "f": 3,
+      "fa": [
+        0,
+        0,
+        2
+      ]
+    },
+    "^\n6\nF6"
+  ],
+  [
+    {
+      "y": -0.875,
+      "c": "#ffb2d2",
+      "f": 9,
+      "a": 6,
+      "w": 1.5
+    },
+    "\n\n<i class='kb kb-Multimedia-Play-Pause'></i>",
+    {
+      "t": "#0d0d0b",
+      "f": 3,
+      "a": 4,
+      "fa": [
+          0,
+          0,
+          2
+      ]
+    },
+    "!\n1\nF1",
+    {
+      "x": 14.5
+    },
+    ")\n0\nF10",
+    {
+      "a": 7,
+      "w": 1.5
+    },
+    "F11"
+  ],
+  [
+    {
+      "y": -0.375,
+      "x": 3.5,
+      "c": "#a7d0db",
+      "t": "#000000",
+      "a": 6
+    },
+    "G",
+    {
+      "x": 10.5
+    },
+    "C"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 2.5,
+      "c": "#bfbad1",
+      "t": "#0d0d0b",
+      "a": 6
+    },
+    "W",
+    {
+      "x": 1,
+      "c": "#7adabd",
+      "t": "#000000",
+      "a": 6
+    },
+    "L",
+    {
+      "x": 8.5
+    },
+    "H",
+    {
+      "x": 1,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "P"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 5.5,
+      "c": "#7adabd",
+      "t": "#000000"
+    },
+    "M",
+    {
+      "c": "#93c9b7",
+      "a": 4,
+      "fa": [0, 0, 0],
+      "h": 1.5
+    },
+    "{\n(\n[",
+    {
+      "x": 4.5,
+      "h": 1.5
+    },
+    "}\n)\n]",
+    {
+      "c": "#7adabd",
+      "a": 6
+    },
+    "F"
+  ],
+  [
+    {
+      "y": -0.875,
+      "c": "#ffb07b",
+      "t": "#0d0d0b",
+      "f": 3,
+      "a": 4,
+      "w": 1.5
+    },
+    "\n\n~\n`",
+    {
+      "c": "#ffb2d2",
+      "a": 6,
+      "f": 3
+    },
+    "Y",
+    {
+      "x": 14.5,
+      "a": 6
+    },
+    "X",
+    {
+      "a": 4,
+      "w": 1.5
+    },
+    "|\n\\"
+  ],
+  [
+    {
+      "y": -0.375,
+      "x": 3.5,
+      "c": "#a7d0db",
+      "t": "#000000",
+      "a": 6
+    },
+    "E",
+    {
+      "x": 10.5
+    },
+    "T"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 2.5,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "O",
+    {
+      "x": 1,
+      "c": "#7adabd",
+      "t": "#000000",
+      "n": true
+    },
+    "I",
+    {
+      "x": 8.5,
+      "n": true
+    },
+    "R",
+    {
+      "x": 1,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "N"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 5.5,
+      "c": "#7adabd",
+      "t": "#000000"
+    },
+    "U",
+    {
+      "x": 6.5
+    },
+    "D"
+  ],
+  [
+    {
+      "y": -0.875,
+      "c": "#ffb2d2",
+      "t": "#0d0d0b",
+      "fa": [
+        6
+      ],
+      "w": 1.5
+    },
+    "<i class='fa fa-arrows'></i>\n\nTab",
+    {
+      "f": 3
+    },
+    "A",
+    {
+      "x": 14.5,
+      "f": 3
+    },
+    "S",
+    {
+      "a": 4,
+      "fa": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        6
+      ],
+      "w": 1.5
+    },
+    "+\n="
+  ],
+  [
+    {
+      "y": -0.625,
+      "x": 6.5,
+      "c": "#93c9b7",
+      "t": "#000000",
+      "h": 1.5
+    },
+    ";\n:",
+    {
+      "x": 4.5,
+      "h": 1.5
+    },
+    "_\n-"
+  ],
+  [
+    {
+      "y": -0.75,
+      "x": 3.5,
+      "c": "#a7d0db",
+      "a": 4,
+      "f": 3
+    },
+    "\"\n'",
+    {
+      "x": 10.5,
+      "a": 6,
+      "f": 3
+    },
+    "V"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 2.5,
+      "c": "#bfbad1",
+      "t": "#0d0d0b",
+      "a": 6
+    },
+    "Q",
+    {
+      "x": 1,
+      "c": "#7adabd",
+      "t": "#000000",
+      "a": 4
+    },
+    "<\n,",
+    {
+      "x": 8.5,
+      "a": 6
+    },
+    "K",
+    {
+      "x": 1,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "J"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 5.5,
+      "c": "#7adabd",
+      "t": "#000000",
+      "a": 4
+    },
+    ">\n.",
+    {
+      "x": 6.5,
+      "a": 6
+    },
+    "B"
+  ],
+  [
+    {
+      "y": -0.875,
+      "c": "#ffb07b",
+      "f": 9,
+      "w": 1.5,
+      "g": true
+    },
+    "",
+    {
+      "c": "#ffb2d2",
+      "t": "#0d0d0b",
+      "a": 6,
+      "f": 3,
+      "g": false
+    },
+    "Z",
+    {
+      "x": 14.5,
+      "a": 4
+    },
+    "?\n/",
+    {
+      "c": "#ffb07b",
+      "t": "#000000",
+      "f": 9,
+      "g": true,
+      "w": 1.5,
+      "a": 4
+    },
+    ""
+  ],
+  [
+    {
+      "y": -0.375,
+      "x": 3.5,
+      "c": "#d9dae0",
+      "g": true,
+      "a": 7,
+      "f": 3
+    },
+    "",
+    {
+      "x": 10.5
+    },
+    ""
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 2.5
+    },
+    "",
+    {
+      "x": 1,
+      "c": "#d4872a",
+      "g": true,
+      "a": 5
+    },
+    "",
+    {
+      "x": 8.5
+    },
+    "",
+    {
+      "x": 1,
+      "c": "#d9dae0",
+      "g": true,
+      "a": 7
+    },
+    ""
+  ],
+  [
+    {
+      "y": -0.75,
+      "x": 0.5
+    },
+    "",
+    {},
+    "",
+    {
+      "x": 14.5
+    },
+    "",
+    {},
+    ""
+  ],
+  [
+    {
+      "r": 30,
+      "rx": 6.5,
+      "ry": 4.25,
+      "y": -1,
+      "x": 1,
+      "c": "#f9cd31",
+      "g": false
+    },
+    "Alt",
+    {
+      "a": 4,
+      "fa": [
+        0,
+        0,
+        0,
+        9
+      ]
+    },
+    "\n\n\n<i class='kb kb-logo-linux-debian fa-large'></i>"
+  ],
+  [
+    {
+      "c": "#d4872a",
+      "a": 7,
+      "f": 9,
+      "h": 2
+    },
+    "<i class='kb kb-Unicode-BackSpace-DeleteLeft-Big'></i>",
+    {
+      "h": 2
+    },
+    "<i class='fa fa-angle-double-up'></i>",
+    {
+      "c": "#f9cd31",
+      "f": 3
+    },
+    "Ctrl"
+  ],
+  [
+    {
+      "x": 2,
+      "c": "#e26757"
+    },
+    "ESC"
+  ],
+  [
+    {
+      "r": -30,
+      "rx": 13,
+      "y": -1,
+      "x": -3,
+      "c": "#f9cd31",
+      "f": 2
+    },
+    "MEDIA",
+    {},
+    "DEL"
+  ],
+  [
+    {
+      "x": -3
+    },
+    "HUN",
+    {
+      "c": "#d4872a",
+      "f": 9,
+      "h": 2
+    },
+    "<i class='kb kb-Return-2'></i>",
+    {
+      "f": 3,
+      "h": 2
+    },
+    "SPC"
+  ],
+  [
+    {
+      "x": -3,
+      "c": "#f9cd31",
+      "f": 2
+    },
+    "LEAD"
+  ]
+]
diff --git a/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.Dvorak.json b/keyboards/ergodox/keymaps/algernon/tools/heatmap-layout.Dvorak.json
new file mode 100644 (file)
index 0000000..1248d36
--- /dev/null
@@ -0,0 +1,542 @@
+[
+  {
+    "backcolor": "#ffffff",
+    "name": "ErgoDox - algernon's layout: Heatmap",
+    "author": "Gergely Nagy <kbd@gergo.csillger.hu>",
+    "notes": "See [here](https://github.com/algernon/ergodox-layout#readme) for the QMK keymap source.",
+    "switchMount": "cherry",
+    "switchBrand": "gateron",
+    "switchType": "KS-3-Tea",
+    "pcb": true,
+    "css": ".keyborder { -webkit-filter: blur(5px); filter: blur(5px); } .keytop { -webkit-filter: blur(10px); } .keylabels { border: 1px solid black; }"
+  },
+  [
+    {
+      "x": 3.5,
+      "c": "#a7d0db",
+      "fa": [
+        0,
+        0,
+        2
+      ]
+    },
+    "#\n3\nF3",
+    {
+      "x": 10.5,
+      "c": "#a7d0db",
+      "t": "#000000",
+      "a": 4,
+      "fa": [
+        0,
+        0,
+        2
+      ]
+    },
+    "*\n8\nF8"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 2.5,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "@\n2\nF2",
+    {
+      "x": 1,
+      "c": "#7adabd",
+      "t": "#000000"
+    },
+    "$\n4\nF4",
+    {
+      "x": 8.5
+    },
+    "&\n7\nF7",
+    {
+      "x": 1,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "(\n9\nF9"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 5.5,
+      "c": "#7adabd",
+      "t": "#000000"
+    },
+    "%\n5\nF5",
+    {
+      "c": "#f9cd31",
+      "a": 7,
+      "f": 2
+    },
+    "STENO",
+    {
+      "x": 4.5,
+      "f": 3
+    },
+    "F12",
+    {
+      "c": "#7adabd",
+      "a": 4,
+      "f": 3,
+      "fa": [
+        0,
+        0,
+        2
+      ]
+    },
+    "^\n6\nF6"
+  ],
+  [
+    {
+      "y": -0.875,
+      "c": "#ffb2d2",
+      "f": 6,
+      "a": 6,
+      "w": 1.5
+    },
+    "<i class='fa fa-fast-backward'></i>\n\n<i class='fa fa-fast-forward'></i>",
+    {
+      "f": 3,
+      "t": "#0d0d0b",
+      "a": 4,
+      "fa": [
+          0,
+          0,
+          2
+      ]
+
+    },
+    "!\n1\nF1",
+    {
+      "x": 14.5
+    },
+    ")\n0\nF10",
+    {
+      "a": 7,
+      "w": 1.5
+    },
+    "F11"
+  ],
+  [
+    {
+      "y": -0.375,
+      "x": 3.5,
+      "c": "#a7d0db",
+      "t": "#000000",
+      "a": 4
+    },
+    ">\n.",
+    {
+      "x": 10.5,
+      "a": 6
+    },
+    "C"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 2.5,
+      "c": "#bfbad1",
+      "t": "#0d0d0b",
+      "a": 4
+    },
+    "<\n,",
+    {
+      "x": 1,
+      "c": "#7adabd",
+      "t": "#000000",
+      "a": 6
+    },
+    "P",
+    {
+      "x": 8.5
+    },
+    "G",
+    {
+      "x": 1,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "R"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 5.5,
+      "c": "#7adabd",
+      "t": "#000000"
+    },
+    "Y",
+    {
+      "c": "#93c9b7",
+      "a": 4,
+      "h": 1.5
+    },
+    "{\n(\n[",
+    {
+      "x": 4.5,
+      "h": 1.5
+    },
+    "}\n)\n]",
+    {
+      "c": "#7adabd",
+      "a": 6
+    },
+    "F"
+  ],
+  [
+    {
+      "y": -0.875,
+      "c": "#ffb07b",
+      "t": "#0d0d0b",
+      "f": 3,
+      "w": 1.5
+    },
+    "\n\n~\n`",
+    {
+      "c": "#ffb2d2",
+      "a": 4,
+      "f": 3
+    },
+    "\"\n'",
+    {
+      "x": 14.5,
+      "a": 6
+    },
+    "L",
+    {
+      "a": 4,
+      "w": 1.5
+    },
+    "|\n\\"
+  ],
+  [
+    {
+      "y": -0.375,
+      "x": 3.5,
+      "c": "#a7d0db",
+      "t": "#000000",
+      "a": 6
+    },
+    "E",
+    {
+      "x": 10.5
+    },
+    "T"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 2.5,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "O",
+    {
+      "x": 1,
+      "c": "#7adabd",
+      "t": "#000000",
+      "n": true
+    },
+    "U",
+    {
+      "x": 8.5,
+      "n": true
+    },
+    "H",
+    {
+      "x": 1,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "N"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 5.5,
+      "c": "#7adabd",
+      "t": "#000000"
+    },
+    "I",
+    {
+      "x": 6.5
+    },
+    "D"
+  ],
+  [
+    {
+      "y": -0.875,
+      "c": "#ffb2d2",
+      "t": "#0d0d0b",
+      "fa": [
+        6
+      ],
+      "w": 1.5
+    },
+    "<i class='fa fa-arrows'></i>\n\nTab",
+    {
+      "f": 3
+    },
+    "A",
+    {
+      "x": 14.5,
+      "f": 3
+    },
+    "S",
+    {
+      "a": 4,
+      "fa": [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        6
+      ],
+      "w": 1.5
+    },
+    "+\n="
+  ],
+  [
+    {
+      "y": -0.625,
+      "x": 6.5,
+      "c": "#93c9b7",
+      "t": "#000000",
+      "a": 7,
+      "h": 1.5
+    },
+    "(",
+    {
+      "x": 4.5,
+      "h": 1.5
+    },
+    ")"
+  ],
+  [
+    {
+      "y": -0.75,
+      "x": 3.5,
+      "c": "#a7d0db",
+      "a": 6
+    },
+    "J",
+    {
+      "x": 10.5
+    },
+    "W"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 2.5,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "Q",
+    {
+      "x": 1,
+      "c": "#7adabd",
+      "t": "#000000"
+    },
+    "K",
+    {
+      "x": 8.5
+    },
+    "M",
+    {
+      "x": 1,
+      "c": "#bfbad1",
+      "t": "#0d0d0b"
+    },
+    "V"
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 5.5,
+      "c": "#7adabd",
+      "t": "#000000"
+    },
+    "X",
+    {
+      "x": 6.5
+    },
+    "B"
+  ],
+  [
+    {
+      "y": -0.875,
+      "c": "#ffb07b",
+      "f": 9,
+      "w": 1.5
+    },
+    "\n\n<i class='kb kb-Multimedia-Play-Pause'></i>",
+    {
+      "c": "#ffb2d2",
+      "t": "#0d0d0b",
+      "a": 4,
+      "f": 3
+    },
+    "?\n/",
+    {
+      "x": 14.5,
+      "a": 6
+    },
+    "Z",
+    {
+      "c": "#ffb07b",
+      "t": "#000000",
+      "f": 9,
+      "w": 1.5
+    },
+    "<i class='kb kb-Multimedia-Stop'></i>"
+  ],
+  [
+    {
+      "y": -0.375,
+      "x": 3.5,
+      "c": "#d9dae0",
+      "g": true,
+      "a": 7,
+      "f": 3
+    },
+    "",
+    {
+      "x": 10.5
+    },
+    ""
+  ],
+  [
+    {
+      "y": -0.875,
+      "x": 2.5
+    },
+    "",
+    {
+      "x": 1,
+      "c": "#d4872a",
+      "g": false,
+      "a": 5
+    },
+    ";\n:",
+    {
+      "x": 8.5
+    },
+    "_\n-",
+    {
+      "x": 1,
+      "c": "#d9dae0",
+      "g": true,
+      "a": 7
+    },
+    ""
+  ],
+  [
+    {
+      "y": -0.75,
+      "x": 0.5
+    },
+    "",
+    {},
+    "",
+    {
+      "x": 14.5
+    },
+    "",
+    {},
+    ""
+  ],
+  [
+    {
+      "r": 30,
+      "rx": 6.5,
+      "ry": 4.25,
+      "y": -1,
+      "x": 1,
+      "c": "#f9cd31",
+      "g": false
+    },
+    "Alt",
+    {
+      "a": 4,
+      "fa": [
+        0,
+        0,
+        0,
+        9
+      ]
+    },
+    "\n\n\n<i class='kb kb-logo-linux-debian fa-large'></i>"
+  ],
+  [
+    {
+      "c": "#d4872a",
+      "a": 7,
+      "f": 9,
+      "h": 2
+    },
+    "<i class='kb kb-Unicode-BackSpace-DeleteLeft-Big'></i>",
+    {
+      "h": 2
+    },
+    "<i class='fa fa-angle-double-up'></i>",
+    {
+      "c": "#f9cd31",
+      "f": 3
+    },
+    "Ctrl"
+  ],
+  [
+    {
+      "x": 2,
+      "c": "#e26757"
+    },
+    "ESC"
+  ],
+  [
+    {
+      "r": -30,
+      "rx": 13,
+      "y": -1,
+      "x": -3,
+      "c": "#f9cd31",
+      "f": 2
+    },
+    "MEDIA",
+    {},
+    "DEL"
+  ],
+  [
+    {
+      "x": -3
+    },
+    "LEAD",
+    {
+      "c": "#d4872a",
+      "f": 9,
+      "h": 2
+    },
+    "<i class='kb kb-Return-2'></i>",
+    {
+      "f": 3,
+      "h": 2
+    },
+    "SPC"
+  ],
+  [
+    {
+      "x": -3,
+      "c": "#f9cd31",
+      "f": 2
+    },
+    "HUN"
+  ]
+]
index a13d12e81af03c1fce2c39db6b12f12241254b4f..68585843bed0eeb9b9092fcc8a40b658d44619de 100755 (executable)
@@ -3,143 +3,247 @@ import json
 import os
 import sys
 import re
+import argparse
 
 from math import floor
+from os.path import dirname
+
+class Heatmap(object):
+    coords = [
+        [
+            # Row 0
+            [ 4,  0], [ 4,  2], [ 2,  0], [ 1,  0], [ 2,  2], [ 3,  0], [ 3,  2],
+            [ 3,  4], [ 3,  6], [ 2,  4], [ 1,  2], [ 2,  6], [ 4,  4], [ 4,  6],
+        ],
+        [
+            # Row 1
+            [ 8,  0], [ 8,  2], [ 6,  0], [ 5,  0], [ 6,  2], [ 7,  0], [ 7,  2],
+            [ 7,  4], [ 7,  6], [ 6,  4], [ 5,  2], [ 6,  6], [ 8,  4], [ 8,  6],
+        ],
+        [
+            # Row 2
+            [12,  0], [12,  2], [10,  0], [ 9,  0], [10,  2], [11, 0], [     ],
+            [      ], [11,  2], [10,  4], [ 9,  2], [10,  6], [12, 4], [12, 6],
+        ],
+        [
+            # Row 3
+            [17,  0], [17,  2], [15,  0], [14,  0], [15,  2], [16,  0], [13,  0],
+            [13,  2], [16,  2], [15,  4], [14,  2], [15,  6], [17,  4], [17,  6],
+        ],
+        [
+            # Row 4
+            [20,  0], [20,  2], [19,  0], [18,  0], [19,  2], [], [], [], [],
+            [19,  4], [18,  2], [19,  6], [20,  4], [20,  6],
+        ],
+        [
+            # Row 5
+            [     ], [23,  0], [22,  2], [22,  0], [22,  4], [21,  0], [21,  2],
+            [24, 0], [24,  2], [25,  0], [25,  4], [25,  2], [26,  0], [      ],
+        ],
+    ]
+
+    def set_attr_at(self, block, n, attr, fn, val):
+        blk = self.heatmap[block][n]
+        if attr in blk:
+            blk[attr] = fn(blk[attr], val)
+        else:
+            blk[attr] = fn(None, val)
+
+    def coord(self, col, row):
+        return self.coords[row][col]
+
+    @staticmethod
+    def set_attr(orig, new):
+        return new
+
+    def set_bg(self, (block, n), color):
+        self.set_attr_at(block, n, "c", self.set_attr, color)
+        #self.set_attr_at(block, n, "g", self.set_attr, False)
+
+    def set_tap_info(self, (block, n), count, cap):
+        def _set_tap_info(o, _count, _cap):
+            ns = 4 - o.count ("\n")
+            return o + "\n" * ns + "%.02f%%" % (float(_count) / float(_cap) * 100)
+
+        if not cap:
+            cap = 1
+        self.heatmap[block][n + 1] = _set_tap_info (self.heatmap[block][n + 1], count, cap)
+
+    @staticmethod
+    def heatmap_color (v):
+        colors = [ [0.3, 0.3, 1], [0.3, 1, 0.3], [1, 1, 0.3], [1, 0.3, 0.3]]
+        fb = 0
+        if v <= 0:
+            idx1, idx2 = 0, 0
+        elif v >= 1:
+            idx1, idx2 = len(colors) - 1, len(colors) - 1
+        else:
+            val = v * (len(colors) - 1)
+            idx1 = int(floor(val))
+            idx2 = idx1 + 1
+            fb = val - float(idx1)
+
+        r = (colors[idx2][0] - colors[idx1][0]) * fb + colors[idx1][0]
+        g = (colors[idx2][1] - colors[idx1][1]) * fb + colors[idx1][1]
+        b = (colors[idx2][2] - colors[idx1][2]) * fb + colors[idx1][2]
+
+        r, g, b = [x * 255 for x in r, g, b]
+        return "#%02x%02x%02x" % (r, g, b)
+
+    def __init__(self, layout):
+        self.log = {}
+        self.total = 0
+        self.max_cnt = 0
+        self.layout = layout
+
+    def update_log(self, (c, r)):
+        if not (c, r) in self.log:
+            self.log[(c, r)] = 0
+        self.log[(c, r)] = self.log[(c, r)] + 1
+        self.total = self.total + 1
+        if self.max_cnt < self.log[(c, r)]:
+            self.max_cnt = self.log[(c, r)]
+
+    def get_heatmap(self):
+        with open("%s/heatmap-layout.%s.json" % (dirname(sys.argv[0]), self.layout), "r") as f:
+            self.heatmap = json.load (f)
+
+        ## Reset colors
+        for row in self.coords:
+            for coord in row:
+                if coord != []:
+                    self.set_bg (coord, "#d9dae0")
+
+        for (c, r) in self.log:
+            coords = self.coord(c, r)
+            b, n = coords
+            cap = self.max_cnt
+            if cap == 0:
+                cap = 1
+            v = float(self.log[(c, r)]) / cap
+            self.set_bg (coords, self.heatmap_color (v))
+            self.set_tap_info (coords, self.log[(c, r)], self.total)
+        return self.heatmap
+
+    def get_stats(self):
+        usage = [
+            # left hand
+            [0, 0, 0, 0, 0],
+            # right hand
+            [0, 0, 0, 0, 0]
+        ]
+        finger_map = [0, 0, 1, 2, 3, 4, 4]
+        for (c, r) in self.log:
+            if r == 5: # thumb cluster
+                if c <= 6: # left side
+                    usage[0][4] = usage[0][4] + self.log[(c, r)]
+                else:
+                    usage[1][4] = usage[1][4] + self.log[(c, r)]
+            else:
+                fc = c
+                hand = 0
+                if fc >= 7:
+                    fc = fc - 7
+                    hand = 1
+                fm = finger_map[fc]
+                usage[hand][fm] = usage[hand][fm] + self.log[(c, r)]
+        hand_usage = [0, 0]
+        for f in usage[0]:
+            hand_usage[0] = hand_usage[0] + f
+        for f in usage[1]:
+            hand_usage[1] = hand_usage[1] + f
+
+        total = self.total
+        if total == 0:
+            total = 1
+        stats = {
+            "hands": {
+                "left": {
+                    "usage": float(hand_usage[0]) / total * 100,
+                    "fingers": {
+                        "0 - pinky": 0,
+                        "1 - ring": 0,
+                        "2 - middle": 0,
+                        "3 - index": 0,
+                        "4 - thumb": 0,
+                    }
+                },
+                "right": {
+                    "usage": float(hand_usage[1]) / total * 100,
+                    "fingers": {
+                        "0 - thumb": 0,
+                        "1 - index": 0,
+                        "2 - middle": 0,
+                        "3 - ring": 0,
+                        "4 - pinky": 0,
+                    }
+                },
+            }
+        }
+
+        hmap = ['left', 'right']
+        fmap = ['0 - pinky', '1 - ring', '2 - middle', '3 - index', '4 - thumb',
+                '0 - thumb', '1 - index', '2 - middle', '3 - ring', '4 - pinky']
+        for hand_idx in range(len(usage)):
+            hand = usage[hand_idx]
+            for finger_idx in range(len(hand)):
+                stats['hands'][hmap[hand_idx]]['fingers'][fmap[finger_idx + hand_idx * 5]] = float(hand[finger_idx]) / total * 100
+        return stats
+
+def dump_all(out_dir, heatmaps):
+    for layer in heatmaps.keys():
+        if len(heatmaps[layer].log) == 0:
+            continue
 
-cr_coord_map = [
-    [
-        # Row 0
-        [ 4,  0], [ 4,  2], [ 2,  0], [ 1,  0], [ 2,  2], [ 3,  0], [ 3,  2],
-        [ 3,  4], [ 3,  6], [ 2,  4], [ 1,  2], [ 2,  6], [ 4,  4], [ 4,  6],
-    ],
-    [
-        # Row 1
-        [ 8,  0], [ 8,  2], [ 6,  0], [ 5,  0], [ 6,  2], [ 7,  0], [ 7,  2],
-        [ 7,  4], [ 7,  6], [ 6,  4], [ 5,  2], [ 6,  6], [ 8,  4], [ 8,  6],
-    ],
-    [
-        # Row 2
-        [12,  0], [12,  2], [10,  0], [ 9,  0], [10,  2], [11, 0], [     ],
-        [      ], [11,  2], [10,  4], [ 9,  2], [10,  6], [12, 4], [12, 6],
-    ],
-    [
-        # Row 3
-        [17,  0], [17,  2], [15,  0], [14,  0], [15,  2], [16,  0], [13,  0],
-        [13,  2], [16,  2], [15,  4], [14,  2], [15,  6], [17,  4], [17,  6],
-    ],
-    [
-        # Row 4
-        [20,  0], [20,  2], [19,  0], [18,  0], [19,  2], [], [], [], [],
-        [19,  4], [18,  2], [19,  6], [20,  4], [20,  6],
-    ],
-    [
-        # Row 5
-        [     ], [23,  0], [22,  2], [22,  0], [22,  4], [21,  0], [21,  2],
-        [24, 0], [24,  2], [25,  0], [25,  4], [25,  2], [26,  0], [      ],
-    ],
-]
-
-def set_attr_at(j, b, n, attr, fn, val):
-    blk = j[b][n]
-    if attr in blk:
-        blk[attr] = fn(blk[attr], val)
-    else:
-        blk[attr] = fn(None, val)
-
-def coord(col, row):
-    return cr_coord_map[row][col]
-
-def set_attr(orig, new):
-    return new
-
-def set_bg(j, (b, n), color):
-    set_attr_at(j, b, n, "c", set_attr, color)
-    #set_attr_at(j, b, n, "g", set_attr, False)
-
-def _set_tap_info(o, count, cap):
-    ns = 4 - o.count ("\n")
-    return o + "\n" * ns + "%.02f%%" % (float(count) / float(cap) * 100)
-
-def set_tap_info(j, (b, n), count, cap):
-    j[b][n + 1] = _set_tap_info (j[b][n + 1], count, cap)
-
-def heatmap_color (v):
-    colors = [ [0.3, 0.3, 1], [0.3, 1, 0.3], [1, 1, 0.3], [1, 0.3, 0.3]]
-    fb = 0
-    if v <= 0:
-        idx1, idx2 = 0, 0
-    elif v >= 1:
-        idx1, idx2 = len(colors) - 1, len(colors) - 1
-    else:
-        val = v * (len(colors) - 1)
-        idx1 = int(floor(val))
-        idx2 = idx1 + 1
-        fb = val - float(idx1)
-
-    r = (colors[idx2][0] - colors[idx1][0]) * fb + colors[idx1][0]
-    g = (colors[idx2][1] - colors[idx1][1]) * fb + colors[idx1][1]
-    b = (colors[idx2][2] - colors[idx1][2]) * fb + colors[idx1][2]
-
-    r, g, b = [x * 255 for x in r, g, b]
-    return "#%02x%02x%02x" % (r, g, b)
-
-# Load the keylog
-def load_keylog(fname, restrict_row):
-    keylog = {}
-    total = 0
-    with open(fname, "r") as f:
-        lines = f.readlines()
-    for line in lines:
-        m = re.search ('KL: col=(\d+), row=(\d+)', line)
+        with open ("%s/%s.json" % (out_dir, layer), "w") as f:
+            json.dump(heatmaps[layer].get_heatmap(), f)
+        print >>sys.stderr, "%s stats:" % (layer)
+        json.dump (heatmaps[layer].get_stats(), sys.stderr,
+                   indent = 4, sort_keys = True)
+        print >>sys.stderr, ""
+        print >>sys.stderr, ""
+
+def main(opts):
+
+    heatmaps = {"Dvorak": Heatmap("Dvorak"),
+                "ADORE": Heatmap("ADORE")
+    }
+    cnt = 0
+    restrict_row = opts.restrict_row
+    out_dir = opts.outdir
+
+    while True:
+        line = sys.stdin.readline()
+        if not line:
+            break
+        m = re.search ('KL: col=(\d+), row=(\d+), pressed=(\d+), layer=(.*)', line)
         if not m:
             continue
-        (c, r) = (int(m.group (2)), int(m.group (1)))
-        if restrict_row != None and r != int(restrict_row):
+
+        cnt = cnt + 1
+        (c, r, l) = (int(m.group (2)), int(m.group (1)), m.group (4))
+        if restrict_row != -1 and r != restrict_row:
+            continue
+        if c in opts.ignore_columns:
             continue
-        if (c, r) in keylog:
-            keylog[(c, r)] = keylog[(c, r)] + 1
-        else:
-            keylog[(c, r)] = 1
-        total = total + 1
-    return total / 2, keylog
-
-def l_flat(s):
-    f = s.split("\n")
-    return ", ".join (f)
-
-def main(base_fn, log_fn, restrict_row = None):
-
-    with open(base_fn, "r") as f:
-        layout = json.load (f)
-
-    ## Reset colors
-    for row in cr_coord_map:
-        for col in row:
-            if col != []:
-                set_bg (layout, col, "#d9dae0")
-                #set_attr_at (layout, col[0], col[1], "g", set_attr, True)
-
-    total, log = load_keylog (log_fn, restrict_row)
-    max_cnt = 0
-    for (c, r) in log:
-        max_cnt = max(max_cnt, log[(c, r)])
-
-    # Create the heatmap
-    for (c, r) in log:
-        coords = coord(c, r)
-        b, n = coords
-        cap = max_cnt
-        v = float(log[(c, r)]) / cap
-        print >> sys.stderr, "%s => %d/%d => %f = %s" % (l_flat(layout[b][n+1]), log[(c,r)], cap, v, heatmap_color(v))
-        set_bg (layout, coord(c, r), heatmap_color (v))
-        set_tap_info (layout, coord (c, r), log[(c, r)], total)
-
-    print json.dumps(layout)
 
-if __name__ == "__main__":
-    if len(sys.argv) < 3:
-        print """Log to Heatmap -- creates a heatmap out of keyboard logs
+        heatmaps[l].update_log ((c, r))
+
+        if opts.dump_interval != -1 and cnt >= opts.dump_interval:
+            cnt = 0
+            dump_all(out_dir, heatmaps)
 
-Usage: log-to-heatmap.py base-layout.json logfile [row] >layout.json"""
-        sys.exit (1)
-    main(*sys.argv[1:])
+    dump_all (out_dir, heatmaps)
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser (description = "keylog to heatmap processor")
+    parser.add_argument ('outdir', action = 'store',
+                         help = 'Output directory')
+    parser.add_argument ('--row', dest = 'restrict_row', action = 'store', type = int,
+                         default = -1, help = 'Restrict processing to this row only')
+    parser.add_argument ('--dump-interval', dest = 'dump_interval', action = 'store', type = int,
+                         default = 100, help = 'Dump stats and heatmap at every Nth event, -1 for dumping at EOF only')
+    parser.add_argument ('--ignore-column', dest = 'ignore_columns', action = 'append', type = int,
+                         default = [], help = 'Ignore the specified columns')
+    args = parser.parse_args()
+    main(args)