SublimeText で DoxyDoc 使用時の日本語入力の確定を Enter キーのみで行う


MacのSublimeText3でDoxyDocやMarkdownなどを使用している時に
日本語入力ができない問題を解決する記事がいくつかありますが,どれも
EnterShift+Enterと変更するものがほとんどです.
自分は日本語入力の時にEnterで確定する癖がついているので,
どうしてもEnterを変更したくないということでこの記事を書きました.

基本的な解決方法は以下を参考にさせて頂きました.

参考
MacのSublimeText3で日本語が消えるバグを回避する

注意点

自分の日本語入力の時の癖(日本語入力→スペースで選択→Enter)を再現できるようにしているので,以下の場合の問題が解決できていません.

  • 日本語の変換に tab キーを使う場合.
  • ひらがなのみの場合(スペースキーを押さずに Enter)

環境

  • Mac OS X Yosemite
  • Sublime Text 3 (Build 3143)

DoxyDocとは

Doxygen コメントを自動挿入してくれるSublime Textのプラグインです.
関数の引数や返り値などに応じた雛形を作ってくれます.
ここのコメントの行で日本語が入力できなくなってしまうのが今回の問題点です.

日本語入力ができない原因

Macの場合,日本語を確定するためのEnterと改行のためのEnterが競合し,日本語が消えてしまいます.
(正確には特定条件を満たしたときのEnterの処理と競合している)

解決方法

Package Control 経由ではなく,GitHub からダウンロードすることでキーバインドを編集できるようにし,改行のイベントの部分を変更することで解決します.
ステップ3までは参考ページと同じとなっています.

1. パッケージの削除

Package Control 経由でインストールしている場合は削除します.

Shift + Command + pで Command Palette を開き
Package Control: Remove Package を選択します.
次に出てきた窓で DoxyDoc を入力し選択することで,削除が完了します.


2. GitHubからのダウンロード

DoxyDocのGitHubベージへアクセスし
releases から最新のバージョンをダウンロードし,解凍します.

解凍したファイル名"DoxyDoc-x.x.x"は"DoxyDoc"に変更します.
(2017/10/17時点ではDoxyDoc-1.2.1)

3. パッケージのインストール

ターミナルを開き

$ open ~/Library/Application\ Support/Sublime\ Text\ 3/Packages/ 

と打ちます.

Finder が開くので,先程解凍したディレクトリを Packages 以下に入れます.


4. キーバインドの設定

Doxydoc/Default.sublime-keymap を開きます

20行目以降にはEnterキーに対する処理が3つ記述されています.
それぞれに以下のような記述があるかと思います.

{ "key": "setting.auto_indent",   "operator": "equal",          "operand": true,              "match_all": true },
{ "key": "selector",              "operator": "equal",          "operand": "comment.block",   "match_all": true },
{ "key": "auto_complete_visible", "operator": "equal",          "operand": false,             "match_all": true },
{ "key": "preceding_text",        "operator": "regex_contains", "operand": "^\\s*\\*\\s*\\S", "match_all": true }

4つ目の最後の"}"の後に","を記述し,以下のコードを追加します.

{ "key": "selection_empty",       "operator": "equal",          "operand": true,              "match_all": true }

