Diferença entre init e config no pacote de uso

16

Eu tenho uma configuração como esta:

(use-package html-mode
  :mode "\\.html\\'"
  :config
  (progn
    (add-hook 'html-mode-hook 'turn-off-auto-fill)))

Agora, quando visito um arquivo HTML, observo que auto-fillnão está desativado. Mas se eu usar em :initvez de :config, auto-fillserá desativado. Então, minha pergunta é quando os comandos estão sendo :configexecutados?

Sibi
fonte

Respostas:

16

Eles são diferentes se o pacote for adiado, ou seja, não carregado até que seja necessário. Nesse caso :init, será executado no momento em que seu arquivo emacs for lido pela primeira vez, mas :configserá executado no momento em que o pacote for realmente carregado.

No seu exemplo, o uso de modeimplicitamente adia o carregamento do pacote. Você configurou o pacote para ser carregado na primeira vez que um arquivo html é visitado.

Você pode usar :demandpara garantir que o pacote esteja sempre carregado na inicialização, mas é mais provável que você queira fazer isso aqui :init.

Da documentação:

:init Code to run when `use-package' form evals.

Como você está colocando isso no arquivo user-init, isso basicamente significa que ele será executado na inicialização.

:config Runs if and when package loads.

Portanto, não execute até que o pacote esteja realmente sendo carregado.

:defer Defer loading of package -- automatic if :commands, :bind, :bind*,  :mode or :interpreter are used.

Observe a lista de itens que automaticamente tornam um pacote adiado. Basicamente, se você informar use-packageas condições em que precisa deste pacote, ele pressupõe que não deseja carregá-lo até que essas condições ocorram.

:demand Prevent deferred loading in all cases.

Verifique se o pacote está carregado na inicialização, independentemente de outras opções que você especificou.

Atualizar

Revisitando isso com base nos comentários recentes ... O que eu disse acima é verdade, mas acho que não responde corretamente à pergunta. O problema raiz aqui é, na verdade, que html-modenão é um pacote, mas um modo definido pelo pacote sgml-mode. Isso funciona como esperado para mim:

(use-package sgml-mode
  :mode ("\\.html\\'" . html-mode)
  :config (add-hook 'html-mode-hook 'turn-off-auto-fill))

No exemplo original, a :configexpressão nunca é avaliada porque um pacote chamado html-modenunca é carregado. Mover a mesma expressão para :initfunciona porque o código init é sempre avaliado, independentemente de o pacote ser carregado.

glucas
fonte
@npostavs Obrigado, vale a pena notar. Ainda não mudei para o pacote de uso 2.0. Por um lado, eu uso :idlebastante extensivamente e não examinei o impacto de ": ocioso foi removido".
glucas
1
Ainda não entendo por que, quando ele visita um arquivo HTML e aciona o pacote para carregar, auto-fillnão está desativado, ou seja, o código de configuração não foi executado. Eu tenho o mesmo problema.
Ken Williams
@KenWilliams Seu problema também está no modo html? Eu acho que o problema real aqui é que html-modenão é um pacote. Pelo menos na minha versão atual do Emacs, html-modeestá definida no pacote sgml-mode. Portanto, se você pedir use-packagepara fazer alguma coisa quando um pacote nomeado html-modefor carregado, esse código nunca será executado porque esse pacote nunca será carregado. Você precisa colocar a configuração do modo html em um arquivo (use-package sgml-mode ....).
glucas
Desculpe - meu problema é com org-mode, não html-mode. Um problema semelhante é que o pacote é chamado org-mode, mas o pacote ELPA é chamado org. Talvez isso seja confuso (ou eu)?
Ken Williams
7

Este exemplo me facilitou muito a compreensão da diferença entre :inite :config. Vamos dar um exemplo de ace-windowpacote (mas pode ser qualquer pacote). Coloque isso no seu init.elarquivo:

(use-package ace-window
  :ensure t
  :defer t
  :config
  (progn
    (message "ace window: hello world")))

Agora abra o seu emacs e veja no *Messages*buffer para ver se há alguma hello worldmensagem. Você não poderá encontrar nenhum porque o pacote foi adiado. Agora mude de configpara init:

(use-package ace-window
  :ensure t
  :defer t
  :init
  (progn
    (message "ace window: hello world")))

Agora feche e reabra o emacs e inspecione o *Messages*buffer. Você verá a mensagem ace window: hello worldporque o código é executado, independentemente de quando :inité fornecido. No caso, configele será executado apenas quando esse pacote for carregado.

Sibi
fonte
isso ajuda, apenas uma questão secundária, qual é a diferença entre a palavra-chave :inite com :prefacebase no seu exemplo?
doctorado
@ doctorate: :prefaceé executado mesmo que o pacote em questão esteja desabilitado, enquanto :inité executado somente quando um pacote está habilitado.
bbenne10