[comp.emacs] Portable Emacs Customizations

kayvan@EDDIE.MIT.EDU (Kayvan Sylvan) (12/04/90)

As a result of the recent discussion about maintaining large .emacs
files (and modularity and portability, including ease of change) of
these large files, I took a look at my setup and redesigned it in a
way that makes it easy to use, doesn't use unnecessary space (most of
my package-specific variables don't clutter up my virtual space until
they are needed), and aesthetically pleasing.

Here's what I did. Near the top of my ``.emacs'' file:

    (setq user-private-lisp-directory "~kayvan/src/elisp")
    (if (not (memq (expand-file-name user-private-lisp-directory) load-path))
	(setq load-path
	      (cons (expand-file-name user-private-lisp-directory) load-path)))

Then I have all the global key bindings, autoloads and variable settings (like
auto-save-default, default-major-mode, etc.).

At the end of my ``.emacs'' I have:

    ;;
    ;; Do mode-hook, package, and local initializations.
    ;;
    (load "packages/Initialize" t t)	; Run packages file
    (load "mode-hooks/Initialize" t t)	; Run mode-hooks file
    (load "local/Initialize" t t)		; Set up local hacks

The above three lines do the rest of my setup.

The ``packages'', ``mode-hooks'' and ``local'' directories are
subdirectories of my private elisp directory (~kayvan/src/elisp
above).

The ``packages/Initialize.el'' file contains this code:

    ;;;
    ;;; top level load file of packages directory
    ;;;
    ;;; Author: Kayvan Sylvan
    ;;;

    (autoload 'mail "packages/mail" "" t)
    (autoload 'mail-other-window "packages/mail" "" t)

    (autoload 'sy-cite-original "packages/supercite" "For Supercite 2.0" t)
    (autoload 'sy-cite "packages/supercite" "Interactive Supercite 2.0" t)
    (autoload 'supercite "packages/supercite" "Describe Supercite 2.0" t)

    (autoload 'vm "packages/vm" "" t)
    (autoload 'vm-visit-folder "packages/vm" "" t)

Now, if I do ``M-x mail'' in emacs, the autoload above will load
the file ``packages/mail.el'' which contains all my customizations of
mail-mode variables and a ``(load "sendmail")'' which will load the
actual mail package.

Similarly, my ``packages/vm.el'' file contains all my vm
initializations (a rather large file with all the folder definitions)
and does a ``(load "vm")'' at the end.

The ``mode-hooks/Initialize.el'' file contains this code:

    ;;;
    ;;; top level load file of mode-hooks directory
    ;;;
    ;;; Author: Kayvan Sylvan
    ;;;

    (defun mode-hook-auto-load (hook file)
      "Set HOOK to a function that autoloads from FILE and then run the HOOK.
    The file should simply define the hook and any supporting functions."
      (eval
       (list 'setq hook
	     (list 'quote (list 'lambda nil (list 'load file nil t)
				(list 'run-hooks (list 'quote hook)))))))

The above function is used in the rest of the file. It makes it easy
to define the various mode-hooks in terms of a file that contains the
actual definition (making them easy to change).

    ;;
    ;; Mode hooks for packages
    ;;
    (mode-hook-auto-load 'c-mode-hook "mode-hooks/c-mode")
    (mode-hook-auto-load 'gnus-Startup-hook "mode-hooks/gnus")
    (mode-hook-auto-load 'outline-mode-hook "mode-hooks/outline")
    (mode-hook-auto-load 'cmushell-load-hook "mode-hooks/cmushell")
    (mode-hook-auto-load 'dired-mode-hook "mode-hooks/dired")

So if I invoke c-mode (by visiting a C file), the c-mode-hook defined
by the mode-hook-auto-load function will load the
``mode-hooks/c-mode.el'' file and then execute the real c-mode-hook
(which the file defined).

The ``mode-hooks/Initialize.el'' file also contains some simple
mode-hook definitions.

    ;;
    ;; Mode hook code
    ;;
    (setq text-mode-hook '(lambda () (setq fill-column 70)))
    (setq TeX-mode-hook '(lambda () (progn (auto-fill-mode 1))))
    (setq texinfo-mode-hook '(lambda () (progn (auto-fill-mode 1))))

The last piece of this scheme, ``local/Initialize.el'' is a catch-all
for any local customizations and overrides that I might have.
The ``local/'' directory contains code that is locally generated and
then called (and or bound to keys).

    ;;
    ;; Local hacks and additions top-level
    ;;

    (global-set-key "\C-x%" 'match-it)
    (autoload 'match-it "local/match" "" t)

    ;
    ; Coerce emacs into automagically rebuilding mail aliasii when
    ; .mailrc edited --- Inspired by Mike Meissner (meissner@osf.org)

    (defun rebuild-mail-aliases ()
      "Hook to rebuild the mail aliases, whenever ~/.mailrc is stored."
      (if (string-equal buffer-file-name (expand-file-name "~/.mailrc"))
	  (progn
	    (setq mail-aliases t)	;Force sendmail to [re]read .mailrc
	    nil)))			;Procede normally to save the file

    (if (not (memq 'rebuild-mail-aliases write-file-hooks))
	(setq write-file-hooks (cons 'rebuild-mail-aliases
				     write-file-hooks)))

    (display-time)				; Display time and load
    (load "local/status")
    (load "local/key-trans" nil t)

Of course, in this message, whenever I refer to ``file.el'', I really
mean ``file.elc'' (all my .el files are compiled).

I've been running with this setup for a couple of weeks now and I love
its simplicity and flexibility.

I hope this is of some use to you.

			---Kayvan

| Kayvan Sylvan       Unix/C, GNU tools   879 Lewiston Drive   408-978-1407  |
| Sylvan Associates   GUIs, Databases     San Jose, CA 95136   I Love Tigger |
|                     Networking          apple!satyr!kayvan   I Love Kathy  |