最終的に以下のようになればOKなので保存して完了です.

    { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "\n${TM_CURRENT_LINE/^\\s*(\\*\\s*).*$/$1/}"}, "context":
        [
            { "key": "setting.auto_indent",   "operator": "equal",          "operand": true,              "match_all": true },
            { "key": "selector",              "operator": "equal",          "operand": "comment.block",   "match_all": true },
            { "key": "auto_complete_visible", "operator": "equal",          "operand": false,             "match_all": true },
            { "key": "preceding_text",        "operator": "regex_contains", "operand": "^\\s*\\*\\s*\\S", "match_all": true },
            { "key": "selection_empty",       "operator": "equal",          "operand": true,              "match_all": true }
        ]
    },
    { "keys": ["enter"], "command": "insert_snippet", "args": {"contents": "\n${TM_CURRENT_LINE/^\\s*(\\*\\s*).*$/$1/}"}, "context":
        [
            { "key": "setting.auto_indent",   "operator": "equal",          "operand": true,            "match_all": true },
            { "key": "selector",              "operator": "equal",          "operand": "comment.block", "match_all": true },
            { "key": "auto_complete_visible", "operator": "equal",          "operand": false,           "match_all": true },
            { "key": "preceding_text",        "operator": "regex_contains", "operand": "^\\s*\\*",      "match_all": true },
            { "key": "selection_empty",       "operator": "equal",          "operand": true,              "match_all": true }
        ]
    },
    { "keys": ["keypad_enter"], "command": "insert_snippet", "args": {"contents": "\n${TM_CURRENT_LINE/^\\s*(\\*\\s*).*$/$1/}"}, "context":
        [
            { "key": "setting.auto_indent",   "operator": "equal",          "operand": true,            "match_all": true },
            { "key": "selector",              "operator": "equal",          "operand": "comment.block", "match_all": true },
            { "key": "auto_complete_visible", "operator": "equal",          "operand": false,           "match_all": true },
            { "key": "preceding_text",        "operator": "regex_contains", "operand": "^\\s*\\*",      "match_all": true },
            { "key": "selection_empty",       "operator": "equal",          "operand": true,              "match_all": true }
        ]
    }

変更後の動作

日本語入力でEnterを押しても改行されずに日本語が確定できます.





以上で解決方法の説明は終わりです.以降はDoxyDocのキーバインドについて少し解説していきます.
以下の記事を参考にしました.

参考
SublimeText2のキーバインドを、ちょっと突っ込んで解説

設定されているキー

2行目や8行目にある
{"keys":["キー"],...
では設定するキーを記述します.
今回登場するキーは以下の3つです.

  • enter [Enterキー]
  • keypad_enter [テンキーのEnter]
  • tab [tabキー]

キーに対する処理

設定が6つありますが,処理としては前半3つと後半3つの2つに分かれます.

  • /** 後の Enter によって雛形を出現させるもの
  • コメント行での Enter によって改行しつつ,同じインデントに*を出現させるもの

今回は後半の処理が原因となっていました.

コンテキストの説明

Doxydoc に登場する記述を説明します.

{ "key": "preceding_text",      "operator": "regex_contains", "operand": "^\\s*\\/\\*{2}$", "match_all": true} 
  • "key":"preceding_text"
    • `キャレットの前の文字がどうなっているか調べる.
  • "operator": "regex_contains"
    • "key"で選ばれる文字列が operand の正規表現とマッチするなら実行する.
  • "operand": "^\\s*\\/\\*{2}$"
    • 先頭^からスペース0個以上\s*の後に/** (スラッシュアス,タリスク×2)\/\*{2}の後が末尾$となっている.
  • "match_all": true
    • 判定のすべてが true にならなければマッチしたことにならない.

つまり/**の後に対応するキーを押下するとイベントが発生します.
後半の場合は正規表現が^\\s*\\*^\\s*\\*\\s*\\Sとなっています.
なので,後半のイベントはコメント行の中で発生することがわかります.

今回追加した記述の説明

{ "key": "selection_empty",  "operator": "equal",   "operand": true,  "match_all": true }
  • "key":"selection_empty"
    • 何も選択していなければtrue.
  • "operator": "equal"
    • operand("operand": true) とイコール.

つまり何も選択されていない時にイベントが発生するようにしました.
日本語入力では確定前の状態(スペース押下後)は文字列を選択している状態になっているようです.
そのため,コメント行での Enter のイベントが発生しないので日本語の確定が行われるようになります.

参考
SublimeText2のキーバインドを、ちょっと突っ込んで解説
MacのSublimeText3で日本語が消えるバグを回避する