Por que preciso adicionar cada pacote ao caminho de carregamento? (ou Problema com pacote require 'no meu arquivo init)

17

Cada vez que instalo um pacote no menu Package, se eu tentar requireno meu arquivo init, recebo um erro, a menos que eu o adicione manualmente no caminho de carregamento:

(add-to-list 'load-path "/home/nick/.emacs.d/elpa/use-package-20141220.1645")

(require 'use-package-autoloads)
(require 'use-package)

Isso é entediante. E geralmente o caminho do pacote contém números de versão. Se um pacote foi atualizado, tenho que editar manualmente o caminho de carregamento.

Existe alguma maneira de automatizar isso?

usuario
fonte

Respostas:

23

TL; DR:

Adicione a seguinte linha ao topo do seu arquivo init ( .emacs.d/init.elou .emacs):

(package-initialize)

A explicação

Criar mais arquivos que o Emacs pode usar como user-init-filedefinitivamente não é a abordagem correta. Como o manual não diz qual é o preferido no caso de um conflito, pelo menos não na parte que você citou, tudo o que isso faz é adicionar confusão - agora não sabemos qual é realmente user-init-file((cujo valor você pode querer inspecionar para descobrir).

Portanto, comece removendo todos os candidatos, exceto o ~/.emacs.d/init.elque geralmente é preferido (pelos usuários), porque não contribui para a bagunça profana que é $HOMEe permite manter todos os arquivos de configuração do Emacs, incluindo o mais importante, sob controle de versão usando um repositório apenas para Emacs.

Por padrão, o Emacs chama package-initialize após o carregamento do arquivo init do usuário. Fá-lo em tudo , porque hoje em dia a maioria dos usuários instalar seus pacotes usando package.el- para que eles não deveriam ter que fazer qualquer coisa para estes pacotes a serem disponibilizados.

Por outro lado, nem todo mundo faz, por isso deve ser possível não ligar package-initialize. Impedir que essa função seja chamada é feito adicionando (setq package-enable-at-startup nil)ao arquivo init do usuário (onde mais você poderia colocá-lo?).

package-initializenão pode ser chamado antes que o usuário tenha uma alteração para dizer ao Emacs para não fazê-lo, e isso deve ser feito após o carregamento do arquivo init. Desde que o usuário instale apenas pacotes e os use como estão ou os personalize, usando a interface Personalizada que funciona bem. Mas se você quiser personalizar seus pacotes usando o elisp, precisará certificar-se de que eles estejam realmente ativos load-pathantes de usar as funções que eles definem.

É muito fácil de fazer e documentado adequadamente (se eu tivesse pesquisado isso primeiro, não teria que escrever a maioria dos itens acima: - /

O motivo pelo qual o carregamento automático de pacotes ocorre após o carregamento do arquivo init é que as opções do usuário somente recebem seus valores customizados após o carregamento do arquivo init, incluindo as opções do usuário que afetam o sistema de empacotamento. Em algumas circunstâncias, convém carregar pacotes explicitamente no seu arquivo init (geralmente porque algum outro código no arquivo init depende de um pacote). Nesse caso, o arquivo de inicialização deve chamar a função package-initialize. Cabe a você garantir que as opções relevantes do usuário, como package-load-list(veja abaixo), sejam configuradas antes da package-initializechamada. Você também deve definir package-enable-at-startupcomonil, para evitar carregar os pacotes novamente após o processamento do arquivo init. Como alternativa, você pode optar por inibir completamente o carregamento de pacotes na inicialização e chamar o comando `Mx package-initialize 'para carregar seus pacotes manualmente.

Então:

;;; .emacs.d/init.el -- the `user-init-file'

(package-initialize)
(setq package-enable-at-startup nil)

(require 'use-package)

(use-package some-package
  :init (setq some-package-variable "foobar")

    ...

;;; .emacs.d/init.el ends here

É claro que o problema (ou um problema adicional) também pode ser que o erro de digitação Symbol's function definition is void: use-packgeesteja no seu arquivo init e não aconteceu até que você o tenha digitado no emacs.se.

tarso
fonte
1
Também coberto em stackoverflow.com/questions/11127109/…
phils
Está tudo bem em usar (require 'use-package)antes (package-initialize)?
陳力
3

Eu acho que a after-init-hooksolução mencionada nesta resposta de estouro de pilha deve ser mencionada:

(defun my-packages-init ()
  (require 'some-great-package))

(add-hook 'after-init-hook 'my-packages-init)

Eu pensei que era assim que deveria ser feito, mas as outras respostas fornecem informações sobre outras maneiras de fazê-lo.

Nome de usuário significativo
fonte
0

A seguir, todos os diretórios são adicionados ~/.emacs.d/site-lispao caminho de carregamento, para que você possa apenas requireo pacote e pronto:

(let* ((my-lisp-dir "~/.emacs.d/site-lisp/")
       (default-directory my-lisp-dir)
       (orig-load-path load-path))
  (setq load-path (cons my-lisp-dir nil))
  (normal-top-level-add-subdirs-to-load-path)
  (nconc load-path orig-load-path))
Adobe
fonte