При типичном использовании текстовых свойств часто несколько или многие последовательные символы имеют одинаковое значение для некоторого свойства. Вместо того чтобы писать программы, проверяющие символы по одному, гораздо быстрее обрабатывать целые фрагменты текста с одинаковым значением свойства.
Ниже приведены функции, которые можно использовать для этого. Они используют eq для
сравнения значений свойств. Во всех случаях object по умолчанию равен текущему
буферу.
Для хорошей производительности очень важно использовать аргумент limit в этих функциях, особенно в тех, которые ищут одно свойство — в противном случае они могут тратить много времени на сканирование до конца буфера, если интересующее вас свойство не изменяется.
Эти функции не перемещают точку; вместо этого они возвращают позицию (или
nil). Помните, что позиция всегда находится между двумя символами;
позиция, возвращаемая этими функциями, находится между двумя символами с
разными свойствами.
Эта функция просматривает текст вперёд от позиции pos в строке или буфере object до тех пор, пока не найдет изменение какого-либо текстового свойства, а затем возвращает позицию изменения. Другими словами, она возвращает позицию первого символа после pos, чьи свойства не идентичны свойствам символа, следующего сразу за pos.
Если limit не равен nil, то сканирование заканчивается на позиции
limit. Если до этой точки изменения свойства не найдено, эта
функция возвращает limit.
Значение равно nil, если свойства остаются неизменными до самого
конца object, а limit равен 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))))
Обработка текста от точки до next-change…
(goto-char next-change)))
Эта функция аналогична next-property-change, но сканирует назад от pos,
а не вперёд. Если значение не равно nil, то это позиция
меньше или равная pos; она равна pos только в том случае, если limit
равен pos.
Эта функция просматривает текст на предмет изменения свойства prop, а затем возвращает позицию изменения. Сканирование выполняется вперёд от позиции pos в строке или буфере object. Другими словами, эта функция возвращает позицию первого символа после pos, чьё свойство prop отличается от свойства символа, следующего сразу за pos.
Если limit не равен nil, то сканирование заканчивается на позиции
limit. Если до этой точки изменения свойства не найдено,
next-single-property-change возвращает limit.
Значение равно nil, если свойство остается неизменным до самого
конца object, а limit равен nil. Если значение
не равно nil, то это позиция больше или равная pos; она
равна pos только в том случае, если limit равен pos.
Эта функция аналогична next-single-property-change, но сканирует назад от
pos, а не вперёд. Если значение не равно nil, то это
позиция меньше или равная pos; она равна pos только в том случае,
если limit равен pos.
Эта функция аналогична next-property-change, за исключением того, что она учитывает
свойства наложений (overlay) наряду с текстовыми свойствами, и если изменение не
найдено до конца буфера, она возвращает максимальную позицию
буфера, а не nil (в этом смысле она напоминает
соответствующую функцию для наложений next-overlay-change, а не
next-property-change). Операнд object отсутствует,
поскольку эта функция работает только с текущим буфером. Она возвращает
следующую позицию, в которой изменяется свойство любого из этих типов.
Эта функция аналогична next-char-property-change, но сканирует назад от
pos, а не вперёд, и возвращает минимальную позицию
буфера, если изменение не найдено.
Эта функция аналогична next-single-property-change, за исключением того, что она
учитывает свойства наложений наряду с текстовыми свойствами, и если
изменение не найдено до конца object, она возвращает
максимальную допустимую позицию в object, а не nil. В отличие от
next-char-property-change, эта функция имеет
операнд object; если object не является буфером, учитываются
только текстовые свойства.
Эта функция аналогична next-single-char-property-change, но сканирует назад
от pos, а не вперёд, и возвращает минимальную допустимую
позицию в object, если изменение не найдено.
Эта функция возвращает не nil, если хотя бы один символ между
start и end имеет свойство prop, значение которого равно
value. Точнее, она возвращает позицию первого такого символа.
В противном случае она возвращает nil.
Необязательный пятый аргумент object задает строку или буфер для сканирования. Позиции задаются относительно object. По умолчанию для object используется текущий буфер.
Эта функция возвращает не nil, если хотя бы один символ между
start и end не имеет свойства prop со значением
value. Точнее, она возвращает позицию первого такого символа.
В противном случае она возвращает nil.
Необязательный пятый аргумент object задает строку или буфер для сканирования. Позиции задаются относительно object. По умолчанию для object используется текущий буфер.
Выполняет поиск следующей области текста, свойство prop которой
соответствует value (по умолчанию nil) согласно
predicate.
Эта функция смоделирована по образу search-forward (см. Поиск строк) и подобных ей, в том смысле, что она перемещает точку, но также возвращает
структуру, описывающую совпадение, вместо того чтобы возвращать его в
match-beginning и подобных переменных.
Если текстовое свойство, значение которого соответствует условию, не найдено, функция
возвращает nil. Если оно найдено, точка помещается в конец
области, имеющей это совпадающее текстовое свойство, и функция
возвращает структуру prop-match с информацией о
совпадении.
predicate может быть либо t (что является синонимом
equal), nil (что означает «не равно»), либо предикатом,
который будет вызван с двумя аргументами: value и значением
текстового свойства prop в позиции буфера, которая является
кандидатом на совпадение. Функция должна возвращать не 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» имеют лицо bold, а слово
«italic» — лицо 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))
Это выберет все фрагменты, у которых нет свойств лица, что
даст список ‘("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, но выполняет поиск
назад, и если совпадение найдено, точка помещается в начало
совпавшей области, а не в её конец.