Open Tools API その0:概要

戯言前口上

RAD Studioにコードフォーマッターが実装されても、残念ながら、宗教論争にすらなるC/C++のコーディングスタイルすべてをカバーし切れていないのが不満。ということで、RAD Studioのコードエディタ上からGNU IndentUncrustifyといった既存のコードフォーマッタを手軽に呼び出したり、あるいは、エディタの選択部分に対して、sedとかawkのようなテキストフィルタをvi(ex)の!コマンドのようにフィルタをかけられたら便利かなと思い、敷居が高いと言われるOpen Tools APIに挑戦して、何とか実装してみようと。

本音を言えば、C++Builderで書きたいのだけど、キモであるウィザードインターフェースの実装部分が少々面倒*1なのと、デバッグ時に何故かブレークポイントを設定しても止まらない場合がある*2ので、少々不本意ながら記述言語はDelphiで。てか、Open Tools APIに関してはDelphiのほうが楽かも。

Open Tools APIって何?

Open Tools APIとは、RAD Studioを拡張するためのAPI群のことで、メインメニューに何らかの項目を追加したり、コードエディタ内部にアクセスするなど、これらを使用することによってRAD Studioを自由に拡張することが可能になる。IDEを拡張するには、後述する「ウイザードインターフェース」と「ノーティファイアインターフェース」と呼ばれるクラスを継承したサブクラスを持つパッケージを作成して、そのパッケージをIDEに登録するだけでOK。*3デバッグIDEそのものをデバッグする感じでデバッグが出来る。ただし、デバッグ時にパッケージの登録・削除を繰り返すとIDEが予期せぬところでコケるので、タスクマネージャの使用は必須。

リソースいろいろ

Open Tools APIについての役に立ちそうなリソースは以下の通り。

書籍類は両方とも絶版でAmazonでプレミア付き。でも、Delphiコンポーネント設計&開発完全解説はPDF版がある。

ウィザードインターフェース、サービスインターフェース、ノーティファイアインターフェース

ウィザードインターフェースとはIDEに対するアドオンとなるクラスのことで、用途によって以下の4種類がある。(ヘルプより抜粋)

インターフェース型 説明
IOTAFormWizard 通常,新しいユニット,フォーム,その他のファイルを作成する
IOTAMenuWizard へルプメニューに自動的に追加される
IOTAProjectWizard 通常,新しいアプリケーションまたはその他のプロジェクトを作成する
IOTAWizard 他のカテゴリに当てはまらないその他のウィザード

ノーティファイアインターフェースとは、IDEからの通知を受け取るクラスで、ウィザードインターフェースとセットで使用する。(ヘルプより抜粋)

インターフェース 説明
IOTANotifier すべてのノーティファイアの抽象基本クラス
IOTABreakpointNotifier デバッガのブレークポイントの発生または変更
IOTADebuggerNotifier デバッガのプログラムの実行,あるいはブレークポイントの追加または削除
IOTAEditLineNotifier ソースエディタ内の行の移動の追跡
IOTAEditorNotifier ソースファイルの変更または保存,あるいはエディタにおけるファイルの切り替え
IOTAFormNotifier フォームの保存,あるいはフォームまたはフォーム(またはデータモジュール)上の任意のコンポーネントの変更
IOTAIDENotifier プロジェクトのロード,パッケージのインストールなどのグローバル IDE イベント
IOTAMessageNotifier メッセージの表示におけるタブ(メッセージグループ)の追加と削除
IOTAModuleNotifier モジュールの変更,保存,名前の変更
IOTAProcessModNotifier デバッガにおけるプロセスモジュールのロード
IOTAProcessNotifier デバッガにおけるスレッドとプロセスの作成または破棄
IOTAThreadNotifier デバッガにおけるスレッドの状態の変更
IOTAToolsFilterNotifier ツールフィルタの呼び出し

サービスインターフェースとは、アドオンがIDEの機能(エディタ、デバッガなど)に対して何らかの操作を行う場合の仲介役で、これにアクセスすることで、IDEの内部を触ることが出来る。主なものとして以下の物がある。

サービスインターフェース型 説明
INTAServices IDEそのもの
IOTAEditorServices ソースエディタ
IOTAModuleServices IDEが開いているファイル・プロジェクトなど
IOTAMessageServices メッセージウィンドウ
IOTAKeyBindingServices キーバインド
IOTADebuggerServices デバッガ
IOTACodeInsightServices コードインサイト

実際にアドオンを実装する場合はパッケージを作成して、「ウイザードインターフェース」と「ノーティファイアインターフェース」を親に持つサブクラスを定義する。そのサブクラスをIDEに「登録」すれば、サブクラスはIDEのアドオンとなる。*4IDE内部で何らかの処理が行われた場合、「ノーティファイアインターフェース」の特定のメソッドが呼ばれるので、サブクラスに「ノーティファイアインターフェース」の対応するメソッドをオーバーライドしたメソッドを記述すれば、アドオンにおけるIDEからの応答先となる。そこで必要に応じてサービスインターフェースを介してIDE内部の情報にアクセスする。

これらのクラスの定義とインスタンスはToolsAPI.pasで定義してあるので、Delphiならばuses節にToolsAPIを記述、C++Builderならば、ToolsAPI.hppをインクルードする必要がある。最後に、プロジェクトマネージャの[参照の追加]で$(BDS)\lib\win32\release\designide.dcpをプロジェクトに含めておくこと。

*1:ただし、ヘルプからコピペでOK

*2:もしかしたら、おいらの環境だけかも。

*3:DLLでもOKだけど、まだテストしていない。

*4:インスタンスIDEが生成してくれる。