This article essentially describes the top of my Emacs init file. That part of the code is devoted to modify the session bootstrap process, that is, some things that are normally done very early. It mostly deals with the package infrastructure but also contains a couple of other tricks that some people may consider useful. It goes like this…
The first line is self-explanatory (and please, be warned that I will discard any comment about it. You know why).
(require 'cl)
Platform-specific tweaks
A self-contained Emacs.app on MacOS X has its own site-lisp directory, but I want to make sure that the standard Unix one is here as well, and takes precedence.
(when (featurep 'ns) (add-to-list 'load-path "/usr/local/share/emacs/site-lisp"))
When not starting Emacs from the command-line (e.g. MacOS X app clicks or Quicksilver, Unitiy launcher on Ubuntu etc.), I don't necessarily get my environment-based exec-path so I need to restore it. Note that this trick works because the standard value is (I think) computed when Emacs is built, and I happen to build it myself, in my own environment.
(let ((standard-exec-path (cadar (get 'exec-path 'standard-value)))) (mapc (lambda (path) (setq exec-path (remove path exec-path))) standard-exec-path) (setq exec-path (append standard-exec-path exec-path)))
ELPA infrastructure
Initialize ELPA now so that the rest of the initialization process may rely on packages without having to go through after-init-hook.
(require 'package)
I want system-wide directories to be named emacs-packages instead of site-lisp/elpa.
(setq package-directory-list (let (result) (dolist (path load-path) (and (stringp path) (equal (file-name-nondirectory path) "site-lisp") (push (expand-file-name "emacs-packages" (file-name-directory (directory-file-name path))) result))) (nreverse result)))
I want my local directory to follow the same convention.
(setq package-user-dir "~/.emacs.d/emacs-packages")
Now, it's okay to initialize ELPA.
(package-initialize)
Now that the packages have been initialized, I actually want ELPA to install in /usr/local/share/emacs/emacs-packages by default, and keep my local directory for manual installations. One simple way to achieve that is to set my local directory to /usr/local/share/emacs/emacs-packages and to remove that from the system-wide directory list. One small drawback of this is that my local path is gone, so any new package installed there won't be seen until the next restart. This is not much of a problem though.
(setq package-user-dir "/usr/local/share/emacs/emacs-packages" package-directory-list (remove "/usr/local/share/emacs/emacs-packages" package-directory-list))
Site and local (non ELPA) packages infrastructure
The purpose of this other infrastructure is to support packages that would be installed manually, outside ELPA, and in a way similar to XEmacs packages. A packages directory has lisp/, etc/ and info/ subdirectories. Every package installs its stuff directly in etc/ and info/, but adds its own subdirectory to lisp/ and puts its code (including a potential autoloads file) in there.
This additional infrastructure comes in handy in several situations. For instance, having Slime (auto)loaded in your session now becomes as simple as this:
ln -s /path/to/slime /usr/local/share/emacs/local-packages/lisp/
(defun dvl-initialize-packages (directory) "Initialize non-ELPA packages DIRECTORY. This means: - adding the whole lisp/ subtree to LOAD-PATH, - loading the autoload files found there. - adding DIRECTORY to INFO-DEFAULT-DIRECTORY-LIST." (let ((default-directory (expand-file-name "lisp" directory))) ;; 1. Update LOAD-PATH (setq load-path (append (let ((load-path (copy-sequence load-path))) (append (copy-sequence (normal-top-level-add-to-load-path '("."))) (normal-top-level-add-subdirs-to-load-path))) load-path)) ;; 2. Load autoload files (loop for directory in load-path while (string-prefix-p default-directory directory) do (mapc #'load (directory-files directory t "-autoloads\\.el$")))) ;; 3. Update the default Info directory list (add-to-list 'Info-default-directory-list (expand-file-name "info" directory))) (require 'info)
Be sure to do this by increasing priority order.
(mapc #'dvl-initialize-packages `("/usr/local/share/emacs/local-packages" "~/.emacs.d/local-packages"))
And now we can re-initialize Info with the proper defaults.
(setq Info-directory-list nil) (info-initialize)
Custom settings
Now that we have bootstrapped the complete packages infrastructure, we can set the Custom file to something that makes sense and load it now.
(setq custom-file "~/.emacs.d/custom.el") (load custom-file)
That completes my session bootstrap process.