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

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

;; -----------------------------------------------------------------------
;; Garbage Collector
;; -----------------------------------------------------------------------
;; We have extra ram these days. Use 3 megs of memory to speed up
;; runtime a bit. This shaves off about 1/10 of a second on startup.
(setq gc-cons-threshold (max 3000000 gc-cons-threshold))

;; -----------------------------------------------------------------------
;; 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)
        (font . "Bitstream Vera Sans Mono-12")
        (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))))

;; -----------------------------------------------------------------------
;; Project root
;; -----------------------------------------------------------------------
(require 'project-root)
(setq project-roots
      '(("Scons Project" :root-contains-files ("SConstruct"))
        ("Generic Perl Project" :root-contains-files ("t" "lib"))))

;; My additions...
(require 'erg-project-root)

;; -----------------------------------------------------------------------
;; Personal Keybindings
;; -----------------------------------------------------------------------
(global-set-key '[f2] 'project-root-grep)
(global-set-key '[f3] 'select-vc-status)
(global-set-key '[f4] 'gdb)
(global-set-key '[f5] 'compile)
;;;;;;; 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)
(global-set-key "\M-/" 'hippie-expand)
(global-set-key (kbd "M-SPC") 'hippie-expand)
(setq hippie-expand-try-functions-list
      '(try-expand-dabbrev
        try-complete-file-name
        try-expand-all-abbrevs
        try-expand-list
        try-expand-dabbrev-all-buffers
        try-expand-dabbrev-from-kill))

;; -----------------------------------------------------------------------
;; Global Hook Additions
;; -----------------------------------------------------------------------
;;(add-hook 'before-save-hook 'copyright-update)
;;(setq-default copyright-query nil)

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

;; 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)
                ("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.4/haskell-site-file")
(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)
(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
(add-hook 'haskell-mode-hook 'turn-on-haskell-decl-scan)

;; ---------------------------------------------------------- [ ido-mode ]
(require 'ido)
(ido-mode t)

;; ---------------------------------------------------------- [ 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/"))))

;; ------------------------------------------------------------- [ 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"))))

;; ----------------------------------------------------------- [ 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)))))

;; -------------------------------------------------------- [ grepsource ]
;; (defconst grepsource-command
;;   "find . -name \"*.c\" -or -name \"*.cc\" -or -name \"*.cpp\" -or -name \"*.m\" -or -name \"*.mm\" -or -name \"*.java\" -or -name \"*.h\" -or -name \"*.hh\" -or -name \"*.hpp\" -or -name \"*.el\" | xargs grep -n "
;;   "Base command for grepsource. (Basically quoted version of
;; whatever my current grepsource alias is.")

;; (defun grepsource (cmd-args)
;;   "Invoke an in-emacs equivalent of my grepsource bash alias,
;; defaulting withing the current project."
;;   (interactive (list (read-from-minibuffer "Grep project for string: ")))
;;   (let ((default-directory (or local-project-root default-directory)))
;;     (grep (concat grepsource-command "\""
;;                   (replace-regexp-in-string "\"" "\\\\\"" cmd-args) "\""))))

;; ------------------------------------------------- [ 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)

  (project-root-fetch)

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

;; --------------------------------------- [ find-root-project-directory ]
(defun find-root-project-directory (current-directory)
  "Finds the root directory of the project. Currently looks for
the existance of both a src/ and etc/ directory."
  (cond
   ;; If we've worked our way up to the root directory cut out.
   ((or (string= current-directory "/opt/local/")
        (string= current-directory "/opt/")
        (string= current-directory "/usr/")
        (string= current-directory "/sw/")
        (string= current-directory "/"))
    nil)
   ((or (file-exists-p (concat current-directory "OMakeroot"))
        (file-exists-p (concat current-directory ".git"))
        (file-exists-p (concat current-directory "etc")))
    current-directory)
   (t
    (find-root-project-directory
     (expand-file-name (concat current-directory "../"))))))

;; -------------------------------------------------- [ 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
          (if (project-root-p) (cdr project-details) default-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)))))

;; ------------------------------------- [ set-up-ffap-alist-for-project ]
(defun set-up-ffap-alist-for-project ()
  "Makes the variable `ffap-c-path' contain interesting locations for the
current project."
  (require 'ffap)
  (make-local-variable 'ffap-c-path)
  (when (project-root-p)
    (let ((project-dir (cdr project-details)))
      (add-to-list 'ffap-c-path project-dir)
      (let ((include-dir (expand-file-name (concat project-dir "include"))))
        (if (file-exists-p include-dir)
            (add-to-list 'ffap-c-path include-dir))))))

;; ------------------------------------------------- [ 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)
;; -----------------------------------------------------------------------
;; -------------------------------------------------- [ 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

;; ------------------------------------------------------- [ Lua startup ]
(defun my-lua-startup ()
  "Change the default lua environment."
  (interactive)
  (start-programing-mode)
  (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" "#!/usr/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)

  (auto-revert-mode t)

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

  (when (project-root-p)
    (local-set-key '[f4] 'erg-project-root-gdb)
    (local-set-key '[f5] 'erg-project-root-compile)
    (set-up-ffap-alist-for-project)))

(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)
  (local-set-key "\C-o" 'ff-get-other-file))

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

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

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

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

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