User:Gwern/.emacs

From Wikipedia, the free encyclopedia

;.emacs.el --- my Emacs customizations

;Copyright (C) 2006, 2007 by Gwern Branwen
;License: Public domain
;When:  Time-stamp: "2007-12-23 19:56:42 gwern"
;Keywords: local,customization,emacs,gnu,dot,public domain

;Commentary
;;The first section sets and modifies stuff directly, invoking and tweaking
;;packages and settings that come with a modern vanilla Emacs:  scrolling,
;;key bindings, etc. The second section handles downloaded files and addons.
;;The fourth section is reserved for Customize.

;Table of contents
;;1: TO DO
;;2: EMACS
;;3: PACKAGES
;;4: CUSTOM

;;;;;;;;;;;;;;;;;;;
;;;; TO DO ;;;;;;;;
;;;;;;;;;;;;;;;;;;;
;work in powermacro <http://www.blackie.dk/emacs/>
;Figure out a way to have C-x # work as C-x 5 0 if no client is open
;Work in predictive text completion
;;Highlight-trailing line

;;;;;;;;;;;;;;;;
;;; EMACS  ;;;;;
;;;;;;;;;;;;;;;;
; Ideally things would be done through Customization, but sometimes variables
; or hooks just aren't setup to go through Customization. So they go in here.

;Add the directory I keep all my special .el files in default load path.
(setq load-path (push "~/.emacs.d/" load-path))

;Gentoo by default stores stuff here. Emacs packages installed through the
;system are only accessible through this.
(when (file-exists-p "/usr/share/emacs/site-lisp/site-gentoo.el")
  (load "/usr/share/emacs/site-lisp/site-gentoo"))

;Do without those obnoxious startup messages
(eval '(setq inhibit-startup-echo-area-message (user-login-name)))

;Modify the mode-line as well. This is a cleaner setup than the
;default settings for the mode-line.
(setq default-mode-line-format
      '("-"
        mode-line-mule-info
        mode-line-modified
        mode-line-frame-identification
        mode-line-buffer-identification
        "  "
        global-mode-string
        "   %[(" mode-name mode-line-process minor-mode-alist "%n"
        ")%]--"
        (line-number-mode "L%l--")
        (column-number-mode "C%c--")
        (-3 . "%p")
        "-%-"))

(if (not window-system)
    ;While we are getting rid of stuff, let's get rid of the buttons.
    ;The menu is useful, so we will keep that (can be accessed by C-right click), but the
    ;buttons are  redundant with the menu options, and I know most of the keybindings
    ;for the buttons, anyway.
    ;Turn off the status bar if we're not in a window system. I currently have it always off.
    (menu-bar-mode t) ; else
  (menu-bar-mode -1))

