M-x all-things-emacs

Declaring .emacs Bankruptcy

October 7th, 2007 by Ryan McGeary · 30 Comments

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.d directory.
  • 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?

Tags: misc

30 responses so far ↓

  • 1 Tim Daniel // Oct 7, 2007 at 3:23 pm

    That scheme looks very nice, I’ll think I’ll adapt this scheme more or later.

  • 2 Phil // Oct 7, 2007 at 7:37 pm

    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.

  • 3 she // Oct 7, 2007 at 8:45 pm

    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 …

  • 4 sean // Oct 7, 2007 at 8:54 pm

    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.

  • 5 sean // Oct 7, 2007 at 9:33 pm

    Nice system. I use something similar, but without the redundancy of explicit requires. Instead, my .emacs sources all files named “~/.emacs.d/init-*.el”.

  • 6 hws // Oct 7, 2007 at 9:44 pm

    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

  • 7 piyo // Oct 8, 2007 at 12:28 am

    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:

    (add-hook 'emacs-lisp-mode-hook 'my-prefhand--emacs-lisp-mode)
    (defun my-prefhand--emacs-lisp-mode ()
      (add-hook 'local-write-file-hooks 'check-parens))

    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?)?

  • 8 sean // Oct 8, 2007 at 1:41 am

    @piyo —

    re “make”: I just use this on write-file-hook, and it’s not too annoying:

    (defun my-recompile-el ()
      (interactive)
      (when (and buffer-file-name
                 (string-match "/.*\\.el$"  buffer-file-name)
                 (file-newer-than-file-p buffer-file-name
                                         (concat buffer-file-name "c"))
                 (y-or-n-p (format "byte-compile %s? "
                                   (file-name-nondirectory (buffer-file-name)))))
        (byte-compile-file buffer-file-name)))

    re load: it’s actually explicit, but automatic:

    (dolist (file (sort (file-expand-wildcards "~/.emacs.d/init-*.el") #'string<))
      (load (file-name-sans-extension file) t))

    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.

  • 9 Daniel Brockman // Oct 8, 2007 at 6:57 am

    I just use Customize.

  • 10 Nik // Oct 8, 2007 at 11:57 am

    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.

    (dolist (file (let ((default-directory "/path/to/config"))
                    (mapcar 'file-name-sans-extension
    			(file-expand-wildcards "*-start.el"))))
      (eval-after-load (intern (progn (string-match "\\(.*\\)-start" file)
    				  (match-string 1 file)))
        `(load ,(expand-file-name file emacs-home))))
  • 11 Donnie // Oct 8, 2007 at 12:03 pm

    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.

  • 12 Michael Olson // Oct 8, 2007 at 6:17 pm

    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.

  • 13 Peter Mielke // Oct 9, 2007 at 4:01 pm

    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

  • 14 Matt M // Oct 10, 2007 at 4:24 am

    I did a similar thing a couple years ago but borrowed the ‘safe-load’ technique from this website:

    http://www.dotemacs.de/recovery.html

  • 15 ttn // Oct 15, 2007 at 12:37 pm

    i use a “personal elisp” package:

    same idea, more work. :-P

    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. [...]

  • 17 Trey Jackson // Nov 7, 2007 at 7:18 pm

    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).

  • 18 Ryan McGeary // Nov 7, 2007 at 7:36 pm

    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.

  • 19 Phil Hagelberg // Nov 12, 2007 at 12:25 am

    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 [...]

  • 21 Daniel Høyer Iversen // Jul 23, 2008 at 5:03 pm

    My .emacs file http://dahoiv.net/.emacs

  • 22 Dave Abrahams // Aug 29, 2008 at 3:37 pm

    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!

  • 23 Ryan McGeary // Aug 29, 2008 at 6:24 pm

    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 .cvsignore are 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 [...]

  • 25 Stefan Kangas // Sep 29, 2009 at 6:23 pm

    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)))) 
  • 26 Kirk Strauser // Dec 22, 2009 at 6:00 pm

    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!

  • 27 Kirk Strauser // Dec 22, 2009 at 6:01 pm

    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. [...]

  • 29 Elvin Shehab // Jul 11, 2011 at 8:55 am

    This is just what I had been searching for… I desired some good information for my class and also you gave good quality insight thanks.

  • 30 Ryan McGeary // Jul 11, 2011 at 12:29 pm

    Elvin, Thanks. Since the time that I wrote this post, I’ve slightly changed my setup based on others feedback and after borrowing some other people’s conventions. You can browse it here:

    https://github.com/rmm5t/dotfiles/tree/master/emacs.d