Karabinerの代替アプリ

macOS Sierraにして[Karabiner](https://pqrs.org/osx/karabiner/index.html.ja)が使えなくなってしまった。

[Karabiner-Elements](https://github.com/tekezo/Karabiner-Elements)が開発中であるが

* キーの割当てを変更する
* キーリピートの速度を変更する

といった簡単な機能くらいしかまだない。

Karabinerが持っていた機能で

* 修飾キーを単独で押した時と組み合わせて押したときで挙動を変更する
* キーの割当て先に連続するキー入力を割り当てる
* アプリケーションごとの設定を変更する

あたりはほしいところであるが、色々なアプリを組み合わせれば、だいたいやりたいことができる。

まず、自分は右commandをoptionに変更する設定をしていたが、それはKarabiner-Elementsを使って変更できる。

また、Karabiner-Elementsを使っているとcaps lockをcontrolに変更する設定を、システム環境設定でやっていても効かなくなるので、Karabiner-Elementsで設定する。

単独で左commandキーを押した時は「英数」、右commandキーを押した時は「かな」などにしたい場合は[⌘英かな](https://ei-kana.appspot.com/)が使える。

Vimを使って日本語入力をしていると、挿入モードを抜けた時は英数になって欲しいが、これをするにはEscに対して、Esc+英数を割り当てる必要がある。
これは[BetterTouchTool](https://www.boastr.net/)でできる。
正確にはCtrl+[をEscに割り当てて、Additional Actionに英数を割り当てる（EscにEscを割り当てると無限ループが起こるので）。
やり方はBetterTouchToolのKeyboardのタブで、下にある「Add New Shortcut or Key Sequence」を使って左側の空白にCtrl+[を入力して、右側の「Trigger Other Keyboard Shortcut」にEscを入力する。
さらに、下にある「Atach Additional Action」を押して、そこで英数（英かなで設定したキー）を押す。

## Keyhac

実のところのこれらの設定は[Keyhac](https://sites.google.com/site/craftware/keyhac-ja)で全部できる。しかし、keyhacを使うとたまにctrlが押しっぱなしのような状態になるので、上記の設定で十分な場合は使わないほうがよいかも。
そういう状態になったら、ctrlを一回押すと直る。

Keyhacでは以下の様なことができる

* キー入力に対して色々とを割り当てることができる
    * 単独で修飾キーを押したときと、組み合わせて押したときの挙動を変更できる
    * キー入力に対して、キーストロークを割り当てられる
    * キーストロークに対しても設定できる
    * キー入力に対してPythonの関数を実行できる
    * アプリケーションごとに設定できる
* クリップボード履歴機能がある
    * クリップボードの内容を修正して貼り付けられる
    * 定型文もつくれる
    * それらをインクリメントで検索できる
    * ただし、画像などは扱えない
* キーボードマクロがある

設定はPythonで書く。たとえばこんな感じ。

```python:config.py
import os
import datetime
import subprocess

from keyhac import *


def configure(keymap):

    # --------------------------------------------------------------------
    # Text editer setting for editting config.py file

    # Setting with program file path (Simple usage)
    keymap.editor = "MacVim"

    # --------------------------------------------------------------------
    # Customizing the display

    # Font
    keymap.setFont("Osaka-Mono", 16)

    # Theme
    keymap.setTheme("black")

    # --------------------------------------------------------------------
    # global keymap

    # 右Commandを右Optionに変更
    keymap.replaceKey("RCmd", "RAlt")

    keymap_global = keymap.defineWindowKeymap()

    # 左Command単独押しで英数
    keymap_global["O-LCmd"] = "102"
    # 右Command単独押しでかな
    keymap_global["O-RAlt"] = "104"

    # Ctrl+SemicolonでEscして、英数
    keymap_global["Ctrl-Semicolon"] = "Esc", "102"
    keymap_global["Ctrl-OpenBracket"] = "Esc"

    keymap_global["Fn-q"] = keymap.command_RecordToggle
    # keymap_globa;["Fn-1"] = keymap.command_RecordStart
    # keymap_global["Fn-2"] = keymap.command_RecordStop
    keymap_global["Fn-Atmark"] = keymap.command_RecordPlay
    # keymap_global[ "Fn-4" ] = keymap.command_RecordClear

    # config.pyリロード
    keymap_global['Fn-r'] = keymap.command_ReloadConfig

    keymap_global['Alt-b'] = 'Alt-Left'
    keymap_global['Alt-d'] = 'Fn-Alt-Delete'
    keymap_global['Alt-f'] = 'Alt-Right'
    keymap_global['Ctrl-b'] = 'Left'
    keymap_global['Ctrl-f'] = 'Right'
    keymap_global['Ctrl-n'] = 'Down'
    keymap_global['Ctrl-p'] = 'Up'
    keymap_global['Ctrl-w'] = 'Alt-Back'

    keymap_global['Cmd-Ctrl-n'] = 'Down'
    keymap_global['Cmd-Ctrl-p'] = 'Up'
    keymap_global['Cmd-Ctrl-b'] = 'Left'
    keymap_global['Cmd-Ctrl-f'] = 'Right'

    # --------------------------------------------------------------------
    # local keymap

    keymap_local = {}
    for app in ["com.googlecode.iterm2", "org.vim.MacVim"]:
        keymap_local[app] = keymap.defineWindowKeymap(app_name=app)
        keymap_local[app]['Ctrl-b'] = 'Ctrl-b'
        keymap_local[app]['Ctrl-f'] = 'Ctrl-f'
        keymap_local[app]['Ctrl-n'] = 'Ctrl-n'
        keymap_local[app]['Ctrl-p'] = 'Ctrl-p'
        keymap_local[app]['Ctrl-w'] = 'Ctrl-w'
        keymap_local[app]['Alt-b'] = 'Alt-b'
        keymap_local[app]['Alt-d'] = 'Alt-d'
        keymap_local[app]['Alt-f'] = 'Alt-f'

    for app in ["org.mozilla.firefox", "com.google.Chrome"]:
        keymap_local[app] = keymap.defineWindowKeymap(app_name=app)
        keymap_local[app]['Ctrl-b'] = 'Ctrl-b'
        keymap_local[app]['Ctrl-f'] = 'Ctrl-f'

    for app in ["com.microsoft.Outlook"]:
        keymap_local[app] = keymap.defineWindowKeymap(app_name=app)
        keymap_local[app]['Ctrl-a'] = 'Home'
        keymap_local[app]['Ctrl-e'] = 'End'
```

単純にキーを変更したい場合は

```python
# 右Commandを右Optionに変更
keymap.replaceKey("RCmd", "RAlt")
```

の様に書く。

修飾キー付きに入力を変更したい場合は`keymap.defineWindowKeymap()`を使う。
`keymap.defineWindowKeymap()`で引数に何も指定しないと全アプリケーションに適応されるオブジェクトが返ってくるので、それ(`keymap_global`)に対して、辞書で設定していく。
あるアプリケーション、例えばFirefoxに対してのみ設定したい場合は`keymap.defineWindowKeymap(app="org.mozilla.firefx")`の戻り値に対して、辞書で設定していく。

基本的にキーの変更の設定をしたいけど、あるアプリケーションでは設定したくない時は

```python
keymap_global['Ctrl-n'] = 'Down'
keymap_local["com.googlecode.iterm2"] = keymap.defineWindowKeymap(app_name="com.googlecode.iterm2")
keymap_local["com.googlecode.iterm2"]['Ctrl-n'] = 'Ctrl-n'
```

のように元に戻せばよい。

ここで入力するアプリケエーションを表す文字列はKeyhacのアイコンをクリックするメニューの「端末の表示」でKeyhacの端末を表示して、「内部ログ ON」をすると、アプリケーションを変更したタイミングで、表示されるのでそれを使う。