Sublime Text 2 プラグインチュートリアルのまとめ


ほぼ公式認定 Sublime プラグインチュートリアル、[How to Create a Sublime Text 2 Plugin](http://net.tutsplus.com/tutorials/python-tutorials/how-to-create-a-sublime-text-2-plugin/) から、メモ書き程度に要点を抜き出しています。また、説明が不十分なものに関しては他のドキュメントを参考に説明を加えています。元ネタはチュートリアル形式になっています。チュートリアルの完成形コードが [GitHub にあります](https://github.com/wbond/sublime_prefixr)ので、ご参考までに。

-

[Sublime Text 2 API Reference](http://www.sublimetext.com/docs/2/api_reference.html) と Default パッケージを参照しながら作っていくといいよ。

##作成するPythonファイルの名前
.pyで終わっていれば、ぶっちゃけ何でもよい。

## インポート
*sublime* と *sublime_plugin* の、２つのパッケージが必要。

```python:
import sublime, sublime_plugin
```

## クラス宣言
*sublime_plugin* パッケージの３つのクラスのどれかを継承する。

* **TextCommand** View オブエジェクトで、選択したファイルやバッファにアクセスできる
* **WindowCommand** Window オブジェクトで、現在のウィンドウにアクセスできる
* **ApplicationCommand** 特定のウィンドウやファイル・バッファにアクセスできない。あまり使われない

コマンド名は、最後の Command を取って、CamelCase(単語単位で大文字にする記法) を underscore_notation(全部小文字で、アンダースコアでつなげる記法) に変えたものとなる。

例えば、このようになる。

```python:
class CommandNameCommand(sublime_plugin.TextCommand):
```

##コマンドの実行
ctrl+` で Sublime コンソールを開き、例えば先の例の場合、次のようにして実行する。

```python:
view.run_command('command_name')
```

## 選択範囲の取得
TextCommand では、*self.view* で現在のビューにアクセスできる。View オブジェクトの *sel()* で、選択範囲が iterable な RegionSet で返される。Set になっているのは、Sublime Text では１度に複数の箇所を選択できるようになっているため。

```python:
sels = self.view.sel()
for sel in sels:
	(この時点で、１カ所の選択範囲が sel に入っている)
```

## 選択範囲の操作
[Sublime Text 2 API Reference](http://www.sublimetext.com/docs/2/api_reference.html) に *sublime.RegionSet* の関数がある。

```python:
# 追加 (隣り合った選択範囲があれば、それにつながる)
sels.add(region)
# 一部削除
sels.subtract(region)
# クリア
sels.clear()
# 選択した範囲を含むか
sels.contains(region)
```

## Edit オブジェクト
要は、Undo/Redo グループのこと。

```python:
# command_name コマンドの Undo/Redo グループを作成
edit = self.view.begin_edit('command_name')
# Undo/Redo グループを削除
self.view.end_edit(edit)
```

## テキストの操作
[Sublime Text 2 API Reference](http://www.sublimetext.com/docs/2/api_reference.html) で引数に *region* が入っていれば、そこに前項で取得した RegionSet を突っ込める。

```python:
# 選択範囲にあるテキストを取得
self.view.substr(sel)
# 選択範囲のテキストを置換
self.view.replace(edit, sel, 'any_string')
```

## プラグインで他のコマンドを実行
*self.view* で現在のビューにアクセスできるため、次のように書ける。

```python:
self.view.run_command('command_name')
```

## スレッド化
HTTP リクエストを発行するようなものに関しては、レスポンスが悪化するため、バックグラウンドで実行するようにする必要がある。このあたりの説明は、むしろ[Pythonのドキュメント](http://docs.python.org/library/threading.html#thread-objects)の方が詳しい。

## ステータスバーに表示
*key* の部分は何でもよい。ステータスバーには *key* の昇順に並ぶ。

```python:
# ステータスバーに設定
self.view.set_status('key', 'any_string'))
# ステータスバーをクリア
self.view.erase_status('key');
# メッセージ領域に設定
sublime.status_message('any_string')
```


## タイムアウト付きで関数を実行
some_function() を実行して、100 ミリ秒でタイムアウトさせる場合、次のようにする。

```python:
sublime.set_timeout(lambda: some_function(), 100)
```

## 設定を取得
*/Packages/Default/Preferences.sublime-settings* に設定の一覧がある。

```python:
# Line Endings 設定を取得
line_endings = self.view.settings().get('default_line_ending')
```

## キーバインディング
* **Default (Windows).sublime-keymap**
* **Default (Linux).sublime-keymap**
* **Default (OSX).sublime-keymap**

作成しているパッケージのフォルダの中に、上の３つのファイルを作成し、それぞれ次のように記載する。Default フォルダの中の同名ファイルを見て、かぶらないようなバインディングを指定すること。

```json:
[  
    {  
        "keys": ["ctrl+alt+x"], "command": "command_name"  
    }  
]
```

## メニューへ追加
* **Main.sublime-menu** メインメニューに追加
* **Side Bar.sublime-menu** サイドバーでファイルやフォルダを右クリックしたときに出るメニューに追加
* **Context.sublime-menu** エディタで右クリックしたときに出るメニューに追加

作成しているパッケージのフォルダの中に、上の３つのうちのどれかの名前でファイルを作り、*/Packages/Default* にある同じ名前のファイルを参考にして、差分を記入する。例えば、Edit > Wrap に *command_name* コマンドを追加したい場合は、次のようにする。

```json:
[
    {
        "id": "edit",
        "children":
        [
        	{
	        	"id": "wrap",
	        	"children":
	        	[
	        		{"id": "command_name"},
					{ "command": "command_name" }
	        	]
        	}
        ]
    }
]
```