Onde devo incluir uma inicialização lenta?

13

Quero adicionar uma ligação de chave específica ao modo látex:

(define-key latex-mode-map (kbd "<f6>") 'my-latex-defun)

Ao mesmo tempo, desejo defini-lo apenas quando o modo específico estiver carregado. Então, eu gostaria de saber se há uma preferência (melhor prática) entre usar o hook apropriado ( latex-mode-hook) para fazer isso ou usar a cláusula (with-eval-after-load "tex-mode" ...para quebrar a definição de ligação de chave. Eu testei os dois e eles funcionam bem, mas me pergunto qual é o caminho certo para fazê-lo.

jrbalderrama
fonte
2
with-eval-after-loadé carregado uma vez , portanto, uma alteração no mapa de teclas é executada lá. Os ganchos são carregados toda vez que o modo é executado , por exemplo, ao carregar um novo arquivo associado ao modo ou, no entanto, o gancho é definido. Você carregaria, por exemplo, flyspell-modeou hl-line-modeem um gancho. No meu init.eleu uso with-eval-after-loadaproximadamente 160 vezes e add-hook110 vezes. Um init lento é um bom init (IMO).
Rasmus
@rasmus soa como uma resposta se você tiver tempo :) A distinção de quantas vezes o código é executado é a principal a considerar, na minha opinião. (É também o único que eu posso pensar ...)
Sean Allred
Por isso é uma má idéia para mudar teclas em ganchos modo de ver emacs.stackexchange.com/questions/990/...
tarsius

Respostas:

18

Um init preguiçoso é um bom init.

(IMO)

Quando usar with-eval-after-load

with-eval-after-loadé carregado uma vez quando um determinado recurso ou arquivo é carregado pela primeira vez, portanto, uma alteração no mapa de teclas entra claramente em um deles. Não menos importante, porque o mapa de teclas pode não ser conhecido no momento do início [tente algo como (define-key message-mode-map (kbd "C-c f") 'Footnote-add-footnote)em emacs -q]. Um gancho não é uma solução agradável aqui, pois vincula a função a uma chave toda vez que o gancho é iniciado. Como tarsius notas, você pode ler mais sobre por que não para local-set-keyem ganchos.

Finalmente, observe que o with-eval-after-loadGNU Emacs 24.4 é um wrapper de 2 linhas em torno do eval-after-loadqual bodynão precisa ser citado.

Quando usar ganchos

Ganchos são uma lista de funções carregadas toda vez que um critério é atendido, por exemplo, um determinado modo é iniciado. Um uso comum de ganchos é carregar modos menores, como flyspell-modeou hl-line-mode. Por exemplo (add-hook 'org-agenda-mode-hook 'hl-line-mode). Como Rémi aponta, add-hooksé inteligente e fará a coisa certa, mesmo que a variável hook ainda não tenha sido carregada. No entanto, tenho muitas cláusulas como as seguintes, que podem ser insignificantes para ganhos de velocidade, mas fornecem um senso de organização e estrutura de dependência:

(with-eval-after-load 'org-agenda
  (add-hook 'org-agenda-mode-hook 'hl-line-mode))

Por que adicionar ao gancho depois org-agenda? Como sempre, C-h v org-agenda-mode-hook C-jentrega. O gancho é definido org-agenda.elcomo mostrado em *help*.

Carregando recursos extras with-eval-after-load

with-eval-after-loadtambém é importante para carregar recursos extras. Você provavelmente desejaria algo como (with-eval-after-load 'org (require 'org-inlinetask))carregar inlinetasks org. Para ver o porquê (find-library "org-inlinetask"). Como org-inlinetasks.eldiretamente (require 'org), todo o bom autoloadque seus amigáveis ​​mantenedores do Emacs tomaram muito cuidado para fornecer será "ignorado" e todos org.el(c)serão carregados.

Mas e se o seu (pessoal) defunfor necessário em vários lugares? Se você é realmente exigente, pode colocar os defuns em outro arquivo no seu load-pathe adicionar autoloadcookies, ou pode dizer ao Emacs onde encontrar a função com a autoloadfunção. Então algo assim funcionaria:

(autoload 'org-cdlatex-mode "org" "cdlatex mode from org.")
(with-eval-after-load "latex"
  (add-hook 'TeX-mode-hook 'org-cdlatex-mode))

Ou você poderia require org, por sua vez, puxarcdlatex

E, honestamente, o desânimo pessoal não importa muito para o tempo de inicialização na maioria das vezes. As 1150 linhas de desajustes pessoais (84 desajustados) nos meus init.eladicionam 0,02s sobre o Emacs de baunilha.

Medindo o tempo de inicialização

Uma maneira fácil de aproximar o tempo de inicialização é

time emacs --eval "(kill-emacs)"

(referência contra emacs -q.

Mas, para obter uma aproximação mais detalhada de onde estão os gargalos de inicialização, consulte Joe Schafer esup.

Finalmente, o tempo de carregamento não desaparece magicamente. Você está apenas avançando (na medida em que você usa todos os recursos em cada sessão).

rasmus
fonte
1
Você não precisa colocar o add-hook em um with-eval-after-load, porque o add-hook vincula a variável se ela ainda não estiver lá.
Rémi 27/10
Você está certo! Ainda poderia haver ganhos de velocidade com isso? [Vou tentar atualizar a resposta mais tarde para refletir essa]
Rasmus
E quanto aos desajustes que mais tarde eu gostaria de vincular a um gancho ou a uma chave. Devo definir um desfecho fora do with-eval-after-loadsem perder vantagens de inicialização lenta?
Jrbalderrama # 27/14
5

Além de suas sugestões eval-after-loade uso de um gancho, deixe-me sugerir use-package.el. Você pode fazer o que precisar com

(use-package latex
  :ensure auctex
  :bind ("<f6>" . my-latex-defun))

LaTeX não será carregado até depois de você solicitar.

Apenas como uma observação lateral: o uso cuidadoso de use-packagereduziu meus tempos de inicialização para menos de um segundo. (Demorava cerca de quatro segundos.)

Sean Allred
fonte
Obrigado pela sua sugestão. Também considerei usar o pacote de uso, mas realmente quero descobrir como fazê-lo sem pacotes adicionais.
Jrbalderrama # 26/14
1
@jrbalderrama note que use-packageestá programado para ser lançado com o Emacs 25. #
456 Sean Allred