コード エディタでの ToolsAPI サポート
RAD Studio 11.3 より、完全、包括的かつ非常に細やかな Tools API のセットが提供されています。これによりユーザーは、色付け、エディタやその他コンテンツについての検索、コード エディタに対するイベントの取得など、コード エディタをカスタマイズすることができます。
目次
できること
もっともエキサイティングで便利なプラグインは、エディタ内で機能します。 そのため、私たちは革新を促進する包括的で価値のある API を提供することを目指しています。私たちが考えもしなかったことを実行するプラグインを簡単に作成できるようになるでしょう。
これらの API を使用すると、ユーザーは、エディターの行、ガターやテキストの描画のすべての段階で割込むことができ、各ステージの前後で呼び出されるイベントで、IDE に動作を追加したり、それを完全に置き換えたりすることができます(IDE がその段階で通常の描画を行わないようにします)。
エディタ、編集ビューの完全なリストを取得することができ、それをマッピングすることができます。エディタの場合、ユーザーは利用可能な多くの情報でその状態を照会し、また、各行に対してより詳細な情報を照会することもできます。 Paint イベントには完全なコンテキストが含まれています。 これを使用することで、考えられるエディタの描画を行ったり、エディタやそこにあるものについて(たとえそれが描画されていなくても)情報を取得することができます。
主な概念
エディタ バッファ(IOTAEditView.Buffer は IOTAEditBuffer を提供します)は、テキスト/コードが格納される場所です。ビュー(IOTAEditView)は、このバッファのビューであり、エディタ コントロール(エディタを実装する VCL コントロール)によって使用されます。ファイル コンテンツにバッファは 1 つですが、複数のビューによって、ユーザーはそのバッファを編集して、その結果、同じファイルに多数のエディタ ウィンドウを表示させることができます。1 つのエディタ コントロールは、1 つのビューにマップされ、それを使用し、逆も同様です。
エディタ行番号 vs. 論理行番号
行の状態と、この API のその他の領域では、エディタの行番号と論理行番号が区別されます。行が省略されている場合、この違いは重要です。Elided は、折りたたまれたコードを表す IDE の用語です。エディタの画面には多くの行が表示される場合がありますが、折りたたみポイントでは、エディタの行番号と論理行番号が分かれるため、折りたたみポイントが画面の外になります。
論理行は「実際の」行番号です。
エディタ行はエディタ内に表示されるか、エディタがスクロールされた場合に表示されます。
たとえば、(論理行が)10 行のファイルで、4 行目から 7 行目が折り返されているか省略されている場合、論理行は最大 10 行になりますが、エディタ行は最大 7 行になります(省略されたセクションの場合、常に 1 行は存在します)。表示行はエディタの画面に表示される行であり、折り返しのため、バッファ内の行のサブセットになることがあります。したがって、表示されるエディタ行は常に連続していますが、論理行番号にはギャップがあり、折り返しポイントでジャンプすることがあります。
行の行状態において、論理行番号とエディタ行番号を変換でき、どちらの行番号でもクエリをかけることができます。つまり、論理行またはエディタ行ごとに行の状態を取得し、それがどの論理行またはエディタ行を表すかを問い合わせます。
コード エディタ サービス
開始点は INTACodeEditorServices インターフェイスです。このインターフェイスにより、次のことが可能になります:
- エディタのイベントの登録(マウス、スクロール、サイズ変更、ペイントなど)
- エディタ コントロールのビュー、およびビューのエディタ コントロールの検索。バッファは 1 つですが、そのバッファに複数のビューを持つことができ、各エディタ コントロールは 1 つのビューを使用します。
- すべてのエディタ コントロールと、すべての編集ビューの一覧表示
- 最上位のエディタ コントロールの取得(最後に操作したもの)
- エディタ コントロールのエディタの状態の取得。どの行でも、エディタの状態から行の状態を取得することができます。
- エディタに関するさまざまな情報の取得
- プラグイン利用のため、エディタの左余白の一部を予約
- 他のインターフェイスと同様、
BorlandIDEServicesからINTACodeEditorServices へのアクセス - 四角形またはエディタ全体に対して、論理線による、エディタの一部に対する無効化(つまり、再描画発生)
高性能コードエディタの読み取りと書き込み
エディタ バッファからの読み込み
IOTAEditReader インターフェイスを使用して、エディタ バッファから読み込みます。この API はとても低層のもので、パフォーマンスに優れています。エディタのコンテンツに直接アクセスでき、コードを解析する必要がある場合は、ポインタ ベースの文字列解析を使用して解析すると、文字列の割り当てやコピーをまったく行わずに解析できます。
一連の行のエディタ バッファの内容を取得するには、GetLineData を呼び出し、最初の行番号、最後の行番号、コールバック、および、好きなデータを表すことができる任意のポインタを渡します。このポインタは、変更されずにコールバックに渡されます。これは、オブジェクト インスタンスを参照し、コールバック内のオブジェクト指向メソッド呼び出しに変換するために使用されます。
コールバックは、行番号、渡された変更されていないポインタ、および行情報へのポインタを取得します。この行情報の構造体には、行の長さ、行末の種類(CRLF、CR のみ、LF のみ、などを表す列挙型)、および行文字列へのポインタが含まれます。
行の文字列は、UTF8 形式で null 終端ではありません。行末バイトの追加はありません。これは、行の内容のみへのポインタであり、エディタ バッファのメモリ内に直接存在します。
IOTAEditReader インターフェイスでは、次のことが可能です:
- バッファ内の行数は
LinesInBufferプロパティで取得します:
- 単一行またはある範囲の行の行データを、次のプロシージャを使用して取得します:
procedure GetLineData(AFirstLine: Integer; ARange; Integer;
ACallBack: TOTALineDataCallback; AUserData: Pointer);
- 行データの取得には、次のようなコールバックが必要です:
TOTALineDataCallback = procedure(ALine: Longint; ALineInfo:
POTALineInfo; AUserData: Pointer)
また、(以前の API では必要だった)全体のバッファをストリーミングし解析するオーバヘッドなしで、行カウントなどを実現できます。同様に、バイト内のバッファの全体サイズの計算も、これまたストリーミングの必要なく行うことができます。
エディタ バッファへの書き込み
以下は、エディタ バッファへの書き込みのためのさまざまなメソッドです:
IOTAEditWriter: 位置を指定してからコピー、挿入、削除などの基本操作を実行するストリームのような API を提供するインターフェイス。 このメソッドでは、実装されるオペレーションに対してエディタ テキストをストリーミングする必要があります。Insert(): UTF8String を取るオーバーロード。 このメソッドは、より行番号指向です。
よりパフォーマンスの高いメソッド:
InsertBlankLine: 特定の行番号に挿入。InsertLine: 特定の行番号に挿入。 これは、UTF8 コンテンツへのポインタまたは UTF8String を取り、そのコンテンツを新しい行へ挿入します。DeleteLine: 特定の行番号を削除。ReplaceLine: 特定の行番号を、UTF8 コンテンツへのポインタまたは UTF8String と。
IOTAEditPosition を介して利用できる書き込みの基本要素は他にもあり、これは、人間がエディタを操作する方法により近い基本要素を提供します。これらもまた十分高性能であり、IOTAEditWriter の代替手段となります。コード エディタのイベント
INTACodeEditorEvents 通知インターフェイスのインスタンスを、AddEditorEventsNotifier を使用して登録します。
このインターフェイスは、さまざまなイベントの通知を受けられるようにします。以下はその例です:
ウィンドウ イベント
次の API では、何かがエディタ画面上に表示するべきかどうかをチェックすることができます。 エディタの TWinControl の Width プロパティおよび Height プロパティを使用することで、新しいエディタのサイズを問い合わせることができます。これは、通常のビジュアル コンポーネントと同様です。
- EditorResized でエディタをサイズ変更します。
- EditorScrolled でエディタをスクロールします。
これらのイベントは、cevWindowEvents が AllowedEvents で返されたときのみ呼び出されます。
マウス イベント
マウスのイベントでは、ユーザーは、コード エディタ内でやり取り可能な要素を実装することができます。 マウス イベントには次のものがあります:
これらのイベントは、cevMouseEvents が AllowedEvents で返されたときのみ呼び出されます。
状態変更イベント
状態変更イベントは、行が省略または省略解除されたときに、その行の場所で発生します。
最適化イベント
次は、ユーザーがコード エディタで実装できる最適化イベントです。
- AllowedEvents: プラグインが関心のあるイベントを返します。
- AllowedGutterStages と AllowedLineStages: ペイント時にプラグインを呼び出す、ガター、行ペイント、テキスト ペイントのステージを指定するための同様のマスク。
パフォーマンスへの影響を避けるには、これらのメソッドの結果を使用して、プラグインが必要なイベントに対してのみ呼び出されるようにします。
ペイント イベント
ペイントには複数のメソッドがあります。 行、行内のテキスト、エディタのガターをペイントするメソッドがあります。 ペイントは行ベースで行われ、内部エディタ モデルに従います。このモデルでは、行に関連づけられていないものをペイントするモデルがありませんが、各行内に四角形をペイントすることで対応できます。
これら 3 つ(ガター、行、テキスト)それぞれについて、メソッドは....
- 複数回(ペイント ステージ毎に 1 回、およびそのステージの前と後に)呼び出されます。
- ペイント ステージには、開始と終了(つまり、すべてのペイントの前とすべてのペイントの後)、行の背景、一般的なマーク/マークアップ、強調表示されたペア、右余白、折り畳まれた行のインジケーターが含まれます。
- コンテキストが渡されます。これにより、描画四角形、キャンバス、行番号、論理行番号、ファイル名、コントロール、編集ビューにアクセスでき、行の状態とエディタの状態を問い合わせることができるようになります。
- IDE の特定のステージのデフォルトの処理によって、このステージのペイントが完全に処理されないようにすることができます。 複数のプラグインがペイントしている場合は、他のプラグインもペイントしないようにすることはできません。
ペイント メソッド
INTACodeEditorEvents インターフェイスには次のペイント メソッドが含まれています:
- BeginPaint と EndPaint: これらのメソッドは、エディタ全体のペイントの前後に呼び出されます。 BeginPaint は、エディタ全体の再描画を強制します。
- これらのメソッドは、
cevBeginEndPaintEventsがAllowedEventsで返されたときにのみ呼び出されます。
- これらのメソッドは、
- PaintGutter: このメソッドを使用するとエディタ ガターをペイントできます。
- このメソッドは、
cevPaintGutterEventsがAllowedEventsで返されたときにのみ呼び出されます。
- このメソッドは、
- PaintLine: これは、行をペイントする汎用メソッドです。 このメソッドの一般的な用途は、テキストが描画された後に、背景ペイントの変更や、テキストが描画された後にマークアップを追加することです。
- このメソッドは、
cevPaintLineEventsがAllowedEventsで返されたときにのみ呼び出されます。
- このメソッドは、
- PaintText: このメソッドは、エディタ行でコード(つまり、テキスト)のコンテンツをペイントする際に呼び出されます。 論理的テキスト セグメント(各シンボルやコメントなど)についてそれぞれ、このメソッドを呼び出します。 パラメータは、ペイントされる列番号、テキストそのものについて、構文の強調表示情報、そしてテキストが選択されているかどうか、などについての情報を提供します。 なぜなら、すべてのメソッドと同様、これは、IDE のペイントを回避することができるため、IDE のコード整形の変更に使用される可能性があるからです。
- このメソッドは、
cevPaintTextEventsがAllowedEventsで返されたときにのみ呼び出されます。
- このメソッドは、
イベントとペイント ステージの登録
これらのメソッドは細かい範囲で使用できるため(多くのペイントのステージで、IDE の処理の前後双方で、3 つの異なるペイント領域に対して)、ペイント時にパフォーマンスに影響を与える可能性があります。 この問題は、応答してメソッドが呼び出される可能性のあるイベントのサブセットを、詳細に登録することで対応することができます。 AllowedEvents を実装し、どのイベントが呼び出されるかを返すようにします。
その後、呼び出されるイベントについてはその多くが、ペイントのプロセスにおいてメソッドが呼び出される複数のステージを持っています。 繰り返しになりますが、最適化のために、呼び出しを発生させたいステージを指定する必要があります。 AllowedGutterStages を実装し、エディタ ガターの描画について通知を受けたいペイント ステージを、AllowedLineStages は、行の描画について通知を受けたいペイント ステージを返すようにします。 PaintText には、ステージが複数ありません。
エディタの状態
INTACodeEditorState インターフェイスを使用することによりユーザーは、特定のエディタに何が表示されるか、情報を入手することができます。 これには次が含まれています:
- エディタの四角形。
- ガターのサイズ。
- コードが描画される左側の端。
- コード エディタのコンポーネント(TWinControl など)と使用されるエディタ ビュー
- 上下の表示行
- 左右の表示列(水平にスクロールするとき)
- 最大表示行の幅を文字数で。
- ピクセルのポイントを、文字の位置(インデックスと行)に変換。
- 文字の位置(インデックスと行)を文字の境界四角形に変換。
- 特定の行が表示されているかの問い合わせ。
- 非表示行についての情報の問い合わせ。
- 特定の行についての状態の取得。
INTACodeEditorServices から問い合わせるか、ペイント メソッド内の Context パラメータを介して、エディタの状態を取得することができます。 これにより、エディタと行の両方の状態、およびその他のペイント コンテキストを取得することができます。 エディタの状態は、クエリがかけられたときに作成されます。
行の状態
INTACodeEditorLineState インターフェイスで、ユーザーは特定の行について情報を問い合わせることができます。 INTACodeEditorState インターフェイスで行の状態を取得します。 どの行についても、次のことを問い合わせることができます:
- エディタの行番号および論理行番号。
- 省略された行の場合: 省略された行のセクションと、その省略されたセクションの開始範囲と終了範囲を表す表示行。
- さまざまな長方形: エディタの全幅におよぶ行全体の長方形、ガター長方形、ガター マークアップ(行番号や折りたたみ +/- 記号が描画される場所など)長方形、コード領域長方形、テキストを囲む長方形。
- 行のテキストと、その行に表示されるテキストのサブセット。
INTACodeEditorLineState には State プロパティが追加され、次のことが分かるようになりました:
eleLineHighlight: 行が強調表示されている。eleErrorLine: 行はエラーを含んでいる。eleExecution: 行は現在実行中。eleBreakpoint: 行はブレークポイントを含んでいる。eleInvalidBreakpoint: 行は不正なブレークポイントを含んでいる。eleDisabledBreakpoint: 行は無効なブレークポイントを含んでいる。eleCompiled: 行はコンパイル済みでブレークポイントを設定できる。
特定のエディタの INTACodeEditorState から問い合わせるか、ペイント メソッド内の Context パラメータを介して、行の状態を取得することができます。 これにより、エディタと行の両方の状態、およびその他のペイント コンテキストを取得することができます。 行の状態は、クエリがかけられたときに作成されます。
INTACodeEditorLineState には 列でインデックス付けされた CellState プロパティが追加されており、特定のセルが次のいずれかの状態であるかどうかを知ることができます。
eceSelected: セルは現在選択されているeceHotLink: セルはアクティブなホットリンクを含んでいるeceHotLinkable: セルはホットリンクをサポートしているeceSyncEditBackground: セルは同期編集グループの背景内にあるeceSyncEditSearch: セルは検索されている同期編集グループの一部であるeceSyncEditMatch: セルは一致している項目を持つ同期編集グループの一部であるeceSearchMatch: セルは検索クエリと一致するeceExtraMatch: セルは検索クエリと 2 番目に一致するeceBraceMatch: セルは一致する中括弧または角括弧eceHint: セルはヒントを含んでいるeceWarning: セルは警告メッセージを含んでいるeceError: セルはエラー メッセージを含んでいるeceDisabledCode: セルは無効なコードを含んでいるeceFoldBox: セルは折り畳みボックス
エディタのコンテキスト メニュー
以下に一覧されている cEdMenuCat 定数は、エディタのローカル メニューを作成するために使用される、さまざなアクション リストのカテゴリを定義しています。 INTAEditorLocalMenu を使用すると、エディタ ローカル メニューを追加し、これらの定数を使用して、新しいアクション リストをどこに追加するかを制御できます。
以下は、各メニュー カテゴリでのアクションのリストです:
cEdMenuCatIdentifier: 宣言を検索。cEdMenuCatBreakPoint: 有効化、ブレークポイント プロパティ。cEdMenuCatDebugDebug: カーソルまで実行。cEdMenuCatBase: ソース/ヘッダー ファイルを開く、カーソルでファイルを開く、カーソルでシンボルを参照、トピック検索、次のバッファ表示、前のバッファ表示、次の変更、前の変更、次の未保存の変更、前の未保存の変更cEdMenuCatModule: ソース/ヘッダー ファイルを開く、メッセージを表示、エクスプローラで表示cEdMenuCatClipboard: 切り取り、コピー、貼り付けcEdMenuCatBookMarks: すべてのブックマーク項目に移動、および切り替えcEdMenuCatDebug: カーソルまでデバッグおよび実行cEdMenuCatDebug: 表示、メッセージ、読み取り専用、フォームとして表示cEdMenuCatView: フォームとして表示cEdMenuCatElide: 折りたたみ、ドキュメントのコメント、メソッド、最短、入れ子、領域、名前空間、型、展開、すべてcEdMenuCatVersionControl: すべてのバージョンのプラグ メニューの項目cEdMenuCatRefactor: 検索、リファレンスの検索、ローカル リファレンスの検索、宣言シンボルの検索、リファクタリングcEdMenuCatFormat: 囲む、プロトタイプの同期cEdMenuCatRepository: リポジトリに追加cEdMenuCatLast: メッセージの表示、読み取り専用、エディタのオプション
コード エディタのオプション
INTACodeEditorOptions インターフェイスにより、ユーザーは、色、表示可能なガター、フォント、サイズなどについての情報を問い合わせることができます。
エディタ ガターの空白
エディタ ガターは現在、行ごとの情報を描画するのに最適な場所です。 RAD Studio は、行番号、行の折り返しマーカー、行の変更表示、ブレークポイント、ブックマークなどにこれを使用します。 エディタ ガターの一部を予約することで、プラグインのガターを広くします。 これは、RequestGutterColumn でサイズをピクセル単位で指定して行います。 これは、ブレークポイントまたは行番号が描画される前または後(左または右)に配置できます。
GetGutterColumnRect メソッドにより、ユーザーは、特定の登録済みガター領域の四角形を取得することができます。 または、GetGutterColumnRect メソッドを使用して、エディタ ガター内の登録済み領域の四角形を取得することができます。
その他の ToolsAPI の変更
- 11.3 以降、エディタ ペイント用の次の ToolsAPI が廃止予定となりました:
INTAEditViewModifier.BeginPaintINTAEditViewModifier.EndPaintINTAEditViewModifier.PaintLine
新しい API のセットを使用することをお勧めします。