Sublime Textプラグイン作成に関する話題
Sublimeプラグイン作成とスニペット,コード補完,マクロ,キーバインド,メニュー定義など付随する話題をあれこれと...
【 目次 】
プラグイン作成の参考URL
英語だがバイブル的なものから
- How to Create a Sublime Text 2 Plugin - Tuts+ Code Tutorial
- API Reference - Sublime Text 2 Documentation
- API Reference - Sublime Text 3 Documentation
- SublimeText3 - Sublime Text API Reference(翻訳) - Qiita
上記の日本語訳
日本語でわかりやすいのは以下の記事
- Sublime Text2でプラグインを作る | Developers.IO
- Sublime Text 2 のプラグインを作る | ありえるえりあ
特に、Default のプラグインは、サンプル例となることを意識して作られているようなので、参考になります。
プラグインから組み込みのコマンドを呼ぶことができるのですが、どのようなコマンドがあるかを調べるには、キーバインディングの定義が参考になります。
メニューの Preferences > Key Bindings – Default で keymap のファイルを開き、バインドしているキーからコマンド名を逆引きするのが効率のよいやり方です。
メニューからTools->New Plugin...と選択し、プラグインのテンプレートを作成。
プラグインのクラス名はXxxCommand
通常はsublime_plugin.TextCommandを継承
クラス名からCommandを除き、スネークケースにしたものがコマンド名になる。
作成したプラグインソースはパッケージディレクトリ(メニューからPreferences > Browse Packagesを選択して表示されるディレクトリ)直下のUserディレクトリもしくはパッケージディレクトリ直下に新たにデレクトリを作成して保存。
プラグインの実行は、コンソールWindowから
view.run_command('コマンド名')
より詳しい話題やサンプルコードなど
-
# 選択されている文字列を "foo" に置き換える import sublime, sublime_plugin class ExampleCommand(sublime_plugin.TextCommand): def run(self, edit): for region in self.view.sel(): if not region.empty(): self.view.replace(edit, region, 'foo')
-
[ツール/エディタ]Sublime Text3を使いはじめたのでプラグインも作ってみた | Wood-Roots.blog
プラグイン内の1つの機能が1つのクラスとなるため、単一ファイル内に複数のクラスを記述することも可能です。
- SublimeTextのプラグイン作成方法|ブログ|奈良先端科学技術大学院大学 情報基盤システム学研究室
- SublimeText2 - Sublime Text 2 のプラグイン (コマンド) をつくる - Qiita
# ファイルの内容をすべて取得 region_all = sublime.Region(0, self.view.size()) self.view.substr(region_all)
作成したコマンドはkeymapやmenuに登録して実行する事になる。
メニューへ追加
Main.sublime-menu メインメニューに追加
Side Bar.sublime-menu サイドバーでファイルやフォルダを右クリックしたときに出るメニューに追加
Context.sublime-menu エディタで右クリックしたときに出るメニューに追加差分を記入する。
メインメニューにMyCommandsという自作のコマンドを実行するメニューを追加する例を以下に示す。
Main.sublime-menu
[ { "id": "myplugin", "caption": "MyCommands", "mnemonic": "M", "children": [ { "id": "my_g_search", "caption": "googleで検索", "mnemonic": "g", "command": "my_google_search" }, { "id": "my_surround_line", "caption": "<>で囲む", "mnemonic": "<", "command": "my_surround_line", "args": {"begin_str":"<", "end_str":">"} } ] }, ]
captionにメニューに表示される文字列,argsでコマンドの引数(後述),mnemonicはショートカットキーを示しているようだ。
コンソールWindowよりPythonのコマンドを実行してみる。
Sublime Text2のコンソールWindowはPythonの対話型コンソールって感じ。
コンソールWindowは、ctrl + @またはctrl + shift + `またはメニューのView->Show Consoleにて表示
コンソールWindow下部のテキストボックスにてPythonのコマンドを実行できる。
コンソールの実行環境を確認
Sublime Text Tips 2. コンソールで使用できる変数 - 日記
Consoleでは pythonコードを実行可能です。
プラグインのエラーなどもこのコンソールで確認することができます。
Consoleでは手軽にpythonコードを試すことができます。
使える物の一覧は、「globals().keys()」で表示できます。
printコマンドによりコンソールに出力
x='あいうえお' print(x[0])
カレントデレクトリを表示
import os print(os.getcwd())
メモ帳を起動
os.system("notepad.exe")
プラグインのAPIを利用して、編集中のファイル名を表示
view.file_name()
Sublime Text 2とSublime Text 3のプラグインの互換性に関する話題
Sublime Text 2のプラグインソースを参考にSublime Text 3のプラグインを作る場合に、問題となることがある。
begin_edit() と end_edit()がSublime Text 3では使えない等。
プラグイン作成の参考URLで紹介した「Sublime Text 2 のプラグインを作る | ありえるえりあ」の記事にあるSublime Text 2のソースをSublime Text 3で実行したところ19行目でエラーになってしまった。 on_done等のイベントの中でeditオブジェクトは使えないらしい。
それを自分なりに修正を試みたのが以下のコード
SublimeSurroundCommandをSublime3に対応
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class Sublime3SurroundCommand(sublime_plugin.TextCommand): def on_done(self, word): self.view.run_command('sublime3_surround_sub',{"word": word}) def run(self, edit): # Show input panel for surround word, then handling input self.view.window().show_input_panel('Surrond Word: ', '', self.on_done, None, None) class Sublime3SurroundSubCommand(sublime_plugin.TextCommand): def run(self, edit, word): for region in self.view.sel(): if not region.empty(): s = self.view.substr(region) surroundStr = word + s + word # Replace the selection with transformed text self.view.replace(edit, region, surroundStr) |
editを取得するにはbegin_edit()を使うのではなく、self.view.run_commandを使って別のコマンドを作成して呼び出すって事かな。
アウトプットパネルを表示してみる。
-
sublime text3用のプラグイン作成において、WindowCommandでbegin_edit()が出来ないので要注意的なお話 - 適当な感じでプログラミングとか!
sublime text3ではerrorにならないがカーソルが動かなくなってしまう。 -
灯火: Sublime Text 3 : プラグインで出力ウィンドウに文字列を出力する
この記事を参考にget_output_panel
をcreate_output_panel
に変更。
他のSublime Textの記事も参考に。
最終的なコードは
OutputPanel.py
1 2 3 4 5 6 7 8 9 | class OutputPanelCommand(sublime_plugin.TextCommand): def run(self,edit): window = self.view.window() output_view = window.create_output_panel("WindowName") window.run_command("show_panel", {"panel":"output.WindowName"}) output_view.set_read_only(False) output_view.insert(edit, output_view.size(), "Hello, Output") output_view.set_read_only(True) |
キーバインドとコマンド
コマンドに引数を渡す。
通常、プラグインクラスのrunメソッドは以下のようなコードになるが、
プラグインクラスのrunメソッド
class ExampleCommand(sublime_plugin.TextCommand): def run(self, edit):
runメソッドには以下のように自由に引数を定義できる。
プラグインクラスのrunメソッド - 自由に引数を定義
class ExampleCommand(sublime_plugin.TextCommand): def run(self, edit, arg1, arg2, arg3): print "arg1={0}, arg2={1}, arg3={2}".format(arg1, arg2, arg3)
この追加の引数付きのrunメソッドをコンソールより実行。
view.run_command('example', {"arg1": "arg_value1", "arg2": "arg_value2", "arg3": "arg_value3"})
コマンドをキーバインド(作成したコマンドをショトッカトキーに設定)
作成したコマンドをショートカットキーに登録するには
SublimeText2のキーバインドを、ちょっと突っ込んで解説 - Qiita
引数を追加したコマンドをkeymapに登録してみる。
{ "keys": ["キー"], "command": "example", "args": { "arg1": "arg1_value", "arg2": "arg2_value", "arg3": "arg3_value" } }
argsに引数リストを列挙すれば良い。
プラグインより他のsublime textのコマンドを実行
既に示したとおり、プラグインより他のプラグインのコマンド(sublime textのコマンド)を実行する事ができる。
プラグインより他のプラグインのコマンド)を実行
class ExampleCommand(sublime_plugin.TextCommand): def run(self, edit): ... self.view.run_command('sublime3_surround_sub',{"word": "*"}) ...
sublime textのコマンドにはどのようなものがあるかは、メニューよりPreferences > Key Bindings – Default で Default (xxx).sublime-keymapを参照してみれば良い。
例えば、次の行は
{ "keys": ["ctrl+s"], "command": "save" },
以下のコマンドをコンソールにて実行する事で編集中のファイルが保存できる事を示している。
view.run_command('save')
コマンドを簡単に見つけるには
と、ここまで書いたところで、コマンドを見つけるもっと良い方法がある。(SublimeText2 - Sublime Text 2でコマンドパレットのコマンドにショートカットキーを割り当てる - Qiita)
コンソールにて以下ののコマンドを実行すると、どのようなコマンドが実行されたのかコンソールに出力してくれる。
sublime.log_commands(True)
コマンドをコマンドパレットに登録(拡張子.sublime-commandsというファイルに記述。 )
パッケージディレクトリに新しいデレクトリを作成し、 デレクトリ名.sublime-commandsというファイルにコマンド定義を記述してもいいみたい。
引数付きコマンドのコマンドパレット登録の例
[ { "caption": "myPlugin: 自由に引数を定義できる。", "command": "example", "args": { "arg1": "arg1_value", "arg2": "arg2_value", "arg3": "arg3_value" } } ]
スニペットとコード補完
キーワードを入力してタブキーやctrl+spaceでコード補完やスニペットが可能。
例えばhtmlファイル編集中に以下のキーワードを入力してtabキーやctrl+spaceを押すと⇒のように展開される。、
srcまたはscript⇒<script type="text/javascript"></script>
link⇒<link rel="stylesheet" type="text/css" href="">
style⇒<style type="text/css"></style>
php⇒<?php ?>
html⇒<html>..
スニペット
- Sublime Text 3: スニペットの登録方法と使い方 | Web Design Workbook
変数${n:デフォルト値}
$のエスケープは\$ - sublimetextのスニペット
キャレット位置指定
- $1,$2...$n
tabキーを押すたびに$1、$2で指定した編集点にキャレットが移動する。 $0で最後の編集点に移動。 - 選択範囲のテキストを利用
$SELECTION 正規表現を使った置換も可能。 キーバインドでスニペットファイルを設定する事も可能。 キーバインドでスニペットを直接定義する事も可能。
- $1,$2...$n
- Snippets — Sublime Text Help
スニペット定義ファイルの作成は、プラグインと同様、メニューからTools->New Snippet...と選択し、スニペットのテンプレートを作成。
作成したプラグインソースはパッケージディレクトリ直下のUserディレクトリもしくはパッケージディレクトリ配下に保存。
スニペット定義ファイルの拡張子は「.sublime-snippet」。
コマンドパレットにてsnippet:
を入力,スニペットを検索して呼び出すこともできる。
メニューからTools > Snippets...を選択しても同じ。
1つのファイルに複数のスニペットを登録する事はできない。(1ファイル1スニペット)
insert_snippetコマンド
insert_snippetコマンドを使ってスニペットを挿入できる。 例えば、文字列を選択してコンソールより以下を実行すると、選択した文字列が{}で囲まれることになる。
view.run_command('insert_snippet',{"contents": "{${0:$SELECTION}}"})
同様に、keymapに以下を登録する事で、文字列を選択した状態で{
をキー入力すれば、選択した文字列が{}で囲まれることになる。
// 文字列を選択状態で `{` を入力すると '}' が自動入力されて、選択文字列を `{}` で囲む { "keys": ["{"], "command": "insert_snippet", "args": {"contents": "{${0:$SELECTION}}"} }
コード補完
スニペットとの違いがわかりづらいのだが、似たような機能としてコード補完があるもよう。 Packagesデレクトリの配下に拡張子.sublime-completionsのファイルを作成して、コード補完の定義を記述する。
スニペットは1ファイル1スニペットの定義であるが、コード補完の定義ファイルは1つのファイルに複数のコード補完を定義できる。
- Completions Files — Sublime Text Unofficial Documentation
- Completions — Sublime Text Unofficial Documentation
シンタックス(ファイル)とScope Name,Syntax Definitions
スニペット定義ファイルのscopeの項目にsource.pythonと指定すると、pythonのソースを編集中でないとこのスニペットは有効にならない。
また、htmlファイル編集中の時だけスニペットを有効にするにはscopeにtext.htmlと指定する。
scopeにはどのような文字列を指定すれば良いのだろうか?
上記の記事によれば、コンソールWindowより
view.scope_name(view.sel()[0].begin()).strip().split(' ')[0]
を実行する事により、編集中のファイルのscope Nameを知る事ができるそうである。
またctrl+alt+shift+pキーを押下する事でウインドウ下のステータスバーに現在のscope文字列が表示される。
メニューから[Preferences] - [Browse Packages]と選択すればパッケージのディレクトリが出てきます。 Pythonディレクトリを探して中を開いてみると、そこにPython.tmLanguageがあるはずです。
ところがSublime Text 3の場合にはパッケージディレクトリ配下にPythonディレクトリがみあたらない。
Sublime Text 3のインストールデレクトリの直下のPackagesデレクトリ(C:\Program Files\Sublime Text 3\Packages)にPython.sublime-packageというファイルが存在する。
このファイルはzipファイルであるらしく、これをコピーして拡張子zipを付加して解凍するとPython.tmLanguageファイルを得る事ができる。
このファイルを開いてscope_nameで検索するとscope_nameを発見できる。
ところで、この拡張子.tmLanguageというファイルは何のためのファイルなんだろう。
Sublimeの言語パッケージの構文定義(Syntax Definitions)ファイルというものらしい。
Python.tmLanguageであればpythonの言語定義が記述されているパッケージのディレクトリという事になるようだ。
編集中のテキストのシンタックスファイルはコンソールよりview.settings().get('syntax')
を実行する事で取得できる。
以下はpythonやhtml,markdownに編集中のファイルを切替えて実行した結果である。
>>> view.settings().get('syntax') 'Packages/Python/Python.tmLanguage' >>> view.settings().get('syntax') 'Packages/HTML/HTML.tmLanguage' >>> view.settings().get('syntax') 'Packages/Markdown Extended/Syntaxes/Markdown Extended.tmLanguage'
拡張子.pyにSublimeのsyntaxモードが関連付けられており、それに更にScope Nameが関連付けられているとい事なのかな...
scope_nameを取得して、状況に応じて動作を変更するプラグインの例を見つけた。
マクロ
プラグインをわざわざ作成しなくとも、簡単な動作ならマクロで実現できる。
- Mac - SublimeText2/3でマクロを作り、キーボードショートカットに登録する - Qiita
- sublime text「プラグイン」「マクロ」「ファイルで検索」を使ったテクニック3選! | アライドアーキテクツのクリエイターブログ
Sublimeのコマンドを単純にシーケンシャルに実行するだけならマクロで事足りる。
パッケージディレクトリに、拡張子.sublime-macroのファイルを作成して、実行させたいコマンドのリストを記述。 キーボードショートカットやメニューにrun_macro_fileコマンドを登録するだけ。
"command": "run_macro_file", "args": {"file": "Packages/マクロファイルへのパス"}
プラグインサンプル
Webブラウザを開く
- Python | 選択中の文字列で各種Webサイトを開くSublime Text2 Plugin - Tbpgr Blog
- SublimeTextで文章中のURLを一気にブラウザで開くプラグイン作成 | これを読めば思い出す
上記の記事を参考に、選択した文字列をgoogleで検索するプログラムの例を示す。
# 選択した文字列をgoogleで検索 class GSearchCommand(sublime_plugin.TextCommand): def run(self, edit): for region in self.view.sel(): if not region.empty(): # Get the selected text select_text = self.view.substr(region) url = 'http://www.google.co.jp/search?q=%s' % (select_text) import webbrowser webbrowser.open(url)
プラグインより指定のファイルを実行
# explorerを起動 class explorerCommand(sublime_plugin.TextCommand): def run(self, edit): import os os.system('explorer')
編集中のテキスト行をスキャンする。
class LineScanCommand(sublime_plugin.TextCommand): def run(self, edit): # 最終行を取得 line_max, _ = self.view.rowcol(self.view.size()) # 行スキャンのループ for line_no in range(0, line_max): # 行頭のpointを取得 line_point = self.view.text_point(line_no, 0) # 行のreginオブジェクトを取得 line_region = self.view.line(line_point) # 行の文字列を取得 line_text = self.view.substr(line_region) print("{0:>10}: {1}".format(line_no + 1, line_text))
特定のシンタックスモードの時に、「保存時に設定ファイルのコマンドを実行するプラグイン」
蛇足
Sublime TextのJSONのコメント
Sublime Textの設定ファイルはkeymapファイルのようにJSONで記述される事が多い。
そこでSublime TextのJSONのコメントについて一言。
通常のJSONにはコメント構文は無い。
しかし、Sublime TextのJSONには「JavaScriptのコメント構文が許されている」そうである。
(JSONにはコメント構文がない - Qiita)