15

If I have a folder structure set up like this:

~/Projects
    emacs
        package1
            package1-helpers
        package2
            package2-helpers
            package2-more-helpers
        package3
            package3-helpers

How do I add these folders:

  • ~/Projects/emacs
  • ~/Projects/emacs/package1
  • ~/Projects/emacs/package2
  • ~/Projects/emacs/package3

...to the load-path from my .emacs file?

I basically need a short automated version of this code:

(add-to-list 'load-path "~/Projects/emacs")
(add-to-list 'load-path "~/Projects/emacs/package1")
(add-to-list 'load-path "~/Projects/emacs/package2")
(add-to-list 'load-path "~/Projects/emacs/package3")
Alexander Kojevnikov
  • 17,580
  • 5
  • 49
  • 46

6 Answers6

18
(let ((base "~/Projects/emacs"))
  (add-to-list 'load-path base)
  (dolist (f (directory-files base))
    (let ((name (concat base "/" f)))
      (when (and (file-directory-p name) 
                 (not (equal f ".."))
                 (not (equal f ".")))
        (add-to-list 'load-path name)))))
Jouni K. Seppänen
  • 43,139
  • 5
  • 71
  • 100
  • Thanks Jouni! Unfortunately I receive an error: "An error has occurred while loading `c:/Users/Alex/AppData/Roaming/.emacs': Symbol's function definition is void: do". I have Emacs 22.2.1 running under Vista. – Alexander Kojevnikov Oct 21 '08 at 12:05
  • Oops - "do" is in cl.el, so you can make the original suggestion work by adding "(require cl)" in the beginning. But I modified the answer to use dolist, which both makes it simpler and avoids the need for cl.el. – Jouni K. Seppänen Oct 21 '08 at 13:02
10

Here's something I use in my .emacs:

(let* ((my-lisp-dir "~/.elisp/")
       (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))

If you look at the description for normal-top-level-add-subdirs-to-load-path, it's somewhat smart about picking which directories to exclude.

Nicholas Riley
  • 43,532
  • 6
  • 101
  • 124
5

I suggest you to use subdirs.el

link0ff
  • 2,744
  • 1
  • 22
  • 15
2

This is my hacked up version :P

(defun add-to-list-with-subdirs (base exclude-list include-list)
  (dolist (f (directory-files base))
 (let ((name (concat base "/" f)))
   (when (and (file-directory-p name)
     (not (member f exclude-list)))
  (add-to-list 'load-path name)
  (when (member f include-list)
   (add-to-list-with-subdirs name exclude-list include-list)))))
  (add-to-list 'load-path base))

This will add all first level dirs from base and exclude the ones in exclude-list, while for the dirs in include-list, it will add all the first level dirs of that dir too.

(add-to-list-with-subdirs "~/.emacs.d" '("." ".." "backup") '("vendor" "my-lisp"))
Sujoy
  • 8,041
  • 3
  • 30
  • 36
1

This function will map over first level sub-folders and files in BASE-PATH and add it to the LOAD-LIST if it's a directory (excluding directories "." and "..").

(defun add-subdirs-to-load-path (base-path)
  "Adds first level subfolders to LOAD-PATH.
BASE-PATH must not end with a '/'"
  (mapc (lambda (attr)
          (let ((name (car attr))
                (folder-p (cadr attr)))
            (unless (or (not folder-p)
                        (equal name ".")
                        (equal name ".."))
              (add-to-list 'load-path (concat base-path "/" name)))))
        (directory-files-and-attributes base-path)))
1

Install dash and f third-party libraries. Your needed function is f-directories:

(f-directories "~/YOURDIR") ; return only immediate directories
(f-directories "~/YOURDIR" nil t) ; all directories recursively

Then use --each to add each found directory to load-path. This whole operation works in O(n²), but as load-path is usually super-small, who cares.

(add-to-list 'load-path "~/YOURDIR") ; your parent folder itself
(--each (f-directories "~/YOURDIR") (add-to-list 'load-path it))
Mirzhan Irkegulov
  • 17,660
  • 12
  • 105
  • 166