Emacs以外でもStickyKeyを使いたい！

## 更新
2018-04-05 Karabiner Elementsに暫定対応しました！

## StickyKeyって？

CamelCaseとかでコーディングしてると_Shift-B_などの離れた2つのキーを同時に入力する機会が多いですよね？ 
ずっと同じ作業をしていると小指が辛いことになります。
StickyKeyを有効にすると、Shiftボタン、Bボタンの順番で入力すれば同時に入力した状態と同じアクションが実行されます。
_Shift_の場合は特にStickyShiftとよぶんですかね？
今回はエンジニアが多用するCamelCaseの入力が楽になるStickyShiftに絞って説明します！  

## やりたいこと

-   Emacsにはrubikitchさん作のsticky.elという神ツールがありますが、IDEA Intellijでもブラウザでもどこでも使いたんのです！
-   KarabinerにはStickyKeyの設定が用意されていますが、一部の挙動が不便なのでsticky.elの挙動にしたいんです！

### sticky.elの素晴らしい挙動
-   StickyKeyに設定されたキーが2回入力された場合は、元のキーを入力する
-   修飾されたキーの場合は何もしない。

## やりかた(OSX)

Karabiner-Elementsを使用します。  

## 設定してみる(セミコロンの例)

Karabiner-ElementsのComplex Modificationsで実現できます。
以下のファイルを追加して読み込めばOKです。

```json:$HOME/.config/karabiner/karabiner.json
{
  "title": "Sticky",
  "rules": [
    {
      "description": "sticky",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "semicolon"
          },
          "to": [
            {
              "key_code": "semicolon"
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "semicolon"
          },
          "to": [
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 1
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 0
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "a"
          },
          "to": [
            {
              "key_code": "a",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "b"
          },
          "to": [
            {
              "key_code": "b",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "c"
          },
          "to": [
            {
              "key_code": "c",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "d"
          },
          "to": [
            {
              "key_code": "d",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "e"
          },
          "to": [
            {
              "key_code": "e",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "f"
          },
          "to": [
            {
              "key_code": "f",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "g"
          },
          "to": [
            {
              "key_code": "g",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "h"
          },
          "to": [
            {
              "key_code": "h",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "i"
          },
          "to": [
            {
              "key_code": "i",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "j"
          },
          "to": [
            {
              "key_code": "j",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "k"
          },
          "to": [
            {
              "key_code": "k",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "l"
          },
          "to": [
            {
              "key_code": "l",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "m"
          },
          "to": [
            {
              "key_code": "m",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "n"
          },
          "to": [
            {
              "key_code": "n",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "o"
          },
          "to": [
            {
              "key_code": "o",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "p"
          },
          "to": [
            {
              "key_code": "p",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "q"
          },
          "to": [
            {
              "key_code": "q",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "r"
          },
          "to": [
            {
              "key_code": "r",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "s"
          },
          "to": [
            {
              "key_code": "s",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "t"
          },
          "to": [
            {
              "key_code": "t",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "u"
          },
          "to": [
            {
              "key_code": "u",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "v"
          },
          "to": [
            {
              "key_code": "v",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "w"
          },
          "to": [
            {
              "key_code": "w",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "x"
          },
          "to": [
            {
              "key_code": "x",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "y"
          },
          "to": [
            {
              "key_code": "y",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "z"
          },
          "to": [
            {
              "key_code": "z",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "grave_accent_and_tilde"
          },
          "to": [
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            },
            {
              "key_code": "grave_accent_and_tilde",
              "modifiers": [
                "shift"
              ]
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "1"
          },
          "to": [
            {
              "key_code": "1",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "2"
          },
          "to": [
            {
              "key_code": "2",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "3"
          },
          "to": [
            {
              "key_code": "3",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "4"
          },
          "to": [
            {
              "key_code": "4",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "5"
          },
          "to": [
            {
              "key_code": "5",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "6"
          },
          "to": [
            {
              "key_code": "6",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "7"
          },
          "to": [
            {
              "key_code": "7",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "8"
          },
          "to": [
            {
              "key_code": "8",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "9"
          },
          "to": [
            {
              "key_code": "9",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "0"
          },
          "to": [
            {
              "key_code": "0",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "hyphen"
          },
          "to": [
            {
              "key_code": "hyphen",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "equal_sign"
          },
          "to": [
            {
              "key_code": "equal_sign",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "quote"
          },
          "to": [
            {
              "key_code": "quote",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "comma"
          },
          "to": [
            {
              "key_code": "comma",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "period"
          },
          "to": [
            {
              "key_code": "period",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "open_bracket"
          },
          "to": [
            {
              "key_code": "open_bracket",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "close_bracket"
          },
          "to": [
            {
              "key_code": "close_bracket",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "backslash"
          },
          "to": [
            {
              "key_code": "backslash",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "slash"
          },
          "to": [
            {
              "key_code": "slash",
              "modifiers": [
                "shift"
              ]
            },
            {
              "set_variable": {
                "name": "sticky_pressed",
                "value": 0
              }
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "sticky_pressed",
              "value": 1
            }
          ]
        }
      ]
    }
  ]
}

```

## 最後に

Karabiner-Elementsではsticky機能がなくなりましたが力技で解決しました💪
それ以外にもHammerSpoonでも近い動作を実現できたのですが、微妙に期待する動作を実現できなかったので諦めました。

コーディング速度もチョイチョイアップです。