13.12.1 Примитивы для манипулирования советами (advices)

Макрос: add-function where place function &optional props

Этот макрос — удобный способ добавить совет function к функции, хранящейся в place (см. Обобщенные переменные).

where определяет, как function комбинируется с существующей функцией, например, должна ли function вызываться до или после исходной функции. См. Способы комбинирования советов, для списка доступных способов комбинирования двух функций.

При изменении переменной (имя которой обычно заканчивается на -function), вы можете выбрать, будет ли function использоваться глобально или только в текущем буфере: если place — это просто символ, то function добавляется к глобальному значению place. В то время как если place имеет форму (local symbol), где symbol — это выражение, возвращающее имя переменной, то function будет добавлена только в текущий буфер. Наконец, если вы хотите изменить лексическую переменную, вам придется использовать (var variable).

Каждая функция, добавленная с помощью add-function, может сопровождаться списком ассоциаций свойств props. В настоящее время только два из этих свойств имеют особое значение:

name

Это дает имя совету, которое remove-function может использовать для идентификации функции, которую нужно удалить. Обычно используется, когда function является анонимной функцией.

depth

Это указывает, как упорядочить совет, если присутствует несколько частей совета. По умолчанию глубина равна 0. Глубина 100 указывает на то, что эта часть совета должна быть сохранена максимально глубоко, тогда как глубина -100 указывает на то, что она должна остаться самой внешней частью. Когда две части совета указывают одинаковую глубину, самая недавно добавленная будет самой внешней.

Для совета :before быть самой внешней означает, что этот совет будет выполнен первым, до любого другого совета, тогда как быть самой внутренней означает, что он выполнится прямо перед исходной функцией, без выполнения какого-либо другого совета между ними и исходной функцией. Аналогично, для совета :after быть самой внутренней означает, что он выполнится сразу после исходной функции, без выполнения какого-либо другого совета между ними, тогда как быть самой внешней означает, что он будет выполнен в самом конце после всех других советов. Самая внутренняя часть совета :override будет переопределять только исходную функцию, а другие части совета будут применяться к ней, в то время как самая внешняя часть совета :override переопределит не только исходную функцию, но и все другие советы, примененные к ней.

Если function не является интерактивной, то объединенная функция унаследует интерактивную спецификацию, если таковая имеется, от исходной функции. В противном случае, объединенная функция будет интерактивной и будет использовать интерактивную спецификацию function. Одно исключение: если интерактивная спецификация function является функцией (т.е. выражением lambda или символом fbound, а не выражением или строкой), то интерактивная спецификация объединенной функции будет вызовом этой функции с интерактивной спецификацией исходной функции в качестве единственного аргумента. Чтобы интерпретировать полученную спецификацию в качестве аргумента, используйте advice-eval-interactive-spec.

Примечание: Интерактивная спецификация function будет применяться к объединенной функции и, следовательно, должна подчиняться соглашению вызова объединенной функции, а не function. Во многих случаях это не имеет значения, поскольку они идентичны, но это важно для :around, :filter-args и :filter-return, где function получает другие аргументы, чем исходная функция, хранящаяся в place.

Макрос: remove-function place function

Этот макрос удаляет function из функции, хранящейся в place. Это работает только в том случае, если function была добавлена в place с помощью add-function.

function сравнивается с функциями, добавленными в place, с использованием equal, чтобы попытаться сделать это также с лямбда-выражениями. Он также сравнивается с свойством name функций, добавленных в place, что может быть более надежным, чем сравнение лямбда-выражений с помощью equal.

Функция: advice-function-member-p advice function-def

Возвращает не-nil, если advice уже находится в function-def. Как и для remove-function выше, вместо того чтобы advice была фактической функцией, она также может быть name части совета.

Функция: advice-function-mapc f function-def

Вызывает функцию f для каждой части совета, добавленной в function-def. f вызывается с двумя аргументами: функцией совета и его свойствами.

Функция: advice-eval-interactive-spec spec

Вычисляет интерактивную spec так же, как если бы это был интерактивный вызов функции с такой спецификацией, а затем возвращает соответствующий список аргументов, который был создан. Например, (advice-eval-interactive-spec "r\nP") вернет список из трех элементов, содержащий границы области и текущий аргумент префикса.

Например, если вы хотите сделать командную строку C-x m (compose-mail) для заголовка «From:», вы можете написать что-то вроде этого:

(defun my-compose-mail-advice (orig &rest args)
  "Прочитать From: интерактивно."
  (interactive
   (lambda (spec)
     (let* ((user-mail-address
             (completing-read "From: "
                              '("one.address@example.net"
                                "alternative.address@example.net")))
            (from (message-make-from user-full-name
                                     user-mail-address))
            (spec (advice-eval-interactive-spec spec)))
       ;; Поместить заголовок From в аргумент OTHER-HEADERS.
       (push (cons 'From from) (nth 2 spec))
       spec)))
  (apply orig args))

(advice-add 'compose-mail :around #'my-compose-mail-advice)