19

Each time I install a package from the Package Menu, if I try to require it in my init file I get an error unless I manually add it to the load-path:

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

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

That's tedious. And usually the package path contains version-numbers. If a package was updated, I have to manually edit the load-path.

Is there any way to automate this?

0

3 Answers 3

25

TL;DR:

Add the following line to the top of your init file (.emacs.d/init.el or .emacs):

(package-initialize)

The explanation

Creating more of the files which Emacs might use as the user-init-file is definitely not the right approach. Because the manual doesn't say which is preferred in case there is a conflict, at least not in the part you quoted, all this does is to add confusion - now we don't know which actually is the user-init-file (whose value you might want to inspect to find out).

So start by removing all candidates except ~/.emacs.d/init.el which is generally preferred (by users) because it doesn't contribute to the unholy mess that is $HOME and it allows keeping all Emacs configuration files, including the most important one, under version control using a repository just for Emacs.

By default Emacs calls package-initialize after the user's init file has been loaded. It does so at all, because nowadays most users install their packages using package.el - so they should not have to do anything for these packages to be made available.

On the other hand not everybody does, so it should be possible to not call package-initialize. Preventing that function from being called is done by adding (setq package-enable-at-startup nil) to the user's init file (where else could you put it?).

package-initialize cannot be called before the user had a change to tell Emacs not to do it, and so it has to be done after loading the init file. As long as the user only installs packages and then uses them as-is or customizes them using the Custom interface that works just fine. But if you want to do customize your packages using elisp then you do have to make sure they are actually on the load-path before using functions they define.

That's quite easy to do and properly documented (if I had looked that up first, I wouldn't have had to write most of the above :-/

The reason automatic package loading occurs after loading the init file is that user options only receive their customized values after loading the init file, including user options which affect the packaging system. In some circumstances, you may want to load packages explicitly in your init file (usually because some other code in your init file depends on a package). In that case, your init file should call the function package-initialize. It is up to you to ensure that relevant user options, such as package-load-list (see below), are set up prior to the package-initialize call. You should also set package-enable-at-startup to nil, to avoid loading the packages again after processing the init file. Alternatively, you may choose to completely inhibit package loading at startup, and invoke the command `M-x package-initialize' to load your packages manually.

So:

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

Of course the problem (or an additional problem) could also be that the typo in Symbol's function definition is void: use-packge is in your init file and did not not happen until you typed it into emacs.se.

2
3

I think the after-init-hook solution mentioned in this stack overflow answer should be mentioned:

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

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

I thought this was the way it was supposed to be done, but the other answers provide information on other ways to do it.

1

The following adds all dirs under ~/.emacs.d/site-lisp to load path, so you can just require the package and you are done:

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.