SublimeText3の自作プラグインを作る

259, 2019-11-28

目次

最初に

こちらの記事がわかりやすかった。
こちらはAPIの邦訳。

HelloWorld プラグイン

編集中のファイルに「Hello, World!」を出力するだけの HelloWorld プラグインを作成。プラグインのコマンドは TextCommand ベースの HelloWorldCommand のみ(以下のベースクラスを参照)。

ディレクトリ構成

SublimeText3(ST3)を起動して

$ subl

ST3 上部のメニューバーから「Preferences」→「Browse Packages」を開く。パスなら「/home/user-name/.config/sublime-text-3/Packages」ディレクトリ。「Packages」ディレクトリ直下に「HelloWorld」ディレクトリを作成。ここに必要なファイルを作成。
最終的にこんなツリーに。

$ tree
HelloWorld/
|-- HelloWorld.sublime-settings
|-- Context.sublime-menu
|-- HelloWorld.py
|-- Main.sublime-menu
`-- Side Bar.sublime-menu

プラグイン用のベースクラスの選択

参照によると用途によって各コマンドのベースクラスが異なる。

WindowCommand: self.windowでカレントウィンドウにアクセスできる
TextCommand: self.viewで編集中のファイルにアクセスできる
EventListener: ファイルの保存などイベントをフックして実行できる
ApplicationCommand: ウィンドウやファイルにアクセス出来ない

HelloWorld.py の作成

ST3 上部のメニューバーから「Tool」→「Developer」→「New Plugin」と選択して、Pluginのひな形を作成。そして「HelloWorld」ディレクトリ内に「HelloWorld.py」で保存。

import sublime, sublime_plugin

class ExampleCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        self.view.insert(edit, 0, "Hello, World!")

クラス名を「HelloWorldCommand」に変更。このコマンドは TextCommand ベースのコマンド。

class HelloWorldCommand(sublime_plugin.TextCommand):

ここからデバッグが必要になるので、ST3 上部のメニューバーから「View」→「Show Console」と選択してコンソールを開く。コンソールのコマンド実行欄に

view.run_command('hello_world')

と入力して「hello_world」コマンドを実行。現在開いているファイルの先頭に「Hello, World!」が挿入された。
view.run_command にはコマンド名を渡す。しかし、このコマンド名をタイプした覚えがない(゚Д゚)?。これはクラス名から由来するらしい。クラス名が

 class HelloWorldCommand

であれば、コマンド名は「hello_world」に。クラス名が

 class ExampleCommand

であれば、コマンド名は「example」に暗黙的に変換される。参照によるとスネークケースに変換されるらしい。

hello_world コマンドをショートカットキーから呼ぶ

「Preferences」→「Key Bindings - User」から追加。

[
    { "keys": ["super+shift+h"], "command": "hello_world" },
]

hello_world コマンドをメニューから呼ぶ

「Main.sublime-menu」を作成して「HelloWorld」ディレクトリ直下に保存。

[
    {
        "id": "HelloWorld",
        "caption": "Hello, World!",
        "children":
        [
            {
                "caption": "run",
                "command": "hello_world",
            }
        ],
    }
]

ST3 上部のメニューバーに「Hello, World!」アイテムが出現。クリックして「run」で「hello_world」コマンドが実行された。

hello_world コマンドを右クリックメニューから呼ぶ

「Context.sublime-menu」を作成して「HelloWorld」ディレクトリ直下に保存。

[
    {
        "id": "HelloWorld",
        "caption": "Hello, World!",
        "command": "hello_world"
    }
]

編集領域内での右クリックメニューに「Hello, World!」アイテムが出現する。クリックで「hello_world」コマンドが実行された。

hello_world コマンドをプロジェクトサイドバー上の右クリックメニューから呼ぶ


「Side Bar.sublime-menu」を作成して「HelloWorld」ディレクトリ直下に保存。

[
    {
        "id": "HelloWorld",
        "caption": "Hello, World!",
        "command": "hello_world"
    }
]

プロジェクトを開くと ST3 左部にサイドバーが現れる。そこで右クリックすると「Hello, World!」が出現。クリックで「hello_world」コマンドが(ry

プラグインの設定

プラグインは独自の設定ファイルを持つことが出来る。「HelloWorld」ディレクトリ直下に JSON で「HelloWorld.sublime-settings」を保存。

{
    "message": "HelloWorld plugin as free plugin."
}

プラグインから設定ファイル内の設定値を参照するには、最初に設定ファイルのロードを行う。その後、各設定にアクセスできる。

import sublime, sublime_plugin

class ShowSettingsCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        # プラグインの設定ファイルを読み込み
        settings = sublime.load_settings('HelloWorld.sublime-settings')

        # 設定値を取得してコンソールに出力
        message = settings.get('message')
        print(message)

自作プラグインに自作モジュールを読み込む

プラグインが肥大化し、モジュールで分割する必要が出てきた場合などは API の sublime.packages_path() を使ってパッケージまでのパスを作成し、システムに追加。
でもsublime.packages_path()はたまに空文字列を返す。原因は不明。__file__を使う方法もあって、そちらは今のところ正常に動作。それからパッケージ名とプラグイン名が被ると正常に動作しない?いろいろと謎が多い部分(´・ω・)(・ω・`)ネー

