Обработка изменений
Эти переменные-хуки позволяют следить за изменениями в буферах (или в конкретном буфере, если вы сделаете их локальными для буфера). См. также Специальные свойства для обнаружения изменений в определённых частях текста.
Функции, используемые в этих хуках, должны сохранять и восстанавливать данные сопоставления, если они выполняют какие-либо действия с использованием регулярных выражений; в противном случае они будут странным образом мешать операциям редактирования, которые их вызывают.
- Переменная: before-change-functions
Эта переменная содержит список функций, которые нужно вызывать, когда Emacs собирается изменить буфер. Каждая функция получает два аргумента: начало и конец области, которая собирается измениться, представленные целыми числами. Буфер, который собирается измениться, всегда является текущим буфером во время вызова функции.
- Переменная: after-change-functions
-
Эта переменная содержит список функций, которые нужно вызывать после того, как Emacs изменит буфер. Каждая функция получает три аргумента: начало и конец только что изменённой области и длину текста, существовавшего до изменения. Все три аргумента являются целыми числами. Буфер, который был изменён, всегда является текущим буфером при вызове функции.
Длина старого текста представляет собой разницу между позициями буфера до и после изменения текста в виде, в котором он существовал до изменения. Что касается изменённого текста, его длина просто представляет собой разницу между первыми двумя аргументами.
Вывод сообщений в буфер *Messages* не вызывает эти функции, так же как и некоторые внутренние изменения в буферах, созданных Emacs внутри для определённых задач, которые не должны быть видны программам Lisp.
Большинство примитивов изменения буфера будут вызывать before-change-functions и after-change-functions в парных вызовах, по одному разу для каждого изменения, где аргументы этих хуков точно определяют выполняемое изменение. Тем не менее, функции хуков не должны полагаться на то, что это всегда происходит, так как некоторые сложные примитивы вызывают before-change-functions один раз перед выполнением изменений, а затем вызывают after-change-functions ноль или более раз, в зависимости от того, сколько отдельных изменений выполняет примитив. В этом случае аргументы before-change-functions будут охватывать область, в которой выполняются отдельные изменения, но необязательно будут минимальной такой областью, а аргументы каждого последующего вызова after-change-functions будут точно определять изменяемую часть текста. В общем случае рекомендуется использовать либо хук перед изменением, либо хук после изменения, но не оба одновременно.
- Макрос: combine-after-change-calls body…
-
Макрос выполняет body обычно, но организует вызов функций after-change только один раз для серии из нескольких изменений — если это кажется безопасным.
Если программа выполняет несколько изменений текста в одной и той же области буфера, использование макроса
combine-after-change-callsв этой части программы может значительно ускорить её работу при использовании хуков after-change. При конечном вызове хуков after-change аргументы указывают на часть буфера, включающую все изменения, выполненные внутри телаcombine-after-change-calls.Предупреждение: Не изменяйте значения
after-change-functionsвнутри тела формыcombine-after-change-calls.Предупреждение: Если изменения, которые вы объединяете, происходят в широко разбросанных частях буфера, это всё равно будет работать, но это не рекомендуется, так как это может привести к неэффективному поведению для некоторых функций хуков изменения.
- Макрос: combine-change-calls beg end body…
-
Этот макрос выполняет body обычно, но любые изменения в буфере, которые он делает, не вызывают вызовы
before-change-functionsиafter-change-functions. Вместо этого происходит единственный вызов каждого из этих хуков для области, ограниченной beg и end, параметры, предоставленныеafter-change-functions, отражая изменения, внесённые в размер области телом body.Результат этого макроса — результат, возвращаемый body.
Этот макрос полезен, когда функция выполняет возможно большое количество повторяющихся изменений в буфере, и хуки изменения в противном случае потребовали бы длительного времени выполнения, если бы они выполнялись для каждого отдельного изменения буфера. Emacs сам использует этот макрос, например, в командах
comment-regionиuncomment-region.Предупреждение: Не изменяйте значения
before-change-functionsилиafter-change-functionвнутри body.Предупреждение: Не выполняйте никаких изменений буфера за пределами области, указанной beg и end.
- Переменная: first-change-hook
Эта переменная является обычным хуком, который выполняется всякий раз, когда буфер изменяется, ранее находившийся в неизменённом состоянии.
- Переменная: inhibit-modification-hooks
-
Если эта переменная имеет ненулевое значение, все хуки изменения отключены; ни один из них не выполняется. Это влияет на все переменные хуков, описанные выше в этом разделе, а также на хуки, прикреплённые к определённым специальным свойствам текста (см. Специальные свойства) и свойствам наложений (см. Свойства наложений).
Кроме того, эта переменная привязана к ненулевому значению во время выполнения тех же переменных хуков, поэтому по умолчанию изменение буфера из хука изменения не вызывает выполнение других хуков изменения. Если вы хотите, чтобы хуки изменения выполнялись в определённом фрагменте кода, который сам выполняется из хука изменения, переопределите локально
inhibit-modification-hooksнаnil. Однако это может привести к рекурсивным вызовам хуков изменения, поэтому убедитесь, что вы к этому готовы (например, привязав какую-либо переменную, которая сообщит вашему хуку ничего не делать).Рекомендуется привязывать эту переменную только к изменениям, которые не приводят к постоянным изменениям содержимого текста буфера (например, изменениям стиля отображения или временным изменениям). Если вам нужно отложить хуки изменения во время серии изменений (обычно для повышения производительности), используйте
combine-change-callsилиcombine-after-change-callsвместо этого.
Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Change-Hooks.html