Исходя из ответа на другой вопрос о новой системе рекомендаций :
В старом стиле advice.el
можно было манипулировать отдельными членами списка аргументов рекомендованной функции, не делая каких-либо утверждений относительно тех членов, которыми не манипулировали. Например, следующий совет:
(defadvice ansi-term (around prompt-for-name last)
(let ((name (read-from-minibuffer "Tag: ")))
(and (not (string= name ""))
(ad-set-arg 1 (concat "Term: " name)))
ad-do-it))
разрешает (необязательное) предоставление аргумента имени буфера для ansi-term
вызова, в то время как ansi-term
все еще будет получать свой первый аргумент, запрашивая в соответствии с его собственной интерактивной формой.
(Для дальнейшего использования, ansi-term
подпись есть (PROGRAM &optional BUFFER-NAME)
, и ее интерактивная форма запрашивает PROGRAM с несколькими возможными значениями по умолчанию, но ничего не делает в отношении BUFFER-NAME.)
Я не уверен, возможно ли это в nadvice.el
. Если это так, я не уверен, как это можно сделать. Я нашел несколько способов заменить список аргументов рекомендованной функции.
Например, из * info * (elisp) Советы комбинаторов :
`:filter-args' Call FUNCTION first and use the result (which should be a list) as the new arguments to pass to the old function. More specifically, the composition of the two functions behaves like: (lambda (&rest r) (apply OLDFUN (funcall FUNCTION r)))
Другие комбинаторы предоставляют аналогичные возможности, и общий поток среди них состоит в том, что, хотя список аргументов функции можно заменять, усекать, расширять и т. Д., Для совета функции нет очевидного способа изменить аргумент в данной позиции в списке без утверждая что-нибудь об остальном .
В рассматриваемом случае автору совета представляется невозможным передать ansi-term
только имя буфера, поскольку невозможно создать список, который имеет значение в позиции 1, но ничего, даже nil
в позиции 0. В общем случае автору совета представляется невозможным произвольно изменить аргументы за пределами позиции 0.
Это кажется прискорбным в том смысле, что для получения аналогичного эффекта необходимо скопировать и вставить код: в частности, я могу скопировать ansi-term
интерактивную форму и расширить ее по своему вкусу, или я могу скопировать ansi-term
и расширить ее аналогичным образом. В любом случае, теперь я должен переопределить часть дистрибутива Emacs Lisp в моем файле инициализации, что мне кажется нежелательным с точки зрения как долговечности, так и эстетики.
Мой вопрос, таким образом, заключается в следующем: можно ли сделать такого рода искажение списка аргументов nadvice.el
? Если так, то как?
Ответы:
Напротив, я думаю, что было бы неплохо скопировать и вставить интерактивную форму рекомендованной функции, даже если вам нет необходимости делать это здесь.
Я читаю ваш вопрос сверху вниз. Когда я добрался до блока кода, я догадался, что ваш совет, вероятно , меняет имя буфера. Но я не знал, пока вы позже не предоставили подпись в качестве комментария.
На самом деле ничто не меньше, чем ничто. :-) Но это вряд ли актуально здесь.
Как видно из приведенной вами документации, значение, возвращаемое рекомендацией, используется в качестве аргументов для рекомендуемой функции. Возвращаемое значение должно быть списком всех аргументов, а не только тех, которые были изменены.
Оставаясь как можно ближе к старому совету, вот что вам нужно сделать, используя
nadvice
:Но я рекомендую вместо этого определить этот совет:
Этот вариант на самом деле не требует пояснений.
источник
args
список в случае вызова, как(ansi-term "foo")
, иначе,(setf (nth 1 args)...
возникнет ошибка.buffer-name
это обязательно.:filter-args
advice получает единственный аргумент, который представляет собой список аргументов для функции advised, поэтому 1-й вариант должен быть отброшен,&rest
а 2-й вариант должен будет использовать какую-то конструкцию деструктуризации для получения хороших имен.Вот как я это сделаю:
в то время как я был тем, кто представил,
:filter-args
лично я нахожу это редко удобным.источник