myplugin/ # <- プラグインのルート
    myplugin.py # <- プラグイン本体
    mypackage/ # <- パッケージ
        __init__.py
        mymodule.py # <- モジュール

sublime.packages_path()を使う場合。

import sublime, sublime_plugin
import os, sys

sys.path.append(os.path.join(sublime.packages_path(), 'mypackage')) # <- 'mypackage' は パッケージ名
from mypackage import mymodule
from mypackage.mymodule import myfunc

__file__を使う場合。

import sublime, sublime_plugin
import os, sys

sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from mypackage import mymodule
from mypackage.mymodule import myfunc

API の使い方

ST3 のプラグイン開発では ST3 提供の API を使用して開発する。その API の詳細は Sublime Text 3 Documentation - API Reference から参照可能だけど、「プラグイン開発者がやりたいこと」と「そのやりたいことを実現する API」のリンクで難儀したので試してみた結果を以下に履歴。

TextCommand

ReplaceToReimuCommand

現在開いているファイルのテキスト全てをAAに置き換え。参照元のコードではペガサスに置き換えていた。

import sublime, sublime_plugin

class ReplaceToReimuCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        allContent = sublime.Region(0, self.view.size())
        self.view.replace(edit, allContent, '    , -、\n   _ ,ノ\n / :;;/" 、⌒ヽ,\n | :: ( △::;;;::△:;|\n ヽ,,::、WWW;/\n  くi Lノノハノ)」\n   λ.[i ゚ ヮ゚ノi! Trick or Treat!(お賽銭をくれなきゃいたずらするわよ)\n   レ\',ヘ.i`ム\'」つ\n   ,く_,//T.iλ\n   "ーr_,t_ァ\'"\n')

カーソルが置かれている行を取得してコンソールに文字列を表示

参照: python - Get current line in Sublime Text 3 plugin - Stack Overflow

import sublime, sublime_plugin

class ShowCurLineCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        vw = self.view

        # Selection オブジェクトを取得
        sel = vw.sel()

        # Selection から Region オブジェクトを取得
        reg = sel[0]

        # line() で Region を行単位に拡大する
        # line() は full_line() のエイリアス
        reg = vw.line(reg)

        # Region を String オブジェクトに変換
        curln = vw.substr(reg)

        # ST3 のコンソールに出力
        print(curln)

カーソルが置かれている行を文字列で置き換え

import sublime, sublime_plugin

class ReplaceCurLineCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        vw = self.view

        # Selection オブジェクトを取得
        sel = vw.sel()

        # Selection から Region オブジェクトを取得
        reg = sel[0]

        # line() で Region を行単位に拡大する
        # line() は full_line() のエイリアス
        reg = vw.line(reg)

        # カーソルが置かれている行を置き換え
        vw.replace(edit, reg, 'REPLACE!')

参照

投稿者名です。64字以内で入力してください。

必要な場合はEメールアドレスを入力してください(全体に公開されます)。

投稿する内容です。

スポンサーリンク

スポンサーリンク

スポンサーリンク

スポンサーリンク