Azukiの使い方

はじめに

この文書ではAzukiの使い方を要点を絞って説明しています。「これも説明して欲しい」といった要望がありましたら、ぜひsgry@users.sourceforge.jpまで連絡してください。

セットアップ

Azukiの運用

Azukiの使用方法として想定されているのは、Azukiを使うアプリケーション(以下「アプリ」)の実行ファイルと同じフォルダにAzukiのDLLを配置して使う方法です。この場合は、アプリをビルドする時にAzukiのDLLを参照(reference)する形になります。

Visual Studioでの使用方法

Visual Studioでの使用方法を説明します(ここではVisual Studio 2005を例としますが、Visual Studio 2008でも操作は同じです)。まずAzukiControlをVisual Studioのビジュアルデザイナで使えるようにする手順を次に示します。

  1. Azuki.dllとAzuki.xmlをどこかのフォルダに配置します。
    なお、配置先は作成するプロジェクトとは無関係なフォルダが良いです(たとえばC:\lib\Azukiなど)。
  2. Visual Studioを起動し、「Windows フォーム アプリケーション」のプロジェクトを新規作成(あるいは既存のプロジェクトをオープン)します。
  3. screenshot

    アプリケーションのGUIをデザインするビジュアルデザイナーの画面を開き、ツールボックスの「全般」タブを右クリックして「アイテムの選択」を選択するか、
    「ツール」メニューの「ツールボックス アイテムの選択」を選択します。すると、「ツールボックス アイテムの選択」ダイアログが表示されます。

  4. screenshot

    「ツールボックス アイテムの選択」ダイアログの「.NET Framework コンポーネント」タブを選択し、「参照」ボタンを押してAzukiのDLLを選択します。
    選択したら、OKボタンを押してダイアログを閉じます。すると、デザイナの「全般」タブにAzukiControlが追加されます。

ツールボックスにAzukiControlが追加されたら、あとは標準の.NETコントロールと同じです。ドラッグ&ドロップでアプリのフォームへAzukiControlを追加して、プロパティを設定していってください。

screenshot

なおAzukiControlをデザイナで追加すると、自動的にプロジェクトの設定が更新されてAzukiのDLLが参照に追加されます。また参照設定が追加されることで、アプリのビルド時にVisual Studioが自動的にAzukiのDLLをアプリのフォルダにコピーするようになります。これが、一番おすすめの使用方法です。

※AzukiのDLLは毎回ビルド時に必要です。一度コピーすれば用済みというわけではありませんので、手順1で配置したフォルダからDLLを削除しないように注意してください。

※Windows CEやWindows Mobile用のプロジェクトで使う場合は、Windows フォーム アプリケーションのかわりに「SmartDevice プロジェクト」を新規作成、またはオープンします。また、DLLへの参照を追加する場合にAzuki.dllではなくAzukiCompact.dllを選択してください。その後は、ほぼ同じ手順で使えるようになります。

コマンドラインツールでの使用方法

コマンドラインツールでの使用方法を説明します。まずコマンドラインツールに限らず.NETの世界においては、プログラムhogeから別のDLLで定義されたクラスを使うにはそのDLLを「参照」に加えてコンパイルする必要があります。Azukiも、やはり「参照」に加えてコンパイルすることでプログラムから使えるようになります。

外部DLLを参照に加える方法は、コマンドラインツールによって少しずつ違っています。そのためここではcsc/vbc、msbuild、NAntを使う場合の簡単な説明だけをしておきます。詳細は、それぞれのコマンドラインツールのマニュアルやヘルプをご参照ください。

cscまたはvbcを使う場合

cscはMicrosoft製のC#コンパイラ、vbcはMicrosoft製のVisualBasic.NETコンパイラです。これらの場合は-referenceオプション(省略形の-rでも可)を使ってAzukiのDLLパスを指定すれば参照に加えることができます。次に例を示します。

csc -nologo -lib:"C:\lib\Azuki-1.3.3" -r:Azuki.dll  *.cs
msbuild を使う場合

msbuild は Microsoft 製のビルドツールです。 多くの場合は Visual Studio が生成した .csproj ファイルや .sln ファイルを直接 msbuild の対象として使うと思いますので、 「2.2 Visual Studio での使用方法」 で説明したように Visual Studio 上で参照を追加してあれば、 これといってコマンド上で何か特別に操作する必要はありません。

なお、msbuild 用に .csproj ファイルなどを直接編集する場合は Project の子要素 ItemGroup に Reference 要素を追加して Azuki.dll を参照に加えます。 次に例を示します。

