Spec-Zone.ru › Elisp

Перехватчики изменений

Эти переменные-перехватчики позволяют отслеживать изменения в буферах (или в определённом буфере, если сделать их локальными для буфера). О том, как обнаруживать изменения в определённых частях текста, см. также раздел Свойства с особым значением.

Функции, используемые в этих перехватчиках, должны сохранять и восстанавливать данные о совпадении, если они выполняют действия с регулярными выражениями; в противном случае они будут самым неожиданным образом мешать операциям редактирования, которые их вызывают. Кроме того, функции этих перехватчиков должны избегать изменения текста буфера, начертаний, свойств, наложений и других аспектов состояния буфера, кроме тех, которые сами функции-перехватчики создают и которыми управляют, поскольку такие изменения, произведённые без ведома других частей 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API