Edited at

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


ファイルフォーマット

ファイル形式はJSONで、拡張子は.sublime-keymap

プラットフォーム毎にファイルが作られます。


  • Default (Windows).sublime-keymap

  • Default (Linux).sublime-keymap

  • Default (OSX).sublime-keymap

また、キーバインドの設定ファイルは、DefaultとUserの2つのファイルがありますがUserほうが優先順位が高いので、自分設定を追加する場合はUserのほうに書いていくほうがいいと思います。Userのほうは一番初めに開くと空っぽのファイルなので[]の入力をお忘れなく。

キーバインドの設定ファイルは、メニューの下記のところに。


  • Preferences -> Key Bindings - Default

  • Preferences -> Key Bindings - User


キーバインドの構造


  • keys

    設定するキー

    省略不可


  • command

    設定されたキーで、実行するコマンドのコマンド名。

    省略不可


  • args

    コマンドへ渡す引数。

    省略可


  • context

    何時このキーバインドを有効にするかを設定する。設定がなければ常に有効になります。

    ここの設定で、特定のsyntaxでのみキーバインドを有効にする。みたいなことができるようになります。

    省略可



基本形

一番シンプルな設定方法は、こんな感じ。

{ "keys": ["キー"], "command": "コマンド名" }

// キーストロークが1回の時

{ "keys": [ctrl+n], "command": "new_window" },

// キーストロークが2回の時
{ "keys": [ctrl+n, ctrl+w], "command": "new_window"}

・Plugin作りたい人へのTips

このコマンド名はpythonのクラス名になっており、先頭と_の直後を大文字に変更したクラス名を設定します。

例えば上記の例だと NewWindowCommand or NewWindow どちらかのクラス名になっています。


引数がある場合

値をコマンドに渡したい時は、argsに続けて入力します。

{ "keys": ["キー"], "command": "コマンド名", "args": {"変数名": "値"} }

このargsに入る値はコマンドによって異なるので、

insertにのargsに{"by": "characters", "forward": false}を設定したらエラーになります。

// 引数ひとつの時

{ "keys": ["enter"], "command": "insert", "args": {"characters": "\n"} },

// 引数複数の時
{ "keys": ["left"], "command": "move", "args": {"by": "characters", "forward": false} },

// 引数配列の時
{ "keys": ["alt+o"], "command": "switch_file", "args": {"extensions": ["cpp", "c", "h"]} }

command に 'insert_snippet' を使うと、$0の位置にキャレットを移動させたり、'${0:$SELECTION}'で、選択文字列を取得したり、スニペット風の引数文字列を使うことができます。

// `{` を入力すると '}' が自動入力され、キャレットが `{}` の間に移動

{ "keys": ["{"], "command": "insert_snippet", "args": {"contents": "{$0}"} },

// 文字列を選択状態で `{` を入力すると '}' が自動入力されて、選択文字列を `{}` で囲む
{ "keys": ["{"], "command": "insert_snippet", "args": {"contents": "{${0:$SELECTION}}"} }

・Plugin作りたい人へのTips

この時pythonのクラスは、こんな感じだと予想されます。


plugin.py

class InsertCommand(sublime_plugin.TextCommand):

def run(self, edit, characters):

class MoveCommand(sublime_plugin.TextCommand):
def run(self, edit, characters, forward):

class SwitchFileCommand(sublime_plugin.WindowCommand):
def run(self, extensions):


引数のInsertCommand, MoveCommandが持っているeditはテキスト編集したい時にベースクラスからもってくるものです。

ベースクラスは4つあって、その中でもテキストを編集するsublime_plugin.TextCommandを使用する時にだけ必要な引数です。

switch_fileはソースファイルに対応したヘッダファイルを開くコマンドなので、sublime_plugin.WindowCommandになっている。


コンテキストがある場合


コンテキストの構造


  • key

    状態を表す

    例えば、selection_empty が入っていたら 文字選択をしていない場合 true を返す。

    省略不可


  • operator

    演算子

    例えば、equal, not_equal などがある。

    省略可


  • operand

    operatorがequal, not_equalならtrue, false、1, 2などを入力。

    regex_match, not_regex_match なら正規表現を入力。

    省略可


  • match_all

    これをtrueにした判定のがすべてtrueにならなければマッチしたことにはならない。

    デフォルトではfalse

    省略可



コンテキストの設定

コンテキストの使い方はこんな感じ。もちろんcommandによってはargsが入ります。

{ "keys": ["キー"], "command": "コマンド名", "context": 

[
{ "key": "キー", "operator": "演算子", "operand": "結果", "match_all": "true or false" }
]
}


keyの一覧


  • num_selections

    選択している数


  • selection_empty

    何も選択していなければtrue


  • preceding_text

    キャレットより前の文字がどうなっているかを調べる


  • following_text

    キャレットより後の文字がどうなっているかを調べる


  • has_prev_field

    前に使用可能なスニペットフィールドがあればtrue


  • has_next_field

    後ろに使用可能なスニペットフィールドがあればtrue


  • auto_complete_visible

    オートコンプリートリストが表示されていればtrue


  • panel_visible

    何かpanelが表示されていればtrue


  • overlay_visible

    オーバーレイが表示されていればtrue


  • setting.XXX

    settingファイルで設定されているXXXの値が返る

    値の確認はメニューの Preferences -> Setting - Default, Preferences -> Setting - User で確認


  • selector

    現在の scope が返ります

    Packages -> 'scope名のフォルダ' -> 'scope名.tmLanguage'ファイルの下のほうにあるscopeNameでどんなscope名になってるか確認

    こんな風に書いてあるところです


<key>scopeName</key>

<string>source.c++</string>