<Project ...>
    ...
    <ItemGroup>
        <Reference Include="Azuki.dll" />
        ...
    </ItemGroup>
    ...
</Project>
NAnt を使う場合

NAnt はオープンソースの .NET 環境用ビルドツールです。 NAnt の場合は csc タスクや vbc タスクの子要素として references 要素を定義し、 そこで Azuki の DLL を指定すれば参照に加えることができます。 次に例を示します。

<csc ...>
    <references>
        <lib>
            <include name="..\package"/>
        </lib>
        <include name="Azuki.dll"/>
    </references>
</csc>

全般

重要なクラス

Azuki を使うプログラマがアクセスするのは主にユーザインタフェース部(AzukiControl クラス)とドキュメント部(Document クラス)です。 ユーザインタフェース部はユーザインタフェース機能を担当します。 ドキュメント部は編集内容に関する機能を担当します。 なお、便利のため、 ユーザインタフェース部からは主な表示関連機能やドキュメント関連機能にもアクセスできます。

テキストの範囲

Azuki の多くの操作ではテキストの「範囲」をパラメータとして扱うことになります。 Azuki の中ではテキストの範囲を「以上未満」で表現します。 たとえば Azuki に foobar という文字列が設定されている場合に barの範囲は「3 以上 6 未満」となります。

API ドキュメントなどでは以上未満の範囲を数学の記法で書き表している箇所があります。 具体的には、たとえば 3 以上 6 未満を [3, 6) と書いています。 また Azuki のソースコードでは多くの場面で範囲の開始位置を begin、 終了位置を end という名前で呼んでいます。 また、処理上のポイントとして次の 2 点を挙げておきます。

  • 範囲の長さは end - begin
  • ドキュメント全体を指す範囲は [0, doc.Length) (Documentオブジェクト型の変数docがある場合)

ユーザインタフェース部

ユーザインタフェース部 (UI部) は、ユーザが直接アクセスする部分です。 現在、Windows および Windows Mobile 用の UI 部として Sgry. Azuki. Windows. AzukiControl クラスが用意されています。

UI 部の主な役割は、 環境に依存した GUI 部品として Azuki の機能をユーザにアクセス可能にすることです。 現在唯一の UI 部である AzukiControl クラスは System. Windows. Forms. Control クラスを継承し、 標準的な GUI 部品として要求される機能を提供します。 またキーボードショートカットなどのユーザ入力に応じたアクションを起動する機能も担当します。 さらに UI 部からは、 表示部のほぼ全機能へアクセス可能となっています。 次に UI 部が担当する機能を記します。

  • GUI 機能(表示位置やサイズの操作など)
  • キーボードショートカット
  • 上書きモード
  • 表示部の機能(の一部)
UI 部が扱うドキュメント

UI 部が扱っている(ユーザに対して表示、操作可能にしている) ドキュメントへは Document プロパティでアクセス可能です。 現在編集中のドキュメントを細かく操作したい場合はこのプロパティから ドキュメントクラスを取得してください。 書類クラスについては該当章を参照してください。

Document プロパティに別のドキュメントオブジェクトを設定すると UI 部が扱うドキュメントを変更できます。 この操作を行うと、 UI 部を複数作らずに複数のドキュメントを扱えるようになります。

色分け設定

Azuki はキーワードや文字列など、文字種を分析して色分け表示する機能があります。 各文字種が表示される際の色は ColorScheme プロパティで設定できます。 なお標準の色設定は ColorScheme.Default プロパティで取得できます。

レンダリング方法 – 折り返し表示など

テキストのレンダリングエンジンは ViewType プロパティでアクセスできます。 このプロパティの型は ViewType 列挙子で、 ViewType.Proportional か ViewType.WrappedProportional のどちらかが設定できます。 前者がプロポーショナルフォントでのレンダリングエンジンで、 後者はプロポーショナルでさらに指定幅で折り返し表示可能なレンダリングエンジンです。

WrappedProportional を選択時、折り返し幅は ViewWidth プロパティで決定します。 もし「画面端で折り返し」したい場合は、 UI 部のサイズが変更するたびに ViewWidth を新しい UI 部の幅に再設定してください。 たとえば AzukiControl の変数を azuki として次のコードで実現できます (ただし、画面端折り返しをやめたくなった時に困るコードですが)。

azuki.Resize += delegate {
    azuki.ViewWidth = azuki.ClientSize.Width;
};

日本語テキストエディタに Azuki を組み込む場合、 文字数で折り返し幅を設定したいケースも多いと思います。 その場合は水平ルーラーの単位幅(IView.HRulerUnitWidth プロパティ)に文字数をかけた値を折り返し幅として指定してください。

