I felt my init.el file was getting too bloated, so I ended up doing a fair amount of refactoring on it. I moved essentially all the code from init.el into a few directories I made in .emacs.d. Structuring your customizations is pretty important if you ever either need to go back to change them or find them to suggest to others; I do both of these a fair amount, so I spend a fair amount of time organizing my files. I probably ended up erring on the side of too many horizontal files, but I think it should be OK for now.
My .emacs.d directory now has four main elisp directories: customizations, major-modes, minor-modes, and utilities. It also has temporary information, documentation, Clojure, and hopefully everything I need to just be able to check it out and have my full working setup. The customizations and utilities directory are currently flat; They contain small files described for what they modify or are for. For example, the Ibuffer customizations I recently suggested are in ibuffer.el. This does sometimes pose organizational problems; Should changing an variable customizing a minor-mode on entering a major-mode be a customization of the minor-mode or major-mode? I currently go for the major-mode, but this could change if I ever have problems finding anything.
Major-modes and minor-modes contain precisely what they describe; All the major and minor modes I have downloaded. Packages that modify other major modes, such as dired+, do not go in these directories; they still go in the customizations file. These two directories can be arbitrarily nested - I just put the modes in however they are distributed.
After moving all the customizations out of init.el, I had the following left:
(let ((default-directory "~/.emacs.d/")) (add-to-list 'load-path default-directory) (normal-top-level-add-subdirs-to-load-path)) (defun load-directory (dir) (mapcar '(lambda (x) (load-file x)) (directory-files dir t "\\.el$"))) (load-directory "~/.emacs.d/customizations/") (load-directory "~/.emacs.d/utility/")
The first let expression is a simplification of something I blogged about a while ago; It will add all subdirectories of ~/.emacs.d/ to the load-path; this is necessary so that I don’t have to do manual manipulation of the load-path.
The second function is one I wrote to support my refactorings. It will load every elisp file in a directory. It doesn’t support subdirectories, but this wouldn’t be too hard to add if I ever need it. I then just load up my customizations and utility functions and am good to go. I highly recommend doing something similar to this; Splitting your customizations from one big file and aggregating similarities makes it much easier to manage your configuration.
Tags: elisp, emacs, refactoring
It’s a matter of taste. 2 years ago I did a splitting of my .emacs file but after some days I come back to a single file because many times I had problems finding customizations for specific libraries. I made nice comments in my .emacs file and I can easily jump to places I need with C-s. My emacs file has over 7000 lines and I had no problems to manage it so far.
I have this, with some macros for facilitating host- and OS-specific customizations:
- .emacs.d
-- lisp
--- mode1setup.el
--- mode2setup.el
--- os1
---- mode1setup.os1.el
---- mode2setup.os1.el
--- os2
---- mode1setup.os2.el
---- mode2setup.os2.el
--- host1
---- mode1setup.host1.el
---- mode2setup.host1.el
--- host2
---- mode1setup.host2.el
---- mode2setup.host2.el
-- site-lisp
--- nxml
--- org
--- dvc
--- traverse
--- etc
Easily extensible to other kinds of per-something customizations: DNS domain, window system, processor architecture… haven’t needed any of those myself yet.
How about:
(defun load-directory (dir)
(mapc 'load-file (directory-files dir t "\\.el\\'")))
* mapc: for side effects only, doesn’t accumulate results (unlike mapcar).
* No lambda wrapper required for load-file, since it takes exactly one argument anyway.
* Better to terminate file extension patterns with backslash-quote rather than dollar. It means you don’t accidentally match files that (perversely) include the newline character in their names.
Useful function though, thanks for sharing it.
Ive just refactored my .emacs file using your two functions above (hoping you dont mind), the only problem ive hit so far is with downloaded .el files, such as browse-kill-ring.el. Im trying in my customizations folder to call things by the same name (as the source file) which leads to a recursive load, but its a non-issue for intergrated things like ido.el. my tempory solution has been to rename the files in custimizations to allow them to load, just wondering if you have a better solution.
Thanks Ive been quite likeing your emacs posts recently
My emacs configuration file refactor…
In a previous post I described that a few months ago, I moved the third party elisp code under version control to make it easier to move it between machines and ensure a consistent configuration across them. The one remaining problem to solve was putti…