Emacsは、アラビア語、ペルシア語、ヘブライ語など、表示時の水平方向の自然な順序が右から左となる文字体系で書かれたテキストの編集をサポートしています。しかし、これらの文字体系に埋め込まれた数字やラテン文字は、依然として左から右に表示されます。また、それ以外の部分がラテン文字である文書の中に、アラビア語やヘブライ語のテキストが一部埋め込まれていることも珍しくありません。例えば、プログラムのソースファイル内のコメントや文字列などが挙げられます。こうした理由から、これらの文字体系を用いたテキストは実際には双方向であり、左から右へ書かれる文字と右から左へ書かれる文字が混在しています。
この節では、双方向テキストを編集するために Emacs が提供する機能やオプションについて説明します。
Emacsは、右から左へ書かれるテキストや双方向テキストを、いわゆる論理(または読み順)で格納します。つまり、最初に読み取った文字のバッファまたは文字列上の位置が、次の文字の位置よりも先になります。双方向テキストを表示順に並べ替える処理は、表示時に行われます。その結果、文字の位置は、画面上の位置に応じて単調に増加しなくなります。Emacsは、表示用の双方向テキストの並べ替えに、Unicode Standard Annex #9で記述されているUnicode Bidirectional Algorithm (UBA)を実装しています。UBAと異なる点は、テキストの方向がベースとなる段落の方向と逆である場合(例えば、右から左へ書かれる段落に長い英文の行が現れる場合など)の、継続行の表示方法のみです。
バッファローカル変数 bidi-display-reordering
は、バッファ内のテキストを表示時に並べ替えるかどうかを制御します。その値が nil
以外の場合、Emacs は右から左への書字方向を持つ文字を表示時に並べ替えます。デフォルト値は t
です。
双方向テキストの各段落は、右から左、または左から右のいずれかの基本方向を持つことができます。左から右へ記述される段落のテキストは、画面上のウィンドウ左端から始まり、右端に達すると切り詰められるか、あるいは続きが表示されます。対照的に、右から左へ記述される段落のテキストは、右端から始まり、左端で続きが表示されるか、あるいは切り詰められます。デフォルトでは、段落の境界は空行、つまり空白文字のみで構成される行となります。これを変更するには、2つの変数
bidi-paragraph-start-re と bidi-paragraph-separate-re
をカスタマイズできます。これらの変数の値は正規表現(文字列)である必要があります。例えば、単一の改行で新しい段落を開始させるには、これら両方の変数を
"^" に設定します。これら2つの変数はバッファローカルです(ローカル変数を参照)。
Emacsは、各段落の冒頭のテキストに基づいて、段落の基本方向を動的に決定します。ただし、バッファによっては、段落に特定の基本方向を強制的に適用する必要がある場合があります。変数
bidi-paragraph-direction が nil
以外の場合、基本方向の動的決定が無効になり、代わりにバッファ内のすべての段落に、バッファローカル値で指定された方向が強制的に適用されます。この値は
right-to-left または left-to-right のいずれかになります。それ以外の値は nil として解釈されます。
あるいは、段落の前に特殊な書式文字を挿入することで、その段落の基本方向を制御することもできます。特殊文字 RIGHT-TO-LEFT MARK または RLM
は、後続の段落に右から左への方向を強制し、LEFT-TO-RIGHT MARK または LRM は左から右への方向を強制します。(これらの文字を挿入するには C-x 8
RET を使用できます。)GUIセッションでは、LRM および RLM
文字は非常に細い空白文字として表示され、テキスト端末では空白として表示されます。
文字は表示用に再配置されるため、論理的な順序やバッファ位置の連続範囲に対して動作するEmacsコマンドは、予期しない挙動を示すことがあります。例えば、C-f や C-b コマンドは論理的な順序でポイントを移動させるため、ポイントが再配置された双方向テキストを横切る際に、カーソルがジャンプすることがあります。同様に、連続した文字位置の範囲をカバーするハイライト領域が、その領域が再配置されたテキストにまたがっている場合、不連続に見えることがあります。これは正常な動作であり、双方向テキストをサポートする他のプログラムの挙動と同様です。
LEFT や C-RIGHT など、矢印キーに割り当てられたカーソル移動コマンドは、現在の段落の基本方向の影響を受けます。左から右へ記述される段落では、修飾子の有無にかかわらず RIGHT に割り当てられたコマンドはバッファテキスト内を前方に移動しますが、右から左へ記述される段落では代わりに後方に移動します。これは、右から左へ記述される段落において、画面上を左に移動するとバッファ位置が主に増加するという事実を反映しています。
段落から移動すると、前後の段落の基本方向が移動元の段落と異なる場合、矢印キーの意味が変わることがあります。その場合は、押す矢印キーを新しい基本方向に合わせて調整する必要があります。
デフォルトでは、LEFT と RIGHT
は論理的な順序で移動しますが、visual-order-cursor-movement が
nil
以外の場合、これらのコマンドは、現在の画面位置からそれぞれ左または右にある文字へ移動し、状況に応じて次の、あるいは前の画面行へと移動します。なお、周囲の双方向コンテキストによっては、これによりポイントがバッファ位置単位で大きく移動する可能性がある点に注意してください。
双方向テキストでは、表示時のテキストの並べ替えに影響を与えるために、特殊な書式文字が使用されることがあります。前述の LRM および RLM
文字はその一例ですが、他にも同様の文字が存在します。これらの文字は、デフォルトではGUIフレームでは細いスペースグリフとして、テキストモードフレームでは単純なスペースとして表示されます。表示への影響に驚かないよう、これらの特殊な制御文字を把握しておきたい場合は、glyphless-display-mode を有効にすることができます(テキストの表示方法
を参照)。このマイナーモードを有効にすると、これらの書式文字が小さなボックス内の略語として表示されるため、画面上で目立ち、その効果を理解しやすくなります。