キーボードショートカット

キーボードショートカットは SetKeyBind メソッドで設定します。 キーにアクションを関連づけるには、 SetKeyBind にキーコードと実行するアクションを定義したメソッド (正確にはデリゲートオブジェクト) を渡します。 なお Azuki が内蔵している標準アクションは Actions クラスのメンバとして定義されています。 たとえば Ctrl+E に「コピー」を割り当てたい場合は次のようなコードになります。

azuki.SetKeyBind( Keys.E | Keys.Control, Actions.Copy );

なおアクションは ActionProc 型であれば何でも良く、 ユーザが定義したメソッドでも設定できます。 また Azuki が管理しているショートカットキーとアクションの関係は一対一であり、 同じキーに対して複数のアクションを登録することはできません。 もし、あるキーにアクションが何も関連づけられていない状態にしたい場合は、 そのキーのアクションとして null を設定してください。

以上の内容は C# を使う場合の話であり、 Visual Basic.NET を使う場合は少しだけ話が違ってきます。 VB.NET を使う場合、アクションを関連づける場合にはメソッド名だけではなくその前に AddressOf を付けて下さい。 また、キーにアクションが関連づけられていない状態にする場合は Nothing を設定してください。

標準のショートカットキー設定を次に示します。 なお表中で [FF] と書いてある部分は通常の .NET Framework 用 Azuki で使えるもので、 [CF] と書いてある部分は .NET Compact Framework 用 Azuki で使えるものです。

方向キー関係
単独 Shift 同時押し Ctrl 同時押し Ctrl + Shift 同時押し Alt 同時押し
Left 前の文字へ移動 前の文字まで選択 前の単語の開始へ移動 前の単語の開始まで選択 箱形選択範囲を左に広げる
Right 次の文字へ移動 次の文字まで選択 次の単語の開始へ移動 次の単語の開始まで選択 箱形選択範囲を右に広げる
Up 1行上へ移動 1行上まで選択 [FF] 1行上へスクロール /
[CF] 1ページ前まで移動
[CF] 1ページ前まで選択 箱形選択範囲を上に広げる
Down 1行下へ移動 1行下まで選択 [FF] 1行下へスクロール /
[CF] 1ページ後へ移動
[CF] 1ページ後まで選択 箱形選択範囲を下に広げる
その他のキー
キー アクション
Ctrl + A すべて選択
Ctrl + Z 元に戻す
Ctrl + Shift + Z やりなおす
Ctrl + Y やりなおす
Ctrl + X 切り取り
Ctrl + C コピー
Ctrl + V 貼り付け
Tab (選択中) ブロック・インデント
Shift + Tab (選択中) ブロック・アンインデント
Ctrl + [ キャレットの位置にあるカッコのペアになっているカッコへ移動
Ctrl + ] キャレットの位置にあるカッコのペアになっているカッコへ移動
Ctrl + B 箱形選択モードに入る

ドキュメント部

概要

ドキュメント部は Azuki が編集しているテキストの内容や状態などを担当する部分です。 Document クラスがドキュメント部となります。 編集対象の Document は AzukiControl. Document プロパティで取得・設定できます。 また、便宜的に AzukiControl. Text プロパティで編集中テキストのコピーを String オブジェクトとして取得できます。 Document クラスは次の機能を担当しています。

  • 編集中テキストの内容とその操作
  • 論理行の管理
  • 選択範囲の管理
  • 編集履歴の管理
  • 読み取り専用モードの管理

なお Document クラスが扱う行は「論理行」である点に注意してください。 論理行とは改行コードで区切られた範囲のことです。 したがって画面上でテキストが折り返し表示された結果、 画面上で行と見えるモノは、論理行ではありません。 折り返しによってできる行である「スクリーン行」を扱いたい場合は UI 部の行関連メソッドを使ってください。

選択、アンカー、キャレット

テキストを選択するには、 SetSelection メソッドを使って 「アンカー」と「キャレット(カーソル)」で選択対象を挟みます。 アンカーは、選択を開始した位置です。 キャレットは、カーソルのことです (マウスカーソルとはっきり区別するためにキャレットという用語を使っています)。 たとえば [4, 8) の範囲を選択する場合は SetSelection( 4, 8 ) あるいは SetSelection( 8, 4 ) で選択できます。 これらの方法の違いは、前者ではキャレットが選択の末尾に、 後者では選択の先頭にくる点です。

Azuki のキャレット移動は選択範囲の移動です。 つまり foobar の a から b にキャレットを戻すことは、 選択範囲を [4, 4) から [3, 3) に変更することです。 そのため、ユーザがキャレットを移動した時には SelectionChanged イベントが発行されます。

