I noticed today that Emacs For Mac OS X (installed via Homebrew) doesn’t include /usr/local/share/emacs/site-lisp in the load-path, but Homebrew still installs Emacs packages in this path. It’s an easy fix to add this to your initialisation:

(let ((default-directory  "/usr/local/share/emacs/site-lisp"))
  (normal-top-level-add-subdirs-to-load-path))

You shouldn’t need to do this for Emacs in Linux installation. So you might want to wrap this in (when (eq system-type 'darwin) ...).

Aside 1: Lexical binding is so powerful

If you don’t know what lexical binding is, I’d recommend you read about it. Here we define the variable default-directory, but this value only exists within this binding (i.e. calling normal-top-level-add-subdirs-to-load-path). Any value that existed prior to this command still remains outside of this construct.

What this means is that we can set variables for specific cases, without worrying if they exist elsewhere, trying to remember to set them to the previous values after we do something, or anything like that. Powerful stuff.

Aside 2: Repeatedly adding the same directory?

If you do something like this in your shell (bash/zsh/…)

export PATH=/my/new/path:$PATH
# something
export PATH=/my/new/path:$PATH

you will get two copies of /my/new/path in your path. From painful experience this can get out-of-hand when you start shells within other shells…

However, it’s not a problem with normal-top-level-add-subdirs-to-load-path, only new directories get added. You can prove this to yourself by running the command above a couple of times and then looking at the value of load-path.

Or…you can see this by looking at the code.

Start with describe-function (C-h f) on normal-top-level-add-subdirs-to-load-path and then see that it calls normal-top-level-add-to-load-path which (C-h f again) which does the uniqueness check.

Again, another reason why being able to dig right into what Emacs is doing is a superpower.