operatorの一覧


  • equal, not_equal

    key と operand が同じだったら実行させたい = equal

    違ったら実行させたい = not_equal


  • regex_match, not_regex_match

    key で選ばれる文字列が operand の正規表現とマッチするなら実行させたい = regex_match

    違ったら実行させたい = not_regex_match

    こっちはPythonでいう re.search. 文字列の途中マッチOK


  • regex_contains, not_regex_contains

    key で選ばれる文字列が operand の正規表現とマッチするなら実行させたい = regex_contains

    違ったら実行させたい = not_regex_contains

    こっちはPythonでいう re.match. 文字列の途中マッチNG



keyの使用例


num_selections

選択している数


Default(Windows).sublime-keymap

  { "keys": ["escape"], "command": "single_selection", "context":

[
{ "key": "num_selections", "operator": "not_equal", "operand": 1 }
]
}

2つ選択しているので、escapeキーを押すと、single_selectionが実行される

selection_empty


selection_empty

何も選択していなければtrue


Default(Windows).sublime-keymap

  { "keys": ["ctrl+w"], "command": "cut", "context":

[
{ "key": "selection_empty", "operator": "equal", "operand": true }
]
}

何も選択されていないのでtrueになり、ctrl+wを押すと、cutが実行される

selection_empty


preceding_text

キャレットより前の文字がどうなっているかを調べる


Default(Windows).sublime-keymap

  { "keys": ["shift+tab"], "command": "unindent", "context":

[
{ "key": "preceding_text", "operator": "regex_match", "operand": "^[\t ]*" }
]
},

キャレットより前の文字が^[\t ]*にマッチしているので、shift+tabを押すとunindentが実行される

preceding_text


following_text

キャレットより後の文字がどうなっているかを調べる


Default(Windows).sublime-keymap

  { "keys": ["ctrl+j"], "command": "move", "args": {"by": "characters", "forward": true}, "context":

[
{ "key": "following_text", "operator": "regex_match", "operand": ";$" }
]
}

キャレットより後ろの文字が ;$ にマッチしているので、ctrl+j を押すとキャレットがひとつ後ろに移動する

following_text


has_prev_field

前に使用可能なスニペットフィールドがあればtrue


Default(Windows).sublime-keymap

  { "keys": ["shift+tab"], "command": "prev_field", "context":

[
{ "key": "has_prev_field", "operator": "equal", "operand": true }
]
},


030-for-int-loop-(fori).sublime-snippet

<snippet>

<description>For Loop</description>
<content><![CDATA[
for( int ${1:i} = 0; $1 < ${2:count}; ${3:++}$1 ){
${0:/* code */}
}
]]>
</content>
<tabTrigger>for</tabTrigger>
<scope>source.c, source.objc, source.c++, source.objc++</scope>
</snippet>

{2:count}のスニペットフィールドを選択していて、$1のスニペットフィールドがあるのでshift+tabを押すとprev_fieldが実行される

has_prev_field


has_next_field

has_prev_fieldの反対

後ろに使用可能なスニペットフィールドがあればtrue

上記の例からhas_prev_field を has_next_fieldに変えた場合、画像は${2:count}のスニペットフィールドを選択していて、${3:++}のスニペットフィールドがあるのでshift+tabを押すとprev_fieldが実行される


auto_complete_visible

オートコンプリートリストが表示されていればtrue


Default(Windows).sublime-keymap

  { "keys": ["escape"], "command": "hide_auto_complete", "context":

[
{ "key": "auto_complete_visible", "operator": "equal", "operand": true }
]
},

表示されているのでtrueになり、escapeキーを押すと、hide_auto_compliteが実行される

auto_complete_visible


panel_visible

何かpanelが表示されていればtrue


Default(Windows).sublime-keymap

  { "keys": ["escape"], "command": "hide_panel", "args": {"cancel": true},

"context":
[
{ "key": "panel_visible", "operator": "equal", "operand": true }
]
},

パネルが表示されているので、hide_panelが実行される

panel_visible


overlay_visible

オーバーレイが表示されていればtrue


Default(Windows).sublime-keymap

  { "keys": ["escape"], "command": "hide_overlay", "context":

[
{ "key": "overlay_visible", "operator": "equal", "operand": true }
]
}

オーバーレイが表示されているので、hide_overlay が実行される

overlay_visible


setting.XXX

settingファイルで設定されているXXXの値が返る

値の確認は Preferences -> Setting - Default, Preferences -> Setting - User で確認。


Preferences.sublime-settings

    "shift_tab_unindent": false



Default(Windows).sublime-keymap

  { "keys": ["shift+tab"], "command": "unindent", "context":

[
{ "key": "setting.shift_tab_unindent", "operator": "equal", "operand": true }
]
}

shift_tab_unindent は falseに設定されているので、 shift_tab_unindent の時にshift+tabを押しても unindent は実行されません。


selector

現在の scope名が返ります


Default(Windows).sublime-keymap

{

"keys": ["ctrl+s"], "command": "generate_snippet_from_raw_snippet", "context":
[
{ "key": "selector", "operator": "equal", "operand": "source.sublimesnippetraw" }
]
}

ctrl+sを押すと、operand で選んだ scopeでのみ generate_snippet_from_raw_snippet が実行されます。


key が panelの場合

keypanel になっている時は operand には panelの名称が入ります。

panelの名称一覧


  • find

    find


  • incremental_find

    incremental_find


  • find_in_files

    find_in_files


  • replace

    replace


  • console

    console



Packageの開発者の人へ

windows: Ctrl+Alt+<alphanum>

OSX: Option+<alphanum>

この組み合わせのキーは非ASCIIコードを入力できなくなる可能性があるので、使用しないほうがいいみたいです。