テキストプロパティの一般的な利用においては、多くの場合、連続する数文字あるいは多数の文字が同じプロパティ値を持ちます。文字を一つずつ調べるようにプログラムを組むよりも、同じプロパティ値を持つテキストの塊を処理する方がはるかに高速です。
これを実現するために利用できる関数を以下に示します。これらの関数では、プロパティ値の比較に eq
を使用します。いずれの場合も、object はデフォルトで現在のバッファとなります。
良好なパフォーマンスを得るには、これらの関数、特に単一のプロパティを検索する関数に limit 引数を指定することが非常に重要です。そうしないと、関心のあるプロパティが変化しない場合、バッファの末尾までスキャンするのに長い時間を要する可能性があります。
これらの関数はポイントを移動させず、代わりに位置(または nil)を返します。位置は常に2つの文字の間にあることに留意してください。これらの関数が返す位置は、異なるプロパティを持つ2つの文字の間にあります。
この関数は、文字列またはバッファ object の位置 pos からテキストを前方にスキャンし、何らかのテキストプロパティの変化が見つかるまで処理を続け、その変化の位置を返します。言い換えれば、pos より後ろにある文字のうち、そのプロパティが pos の直後の文字のプロパティと同一ではない最初の文字の位置を返します。
limit が nil でない場合、スキャンは位置
limit で終了します。その時点までにプロパティの変更がない場合、この関数は limit を返します。
object の最後までプロパティが変更されず、かつ limit が nil である場合、値は nil となる。値が nil 以外である場合、それは
pos 以上の位置となる。値が pos
と等しくなるのは、limit が pos
と等しい場合に限られる。
すべてのプロパティが一定であるテキストのチャンク単位でバッファをスキャンする方法の例を以下に示します。
(while (not (eobp))
(let ((plist (text-properties-at (point)))
(next-change
(or (next-property-change (point) (current-buffer))
(point-max))))
Process text from point to next-change...
(goto-char next-change)))
これは next-property-change のようなものですが、前方ではなく pos から遡ってスキャンします。値が nil
以外の場合、それは pos 以下の位置となり、limit が
pos と等しい場合にのみ pos と等しくなります。
この関数は、テキスト内で prop プロパティの変化をスキャンし、その変化の位置を返します。スキャンは、文字列内の位置 pos またはバッファ内の位置 object から順に行われます。言い換えれば、この関数は、pos より後ろで、prop プロパティが pos の直後の文字のプロパティと異なる最初の文字の位置を返します。
limit が nil でない場合、スキャンは位置
limit で終了します。その時点までにプロパティの変更がなければ、next-single-property-change は limit を返します。
プロパティがobjectの最後まで変更されず、かつlimitがnilである場合、値はnilとなる。値がnil以外である場合は、pos以上の位置となり、limitがposと等しい場合にのみposと等しくなる。
これは next-single-property-change のようなものですが、前方ではなく
pos から遡ってスキャンします。値が nil
以外の場合、それは pos 以下の位置となり、limit が
pos と等しい場合にのみ pos と等しくなります。
これは next-property-change
と同様ですが、テキストプロパティだけでなくオーバーレイプロパティも考慮し、バッファの末尾までに変更が検出されなかった場合は、nil ではなく最大バッファ位置を返します(この点において、next-property-change ではなく対応するオーバーレイ関数 next-overlay-change
に似ています)。この関数は現在のバッファに対してのみ動作するため、object
オペランドは存在しません。いずれかの種類のプロパティが変更された次のアドレスを返します。
これは next-char-property-change と同様ですが、前方ではなく pos から遡ってスキャンし、変更が見つからなかった場合は最小のバッファ位置を返します。
これは next-single-property-change
と同様ですが、テキストプロパティに加えてオーバーレイプロパティも考慮し、object
の終了までに変更が検出されなかった場合は、nil ではなく object における最大の有効な位置を返します。next-char-property-change とは異なり、この関数には object オペランドが存在します。object がバッファでない場合は、テキストプロパティのみが考慮されます。
これは next-single-char-property-change と同様ですが、前方ではなく
pos から遡ってスキャンし、変更が見つからない場合は object 内の最小の有効な位置を返します。
この関数は、start と end
の間にある文字のうち、少なくとも1つが値 value のプロパティ prop を持つ場合、非 nil
を返します。より正確には、そのような最初の文字の位置を返します。それ以外の場合は、nil
を返します。
省略可能な第5引数 object は、スキャン対象の文字列またはバッファを指定します。位置は object を基準とします。object のデフォルト値は現在のバッファです。
この関数は、start と end
の間にある文字のうち、少なくとも1つが値 value のプロパティ prop を持たない場合、non-nil
を返します。より正確には、そのような最初の文字の位置を返します。それ以外の場合は、nil
を返します。
省略可能な第5引数 object は、スキャン対象の文字列またはバッファを指定します。位置は object を基準とします。object のデフォルト値は現在のバッファです。
predicate に従い、プロパティ prop が
value(デフォルトは nil)に一致する次のテキスト領域を検索します。
この関数は、ポイントを移動させる点では search-forward(文字列の検索
を参照)およびその関連関数を踏襲していますが、match-beginning
およびその関連関数のようにマッチ結果を返すのではなく、マッチ内容を記述する構造体を返します。
値が一致するテキストプロパティが見つからない場合、関数は nil
を返します。見つかった場合は、point はこの一致するテキストプロパティを持つ領域の末尾に配置され、関数は一致に関する情報を含む prop-match 構造体を返します。
predicate は、t(equal の同義語)、nil(「等しくない」の意)、または
2 つの引数(value と、マッチ候補となるバッファ位置における text プロパティ prop の値)で呼び出される述語のいずれかとなります。この関数は、マッチした場合は non-nil を、そうでない場合は nil を返す必要があります。
not-current が nil
でない場合、ポイントがすでにプロパティマッチのある領域に含まれているなら、その領域をスキップして代わりに次の領域を探す。
prop-match 構造には、以下のアクセサ関数があります。prop-match-beginning(マッチの開始位置)、prop-match-end(マッチの終了位置)、および prop-match-value(マッチ開始位置における property の値)です。
以下の例では、次のような内容のバッファを使用します。
This is a bold and here’s bolditalic and this is the end.
つまり、「太字」の単語はboldフェイスであり、「斜体」の単語はitalicフェイスです。
開始時点での地点:
(while (setq match (text-property-search-forward 'face 'bold t))
(push (buffer-substring (prop-match-beginning match)
(prop-match-end match))
words))
これにより、boldフェイスを使用しているすべての単語が抽出されます。
(while (setq match (text-property-search-forward 'face nil t))
(push (buffer-substring (prop-match-beginning match)
(prop-match-end match))
words))
これにより、faceプロパティを持たないすべてのビットが抽出され、結果としてリスト ‘("This is a "
"and here's "
"and this is the end")’
が得られます(pushを使用したため、逆順になります。詳細は リスト変数の変更 を参照してください)。
(while (setq match (text-property-search-forward 'face nil nil))
(push (buffer-substring (prop-match-beginning match)
(prop-match-end match))
words))
これにより、face
に何らかの値が設定されているすべてのリージョンが抽出されますが、プロパティが変化する箇所ごとに分割されるため、ここでの結果は ‘("bold" "bold"
"italic")’ となります。
このような使い方が想定されるより現実的な例を挙げると、特定のセクションがURLを表し、それらに shr-url というタグが付いているバッファがあるとします。
(while (setq match (text-property-search-forward 'shr-url nil nil)) (push (prop-match-value match) urls))
これで、それらすべてのURLの一覧が表示されます。
これは text-property-search-forward
と同様ですが、代わりに後方を検索し、一致が見つかった場合は、point が一致領域の末尾ではなく先頭に配置されます。