dot/dircolors: Set colours on `xterm-256color' terminals.
[profile] / el / dot-emacs.el
index bd29385..2fdc9ab 100644 (file)
@@ -57,6 +57,12 @@ This may be at the expense of cool features.")
   (interactive)
   (error "wrong button"))
 
+(defun mdw-emacs-version-p (major &optional minor)
+  "Return non-nil if the running Emacs is at least version MAJOR.MINOR."
+  (or (> emacs-major-version major)
+      (and (= emacs-major-version major)
+          (>= emacs-minor-version (or minor 0)))))
+
 ;; Some error trapping.
 ;;
 ;; If individual bits of this file go tits-up, we don't particularly want
@@ -96,6 +102,15 @@ This may be at the expense of cool features.")
                    (concat "(" (buffer-string) ")")))))))
   (cdr (assq sym mdw-config)))
 
+;; Width configuration.
+
+(defvar mdw-column-width
+  (string-to-number (or (mdw-config 'emacs-width) "77"))
+  "Width of Emacs columns.")
+(defvar mdw-text-width mdw-column-width
+  "Expected width of text within columns.")
+(put 'mdw-text-width 'safe-local-variable 'integerp)
+
 ;; Local variables hacking.
 
 (defun run-local-vars-mode-hook ()
@@ -189,10 +204,9 @@ fringes is not taken out of the allowance for WIDTH, unlike
   "Split a wide window into appropriate widths."
   (interactive "P")
   (setq width (cond (width (prefix-numeric-value width))
-                   ((and window-system
-                         (>= emacs-major-version 22))
-                    77)
-                   (t 78)))
+                   ((and window-system (mdw-emacs-version-p 22))
+                    mdw-column-width)
+                   (t (1+ mdw-column-width))))
   (let* ((win (selected-window))
         (sb-width (mdw-horizontal-window-overhead))
         (c (/ (+ (window-width) sb-width)
@@ -225,6 +239,40 @@ frame is actually mapped on the screen."
        ad-do-it)))
 
 (mdw-advise-to-inhibit-raise-frame select-frame-set-input-focus)
+(mdw-advise-to-inhibit-raise-frame appt-disp-window)
+
+;; Bug fix for markdown-mode, which breaks point positioning during
+;; `query-replace'.
+(defadvice markdown-check-change-for-wiki-link
+    (around mdw-save-match activate compile)
+  "Save match data around the `markdown-mode' `after-change-functions' hook."
+  (save-match-data ad-do-it))
+
+;; Bug fix for `bbdb-canonicalize-address': on Emacs 24, `run-hook-with-args'
+;; always returns nil, with the result that all email addresses are lost.
+;; Replace the function entirely.
+(defadvice bbdb-canonicalize-address
+    (around mdw-bug-fix activate compile)
+  "Don't use `run-hook-with-args', because that doesn't work."
+  (let ((net (ad-get-arg 0)))
+
+    ;; Make sure this is a proper hook list.
+    (if (functionp bbdb-canonicalize-net-hook)
+       (setq bbdb-canonicalize-net-hook (list bbdb-canonicalize-net-hook)))
+
+    ;; Iterate over the hooks until things converge.
+    (let ((donep nil))
+      (while (not donep)
+       (let (next (changep nil)
+             hook (hooks bbdb-canonicalize-net-hook))
+         (while hooks
+           (setq hook (pop hooks))
+           (setq next (funcall hook net))
+           (if (not (equal next net))
+               (setq changep t
+                     net next)))
+         (setq donep (not changep)))))
+    (setq ad-return-value net)))
 
 ;; Transient mark mode hacks.
 
@@ -245,8 +293,63 @@ it's currently off."
         (or transient-mark-mode (setq transient-mark-mode 'only))
         (set-mark (mark t)))))
 
+;; Improved compilation machinery.
+
+(setq compile-command
+      (let ((ncpu (with-temp-buffer
+                   (insert-file-contents "/proc/cpuinfo")
+                   (buffer-string)
+                   (count-matches "^processor\\s-*:"))))
+       (format "make -j%d -k" (* 2 ncpu))))
+
+(defun mdw-compilation-buffer-name (mode)
+  (concat "*" (downcase mode) ": "
+         (abbreviate-file-name default-directory) "*"))
+(setq compilation-buffer-name-function 'mdw-compilation-buffer-name)
+
+(eval-after-load "compile"
+  '(progn
+     (define-key compilation-shell-minor-mode-map "\C-c\M-g" 'recompile)))
+
+(defun mdw-compile (command &optional directory comint)
+  "Initiate a compilation COMMAND, maybe in a different DIRECTORY.
+The DIRECTORY may be nil to not change.  If COMINT is t, then
+start an interactive compilation.
+
+Interactively, prompt for the command if the variable
+`compilation-read-command' is non-nil, or if requested through
+the prefix argument.  Prompt for the directory, and run
+interactively, if requested through the prefix.
+
+Use a prefix of 4, 6, 12, or 14, or type C-u between one and three times, to
+force prompting for a directory.
+
+Use a prefix of 2, 6, 10, or 14, or type C-u three times, to force
+prompting for the command.
+
+Use a prefix of 8, 10, 12, or 14, or type C-u twice or three times,
+to force interactive compilation."
+  (interactive
+   (let* ((prefix (prefix-numeric-value current-prefix-arg))
+         (command (eval compile-command))
+         (dir (and (plusp (logand prefix #x54))
+                   (read-directory-name "Compile in directory: "))))
+     (list (if (or compilation-read-command
+                  (plusp (logand prefix #x42)))
+              (compilation-read-command command)
+            command)
+          dir
+          (plusp (logand prefix #x58)))))
+  (let ((default-directory (or directory default-directory)))
+    (compile command comint)))
+
 ;; Functions for sexp diary entries.
 
+(defun mdw-not-org-mode (form)
+  "As FORM, but not in Org mode agenda."
+  (and (not mdw-diary-for-org-mode-p)
+       (eval form)))
+
 (defun mdw-weekday (l)
   "Return non-nil if `date' falls on one of the days of the week in L.
 L is a list of day numbers (from 0 to 6 for Sunday through to
@@ -258,6 +361,50 @@ function returns non-nil."
        (memq (nth d '(sunday monday tuesday wednesday
                              thursday friday saturday)) l))))
 
+(defun mdw-discordian-date (date)
+  "Return the Discordian calendar date corresponding to DATE.
+
+The return value is (YOLD . st-tibs-day) or (YOLD SEASON DAYNUM DOW).
+
+The original is by David Pearson.  I modified it to produce date components
+as output rather than a string."
+  (let* ((days ["Sweetmorn" "Boomtime" "Pungenday"
+               "Prickle-Prickle" "Setting Orange"])
+        (months ["Chaos" "Discord" "Confusion"
+                 "Bureaucracy" "Aftermath"])
+        (day-count [0 31 59 90 120 151 181 212 243 273 304 334])
+        (year (- (extract-calendar-year date) 1900))
+        (month (1- (extract-calendar-month date)))
+        (day (1- (extract-calendar-day date)))
+        (julian (+ (aref day-count month) day))
+        (dyear (+ year 3066)))
+    (if (and (= month 1) (= day 28))
+       (cons dyear 'st-tibs-day)
+      (list dyear
+           (aref months (floor (/ julian 73)))
+           (1+ (mod julian 73))
+           (aref days (mod julian 5))))))
+
+(defun mdw-diary-discordian-date ()
+  "Convert the date in `date' to a string giving the Discordian date."
+  (let* ((ddate (mdw-discordian-date date))
+        (tail (format "in the YOLD %d" (car ddate))))
+    (if (eq (cdr ddate) 'st-tibs-day)
+       (format "St Tib's Day %s" tail)
+      (let ((season (cadr ddate))
+           (daynum (caddr ddate))
+           (dayname (cadddr ddate)))
+      (format "%s, the %d%s day of %s %s"
+             dayname
+             daynum
+             (let ((ldig (mod daynum 10)))
+               (cond ((= ldig 1) "st")
+                     ((= ldig 2) "nd")
+                     ((= ldig 3) "rd")
+                     (t "th")))
+             season
+             tail)))))
+
 (defun mdw-todo (&optional when)
   "Return non-nil today, or on WHEN, whichever is later."
   (let ((w (calendar-absolute-from-gregorian (calendar-current-date)))
@@ -277,6 +424,52 @@ function returns non-nil."
                                (nth 2 when))))))))
     (eq w d)))
 
+(defvar mdw-diary-for-org-mode-p nil)
+
+(defadvice org-agenda-list (around mdw-preserve-links activate)
+  (let ((mdw-diary-for-org-mode-p t))
+    ad-do-it))
+
+(defadvice diary-add-to-list (before mdw-trim-leading-space compile activate)
+  "Trim leading space from the diary entry string."
+  (save-match-data
+    (let ((str (ad-get-arg 1))
+         (done nil) old)
+      (while (not done)
+       (setq old str)
+       (setq str (cond ((null str) nil)
+                       ((string-match "\\(^\\|\n\\)[ \t]+" str)
+                        (replace-match "\\1" nil nil str))
+                       ((and mdw-diary-for-org-mode-p
+                             (string-match (concat
+                                            "\\(^\\|\n\\)"
+                                            "\\(" diary-time-regexp
+                                            "\\(-" diary-time-regexp "\\)?"
+                                            "\\)"
+                                            "\\(\t[ \t]*\\| [ \t]+\\)")
+                                           str))
+                        (replace-match "\\1\\2 " nil nil str))
+                       ((and (not mdw-diary-for-org-mode-p)
+                             (string-match "\\[\\[[^][]*]\\[\\([^][]*\\)]]"
+                                           str))
+                        (replace-match "\\1" nil nil str))
+                       (t str)))
+       (if (equal str old) (setq done t)))
+      (ad-set-arg 1 str))))
+
+(defadvice org-bbdb-anniversaries (after mdw-fixup-list compile activate)
+  "Return a string rather than a list."
+  (with-temp-buffer
+    (let ((anyp nil))
+      (dolist (e (let ((ee ad-return-value))
+                  (if (atom ee) (list ee) ee)))
+       (when e
+         (when anyp (insert ?\n))
+         (insert e)
+         (setq anyp t)))
+      (setq ad-return-value
+           (and anyp (buffer-string))))))
+
 ;; Fighting with Org-mode's evil key maps.
 
 (defvar mdw-evil-keymap-keys
@@ -444,6 +637,27 @@ so that it can be used for convenient filtering."
          (setenv "REAL_MOVEMAIL" try))
       (setq path (cdr path)))))
 
