Na sequência de uma resposta a outra pergunta sobre o novo sistema de aconselhamento :
No estilo antigo advice.el
, era possível manipular membros individuais da lista de argumentos de uma função aconselhada, sem fazer nenhuma afirmação sobre os membros não tão manipulados. Por exemplo, o seguinte conselho:
(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))
permite o fornecimento (opcional) de um argumento de nome de buffer para uma ansi-term
chamada, enquanto ansi-term
ainda obtém seu primeiro argumento solicitando de acordo com sua própria forma interativa.
(Para referência posterior, ansi-term
a assinatura é (PROGRAM &optional BUFFER-NAME)
e seu formulário interativo solicita PROGRAM com vários padrões possíveis, mas não faz nada em relação ao BUFFER-NAME.)
Não sei se isso é possível ou não nadvice.el
. Se for, não tenho certeza de como isso pode ser feito. Encontrei algumas maneiras de substituir a lista de argumentos de uma função recomendada.
Por exemplo, de * info * (elisp) combinadores de conselhos :
`: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)))
Outros combinadores fornecem recursos semelhantes, e a linha comum entre eles é que, embora a lista de argumentos de uma função possa ser substituída, truncada, estendida etc., não há maneira aparente para o aconselhamento de funções modificar o argumento em uma determinada posição na lista sem afirmando qualquer coisa sobre o resto .
No caso em discussão, parece impossível para o autor do conselho passar ansi-term
apenas um nome de buffer, porque não é possível construir uma lista que tenha um valor na posição 1, mas nada, nem mesmo nil
na posição 0. No caso geral, parece impossível para o autor do conselho modificar arbitrariamente argumentos além da posição 0.
Isso parece lamentável, pois, para produzir um efeito semelhante, é necessário copiar e colar o código: especificamente, ou eu posso copiar ansi-term
o formulário interativo e estendê-lo ao meu gosto, ou posso copiar ansi-term
completamente e estendê-lo da mesma forma. Nos dois casos, agora devo redefinir parte da distribuição Emacs Lisp no meu arquivo init, o que me parece indesejável em termos de durabilidade e estética.
Minha pergunta, então, é: esse tipo de lista de argumentos pode ser confundido nadvice.el
? Se sim, como?
Respostas:
Pelo contrário, acho que seria uma boa ideia copiar e colar a forma interativa da função recomendada, mesmo que você não precise fazer isso aqui.
Eu li sua pergunta de cima para baixo. Quando cheguei ao bloco de código, imaginei que seu conselho provavelmente estivesse mudando o nome do buffer. Mas eu não sabia até que você mais tarde forneceu a assinatura como um comentário.
De fato, nada é menos nada que nada. :-) Mas isso não é relevante aqui.
Como você pode ver na documentação que você citou, o valor retornado pelo aviso é usado como argumento para a função recomendada. O valor de retorno deve ser uma lista de todos os argumentos, não apenas os que foram alterados.
Ficando o mais próximo possível do conselho antigo, é isso que você precisa fazer usando
nadvice
:Mas eu recomendo que você defina o conselho como este:
Essa variante, na verdade, é auto-explicativa.
fonte
args
lista em caso de uma chamada como(ansi-term "foo")
, ou isso(setf (nth 1 args)...
geraria um erro.buffer-name
é obrigatório.:filter-args
conselho obtém um único argumento, que é uma lista de argumentos para a função recomendada, portanto a 1ª variante deve cair&rest
e a 2ª variante precisaria usar algum tipo de construção de desestruturação para obter nomes legais.Aqui está como eu faria isso:
enquanto fui eu quem apresentou
:filter-args
, pessoalmente acho raramente conveniente.fonte