Emacs NS build + Google IME でストレスなくIMEを切り替える

==本記事は暫定版です==

Emacs NS build と Google IME を併用すると，IMEが正しく切り替わらないことがある．以下はこの問題に対処するための一つの手法である．

Google IMEによる切替系統を，Emacs.app だけ分離する
 - Emacs.app は内部のAPIを直接呼び出し Google IME を切り替える
 - 他のアプリは通常通りに使う

以下は，`Cmd-Space`もしくは`Shift-Space`をIME切替のキーとして使う事例である．

![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12232/e3b50758-ba8b-14bf-114e-51116dc62816.gif)


### 想定する環境

- macOS (Catalina)
- Emacs 27.0.91 (with ns-inline-patch)

### 必要なアプリケーション

- Google IME
    - https://www.google.co.jp/ime/
- Karabiner-Elements
    - https://karabiner-elements.pqrs.org/
- ns-inline-patch 付き Emacs.app (NS build)
    - https://pxaka.tokyo/emacs/pkg/emacs-27.0.91.pkg
    - https://github.com/takaxp/ns-inline-patch (27.1以降 Apple Silicon用もあります)

### macOSの IME切替を Ctrl-` に割り当てる 

macOSの環境設定で変える．

![Screen Shot 2020-05-24 at 2.46.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12232/6bcf7707-04b0-c4be-1675-955f74cc98aa.png)

![Screen Shot 2020-05-24 at 2.46.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12232/7c59f323-3510-a983-b097-8fefb8d9404a.png)

### Ctrl-` に Cmd-Space と Shift-Spaceを割り当てる

Karabiner-Elements で設定する．

~/.config/karabiner/assets/complex_modifications/toggle-ime-except-emacs.json として配置後，Karabiner-Elements.app を起動して確認．

これにより，Ctrl-`，Cmd-Space, Shift-Space の3つの方法で IME を切り替えられるようになる．ただし，Emacs.appの使用中は，Emacs.app内部の機能でIMEを切り替えるために，Cmd-Space と Shift-Space の押下を OSに渡さない．

```:toggle-ime-except-emacs.json
{
    "title": "Toggle IME (except Emacs.app)",
    "rules": [
        {
            "description": "Toggle IME by Shift-Space (left side)",
            "manipulators": [
                {
                    "type": "basic",
                    "from": {
                        "key_code": "spacebar",
                        "modifiers": {
                            "mandatory": [
                                "left_shift"
                            ]
                        }
                    },
                    "to": [
                        {
                            "key_code": "grave_accent_and_tilde",
                            "modifiers": [
                                "left_control"
                            ]
                        }
                    ],
                    "conditions": [
                        {
                            "type": "frontmost_application_unless",
                            "bundle_identifiers": [
                                "Emacs"
                            ]
                        }
                    ]
                }
            ]
        },
        {
            "description": "Toggle IME by Shift-Space (right side)",
            "manipulators": [
                {
                    "type": "basic",
                    "from": {
                        "key_code": "spacebar",
                        "modifiers": {
                            "mandatory": [
                                "right_shift"
                            ]
                        }
                    },
                    "to": [
                        {
                            "key_code": "grave_accent_and_tilde",
                            "modifiers": [
                                "left_control"
                            ]
                        }
                    ],
                    "conditions": [
                        {
                            "type": "frontmost_application_unless",
                            "bundle_identifiers": [
                                "Emacs"
                            ]
                        }
                    ]
                }
            ]
        },
        {
            "description": "Toggle IME by Cmd-Space (left side)",
            "manipulators": [
                {
                    "type": "basic",
                    "from": {
                        "key_code": "spacebar",
                        "modifiers": {
                            "mandatory": [
                                "left_command"
                            ]
                        }
                    },
                    "to": [
                        {
                            "key_code": "grave_accent_and_tilde",
                            "modifiers": [
                                "left_control"
                            ]
                        }
                    ],
                    "conditions": [
                        {
                            "type": "frontmost_application_unless",
                            "bundle_identifiers": [
                                "Emacs"
                            ]
                        }
                    ]
                }
            ]
        },
        {
            "description": "Toggle IME by Cmd-Space (right side)",
            "manipulators": [
                {
                    "type": "basic",
                    "from": {
                        "key_code": "spacebar",
                        "modifiers": {
                            "mandatory": [
                                "right_command"
                            ]
                        }
                    },
                    "to": [
                        {
                            "key_code": "grave_accent_and_tilde",
                            "modifiers": [
                                "left_control"
                            ]
                        }
                    ],
                    "conditions": [
                        {
                            "type": "frontmost_application_unless",
                            "bundle_identifiers": [
                                "Emacs"
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

```

![Screen Shot 2020-05-24 at 2.53.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12232/a4616316-2832-0bc8-1c0f-6a80ba0302d0.png)

### ns-inline-patch で Google IME を有効化

```:init.el
;; Google IME を指定（locale=en や自動検出がコケる場合には必須）
(custom-set-variables
     '(mac-default-input-source "com.google.inputmethod.Japanese.base"))

;; インラインパッチの有効化
(mac-input-method-mode 1)
```

### Emacs.app で Google IME 切替を Cmd-Space と Shift-Space に割り当てる

```:init.el
(global-set-key (kbd "M-SPC") 'mac-ime-toggle)
(global-set-key (kbd "S-SPC") 'mac-ime-toggle)
(define-key isearch-mode-map (kbd "M-SPC") 'mac-ime-toggle)
(define-key isearch-mode-map (kbd "S-SPC") 'mac-ime-toggle)
```

### Google IME の設定で Shift-Space を透過させる

Shift-Space が Emacs.app に透過しないケースがある．

![Screen Shot 2020-05-24 at 4.31.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12232/3284cb15-ccc3-bc8a-7a0d-724ce41b750f.png)

Googke IME Keymap Style > Google IME input keymap editor から，「Shift Space」が Keyになっているコマンドを削除（Porcomposition, Composition, Conversion）すれば希望の操作（Shift-Spaceがダイレクトに Emacsに通る）

なおこの設定はエクスポートしてテキストで保存できる．新しい環境では，それをインポートすれば良い．

### 補助関数

- mac-ime-toggle (IMEのON/OFF切替関数, interactive）
- mac-ime-active-p（IMEのON判定関数）
- mac-ime-activate（IMEのON関数, interactive）
- mac-ime-deactivate（IMEのOFF関数, interactive）
- mac-ime-input-source-list（使えるIMEのコードをメッセージバッファに書き出す, interactive）

### Hooks

カーソルの色を変えるなどのカスタム関数を hook にぶら下げると便利です．

- input-method-activate-hook（mac-ime-activate内で呼ばれる）
- input-method-deactivate-hook（mac-ime-deactivate内で呼ばれる）