+;; AUTHINFO GENERIC kludge.
+
+(defvar nntp-authinfo-generic nil
+  "Set to the `NNTPAUTH' string to pass on to `authinfo-kludge'.
+
+Use this to arrange for per-server settings.")
+
+(defun nntp-open-authinfo-kludge (buffer)
+  "Open a connection to SERVER using `authinfo-kludge'."
+  (let ((proc (start-process "nntpd" buffer
+                            "env" (concat "NNTPAUTH="
+                                          (or nntp-authinfo-generic
+                                              (getenv "NNTPAUTH")
+                                              (error "NNTPAUTH unset")))
+                            "authinfo-kludge" nntp-address)))
+    (set-buffer buffer)
+    (nntp-wait-for-string "^\r*200")
+    (beginning-of-line)
+    (delete-region (point-min) (point))
+    proc))
+
 (eval-after-load "erc"
     '(load "~/.ercrc.el"))
 
@@ -557,7 +771,8 @@ sequences separated by `.'."
        (cond ((null la) (throw 'done lb))
              ((null lb) (throw 'done nil))
              ((< (car la) (car lb)) (throw 'done t))
-             ((= (car la) (car lb)) (setq la (cdr la) lb (cdr lb))))))))
+             ((= (car la) (car lb)) (setq la (cdr la) lb (cdr lb)))
+             (t (throw 'done nil)))))))
 
 (defun mdw-check-autorevert ()
   "Sets global-auto-revert-ignore-buffer appropriately for this buffer.
@@ -603,6 +818,17 @@ options."
       (ad-set-arg 0 dir)
       ad-do-it)))
 
+(defun mdw-dired-run (args &optional syncp)
+  (interactive (let ((file (dired-get-filename t)))
+                (list (read-string (format "Arguments for %s: " file))
+                      current-prefix-arg)))
+  (funcall (if syncp 'shell-command 'async-shell-command)
+          (concat (shell-quote-argument (dired-get-filename nil))
+                  " " args)))
+
+(eval-after-load "dired"
+  '(define-key dired-mode-map "X" 'mdw-dired-run))
+
 ;;;--------------------------------------------------------------------------
 ;;; URL viewing.
 
@@ -810,6 +1036,8 @@ case."
       (whitespace-mode arg))
     (setq show-trailing-whitespace whitespace-mode)))
 
+(defvar mdw-do-misc-mode-hacking nil)
+
 (defun mdw-misc-mode-config ()
   (and mdw-auto-indent
        (cond ((eq major-mode 'lisp-mode)
@@ -819,14 +1047,13 @@ case."
              nil)
             (t
              (local-set-key "\C-m" 'newline-and-indent))))
+  (set (make-local-variable 'mdw-do-misc-mode-hacking) t)
   (local-set-key [C-return] 'newline)
   (make-local-variable 'page-delimiter)
   (setq page-delimiter "\f\\|^.*-\\{6\\}.*$")
   (setq comment-column 40)
   (auto-fill-mode 1)
-  (setq fill-column 77)
-  (setq show-trailing-whitespace t)
-  (mdw-whitespace-mode 1)
+  (setq fill-column mdw-text-width)
   (and (fboundp 'gtags-mode)
        (gtags-mode))
   (if (fboundp 'hs-minor-mode)
@@ -835,8 +1062,28 @@ case."
   (reveal-mode t)
   (trap (turn-on-font-lock)))
 
-(defun mdw-post-config-mode-hack ()
-  (mdw-whitespace-mode 1))
+(defun mdw-post-local-vars-misc-mode-config ()
+  (setq whitespace-line-column mdw-text-width)
+  (when (and mdw-do-misc-mode-hacking
+            (not buffer-read-only))
+    (setq show-trailing-whitespace t)
+    (mdw-whitespace-mode 1)))
+(add-hook 'hack-local-variables-hook 'mdw-post-local-vars-misc-mode-config)
+
+(defmacro mdw-advise-update-angry-fruit-salad (&rest funcs)
+  `(progn ,@(mapcar (lambda (func)
+                     `(defadvice ,func
+                          (after mdw-angry-fruit-salad activate)
+                        (when mdw-do-misc-mode-hacking
+                          (setq show-trailing-whitespace
+                                (not buffer-read-only))
+                          (mdw-whitespace-mode (if buffer-read-only 0 1)))))
+                   funcs)))
+(mdw-advise-update-angry-fruit-salad toggle-read-only
+                                    read-only-mode
+                                    view-mode
+                                    view-mode-enable
+                                    view-mode-disable)
 
 (eval-after-load 'gtags
   '(progn
@@ -885,62 +1132,6 @@ doesn't match any of the regular expressions in
 (add-hook 'delete-frame-functions 'mdw-last-one-out-turn-off-the-lights)
 
 ;;;--------------------------------------------------------------------------
-;;; Where is point?
-
-(defvar mdw-point-overlay
-  (let ((ov (make-overlay 0 0))
-       (s "."))
-    (overlay-put ov 'priority 2)
-    (put-text-property 0 1 'display '(left-fringe vertical-bar) s)
-    (overlay-put ov 'before-string s)
-    (delete-overlay ov)
-    ov)
-  "An overlay used for showing where point is in the selected window.")
-
-(defun mdw-remove-point-overlay ()
-  "Remove the current-point overlay."
-  (delete-overlay mdw-point-overlay))
-
-(defun mdw-update-point-overlay ()
-  "Mark the current point position with an overlay."
-  (if (not mdw-point-overlay-mode)
-      (mdw-remove-point-overlay)
-    (overlay-put mdw-point-overlay 'window (selected-window))
-    (if (bolp)
-       (move-overlay mdw-point-overlay
-                     (point) (1+ (point)) (current-buffer))
-      (move-overlay mdw-point-overlay
-                   (1- (point)) (point) (current-buffer)))))
-
-(defvar mdw-point-overlay-buffers nil
-  "List of buffers using `mdw-point-overlay-mode'.")
-
-(define-minor-mode mdw-point-overlay-mode
-  "Indicate current line with an overlay."
-  :global nil
-  (let ((buffer (current-buffer)))
-    (setq mdw-point-overlay-buffers
-         (mapcan (lambda (buf)
-                   (if (and (buffer-live-p buf)
-                            (not (eq buf buffer)))
-                       (list buf)))
-                 mdw-point-overlay-buffers))
-    (if mdw-point-overlay-mode
-       (setq mdw-point-overlay-buffers
-             (cons buffer mdw-point-overlay-buffers))))
-  (cond (mdw-point-overlay-buffers
-        (add-hook 'pre-command-hook 'mdw-remove-point-overlay)
-        (add-hook 'post-command-hook 'mdw-update-point-overlay))
-       (t
-        (mdw-remove-point-overlay)
-        (remove-hook 'pre-command-hook 'mdw-remove-point-overlay)
-        (remove-hook 'post-command-hook 'mdw-update-point-overlay))))
-
-(define-globalized-minor-mode mdw-global-point-overlay-mode
-  mdw-point-overlay-mode
-  (lambda () (if (not (minibufferp)) (mdw-point-overlay-mode t))))
-
-;;;--------------------------------------------------------------------------
 ;;; Fullscreen-ness.
 
 (defvar mdw-full-screen-parameters
@@ -978,12 +1169,14 @@ doesn't match any of the regular expressions in
 ;;;--------------------------------------------------------------------------
 ;;; General fontification.
 
+(make-face 'mdw-virgin-face)
+
 (defmacro mdw-define-face (name &rest body)
   "Define a face, and make sure it's actually set as the definition."
   (declare (indent 1)
           (debug 0))
   `(progn
-     (make-face ',name)
+     (copy-face 'mdw-virgin-face ',name)
      (defvar ,name ',name)
      (put ',name 'face-defface-spec ',body)
      (face-spec-set ',name ',body nil)))
@@ -997,22 +1190,21 @@ doesn't match any of the regular expressions in
   (((type w32)) :family "courier new" :height 85)
   (((type x)) :family "6x13" :foundry "trad" :height 130)
   (t :foreground "white" :background "black"))
-(if (>= emacs-major-version 23)
+(if (mdw-emacs-version-p 23)
     (mdw-define-face variable-pitch
       (((type x)) :family "sans" :height 100))
   (mdw-define-face variable-pitch
     (((type x)) :family "helvetica" :height 90)))
 (mdw-define-face region
-  (((type tty) (class color)) :background "blue")
-  (((type tty) (class mono)) :inverse-video t)
-  (t :background "grey30"))
+  (((min-colors 64)) :background "grey30")
+  (((class color)) :background "blue")
+  ((t) :inverse-video t))
 (mdw-define-face match
-  (((type tty) (class color)) :background "blue")
-  (((type tty) (class mono)) :inverse-video t)
-  (t :background "blue"))
+  (((class color)) :background "blue")
+  (t :inverse-video t))
 (mdw-define-face mc/cursor-face
-  (((type tty) (class mono)) :inverse-video t)
-  (t :background "red"))
+  (((class color)) :background "red")
+  (t :inverse-video t))
 (mdw-define-face minibuffer-prompt
   (t :weight bold))
 (mdw-define-face mode-line
@@ -1037,8 +1229,8 @@ doesn't match any of the regular expressions in
   (((class color)) :background "red")
   (t :inverse-video t))
 (mdw-define-face highlight
-  (((type x) (class color)) :background "DarkSeaGreen4")
-  (((type tty) (class color)) :background "cyan")
+  (((min-colors 64)) :background "DarkSeaGreen4")
+  (((class color)) :background "cyan")
   (t :inverse-video t))
 
 (mdw-define-face holiday-face
@@ -1051,6 +1243,9 @@ doesn't match any of the regular expressions in
 (mdw-define-face comint-highlight-input
   (t nil))
 
+(mdw-define-face ido-subdir
+  (t :foreground "cyan" :weight bold))
+
 (mdw-define-face dired-directory
   (t :foreground "cyan" :weight bold))
 (mdw-define-face dired-symlink
@@ -1061,8 +1256,12 @@ doesn't match any of the regular expressions in
 (mdw-define-face trailing-whitespace
   (((class color)) :background "red")
   (t :inverse-video t))
+(mdw-define-face whitespace-line
+  (((class color)) :background "darkred")
+  (t :inverse-video t))
 (mdw-define-face mdw-punct-face
-  (((type tty)) :foreground "yellow") (t :foreground "burlywood2"))
+  (((min-colors 64)) :foreground "burlywood2")
+  (((class color)) :foreground "yellow"))
 (mdw-define-face mdw-number-face
   (t :foreground "yellow"))
 (mdw-define-face mdw-trivial-face)
@@ -1081,45 +1280,105 @@ doesn't match any of the regular expressions in
 (mdw-define-face font-lock-variable-name-face
   (t :slant italic))
 (mdw-define-face font-lock-comment-delimiter-face
-  (((class mono)) :weight bold)
-  (((type tty) (class color)) :foreground "green")
-  (t :slant italic :foreground "SeaGreen1"))
+  (((min-colors 64)) :slant italic :foreground "SeaGreen1")
+  (((class color)) :foreground "green")
+  (t :weight bold))
 (mdw-define-face font-lock-comment-face
-  (((class mono)) :weight bold)
-  (((type tty) (class color)) :foreground "green")
-  (t :slant italic :foreground "SeaGreen1"))
+  (((min-colors 64)) :slant italic :foreground "SeaGreen1")
+  (((class color)) :foreground "green")
+  (t :weight bold))
 (mdw-define-face font-lock-string-face
-  (((class mono)) :weight bold)
-  (((class color)) :foreground "SkyBlue1"))
+  (((min-colors 64)) :foreground "SkyBlue1")
+  (((class color)) :foreground "cyan")
+  (t :weight bold))
 
 (mdw-define-face message-separator
   (t :background "red" :foreground "white" :weight bold))
 (mdw-define-face message-cited-text
   (default :slant italic)
-  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+  (((min-colors 64)) :foreground "SkyBlue1")
+  (((class color)) :foreground "cyan"))
 (mdw-define-face message-header-cc
-  (default :weight bold)
-  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+  (default :slant italic)
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
 (mdw-define-face message-header-newsgroups
-  (default :weight bold)
-  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+  (default :slant italic)
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
 (mdw-define-face message-header-subject
-  (default :weight bold)
-  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
 (mdw-define-face message-header-to
-  (default :weight bold)
-  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
 (mdw-define-face message-header-xheader
-  (default :weight bold)
-  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+  (default :slant italic)
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
 (mdw-define-face message-header-other
-  (default :weight bold)
-  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+  (default :slant italic)
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
 (mdw-define-face message-header-name
-  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+  (default :weight bold)
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
+
 (mdw-define-face which-func
   (t nil))
 
+(mdw-define-face gnus-header-name
+  (default :weight bold)
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
+(mdw-define-face gnus-header-subject
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
+(mdw-define-face gnus-header-from
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
+(mdw-define-face gnus-header-to
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
+(mdw-define-face gnus-header-content
+  (default :slant italic)
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
+
+(mdw-define-face gnus-cite-1
+  (((min-colors 64)) :foreground "SkyBlue1")
+  (((class color)) :foreground "cyan"))
+(mdw-define-face gnus-cite-2
+  (((min-colors 64)) :foreground "RoyalBlue2")
+  (((class color)) :foreground "blue"))
+(mdw-define-face gnus-cite-3
+  (((min-colors 64)) :foreground "MediumOrchid")
+  (((class color)) :foreground "magenta"))
+(mdw-define-face gnus-cite-4
+  (((min-colors 64)) :foreground "firebrick2")
+  (((class color)) :foreground "red"))
+(mdw-define-face gnus-cite-5
+  (((min-colors 64)) :foreground "burlywood2")
+  (((class color)) :foreground "yellow"))
+(mdw-define-face gnus-cite-6
+  (((min-colors 64)) :foreground "SeaGreen1")
+  (((class color)) :foreground "green"))
+(mdw-define-face gnus-cite-7
+  (((min-colors 64)) :foreground "SlateBlue1")
+  (((class color)) :foreground "cyan"))
+(mdw-define-face gnus-cite-8
+  (((min-colors 64)) :foreground "RoyalBlue2")
+  (((class color)) :foreground "blue"))
+(mdw-define-face gnus-cite-9
+  (((min-colors 64)) :foreground "purple2")
+  (((class color)) :foreground "magenta"))
+(mdw-define-face gnus-cite-10
+  (((min-colors 64)) :foreground "DarkOrange2")
+  (((class color)) :foreground "red"))
+(mdw-define-face gnus-cite-11
+  (t :foreground "grey"))
+
 (mdw-define-face diff-header
   (t nil))
 (mdw-define-face diff-index
@@ -1127,48 +1386,101 @@ doesn't match any of the regular expressions in
 (mdw-define-face diff-file-header
   (t :weight bold))
 (mdw-define-face diff-hunk-header
-  (t :foreground "SkyBlue1"))
+  (((min-colors 64)) :foreground "SkyBlue1")
+  (((class color)) :foreground "cyan"))
 (mdw-define-face diff-function
-  (t :foreground "SkyBlue1" :weight bold))
+  (default :weight bold)
+  (((min-colors 64)) :foreground "SkyBlue1")
+  (((class color)) :foreground "cyan"))
 (mdw-define-face diff-header
-  (t :background "grey10"))
+  (((min-colors 64)) :background "grey10"))
 (mdw-define-face diff-added
-  (t :foreground "green"))
+  (((class color)) :foreground "green"))
 (mdw-define-face diff-removed
-  (t :foreground "red"))
+  (((class color)) :foreground "red"))
 (mdw-define-face diff-context
   (t nil))
 (mdw-define-face diff-refine-change
-  (((class color) (type x)) :background "RoyalBlue4")
+  (((min-colors 64)) :background "RoyalBlue4")
+  (t :underline t))
+(mdw-define-face diff-refine-removed
+  (((min-colors 64)) :background "#500")
+  (t :underline t))
+(mdw-define-face diff-refine-added
+  (((min-colors 64)) :background "#050")
   (t :underline t))
 
-(mdw-define-face dylan-header-background
-  (((class color) (type x)) :background "NavyBlue")
-  (t :background "blue"))
+(setq ediff-force-faces t)
+(mdw-define-face ediff-current-diff-A
+  (((min-colors 64)) :background "darkred")
+  (((class color)) :background "red")
+  (t :inverse-video t))
+(mdw-define-face ediff-fine-diff-A
+  (((min-colors 64)) :background "red3")
+  (((class color)) :inverse-video t)
+  (t :inverse-video nil))
+(mdw-define-face ediff-even-diff-A
+  (((min-colors 64)) :background "#300"))
+(mdw-define-face ediff-odd-diff-A
+  (((min-colors 64)) :background "#300"))
+(mdw-define-face ediff-current-diff-B
+  (((min-colors 64)) :background "darkgreen")
+  (((class color)) :background "magenta")
+  (t :inverse-video t))
+(mdw-define-face ediff-fine-diff-B
+  (((min-colors 64)) :background "green4")
+  (((class color)) :inverse-video t)
+  (t :inverse-video nil))
+(mdw-define-face ediff-even-diff-B
+  (((min-colors 64)) :background "#020"))
+(mdw-define-face ediff-odd-diff-B
+  (((min-colors 64)) :background "#020"))
+(mdw-define-face ediff-current-diff-C
+  (((min-colors 64)) :background "darkblue")
+  (((class color)) :background "blue")
+  (t :inverse-video t))
+(mdw-define-face ediff-fine-diff-C
+  (((min-colors 64)) :background "blue1")
+  (((class color)) :inverse-video t)
+  (t :inverse-video nil))
+(mdw-define-face ediff-even-diff-C
+  (((min-colors 64)) :background "#004"))
+(mdw-define-face ediff-odd-diff-C
+  (((min-colors 64)) :background "#004"))
+(mdw-define-face ediff-current-diff-Ancestor
+  (((min-colors 64)) :background "#630")
+  (((class color)) :background "blue")
+  (t :inverse-video t))
+(mdw-define-face ediff-even-diff-Ancestor
+  (((min-colors 64)) :background "#320"))
+(mdw-define-face ediff-odd-diff-Ancestor
+  (((min-colors 64)) :background "#320"))
+
+(mdw-define-face magit-hash
+  (((min-colors 64)) :foreground "grey40")
+  (((class color)) :foreground "blue"))
+(mdw-define-face magit-diff-hunk-heading
+  (((min-colors 64)) :foreground "grey70" :background "grey25")
+  (((class color)) :foreground "yellow"))
+(mdw-define-face magit-diff-hunk-heading-highlight
+  (((min-colors 64)) :foreground "grey70" :background "grey35")
+  (((class color)) :foreground "yellow" :background "blue"))
+(mdw-define-face magit-diff-added
+  (((min-colors 64)) :foreground "#ddffdd" :background "#335533")
+  (((class color)) :foreground "green"))
+(mdw-define-face magit-diff-added-highlight
+  (((min-colors 64)) :foreground "#cceecc" :background "#336633")
+  (((class color)) :foreground "green" :background "blue"))
+(mdw-define-face magit-diff-removed
+  (((min-colors 64)) :foreground "#ffdddd" :background "#553333")
+  (((class color)) :foreground "red"))
+(mdw-define-face magit-diff-removed-highlight
+  (((min-colors 64)) :foreground "#eecccc" :background "#663333")
+  (((class color)) :foreground "red" :background "blue"))
 
-(mdw-define-face magit-diff-add
-  (t :foreground "green"))
-(mdw-define-face magit-diff-del
-  (t :foreground "red"))
-(mdw-define-face magit-diff-file-header
-  (t :weight bold))
-(mdw-define-face magit-diff-hunk-header
-  (t :foreground "SkyBlue1"))
-(mdw-define-face magit-item-highlight
-  (((type tty)) :background "blue")
-  (t :background "DarkSeaGreen4"))
-(mdw-define-face magit-log-head-label-remote
-  (((type tty)) :background "cyan" :foreground "green")
-  (t :background "grey11" :foreground "DarkSeaGreen2" :box t))
-(mdw-define-face magit-log-head-label-local
-  (((type tty)) :background "cyan" :foreground "yellow")
-  (t :background "grey11" :foreground "LightSkyBlue1" :box t))
-(mdw-define-face magit-log-head-label-tags
-  (((type tty)) :background "red" :foreground "yellow")
-  (t :background "LemonChiffon1" :foreground "goldenrod4" :box t))
-(mdw-define-face magit-log-graph
-  (((type tty)) :foreground "magenta")
-  (t :foreground "grey80"))
+(mdw-define-face dylan-header-background
+  (((min-colors 64)) :background "NavyBlue")
+  (((class color)) :background "blue"))
 
 (mdw-define-face erc-input-face
   (t :foreground "red"))
@@ -1226,7 +1538,7 @@ doesn't match any of the regular expressions in
 (mdw-define-face mdw-ellipsis-face
   (((type tty)) :foreground "blue") (t :foreground "grey60"))
 (let ((dollar (make-glyph-code ?$ 'mdw-ellipsis-face))
-      (backslash (make-glyph-code ?\ 'mdw-ellipsis-face))
+      (backslash (make-glyph-code ?\\ 'mdw-ellipsis-face))
       (dot (make-glyph-code ?. 'mdw-ellipsis-face))
       (bar (make-glyph-code ?| mdw-ellipsis-face)))
   (set-display-table-slot standard-display-table 0 dollar)
@@ -1236,18 +1548,85 @@ doesn't match any of the regular expressions in
   (set-display-table-slot standard-display-table 5 bar))
 
 ;;;--------------------------------------------------------------------------
-;;; C programming configuration.
-
-;; Linux kernel hacking.
+;;; Where is point?
 
-(defvar linux-c-mode-hook)
+(mdw-define-face mdw-point-overlay
+  (((type graphic)))
+  (((min-colors 64)) :background "darkblue")
+  (((class color)) :background "blue")
+  (((type tty) (class mono)) :inverse-video t))
+
+(defvar mdw-point-overlay-fringe-display '(vertical-bar . vertical-bar))
+
+(defun mdw-configure-point-overlay ()
+  (let ((ov (make-overlay 0 0)))
+    (overlay-put ov 'priority 0)
+    (let* ((fringe (or mdw-point-overlay-fringe-display (cons nil nil)))
+          (left (car fringe)) (right (cdr fringe))
+          (s ""))
+      (when left
+       (let ((ss "."))
+         (put-text-property 0 1 'display `(left-fringe ,left) ss)
+         (setq s (concat s ss))))
+      (when right
+       (let ((ss "."))
+         (put-text-property 0 1 'display `(right-fringe ,right) ss)
+         (setq s (concat s ss))))
+      (when (or left right)
+       (overlay-put ov 'before-string s)))
+    (overlay-put ov 'face 'mdw-point-overlay)
+    (delete-overlay ov)
+    ov))
 
-(defun linux-c-mode ()
+(defvar mdw-point-overlay (mdw-configure-point-overlay)
+  "An overlay used for showing where point is in the selected window.")
+(defun mdw-reconfigure-point-overlay ()
   (interactive)
-  (c-mode)
-  (setq major-mode 'linux-c-mode)
-  (setq mode-name "Linux C")
-  (run-hooks 'linux-c-mode-hook))
+  (setq mdw-point-overlay (mdw-configure-point-overlay)))
+
+(defun mdw-remove-point-overlay ()
+  "Remove the current-point overlay."
+  (delete-overlay mdw-point-overlay))
+
+(defun mdw-update-point-overlay ()
+  "Mark the current point position with an overlay."
+  (if (not mdw-point-overlay-mode)
+      (mdw-remove-point-overlay)
+    (overlay-put mdw-point-overlay 'window (selected-window))
+    (move-overlay mdw-point-overlay
+                 (line-beginning-position)
+                 (+ (line-end-position) 1))))
+
+(defvar mdw-point-overlay-buffers nil
+  "List of buffers using `mdw-point-overlay-mode'.")
+
+(define-minor-mode mdw-point-overlay-mode
+  "Indicate current line with an overlay."
+  :global nil
+  (let ((buffer (current-buffer)))
+    (setq mdw-point-overlay-buffers
+         (mapcan (lambda (buf)
+                   (if (and (buffer-live-p buf)
+                            (not (eq buf buffer)))
+                       (list buf)))
+                 mdw-point-overlay-buffers))
+    (if mdw-point-overlay-mode
+       (setq mdw-point-overlay-buffers
+             (cons buffer mdw-point-overlay-buffers))))
+  (cond (mdw-point-overlay-buffers
+        (add-hook 'pre-command-hook 'mdw-remove-point-overlay)
+        (add-hook 'post-command-hook 'mdw-update-point-overlay))
+       (t
+        (mdw-remove-point-overlay)
+        (remove-hook 'pre-command-hook 'mdw-remove-point-overlay)
+        (remove-hook 'post-command-hook 'mdw-update-point-overlay))))
+
+(define-globalized-minor-mode mdw-global-point-overlay-mode
+  mdw-point-overlay-mode
+  (lambda () (if (not (minibufferp)) (mdw-point-overlay-mode t))))
+
+;;;--------------------------------------------------------------------------
+;;; C programming configuration.
 
 ;; Make C indentation nice.
 
@@ -1267,28 +1646,108 @@ doesn't match any of the regular expressions in
        c-basic-offset
       nil)))
 
-(defun mdw-c-style ()
-  (c-add-style "[mdw] C and C++ style"
-              '((c-basic-offset . 2)
-                (comment-column . 40)
-                (c-class-key . "class")
-                (c-backslash-column . 72)
-                (c-offsets-alist
-                 (substatement-open . (add 0 c-indent-one-line-block))
-                 (defun-open . (add 0 c-indent-one-line-block))
-                 (arglist-cont-nonempty . mdw-c-lineup-arglist)
-                 (topmost-intro . mdw-c-indent-extern-mumble)
-                 (cpp-define-intro . 0)
-                 (knr-argdecl . 0)
-                 (inextern-lang . [0])
-                 (label . 0)
-                 (case-label . +)
-                 (access-label . -)
-                 (inclass . +)
-                 (inline-open . ++)
-                 (statement-cont . +)
-                 (statement-case-intro . +)))
-              t))
+(defun mdw-c-indent-arglist-nested (langelem)
+  "Indent continued argument lists.
+If we've nested more than one argument list, then only introduce a single
+indentation anyway."
+  (let ((context c-syntactic-context)
+       (pos (c-langelem-2nd-pos c-syntactic-element))
+       (should-indent-p t))
+    (while (and context
+               (eq (caar context) 'arglist-cont-nonempty))
+      (when (and (= (caddr (pop context)) pos)
+                context
+                (memq (caar context) '(arglist-intro
+                                       arglist-cont-nonempty)))
+       (setq should-indent-p nil)))
+    (if should-indent-p '+ 0)))
+
+(defvar mdw-define-c-styles-hook nil
+  "Hook run when `cc-mode' starts up to define styles.")
+
+(defmacro mdw-define-c-style (name &rest assocs)
+  "Define a C style, called NAME (a symbol), setting ASSOCs.
+A function, named `mdw-define-c-style/NAME', is defined to actually install
+the style using `c-add-style', and added to the hook
+`mdw-define-c-styles-hook'.  If CC Mode is already loaded, then the style is
+set."
+  (declare (indent defun))
+  (let* ((name-string (symbol-name name))
+        (func (intern (concat "mdw-define-c-style/" name-string))))
+    `(progn
+       (defun ,func () (c-add-style ,name-string ',assocs))
+       (and (featurep 'cc-mode) (,func))
+       (add-hook 'mdw-define-c-styles-hook ',func))))
+
+(eval-after-load "cc-mode"
+  '(run-hooks 'mdw-define-c-styles-hook))
+
+(mdw-define-c-style mdw-trustonic-c
+  (c-basic-offset . 4)
+  (comment-column . 0)
+  (c-indent-comment-alist (anchored-comment . (column . 0))
+                         (end-block . (space . 1))
+                         (cpp-end-block . (space . 1))
+                         (other . (space . 1)))
+  (c-class-key . "class")
+  (c-backslash-column . 0)
+  (c-auto-align-backslashes . nil)
+  (c-label-minimum-indentation . 0)
+  (c-offsets-alist (substatement-open . (add 0 c-indent-one-line-block))
+                  (defun-open . (add 0 c-indent-one-line-block))
+                  (arglist-cont-nonempty . mdw-c-indent-arglist-nested)
+                  (topmost-intro . mdw-c-indent-extern-mumble)
+                  (cpp-define-intro . 0)
+                  (knr-argdecl . 0)
+                  (inextern-lang . [0])
+                  (label . 0)
+                  (case-label . +)
+                  (access-label . -2)
+                  (inclass . +)
+                  (inline-open . ++)
+                  (statement-cont . +)
+                  (statement-case-intro . +)))
+
+(mdw-define-c-style mdw-c
+  (c-basic-offset . 2)
+  (comment-column . 40)
+  (c-class-key . "class")
+  (c-backslash-column . 72)
+  (c-label-minimum-indentation . 0)
+  (c-offsets-alist (substatement-open . (add 0 c-indent-one-line-block))
+                  (defun-open . (add 0 c-indent-one-line-block))
+                  (arglist-cont-nonempty . mdw-c-lineup-arglist)
+                  (topmost-intro . mdw-c-indent-extern-mumble)
+                  (cpp-define-intro . 0)
+                  (knr-argdecl . 0)
+                  (inextern-lang . [0])
+                  (label . 0)
+                  (case-label . +)
+                  (access-label . -)
+                  (inclass . +)
+                  (inline-open . ++)
+                  (statement-cont . +)
+                  (statement-case-intro . +)))
+
+(defun mdw-set-default-c-style (modes style)
+  "Update the default CC Mode style for MODES to be STYLE.
+
+MODES may be a list of major mode names or a singleton.  STYLE is a style
+name, as a symbol."
+  (let ((modes (if (listp modes) modes (list modes)))
+       (style (symbol-name style)))
+    (setq c-default-style
+         (append (mapcar (lambda (mode)
+                           (cons mode style))
+                         modes)
+                 (remove-if (lambda (assoc)
+                              (memq (car assoc) modes))
+                            (if (listp c-default-style)
+                                c-default-style
+                              (list (cons 'other c-default-style))))))))
+(setq c-default-style "mdw-c")
+
+(mdw-set-default-c-style '(c-mode c++-mode) 'mdw-c)
 
 (defvar mdw-c-comment-fill-prefix
   `((,(concat "\\([ \t]*/?\\)"
@@ -1307,78 +1766,87 @@ doesn't match any of the regular expressions in
   (modify-syntax-entry ?\n "> b")
 
   ;; Other stuff.
-  (mdw-c-style)
-  (setq c-hanging-comment-ender-p nil)
-  (setq c-backslash-column 72)
-  (setq c-label-minimum-indentation 0)
   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
 
   ;; Now define things to be fontified.
   (make-local-variable 'font-lock-keywords)
   (let ((c-keywords
-        (mdw-regexps "and"             ;C++
-                     "and_eq"          ;C++
-                     "asm"             ;K&R, GCC
-                     "auto"            ;K&R, C89
-                     "bitand"          ;C++
-                     "bitor"           ;C++
-                     "bool"            ;C++, C9X macro
-                     "break"           ;K&R, C89
-                     "case"            ;K&R, C89
-                     "catch"           ;C++
-                     "char"            ;K&R, C89
-                     "class"           ;C++
-                     "complex"         ;C9X macro, C++ template type
-                     "compl"           ;C++
-                     "const"           ;C89
-                     "const_cast"      ;C++
-                     "continue"        ;K&R, C89
-                     "defined"         ;C89 preprocessor
-                     "default"         ;K&R, C89
-                     "delete"          ;C++
-                     "do"              ;K&R, C89
-                     "double"          ;K&R, C89
-                     "dynamic_cast"    ;C++
-                     "else"            ;K&R, C89
-                     ;; "entry"        ;K&R -- never used
-                     "enum"            ;C89
-                     "explicit"        ;C++
-                     "export"          ;C++
-                     "extern"          ;K&R, C89
-                     "float"           ;K&R, C89
-                     "for"             ;K&R, C89
-                     ;; "fortran"      ;K&R
-                     "friend"          ;C++
-                     "goto"            ;K&R, C89
-                     "if"              ;K&R, C89
-                     "imaginary"       ;C9X macro
-                     "inline"          ;C++, C9X, GCC
-                     "int"             ;K&R, C89
-                     "long"            ;K&R, C89
-                     "mutable"         ;C++
-                     "namespace"       ;C++
-                     "new"             ;C++
-                     "operator"        ;C++
-                     "or"              ;C++
-                     "or_eq"           ;C++
-                     "private"         ;C++
-                     "protected"       ;C++
-                     "public"          ;C++
-                     "register"        ;K&R, C89
+        (mdw-regexps "alignas"          ;C11 macro, C++11
+                     "alignof"          ;C++11
+                     "and"              ;C++, C95 macro
+                     "and_eq"           ;C++, C95 macro
+                     "asm"              ;K&R, C++, GCC
+                     "atomic"           ;C11 macro, C++11 template type
+                     "auto"             ;K&R, C89
+                     "bitand"           ;C++, C95 macro
+                     "bitor"            ;C++, C95 macro
+                     "bool"             ;C++, C99 macro
+                     "break"            ;K&R, C89
+                     "case"             ;K&R, C89
+                     "catch"            ;C++
+                     "char"             ;K&R, C89
+                     "char16_t"         ;C++11, C11 library type
+                     "char32_t"         ;C++11, C11 library type
+                     "class"            ;C++
+                     "complex"          ;C99 macro, C++ template type
+                     "compl"            ;C++, C95 macro
+                     "const"            ;C89
+                     "constexpr"        ;C++11
+                     "const_cast"       ;C++
+                     "continue"         ;K&R, C89
+                     "decltype"         ;C++11
+                     "defined"          ;C89 preprocessor
+                     "default"          ;K&R, C89
+                     "delete"           ;C++
+                     "do"               ;K&R, C89
+                     "double"           ;K&R, C89
+                     "dynamic_cast"     ;C++
+                     "else"             ;K&R, C89
+                     ;; "entry"         ;K&R -- never used
+                     "enum"             ;C89
+                     "explicit"         ;C++
+                     "export"           ;C++
+                     "extern"           ;K&R, C89
+                     "float"            ;K&R, C89
+                     "for"              ;K&R, C89
+                     ;; "fortran"       ;K&R
+                     "friend"           ;C++
+                     "goto"             ;K&R, C89
+                     "if"               ;K&R, C89
+                     "imaginary"        ;C99 macro
+                     "inline"           ;C++, C99, GCC
+                     "int"              ;K&R, C89
+                     "long"             ;K&R, C89
+                     "mutable"          ;C++
+                     "namespace"        ;C++
+                     "new"              ;C++
+                     "noexcept"         ;C++11
+                     "noreturn"         ;C11 macro
+                     "not"              ;C++, C95 macro
+                     "not_eq"           ;C++, C95 macro
+                     "nullptr"          ;C++11
+                     "operator"         ;C++
+                     "or"               ;C++, C95 macro
+                     "or_eq"            ;C++, C95 macro
+                     "private"          ;C++
+                     "protected"        ;C++
+                     "public"           ;C++
+                     "register"         ;K&R, C89
                      "reinterpret_cast" ;C++
-                     "restrict"         ;C9X
+                     "restrict"         ;C99
                      "return"           ;K&R, C89
                      "short"            ;K&R, C89
                      "signed"           ;C89
                      "sizeof"           ;K&R, C89
                      "static"           ;K&R, C89
+                     "static_assert"    ;C11 macro, C++11
                      "static_cast"      ;C++
                      "struct"           ;K&R, C89
                      "switch"           ;K&R, C89
                      "template"         ;C++
                      "throw"            ;C++
                      "try"              ;C++
-                     "this"             ;C++
+                     "thread_local"     ;C11 macro, C++11
                      "typedef"          ;C89
                      "typeid"           ;C++
                      "typeof"           ;GCC
@@ -1391,12 +1859,19 @@ doesn't match any of the regular expressions in
                      "volatile"         ;C89
                      "wchar_t"          ;C++, C89 library type
                      "while"            ;K&R, C89
-                     "xor"              ;C++
-                     "xor_eq"           ;C++
-                     "_Bool"            ;C9X
-                     "_Complex"         ;C9X
-                     "_Imaginary"       ;C9X
-                     "_Pragma"          ;C9X preprocessor
+                     "xor"              ;C++, C95 macro
+                     "xor_eq"           ;C++, C95 macro
+                     "_Alignas"         ;C11
+                     "_Alignof"         ;C11
+                     "_Atomic"          ;C11
+                     "_Bool"            ;C99
+                     "_Complex"         ;C99
+                     "_Generic"         ;C11
+                     "_Imaginary"       ;C99
+                     "_Noreturn"        ;C11
+                     "_Pragma"          ;C99 preprocessor
+                     "_Static_assert"   ;C11
+                     "_Thread_local"    ;C11
                      "__alignof__"      ;GCC
                      "__asm__"          ;GCC
                      "__attribute__"    ;GCC
@@ -1412,9 +1887,9 @@ doesn't match any of the regular expressions in
                      "__volatile__"     ;GCC
                      ))
        (c-constants
-        (mdw-regexps "false"           ;C++, C9X macro
+        (mdw-regexps "false"            ;C++, C99 macro
                      "this"             ;C++
-                     "true"             ;C++, C9X macro
+                     "true"             ;C++, C99 macro
                      ))
        (preprocessor-keywords
         (mdw-regexps "assert" "define" "elif" "else" "endif" "error"
@@ -1461,19 +1936,17 @@ doesn't match any of the regular expressions in
 
           ;; And anything else is punctuation.
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face))))
+                '(0 mdw-punct-face))))))
 
-    (mdw-post-config-mode-hack)))
+(define-derived-mode sod-mode c-mode "Sod"
+  "Major mode for editing Sod code.")
+(push '("\\.sod$" . sod-mode) auto-mode-alist)
 
 ;;;--------------------------------------------------------------------------
 ;;; AP calc mode.
 
-(defun apcalc-mode ()
-  (interactive)
-  (c-mode)
-  (setq major-mode 'apcalc-mode)
-  (setq mode-name "AP Calc")
-  (run-hooks 'apcalc-mode-hook))
+(define-derived-mode apcalc-mode c-mode "AP Calc"
+  "Major mode for editing Calc code.")
 
 (defun mdw-fontify-apcalc ()
 
@@ -1482,9 +1955,6 @@ doesn't match any of the regular expressions in
   (modify-syntax-entry ?/ ". 14")
 
   ;; Other stuff.
-  (mdw-c-style)
-  (setq c-hanging-comment-ender-p nil)
-  (setq c-backslash-column 72)
   (setq comment-start "/* ")
   (setq comment-end " */")
   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
@@ -1515,34 +1985,29 @@ doesn't match any of the regular expressions in
 
           ;; And anything else is punctuation.
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                '(0 mdw-punct-face))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Java programming configuration.
 
 ;; Make indentation nice.
 
-(defun mdw-java-style ()
-  (c-add-style "[mdw] Java style"
-              '((c-basic-offset . 2)
-                (c-offsets-alist (substatement-open . 0)
-                                 (label . +)
-                                 (case-label . +)
-                                 (access-label . 0)
-                                 (inclass . +)
-                                 (statement-case-intro . +)))
-              t))
+(mdw-define-c-style mdw-java
+  (c-basic-offset . 2)
+  (c-backslash-column . 72)
+  (c-offsets-alist (substatement-open . 0)
+                  (label . +)
+                  (case-label . +)
+                  (access-label . 0)
+                  (inclass . +)
+                  (statement-case-intro . +)))
+(mdw-set-default-c-style 'java-mode 'mdw-java)
 
 ;; Declare Java fontification style.
 
 (defun mdw-fontify-java ()
 
   ;; Other stuff.
-  (mdw-java-style)
-  (setq c-hanging-comment-ender-p nil)
-  (setq c-backslash-column 72)
   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
 
   ;; Now define things to be fontified.
@@ -1583,9 +2048,7 @@ doesn't match any of the regular expressions in
 
           ;; And anything else is punctuation.
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                '(0 mdw-punct-face))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Javascript programming configuration.
@@ -1643,9 +2106,7 @@ doesn't match any of the regular expressions in
 
           ;; And anything else is punctuation.
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                '(0 mdw-punct-face))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Scala programming configuration.
@@ -1718,34 +2179,29 @@ doesn't match any of the regular expressions in
                         "\\|" "\\\\" "." "\\)"
                         "\\('\\)")
                 '(1 "\"")
-                '(4 "\"")))))
-
-  (mdw-post-config-mode-hack))
+                '(4 "\""))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; C# programming configuration.
 
 ;; Make indentation nice.
 
-(defun mdw-csharp-style ()
-  (c-add-style "[mdw] C# style"
-              '((c-basic-offset . 2)
-                (c-offsets-alist (substatement-open . 0)
-                                 (label . 0)
-                                 (case-label . +)
-                                 (access-label . 0)
-                                 (inclass . +)
-                                 (statement-case-intro . +)))
-              t))
+(mdw-define-c-style mdw-csharp
+  (c-basic-offset . 2)
+  (c-backslash-column . 72)
+  (c-offsets-alist (substatement-open . 0)
+                  (label . 0)
+                  (case-label . +)
+                  (access-label . 0)
+                  (inclass . +)
+                  (statement-case-intro . +)))
+(mdw-set-default-c-style 'csharp-mode 'mdw-csharp)
 
 ;; Declare C# fontification style.
 
 (defun mdw-fontify-csharp ()
 
   ;; Other stuff.
-  (mdw-csharp-style)
-  (setq c-hanging-comment-ender-p nil)
-  (setq c-backslash-column 72)
   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
 
   ;; Now define things to be fontified.
@@ -1791,9 +2247,7 @@ doesn't match any of the regular expressions in
 
           ;; And anything else is punctuation.
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                '(0 mdw-punct-face))))))
 
 (define-derived-mode csharp-mode java-mode "C#"
   "Major mode for editing C# code.")
@@ -1908,9 +2362,7 @@ doesn't match any of the regular expressions in
                      '(0 mdw-number-face))
 
                (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                     '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                     '(0 mdw-punct-face))))))
 
 (defun mdw-fontify-inferior-fsharp ()
   (mdw-fontify-fsharp)
@@ -1979,9 +2431,7 @@ doesn't match any of the regular expressions in
 
           ;; And anything else is punctuation.
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                '(0 mdw-punct-face))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Rust programming configuration.
@@ -2030,13 +2480,13 @@ doesn't match any of the regular expressions in
          (list
 
           ;; Handle the keywords defined above.
-          (list (concat "\\<\\(" rust-keywords "\\)\\>")
+          (list (concat "\\_<\\(" rust-keywords "\\)\\_>")
                 '(0 font-lock-keyword-face))
-          (list (concat "\\<\\(" rust-builtins "\\)\\>")
+          (list (concat "\\_<\\(" rust-builtins "\\)\\_>")
                 '(0 font-lock-variable-name-face))
 
           ;; Handle numbers too.
-          (list (concat "\\<\\("
+          (list (concat "\\_<\\("
                               "[0-9][0-9_]*"
                               "\\(" "\\(\\.[0-9_]+\\)?[eE][-+]?[0-9_]+"
                               "\\|" "\\.[0-9_]+"
@@ -2048,7 +2498,7 @@ doesn't match any of the regular expressions in
                               "\\|" "0b[01_]+"
                               "\\)"
                               "\\([ui]\\(8\\|16\\|32\\|64\\|s\\|size\\)\\)?"
-                        "\\)\\>")
+                        "\\)\\_>")
                 '(0 mdw-number-face))
 
           ;; And anything else is punctuation.
@@ -2057,31 +2507,26 @@ doesn't match any of the regular expressions in
 
   ;; Hack key bindings.
   (local-set-key [?{] 'mdw-self-insert-and-indent)
-  (local-set-key [?}] 'mdw-self-insert-and-indent)
-
-  ;; Final hacking.
-  (mdw-post-config-mode-hack))
+  (local-set-key [?}] 'mdw-self-insert-and-indent))
 
 ;;;--------------------------------------------------------------------------
 ;;; Awk programming configuration.
 
 ;; Make Awk indentation nice.
 
-(defun mdw-awk-style ()
-  (c-add-style "[mdw] Awk style"
-              '((c-basic-offset . 2)
-                (c-offsets-alist (substatement-open . 0)
-                                 (statement-cont . 0)
-                                 (statement-case-intro . +)))
-              t))
+(mdw-define-c-style mdw-awk
+  (c-basic-offset . 2)
+  (c-offsets-alist (substatement-open . 0)
+                  (c-backslash-column . 72)
+                  (statement-cont . 0)
+                  (statement-case-intro . +)))
+(mdw-set-default-c-style 'awk-mode 'mdw-awk)
 
 ;; Declare Awk fontification style.
 
 (defun mdw-fontify-awk ()
 
   ;; Miscellaneous fiddling.
-  (mdw-awk-style)
-  (setq c-backslash-column 72)
   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
 
   ;; Now define things to be fontified.
@@ -2118,15 +2563,15 @@ doesn't match any of the regular expressions in
 
           ;; And anything else is punctuation.
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                '(0 mdw-punct-face))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Perl programming style.
 
 ;; Perl indentation style.
 
+(setq perl-indent-level 2)
+
 (setq cperl-indent-level 2)
 (setq cperl-continued-statement-offset 2)
 (setq cperl-continued-brace-offset 0)
@@ -2180,9 +2625,7 @@ doesn't match any of the regular expressions in
 
           ;; And anything else is punctuation.
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                '(0 mdw-punct-face))))))
 
 (defun perl-number-tests (&optional arg)
   "Assign consecutive numbers to lines containing `#t'.  With ARG,
@@ -2225,9 +2668,7 @@ strip numbers instead."
 
         ;; And anything else is punctuation.
         (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-              '(0 mdw-punct-face))))
-
-  (mdw-post-config-mode-hack))
+              '(0 mdw-punct-face)))))
 
 ;; Define Python fontification styles.
 
@@ -2242,12 +2683,63 @@ strip numbers instead."
 (defun mdw-fontify-pyrex ()
   (mdw-fontify-pythonic
    (mdw-regexps "and" "as" "assert" "break" "cdef" "class" "continue"
-               "ctypedef" "def" "del" "elif" "else" "except" "exec"
+               "ctypedef" "def" "del" "elif" "else" "enum" "except" "exec"
                "extern" "finally" "for" "from" "global" "if"
                "import" "in" "is" "lambda" "not" "or" "pass" "print"
-               "raise" "return" "struct" "try" "while" "with"
+               "property" "raise" "return" "struct" "try" "while" "with"
                "yield")))
 
+(define-derived-mode pyrex-mode python-mode "Pyrex"
+  "Major mode for editing Pyrex source code")
+(setq auto-mode-alist
+      (append '(("\\.pyx$" . pyrex-mode)
+               ("\\.pxd$" . pyrex-mode)
+               ("\\.pxi$" . pyrex-mode))
+             auto-mode-alist))
+
+;;;--------------------------------------------------------------------------
+;;; Lua programming style.
+
+(setq lua-indent-level 2)
+
+(defun mdw-fontify-lua ()
+
+  ;; Miscellaneous fiddling.
+  (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
+
+  ;; Now define fontification things.
+  (make-local-variable 'font-lock-keywords)
+  (let ((lua-keywords
+        (mdw-regexps "and" "break" "do" "else" "elseif" "end"
+                     "false" "for" "function" "goto" "if" "in" "local"
+                     "nil" "not" "or" "repeat" "return" "then" "true"
+                     "until" "while")))
+    (setq font-lock-keywords
+         (list
+
+          ;; Set up the keywords defined above.
+          (list (concat "\\_<\\(" lua-keywords "\\)\\_>")
+                '(0 font-lock-keyword-face))
+
+          ;; At least numbers are simpler than C.
+          (list (concat "\\_<\\(" "0[xX]"
+                                  "\\(" "[0-9a-fA-F]+"
+                                        "\\(\\.[0-9a-fA-F]*\\)?"
+                                  "\\|" "\\.[0-9a-fA-F]+"
+                                  "\\)"
+                                  "\\([pP][-+]?[0-9]+\\)?"
+                            "\\|" "\\(" "[0-9]+"
+                                        "\\(\\.[0-9]*\\)?"
+                                  "\\|" "\\.[0-9]+"
+                                  "\\)"
+                                  "\\([eE][-+]?[0-9]+\\)?"
+                            "\\)")
+                '(0 mdw-number-face))
+
+          ;; And anything else is punctuation.
+          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                '(0 mdw-punct-face))))))
+
 ;;;--------------------------------------------------------------------------
 ;;; Icon programming style.
 
@@ -2301,9 +2793,7 @@ strip numbers instead."
 
           ;; And anything else is punctuation.
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                '(0 mdw-punct-face))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Assembler mode.
@@ -2313,6 +2803,7 @@ strip numbers instead."
   (modify-syntax-entry ?. "w")
   (modify-syntax-entry ?\n ">")
   (setf fill-prefix nil)
+  (local-set-key ";" 'self-insert-command)
   (mdw-standard-fill-prefix "\\([ \t]*;+[ \t]*\\)"))
 
 (defun mdw-asm-set-comment ()
@@ -2337,8 +2828,7 @@ strip numbers instead."
                       "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
               '(0 mdw-number-face))
         (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-              '(0 mdw-punct-face))))
-  (mdw-post-config-mode-hack))
+              '(0 mdw-punct-face)))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Dylan programming configuration.
@@ -2404,9 +2894,7 @@ strip numbers instead."
                              "\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\|"
                              "\\_<[-+*/=<>:&|]+\\_>"
                              "\\)")
-                     '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                     '(0 mdw-punct-face))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Algol 68 configuration.
@@ -2448,9 +2936,7 @@ strip numbers instead."
                              "\\>")
                      '(0 mdw-number-face))
                (list "\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/"
-                     '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                     '(0 mdw-punct-face))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; REXX configuration.
@@ -2523,9 +3009,7 @@ strip numbers instead."
 
           ;; And everything else is punctuation.
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                '(0 mdw-punct-face))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Standard ML programming style.
@@ -2575,9 +3059,7 @@ strip numbers instead."
 
           ;; And anything else is punctuation.
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                '(0 mdw-punct-face))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Haskell configuration.
@@ -2655,9 +3137,7 @@ strip numbers instead."
                         "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)")
                 '(0 mdw-number-face))
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                '(0 mdw-punct-face))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Erlang configuration.
@@ -2690,9 +3170,7 @@ strip numbers instead."
           (list "\\<[0-9]+\\(\\|#[0-9a-zA-Z]+\\|[eE][+-]?[0-9]+\\)\\>"
                 '(0 mdw-number-face))
           (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
-
-  (mdw-post-config-mode-hack))
+                '(0 mdw-punct-face))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Texinfo configuration.
@@ -2726,9 +3204,7 @@ strip numbers instead."
 
         ;; Fontify TeX special characters as punctuation.
         (list "[{}]+"
-              '(0 mdw-punct-face))))
-
-  (mdw-post-config-mode-hack))
+              '(0 mdw-punct-face)))))
 
 ;;;--------------------------------------------------------------------------
 ;;; TeX and LaTeX configuration.
@@ -2742,6 +3218,10 @@ strip numbers instead."
   (modify-syntax-entry ?$ "." font-lock-syntax-table)
   (local-set-key [?$] 'self-insert-command)
 
+  ;; Make `tab' be useful, given that tab stops in TeX don't work well.
+  (local-set-key "\C-\M-i" 'indent-relative)
+  (setq indent-tabs-mode nil)
+
   ;; Set fill prefix.
   (mdw-standard-fill-prefix "\\([ \t]*%+[ \t]*\\)")
 
@@ -2794,9 +3274,26 @@ strip numbers instead."
 
         ;; Fontify TeX special characters as punctuation.
         (list "[$^_{}#&]"
-              '(0 mdw-punct-face))))
-
-  (mdw-post-config-mode-hack))
+              '(0 mdw-punct-face)))))
+
+(eval-after-load 'font-latex
+  '(defun font-latex-jit-lock-force-redisplay (buf start end)
+     "Compatibility for Emacsen not offering `jit-lock-force-redisplay'."
+     ;; The following block is an expansion of `jit-lock-force-redisplay'
+     ;; and involved macros taken from CVS Emacs on 2007-04-28.
+     (with-current-buffer buf
+       (let ((modified (buffer-modified-p)))
+        (unwind-protect
+            (let ((buffer-undo-list t)
+                  (inhibit-read-only t)
+                  (inhibit-point-motion-hooks t)
+                  (inhibit-modification-hooks t)
+                  deactivate-mark
+                  buffer-file-name
+                  buffer-file-truename)
+              (put-text-property start end 'fontified t))
+          (unless modified
+            (restore-buffer-modified-p nil)))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; SGML hacking.
@@ -3156,8 +3653,7 @@ that character only to be normal punctuation.")
                       "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
               '(0 mdw-number-face))
         (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-              '(0 mdw-punct-face))))
-  (mdw-post-config-mode-hack))
+              '(0 mdw-punct-face)))))
 
 ;; Lispy languages.
 
@@ -3214,9 +3710,7 @@ that character only to be normal punctuation.")
                            "\\)\\_>")
                    '(0 mdw-number-face))
              (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                   '(0 mdw-punct-face))))
-
-  (mdw-post-config-mode-hack))
+                   '(0 mdw-punct-face)))))
 
 (defun comint-send-and-indent ()
   (interactive)
@@ -3244,6 +3738,9 @@ that character only to be normal punctuation.")
    "\\([ \t]*\\([>#|:] ?\\)*[ \t]*\\)" 3)
   (auto-fill-mode 1))
 
+(eval-after-load "flyspell"
+  '(define-key flyspell-mode-map "\C-\M-i" nil))
+
 ;;;--------------------------------------------------------------------------
 ;;; Outline and hide/show modes.
 
@@ -3322,6 +3819,267 @@ This allows you to pass a list of arguments through `ansi-term'."
   (grep command-args))
 
 ;;;--------------------------------------------------------------------------
+;;; Magit configuration.
+
+(setq magit-diff-refine-hunk 'all
+      magit-view-git-manual-method 'man
+      magit-log-margin '(nil age magit-log-margin-width t 18)
+      magit-wip-after-save-local-mode-lighter ""
+      magit-wip-after-apply-mode-lighter ""
+      magit-wip-before-change-mode-lighter "")
+(eval-after-load "magit"
+  '(progn (global-magit-file-mode 1)
+         (magit-wip-after-save-mode 1)
+         (magit-wip-after-apply-mode 1)
+         (magit-wip-before-change-mode 1)
+         (add-to-list 'magit-no-confirm 'safe-with-wip)
+         (push '(:eval (if (or magit-wip-after-save-local-mode
+                               magit-wip-after-apply-mode
+                               magit-wip-before-change-mode)
+                           (format " wip:%s%s%s"
+                                   (if magit-wip-after-apply-mode "A" "")
+                                   (if magit-wip-before-change-mode "C" "")
+                                   (if magit-wip-after-save-local-mode "S" ""))))
+               minor-mode-alist)
+         (dolist (popup '(magit-diff-popup
+                          magit-diff-refresh-popup
+                          magit-diff-mode-refresh-popup
+                          magit-revision-mode-refresh-popup))
+           (magit-define-popup-switch popup ?R "Reverse diff" "-R"))))
+
+(setq magit-repolist-columns
+      '(("Name" 16 magit-repolist-column-ident nil)
+       ("Version" 18 magit-repolist-column-version nil)
+       ("St" 2 magit-repolist-column-dirty nil)
+       ("L<U" 3 mdw-repolist-column-unpulled-from-upstream nil)
+       ("L>U" 3 mdw-repolist-column-unpushed-to-upstream nil)
+       ("Path" 32 magit-repolist-column-path nil)))
+
+(setq magit-repository-directories '(("~/etc/profile" . 0)
+                                    ("~/src/" . 1)))
+
+(defadvice magit-list-repos (around mdw-dirname () activate compile)
+  "Make sure the returned names are directory names.
+Otherwise child processes get started in the wrong directory and
+there is sadness."
+  (setq ad-return-value (mapcar #'file-name-as-directory ad-do-it)))
+
+(defun mdw-repolist-column-unpulled-from-upstream (_id)
+  "Insert number of upstream commits not in the current branch."
+  (let ((upstream (magit-get-upstream-branch (magit-get-current-branch) t)))
+    (and upstream
+        (let ((n (cadr (magit-rev-diff-count "HEAD" upstream))))
+          (propertize (number-to-string n) 'face
+                      (if (> n 0) 'bold 'shadow))))))
+
+(defun mdw-repolist-column-unpushed-to-upstream (_id)
+  "Insert number of commits in the current branch but not its upstream."
+  (let ((upstream (magit-get-upstream-branch (magit-get-current-branch) t)))
+    (and upstream
+        (let ((n (car (magit-rev-diff-count "HEAD" upstream))))
+          (propertize (number-to-string n) 'face
+                      (if (> n 0) 'bold 'shadow))))))
+
+;;;--------------------------------------------------------------------------
+;;; MPC configuration.
+
+(eval-when-compile (trap (require 'mpc)))
+
+(setq mpc-browser-tags '(Artist|Composer|Performer Album|Playlist))
+
+(defun mdw-mpc-now-playing ()
+  (interactive)
+  (require 'mpc)
+  (save-excursion
+    (set-buffer (mpc-proc-cmd (mpc-proc-cmd-list '("status" "currentsong"))))
+    (mpc--status-callback))
+  (let ((state (cdr (assq 'state mpc-status))))
+    (cond ((member state '("stop"))
+          (message "mpd stopped."))
+         ((member state '("play" "pause"))
+          (let* ((artist (cdr (assq 'Artist mpc-status)))
+                 (album (cdr (assq 'Album mpc-status)))
+                 (title (cdr (assq 'Title mpc-status)))
+                 (file (cdr (assq 'file mpc-status)))
+                 (duration-string (cdr (assq 'Time mpc-status)))
+                 (time-string (cdr (assq 'time mpc-status)))
+                 (time (and time-string
+                            (string-to-number
+                             (if (string-match ":" time-string)
+                                 (substring time-string
+                                            0 (match-beginning 0))
+                               (time-string)))))
+                 (duration (and duration-string
+                                (string-to-number duration-string)))
+                 (pos (and time duration
+                           (format " [%d:%02d/%d:%02d]"
+                                   (/ time 60) (mod time 60)
+                                   (/ duration 60) (mod duration 60))))
+                 (fmt (cond ((and artist title)
+                             (format "`%s' by %s%s" title artist
+                                     (if album (format ", from `%s'" album)
+                                       "")))
+                            (file
+                             (format "`%s' (no tags)" file))
+                            (t
+                             "(no idea what's playing!)"))))
+            (if (string= state "play")
+                (message "mpd playing %s%s" fmt (or pos ""))
+              (message "mpd paused in %s%s" fmt (or pos "")))))
+         (t
+          (message "mpd in unknown state `%s'" state)))))
+
+(defmacro mdw-define-mpc-wrapper (func bvl interactive &rest body)
+  `(defun ,func ,bvl
+     (interactive ,@interactive)
+     (require 'mpc)
+     ,@body
+     (mdw-mpc-now-playing)))
+
+(mdw-define-mpc-wrapper mdw-mpc-play-or-pause () nil
+  (if (member (cdr (assq 'state (mpc-cmd-status))) '("play"))
+      (mpc-pause)
+    (mpc-play)))
+
+(mdw-define-mpc-wrapper mdw-mpc-next () nil (mpc-next))
+(mdw-define-mpc-wrapper mdw-mpc-prev () nil (mpc-prev))
+(mdw-define-mpc-wrapper mdw-mpc-stop () nil (mpc-stop))
+
+(defun mdw-mpc-louder (step)
+  (interactive (list (if current-prefix-arg
+                        (prefix-numeric-value current-prefix-arg)
+                      +10)))
+  (mpc-proc-cmd (format "volume %+d" step)))
+
+(defun mdw-mpc-quieter (step)
+  (interactive (list (if current-prefix-arg
+                        (prefix-numeric-value current-prefix-arg)
+                      +10)))
+  (mpc-proc-cmd (format "volume %+d" (- step))))
+
+(defun mdw-mpc-hack-lines (arg interactivep func)
+  (if (and interactivep (use-region-p))
+      (let ((from (region-beginning)) (to (region-end)))
+       (goto-char from)
+       (beginning-of-line)
+       (funcall func)
+       (forward-line)
+       (while (< (point) to)
+         (funcall func)
+         (forward-line)))
+    (let ((n (prefix-numeric-value arg)))
+      (cond ((minusp n)
+            (unless (bolp)
+              (beginning-of-line)
+              (funcall func)
+              (incf n))
+            (while (minusp n)
+              (forward-line -1)
+              (funcall func)
+              (incf n)))
+           (t
+            (beginning-of-line)
+            (while (plusp n)
+              (funcall func)
+              (forward-line)
+              (decf n)))))))
+
+(defun mdw-mpc-select-one ()
+  (when (and (get-char-property (point) 'mpc-file)
+            (not (get-char-property (point) 'mpc-select)))
+    (mpc-select-toggle)))
+
+(defun mdw-mpc-unselect-one ()
+  (when (get-char-property (point) 'mpc-select)
+    (mpc-select-toggle)))
+
+(defun mdw-mpc-select (&optional arg interactivep)
+  (interactive (list current-prefix-arg t))
+  (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-select-one))
+
+(defun mdw-mpc-unselect (&optional arg interactivep)
+  (interactive (list current-prefix-arg t))
+  (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-unselect-one))
+
+(defun mdw-mpc-unselect-backwards (arg)
+  (interactive "p")
+  (mdw-mpc-hack-lines (- arg) t 'mdw-mpc-unselect-one))
+
+(defun mdw-mpc-unselect-all ()
+  (interactive)
+  (setq mpc-select nil)
+  (mpc-selection-refresh))
+
+(defun mdw-mpc-next-line (arg)
+  (interactive "p")
+  (beginning-of-line)
+  (forward-line arg))
+
+(defun mdw-mpc-previous-line (arg)
+  (interactive "p")
+  (beginning-of-line)
+  (forward-line (- arg)))
+
+(defun mdw-mpc-playlist-add (&optional arg interactivep)
+  (interactive (list current-prefix-arg t))
+  (let ((mpc-select mpc-select))
+    (when (or arg (and interactivep (use-region-p)))
+      (setq mpc-select nil)
+      (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-select-one))
+    (setq mpc-select (reverse mpc-select))
+    (mpc-playlist-add)))
+
+(defun mdw-mpc-playlist-delete (&optional arg interactivep)
+  (interactive (list current-prefix-arg t))
+  (setq mpc-select (nreverse mpc-select))
+  (mpc-select-save
+    (when (or arg (and interactivep (use-region-p)))
+      (setq mpc-select nil)
+      (mpc-selection-refresh)
+      (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-select-one))
+      (mpc-playlist-delete)))
+
+(defun mdw-mpc-hack-tagbrowsers ()
+  (setq-local mode-line-format
+             '("%e"
+               mode-line-frame-identification
+               mode-line-buffer-identification)))
+(add-hook 'mpc-tagbrowser-mode-hook 'mdw-mpc-hack-tagbrowsers)
+
+(defun mdw-mpc-hack-songs ()
+  (setq-local header-line-format
+             ;; '("MPC " mpc-volume " " mpc-current-song)
+             (list (propertize " " 'display '(space :align-to 0))
+                   ;; 'mpc-songs-format-description
+                   '(:eval
+                     (let ((deactivate-mark) (hscroll (window-hscroll)))
+                       (with-temp-buffer
+                         (mpc-format mpc-songs-format 'self hscroll)
+                         ;; That would be simpler than the hscroll handling in
+                         ;; mpc-format, but currently move-to-column does not
+                         ;; recognize :space display properties.
+                         ;; (move-to-column hscroll)
+                         ;; (delete-region (point-min) (point))
+                         (buffer-string)))))))
+(add-hook 'mpc-songs-mode-hook 'mdw-mpc-hack-songs)
+
+(eval-after-load "mpc"
+  '(progn
+     (define-key mpc-mode-map "m" 'mdw-mpc-select)
+     (define-key mpc-mode-map "u" 'mdw-mpc-unselect)
+     (define-key mpc-mode-map "\177" 'mdw-mpc-unselect-backwards)
+     (define-key mpc-mode-map "\e\177" 'mdw-mpc-unselect-all)
+     (define-key mpc-mode-map "n" 'mdw-mpc-next-line)
+     (define-key mpc-mode-map "p" 'mdw-mpc-previous-line)
+     (define-key mpc-mode-map "/" 'mpc-songs-search)
+     (setq mpc-songs-mode-map (make-sparse-keymap))
+     (set-keymap-parent mpc-songs-mode-map mpc-mode-map)
+     (define-key mpc-songs-mode-map "l" 'mpc-playlist)
+     (define-key mpc-songs-mode-map "+" 'mdw-mpc-playlist-add)
+     (define-key mpc-songs-mode-map "-" 'mdw-mpc-playlist-delete)
+     (define-key mpc-songs-mode-map "\r" 'mpc-songs-jump-to)))
+
+;;;--------------------------------------------------------------------------
 ;;; Inferior Emacs Lisp.
 
 (setq comint-prompt-read-only t)