Occasionally people ask to see my .emacs file. This always throws me for a sec. It feels like they've asked if they can take a peek at my Linux file, or my Windows file. The question doesn't make sense at first, until I remember that it's a perfectly natural question if you haven't really grasped the Zen of Emacs.

But since they've asked so often, here it is. My .emacs file...


;;;
;;; Stevey's .emacs file. Loads up lots of libraries.
;;;
;; I use the Common Lisp stuff all the time
(require 'cl)

;; I keep all my emacs-related stuff under ~/emacs
(defvar emacs-root (if (or (eq system-type 'cygwin)
(eq system-type 'gnu/linux)
(eq system-type 'linux))
"/home/stevey/" "c:/home/stevey/")
"My home directory — the root of my personal emacs load-path.")

;; add all the elisp directories under ~/emacs to my load path
(labels ((add-path (p)
(add-to-list 'load-path
(concat emacs-root p))))
(add-path "emacs/lisp") ;; all my personal elisp code
(add-path "emacs/lisp/ttest") ;; a typing-test package I wrote
(add-path "emacs/site-lisp") ;; elisp stuff I find on the 'net
(add-path "emacs/calc-2.02f") ;; fix for M-x calc on NT Emacs
(add-path "emacs/vm-7.04") ;; a fancy mail client
(add-path "emacs/jde-2.3.2/lisp") ;; Java IDE support
(add-path "emacs/jde-2.3.2/elib-1.0")
(add-path "emacs/jde-2.3.2/eieio-0.17")
(add-path "emacs/jde-2.3.2/speedbar-0.14beta4")
(add-path "emacs/jde-2.3.2/semantic-1.4.4")

(add-path "emacs/site-lisp/nxml-mode") ;; XML support
(add-path "emacs/site-lisp/tuareg-mode-1.41.5") ;; OCaml support
(add-path "emacs/site-lisp/emacs-wiki-2.67.1") ;; personal Wiki
)

;; I use the same .emacs and elisp files everywhere. I make sure
;; everything works in both GNU Emacs 21.x and XEmacs on various
;; platforms, including native Windows XP, Cygwin on Windows XP,
;; and various flavors of Linux, in windowing and terminal modes.
(require 'emacs-type) ;; support for multiple emacs platforms
(load-library "ekeys") ;; my key bindings and some aliases
(load-library "modes") ;; configuration for 100-odd emacs modes
(if-not-terminal
(progn (ignore-errors (require 'jde))
(load-library "myfont"))) ;; my own fonts and window colors
(load-library "efuncs") ;; a bunch of my own utility functions
(load-library "my-config") ;; one-off variable settings
(load-library "java-config") ;; java/python/ruby IDE setup
(load-library "mail-config") ;; smtp config for various locations
(load-library "perl-config") ;; extra support for perl coding
(load-library "screen-config") ;; window positioning for all platforms
(load-library "xml-config") ;; a few xml and html helper functions
(if-not-xemacs (require 'kawa-support)) ;; some helpers for Kawa Scheme
;; startup "script" for when we've got a window system
(if-not-terminal
(progn ;; start gnuserv, so apps can talk to us (e.g. p4, browsers)
(when (or google
(and winnt (not cygwin)))
(require 'gnuserv)
(setq gnuserv-frame (selected-frame))
(gnuserv-start))

;; set the fonts and colors I like
(global-font-lock-mode t)
(parchment-screen)
(set-default-font linux-font)
(set-mouse-color "black")

;; position window automatically based on display resolution
(size-screen)))

;; load in customizations, which I keep in their own little petting zoo
(load-library "~/.custom")

;; I always run a shell in Emacs. Always always.
(shell)

;;; end .emacs

That's it! About 90 lines, including blank lines and comments. That's why I give you a funny look for a sec if you ask to see it. There isn't much to see.

My .emacs "file" is actually a directory tree, which I always keep under my home directory: /home/stevey/emacs. I have about 10k lines of Emacs-lisp code of my own, and a quarter million lines, in over 400 files, that I've gotten off the net from various places, such as this one.

My emacs tree also has a fonts/ directory with Windows versions of some of my favorite Unix fonts (the sony fixed-width ones, my favorite being the one called "7x13"), an info/ directory with over 400 Emacs info files (individually gzipped, of course), and misc odds and ends: stuff written in perl, java, python, all tools to help integrate Emacs with my other applications.

The whole thing is under CVS (soon to be Subversion) control, with the repository hosted on a server in the Westin building in downtown Seattle, for which I pay a monthly colocation fee.

The server is remote-controlled via radio waves emitted by a giant radioactive moth from a concrete bunker at the center of a huge blimp that orbits Jupiter. Or so it would seem, since it's the only possible explanation for why server only seems to go down on Friday afternoons, right before my ISP's employees leave on holiday. Other than that, it works great.

I can check out my Emacs tree onto any computer with Linux or Cygwin, make a handful of local tweaks to the .emacs file, and I'm up and running. The same set of files works no matter how I'm running Emacs, including:

  • on a Windows machine (NT Emacs)
  • on a Linux machine under X (GNU Emacs)
  • on a Windows machine using the Cygwin-compiled GNU Emacs
  • ssh'ed remotely into a Linux box
  • ssh'ed remotely into a Windows box, running Cygwin bash
  • misc video modes and screen resolutions

I try to keep things working with XEmacs, or at least loading without errors. I use XEmacs occasionally, but it's never been stable enough for me to get hooked on it.

Emacs the Operating System

So what is all that stuff, anyway? Who would need 400+ elisp files in 70+ directories?

Well, most it is from a handful of big applications for Emacs. I'll mention some of the really major ones briefly, since they're all pretty cool.

JDEE

Paul Kinnucan is the author of the JDEE, or Java Development Environment for Emacs. It turns Emacs into something approximating an IDE for Java development. The website has some screen shots you can check out under the "JDEE Quick Tour".

It's an absolutely unbelievable pain in the arse to install. And his website is buggy, and the code is often buggy, and I generally detest the application, and Paul K's no picnic himself. Other than that, it's great.

In practice, it has some features that I find absolutely indispensable when I'm doing Java coding, which is fairly often. In particular, being able to open a Java file, compile it, and run it (with stdout/stderr going to a buffer) is just ... I'd die without it. And jumping to compile errors, of course. There might be other features I use, but not too many. I've wrestled with both debuggers it ships with, and have gotten them working a few times, but Java debugging has never been very good, regardless of the IDE. Not for big, multithreaded applications anyway.

I don't use it for syntax highlighting; I use an ancient file called andersl-java-font-lock.el that I've hacked up a lot. JDEE supposedly has 1.5-compliant highlighting now, so maybe I should try, once again, to fix all his frigging bugs so I can use it.

I don't use his stuff for code-template generation either; I wrote my own template-generation package for Java years ago, and it works better than his does, IMO. I donated it to Paul's JDEE project in 1998, and he loved it. He rewrote it just enough that he didn't need to give me any credit for it, which is half of why I think he's such a dick. The other half is that he produces such buggy, crappy code, web pages, installers, docs, and everything else.

But it's a monster application, clocking in at something like 80,000 lines of elisp and 20,000 lines of Java, or about 30% of my total elisp code tree. And it takes advantage of many other Emacs packages, so it has a surprising amount of functionality (that he takes credit for in his web pages.)

But enough Kinnucan-bashing. JDEE is what we Emacs users have for Java development today. And on the whole, it's not too bad, really. It's starting to get refactoring tools added in, since it has a full parser for the Java language, and it has class browsing and auto-completion and all that fun stuff.

Calc

This is Dave Gillespie's unbelievable calculator application. Rather than trying to describe it, I'll just copy Dave's description of it out of the Info file:

"Calc" is an advanced calculator and mathematical tool that runs
as part of the GNU Emacs environment. Very roughly based on the
HP-28/48 series of calculators, its many features include:

* Choice of algebraic or RPN (stack-based) entry of calculations.

* Arbitrary precision integers and floating-point numbers.

* Arithmetic on rational numbers, complex numbers (rectangular
and polar), error forms with standard deviations, open and
closed intervals, vectors and matrices, dates and times,
infinities, sets, quantities with units, and algebraic formulas.

* Mathematical operations such as logarithms and trigonometric functions.

* Programmer's features (bitwise operations, non-decimal numbers).

* Financial functions such as future value and internal rate of return.

* Number theoretical features such as prime factorization and
arithmetic modulo M for any M.

* Algebraic manipulation features, including symbolic calculus.

* Moving data to and from regular editing buffers.

* "Embedded mode" for manipulating Calc formulas and data
directly inside any editing buffer.

* Graphics using GNUPLOT, a versatile (and free) plotting program.

* Easy programming using keyboard macros, algebraic formulas,
algebraic rewrite rules, or extended Emacs Lisp.

To be honest, I mostly use it for arithmetic. Stack-based/RPN calculators are da bomb. I also occasionally use some of the actual scientific and math functions, or use it to display numbers in different radices. But I'm basically way, way underutilizing it.

You need calc-2.02f to run it on NT Emacs 21.x. I'm pretty sure I had to patch it, since I couldn't find an actual distribution of it, just a patch to 2.02. It's easy, though, and if you're intent on trying it, I can just send you a zipped-up copy. It's all in one subdirectory.

Calc alone is about 20% of the total elisp code in my tree. Dave Gillespie also wrote much of the Common Lisp support that comes bundled with Emacs, primarily for Calc's use.

VM

This is Kyle Jones' mail program for Emacs and XEmacs. I used it as my primary mail client for about 10 years, until a combination of the Spam problem and our switch to Exchange finally drove me to Outlook. But I'm a wimp. I should go back.

VM's source code comprises about 16% of total in my emacs tree. But all I use it for these days is its mail-send mode, sadly.

I also hear gnus is very good email client. Haven't tried it, but people absolutely swear by it. Someday I'll go back to Emacs as my mailer — maybe next year, since it'll take some work — and life will be happy again.

nXML-mode

James Clark, one of the original creators of XML, implemented nXML-mode sometime in 2003 as far as I can tell. It's a comprehensive plug-in that turns Emacs into a powerful XML editor.

It's another 10% of my total lisp glob. Just under half the nXML elisp files are data files for character sets.

Other big apps

Those four plug-ins (JDEE, Calc, VM, and nXML-mode) make up about 75% of the Emacs plug-in code that I use, at least by volume.

There are various other big applications for Emacs, including:

  • SES, a spreadsheet app (there are a few other spreadsheet applications for Emacs; not sure which one is the best. Calc works fine for most of my purposes.)

  • W3, a web browser.

  • TNT, a very cool Emacs client for AIM

  • chess.el - EmacsChess

And gosh, a whole bunch of others as well. Plus there are lots of them distributed with the standard GNU Emacs distribution.

Indispensable Apps

Here are some built-in, stock, out-of-the-box Emacs utilities that I use all the time. If you're using Emacs 21, you should have all of these automatically. For Emacs 20 and lower, may I recommend upgrading to Emacs 21? It's only, like, 100 years old now. It's safe. You can do it. Be brave.

OK, in no particular order, here are the "applications" that I think are the most interesting within Emacs, and I use them all the time.

Shell

Yep, I run a bash shell inside of Emacs, sometimes more than one. Indispensable. Can't live without it.

There are some differences from using a "real" bash shell, meaning one running in a reasonably powerful terminal emulator such as PuTTY or an xterm. The biggest thing that's missing is the ability to do curses/ncurses stuff. (Curses is a C/Unix library that knows about lots of terminal types, and provides a device-independent way to do text-base "UIs" in a terminal.)

So a fair number of Unix (and Windows) programs don't work properly inside an Emacs shell, notably:

  • ssh, rlogin and telnet
  • top
  • nethack
(Note: the apps above all have "native Emacs ports", though)

However, most utilities do work, and for the ones that don't (poor Nethack excepted), there's almost always a better way to do it using "native" Emacs functionality. For instance, you can run ssh or telnet in a subprocess using terminal-mode, which does provide full terminal emulation. And if you were really set on it, you could probably write an Emacs frontend to Unix top. Probably someone has; it's just really hard to search for on Google because "top" is such a common word.

In order to use Emacs shell effectively, you have to have a real terminal window open on the same desktop, and get used to switching over to it whenever you have a task that requires a true terminal. Which is almost never, these days. Emacs shell support is pretty solid.

And as for the advantages... well, it's Emacs! It's not just command-line editing any more; you have the entire history of your shell interaction (for that session) in a buffer, all nicely syntax-highlighted, and you can go back and perform any editing operations you like.

To use Bash with NT Emacs on Windows boxen, you should install Cygwin. It's easy, although it takes a while, since it's essentially turning your Windows machine into a Unix-compatible one.

My advice for you, if you use Cygwin: install it in your root directory, "c:\" or whatever your drive letter is. Don't let it use the default installation dir of c:\cygwin (or wherever the default is). The installer will warn you and say it's a bad idea. Ignore the warning. They're wrong. It's the only way to use Cygwin, and to make Cygwin usable, and it's the only way that Emacs will ever truly be happy interacting with Cygwin.

I've been installing it to root (on various computers) and using it that way for at least 3 years, and it's never caused a problem. They're just worried some application will come along and biff your /lib or /bin directory. Trust me: it won't happen. Applications these days stick themselves in "Program Files" or in "My Documents", or in some other godawful long directory path with spaces in it. Cygwin will be safe.

Once you've installed Cygwin, you have essentially a full Unix (mostly Linux-compatible) distribution on your Windows box. It has shells, X11, all the unix utilities, Apache, everything you want. Most Linux applications compile under Cygwin these days - it's supported directly by their autoconf and makefiles.

Cygwin is a better desktop Unix than Linux. Really. I've used both for many years. Linux for servers, Cygwin on your desktop. You'll never have a device-driver problem again, you'll never have to worry about RedHat switching all the config-file locations around from release to release, and you can throw Exceed right out the window.

Anyway, once Cygwin is installed, you can have bash (or zsh if you prefer) running inside an Emacs buffer. I recommend NT Emacs over Cygwin Emacs because it performs a bit better. But they're both great, and the Cygwin version has some bells and whistles that the NT one doesn't, such as inline image support.

Calendar

Type M-x calendar, and you'll see a pretty 3-month calendar display, scrollable left and right with "<" and ">", and all the holidays highlighted. Mouse-click on a day to get a popup menu, or move the cursor to a day and type "h" to see what holiday it is. It has appointments, lunar phases, daylight savings time indicators, time-interval tracking, and integration with the Emacs diary (another built-in app).

Calendar is just cool. Can't live without it.

However, as far I'm concerned, they got the "<" and ">" keys reversed, and the scrolling is totally unintuitive for me. So stick this into your .emacs file if you want to reverse them as well:

;; Fix foolish calendar-mode scrolling.
(add-hook 'calendar-load-hook
'(lambda ()
(setq mark-holidays-in-calendar t)
(define-key calendar-mode-map ">" 'scroll-calendar-left)
(define-key calendar-mode-map "<" 'scroll-calendar-right)
(define-key calendar-mode-map "\C-x>" 'scroll-calendar-left)
(define-key calendar-mode-map "\C-x<" 'scroll-calendar-right)))

The "mark-holidays-in-calendar" setting highlights all the days that are holidays, which is kind of nice.

Calendar rocks.

Other Stuff

Plus there's other stuff.

The "other stuff" that you find for Emacs typically falls into the following categories:

  • stuff that enhances your editing, such as chop.el, which moves the cursor around your screen in a binary search. It's nifty. These tend to affect the behavior of your entire Emacs session, although not always.

  • modes for every file format, programming language, or interactive process in the known universe. Modes are, well, modes - they change the behavior of Emacs in various ways. A simple one might simply have its own set of key bindings, syntax coloring, comment syntax (for comment-region), indentation rules, stuff like that. A complex mode might have thousands of lines of code, perform network operations, and offer hundreds of new functions. p4.el (the Perforce mode for Emacs) is a good example. Modes tend to be buffer-local.

  • "applications" such as games, spreadsheets, screen savers, diversions, productivity tools, specialized shells, you name it. Zillions of them.

There isn't really a clear-cut distinction between these categories; everything is essentially just a plugin.

My Stuff

Then there's all the stuff I've written for myself.

I have a bunch of my own keybindings and little aliases (such as "qrr" instead of "query-replace-regexp") in "ekeys.el". Not that interesting.

"modes.el" is where I cram most of my mode-specific customizations and autoloads. Most of the functions start with "fix-". Fix this, fix that. The great thing about Emacs is that well-written plug-ins are themselves extensible; people have been known to ship plug-ins that modify other plug-ins. Dunno if anyone's made it to the 3rd metalevel yet, but it wouldn't surprise me.

"my-config.el" is where I override all the standard stuff - a lot of it would normally be handled these days through M-x customize, but this file predates customize by about a decade.

There are some REALLY cool settings that Emacs doesn't have on by default, such as (auto-compression-mode 1), which automatically parses the archive of a gzip/zip/jar/tar or basically any other archive when you open it in Emacs, and lets you selectively open (and modify and save!) files inside of archives - including files in archives in other archives.

I have a "screen-config.el" that has a bunch of functions that decide where to put Emacs when it starts up, depending on the screen dimensions and other stuff. It also has functions I wrote that will change the color theme: black background, gray background, white background, to reduce eyestrain. Although these days I usually just use white, since it's not actually all that white on LCD monitors.

My "mail-config.el" file has machine-specific settings for my incoming and outgoing mail setup: servers, hosts, reply-to addresses, etc. Also some functions that let me auto-insert certain email addresses and lists when I'm composing email in Emacs.

The "ttest" directory contains a little application I wrote, M-x typing-test, which tells you how fast you actually type inside of Emacs, with access to all your shortcuts. It's actually quite fancy, and does a more accurate job of computing words per minute than any typing-test software I've seen online, since I invented a fairly robust mechanism for detecting typing errors. It emits various stats on your speed and accuracy, has some customization options, and is probably one of the most ambitious elisp apps I've created.

"efuncs.el" is where I have most of my productivity functions - things I've written or accumulated that fill in gaps I think are missing from Emacs. Like this function, which assumes you have 2 buffers showing, and it swaps them:

;; someday might want to rotate windows if more than 2 of them
(defun swap-windows ()
"If you have 2 windows, it swaps them." (interactive) (cond ((not (= (count-windows) 2)) (message "You need exactly 2 windows to do this."))
(t
(let* ((w1 (first (window-list)))
(w2 (second (window-list)))
(b1 (window-buffer w1))
(b2 (window-buffer w2))
(s1 (window-start w1))
(s2 (window-start w2)))
(set-window-buffer w1 b2)
(set-window-buffer w2 b1)
(set-window-start w1 s2)
(set-window-start w2 s1)))))

Or these two, which I consider serious omissions in the lineup of standard file-manipulation functions:

;;
;; Never understood why Emacs doesn't have this function.
;;
(defun rename-file-and-buffer (new-name)
"Renames both current buffer and file it's visiting to NEW-NAME." (interactive "sNew name: ")
(let ((name (buffer-name))
(filename (buffer-file-name)))
(if (not filename)
(message "Buffer '%s' is not visiting a file!" name)
(if (get-buffer new-name)
(message "A buffer named '%s' already exists!" new-name)
(progn (rename-file name new-name 1) (rename-buffer new-name) (set-visited-file-name new-name) (set-buffer-modified-p nil)))))) ;;
;; Never understood why Emacs doesn't have this function, either.
;;
(defun move-buffer-file (dir)
"Moves both current buffer and file it's visiting to DIR." (interactive "DNew directory: ")
(let* ((name (buffer-name))
(filename (buffer-file-name))
(dir
(if (string-match dir "\\(?:/\\|\\\\)$")
(substring dir 0 -1) dir))
(newname (concat dir "/" name)))

(if (not filename)
(message "Buffer '%s' is not visiting a file!" name)
(progn (copy-file filename newname 1) (delete-file filename) (set-visited-file-name newname) (set-buffer-modified-p nil) t))))

There's tons of stuff in there. Mostly junk that only I would use. But that's the point! If you have an extensible system, you should extend it for yourself. Doesn't need to be packaged for public consumption.

Info Files

Lastly, and I consider this to be veeeery important to my productivity, I have a bunch of Info files.

You can find (or build) Info files out of the docs for just about anything. I have a custom "dir" node with at least 100 entries in it. I have the Perl 5 info pages, for example, which is essentially the full Camel book. And the Ruby info pages, and Python, and OCaml, Scheme, Common Lisp, Guile, a whole bunch of language references. All bookmarked heavily — Emacs has a very nice bookmark facility.

I also have info files for a bunch of Gnu tools, Emacs utilities, Unix utilities, all kinds of stuff. Thousands of pages of documentation, all conveniently organized and searchable. They're a lot more detailed than man pages, usually, and I use them extensively. Sure, you can find the docs online too, but I prefer having everything in one place...

In Emacs, of course.

That's all, folks.

Anyway, that's a whirlwind tour of my .emacs "file".

I'm sure it's absolutely nothing compared to some of the elisp collections at Amazon. One of these days we're all going to have to get together and pool our stuff together.

(Published Sep 25th 2004)


Comments

Nethack in Emacs:

http://freshmeat.net/projects/nethack-el/

Top in Emacs:

http://lists.gnu.org/archive/html/gnu-emacs-sources/2004-07/msg00033.html

Posted by: Derek U. at September 27, 2004 06:50 PM


*laugh* - I can't believe I doubted Emacs even for a moment. Of course it can do Nethack and Top. Thanks Derek.

Posted by: Steve Yegge at September 27, 2004 08:18 PM


I've been trying to get bash/Cygwin to work under NT Emacs for *years*, and I've always been envious (yes, envious) of your success. I don't know what you did right in the first place to make it work, but after a non-trivial Google search, I finally found the magic incantation to make it work for me (listed at the end). For some reason, any command entered in the bash subshell resulted in ' : command not found': somehow, the command-line input wasn't being read correctly.

As for your advice to install Cygwin in C:\ instead of C:\cygwin: Yes, it will probably make things smoother, because more programs will agree on what "/" means, whether they're Cygwin or Windows apps. But the incantation installs some emacs filesystem hooks that translate between the two conventions, so stuff like Emacs filename completion within the interactive bash shell will work, etc. The downside is that it makes Emacs pause at startup while it sorts out the cygwin drive mounts. Someday I'll figure out how to run it as an asynchronous process.

(defconst CYGWIN-BASE "c:/cygwin")
(defconst CYGWIN-BIN (concat CYGWIN-BASE "/bin"))
(setenv "PATH" (concat CYGWIN-BIN ";" (getenv "PATH")))
(setq exec-path (cons CYGWIN-BIN exec-path))
(require 'cygwin-mount) ;; get from http://www.emacswiki.org/elisp/cygwin-mount.el
(cygwin-mount-activate)

(setq shell-mode-hook 'bash-shell-setup)

;; For the interactive shell
(add-hook 'comint-output-filter-functions
'shell-strip-ctrl-m nil t)
(add-hook 'comint-output-filter-functions
'comint-watch-for-password-prompt nil t)
(add-hook 'shell-mode-hook 'bash-shell-setup)

(setq explicit-shell-file-name "bash")
;; For subprocesses invoked via the shell
;; (e.g., "shell -c command")
(setq shell-file-name explicit-shell-file-name)

;; Sets the line-sending convention to \n, instead of \n\r
(defun bash-shell-setup ()
"Sets up BASH shell processes to use Unix coding system" (set-process-coding-system (get-buffer-process (current-buffer)) 'unix 'unix))

Posted by: Chris T. at September 28, 2004 06:10 PM


Here's (as far as I know) what I do to get Cygwin working "properly":

- install it in c:\

In Control Panel:

  • set HOME to /home/stevey
  • add c:\bin;c:\usr\local\bin; to front of PATH
    (make sure it's ahead of c:\windows\system32)
  • set CYGWIN to binmode ntsec tty

In my elisp configuration:

(setenv "HOME" "/home/stevey")

(let ((shellname "/bin/bash"))
(setenv "ESHELL" shellname)
(setenv "SHELL" shellname)
(setq shell-file-name shellname))

(load "comint")
(setq comint-completion-addsuffix t)
(setq comint-eol-on-send t)

As far as I can tell, that's -everything- I needed to do in order to get Emacs to play nicely with cygwin bash shells.

It only partially understands "~" - if I type "cd ~" or "cd" in my bash shell in comint-mode, Emacs doesn't know I've changed directories. So I have to type "cd /home/stevey". However, if I M-x find-file, it will tab-complete ~ properly for me, so at some level it knows ~ is /home/stevey. I'd look into this if it bothered me enough, but it never has.

All that cruft that they give you to put in Emacs to "train" it on the Cygwin paths - not needed. I just got rid of all that years ago.

Posted by: Steve Yegge at September 29, 2004 02:59 AM