Como uso nadvice?


29

Minha configuração está cheia de conselhos e continuo ouvindo sobre o novo nadvice.elpacote minimalista brilhante .

Pesquisei os manuais e li a fonte , mas admito abertamente: ainda não faço ideia de como usá-lo.

Alguém aqui pode me indicar um guia ou me dizer como começar a incluir meus conselhos de estilo antigo?


7
+1 para a pergunta. Se você já procurou os manuais e não encontrou o que você precisava, por favor considere a apresentação de uma (doc) relatório de bug: M-x report-emacs-bug. Alguns desenvolvedores às vezes preferem desenvolver do que documentar. ;-) É importante que o Emacs se documente.
— Drew

2
O manual possui uma seção sobre isso, consulte (info "(elisp) Portando conselhos antigos") . Não está listado no índice detalhado por qualquer motivo.
— wasamasa


3
Alguns exemplos usando nadvicedo meu config: : depois , : filtro de retorno , : em torno de , : antes, até
— Kaushal Modi

1
@wasamasa Receio que essa seção esteja longe de estar completa. Tenho alguns conselhos (talvez apenas um, veremos) que são mais complexos. Devo apenas fazer uma pergunta para cada um aqui?
— precisa saber é o seguinte

Respostas:


22

Todas as informações necessárias estão incluídas, C-h f add-functiondescrevendo o mecanismo subjacente de advice-add.

O novo sistema de aconselhamento basicamente age como substituir a definição atual de uma função pela função descrita na tabela em C-h f add-function, dependendo da sua escolha do WHERE argumento, apenas mais limpa para rastrear qual comportamento foi definido em qual arquivo de origem.

Um exemplo com a :aroundopção

O caso mais geral é a :aroundopção, então eu dou um exemplo para isso. (Provavelmente é melhor usar WHEREparâmetros dedicados quando possível, mas você pode substituir todos os outros por uma :aroundfunção equivalente ).

Apenas como exemplo, digamos que você queira depurar um pouco de uso find-file e queira a printsua lista de argumentos sempre que for chamada. Você poderia escrever

(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)

Com esta nova implementação, tudo o que o conselho precisa é passado como argumento. ad-get-argstorna-se desnecessário, porque os argumentos são passados ​​para o conselho funcionam como argumentos de função normal (para WHEREargumentos para os quais faz sentido). ad-do-ittorna-se desnecessário à medida que o :aroundconselho obtém como argumentos a função e os argumentos, (ad-do-it)sendo substituído pelo formulário

(apply old-function arguments)

ou quando você nomeou os argumentos

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

o que é mais limpo, pois não há formas mágicas envolvidas. A modificação dos argumentos simplesmente acontece passando valores modificados para OLD-FUNCTION.

Outros WHEREvalores

A documentação de add-functioncontém uma tabela de todos os locais de aconselhamento (ou "combinadores") e o que eles equivalem e explica a funcionalidade em termos de um lambdacomportamento equivalente à função recomendada:

`: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')

onde FUNCTION é a função de aconselhamento e OLDFUN a função em que o conselho é adicionado. Não tente entender todos eles de uma só vez, basta selecionar um WHEREsímbolo que pareça adequado e tentar entendê-lo.

Ou apenas use :around. Tanto quanto posso dizer, a única vantagem de usar WHEREs especializados :aroundpara tudo é que você obtém um pouco mais de informações C-h f ADVISED-FUNCTION antes de ler a documentação do conselho. A menos que você planeje publicar o código que contém os conselhos, provavelmente não importa.

Funções de aconselhamento nomeadas

Recomendo o uso de funções nomeadas como orientação, pois oferece muitas vantagens (algumas também se aplicam ao uso de funções nomeadas para ganchos):

  • Ele aparece C-h f find-filecomo

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

    link para a definição da função de aconselhamento, que normalmente contém um link para o arquivo em que foi definido. Se o conselho tivesse sido definido como um lambdaformulário diretamente no advice-add formulário, a doutrina seria mostrada em linha (uma bagunça para longas doutrinas?) E nada indicaria onde foi definida.

  • Você pode remover o aviso com

    (advice-remove #'find-file #'my-find-file-advice-print-arguments)
    
  • Você pode atualizar a definição do aviso sem executar novamente advice-addou arriscar para manter a versão antiga ativa (a execução de advice-adduma alteração lambdaserá reconhecida como novo aviso, não como uma atualização do antigo).

Observação lateral A #'functionnotação é basicamente equivalente a 'function, exceto que ajuda o compilador de bytes a identificar símbolos como nomes de funções e, assim, a identificar funções ausentes (por exemplo, devido a erros de digitação).


De acordo com a discussão que tive com Stephen Monnier, aspas não devem ser usadas aqui em todos os argumentos. Deve ser (advice-add 'find-file :around #'my-find-file-advice-print-arguments)e da mesma forma (advice-remove 'find-file #'my-find-file-advice-print-arguments).
— Kaushal Modi

Eu acho que advice-addé um caso de fronteira. Pessoalmente, considero a ' ↔ #'distinção principalmente uma ajuda para identificar erros de digitação nos nomes das funções; portanto, aqui provavelmente dependeria de se esperar que a função seja definida no momento em que o conselho é adicionado.
— Kdb

@kdb Acabei descobrindo isso por mim mesmo (depois de me deparar com os documentos para add-function). Eu gostaria que os documentos deixassem isso mais claro. Eu posso tentar fazer um patch para isso.
— precisa saber é o seguinte

@kdb Você quer dizer "Ele aparece C-h f find-file, não é C-x?
— Peeja

@Peeja Sim, corrigiu.
— Kdb 30/03/16
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.