user1017523
user1017523

Reputation:

Emacs - Require All Files In a Directory

I am familiar with load-path and require, but I was wondering if I can consolidate the multiple require statements in my init.el into some kind of loop, ultimately doing something like require-ing all the files in a given directory.

Is there any way to do this? Or should I keep it as it is, with multiple require statements?

Upvotes: 5

Views: 2376

Answers (3)

phils
phils

Reputation: 73274

I agree with Drew that you want to use load in this situation. This function is based on Drew's code, with a few tweaks to avoid re-loading a library when both .el and .elc versions are present.

(defun my-load-all-in-directory (dir)
  "`load' all elisp libraries in directory DIR which are not already loaded."
  (interactive "D")
  (let ((libraries-loaded (mapcar #'file-name-sans-extension
                                  (delq nil (mapcar #'car load-history)))))
    (dolist (file (directory-files dir t ".+\\.elc?$"))
      (let ((library (file-name-sans-extension file)))
        (unless (member library libraries-loaded)
          (load library nil t)
          (push library libraries-loaded))))))

Upvotes: 6

Drew
Drew

Reputation: 30699

(let ((loaded  (mapcar #'car load-history)))
  (dolist (file  (directory-files "~/.emacs.d" t ".+\\.elc?$"))
    (unless (catch 'foo
              (dolist (done  loaded)
                (when (equal file done) (throw 'foo t)))
              nil)
      (load (file-name-sans-extension file))
      (push file loaded))))
  • Use load, not require, since the feature name (from provide) is not necessarily the same as the base name of the file. Or the file might not even provide a feature.
  • Load a file only if it has not yet been loaded (or you have already tried to load it).

Upvotes: 3

You could try something like this:

(mapc (lambda (name)
        (require (intern (file-name-sans-extension name))))
      (directory-files ".emacs.d" nil "\\.el$"))

Explanation:

  1. retrieve the list of elisp files using directory-files
  2. remove extension using file-name-sans-extension
  3. get the symbol associated to the file base name using intern, and require it

Upvotes: 3

Related Questions