このセクションで説明するソート関数は、すべてバッファー内のテキストを再配置します。これはリスト要素を再配置するsort
関数とは対照的です(see リストを再配置する関数)。これらの関数がリターンする値に意味はありません。
この関数はバッファーをレコードに細分してそれらをソートする一般的なテキストソートルーチン。このセクションのコマンドのほとんどは、この関数を使用する。
sort-subr
が機能する方法を理解するためには、バッファーのアクセス可能範囲をソートレコード(sort
records)と呼ばれる分離された断片に分割すると考えればよい。レコードは連続、あるいは非連続かもしれないがオーバーラップしてはならない。各ソートレコードの一部(全体かもしれない)はソートキーとして指定される。これらソートキーによるソートによりレコードは再配置される。
レコードは通常はソートキー昇順で再配置される。sort-subr
の1つ目の引数reverseが非nil
ならレコードはソートキー降順にソートされて再配置される。
sort-subr
にたいする以下の4つの引数は、ソートレコード間でポイントを移動するために呼び出される。これらはsort-subr
内で頻繁に呼び出される。
sort-subr
が呼び出された際には、ポイント位置が1つ目のレコードの開始とみなされる。したがってsort-subr
を呼び出す前は、通常はそのバッファーの先頭にポイントを移動すること。
この関数はバッファー終端にポイントを残すことにより、それ以上のソートレコードがないことを示すことができるできる。
nil
値、またはnil
(ソートキーはそのバッファー内のポイント位置から始まることを示す)のいずれかをリターンすること。後者の場合にはソートキー終端を見るけるためにendkeyfunが呼び出される。
nil
をリターンし、かつこの引数が省略(またはnil
)の場合には、そのソートキーはレコード終端まで拡張される。startkeyfunが非nil
値をリターンした場合にはendkeyfunは不要。
引数predicateはキーの比較に使用する関数。この関数は引数として比較する2つのキーを受け取り、1つ目のキーが2つ目のキーよりソート順で前なら非nil
をリターンすること。引数のキーが正確に何であるかはstartkeyfunとendkeyfunがリターンする値に依存する。predicateが省略またはnil
の場合のデフォルトはキーが数値なら<
、キーがコンスセル(car
がキーのバッファー位置の開始でcdr
が終了)ならcompare-buffer-substrings
、それ以外ならstring<
(キーを文字列とみなす)。
sort-subr
の例として以下はsort-lines
関数の完全な定義である:
;; ドキュメント文字列の冒頭2行は ;; ユーザー閲覧時には1行となることに注意 (defun sort-lines (reverse beg end) "リージョン内の行をアルファベット順にソート;\ 引数は降順を意味する プログラムから呼び出す場合は、以下の3つの引数がある:
REVERSE(非nilは逆順の意)、\ およびBEGとEND(ソートするリージョン) 変数`sort-fold-case'は英字\ 大文字小文字の違いが ソート順に影響するかどうかを決定する"
(interactive "P\nr") (save-excursion (save-restriction (narrow-to-region beg end) (goto-char (point-min)) (let ((inhibit-field-text-motion t)) (sort-subr reverse 'forward-line 'end-of-line)))))
ここでforward-line
は次のレコードの先頭にポイントを移動して、end-of-line
はレコードの終端にポイントを移動する。レコード全体をソートキーとするので引数startkeyfunとendkeyfunは渡していない。
sort-paragraphs
はほとんど同じだが、sort-subr
の呼び出しが以下のようになる:
(sort-subr reverse (lambda () (while (and (not (eobp)) (looking-at paragraph-separate)) (forward-line 1))) 'forward-paragraph)
ソートレコード内を指す任意のマーカーは、sort-subr
リターン後は無意味なマーカー位置のまま取り残される。
この変数が非nil
なら、sort-subr
とその他のバッファーソート関数は文字列比較時にcase(大文字小文字)の違いを無視する。
このコマンドはstartからendの間のリージョンを、record-regexpとkey-regexpで指定されたようにアルファベット順にソートする。reverseが負の整数なら逆順にソートする。
アルファベット順のソートとは2つのソートキーにたいして、それぞれの1つ目の文字同士、2つ目の文字同士、...のように比較することにより、キーを比較することを意味する。文字が一致しなければ、それはソートキーが不等なことを意味する。最初の不一致箇所で文字が小さいソートキーが小さいソートキーとなる。個別の文字はEmacs文字セット内の文字コードの数値に応じて比較される。
引数record-regexpの値はバッファーをソートレコードに分割する方法を指定する。各レコードの終端で、この正規表現にたいする検索は完了して、これにマッチするテキストが次のレコードとして採用される。たとえば改行の前に少なくとも1つの文字がある行にマッチする正規表現‘^.+$’は、そのような行をソートレコードとするだろう。正規表現の構文と意味については正規表現を参照のこと。
引数key-regexpの値は各レコードのどの部分がソートキーかを指定する。key-regexpはレコード全体、またはその一部にマッチすることができる。後者の場合にはレコードの残りの部分はソート順に影響しないが、レコードが新たな位置に移動される際はともに移動される。
引数key-regexpはrecord-regexpの部分式(subexpression)、またはその正規表現自体にマッチしたテキストを参照できる。
key-regexpには以下を指定できる:
record-regexp内でdigit番目のカッコ‘\(...\)’でグループ化によりマッチしたテキストがソートキーになる。
レコード全体がソートキーとなる。
sort-regexp-fields
は、そのレコード内で正規表現にたいするマッチを検索する。そのようなマッチがあればそれがソートキー。レコード内にkey-regexpにたいするマッチがなければそのレコードは無視されて、そのバッファー内でのレコードの位置は変更されないことを意味する(他のレコードがそのレコードを移動するかもしれない)。
たとえばリージョン内のすべての行にたいして、最初の単語が文字‘f’で始まる行をソートすることを目論むなら、record-regexpを‘^.*$’、key-regexpを‘\<f\w*\>’にセットすること。結果は以下のような式になる
(sort-regexp-fields nil "^.*$" "\\<f\\w*\\>" (region-beginning) (region-end))
sort-regexp-fields
をインタラクティブに呼び出した場合にはミニバッファー内でrecord-regexpとkey-regexpの入力を求める。
このコマンドはstartとendの間のリージョン内の行をアルファベット順にソートする。reverseが非nil
なら逆順にソートする。
このコマンドはstartとendの間のリージョン内のパラグラフをアルファベット順にソートする。reverseが非nil
なら逆順にソートする。
このコマンドはstartとendの間のリージョン内のページをアルファベット順にソートする。reverseが非nil
なら逆順にソートする。
このコマンドはstartとendの間のリージョン内の行にたいして、各行のfield番目のフィールドをアルファベット順に比較することに行をソートする。fieldは空白文字により区切られて、1から数えられる。fieldが負なら行の終端から-field番目のフィールドでソートする。このコマンドはテーブルのソートに有用。
このコマンドはstartとendの間のリージョン内の行にたいして、各行のfield番目のフィールドを数値的に比較することにより行をソートする。fieldは空白文字により区切られて、1から数えられる。リージョン内の各行の指定されたフィールドは数字を含んでいなければならない。0で始まる数字は8進数、‘0x’で始まる数字は16進数として扱われる。
fieldが負なら行の終端から-field番目のフィールドでソートする。このコマンドはテーブルのソートに有用。
この変数はsort-numeric-fields
にたいして数字を解析するための基本基数を指定する。
このコマンドはbegとendの間にある行にたいして特定の列範囲をアルファベット順に比較することによりソートする。begとendの列位置はソートが行われる列範囲にバインドされる。
reverseが非nil
なら逆順にソートする。
このコマンドが通常と異なるのは、位置begを含む行全体と位置endを含む行全体がソートされるリージョンに含まれることである。
タブは指定された列に分割される可能性があるので、sort-columns
はタブを含むテキストを受け付けないことに注意。ソート前にM-x
untabifyを使用してタブをスペースに変換すること。
可能ならユーティリティプログラムsort
を呼び出すことにより、このコマンドは実際に機能する。