本節で説明するソート関数は、いずれもバッファ内のテキストを並べ替えます。これは、リストの要素の順序を並べ替える関数 sort とは対照的です(リストを並べ替える関数 を参照)。これらの関数が返す値に意味はありません。
この関数は、バッファをレコード単位に分割してソートを行う汎用的なテキストソートルーチンです。本セクションのコマンドの多くは、この関数を使用しています。
sort-subrの仕組みを理解するには、バッファのアクセス可能な領域全体を、ソートレコードと呼ばれる互いに重なり合わない断片に分割されていると考えてください。これらのレコードは連続している場合もあればそうでない場合もありますが、互いに重なってはなりません。各ソートレコードの一部(場合によってはその全部)がソートキーとして指定されます。ソート処理では、レコードがソートキーの順に並べ替えられます。
通常、レコードはソートキーの昇順に並べ替えられます。sort-subr 関数の第1引数 reverse が nil
以外の場合、ソート対象のレコードはソートキーの降順に並べ替えられます。
sort-subr
に続く4つの引数は、ソートレコード内でポイントを移動させるために呼び出される関数です。これらは sort-subr 内部から何度も呼び出されます。
sort-subr
が呼び出された時点で、最初のレコードはポイントの位置から始まっているとみなされます。したがって、通常は sort-subr を呼び出す前に、ポイントをバッファの先頭に移動させておく必要があります。
この関数は、バッファの末尾にポインタを置くことで、ソート対象のレコードがもうないことを示せます。
nil 値を返すか、あるいはソートキーがポインタから始まるバッファ内にあることを示すために
nil を返す必要があります。後者の場合、ソートキーの終端を特定するために endkeyfun が呼び出されます。
nil
を返し、かつこの引数が省略された(または nil
が指定された)場合、ソートキーはレコードの末尾まで及びます。startkeyfun が nil 以外の値を返す場合、endkeyfun は不要です。
引数 predicate
は、キーを比較するために使用する関数です。比較対象のキーという2つの引数で呼び出され、ソート順において最初のキーが2番目のキーより前に来るべき場合は
non-nil を返す必要があります。キーの引数が具体的に何になるかは、startkeyfun と endkeyfun
が何を返すかによって決まります。predicate が省略されているか、あるいは nil である場合、キーが数値であれば <
に、キーがコンスセル(その car と cdr
がキーの開始および終了バッファ位置となるもの)であれば compare-buffer-substrings に、それ以外の場合(キーが文字列であると想定される場合)は
string< にデフォルトで設定されます。
sort-subr の例として、sort-lines の完全な関数定義を以下に示します。
;; Note that the first two lines of doc string ;; are effectively one line when viewed by a user. (defun sort-lines (reverse beg end) "Sort lines in region alphabetically;\ argument means descending order. Called from a program, there are three arguments:
REVERSE (non-nil means reverse order),\ BEG and END (region to sort). The variable `sort-fold-case' determines\ whether alphabetic case affects the sort order."
(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 およびその他のバッファソート関数は、文字列の比較時に大文字小文字を区別しません。
このコマンドは、start から end までの範囲を、record-regexp および key-regexp で指定された通りにアルファベット順にソートします。reverse が負の整数の場合、ソートは逆順で行われます。
アルファベット順のソートとは、2つのソートキーの先頭文字、2番目の文字というように順に比較することを指します。不一致が見つかった場合、それらのソートキーは等しくないことを意味し、最初に不一致が生じた箇所の文字が小さい方のソートキーが、より小さいソートキーとなります。個々の文字は、Emacs文字セットにおける数値文字コードに基づいて比較されます。
record-regexp 引数の値は、バッファをソートレコードにどのように分割するかを指定します。各レコードの末尾でこの正規表現による検索が行われ、それに一致するテキストが次のレコードとして取り込まれます。例えば、改行以外の文字を少なくとも1つ含む行に一致する正規表現 ‘^.+$’ を使用すると、そのような各行がソートレコードになります。正規表現の構文と意味については、正規表現を参照してください。
key-regexp 引数の値で、各レコードのどの部分がソートキーになるかを指定します。key-regexp はレコード全体、あるいはその一部に一致することがあります。後者の場合、レコードの残りの部分はソート順に影響を与えませんが、レコードが新しい位置に移動する際にそのまま引き継がれます。
key-regexp 引数は、record-regexp の部分式にマッチしたテキストを参照することも、それ自体が正規表現であることもできます。
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番目のフィールドでアルファベット順にソートします。フィールドは空白文字で区切られ、1から番号が振られます。fieldが負の値の場合、行の末尾から−field番目のフィールドでソートされます。このコマンドはテーブルのソートに便利です。
このコマンドは、start と end の間の領域にある行を、各行の 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 ユーティリティプログラムを呼び出すことで動作します。