My .emacs file is a collection of hacks, both stolen from the internet and written myself.

In addition to my .emacs file, you may also be interested in my quasi-project system, find-things-fast, which provides git accelerated find-file-in-project and grepsource commands (with reasonable fallbacks in non-git controlled repositories).

In case you’re into RealLive hacking, I also wrote rldev-el, which is a few very simple major-modes for working with rldev disassembled files.

;; -----------------------------------------------------------------------
;; Elliot's .emacs file
;; -----------------------------------------------------------------------

;; -----------------------------------------------------------------------
;; Platform Selection
;; -----------------------------------------------------------------------
(defvar running-apple (string-match "apple" system-configuration))

;; -----------------------------------------------------------------------
;; User interface
;; -----------------------------------------------------------------------
;; Previously, I've been trying to control the height of emacs on different
;; platforms. Stop doing that, set 'default-frame-alist with values that work
;; on all platforms.
(setq default-frame-alist
      '((wait-for-wm . nil)
        (top . 0)
        (width . 80)
        (tool-bar-lines . 0)
        (menu-bar-lines . 0)))

;; Interface needs to be minimal...
(put 'scroll-left 'disabled nil)
(if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
(if (fboundp 'blink-cursor-mode) (blink-cursor-mode -1))
(transient-mark-mode t)

;; Only hide the menu bar when I'm not on an apple machine since it doesn't
;; cost me anything on OSX.
(unless running-apple
  (if (fboundp 'menu-bar-mode) (menu-bar-mode -1)))

;; -----------------------------------------------------------------------
;; Load paths
;; -----------------------------------------------------------------------
(defvar my-load-path (expand-file-name "~/.elliot-unix/emacs/site-lisp"))
(add-to-list 'load-path my-load-path)
(setq byte-compile-warnings nil)

;; -----------------------------------------------------------------------
;; Color Themes
;; -----------------------------------------------------------------------
(require 'color-theme)
;; Use color themes only in windowed modes.
(defun my-color-theme-frame-init (frame)
  (set-variable 'color-theme-is-global nil)
  (select-frame frame)
  (if window-system
      (progn (require 'color-theme-black-forest)
             (color-theme-black-forest))
    (progn (load-library "color-theme-library")
           (color-theme-tty-dark))))

(add-hook 'after-make-frame-functions 'my-color-theme-frame-init)

;; Must manually call `my-color-theme-frame-init' for the initial frame.
(cond ((selected-frame)
       (my-color-theme-frame-init (selected-frame))))

;; -----------------------------------------------------------------------
;; Find Things Fast
;; -----------------------------------------------------------------------
(require 'find-things-fast)
(global-set-key '[f1] 'ftf-find-file)
(global-set-key '[f2] 'ftf-grepsource)
(global-set-key '[f4] 'ftf-gdb)
(global-set-key '[f5] 'ftf-compile)

;; -----------------------------------------------------------------------
;; Personal Keybindings
;; -----------------------------------------------------------------------
(global-set-key '[f3] 'select-vc-status)
;;;;;;; DO NOT USE [f9], [f10], [f11], OR [f12]. They're taken by the
;;;;;;; OS on OSX for the Expose stuff.

(global-set-key "\C-x\M-f" 'find-file-at-point)
(global-set-key "\M-gc" 'goto-char)

;;; Unbind the stupid minimize that I always hit.
(global-unset-key "\C-z")

(global-set-key [(shift home)] '(lambda () (interactive) (other-window -1)))
(global-set-key [(shift end)] '(lambda () (interactive) (other-window 1)))

;; Setup hippie-expand (we're going to have to make an eval-after-load
;; section later)
(defun hippie-expand-case-sensitive (arg)
  "Do case sensitive searching so we deal with gtk_xxx and GTK_YYY."
  (interactive "P")
  (let ((case-fold-search nil))
    (hippie-expand arg)))

(global-set-key "\M-/" 'hippie-expand-case-sensitive)
(global-set-key (kbd "M-SPC") 'hippie-expand-case-sensitive)
(setq hippie-expand-try-functions-list
      '(try-expand-dabbrev
        try-complete-file-name-partially
        try-complete-file-name
        try-expand-all-abbrevs
        try-expand-list
        try-expand-dabbrev-all-buffers
        try-expand-dabbrev-from-kill))

;; -----------------------------------------------------------------------
;; Initial register values
;; -----------------------------------------------------------------------
(set-register ?e '(file . "~/.elliot-unix/emacs/emacs"))
(set-register ?b '(file . "~/.elliot-unix/bash/bashrc"))
(cond ((file-exists-p (expand-file-name "~/work/rldev"))
       (set-register ?k '(file . "~/work/rldev/lib/reallive.kfn")))
      ((file-exists-p (expand-file-name "~/Projects/rldev"))
       (set-register ?k '(file . "~/Projects/rldev/lib/reallive.kfn")))
      ((file-exists-p (expand-file-name "~/rldev"))
       (set-register ?k '(file . "~/rldev/lib/reallive.kfn"))))

;; -----------------------------------------------------------------------
;; Autoloads (aka, the way to make emacs fast)
;; -----------------------------------------------------------------------
(autoload 'hide-ifdef-define "hideif" nil t)
(autoload 'hide-ifdef-undef  "hideif" nil t)
(autoload 'c-mode "cc-mode" "C Editing Mode" t)
(autoload 'c++-mode "cc-mode" "C++ Editing Mode" t)
(autoload 'objc-mode "cc-mode" "ObjC Editing Mode" t)
(autoload 'ruby-mode "ruby-mode" "Major mode for editing ruby scripts." t)
(autoload 'bison-mode "bison-mode" "Major mode for editing yacc files." t)
(autoload 'flex-mode "flex-mode" "Major mode for editing lex files." t)
(autoload 'make-regexp "make-regexp"
  "Return a regexp to match a string item in STRINGS." t)
(autoload 'make-regexps "make-regexp"  "Return a regexp to REGEXPS." t)
(autoload 'ascii-table "ascii-table" "Displays the ASCII table." t)
(autoload 'filladapt-mode "filladapt" "Filladapt mode." t)
(autoload 'doxymacs-mode "doxymacs" "Deal with doxygen." t)
(autoload 'cg-mode "cg-mode" "Edit files written in nVidia's Cg language." t)
(autoload 'lua-mode "lua-mode" "Lua editing mode." t)
(autoload 'rubydb "rubydb3x" "Ruby debugger" t)
(autoload 'git-status "git" "git status mode." t)
(autoload 'svn-status "psvn" "psvn.el status mode." t)
(autoload 'malyon "malyon" "Z-Machine interpreter." t)

(autoload 'textile-mode "textile-mode" "Textile editing mode." t)
(autoload 'markdown-mode "markdown-mode" "Markdown editing mode." t)

(autoload 'go-mode "go-mode" "Major mode for editing Go source text." t nil)

;; Autoloads to my custom header inserters
(autoload 'insert-c++-seperator-line "e-seperators" nil t)
(autoload 'insert-c-seperator-line "e-seperators" nil t)
(autoload 'insert-elisp-seperator-line "e-seperators" nil t)
(autoload 'insert-script-seperator-line "e-seperators" nil t)
(autoload 'insert-c-section-header "e-seperators" nil t)
(autoload 'insert-c++-section-header "e-seperators" nil t)
(autoload 'insert-elisp-section-header "e-seperators" nil t)
(autoload 'insert-script-section-header "e-seperators" nil t)
(autoload 'insert-c++-big-header "e-seperators" nil t)
(autoload 'insert-elisp-big-header "e-seperators" nil t)
(autoload 'insert-script-big-header "e-seperators" nil t)
(autoload 'insert-text-seperator-line "e-seperators" nil t)

;; RLVM and rldev related modes
(autoload 'kfn-mode "kfn-mode" nil t)
(autoload 'kepago-mode "kepago-mode" nil t)

;; -----------------------------------------------------------------------
;; Set up coding system.
;; -----------------------------------------------------------------------
(prefer-coding-system 'utf-8)
(modify-coding-system-alist 'file "\\.sjs\\'" 'shift_jis)

;; -----------------------------------------------------------------------
;; auto-mode-alist
;; -----------------------------------------------------------------------
(setq auto-mode-alist
      (append '(("\\.[Cc][Xx][Xx]$" . c++-mode)
                ("\\.[Cc][Pp][Pp]$" . c++-mode)
                ("\\.[Hh][Xx][Xx]$" . c++-mode)
                ("\\.[Tt][Cc][Cc]$" . c++-mode)
                ("\\.h$" . c++-mode)
                ("\\.i$" . c++-mode)    ; SWIG
                ("\\.mm?$" . objc-mode)
                ("_emacs" . lisp-mode)
                ("\\.el\\.gz$" . lisp-mode)
                ("\\.mak$" . makefile-mode)
                ("\\.conf$" . conf-mode)
                ("\\.go$" .  go-mode)
                ("Doxyfile.tmpl$" . makefile-mode)
                ("Doxyfile$" . makefile-mode)
                ("\\.uncompressed$" . hexl-mode)
                ("\\.ke$" . kepago-mode)
                ("\\.markdown$" . markdown-mode)
                ("\\.md$" . markdown-mode)
                ("\\.textile$" . textile-mode)
                ("\\.kfn$" . kfn-mode)
                ("\\.rb$" . ruby-mode)
                ("\\.cml$" . xml-mode)
                ("\\.cg$" . cg-mode)
                ("\\.y$" . bison-mode)
                ("\\.yy$" . bison-mode)
                ("\\.l$" . flex-mode)
                ("\\.ll$" . flex-mode)
                ("\\.lua$" . lua-mode)
                ("\\.org$" . org-mode)
                ("\\.scons$" . python-mode)
                ("SCons\\(cript\\|truct\\)" . python-mode)
                ("\\.gclient$" . python-mode)
                ) auto-mode-alist))

(setq interpreter-mode-alist
      (append '(("ruby" . ruby-mode))
              interpreter-mode-alist))

;; Ignore haskell interface files.
(add-to-list 'completion-ignored-extensions ".hi")

;; -----------------------------------------------------------------------
;; Startup variables
;; -----------------------------------------------------------------------
(setq user-full-name "Elliot Glaysher"
      user-mail-address "glaysher@umich.edu"

      enable-local-variables :safe
      inhibit-startup-message t
      default-major-mode 'text-mode
      require-final-newline t
      default-tab-width 4
      default-fill-column 79
      truncate-partial-width-windows nil
      frame-title-format (concat user-login-name "@" system-name))

(add-hook 'suspend-hook 'do-auto-save) ;; Auto-Save on ^Z

(setq-default echo-keystrokes 2
              next-screen-context-lines 4
              compilation-scroll-output t
              indent-tabs-mode nil
              tags-revert-without-query t)

(put 'eval-expression 'disabled nil)
(fset 'yes-or-no-p 'y-or-n-p) ;; Make all yes-or-no questions as y-or-n

;; -----------------------------------------------------------------------
;; Modules loaded at startup (and their configuration)
;; -----------------------------------------------------------------------
;; ------------------------------------------------------ [ haskell-mode ]
(load "~/.elliot-unix/emacs/site-lisp/haskell-mode-2.7.0/haskell-site-file")

;; ---------------------------------------------------------- [ ido-mode ]
(require 'ido)
(ido-mode t)
(setq ido-default-file-method 'selected-window)
(setq ido-default-buffer-method 'selected-window)

;; ---------------------------------------------------------- [ diminish ]
;; Makes minor mode names in the modeline shorter.
(require 'diminish)

(eval-after-load "filladapt"
  '(diminish 'filladapt-mode "Fill"))
(eval-after-load "abbrev"
  '(diminish 'abbrev-mode "Abv"))
(eval-after-load "doxymacs"
  '(diminish 'doxymacs-mode "dox"))

;; -------------------------------------------------------- [ backup-dir ]
;; Changes the location where backup files are placed. Instead of
;; being spread out all over the filesystem, they're now placed in one
;; location.
(if (file-accessible-directory-p (expand-file-name "~/.Trash"))
    (add-to-list 'backup-directory-alist
                 (cons "." (expand-file-name "~/.Trash/emacs-backups/"))))

;; ----------------------------------------------------- [ midnight-mode ]
(require 'midnight)

;; Never clean up these files. I will probably always have my .emacs file open.
(add-to-list 'clean-buffer-list-kill-never-buffer-names "emacs")

;; Clean up these buffers more often
(add-to-list 'clean-buffer-list-kill-buffer-names "*Annotate ")

;; ------------------------------------------------------------- [ pager ]
;;; Excellent package for better scrolling in emacs
;;; should be default package. But now it can be downloaded
;;; from: http://user.it.uu.se/~mic/pager.el
(require 'pager)
(global-set-key "\C-v"     'pager-page-down)
(global-set-key [next]     'pager-page-down)
(global-set-key "\ev"      'pager-page-up)
(global-set-key [prior]    'pager-page-up)
(global-set-key '[M-up]    'pager-row-up)
(global-set-key '[M-kp-8]  'pager-row-up)
(global-set-key '[M-down]  'pager-row-down)
(global-set-key '[M-kp-2]  'pager-row-down)

;; -------------------------------------------------- [ browse-kill-ring ]
;; Select something that you put in the kill ring ages ago.
(autoload 'browse-kill-ring "browse-kill-ring" "Browse the kill ring." t)
(global-set-key (kbd "C-c k") 'browse-kill-ring)
(eval-after-load "browse-kill-ring"
  '(progn
     (setq browse-kill-ring-quit-action 'save-and-restore)))

;; ------------------------------------------------------------- [ shell ]
(eval-after-load "shell"
  '(progn
     (ansi-color-for-comint-mode-on)))

;; ------------------------------------------------------------ [ ispell ]
(eval-after-load "ispell"
  '(progn
     ;; Use the -C option when running aspell, which will
     ;; ConsiderCamelCaseToBeCorrect
     (setq ispell-extra-args '("-C"))))

;; ------------------------------------------------------------- [ tramp ]
(eval-after-load "tramp"
  '(add-to-list 'tramp-default-method-alist
                '(".*\\.umich\\.edu\\'" "" "ssh")))

;; ----------------------------------------------------------- [ flymake ]
;; Mostly stolen from http://www.emacswiki.org/cgi-bin/emacs-en/FlymakeRuby
(eval-after-load "flymake"
  '(progn
     (push '(".+\\.rb$" flymake-ruby-init) flymake-allowed-file-name-masks)
     (push '("Rakefile$" flymake-ruby-init) flymake-allowed-file-name-masks)

     (push '("^\\(.*\\):\\([0-9]+\\): \\(.*\\)$" 1 2 nil 3)
           flymake-err-line-patterns)

     (set-face-background 'flymake-errline "red4")
     (set-face-background 'flymake-warnline "dark slate blue")))

;; ----------------------------------------------------------- [ ibuffer ]
;; *Nice* buffer switching
(global-set-key (kbd "C-x C-b") 'ibuffer)

(setq ibuffer-show-empty-filter-groups nil)
(setq ibuffer-saved-filter-groups
      '(("default"
         ("version control" (or (mode . svn-status-mode)
                    (mode . svn-log-edit-mode)
                    (name . "^\\*svn-")
                    (name . "^\\*vc\\*$")
                    (name . "^\\*Annotate")
                    (name . "^\\*git-")
                    (name . "^\\*vc-")))
         ("emacs" (or (name . "^\\*scratch\\*$")
                      (name . "^\\*Messages\\*$")
                      (name . "^TAGS\\(<[0-9]+>\\)?$")
                      (name . "^\\*Help\\*$")
                      (name . "^\\*info\\*$")
                      (name . "^\\*Occur\\*$")
                      (name . "^\\*grep\\*$")
                      (name . "^\\*Compile-Log\\*$")
                      (name . "^\\*Backtrace\\*$")
                      (name . "^\\*Process List\\*$")
                      (name . "^\\*gud\\*$")
                      (name . "^\\*Man")
                      (name . "^\\*WoMan")
                      (name . "^\\*Kill Ring\\*$")
                      (name . "^\\*Completions\\*$")
                      (name . "^\\*tramp")
                      (name . "^\\*shell\\*$")
                      (name . "^\\*compilation\\*$")))
         ("emacs source" (or (mode . emacs-lisp-mode)
                             (filename . "/Applications/Emacs.app")
                             (filename . "/bin/emacs")))
         ("agenda" (or (name . "^\\*Calendar\\*$")
                       (name . "^diary$")
                       (name . "^\\*Agenda")
                       (name . "^\\*org-")
                       (name . "^\\*Org")
                       (mode . org-mode)
                       (mode . muse-mode)))
         ("latex" (or (mode . latex-mode)
                      (mode . LaTeX-mode)
                      (mode . bibtex-mode)
                      (mode . reftex-mode)))
         ("dired" (or (mode . dired-mode))))))

(add-hook 'ibuffer-mode-hook
          (lambda ()
            (ibuffer-switch-to-saved-filter-groups "default")))

;; Order the groups so the order is : [Default], [agenda], [emacs]
(defadvice ibuffer-generate-filter-groups (after reverse-ibuffer-groups ()
                                                 activate)
  (setq ad-return-value (nreverse ad-return-value)))

;; ------------------------------------------------------------- [ tempo ]
(defun tempo-space ()
  (interactive "*")
  (or (tempo-expand-if-complete)
      (insert " ")))

;; ---------------------------------------------------------- [ org-mode ]
(define-key global-map "\C-cl" 'org-store-link)
(define-key global-map "\C-ca" 'org-agenda)
(define-key global-map "\C-co" 'org-jump-to-project-todo)

(eval-after-load 'org
  '(progn
     ;; Add all org files in the org directory to the agenda
     (mapcar
      (lambda (file)
          (add-to-list 'org-agenda-files file))
      (directory-files (expand-file-name "~/org/") t "\\.org"))))

;; --------------------------------------------------------- [ find-file ]

;; This should be the same as the default value of `cc-other-file-alist' except
;; for the addition of Objective-C ".m" and ".mm" files.
(setq cc-other-file-alist
      '(("\\.cc\\'"  (".hh" ".h"))
        ("\\.hh\\'"  (".cc" ".C"))

        ("\\.c\\'"   (".h"))
        ("\\.h\\'"   (".c" ".cc" ".C" ".CC" ".cxx" ".cpp" ".m" ".mm"))

        ("\\.m\\'"    (".h"))
        ("\\.mm\\'"    (".h"))

        ("\\.C\\'"   (".H"  ".hh" ".h"))
        ("\\.H\\'"   (".C"  ".CC"))

        ("\\.CC\\'"  (".HH" ".H"  ".hh" ".h"))
        ("\\.HH\\'"  (".CC"))

        ("\\.c\\+\\+\\'" (".h++" ".hh" ".h"))
        ("\\.h\\+\\+\\'" (".c++"))

        ("\\.cpp\\'" (".hpp" ".hh" ".h"))
        ("\\.hpp\\'" (".cpp"))

        ("\\.cxx\\'" (".hxx" ".hh" ".h"))
        ("\\.hxx\\'" (".cxx"))))

;; ----------------------------------------------------------- [ doxygen ]
;; Disable doxymacs prompts
(defadvice doxymacs-insert-function-comment (around no-prompt activate compile)
  "Prevents tempo from prompting during doxymacs template insertion"
  (let ((tempo-interactive nil)) ad-do-it))

(defadvice doxymacs-insert-file-comment  (around no-prompt activate compile)
  "Prevents tempo from prompting during doxymacs template insertion"
  (let ((tempo-interactive nil)) ad-do-it))

;; -----------------------------------------------------------------------
;; Prevent the bell from ringing all the time.
;; -----------------------------------------------------------------------
;; nice little alternative visual bell; Miles Bader <miles /at/ gnu.org>

;; TODO(erg): Figure out why that note doesn't appear in the mode-line-bar...
(defcustom mode-line-bell-string "ding" ; "♪"
  "Message displayed in mode-line by `mode-line-bell' function."
  :group 'user)
(defcustom mode-line-bell-delay 0.1
  "Number of seconds `mode-line-bell' displays its message."
  :group 'user)

;; internal variables
(defvar mode-line-bell-cached-string nil)
(defvar mode-line-bell-propertized-string nil)

(defun mode-line-bell ()
  "Briefly display a highlighted message in the mode-line.

The string displayed is the value of `mode-line-bell-string',
with a red background; the background highlighting extends to the
right margin.  The string is displayed for `mode-line-bell-delay'
seconds.

This function is intended to be used as a value of `ring-bell-function'."

  (unless (equal mode-line-bell-string mode-line-bell-cached-string)
    (setq mode-line-bell-propertized-string
      (propertize
       (concat
        (propertize
         "x"
         'display
         `(space :align-to (- right ,(string-width mode-line-bell-string))))
        mode-line-bell-string)
       'face '(:background "red")))
    (setq mode-line-bell-cached-string mode-line-bell-string))
  (message mode-line-bell-propertized-string)
  (sit-for mode-line-bell-delay)
  (message ""))

(setq ring-bell-function 'mode-line-bell)

;; -----------------------------------------------------------------------
;; Utility Methods
;; -----------------------------------------------------------------------
;; Taken from O'Reilly Writing Emacs Extensions p 30-31

;; Restrict buffer movement to existing buffers
(defadvice switch-to-buffer (before existing-buffer activate compile)
  "When interactive, switch to existing buffers only, unless given a
prefix argument"
  (interactive
   (list (read-buffer "Switch to buffer: "
              (other-buffer)
              (null current-prefix-arg)))))

;; -----------------------------------------------------------------------

(defadvice switch-to-buffer-other-window (before existing-buffer
                         activate compile)
  "When interactive, switch to existing buffers only, unless given a
prefix argument"
  (interactive
   (list (read-buffer "Switch to buffer: "
              (other-buffer)
              (null current-prefix-arg)))))

;; -----------------------------------------------------------------------

(defadvice switch-to-buffer-other-frame (before existing-buffer activate
                        compile)
  "When interactive, switch to existing buffers only, unless given a
prefix argument"
  (interactive
   (list (read-buffer "Switch to buffer: "
              (other-buffer)
              (null current-prefix-arg)))))

;; ------------------------------------------------- [ intelligent-close ]
(defun intelligent-close ()
  "quit a frame the same way no matter what kind of frame you are on.

This method, when bound to C-x C-c, allows you to close an emacs frame the
same way, whether it's the sole window you have open, or whether it's
a \"child\" frame of a \"parent\" frame.  If you're like me, and use emacs in
a windowing environment, you probably have lots of frames open at any given
time.  Well, it's a pain to remember to do Ctrl-x 5 0 to dispose of a child
frame, and to remember to do C-x C-x to close the main frame (and if you're
not careful, doing so will take all the child frames away with it).  This
is my solution to that: an intelligent close-frame operation that works in
all cases (even in an emacs -nw session).

Stolen from http://www.dotemacs.de/dotfiles/BenjaminRutt.emacs.html."
  (interactive)
  (if (eq (car (visible-frame-list)) (selected-frame))
      ;;for parent/master frame...
      (if (> (length (visible-frame-list)) 1)
          ;;close a parent with children present
          (delete-frame (selected-frame))
        ;;close a parent with no children present
        (save-buffers-kill-emacs))
    ;;close a child frame
    (delete-frame (selected-frame))))

(global-set-key "\C-x\C-c" 'intelligent-close) ;forward reference

;; -----------------------------------------------------------------------
;; Helper Functions (used in mode startup)
;; -----------------------------------------------------------------------
;; --------------------------------------------- [ start-programing-mode ]
(defun start-programing-mode()
  (interactive)

  ;; Display column numbers only in code.
  (column-number-mode t)

  ;; Setup flyspell to make me not look like an idiot to my coworkers
  ;; and Haeleth and whoever else reads my code.
  (flyspell-prog-mode)

  ;; All trailing whitespace needs to be highlighted so it can die.
  (setq show-trailing-whitespace t)

  ;; Highlight matching parenthesis (and other bracket likes)
  (show-paren-mode t))

;; ------------------------------------------- [ my-start-scripting-mode ]
(defun my-start-scripting-mode (file-extension hash-bang)
  ;; All scripting languages are programming languages
  (start-programing-mode)

  (local-set-key "\C-css" 'insert-script-seperator-line)
  (local-set-key "\C-csh" 'insert-script-section-header)
  (local-set-key "\C-csb" 'insert-script-big-header)

  ;; Build a startup template for this mode.
  (my-start-autoinsert)
  (tempo-define-template (concat file-extension "startup")
                         (list (concat hash-bang "\n\n")))
  (push (cons (concat "\\." file-extension "$")
              (intern (concat "tempo-template-" file-extension "startup")))
        auto-insert-alist)

  ;; Make the script executable on save
  (add-hook 'after-save-hook
            'executable-make-buffer-file-executable-if-script-p
            nil t))

;; -------------------------------------------------- [ select-vc-status ]
(defun select-vc-status ()
  "Calls for a directory and calls `svn-status' or `git-status' depending on what
type of version control found in that directory"
  (interactive)
  (let* ((local-default-dir (ftf-project-directory))
         (targetDir
          (read-directory-name "Status of directory: "
                               local-default-dir
                               local-default-dir
                               nil)))
    (cond ((file-exists-p (concat targetDir "/.git"))
           (git-status targetDir))
          ((file-exists-p (concat targetDir "/.svn"))
           (svn-status targetDir))
          ((file-exists-p (concat targetDir "/CVS"))
           (cvs-status targetDir)))))

;; ------------------------------------------------- [ flymake-ruby-init ]
(defun flymake-ruby-init ()
  "Stolen from http://www.emacswiki.org/cgi-bin/emacs-en/FlymakeRuby."
  (let* ((temp-file   (flymake-init-create-temp-buffer-copy
                       'flymake-create-temp-inplace))
     (local-file  (file-relative-name
                       temp-file
                       (file-name-directory buffer-file-name))))
    (list "ruby" (list "-c" local-file))))

;; ------------------------------------------------ [ setup-ruby-flymake ]
(defun setup-ruby-flymake ()
  "Also stolen from http://www.emacswiki.org/cgi-bin/emacs-en/FlymakeRuby."
  (require 'flymake)
  (if (not (null buffer-file-name))
      (flymake-mode)))

;; ----------------------------------------------- [ my-start-autoinsert ]
(defun my-start-autoinsert ()
  "Helper function called from anything that puts in a template
from an empty file."
  (interactive)
  (require 'autoinsert)
  (add-hook 'find-file-hooks 'auto-insert)
  (setq auto-insert-alist '())
  (setq auto-insert-query nil)
  (require 'tempo))

;; -----------------------------------------------------------------------
;;  Mode Hooks (aka the other way to make emacs fast)
;; -----------------------------------------------------------------------
;; ----------------------------------------------- [ Compilation startup ]
(defun my-compilemode-startup ()
  "I want to be able to treat compilation windows like part of the current
project, so if I'm in the compilation buffer, [f3] and [f5] work properly."
  ;; TODO: This causes recursion and thus breaks all compile-mode
  ;; commands. Investigate this further later.
  ;; (setup-project-for-local-buffer)
)

(add-hook 'compilation-mode-hook 'my-compilemode-startup)

;; -------------------------------------------------- [ Makefile startup ]
(defun my-makefile-startup ()
  "Setup how I like editing makefiles (Allow for project access, etc."
  (interactive)
  (start-programing-mode)

  (local-set-key "\C-css" 'insert-script-seperator-line)
  (local-set-key "\C-csh" 'insert-script-section-header)
  (local-set-key "\C-csb" 'insert-script-big-header))

(add-hook 'makefile-mode-hook 'my-makefile-startup)

;; -------------------------------------------------- [ Org Mode startup ]
(defun my-org-mode-startup ()
  "Setup org mode so its useful."
  (setq org-log-done t)
  (setq org-odd-levels-only t)
  (setq org-hide-leading-stars t))

(add-hook 'org-mode-hook 'my-org-mode-startup)

;; ----------------------------------------------------- [ LaTeX startup ]
(defun my-LaTeX-startup ()
  "Change the default LaTeX environment."
  (interactive)
  ;; We want to automatically wrap paragraphs in LaTeX mode...
  (filladapt-mode)
  ;; Set up {fly,i}spell to do the right thing
  (flyspell-mode t)
  (make-local-variable 'ispell-parser)
  (setq ispell-parser 'tex))

(add-hook 'LaTeX-mode-hook 'my-LaTeX-startup)   ;; AUCTex latex mode
(add-hook 'latex-mode-hook 'my-LaTeX-startup)   ;; Emacs latex mode

;; --------------------------------------------------- [ Haskell startup ]
(defun my-haskell-startup ()
  "Change the default haskell environment."
  (interactive)
  (start-programing-mode)

  (ftf-add-filetypes '("*.hs"))

  (turn-on-haskell-doc-mode)
  (turn-on-haskell-indentation)
  (turn-on-haskell-decl-scan))

(add-hook 'haskell-mode-hook 'my-haskell-startup)

;; ------------------------------------------------------- [ Lua startup ]
(defun my-lua-startup ()
  "Change the default lua environment."
  (interactive)
  (start-programing-mode)
  (ftf-add-filetypes '("*.lua"))
  (set (make-local-variable 'lua-indent-level) default-tab-width))

(add-hook 'lua-mode-hook 'my-lua-startup)

;; ------------------------------------------------------ [ Perl Startup ]
(defun my-perl-startup ()
  "Setup perl."
  (interactive)
  (local-set-key '[pause] 'perldb)
  (setq gud-perldb-command-name "perl -w ") ; For warnings
  (setq tab-width 8)
  (setq indent-tabs-mode nil)  ; Autoconvert tabs to spaces
  (setq perl-indent-level 2)
  (setq perl-tab-always-indent nil) ; Indent if at left margin, else tab
  (setq perl-continued-statement-offset 2)
  (setq perl-continued-brace-offset -2)
  (my-start-scripting-mode "pl" "#!/usr/bin/perl"))

(add-hook 'perl-mode-hook 'my-perl-startup)

;; ---------------------------------------------- [ Shell script startup ]
(defun my-shellscript-startup ()
  "Setup shell script mode."
  (interactive)
  (my-start-scripting-mode "sh" "#!/bin/bash"))

(add-hook 'sh-mode-hook 'my-shellscript-startup)

;; ---------------------------------------------------- [ Python startup ]
(defun my-python-startup ()
  "Setup Python style."
  (interactive)
  (local-set-key '[f4] 'pdb)
  (setq tab-width 2)
  (setq indent-tabs-mode nil)  ; Autoconvert tabs to spaces
  (setq python-indent 2)
  (setq python-continuation-offset 2)
  (setq py-smart-indentation nil)
  (my-start-scripting-mode "py" "#!/usr/bin/python"))

(add-hook 'python-mode-hook 'my-python-startup)

;; ------------------------------------------------------ [ Ruby startup ]
(defun my-ruby-startup ()
  "Setup Ruby."
  (interactive)
  (local-set-key '[f4] 'rubydb)

  (my-start-scripting-mode "rb" "#!/home/eglaysher/bin/ruby")

  ;; Ruby uses flymake for the win.
  (setup-ruby-flymake)

  (setq ri-ruby-script
        (expand-file-name "~/.elliot-unix/bin/ri-emacs.rb"))
  (autoload 'ri "ri-ruby.el" nil t))

(add-hook 'ruby-mode-hook 'my-ruby-startup)

;; ------------------------------------------- [ my-common-c-ish-startup ]
(defun my-common-c-ish-startup ()
  (interactive)
  (start-programing-mode)

  (require 'google-c-style)
  (google-set-c-style)

  ;; Load and start up filladapt
  (require 'filladapt)
  (c-setup-filladapt)
  (filladapt-mode)

  (require 'whitespace)
  (set (make-local-variable 'whitespace-style) '(lines-tail))
  (whitespace-mode t)

  (local-set-key "\C-o" 'ff-get-other-file))

(add-hook 'c-mode-common-hook 'my-common-c-ish-startup)

;; --------------------------------------------------------- [ C startup ]
(defun my-c-startup ()
  "Change C C++ and Obj-C indents."
  (interactive)

  (local-set-key "\C-css" 'insert-c-seperator-line)
  (local-set-key "\C-csh" 'insert-c-section-header))

(add-hook 'c-mode-hook 'my-c-startup)

;; ------------------------------------------------------- [ C++ startup ]
(defun my-c++-startup ()
  (interactive)

  ;; Load and start up doxymacs when in C++ mode
  (require 'cc-vars)
  (doxymacs-mode)
  (doxymacs-font-lock)

  ;; Now that doxymacs is loaded, we set up skeletons for hpp files.
  (my-start-autoinsert)

  (require 'e-tempoTemplates)
  (tempo-use-tag-list 'c++-tempo-tags)
  (setq tempo-match-finder "\\(?:^\\|[ \t\n]\\)\\([#&@_[:word:]]+\\)\\=")
  (local-set-key " " 'tempo-space)
  (local-set-key "\C-c\C-f" 'tempo-forward-mark)
  (local-set-key "\C-c\C-b" 'tempo-backward-mark)

  (add-to-list 'auto-insert-alist
               '("\\.hpp$" . tempo-template-hpp-startup))
  (add-to-list 'auto-insert-alist
               '("\\.cpp$" . tempo-template-cpp-startup))
  ;; More specific forms come afterwards
  (add-to-list 'auto-insert-alist
               '("rlvm\\/.*\\.hpp$" . tempo-template-rlvm-hpp-startup))
  (add-to-list 'auto-insert-alist
               '("rlvm\\/.*\\.cpp$" . tempo-template-rlvm-cpp-startup))

  (local-set-key "\C-css" 'insert-c++-seperator-line)
  (local-set-key "\C-csh" 'insert-c++-section-header)
  (local-set-key "\C-csb" 'insert-c++-big-header))

(add-hook 'c++-mode-hook 'my-c++-startup)

;; ------------------------------------------------ [ Emacs Lisp Startup ]
(defun my-elisp-startup ()
  (interactive)
  (start-programing-mode)

  (ftf-add-filetypes '("*.el"))

  ;; Byte compile this file as soon as its saved.
  (setq byte-compile-warnings nil)
  (make-local-variable 'after-save-hook)
  (add-hook 'after-save-hook
        '(lambda () (byte-compile-file buffer-file-name))
        nil t)

  ;; When editing elisp code, we want hippie expand to reference emacs
  ;; lisp symbols. (Note: We are shifting this onto the front of the
  ;; list, so put this so -partially is called first)
  (make-local-variable 'hippie-expand-try-functions-list)
  (add-to-list 'hippie-expand-try-functions-list
               'try-complete-lisp-symbol)
  (add-to-list 'hippie-expand-try-functions-list
               'try-complete-lisp-symbol-partially)

  ;; Define lisp key macros
  (local-set-key "\C-css" 'insert-elisp-seperator-line)
  (local-set-key "\C-csh" 'insert-elisp-section-header)
  (local-set-key "\C-csb" 'insert-elisp-big-header))

(add-hook 'emacs-lisp-mode-hook 'my-elisp-startup)

;; --------------------------------------------- [ Markdown Mode Startup ]
(defun my-markdown-startup ()
  (interactive)
  (longlines-mode t))

(add-hook 'markdown-mode-hook 'my-markdown-startup)

;; ------------------------------------------------- [ Text Mode Startup ]
(defun my-textmode-startup ()
  (interactive)
  (filladapt-mode t)
  (flyspell-mode t)
  (local-set-key "\C-css" 'insert-text-seperator-line))

(add-hook 'text-mode-hook 'my-textmode-startup)

;; ----------------------------------------- [ SVN Log Edit Mode Startup ]
(defun my-svn-load-edit-mode-startup ()
  (interactive)
  (filladapt-mode t)
  (show-paren-mode t)
  (flyspell-mode t))

(add-hook 'svn-log-edit-mode-hook 'my-svn-load-edit-mode-startup)