Як я можу використовувати надвисоку?


29

У мого конфігурації повно порад, і я постійно чую про новий блискучий мінімалістичний nadvice.elпакет.

Я шукав посібники, і читав джерело , але відкрито визнаю: я все ще не маю уявлення, як насправді ним користуватися.

Хтось тут може вказати мені на путівник чи розповісти, як почати переносити поради в старому стилі?


7
+1 для запитання. Якщо ви шукали керівництва і не знайшли те , що вам потрібно, будь ласка , розглянути питання про подання (DOC) повідомлення про помилку: M-x report-emacs-bug. Деякі розробники іноді віддають перевагу розробці над документуванням. ;-) Важливо, щоб Emacs документував сам.
Дрю

2
Посібник насправді має розділ про це, див. (Інформація "(elisp) Перенесення старих порад") . Не вказується в детальному індексі з будь-якої причини.
wasamasa


3
Кілька прикладів використання nadviceз моєї конфігурації: : після того, як , : фільтр зворотного , : навколо , : до того , поки
Kaushal Моді

1
@wasamasa Боюся, що розділ ще далеко не завершений. У мене є кілька порад (можливо, лише один, ми побачимо), які є складнішими. Чи варто просто задати питання для кожного тут?
PythonNut

Відповіді:


22

Вся необхідна інформація міститься в C-h f add-functionякій описується основний механізм роботи advice-add.

Нова система порад в основному діє як заміна поточного визначення функції функцією, описаною в таблиці в C-h f add-function, залежно від вашого вибору WHERE аргументу, лише чистішою для того, щоб відстежувати, яка поведінка була визначена в якому вихідному файлі.

Приклад з :aroundваріантом

Найбільш загальним випадком є :aroundваріант, тому я наводжу приклад для цього. (Можливо, краще використовувати виділені WHEREпараметри, коли це можливо, але ви можете замінити один одного на еквівалентну :aroundфункцію).

Як приклад, скажемо, що ви хочете налагодити деяке використання find-file та хочете в printйого аргументальний список кожного разу, коли він викликається. Ви могли написати

(defun my-find-file-advice-print-arguments (old-function &rest arguments)
  "Print the argument list every time the advised function is called."
  (print arguments)
  (apply old-function arguments))

(advice-add #'find-file :around #'my-find-file-advice-print-arguments)

З цією новою реалізацією все необхідне поради передається як аргумент. ad-get-argsстає непотрібним, оскільки аргументи передаються функції поради як нормальні аргументи функції (для WHEREаргументів, для яких це має сенс). ad-do-itстає непотрібним, оскільки :aroundпорада отримує як аргументи функцію та аргументи, тому (ad-do-it)її замінюють формою

(apply old-function arguments)

або коли ви назвали аргументи

(funcall old-function first-arg second-arg)

яка чистіша, оскільки ніяких магічних форм не задіяно. Змінення аргументів відбувається просто шляхом передачі змінених значень до OLD-FUNCTION.

Інші WHEREзначення

Документальний рядок add-functionмістить таблицю всіх місць для отримання порад (або "комбінаторів") та того, що вони еквівалентні, та пояснює функціональність з точки зору lambdaповедінки, еквівалентної рекомендованій функції:

`:before'       (lambda (&rest r) (apply FUNCTION r) (apply OLDFUN r))
`:after'        (lambda (&rest r) (prog1 (apply OLDFUN r) (apply FUNCTION r)))
`:around'       (lambda (&rest r) (apply FUNCTION OLDFUN r))
`:override'     (lambda (&rest r) (apply FUNCTION r))
`:before-while' (lambda (&rest r) (and (apply FUNCTION r) (apply OLDFUN r)))
`:before-until' (lambda (&rest r) (or  (apply FUNCTION r) (apply OLDFUN r)))
`:after-while'  (lambda (&rest r) (and (apply OLDFUN r) (apply FUNCTION r)))
`:after-until'  (lambda (&rest r) (or  (apply OLDFUN r) (apply FUNCTION r)))
`:filter-args'  (lambda (&rest r) (apply OLDFUN (funcall FUNCTION r)))
`:filter-return'(lambda (&rest r) (funcall FUNCTION (apply OLDFUN r)))

(cited from `C-h f add-function')

де FUNCTION - функція поради, а OLDFUN - функція, де порада додана. Не намагайтеся зрозуміти їх усі одразу, просто виберіть WHEREсимвол, який відповідає звуку, і спробуйте зрозуміти його.

Або просто використовувати :around. Наскільки я можу сказати, єдиною перевагою використання спеціалізованих WHEREs over :aroundдля всього є те, що ви отримуєте трохи більше інформації, шукаючи до C-h f ADVISED-FUNCTION того, як прочитати доктрину поради. Якщо ви не плануєте публікувати код, що містить поради, це, мабуть, не має значення.

Названі функції поради

Я рекомендую використовувати названі функції як пораду, оскільки це надає багато переваг (деякі з них стосуються також використання названих функцій для гачків):

  • Він відображається C-h f find-fileяк

    :around advice: `my-find-file-advice-print-arguments'
    

    посилання на визначення функції поради, яка, як правило, містить посилання на файл, де він був визначений. Якби порада була визначена як lambdaформа безпосередньо у advice-add формі, докстринг відображатиметься в рядку (безлад для довгих доктрингів?), І ніщо б не вказувало, де воно було визначене.

  • Можна видалити поради за допомогою

    (advice-remove #'find-file #'my-find-file-advice-print-arguments)
    
  • Ви можете оновити визначення поради, не відкладаючи advice-addабо не ризикуючи підтримувати стару версію активною (оскільки запущена advice-addзі зміною lambdaбуде визнана новою порадою, а не як оновлення до старої).

Бічне зауваження#'function позначення в основному еквівалентно 'function, за винятком того, що він допомагає байтам компілятору визначити символи, імена функцій і , таким чином , щоб виявити відсутні функції (наприклад , з - за помилки).


Відповідно до дискусії, яку я мав зі Стівеном Моньє, тут не слід застосовувати хеш-цитати у всіх аргументах. Це повинно бути (advice-add 'find-file :around #'my-find-file-advice-print-arguments)і так само (advice-remove 'find-file #'my-find-file-advice-print-arguments).
Каушал Моді

Я думаю advice-add, це прикордонний випадок. Особисто я розглядаю ' ↔ #'розмежування, як правило, допомогу для виявлення помилок друку у назвах функцій, тому тут, мабуть, залежатиме від того, чи очікується, що функція буде визначена до моменту додавання поради.
kdb

@kdb Я врешті-решт з’ясував це для себе (після того, як я наткнувся на документи для add-function). Я хочу, щоб документи зробили це зрозуміліше. Я можу поглянути на те, щоб зробити патч для цього.
PythonNut

@kdb Ви маєте на увазі "Це з'являється в C-h f find-file, ні C-x?
Peeja

@Peeja Так, виправили це.
kdb
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.