内容の変更

Azuki では、あらゆる内容の変更を「置換」で行います。 テキストの挿入は、空の範囲を置換する形で行います。 たとえば文書の末尾に foo を挿入する(追加する)コードは次のようになります。

doc.Replace( "foo", doc.Length, doc.Length ); // 挿入

テキストの削除は、削除する範囲を空文字に置換する形で行います。 たとえば foobar と入力されたドキュメントから ob を削除するコードは次のようになります。

doc.Replace( "", 2, 4 ); // 削除
検索

Document クラスにはテキストを検索する機能があります。 検索は FindNext メソッドと FindPrev メソッドで実行できます。 これらのメソッドにはいくつかオーバーロードがあり、 大文字小文字の区別をしない単純な文字列検索や正規表現検索などが可能です。

単語の扱い(禁則処理を含む)

Azuki ではカーソルの移動、選択、行の折り返し表示 (禁則処理を含むワードラップ) といった処理を単語単位で実行できます。 そのとき、単語をどのように認識するかは Document.WordProc プロパティに設定されたワードプロセッサーが決定します。

ワードプロセッサーは IWordProc インタフェースを実装したオブジェクトです。 Azuki が内蔵しているワードプロセッサーには DefaultWordProc クラス があり、これで禁則処理を含む日本語の単語検出処理を行っています。 また、禁則処理は一般的に細かくカスタマイズされることが多いため、 DefaultWordProc では行頭禁止文字などを細かく指定できるようになっています。 一般的な日本語テキストエディタのニーズは DefaultWordProc で満たすと思いますが、 単語区切りの検出処理が好みに合わない(Ctrl+左右キーでの動きが好みでない)、 日本語でも英語でもない言語に合わせた単語処理を行いたいといった場合は DefaultWordProc を継承したクラスで各メソッドをオーバーライドするか、 IWordProc を実装したワードプロセッサを独自に実装してください。

表示部

表示部は Azuki の「見た目」に関する処理を担当します。 Azuki の表示部は次の機能を担当します。

  • 描画処理(折り返し表示処理を含む)
  • スクリーン行の管理
  • スクロール処理

なお、表示部は基本的に UI 部からアクセスされるものであり、 プログラマが直接アクセスすることはほとんどありません。 独自のアクションを定義する際にアクセスするくらいです。

Azuki のシンタックスハイライト

概要

Azuki では編集中のドキュメントの種類ごとにキーワードに色を付けて表示する 「シンタックスハイライト機能」を提供しています。

Azuki のシンタックスハイライト機能は二段構造になっています。 まず、ドキュメントの文法などをもとに各文字の種類 (CharClass) を判別するハイライターというオブジェクトを UI 部に設定します。 続いて、UI 部の ColorScheme プロパティで 「どの文字種(CharClass)を何色で表示するか」 を定義しておきます。 すると Azuki は、各文字を描画するときにその文字種用に設定された色を ColorScheme から取得し、その色で描画します。

これが Azuki のシンタックスハイライトの概要です。

内蔵ハイライター

Azuki は数種類の文法用にハイライターを内蔵しています。 1.5 では C/C++、C#、Java、Ruby、TeX、XML 用のハイライターが Highlighter.Highlighters クラスから取得できます。 これらの文法のシンタックスハイライトを行いたい場合はこれらのハイライターを利用してください。 次に XML 用の内蔵ハイライターを設定するサンプルコードを示します。

azukiControl.Highlighter = Highlighters.Xml;
KeywordHighlighter

Azuki は単純なキーワードマッチングでハイライトを実行する Sgry.Highlighter.KeywordHighlighter クラスを提供しています。 キーワードをハイライトできれば問題ない場合には、 これを直接使うことができますし、 これを派生した独自のハイライターを作ることもできます。 KeywordHighlighter クラスがサポートする「キーワードグループ」、 「囲い」、「行コメント」の3種類の文字列パターンについて、以下で説明します。

キーワードグループについて説明します。 AddKeywordSet メソッドでは一連のキーワードのグループを登録でき、 またそれらをどんなキーワードなのかを CharClass 型の値から選んで設定できます。 たとえば “if”、 “else” といった文字列を CharClass.Keyword として設定する一方で、 “#define”、”#undef” といった文字列を CharClass.PreprocessorMacro として登録すれば、 これらを区別してハイライト可能です。

