¿Por qué tengo que agregar cada paquete a load-path? (o Problema con el paquete require 'en mi archivo init)

17

Cada vez que instalo un paquete desde el menú Paquete, si lo intento requireen mi archivo de inicio, aparece un error a menos que lo agregue manualmente a la ruta de carga:

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

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

Eso es tedioso Y generalmente la ruta del paquete contiene números de versión. Si se actualizó un paquete, tengo que editar manualmente la ruta de carga.

¿Hay alguna forma de automatizar esto?

Mella
fuente

Respuestas:

23

TL; DR:

Agregue la siguiente línea en la parte superior de su archivo de inicio ( .emacs.d/init.elo .emacs):

(package-initialize)

La explicación

Crear más archivos que Emacs podría usar como user-init-filedefinitivamente no es el enfoque correcto. Debido a que el manual no dice cuál es el preferido en caso de que haya un conflicto, al menos no en la parte que citó, todo lo que hace es agregar confusión; ahora no sabemos cuál es realmente user-init-file(cuyo valor puede desear) inspeccionar para averiguarlo).

Comience por eliminar a todos los candidatos, excepto el ~/.emacs.d/init.elque generalmente es preferido (por los usuarios) porque no contribuye al desorden impuro que es $HOMEy permite mantener todos los archivos de configuración de Emacs, incluido el más importante, bajo control de versiones utilizando un repositorio solo para Emacs

Por defecto, Emacs llama package-initialize después de cargar el archivo init del usuario. Lo hace en absoluto , porque hoy en día la mayoría de los usuarios instalan sus paquetes utilizando package.el, por lo que no deberían tener que hacer nada para que estos paquetes estén disponibles.

Por otro lado, no todos lo hacen, por lo que debería ser posible no llamar package-initialize. Para evitar que se invoque esa función, se agrega (setq package-enable-at-startup nil)al archivo de inicio del usuario (¿dónde más podría ponerlo?).

package-initializeno se puede llamar antes de que el usuario haya realizado un cambio para decirle a Emacs que no lo haga, por lo que debe hacerse después de cargar el archivo init. Siempre que el usuario solo instale paquetes y luego los use tal cual o los personalice utilizando la interfaz personalizada que funciona bien. Pero si desea personalizar sus paquetes usando elisp, entonces debe asegurarse de que realmente estén en el load-pathantes de usar las funciones que definen.

Eso es bastante fácil de hacer y está debidamente documentado (si hubiera buscado eso primero, no habría tenido que escribir la mayoría de lo anterior: - /

La razón por la que se carga el paquete automáticamente después de cargar el archivo init es que las opciones del usuario solo reciben sus valores personalizados después de cargar el archivo init, incluidas las opciones del usuario que afectan el sistema de empaque. En algunas circunstancias, es posible que desee cargar paquetes explícitamente en su archivo de inicio (generalmente porque algún otro código en su archivo de inicio depende de un paquete). En ese caso, su archivo init debería llamar a la función package-initialize. Depende de usted asegurarse de que las opciones de usuario relevantes, como package-load-list(ver más abajo), estén configuradas antes de la package-initializellamada. También debe establecer package-enable-at-startupennil, para evitar cargar los paquetes nuevamente después de procesar el archivo init. Alternativamente, puede optar por inhibir por completo la carga de paquetes al inicio e invocar el comando 'Mx package-initialize' para cargar sus paquetes manualmente.

Entonces:

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

Por supuesto, el problema (o un problema adicional) también podría ser que el error tipográfico Symbol's function definition is void: use-packgeestá en su archivo de inicio y no ocurrió hasta que lo escribió en emacs.se.

tarsius
fuente
1
También cubierto en stackoverflow.com/questions/11127109/…
phils
¿Está bien usarlo (require 'use-package)antes (package-initialize)?
陳 力
3

Creo que la after-init-hooksolución mencionada en esta respuesta de desbordamiento de pila debería mencionarse:

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

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

Pensé que esta era la forma en que se suponía que debía hacerse, pero las otras respuestas proporcionan información sobre otras formas de hacerlo.

Nombre de usuario significativo
fuente
0

A continuación, se agregan todos los directorios ~/.emacs.d/site-lispa la ruta de carga, para que pueda simplemente requireel paquete y listo:

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