Spec-Zone.ru › Elisp

Консультирование функций Emacs Lisp

Когда вам нужно изменить функцию, определенную в другой библиотеке, или когда вам нужно изменить хук, например foo-function, фильтр процесса или, по сути, любое переменное или поле объекта, которое содержит значение функции, вы можете использовать соответствующую функцию-сеттер, например, fset или defun для именованных функций, setq для переменных хуков или set-process-filter для фильтров процессов, но они часто слишком грубые, полностью удаляя предыдущее значение.

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

Система консультаций Emacs предоставляет два набора примитивов для этого: основной набор для значений функций, хранящихся в переменных и полях объектов (соответствующие примитивы add-function и remove-function) и другой набор, наложенный поверх него для именованных функций (основные примитивы advice-add и advice-remove).

В качестве тривиального примера, вот как добавить консультацию, которая будет изменять возвращаемое значение функции каждый раз, когда она вызывается:

(defun my-double (x)
  (* x 2))
(defun my-increase (x)
  (+ x 1))
(advice-add 'my-double :filter-return #'my-increase)

После добавления этой консультации, если вы вызовете my-double со значением ‘3’, возвращаемое значение будет ‘7’. Чтобы удалить эту консультацию, скажите

(advice-remove 'my-double #'my-increase)

Более сложный пример — отслеживание вызовов фильтра процесса процесса proc:

(defun my-tracing-function (proc string)
  (message "Proc %S received %S" proc string))

(add-function :before (process-filter proc) #'my-tracing-function)

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

(remove-function (process-filter proc) #'my-tracing-function)

Аналогично, если вы хотите отследить выполнение функции под названием display-buffer, вы можете использовать:

(defun his-tracing-function (orig-fun &rest args)
  (message "display-buffer called with args %S" args)
  (let ((res (apply orig-fun args)))
    (message "display-buffer returned %S" res)
    res))

(advice-add 'display-buffer :around #'his-tracing-function)

Здесь his-tracing-function вызывается вместо исходной функции и получает исходную функцию (в дополнение к аргументам этой функции) в качестве аргумента, так что она может вызвать её, если и когда это необходимо. Когда вы устанете от этого вывода, вы можете вернуться к поведению без отслеживания с помощью:

(advice-remove 'display-buffer #'his-tracing-function)

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

• Основные примитивы консультации Примитивы для управления консультацией.
• Консультирование именованных функций Консультирование именованных функций.
• Комбинаторы консультации Способы составления консультаций.
• Перевод старой консультации Адаптация кода, использующего старую defadvice.

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/Advising-Functions.html

Spec-Zone.ru

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