次に、「囲い」のハイライトについて説明します。 多くの言語では二重引用符で文字列を囲うと文字列のリテラルとして扱います。 このように特定の文字列パターンから文字列パターンまでをハイライトする場合、 AddEnclosure メソッドを使って開始の文字列パターンと終了の文字列パターンを登録すると、 「囲い」としてハイライトされるようになります。

続いて、行コメントのハイライトについて説明します。 多くの言語では行の中で特定の文字列パターンが出てくると、 それ以降(行末まで)をコメントと扱うような記法が導入されています。 こうした行コメントをハイライトする場合、 AddLineHighlight メソッドを使って行コメントの開始となる文字列パターンを登録します。

最後に、KeywordHighlighter クラスを使う上での注意点を2点、補足します。 1点目は、AddKeywordSet メソッドで登録するキーワードをアルファベット順に並べることです。 たとえば “if” と “in” と “int” をキーワードに登録する場合は “if”、”in”、”int” の順にします。 順番に並んでいないキーワード群を登録すると AddKeywordSet メソッドは ArgumentException を投げます。 その例外オブジェクトには 「どのキーワードとどのキーワードの並び順が逆転しているのか」 をメッセージとして埋め込んでありますので、 例外が発生してしまった場合は参考にしてください。 2点目は、AddEnclosure で登録した 「囲い」 は登録順にマッチングされていくことです。 これを意識するのは 「ある囲いの開始パターンが他の囲いの開始パターンと一致している場合」で、 たとえば “/*” で始まる囲いと “/**” で始まる囲いを区別して登録する場合が該当します。 この場合は、先に “/*” に登録すると “/**” という文字列パターンに “/*” がマッチングしてしまうため、 “/**” の囲いではなく “/*” の囲いとしてハイライトされてしまいます。 囲いのハイライトがうまく行かない場合、 このようなパターンになっていないか確認してみてください。

最後に C# の文法でハイライトを行うハイライターを KeywordHighlighter で作成するサンプルを示します。

// キーワードを定義
keywordHighlighter.AddKeywordSet( new string[] {
	"abstract", "as", "base", "bool",
	"break", "byte", "case", "catch",
	"char", "checked", "class", "const",
	"continue", "decimal", "default", "delegate",
	"do", "double", "else", "enum", "event",
	"explicit", "extern", "false", "finally",
	"fixed", "float", "for", "foreach",
	"goto", "if", "implicit", "in",
	"int", "interface", "internal",
	"is", "lock", "long", "namespace",
	"new", "null", "object", "operator",
	"out", "override", "params", "private",
	"protected", "public", "readonly", "ref",
	"return", "sbyte", "sealed", "short",
	"sizeof", "stackalloc", "static", "string",
	"struct", "switch", "this", "throw",
	"true", "try", "typeof", "uint",
	"ulong", "unchecked", "unsafe", "ushort",
	"using", "virtual", "void", "volatile", "while"
}, CharClass.Keyword );

// 文脈依存キーワードを定義
keywordHighlighter.AddKeywordSet( new string[] {
	"add", "from", "get", ""global", "group", "into",
	"join", "let", "orderby", "partial"", "remove",
	"select", "set"", "value", "var", "where", "yield"
}, CharClass.Keyword2 );

// プリプロセッサのキーワードを定義
keywordHighlighter.AddKeywordSet( new string[] {
	"#define", ""#elif", "#else", "#endif",
	"#endregion", "#error", "#if", "#line",
	"#region", "#undef", "#warning"
}, CharClass.Macro );

// 囲いを定義
keywordHighlighter.AddEnclosure( "'",   "'",  CharClass.String,     false, '\\' );
keywordHighlighter.AddEnclosure( "@\"", "\"", CharClass.String,     true, '\"' );
keywordHighlighter.AddEnclosure( "\"",  "\"", CharClass.String,     false, '\\' );
keywordHighlighter.AddEnclosure( "/**", "*/", CharClass.DocComment, true );
keywordHighlighter.AddEnclosure( "/*",  "*/", CharClass.Comment,    true );

// 行コメントを定義
keywordHighlighter.AddLineHighlight( "///", CharClass.DocComment );
keywordHighlighter.AddLineHighlight( "//",  CharClass.Comment );

マーキング機能

(長くなったので別ページにしました。)
→ マーキング機能について

Tips

OpenType フォントの利用について

OpenType フォントを使う場合は System.Drawing.Font クラスではなく Sgry.Azuki.FontInfo クラスを使ってください (たとえば AzukiControl.Font プロパティではなく AzukiControl.FontInfo)。 というのも System.Drawing.Font クラスは一部の OpenType フォントを扱えません。 そのため正しくフォント名を指定してもそのフォントを利用できなくなることがあります。