Pourquoi dois-je ajouter chaque package au chemin de chargement? (ou problème avec le package require dans mon fichier init)

17

Chaque fois que j'installe un package à partir du menu Package, si j'essaie de le requirefaire dans mon fichier init, j'obtiens une erreur, sauf si je l'ajoute manuellement au chemin de chargement:

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

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

C'est fastidieux. Et généralement, le chemin du package contient des numéros de version. Si un package a été mis à jour, je dois modifier manuellement le chemin de chargement.

Existe-t-il un moyen d'automatiser cela?

pseudo
la source

Réponses:

23

TL; DR:

Ajoutez la ligne suivante en haut de votre fichier init ( .emacs.d/init.elou .emacs):

(package-initialize)

L'explication

Créer plus de fichiers qu'Emacs pourrait utiliser user-init-filen'est certainement pas la bonne approche. Parce que le manuel ne dit pas ce qui est préféré en cas de conflit, du moins pas dans la partie que vous avez citée, tout cela ne fait qu'ajouter de la confusion - maintenant nous ne savons pas quelle est réellement la user-init-file(dont vous voudrez peut-être la valeur inspecter pour le découvrir).

Commencez donc par supprimer tous les candidats sauf celui ~/.emacs.d/init.elqui est généralement préféré (par les utilisateurs) car il ne contribue pas au désordre impie qui est $HOMEet il permet de garder tous les fichiers de configuration Emacs, y compris le plus important, sous contrôle de version en utilisant un référentiel juste pour Emacs.

Par défaut, Emacs appelle package-initialize après le chargement du fichier init de l'utilisateur. Il le fait du tout , car de nos jours la plupart des utilisateurs installent leurs packages en utilisant package.el- ils ne devraient donc pas avoir à faire quoi que ce soit pour que ces packages soient disponibles.

En revanche, tout le monde ne le fait pas, il devrait donc être possible de ne pas appeler package-initialize. Empêcher cette fonction d'être appelée se fait en ajoutant (setq package-enable-at-startup nil)au fichier init de l'utilisateur (où d'autre pourriez-vous le mettre?).

package-initializene peut pas être appelé avant que l'utilisateur n'ait eu une modification pour dire à Emacs de ne pas le faire, et cela doit donc être fait après le chargement du fichier init. Tant que l'utilisateur installe uniquement les packages, puis les utilise tels quels ou les personnalise à l'aide de l'interface personnalisée qui fonctionne très bien. Mais si vous souhaitez personnaliser vos packages à l'aide d'elisp, vous devez vous assurer qu'ils sont bien sur load-pathavant d'utiliser les fonctions qu'ils définissent.

C'est assez facile à faire et correctement documenté (si j'avais d'abord recherché cela, je n'aurais pas eu à écrire la plupart des éléments ci-dessus: - /

La raison du chargement automatique du package après le chargement du fichier init est que les options utilisateur ne reçoivent leurs valeurs personnalisées qu'après le chargement du fichier init, y compris les options utilisateur qui affectent le système de packaging. Dans certaines circonstances, vous souhaiterez peut-être charger explicitement des packages dans votre fichier init (généralement parce qu'un autre code dans votre fichier init dépend d'un package). Dans ce cas, votre fichier init devrait appeler la fonction package-initialize. Il vous appartient de vous assurer que les options utilisateur pertinentes, telles que package-load-list(voir ci-dessous), sont configurées avant l' package-initializeappel. Vous devez également définir package-enable-at-startupànil, pour éviter de charger à nouveau les packages après le traitement du fichier init. Alternativement, vous pouvez choisir d'inhiber complètement le chargement des packages au démarrage et invoquer la commande `Mx package-initialize 'pour charger vos packages manuellement.

Donc:

;;; .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

Bien sûr, le problème (ou un problème supplémentaire) pourrait également être que la faute de frappe se Symbol's function definition is void: use-packgetrouve dans votre fichier init et ne s'est pas produite tant que vous ne l'avez pas saisie dans emacs.se.

tarse
la source
1
Également couvert à stackoverflow.com/questions/11127109/…
phils
Est-il correct d'utiliser (require 'use-package)avant (package-initialize)?
陳 力
3

Je pense que la after-init-hooksolution mentionnée dans cette réponse de débordement de pile doit être mentionnée:

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

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

Je pensais que c'était ainsi que cela devait être fait, mais les autres réponses fournissent des informations sur d'autres façons de le faire.

Nom d'utilisateur significatif
la source
0

Ce qui suit ajoute tous les répertoires sous ~/.emacs.d/site-lispau chemin de chargement, vous pouvez donc juste requirele package et vous avez terminé:

(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
la source