I give up. During the past 6 years of my emacs career, my .emacs initialization file grew to embarrassing levels. As of this morning, it is well over 1000 lines and is a looming burden of disorganization. Startup time is poor, customizations exist for modes that I don’t use anymore (ahem, csharp-mode), and it has been this way for too long.
Today, I am declaring .emacs bankruptcy.
Akin to email bankruptcy, I’m blowing everything away and starting over. Only as I realize a need for something is it going back in. I’m also starting with a better organization scheme. My intent is to have a .emacs file with nothing but load-path additions and requires.
Examples
Here is an early view of my .emacs as I start this process:
;;;; Ryan McGeary's emacs initialization (2001-2007) ;; Enable a backtrace when problems occur ;; (setq debug-on-error t) ;; Load paths (add-to-list 'load-path (expand-file-name "~/.emacs.d")) (add-to-list 'load-path (expand-file-name "~/.emacs.d/lisp")) (add-to-list 'load-path (expand-file-name "~/.emacs.d/lisp-personal")) ;; Personal customizations (require 'my-generic) (require 'my-iswitchb) (require 'my-carbon-emacs) (require 'my-colors) ;; Many more to come
And here is an example of a personal customization (my-generic):
;;; Generic emacs settings I cannot live without ;; "y or n" instead of "yes or no" (fset 'yes-or-no-p 'y-or-n-p) ;; Highlight regions and add special behaviors to regions. ;; "C-h d transient" for more info (setq transient-mark-mode t) ;; Display line and column numbers (setq line-number-mode t) (setq column-number-mode t) ;; Emacs gurus don't need no stinking scroll bars (toggle-scroll-bar -1) ;; Line-wrapping (set-default 'fill-column 80) ;; Prevent the annoying beep on errors (setq visible-bell t) (provide 'my-generic)
This particular component is very likely to grow, but with the added organization elsewhere, I am more likely to refactor early and often.
Key points
- Third party packages go in
~/.emacs.d/lisp. - My own packages go in
~/.emacs.d/lisp-personal. - Personal customizations are broken into manageable components, and each is prefixed with “my” to avoid naming conflicts. These are placed in my
~/.emacs.ddirectory. - Customization components can be compiled for speed, or commented out when not needed.
- My stress levels are reduced knowing everything has it’s own cubbyhole.
I anticipate this being a good bit of work, but I think it’s going to be well worth it. If nothing else, it makes me happier.
Your feedback, please
Who else wants to declare bankruptcy with me? What other techniques, tools, or conventions am I missing?
28 responses so far ↓
That scheme looks very nice, I’ll think I’ll adapt this scheme more or later.
I split everything out a while ago; it helps a lot for keeping everything in your head:
http://dev.technomancy.us/browser/dotfiles/.emacs
Prefixing with initials is a good idea; should start doing that.
I split the logic even with my shell scripts… i have separates lists for aliases variables, personal vars, system vars, and of course a multitude of shell scripts. (I dont use them a lot these days, I use higher-level languages to do the job shell scripts used to do. Its a lot easier to maintain high level languages and not bother with arcane if [] then blablabla fi more_blablablabla
So my point is – GOOD idea, organizing and a good, solid structure help saves a lot of time and energy – and avoid confusion!
I’d just wish that the GNU folks would realize this too …
Phil — Prefixing with initials is a terrible idea: what happens when you give your customizations to someone else, and they modify them to suit their needs? Much better is to use an impersonal prefix like “my-”, which makes sense no matter who is using the code.
Nice system. I use something similar, but without the redundancy of explicit requires. Instead, my .emacs sources all files named “~/.emacs.d/init-*.el”.
I’ve split my “init.el” another day, inspired by jao configuration
http://hacks-galore.org/darcs?r=emacs-debian;a=summary
It was 5000 lines, and most of it were functions I had collected but didn’t use every day. I also have a file for each mode, even if it is only 5 lines long.
My only concern right now is if I should keep local keybindings in a general file or with each mode…
The advantage of having them in a single file is that its easier to find out, for example, who is using some keybinding…
regards
I too declared “.emacs bankruptcy” about 3 years ago and I did a similar reorganization to your system. About the only difference is that I keep the “.emacs” part in a “prefs” directory and any new modes or packages I write from scratch I keep in a “my lisp” directory.
My emacs startup time is about 10 seconds. I obtained timing from after-init-hook, emacs-startup-hook, term-setup-hook, and window-setup-hook, in that order.
There are a number of things I leaned on. One thing that helped immensely with the transition is a version control system. Build a safety net before you jump!
Also I use different flavors of emacs (CVS Emacs on Debian and Meadow on Windows) so I had to figure out what was shared and not. I’ve tried to make all of my personal settings using Customize, but if not, I have a seperate file for that.
I also decided to compile most of my lisp files and libraries I carry around so I made an automated “make” like function. It is implemented in Ruby Rake which inconvenient from a dependency point of view. (One more software to install to make it my computer) I would like some pointers on how to do a “make” like in Emacs Lisp.
I’m sure you know these: Run two copies of Emacs, one for editing, and one for testing startup. If you have trouble use —debug-init liberally. Use the function check-parens to make sure you are writing runnable lisp code:
On the keybindings issue I like to group that and mouse redefines and macros into one file (~/.emacs/prefs/my-input.el), and just use mode hooks or def-advices.
@sean: Where can I find more explanation about this implicit load “~/.emacs/init-*.el”? For example, what order does it run and how to disable implicit load on a per-file basis (just rename file?)?
@piyo —
re “make”: I just use this on write-file-hook, and it’s not too annoying:
re load: it’s actually explicit, but automatic:
I actually use three levels of loading: 0-init-* for macros and early initialization, init-* for normal stuff, and z-init-* for stuff that runs at the end of startup, like desktop and start-server.
I just use Customize.
Organization is good and nice but it won’t help startup speed. The key here is to autoload as much as possible. That means packages AND configuration. The two essential functions for this are autoload and eval-after-load.
I use the following snippet to automatically find and autoload files like c++-mode-start.el in my config dir.
I like the idea of moving everything out. Currently I have one big .emacs file.
I have a directory called elisp under revision control in a publicly-accessible Subversion repository. Whenever I set up a new machine, I check out the elisp directory then create a link called .emacs to the file elisp/emacs.el. This helps me to quickly configure new machines with Emacs just the way I like it. Plus, whenever I make an important change to emacs.el (.emacs) in any machine, I can easily update the repository and all the other machines.
I use Customize as much as possible, and also initsplit.el to separate the customizations automatically into separate files when saved. It works pretty well.
I also had to spend a month or so reorganizing my .emacs and all the related files. I have gone for many small files (each for a particular package or mode). I think that the following link can be applied to emacs initialization as well:
http://blog.objectmentor.com/articles/2006/12/21/size-matters
I did a similar thing a couple years ago but borrowed the ‘safe-load’ technique from this website:
http://www.dotemacs.de/recovery.html
i use a “personal elisp” package:
same idea, more work.
thi
16 genehack.org » Blog Archive » tab dump // 20071022 // Oct 22, 2007 at 10:20 am
[...] Declaring .emacs bankruptcy — I’m declaring bankruptcy bankruptcy. Beat that. [...]
As Nik says, re-organizing your stuff will not help. autoload everything.
I dropped my startup time from over 10 seconds to less than one. And I’ve got 5800 lines of initialization (not including packages loaded – some 50 or so that I actively use).
I think I need to clarify something. The reason my startup time dropped was because during the cleanup, I was was able remove a lot of configuration that I no longer use or need.
It does sound like prudent advice to autoload everything, however.
Ryan: Got your comment on my blog. If you’re interested in helping out with emacs-rails, please join our mailing list. We’d love to hear your ideas: http://tech.groups.yahoo.com/group/ruby_emacs_dev/
20 Emacs i .emacs « Rofrol blog // Mar 10, 2008 at 12:46 am
[...] http://www.emacsblog.org/2007/10/07/declaring-emacs-bankruptcy/#more-105 [...]
My .emacs file http://dahoiv.net/.emacs
Could you explain the rationale for using ~/.emacs.d/ as the base for all this customization? Doesn’t the fact that it gets used by emacs for all kinds of cache files makes it a bit inconvenient if you want to maintain things in source control?
Thanks!
Dave, I want everything emacs related in one location. I’m not worried about cache or backup files sitting there. That’s what
.gitignore,svn propset svn:ignore, or.cvsignoreare for. For example, here’s my .gitignore file:http://github.com/rmm5t/dotfiles/tree/master/emacs.d/.gitignore
24 Nice organization guide for .emacs file | Nerd Gene // Jan 27, 2009 at 6:49 am
[...] .emacs organization suggestions [...]
Here are my changes to the code to automatically compile elisp files that was suggested by “sean” above. Basically, I removed the prompt. Now it simply deletes an older compiled version and compiles the file automatically.
You may or may not like the fact that you can’t defer compilation. Personally, I’d rather get rid of the prompt, and then manually having to comment out some code that I’m working on to stop the compiler from complaining.
(Disclaimer: While I currently use this in emacs23, I’m not very experienced by emacs and YMMV.)
(add-hook 'after-save-hook 'my-recompile-el) (defun my-recompile-el () (interactive) (let ((byte-compile-warnings '(unresolved))) (when (and buffer-file-name (string-match "/.*\\.el$" buffer-file-name) (file-newer-than-file-p buffer-file-name (concat buffer-file-name "c"))) (when (file-exists-p (concat buffer-file-name ".elc")) (delete-file (concat buffer-file-name ".elc"))) (byte-compile-file buffer-file-name))))I’ve used a common .emacs file shared among all my machines for years. It had a big cond blog that used system-name to alter host-specific settings. In the process of migrating to a new .emacs.d layout, I replaced all that with:
;; Per-machine settings
(let ((local-conf-name (format “~/.emacs.d/%s.el” system-name)))
(cond ((file-exists-p local-conf-name)
(load-file local-conf-name))
((message “%s doesn’t exist or I’d load it.” local-conf-name))))
Now it’ll look for ~/.emacs.d/myworkstation.example.com.el and load it if it exists. No more embedded chunks of ugly code!
s/cond blog/cond block/
28 .emacs publishing | Perpetually Curious // Jun 25, 2010 at 4:31 am
[...] Groovy The whole config is split into individual lisp files that are specific to a language or cross cutting feature. The inspiration for doing this work came from M-x all-things-emacs. [...]
Leave a Comment