The copy-region-as-kill function (see copy-region-as-kill) uses the filter-buffer-substring function, which in turn uses the
delete-and-extract-region function. It removes
the contents of a region and you cannot get them back.
ここで扱う他のコードとは異なり、delete-and-extract-region 関数は
Emacs Lisp で書かれているわけではなく、C で書かれており、GNU Emacs
システムのプリミティブの一つです。非常にシンプルなので、Lisp から少し脱線して、ここで説明します。
他の多くのEmacsプリミティブと同様に、delete-and-extract-regionはCマクロのインスタンスとして記述されます。マクロとは、コードのテンプレートのことです。完全なマクロは以下のようになります。
DEFUN ("delete-and-extract-region", Fdelete_and_extract_region,
Sdelete_and_extract_region, 2, 2, 0,
doc: /* Delete the text between START and END and return it. */)
(Lisp_Object start, Lisp_Object end)
{
validate_region (&start, &end);
if (XFIXNUM (start) == XFIXNUM (end))
return empty_unibyte_string;
return del_range_1 (XFIXNUM (start), XFIXNUM (end), 1, 1);
}
マクロの記述プロセスの詳細には触れませんが、このマクロは DEFUN
という単語から始まる点を指摘しておきます。DEFUN という単語を選んだのは、このコードが Lisp
における defun と同じ役割を果たすためです。(C のマクロ DEFUN は emacs/src/lisp.h
で定義されています。)
DEFUN という単語の後には、括弧内に7つの部分が続いています:
delete-and-extract-regionです。
Fdelete_and_extract_regionです。慣習として、‘F’から始まります。C言語では名前にハイフンを使用しないため、代わりにアンダースコアが用いられます。
interactive宣言に続く引数の記述にほぼ似ています。つまり、文字の後に、おそらくプロンプトが続くという形式です。Lispとの唯一の違いは、マクロが引数なしで呼び出される場合です。その際は、このマクロのように、0(空文字列)を記述します。
引数を指定する場合は、引用符で囲みます。goto-char 用の C マクロでは、この位置に
"NGoto char: "
を含めることで、関数が生のプレフィックス(この場合はバッファ内の数値位置)を期待していることを示し、プロンプトを提供しています。
lib-src/make-docfile がこれらのコメントを抽出し、ドキュメントの作成に利用します。)
Cのマクロでは、次に仮引数が続き、それがどのようなオブジェクトであるかが記述され、その後にマクロの本体が続きます。delete-and-extract-regionの場合、本体は以下の4行で構成されています。
validate_region (&start, &end); if (XFIXNUM (start) == XFIXNUM (end)) return empty_unibyte_string; return del_range_1 (XFIXNUM (start), XFIXNUM (end), 1, 1);
validate_region
関数は、領域の開始位置および終了位置として渡された値が適切な型であり、かつ範囲内にあるかを判定します。開始位置と終了位置が同一の場合は、空文字列を返します。
del_range_1
関数は、実際にはテキストを削除します。これは複雑な関数であるため、ここでは詳しく見ません。バッファを更新したり、その他の処理を行ったりします。とはいえ、del_range_1 に渡される2つの引数については見ておく価値があります。それが XFIXNUM (start) と XFIXNUM (end) です。
C言語の観点から言えば、start と end
は、削除対象領域の開始と終了を示す2つの不透明な値である。より正確に言えば――理解にはより高度な専門知識を要するが――これら2つの値は Lisp_Object 型であり、Cのポインタ、Cの整数、あるいはCの struct のいずれかとなり得る。通常、Cコードは Lisp_Object がどのように実装されているかを気にする必要はない。
Lisp_Object
幅はマシンによって異なり、通常は32ビットまたは64ビットです。ビットの一部は情報の種類を指定するために使用され、残りのビットはコンテンツとして使用されます。
‘XFIXNUM’は、より長いビット列から該当する整数を抽出するCマクロであり、型ビットは破棄されます。
delete-and-extract-region 内のコマンドは次のようになります。
del_range_1 (XFIXNUM (start), XFIXNUM (end), 1, 1);
開始位置 start と終了位置 end
の間の領域を削除します。
Lispを書く者の視点からすれば、Emacsはすべて非常にシンプルだ。だが、その裏側には、すべてを動作させるための多大な複雑さが潜んでいる。