Перехватчики изменений
Эти переменные-перехватчики позволяют отслеживать изменения в буферах (или в определённом буфере, если сделать их локальными для буфера). О том, как обнаруживать изменения в определённых частях текста, см. также раздел Свойства с особым значением.
Функции, используемые в этих перехватчиках, должны сохранять и восстанавливать данные о совпадении, если они выполняют действия с регулярными выражениями; в противном случае они будут самым неожиданным образом мешать операциям редактирования, которые их вызывают. Кроме того, функции этих перехватчиков должны избегать изменения текста буфера, начертаний, свойств, наложений и других аспектов состояния буфера, кроме тех, которые сами функции-перехватчики создают и которыми управляют, поскольку такие изменения, произведённые без ведома других частей Emacs, могут привести к их неправильной работе.
- Переменная: 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, но при этом организует вызов функций-перехватчиков после изменения всего один раз для серии из нескольких изменений — если это кажется безопасным.
Если программа вносит несколько изменений текста в одной и той же области буфера, использование макроса
combine-after-change-callsвокруг этой части программы может значительно ускорить её выполнение при использовании перехватчиков после изменения. При окончательном вызове перехватчиков после изменения аргументы указывают часть буфера, включающую все изменения, внесённые в теле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
-
Если значение этой переменной не равно
nil, все перехватчики изменений отключаются и не запускаются. Это касается всех переменных-перехватчиков, описанных выше в этом разделе, а также перехватчиков, связанных с некоторыми особыми текстовыми свойствами (см. Свойства с особым значением) и свойствами наложений (см. Свойства наложений).Кроме того, во время выполнения этих же переменных-перехватчиков этой переменной присваивается значение
nil, чтобы по умолчанию изменение буфера из перехватчика изменений не приводило к запуску других перехватчиков изменений. Если необходимо, чтобы в определённом фрагменте кода, который сам выполняется из перехватчика изменений, запускались перехватчики изменений, локально свяжитеinhibit-modification-hooksсо значениемnil. Однако это может привести к рекурсивным вызовам перехватчиков изменений, поэтому следует предусмотреть защиту от этого (например, связать некоторую переменную, сообщающую вашему перехватчику, что ему ничего не нужно делать).Рекомендуется связывать эту переменную только для изменений, не приводящих к постоянным изменениям содержимого текста буфера (например, изменений начертания или временных изменений). Если нужно отложить запуск перехватчиков изменений на время серии изменений (обычно ради повышения производительности), используйте вместо этого
combine-change-callsилиcombine-after-change-calls.
Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Change-Hooks.html