;Rearrange the menubars, so it goes tools, buffers, help.
(setq menu-bar-final-items '(tools buffer help-menu))

;Don't echo passwords when communicating with interactive programs.
(add-hook 'comint-output-filter-functions 'comint-watch-for-password-prompt)

;Use ANSI colors within sh-mode
(add-hook 'sh-mode-hook 'ansi-color-for-comint-mode-on)

;Enable narrowing of regions
(put 'narrow-to-region 'disabled nil)

;Allow a command to erase an entire buffer
(put 'erase-buffer 'disabled nil)

;Change cutting behaviour:
;"Many times you'll do a kill-line command with the only intention of getting
;the contents of the line into the killring. Here's an idea stolen from Slickedit,
;if you press copy or cut when no region is active you'll copy or cut the current line:"
;<http://www.zafar.se/bkz/Articles/EmacsTips>
(defadvice kill-ring-save (before slickcopy activate compile)
  "When called interactively with no active region, copy a single line instead."
  (interactive
   (if mark-active (list (region-beginning) (region-end))
     (list (line-beginning-position)
           (line-beginning-position 2)))))

(defadvice kill-region (before slickcut activate compile)
  "When called interactively with no active region, kill a single line instead."
  (interactive
   (if mark-active (list (region-beginning) (region-end))
     (list (line-beginning-position)
           (line-beginning-position 2)))))

;Don't bother entering search and replace args if the buffer is
;read-only. Duh.
(defadvice query-replace-read-args (before barf-if-buffer-read-only
                                           activate)
  "Signal a `buffer-read-only' error if the current buffer is read-only."
  (barf-if-buffer-read-only))

;Answer y or n instead of yes or no at minibar prompts.
(defalias 'yes-or-no-p 'y-or-n-p)

;'Woman' offers completion better than 'man'.
(defalias 'man 'woman)

; I mistype this often.
(defalias 'eval-when-load 'eval-after-load)

;;Push the mouse out of the way when the cursor approaches.
(if window-system
    (progn
      (autoload 'avoid "avoid" "Avoid mouse and cursor being near each other")
      (eval-after-load 'avoid (mouse-avoidance-mode 'jump))))

;Make cursor stay in the same column when scrolling using pgup/dn.
;Previously pgup/dn clobbers column position, moving it to the
;beginning of the line.
;<http://www.dotemacs.de/dotfiles/ElijahDaniel.emacs.html>
(defadvice scroll-up (around ewd-scroll-up first act)
  "Keep cursor in the same column."
  (let ((col (current-column)))
    ad-do-it
    (move-to-column col)))
(defadvice scroll-down (around ewd-scroll-down first act)
  "Keep cursor in the same column."
  (let ((col (current-column)))
    ad-do-it
    (move-to-column col)))

;Add alternatives to M-x, on the recommendation of Steve Yegge.
;<http://steve.yegge.googlepages.com/effective-emacs>
(global-set-key "\C-x\C-m" 'execute-extended-command)
(global-set-key "\C-c\C-m" 'execute-extended-command)

;C-x k is a command I use often, but C-x C-k (an easy mistake) is
;bound to nothing! Set C-x C-k to same thing as C-x k.
(global-set-key "\C-x\C-k" 'kill-buffer)
(global-set-key "\C-x\C-c"
                '(lambda () (interactive)
                   (progn (get-buffer-create "*scratch*")
                          (kill-buffer "*scratch*")
                          (save-buffers-kill-emacs t))))

;IMPORTANT! This overrides a default binding!
;I don't use C-l much, and it makes more sense to me for it
;to kill backwards the line, like C-k kills forward the line.
;;define the function to kill the characters from the cursor
;;to the beginning of the current line
(defun backward-kill-line (arg)
  "Kill chars backward until encountering the end of a line."
  (interactive "p")
  (kill-line 0))
(global-set-key "\C-l" 'backward-kill-line)

; Enable smart syntax based deletion commands.
;IMPORTANT! This overrides default bindings!
;<http://www.zafar.se/bkz/Articles/EmacsTips>
(global-set-key [(meta backspace)] 'kill-syntax-backward)
(global-set-key [(meta d)] 'kill-syntax-forward)
(defun kill-syntax-forward ()
  "Kill characters with syntax at point."
  (interactive)
  (kill-region (point)
               (progn (skip-syntax-forward (string (char-syntax (char-after))))
                      (point))))
(defun kill-syntax-backward ()
  "Kill characters with syntax at point."
  (interactive)
  (kill-region (point)
               (progn (skip-syntax-backward (string (char-syntax (char-before))))
                      (point))))

;I like M-g for goto-line
(global-set-key "\M-g" 'goto-line)

;Change C-x C-b behavior so it uses bs; shows only interesting
;buffers.
(global-set-key "\C-x\C-b" 'bs-show)

;IMPORTANT! This overrides the default binding!
;The idea is to sort of imitate Stumpwm for buffer management, so to speak.
(global-set-key "\C-n" 'bury-buffer)
(global-set-key "\C-p" '(lambda () (interactive) (switch-to-buffer (other-buffer))))

; Need because of Urxvt
(global-set-key "\M-o\ c" 'forward-word)
(global-set-key "\M-o\ d" 'backward-word) ;this overrides some fontlock binding
(global-set-key [clearline] 'end-of-buffer) ;dunno, but C-Home appears as this to Urxvt

;I never use set-fill-column and I hate hitting it by accident.
(global-set-key "\C-x\ f" 'find-file)

;M-down and M-up do nothing! :(  Let's make them do something, like M-left
; and M-right do.
(global-set-key [M-down] '(lambda () (interactive) (progn (forward-line 10) (recenter) ) ))
(global-set-key [M-up]   '(lambda () (interactive) (progn (forward-line -10) (recenter) ) ))

;Need edmacro to work with iswitchb buffer switching
(require 'edmacro) ;use require because it's needed right away

;Enable iswitchb buffer mode. I find it easier to use than the
;regular buffer switching. While we are messing with buffer
;movement, the second sexp hides all the buffers beginning
;with "*". The third and fourth sexp does some remapping.
;My instinct is to go left-right in a completion buffer, not C-s/C-r
(eval-when-compile 'iswitchb)
(autoload 'iswitchb "iswitchb" "")
(eval-after-load 'iswitchb '(progn
                              (iswitchb-mode 1)
                              (defun iswitchb-local-keys ()
                                (mapc (lambda (K)
                                        (let* ((key (car K)) (fun (cdr K)))
                                          (define-key iswitchb-mode-map (edmacro-parse-keys key)
                                            fun)))
                                      '(("<right>" . iswitchb-next-match)
                                        ("<left>"  . iswitchb-prev-match)
                                        ("<up>"    . ignore             )
                                        ("<down>"  . ignore             ))))
                              (add-hook 'iswitchb-define-mode-map-hook 'iswitchb-local-keys)))

;"To hit tab to auto-complete (like bash does) put this in your .emacs:"
;<http://www.emacswiki.org/cgi-bin/wiki/EmacsNiftyTricks>
(defun indent-or-complete ()
  "Complete if point is at end of line, and indent line."
  (interactive)
  (if (and (looking-at "$") (not (looking-back "^\\s-*")))
      (hippie-expand nil))
  (indent-for-tab-command))
(add-hook 'find-file-hooks (function (lambda ()
                                       (local-set-key (kbd "<tab>") 'indent-or-complete))))

;"Rebind <RET> key to do automatic indentation in certain modes (not haskell-mode)."
;<http://www.metasyntax.net/unix/dot-emacs.html>
(mapc
 (lambda (mode)
   (let ((mode-hook (intern (concat (symbol-name mode) "-hook"))))
     (add-hook mode-hook (lambda nil (local-set-key (kbd "RET") 'newline-and-indent)))))
 '(ada-mode c-mode c++-mode cperl-mode emacs-lisp-mode java-mode html-mode lisp-mode perl-mode
            php-mode prolog-mode ruby-mode scheme-mode sgml-mode sh-mode sml-mode tuareg-mode))

;"These tell Emacs to associate certain filename extensions with
;certain modes.  I use cc-mode.el (c++-mode) for C as well as C++
;code.  It is fairly all-encompassing, also working with other
;C-like languages, such as Objective C and Java."
(setq auto-mode-alist (cons '("\.el$" . emacs-lisp-mode) auto-mode-alist)
      auto-mode-alist (cons '("\.emacs" . emacs-lisp-mode) auto-mode-alist)
      auto-mode-alist (cons '("\.lisp" . lisp-mode) auto-mode-alist)
      auto-mode-alist (cons '("\.stumpwm" . slime-mode) auto-mode-alist)
      auto-mode-alist (cons '("\.stumpwmrc" . slime-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.C$" . c++-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.c$" . c++-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.cc$" . c++-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.cpp$" . c++-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.cxx$" . c++-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.doc$" . text-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.fonts.conf$" . sgml-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.h$" . c++-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.hs$" . haskell-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.lhs$" . literate-haskell-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.perl$" . perl-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.pl$" . perl-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.plan$" . text-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.plx$" . perl-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.screenrc$" . sh-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.sh$" . sh-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.ss$" . scheme-mode) auto-mode-alist) ;Scheme
      auto-mode-alist (cons '("\\.tcl$" . tcl-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.text$" . text-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.toprc$" . sh-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.txt$" . text-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.zsh$" . sh-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\CHANGELOG" . c++-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\INSTALL" . text-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\README$" . text-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\TODO$" . text-mode) auto-mode-alist)
      auto-mode-alist (cons '("mutt\-.*" . mail-mode) auto-mode-alist)
      auto-mode-alist (cons '("stumpwm.sbcl" . slime-mode) auto-mode-alist)
      auto-mode-alist (cons '("\\.awk$" . awk-mode) auto-mode-alist)

      completion-ignored-extensions (append completion-ignored-extensions
                                            '(".CKP" ".u" ".press" ".imp" ".BAK" ".bak")))
(put 'eval-expression 'disabled nil)

;"Set up highlighting of special words for selected modes."
; <http://www.metasyntax.net/unix/dot-emacs.html>
(make-face 'taylor-special-words)
(set-face-attribute 'taylor-special-words nil :foreground "White" :background "Firebrick")
(let ((pattern "\\<\\(FIXME\\|TODO\\|NOTE\\|WARNING\\|BUGS\\|USE\\):"))
  (mapc
   (lambda (mode)
     (font-lock-add-keywords mode `((,pattern 1 'taylor-special-words prepend))))
   '(ada-mode c-mode c++-mode cperl-mode emacs-lisp-mode java-mode haskell-mode
              literate-haskell-mode html-mode lisp-mode php-mode python-mode ruby-mode
              scheme-mode sgml-mode sh-mode sml-mode tuareg-mode)))

(defun byte-compile-visited-file ()
  (let ((byte-compile-verbose t))
    (byte-compile-file buffer-file-name)))
(add-hook 'emacs-lisp-mode-hook
          (lambda ()
            (when buffer-file-name
              (add-hook 'after-save-hook
                        'byte-compile-visited-file
                        nil t))))

;Tramp does remote file-access. This is very slow to load! You definitely want to autoload!
(autoload 'tramp "tramp" "Remotely access files." t)

;<http://www.cabochon.com/~stevey/blog-rants/my-dot-emacs-file.html>
(defun rename-file-and-buffer (new-name)
  "Renames both current buffer and file it is 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))))))
(global-set-key "\C-x\ W" 'rename-file-and-buffer)

;Make completion buffers in a shell disappear after 10 seconds.
;<http://snarfed.org/space/why+I+don't+run+shells+inside+Emacs>
(add-hook 'completion-setup-hook
          (lambda () (run-at-time 10 nil
                                  (lambda () (delete-windows-on "*Completions*")))))

(autoload 'browse-url "browse-url" "Open up in browsers hyperlinks." t) ;ditto
;When browsing in Gnus, sometimes it's a good idea to open up something graphically.
(global-set-key "\C-\M-b" 'browse-url-elinks-emacs) ;;TODO: not currently defined.

;Since I use a modern setup, UTF-8 is no problem, and this should guarantee that
;Wikipedia articles won't get messed up.
(set-language-environment "UTF-8")
(set-buffer-file-coding-system 'utf-8)

;Add good shortcut for flyspell. The hook makes sure when flyspell-mode is on,
;the buffer gets scanned.
(defun flyspell nil "Do the expected default, which is run flyspell on the whole buffer."
  (interactive)
  (flyspell-buffer))
(add-hook 'flyspell-mode-hook 'flyspell-buffer)

; After we add a word to Ispell or correct something, flyspell's highlighting may become
; outdated. Let's re-run highlighting after a correction.
(defadvice ispell (after advice)
  (flyspell-buffer))
(ad-activate 'ispell t)
(defadvice ispell-word (after advice)
  (flyspell-buffer))
(ad-activate 'ispell-word t)

;Turns tabs into spaces
(defun ska-untabify ()
  "My untabify function as discussed and described at
 http://www.jwz.org/doc/tabs-vs-spaces.html
 and improved by Claus Brunzema:
 - return nil to get `write-contents-hooks' to work correctly
   (see documentation there)
 - `make-local-hook' instead of `make-local-variable'
 - when instead of if"
  (save-excursion
    (goto-char (point-min))
    (when (search-forward "\t" nil t)
      (untabify (1- (point)) (point-max)))
    nil))
(add-hook 'after-save-hook
          '(lambda ()
             (make-local-hook 'write-contents-hooks)
             (add-hook 'write-contents-hooks 'ska-untabify nil t)))

; This macro is used while editing my .procmailrc for sed-formatting escaped strings.
(fset 'sedize
      (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item
                                                                   (quote
                                                                    ([home home 45 101 32
                                                                           39 115 47 94 end
                                                                           46 42 36 47 47
                                                                           39 down home]
                                                                     0 "%d")) arg)))
(add-hook 'sh-mode-hook
          '(lambda ()
             (define-key sh-mode-map "\C-e" 'sedize)))

;;;;;;;;;;;;;;;;;;;
;;;;;PACKAGES;;;;;;
;;;;;;;;;;;;;;;;;;;
;;I send all customizations dealing with Lisp files which set new modes
;;here. All the preceding dealt with usual Emacs options.

;; This was installed by package-install.el.
;; This provides support for the package system and
;; interfacing with ELPA, the package archive.
;; Move this code earlier if you want to reference
;; packages in your .emacs.
; <http://tromey.com/elpa/>
(setq load-path (push "~/.emacs.d/elpa" load-path))
(when (require 'package)
  (if (fboundp 'package-initialize) (package-initialize)))

; Idle-require is provided through ELPA
(eval-when-compile (require 'idle-require))
; Load things in downtime.
(autoload 'idle-require "" "")
(eval-after-load "idle-require"
              (if (fboundp 'idle-require-mode) (idle-require-mode 1)))

;Convenience function. Idle-require expects you to setq all at once, but
;a readable .emacs would require setq-ing all over the place.
(defun idle (arg)
  (if idle-require-symbols
      (setq idle-require-symbols (push arg idle-require-symbols)) ; Variable already has stuff
    (setq idle-require-symbols arg))) ;is nil, so set it to something

;Add browse-kill-ring extension. Lets you see your kill-ring as a
;buffer. Included by default; available also as an add-on.
;<http://www.todesschaf.org/projects/bkr.html>
(autoload 'browse-kill-ring "browse-kill-ring" "Browse text saved to the kill ring." t)

;This supposedly lets the VC interface use darcs.
;<http://www.emacswiki.org/cgi-bin/wiki/vc-darcs.el>
(autoload 'vc-darcs-find-file-hook "vc-darcs")
(add-to-list 'vc-handled-backends 'DARCS)
(add-hook 'find-file-hooks 'vc-darcs-find-file-hook)

;Let's try using darcsum instead of vc-darcs. I've heard good things about it.
(autoload 'darcsum "" "")
(setq idle-require-symbols "darcsum")

;"Recentf is a minor mode that builds a list of recently opened
;files. This list is is automatically saved across Emacs sessions.
;You can then access this list through a menu."
;<http://www.emacswiki.org/cgi-bin/wiki/recentf-buffer.el>
(idle "recentf")
(eval-after-load "recentf" '(progn
                              (setq recentf-auto-cleanup 'never) ;To protect tramp
                              (recentf-mode 1)))

;Force dupwords to be loaded. Dupwords goes through a text looking
;for areas with the same word more than once within a set range.
;Remember! The commands don't start with "dupwords", but with "dw"!
;<http://www.damtp.cam.ac.uk/user/sje30/emacs/dupwords.el>
(eval-when-compile 'dupwords)
(idle "dupwords")

;Wikipedia mode- syntax highlighting for Wikipedia, plus some
;binding of moving around commands.
;<http://www.emacswiki.org/cgi-bin/wiki/WikipediaMode>
(autoload 'wikipedia-mode "" "")
(add-hook 'wikipedia-mode-hook 'pabbrev-mode)
(add-to-list 'auto-mode-alist
             '("\\.wiki\\'" . wikipedia-mode))
(add-to-list 'auto-mode-alist
             '("\\externaleditor.txt\\'" . wikipedia-mode))
(add-to-list 'auto-mode-alist
             '("index.\\.*" . wikipedia-mode))

;I don't know why, but the author of Wikipedia mode added in some
;seriously annoying key bindings. Let's kill them dead!
(defun unset-wikipedia-bindings ()
  (interactive)
  (local-unset-key (kbd "C-<up>"))
  (local-unset-key (kbd "C-<down>"))
  (local-unset-key (kbd "C-<left>"))
  (local-unset-key (kbd "C-<right>")))
(add-hook 'wikipedia-mode-hook 'unset-wikipedia-bindings)

;Dired-sort-menu adds sorting of a dired-shown directory.
;<http://centaur.maths.qmw.ac.uk/Emacs/files/dired-sort-menu.el>
(autoload 'dired-sort-menu "dired-sort-menu" "Minor mode adding ls sort options to dired." t)
(add-hook 'dired-load-hook
          (lambda () (require 'dired-sort-menu nil t)))

;..."you can edit filenames from within the dired buffer using wdired-change-to-wdired-mode.
;I like to have this bound to e which previously would have done the same thing as RET."
;<http://www.shellarchive.co.uk/Emacs.html#sec5>
(add-hook 'dired-mode-hook
          '(lambda ()
             (define-key dired-mode-map "e" 'wdired-change-to-wdired-mode)))

;For editing MS Word .doc files.
;<http://www.ccs.neu.edu/home/guttman/undoc.el>
(autoload 'undoc "undoc" "A minor mode which kills MS Word files dead." t)
(autoload 'undoc-current-buffer "undoc" "" t)
(autoload 'undoc-region-after-mime-decode "undoc" "" t)

;Incremental search of minibuffer history.
;<http://www.sodan.org/~knagano/emacs/minibuf-isearch/>
(idle "minibuf-isearch")

;Haskell-mode is provided through Gentoo's haskell-mode package.
;This changes some of the modules loaded.
(idle "haskell-mode")
(eval-after-load "haskell-mode" '(progn
                                   (setq auto-mode-alist
                                         (append auto-mode-alist
                                                 '(("\\.[hg]s$"  . haskell-mode)
                                                   ("\\.hi$"     . haskell-mode)
                                                   ("\\.l[hg]s$" . literate-haskell-mode))))

                                   (autoload 'haskell-mode "haskell-mode"
                                     "Haskell programing major mode." t)
                                   (autoload 'literate-haskell-mode "haskell-mode"
                                     "Literate Haskell script major mode." t)

                                   ;Spellcheck comments
                                   (add-hook 'haskell-mode-hook 'flyspell-prog-mode)

                                   ;<http://www.emacswiki.org/cgi-bin/wiki/HaskellMode>
                                   (add-hook 'haskell-mode-hook
                                             #'(lambda ()
                                                 (setq comment-padding " "
                                                       comment-start "--")))

                                   ;Use my neat Unicode stuff
                                   (setq haskell-font-lock-symbols 'unicode)

                                   ;Default behaviour is to always jump to the GHCi window.
                                   ;Jump back automatically unless errors.
                                   (defadvice haskell-ghci-load-file (after name)
                                     (other-window 1))
                                   (ad-activate 'haskell-ghci-load-file t)

                                   ;Reflow comments
                                   (add-hook 'haskell-mode-hook
                                             (lambda ()
                                               (auto-fill-mode 1)
                                               (set (make-local-variable
                                                     'fill-nobreak-predicate)
                                                    (lambda ()
                                                      (not (eq (get-text-property (point) 'face)
                                                               'font-lock-comment-face))))))
                                        ; Highlight trailing whitespace in haskell files
                                   (add-hook 'haskell-mode-hook
                                             '(lambda ()
                                                (setq show-trailing-whitespace t)))))

;Programming language modes use flyspell-prog-mode and not normal spell-check.
(add-hook 'sh-mode-hook (lambda () (flyspell-prog-mode)))

; Let's make Haskell and Lisp look more like the math they should!
; <http://www.emacswiki.org/cgi-bin/wiki/PrettyLambda>
(idle "cl")
(eval-when-compile 'cl)
(eval-after-load "cl" '(progn
                         (defun unicode-symbol (name)
                           "Translate a symbolic name for a Unicode character -- e.g., LEFT-ARROW
  or GREATER-THAN into an actual Unicode character code. "
                           (decode-char 'ucs (case name
                                               ; arrows
                                               ('left-arrow 8592)
                                               ('up-arrow 8593)
                                               ('right-arrow 8594)
                                               ('down-arrow 8595)
                                               ; boxes
                                               ('double-vertical-bar #X2551)
                                               ; relational operators
                                               ('equal #X003d)
                                               ('not-equal #X2260)
                                               ('identical #X2261)
                                               ('not-identical #X2262)
                                               ('less-than #X003c)
                                               ('greater-than #X003e)
                                               ('less-than-or-equal-to #X2264)
                                               ('greater-than-or-equal-to #X2265)
                                               ; logical operators
                                               ('logical-and #X2227)
                                               ('logical-or #X2228)
                                               ('logical-neg #X00AC)
                                               ; misc
                                               ('nil #X2205)
                                               ('horizontal-ellipsis #X2026)
                                               ('double-exclamation #X203C)
                                               ('prime #X2032)
                                               ('double-prime #X2033)
                                               ('for-all #X2200)
                                               ('there-exists #X2203)
                                               ('element-of #X2208)
                                               ; mathematical operators
                                               ('square-root #X221A)
                                               ('squared #X00B2)
                                               ('cubed #X00B3)
                                               ; letters
                                               ('lambda #X03BB)
                                               ('alpha #X03B1)
                                               ('beta #X03B2)
                                               ('gamma #X03B3)
                                               ('delta #X03B4))))
                         (defun substitute-pattern-with-unicode (pattern symbol)
                           "Add a font lock hook to replace the matched part of PATTERN with the
  Unicode symbol SYMBOL looked up with UNICODE-SYMBOL."
                           (interactive)
                           (font-lock-add-keywords
                            nil `((,pattern (0 (progn (compose-region (match-beginning 1) (match-end 1)
                                                                      ,(unicode-symbol symbol))
                                                      nil))))))
                         (defun substitute-patterns-with-unicode (patterns)
                           "Call SUBSTITUTE-PATTERN-WITH-UNICODE repeatedly."
                           (mapcar #'(lambda (x)
                                       (substitute-pattern-with-unicode (car x)
                                                                        (cdr x)))
                                   patterns))
                         (defun pretty-greek ()
                           (let ((greek '("alpha" "beta" "gamma" "delta" "epsilon" "zeta" "eta" "theta" "iota"
                                          "kappa" "lambda" "mu" "nu" "xi" "omicron" "pi" "rho" "sigma_final"
                                          "sigma" "tau" "upsilon" "phi" "chi" "psi" "omega")))
                             (loop for word in greek
                                   for code = 97 then (+ 1 code)
                                   do (let ((greek-char (make-char 'greek-iso8859-7 code)))
                                        (font-lock-add-keywords nil
                                                                `((,(concatenate 'string
                                                                                 "\\(^\\|[^a-zA-Z0-9]\\)\\("
                                                                                 word "\\)[a-zA-Z]")
                                                                   (0 (progn
                                                                        (decompose-region
                                                                         (match-beginning 2) (match-end 2))
                                                                        nil)))))
                                        (font-lock-add-keywords nil
                                                                `((,(concatenate 'string
                                                                                 "\\(^\\|[^a-zA-Z0-9]\\)\\("
                                                                                 word "\\)[^a-zA-Z]")
                                                                   (0 (progn (compose-region
                                                                              (match-beginning 2) (match-end 2)
                                                                              ,greek-char)
                                                                             nil)))))))))

                         (add-hook 'lisp-mode-hook 'pretty-greek)
                         (add-hook 'emacs-lisp-mode-hook 'pretty-greek)))

;"Why not use the cursor type and color to let you know what the current context is?
;A bar cursor (vertical bar between characters) is handy for editing, but it is not
;very noticeable in the middle of a sea of text. Why not change it to a box cursor
;(on top of a character) when Emacs is idle, so you can spot it easier?"
;<http://www.emacswiki.org/cgi-bin/wiki/ChangingCursorDynamically>
;<http://www.emacswiki.org/cgi-bin/emacs/cursor-chg.el>
(idle "cursor-chg")
(eval-after-load "cursor-chg"
  '(progn
     (toggle-cursor-type-when-idle 1) ; Turn on cursor  when Emacs is idle
     (change-cursor-mode 1) ; Turn on change for overwrite, read-only, and input mode
     (setq curchg-input-method-cursor-color "palegreen1"
           curchg-input-method-cursor-color "palegreen1")))

;Well, nethack, and nethack-el are installed, so let's modify Nethack to make it usable.
(eval-after-load "nethack"
  '(progn ;20 years and Nethack still doesn't support the D-pad...
     (define-key nh-map-mode-map (kbd "<left>") 'nethack-command-west)
     (define-key nh-map-mode-map (kbd "<up>") 'nethack-command-north)
     (define-key nh-map-mode-map (kbd "<down>") 'nethack-command-south)
     (define-key nh-map-mode-map (kbd "<right>") 'nethack-command-east)
     (define-key nh-map-mode-map (kbd "<home>") 'nethack-command-northwest)
     (define-key nh-map-mode-map (kbd "<prior>") 'nethack-command-northeast)
     (define-key nh-map-mode-map (kbd "<end>")  'nethack-command-southwest)
     (define-key nh-map-mode-map (kbd "<next>") 'nethack-command-southeast)

     (defun nethack-x-timestamp-message ()
       "Add a time-stamp to every message." ;allows for easier tracking of things
       (insert (format "(%d) " (elt nh-status-attribute-T 0))))
     (add-hook 'nethack-before-print-message-hook
               'nethack-x-timestamp-message)

     (defun nethack-x-warn-low-hp (attr new old)
       "Print a message in `nh-message-buffer' when hitpoints get low."
       (if (and (string-equal attr "HP")
                (< new old)
                (< (/ new (float (car nh-status-attribute-HPmax))) 0.20))
           (nhapi-message 'atr-blink "Hitpoints below 20%")))
     (add-hook 'nethack-status-attribute-change-functions 'nethack-x-warn-low-hp)

     (defvar nethack-x-highlights '((" blessed " . nethack-green-face)
                                    (" holy " . nethack-green-face)
                                    (" cursed " . nethack-red-face)
                                    (" unholy " . nethack-green-face)
                                    (" cursed .* (being worn)" . nethack-orange-face))
       "An assoc of regexps and font colors")
     (add-hook 'nethack-add-menu-hook 'nethack-x-highlight-option)

     (defun nethack-x-highlight-option ()
       "Highlight a nethack menu option based on a regexp."
       ; Move to the beginning of the option just added
       (save-excursion
         (let (startuptime.
               (end (point)))
           (forward-line -1)
           (forward-line 0)
           ; A mini-hack so the option accelerator doesn't get highlighted
           (setq start (+ (point) 4))
           (mapc (lambda (x)
                   (if (re-search-forward (car x) nil t)
                       (put-text-property start end 'face (cdr x))))
                 nethack-x-highlights))))))

;;Saveplace: Cursor moves to remembered place. Very useful for large files.
(autoload 'saveplace "" "")
(eval-after-load 'saveplace '(setq-default save-place t))

;Set up msb mode. It is not as quick to use as regular buffer tab,
;but for those I use C-x b, not the menu.
(autoload 'msb "" "")
(eval-after-load 'msb '(msb-mode 1))

;Flymake; enable for Haskell as well as the standard languages.
(idle "flymake")
(eval-after-load "flymake" '(progn
                              (defun flymake-haskell-init ()
                                (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 "ghc" (list "--make" local-file "-i"))))
                              (defvar flymake-ghc-options (list "-Wall -Werror"))
                              (defvar flymake-ghc-packages
                                (mapcar (lambda (p) (concat "-package " p))
                                        '("QuickCheck")))
                              (defun flymake-get-haskell-cmdline (source base-dir)
                                (list "ghc"
                                      (append
                                       (list "--make" "-fno-code" (concat "-i" base-dir) source)
                                       flymake-ghc-options
                                       flymake-ghc-packages)))
                              (push '("\\.[hg]s$" flymake-haskell-init)
                                    flymake-allowed-file-name-masks)
                              (push '("\\.l[hg]$" flymake-haskell-init)
                                    flymake-allowed-file-name-masks)
                              (push '("^\\(.*\.hs\\|\.lhs\\):\\([0-9]+\\):\\([0-9]+\\): \\(\\(.*\n?\\)*\\)$"
                                      1 2 3 4)
                                    flymake-err-line-patterns)
                              (global-set-key [f3] 'flymake-display-err-menu-for-current-line)
                              (global-set-key [f4] 'flymake-goto-next-error)
                              (add-hook 'find-file-hook 'flymake-find-file-hook)))

;;;;;;;;;;;;;;;;;;;
;;;; CUSTOM ;;;;;;;
;;;;;;;;;;;;;;;;;;;
(put 'scroll-left 'disabled t)
(put 'overwrite-mode 'disabled t)
(custom-set-variables
  ;; custom-set-variables was added by Custom.
  ;; If you edit it by hand, you could mess it up, so be careful.
  ;; Your init file should contain only one such instance.
  ;; If there is more than one, they won't work right.
 '(add-log-current-defun-function nil)
 '(auto-compression-mode t)
 '(auto-save-interval 50)
 '(auto-save-timeout 100)
 '(backup-by-copying t)
 '(backup-by-copying-when-linked t)
 '(backup-directory-alist (quote (("." . "~/.saves"))))
 '(before-save-hook (quote (copyright-update time-stamp delete-trailing-whitespace)))
 '(blink-cursor-delay 1)
 '(blink-cursor-interval 0.6)
 '(browse-url-xterm-program "urxvt")
 '(byte-compile-generate-call-tree nil)
 '(change-log-default-name "ChangeLog")
 '(color-theme-history-max-length 10)
 '(column-number-mode t)
 '(completion-ignored-extensions (quote (".o" ".hi" ".elc" ".class" "java~" ".ps" ".pdf" ".abs" ".mx" ".~jv" "#" ".gz" ".tgz" ".fasl" ".CKP" ".u" ".press" ".imp" ".BAK" ".bak")))
 '(completion-max-candidates 15)
 '(completion-min-chars 3)
 '(completion-resolve-old-method (quote reject))
 '(curchg-default-cursor-color "green")
 '(delete-old-versions t)
 '(dired-recursive-copies (quote always))
 '(display-buffer-reuse-frames t)
 '(display-hourglass t)
 '(display-time-mode t)
 '(file-cache-find-command-posix-flag t)
 '(file-cache-ignore-case t)
 '(file-precious-flag t)
 '(fill-column 80)
 '(frame-background-mode (quote dark))
 '(gc-cons-threshold 24000000)
 '(hourglass-delay 2)
 '(icomplete-compute-delay 0.2)
 '(icomplete-mode t)
 '(indent-tabs-mode nil)
 '(inhibit-startup-screen t)
 '(initial-scratch-message "; This buffer is for notes you don't want to save, and for Lisp evaluation.
")
 '(ispell-following-word t)
 '(ispell-highlight-p t)
 '(ispell-program-name "aspell")
 '(ispell-silently-savep t)
 '(iswitchb-case t)
 '(iswitchb-max-to-show 10)
 '(iswitchb-mode t)
 '(iswitchb-prompt-newbuffer t)
 '(iswitchb-regexp t)
 '(iswitchb-use-frame-buffer-list t)
 '(iswitchb-use-virtual-buffers t nil (recentf))
 '(jde-compile-option-command-line-args (quote ("")))
 '(jde-compile-option-verbose t)
 '(jde-compiler (quote ("javac" "/usr/bin/javac")))
 '(kept-new-versions 16)
 '(kept-old-versions 16)
 '(kill-ring-max 120)
 '(mail-source-directory "~/doc/mail/mail/")
 '(message-directory "~/doc/mail/mail/")
 '(message-log-max 1024)
 '(mouse-yank-at-point t)
 '(nethack-message-window-height 13)
 '(nethack-status-highlight-delay 4)
 '(nethack-status-window-height 5)
 '(predictive-add-to-dict-ask nil)
 '(predictive-auto-add-to-dict t)
 '(predictive-auto-learn t)
 '(predictive-completion-speed 0.01)
 '(predictive-max-completions 15)
 '(predictive-use-buffer-local-dict t)
 '(read-file-name-completion-ignore-case t)
 '(save-place-file "~/.emacs.d/emacs-places")
 '(save-place-limit 1024)
 '(scroll-down-aggressively 0.4)
 '(scroll-up-aggressively 0.5)
 '(server-mode t)
 '(server-temp-file-regexp "^/tmp/.*|/draft$")
 '(server-use-tcp t)
 '(show-paren-delay 1)
 '(show-paren-mode t)
 '(show-paren-priority 500)
 '(show-paren-ring-bell-on-mismatch t)
 '(show-paren-style (quote mixed))
 '(tab-width 8)
 '(text-mode-hook (quote (flyspell-mode longlines-mode text-mode-hook-identify)))
 '(tramp-default-method "ssh")
 '(transient-mark-mode t)
 '(vc-follow-symlinks t)
 '(vc-make-backup-files t)
 '(version-control t)
 '(visible-bell t)
 '(voice-punctuations-all-settings (quote (paul nil nil nil nil some)))
 '(w3m-form-input-textarea-buffer-lines 30)
 '(w3m-use-cookies t)
 '(window-min-height 3)
 '(words-include-escapes t)
 '(x-select-enable-clipboard t))
(custom-set-faces
  ;; custom-set-faces was added by Custom.
  ;; If you edit it by hand, you could mess it up, so be careful.
  ;; Your init file should contain only one such instance.
  ;; If there is more than one, they won't work right.
 '(bbdb-field-name ((t (:foreground "cornflowerblue"))) t)
 '(bbdb-name ((t (:foreground "aquamarine"))) t)
 '(bold ((t (:weight bold))))
 '(bold-italic ((t (:slant italic :weight bold))))
 '(border ((t nil)))
 '(brace-face ((((class color)) (:foreground "white"))))
 '(bracket-face ((((class color)) (:foreground "DeepSkyBlue3"))))
 '(buffer-menu-buffer ((t (:inherit font-lock-function-name-face))))
 '(button ((t (:inherit bold))))
 '(comint-highlight-input ((t (:inherit bold))))
 '(compilation-info ((((class color) (min-colors 88) (background dark)) (:foreground "palegreen"))))
 '(compilation-warning ((((class color) (min-colors 16)) (:inherit bold :foreground "Orange"))))
 '(cperl-array ((((class color) (background dark)) (:foreground "yellow2"))))
 '(cperl-hash ((((class color) (background dark)) (:foreground "gold"))))
 '(cperl-nonoverridable ((((class color) (background dark)) (:foreground "plum"))))
 '(cursor ((t (:background "palegreen"))))
 '(custom-link ((((min-colors 88) (class color) (background dark)) (:underline t :weight bold))))
 '(ecb-default-highlight-face ((((class color) (background dark)) (:background "darkslateblue"))))
 '(escape-glyph ((((background dark)) (:foreground "lightsteelblue3"))))
 '(eshell-ls-archive ((((class color) (background dark)) (:foreground "salmon"))))
 '(eshell-ls-directory ((((class color) (background dark)) (:foreground "Skyblue"))))
 '(eshell-ls-executable ((((class color) (background dark)) (:foreground "palegreen"))))
 '(eshell-ls-missing ((((class color) (background dark)) (:foreground "tomato"))))
 '(eshell-ls-symlink ((((class color) (background dark)) (:foreground "Cyan"))))
 '(eshell-prompt ((t (:foreground "aquamarine2"))))
 '(fg:erc-color-face1 ((t (:foreground "grey30"))))
 '(font-lock-builtin-face ((((class grayscale) (background light)) (:foreground "LightGray" :weight bold)) (((class grayscale) (background dark)) (:foreground "DimGray" :weight bold)) (((class color) (min-colors 88) (background light)) (:foreground "Orchid")) (((class color) (min-colors 88) (background dark)) (:foreground "LightSteelBlue")) (((class color) (min-colors 16) (background light)) (:foreground "Orchid")) (((class color) (min-colors 16) (background dark)) (:foreground "LightSteelBlue")) (((class color) (min-colors 8)) (:foreground "cyan" :weight bold)) (t (:weight bold))))
 '(font-lock-comment-delimiter-face ((default (:foreground "tan2")) (((class color) (min-colors 16)) nil)))
 '(font-lock-constant-face ((((type x) (class color) (min-colors 88) (background dark)) (:foreground "Aquamarine3"))))
 '(font-lock-keyword-face ((((type x) (class color) (min-colors 88) (background dark)) (:foreground "turquoise3"))))
 '(font-lock-regexp-grouping-backslash ((t (:foreground "burlywood1"))))
 '(font-lock-string-face ((((type x) (class color) (min-colors 88) (background dark)) (:foreground "burlywood3")) (((type tty)) (:foreground "palegreen"))))
 '(font-lock-type-face ((((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen3"))))
 '(font-lock-variable-name-face ((((type x) (min-colors 88) (background dark)) (:foreground "LightGoldenrod3"))))
 '(font-lock-warning-face ((((type x) (class color) (min-colors 88) (background dark)) (:background "firebrick4" :foreground "white")) (((type tty)) (:background "red" :foreground "white" :weight bold))))
 '(fringe ((((class color) (background dark)) (:background "grey20"))))
 '(header-line ((t (:inherit variable-pitch :background "grey10" :foreground "aquamarine3" :box (:line-width 2 :color "aquamarine4")))))
 '(help-argument-name ((((supports :slant italic)) (:inherit font-lock-variable-name-face))))
 '(highlight ((((type x) (class color) (min-colors 88) (background dark)) (:background "grey20"))))
 '(highlight-changes ((((min-colors 88) (class color)) (:background "grey20"))))
 '(highline-face ((t (:background "grey20"))))
 '(hl-line ((t (:background "#101040"))))
 '(info-menu-star ((((class color)) (:foreground "lightgoldenrod"))))
 '(info-node ((((class color) (background dark)) (:inherit bold :foreground "white" :slant italic))))
 '(info-xref ((((min-colors 88) (class color) (background dark)) (:foreground "lightgoldenrod2"))))
 '(info-xref-visited ((default (:foreground "lightgoldenrod3")) (((class color) (background dark)) nil)))
 '(italic ((((supports :underline t)) (:slant italic))))
 '(match ((((class color) (min-colors 88) (background dark)) (:background "royalblue"))))
 '(menu ((t (:background "grey30" :foreground "gold"))))
 '(message-cited-text ((((class color) (background dark)) (:foreground "burlywood"))))
 '(message-header-cc ((t (:inherit gnus-header-newsgroups))))
 '(message-header-name ((((class color) (background dark)) (:inherit gnus-header-name))))
 '(message-header-newsgroups ((t (:foreground "aquamarine"))))
 '(message-header-other ((((class color) (background dark)) (:inherit gnus-header-content))))
 '(message-header-subject ((((class color) (background dark)) (:inherit gnus-header-subject))))
 '(message-header-to ((t (:inherit gnus-header-from :weight bold))))
 '(message-separator ((((class color) (background dark)) (:foreground "seagreen"))))
 '(minibuffer-prompt ((((background dark)) (:foreground "aquamarine2"))))
 '(mm-uu-extract ((((class color) (background dark)) (:background "grey20"))))
 '(mode-line ((((class color) (min-colors 88)) (:inherit variable-pitch :background "black" :foreground "palegreen3" :box (:line-width 2 :color "palegreen4")))))
 '(mode-line-buffer-id ((t (:inherit bold))))
 '(mode-line-inactive ((((type x)) (:inherit variable-pitch :background "grey20" :foreground "palegreen4" :box (:line-width 2 :color "grey40")))))
 '(paren-face ((((class color)) (:foreground "darkseagreen"))))
 '(paren-face-match ((((class color)) (:background "green"))))
 '(paren-face-mismatch ((((class color)) (:foreground "white" :background "red"))))
 '(paren-match ((t (:background "green"))))
 '(paren-mismatch ((t (:background "red"))))
 '(progmode-special-chars-face ((((class color)) (:foreground "grey90"))))
 '(region ((((class color) (min-colors 88) (background dark)) (:background "darkslateblue"))))
 '(scroll-bar ((t (:inherit Header\ Line :stipple nil :background "black" :foreground "lightgreen" :inverse-video nil :slant italic :weight ultra-bold :height 1 :width condensed))))
 '(semicolon-face ((((class color)) (:foreground "white"))))
 '(sh-escaped-newline ((t (:foreground "tomato"))))
 '(sh-heredoc ((((min-colors 88) (class color) (background dark)) (:inherit font-lock-string-face :background "grey20"))))
 '(sh-quoted-exec ((((class color) (background dark)) (:foreground "salmon1"))))
 '(shadow ((((class color grayscale) (min-colors 88) (background dark)) (:foreground "grey50"))))
 '(show-paren-match ((((class color) (background dark)) (:background "deepskyblue1"))))
 '(show-paren-mismatch ((((class color)) (:background "firebrick3"))))
 '(slime-repl-inputed-output-face ((((class color) (background dark)) (:foreground "lightsalmon"))))
 '(tooltip ((((class color)) (:inherit variable-pitch :background "gray30" :foreground "white"))))
 '(trailing-whitespace ((((class color) (background dark)) (:background "grey30"))))
 '(tuareg-font-lock-governing-face ((t (:foreground "orange"))))
 '(ude-error-face ((t (:background "firebrick4" :foreground "white" :weight normal))))
 '(ude-font-lock-face-1 ((t (:foreground "Plum2"))))
 '(variable-pitch ((t (:height 0.8 :family "arial"))))
 '(vertical-border ((nil (:foreground "grey20"))))
 '(w3m-anchor-face ((((class color) (background dark)) (:foreground "Lightskyblue1"))))
 '(w3m-arrived-anchor-face ((((class color) (background dark)) (:foreground "skyblue2"))))
 '(w3m-bold-face ((t (:foreground "white"))))
 '(w3m-current-anchor-face ((t (:inherit bold :underline t))))
 '(w3m-form-button-face ((((type x w32 mac) (class color)) (:foreground "lightgoldenrod"))))
 '(w3m-form-face ((((class color) (background dark)) (:foreground "lightgoldenrod" :underline t))))
 '(w3m-tab-background-face ((((type x w32 mac) (class color)) (:background "grey20" :foreground "grey80"))))
 '(w3m-tab-selected-background-face ((((type x w32 mac) (class color)) (:background "grey20" :foreground "grey80"))))
 '(which-func ((((class color) (min-colors 88) (background dark)) (:foreground "aquamarine"))))
 '(woman-bold ((((background dark)) (:foreground "palegreen"))))
 '(woman-italic ((((background dark)) (:foreground "lightgoldenrod"))))
 '(woman-italic-no-ul ((t (:foreground "lightgoldenrod"))) t))
;end .emacs