chiark / gitweb /
dot/emacs, el/dot-emacs.el: Switch to using the `cl-lib' package.
[profile] / el / dot-emacs.el
index b5f45b66e6fa9d2e4507d1e9b7f90baf17ee3461..a574f713feb0aaac3dbad2877684574292b886c8 100644 (file)
 ;;;--------------------------------------------------------------------------
 ;;; Check command-line.
 
+(defgroup mdw nil
+  "Customization for mdw's Emacs configuration."
+  :prefix "mdw-")
+
 (defun mdw-check-command-line-switch (switch)
   (let ((probe nil) (next command-line-args) (found nil))
     (while next
@@ -51,15 +55,14 @@ (setq mdw-splashy-startup
 ;;; Some general utilities.
 
 (eval-when-compile
-  (unless (fboundp 'make-regexp)
-    (load "make-regexp"))
-  (require 'cl))
+  (unless (fboundp 'make-regexp) (load "make-regexp"))
+  (require 'cl-lib))
 
 (defmacro mdw-regexps (&rest list)
   "Turn a LIST of strings into a single regular expression at compile-time."
   (declare (indent nil)
           (debug 0))
-  `',(make-regexp list))
+  `',(make-regexp (sort (cl-copy-list list) #'string<)))
 
 (defun mdw-wrong ()
   "This is not the key sequence you're looking for."
@@ -72,20 +75,28 @@ (defun mdw-emacs-version-p (major &optional minor)
       (and (= emacs-major-version major)
           (>= emacs-minor-version (or minor 0)))))
 
+(defun mdw-submode-p (mode parent)
+  "Return non-nil if MODE is indirectly derived from PARENT."
+  (let ((answer nil))
+    (while (cond ((eq mode parent) (setq answer t) nil)
+                (t (setq mode (get mode 'derived-mode-parent)))))
+    answer))
+
 ;; Some error trapping.
 ;;
 ;; If individual bits of this file go tits-up, we don't particularly want
 ;; the whole lot to stop right there and then, because it's bloody annoying.
 
-(defmacro trap (&rest forms)
-  "Execute FORMS without allowing errors to propagate outside."
-  (declare (indent 0)
-          (debug t))
-  `(condition-case err
-       ,(if (cdr forms) (cons 'progn forms) (car forms))
-     (error (message "Error (trapped): %s in %s"
-                    (error-message-string err)
-                    ',forms))))
+(eval-and-compile
+  (defmacro trap (&rest forms)
+    "Execute FORMS without allowing errors to propagate outside."
+    (declare (indent 0)
+            (debug t))
+    `(condition-case err
+        ,(if (cdr forms) (cons 'progn forms) (car forms))
+       (error (message "Error (trapped): %s in %s"
+                      (error-message-string err)
+                      ',forms)))))
 
 ;; Configuration reading.
 
@@ -94,31 +105,33 @@ (defun mdw-config (sym)
   "Read the configuration variable named SYM."
   (unless mdw-config
     (setq mdw-config
-         (flet ((replace (what with)
-                  (goto-char (point-min))
-                  (while (re-search-forward what nil t)
-                    (replace-match with t))))
-           (with-temp-buffer
-             (insert-file-contents "~/.mdw.conf")
-             (replace  "^[ \t]*\\(#.*\\|\\)\n" "")
-             (replace (concat "^[ \t]*"
-                              "\\([-a-zA-Z0-9_.]*\\)"
-                              "[ \t]*=[ \t]*"
-                              "\\(.*[^ \t\n]\\|\\)"
-                              "[ \t]**\\(\n\\|$\\)")
-                      "(\\1 . \"\\2\")\n")
-             (car (read-from-string
-                   (concat "(" (buffer-string) ")")))))))
+           (cl-flet ((replace (what with)
+                       (goto-char (point-min))
+                       (while (re-search-forward what nil t)
+                         (replace-match with t))))
+             (with-temp-buffer
+               (insert-file-contents "~/.mdw.conf")
+               (replace  "^[ \t]*\\(#.*\\)?\n" "")
+               (replace (concat "^[ \t]*"
+                                "\\([-a-zA-Z0-9_.]*\\)"
+                                "[ \t]*=[ \t]*"
+                                "\\(.*[^ \t\n]\\)?"
+                                "[ \t]**\\(\n\\|$\\)")
+                        "(\\1 . \"\\2\")\n")
+               (car (read-from-string
+                     (concat "(" (buffer-string) ")")))))))
   (cdr (assq sym mdw-config)))
 
 ;; Width configuration.
 
-(defvar mdw-column-width
+(defcustom 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)
+  "Width of Emacs columns."
+  :type 'integer)
+(defcustom mdw-text-width mdw-column-width
+  "Expected width of text within columns."
+  :type 'integer
+  :safe 'integerp)
 
 ;; Local variables hacking.
 
@@ -202,8 +215,9 @@ (defun mdw-horizontal-window-overhead ()
     (let ((tot 0))
       (dolist (what '(scroll-bar fringe))
        (dolist (side '(left right))
-         (incf tot (funcall (intern (concat (symbol-name what) "-columns"))
-                            side))))
+         (cl-incf tot
+                  (funcall (intern (concat (symbol-name what) "-columns"))
+                           side))))
       tot)))
 
 (defun mdw-split-window-horizontally (&optional width)
@@ -240,29 +254,124 @@ (defun mdw-divvy-window (&optional width)
       (other-window 1))
     (select-window win)))
 
+(defun mdw-frame-width-quantized-p (frame-width column-width)
+  "Return whether the FRAME-WIDTH was chosen specifically for COLUMN-WIDTH."
+  (let ((sb-width (mdw-horizontal-window-overhead)))
+    (zerop (mod (+ frame-width sb-width)
+               (+ column-width sb-width)))))
+
+(defun mdw-frame-width-for-columns (columns width)
+  "Return the preferred width for a frame with so many COLUMNS of WIDTH."
+  (let ((sb-width (mdw-horizontal-window-overhead)))
+    (- (* columns (+ width sb-width))
+       sb-width)))
+
 (defun mdw-set-frame-width (columns &optional width)
+  "Set the current frame to be the correct width for COLUMNS columns.
+
+If WIDTH is non-nil, then it provides the width for the new columns.  (This
+can be set interactively with a prefix argument.)"
   (interactive "nColumns: 
 P")
   (setq width (if width (prefix-numeric-value width)
                (mdw-preferred-column-width)))
-  (let ((sb-width (mdw-horizontal-window-overhead)))
-    (set-frame-width (selected-frame)
-                    (- (* columns (+ width sb-width))
-                       sb-width))
-    (mdw-divvy-window width)))
+  (set-frame-width (selected-frame)
+                  (mdw-frame-width-for-columns columns width))
+  (mdw-divvy-window width))
 
-(defvar mdw-frame-width-fudge
+(defcustom mdw-frame-width-fudge
   (cond ((<= emacs-major-version 20) 1)
        ((= emacs-major-version 26) 3)
        (t 0))
   "The number of extra columns to add to the desired frame width.
 
-This is sadly necessary because Emacs 26 is broken in this regard.")
+This is sadly necessary because Emacs 26 is broken in this regard."
+  :type 'integer)
+
+(defcustom mdw-frame-colour-alist
+  '((black . ("#000000" . "#ffffff"))
+    (red . ("#2a0000" . "#ffffff"))
+    (green . ("#002a00" . "#ffffff"))
+    (blue . ("#00002a" . "#ffffff")))
+  "Alist mapping symbol names to (FOREGROUND . BACKGROUND) colour pairs."
+  :type '(alist :key-type symbol :value-type (cons color color)))
+
+(defun mdw-set-frame-colour (colour &optional frame)
+  (interactive "xColour name or (FOREGROUND . BACKGROUND) pair: 
+")
+  (when (and colour (symbolp colour))
+    (let ((entry (assq colour mdw-frame-colour-alist)))
+      (unless entry (error "Unknown colour `%s'" colour))
+      (setf colour (cdr entry))))
+  (set-frame-parameter frame 'background-color (car colour))
+  (set-frame-parameter frame 'foreground-color (cdr colour)))
+
+;; Window configuration switching.
+
+(defvar mdw-current-window-configuration nil
+  "The current window configuration register name, or `nil'.")
+
+(defun mdw-switch-window-configuration (register &optional no-save)
+  "Switch make REGISTER be the new current window configuration.
+If a current window configuration register is established, and
+NO-SAVE is nil, then save the current window configuration to
+that register first.
+
+Signal an error if the new register contains something other than
+a window configuration.  If the register is unset then save the
+current window configuration to it immediately.
+
+With one or three C-u, or an odd numeric prefix argument, set
+NO-SAVE, so the previous window configuration register is left
+unchanged.
+
+With two or three C-u, or a prefix argument which is an odd
+multiple of 2, just clear the record of the current window
+configuration register, so that the next switch doesn't save the
+prevailing configuration."
+  (interactive
+   (let ((arg current-prefix-arg))
+     (list (if (or (and (consp arg) (= (car arg) 16) (= (car arg) 64))
+                  (and (integerp arg) (not (zerop (logand arg 2)))))
+              nil
+            (register-read-with-preview "Switch to window configuration: "))
+          (or (and (consp arg) (= (car arg) 4) (= (car arg) 64))
+              (and (integerp arg) (not (zerop (logand arg 1))))))))
+
+  (let ((previous mdw-current-window-configuration)
+       (current-windows (list (current-window-configuration)
+                              (point-marker)))
+       (register-value (and register (get-register register))))
+    (when (and mdw-current-window-configuration (not no-save))
+      (set-register mdw-current-window-configuration current-windows))
+    (cond ((null register)
+          (setq mdw-current-window-configuration nil)
+          (if previous
+              (message "Left window configuration `%c'." previous)
+            (message "Nothing to do!")))
+         ((not (or (null register-value)
+                   (and (consp register-value)
+                        (window-configuration-p (car register-value))
+                        (integer-or-marker-p (cadr register-value))
+                        (null (cl-caddr register-value)))))
+          (error "Register `%c' is not a window configuration" register))
+         (t
+          (cond ((null register-value)
+                 (set-register register current-windows)
+                 (message "Started new window configuration `%c'."
+                          register))
+                (t
+                 (set-window-configuration (car register-value))
+                 (goto-char (cadr register-value))
+                 (message "Switched to window configuration `%c'."
+                          register)))
+          (setq mdw-current-window-configuration register)))))
 
 ;; Don't raise windows unless I say so.
 
-(defvar mdw-inhibit-raise-frame nil
-  "*Whether `raise-frame' should do nothing when the frame is mapped.")
+(defcustom mdw-inhibit-raise-frame nil
+  "Whether `raise-frame' should do nothing when the frame is mapped."
+  :type 'boolean)
 
 (defadvice raise-frame
     (around mdw-inhibit (&optional frame) activate compile)
@@ -338,6 +447,9 @@ (defadvice exchange-point-and-mark
 
 ;; Functions for sexp diary entries.
 
+(defvar mdw-diary-for-org-mode-p nil
+  "Display diary along with the agenda?")
+
 (defun mdw-not-org-mode (form)
   "As FORM, but not in Org mode agenda."
   (and (not mdw-diary-for-org-mode-p)
@@ -385,8 +497,8 @@ (defun mdw-diary-discordian-date ()
     (if (eq (cdr ddate) 'st-tibs-day)
        (format "St Tib's Day %s" tail)
       (let ((season (cadr ddate))
-           (daynum (caddr ddate))
-           (dayname (cadddr ddate)))
+           (daynum (cl-caddr ddate))
+           (dayname (cl-cadddr ddate)))
       (format "%s, the %d%s day of %s %s"
              dayname
              daynum
@@ -417,13 +529,13 @@ (defun mdw-todo (&optional when)
                                (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))
 
-(defvar diary-time-regexp nil)
+(defcustom diary-time-regexp nil
+  "Regexp matching times in the diary buffer."
+  :type 'regexp)
 
 (defadvice diary-add-to-list (before mdw-trim-leading-space compile activate)
   "Trim leading space from the diary entry string."
@@ -463,11 +575,11 @@ (defadvice org-bbdb-anniversaries (after mdw-fixup-list compile activate)
          (insert e)
          (setq anyp t)))
       (setq ad-return-value
-           (and anyp (buffer-string))))))
+             (and anyp (buffer-string))))))
 
 ;; Fighting with Org-mode's evil key maps.
 
-(defvar mdw-evil-keymap-keys
+(defcustom mdw-evil-keymap-keys
   '(([S-up] . [?\C-c up])
     ([S-down] . [?\C-c down])
     ([S-left] . [?\C-c left])
@@ -478,7 +590,9 @@ (defvar mdw-evil-keymap-keys
     (([M-right] [?\e right]) . [C-right]))
   "Defines evil keybindings to clobber in `mdw-clobber-evil-keymap'.
 The value is an alist mapping evil keys (as a list, or singleton)
-to good keys (in the same form).")
+to good keys (in the same form)."
+  :type '(alist :key-type (choice key-sequence (repeat key-sequence))
+               :value-type key-sequence))
 
 (defun mdw-clobber-evil-keymap (keymap)
   "Replace evil key bindings in the KEYMAP.
@@ -502,7 +616,7 @@       (define-key keymap key nil))
        (dolist (key replacements)
          (define-key keymap key binding))))))
 
-(defvar mdw-org-latex-defs
+(defcustom mdw-org-latex-defs
   '(("strayman"
      "\\documentclass{strayman}
 \\usepackage[utf8]{inputenc}
@@ -512,14 +626,32 @@ (defvar mdw-org-latex-defs
      ("\\subsection{%s}" . "\\subsection*{%s}")
      ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
      ("\\paragraph{%s}" . "\\paragraph*{%s}")
-     ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))))
+     ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
+  "Additional LaTeX class definitions."
+  :type '(alist :key-type string
+               :value-type (list string
+                                 (alist :inline t
+                                        :key-type string
+                                        :value-type string))))
+
+(setq org-emphasis-regexp-components
+       '("- \t('\"{}"                  ; prematch
+         "- \t.,:!?;'\")}\\["          ; postmatch
+         " \t\r\n"                     ; /forbidden/ as border
+         "."                           ; body regexp
+         1))                           ; maximum newlines
+
+(setq org-entities-user
+       ;; NAME LATEX MATHP HTML ASCII LATIN1 UTF8
+       '(("relax" "" nil "" "" "" "")))
 
 (eval-after-load "org-latex"
   '(setq org-export-latex-classes
-        (append mdw-org-latex-defs org-export-latex-classes)))
+          (append mdw-org-latex-defs org-export-latex-classes)))
 
 (eval-after-load "ox-latex"
   '(setq org-latex-classes (append mdw-org-latex-defs org-latex-classes)
+        org-latex-caption-above nil
         org-latex-default-packages-alist '(("AUTO" "inputenc" t)
                                            ("T1" "fontenc" t)
                                            ("" "fixltx2e" nil)
@@ -536,11 +668,10 @@ (eval-after-load "ox-latex"
                                            ("" "hyperref" nil)
                                            "\\tolerance=1000")))
 
-
 (setq org-export-docbook-xslt-proc-command "xsltproc --output %o %s %i"
       org-export-docbook-xsl-fo-proc-command "fop %i.safe %o"
       org-export-docbook-xslt-stylesheet
-      "/usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl")
+       "/usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl")
 
 ;; Glasses.
 
@@ -550,6 +681,52 @@ (setq glasses-separator "-"
 
 ;; Some hacks to do with window placement.
 
+(defvar mdw-designated-window nil
+  "The window chosen by `mdw-designate-window', or nil.")
+
+(defun mdw-designated-window-display-buffer-function (buffer not-this-window)
+  "Display buffer function to use the designated window."
+  (unless mdw-designated-window (error "No designated window!"))
+  (prog1 mdw-designated-window
+    (with-selected-window mdw-designated-window (switch-to-buffer buffer))
+    (setq mdw-designated-window nil
+         display-buffer-function nil)))
+
+(defun mdw-display-buffer-in-designated-window (buffer alist)
+  "Display function to use the designated window."
+  (prog1 mdw-designated-window
+    (when mdw-designated-window
+      (with-selected-window mdw-designated-window
+       (switch-to-buffer buffer nil t)))
+    (setq mdw-designated-window nil)))
+
+(defun mdw-designate-window (cancel)
+  "Use the selected window for the next pop-up buffer.
+With a prefix argument, clear the designated window."
+  (interactive "P")
+  (let ((window (selected-window)))
+    (cond (cancel
+          (setq mdw-designated-window nil)
+          (unless (mdw-emacs-version-p 24)
+            (setq display-buffer-function nil))
+          (message "Window designation cleared."))
+         ((window-dedicated-p window)
+          (error "Window is dedicated to its buffer."))
+         (t
+          (setq mdw-designated-window window)
+          (unless (mdw-emacs-version-p 24)
+            (setq display-buffer-function
+                    #'mdw-designated-window-display-buffer-function))
+          (message "Window designated.")))))
+
+(when (mdw-emacs-version-p 24)
+  (setq display-buffer-base-action
+         (let* ((action display-buffer-base-action)
+                (funcs (car action))
+                (alist (cdr action)))
+           (cons (cons 'mdw-display-buffer-in-designated-window funcs)
+                 alist))))
+
 (defun mdw-clobber-other-windows-showing-buffer (buffer-or-name)
   "Arrange that no windows on other frames are showing BUFFER-OR-NAME."
   (interactive "bBuffer: ")
@@ -568,9 +745,9 @@ (defvar mdw-inhibit-walk-windows nil
 buffers in random frames.")
 
 (setq display-buffer--other-frame-action
-      '((display-buffer-reuse-window display-buffer-pop-up-frame)
-       (reusable-frames . nil)
-       (inhibit-same-window . t)))
+       '((display-buffer-reuse-window display-buffer-pop-up-frame)
+         (reusable-frames . nil)
+         (inhibit-same-window . t)))
 
 (defadvice walk-windows (around mdw-inhibit activate)
   "If `mdw-inhibit-walk-windows' is non-nil, then do nothing."
@@ -588,15 +765,102 @@ (defadvice display-buffer (before mdw-inhibit-other-frames activate)
 Pretend they don't exist.  They might be on other display devices."
   (ad-set-arg 2 nil))
 
+(setq even-window-sizes nil
+      even-window-heights nil)
+
+(setq display-buffer-reuse-frames nil)
+
+(defun mdw-last-window-in-frame-p (window)
+  "Return whether WINDOW is the last in its frame."
+  (catch 'done
+    (while window
+      (let ((next (window-next-sibling window)))
+       (while (and next (window-minibuffer-p next))
+         (setq next (window-next-sibling next)))
+       (if next (throw 'done nil)))
+      (setq window (window-parent window)))
+    t))
+
+(defun mdw-display-buffer-in-tolerable-window (buffer alist)
+  "Try finding a tolerable window in which to display BUFFER.
+Begone, foul DWIMmerlaik!
+
+This is all totally subject to arbitrary change in the future, but the
+emphasis is on predictability rather than crazy DWIMmery."
+  (let* ((selected (selected-window)) chosen
+        (full-height-p (window-full-height-p selected))
+        (full-width-p (window-full-width-p selected)))
+    (cond
+
+     ((and full-height-p full-width-p)
+      ;; We're basically the only window in the frame.  If we want to get
+      ;; anywhere, we'll have to split the window.
+
+      (let ((width (window-width selected))
+           (preferred-width (mdw-preferred-column-width)))
+       (if (and (>= width (mdw-frame-width-for-columns 2 preferred-width))
+                (mdw-frame-width-quantized-p width preferred-width))
+           (setq chosen (split-window-right preferred-width))
+         (setq chosen (split-window-below)))
+       (display-buffer-record-window 'window chosen buffer)))
+
+     ((mdw-last-window-in-frame-p selected)
+      ;; This is the last window in the frame.  I don't think I want to
+      ;; clobber the first window, so rebound and clobber the previous one
+      ;; instead.  (This obviously has the same effect if there are only two
+      ;; windows, but seems more useful if there are three.)
+
+      (setq chosen (previous-window selected 'never nil))
+      (display-buffer-record-window 'reuse chosen buffer))
+
+     (t
+      ;; There's another window in front of us.  Let's use that one.
+      (setq chosen (next-window selected 'never nil)))
+      (display-buffer-record-window 'reuse chosen buffer))
+
+    (if (eq chosen selected)
+       (error "Failed to select a different window!"))
+
+    (when chosen
+      (with-selected-window chosen (switch-to-buffer buffer)))
+    chosen))
+
+;; Hack the display actions so that they do something sensible.
+(setq display-buffer-fallback-action
+       '((display-buffer--maybe-same-window
+          display-buffer-reuse-window
+          display-buffer-pop-up-window
+          mdw-display-buffer-in-tolerable-window)))
+
 ;; Rename buffers along with files.
 
+(defvar mdw-inhibit-rename-buffer nil
+  "If non-nil, `rename-file' won't rename the buffer visiting the file.")
+
+(defmacro mdw-advise-to-inhibit-rename-buffer (function)
+  "Advise FUNCTION to set `mdw-inhibit-rename-buffer' while it runs.
+
+This will prevent `rename-file' from renaming the buffer."
+  `(defadvice ,function (around mdw-inhibit-rename-buffer compile activate)
+     "Don't rename the buffer when renaming the underlying file."
+     (let ((mdw-inhibit-rename-buffer t))
+       ad-do-it)))
+(mdw-advise-to-inhibit-rename-buffer recode-file-name)
+(mdw-advise-to-inhibit-rename-buffer set-visited-file-name)
+(mdw-advise-to-inhibit-rename-buffer backup-buffer)
+
 (defadvice rename-file (after mdw-rename-buffers (from to &optional forcep)
                        compile activate)
-  "If a buffer is visiting the file, rename it to match the new name."
-  (let ((buffer (get-file-buffer from)))
-    (when buffer
-      (with-current-buffer buffer
-       (set-visited-file-name to nil t)))))
+  "If a buffer is visiting the file, rename it to match the new name.
+
+Don't do this if `mdw-inhibit-rename-buffer' is non-nil."
+  (unless mdw-inhibit-rename-buffer
+    (let ((buffer (get-file-buffer from)))
+      (when buffer
+       (let ((to (if (not (string= (file-name-nondirectory to) "")) to
+                   (concat to (file-name-nondirectory from)))))
+         (with-current-buffer buffer
+           (set-visited-file-name to nil t)))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Improved compilation machinery.
@@ -604,11 +868,11 @@ (defadvice rename-file (after mdw-rename-buffers (from to &optional forcep)
 ;; Uprated version of M-x compile.
 
 (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))))
+       (let ((ncpu (with-temp-buffer
+                     (insert-file-contents "/proc/cpuinfo")
+                     (buffer-string)
+                     (count-matches "^processor\\s-*:"))))
+         (format "nice make -j%d -k" (* 2 ncpu))))
 
 (defun mdw-compilation-buffer-name (mode)
   (concat "*" (downcase mode) ": "
@@ -646,14 +910,14 @@ (defun mdw-compile (command &optional directory comint)
   (interactive
    (let* ((prefix (prefix-numeric-value current-prefix-arg))
          (command (eval compile-command))
-         (dir (and (plusp (logand prefix #x54))
+         (dir (and (cl-plusp (logand prefix #x54))
                    (read-directory-name "Compile in directory: "))))
      (list (if (or compilation-read-command
-                  (plusp (logand prefix #x42)))
+                  (cl-plusp (logand prefix #x42)))
               (compilation-read-command command)
             command)
           dir
-          (plusp (logand prefix #x58)))))
+          (cl-plusp (logand prefix #x58)))))
   (let ((default-directory (or directory default-directory)))
     (compile command comint)))
 
@@ -663,13 +927,13 @@ (defun mdw-find-build-dir (build-file)
   (catch 'found
     (let* ((src-dir (file-name-as-directory (expand-file-name ".")))
           (dir src-dir))
-      (loop
+      (cl-loop
        (when (file-exists-p (concat dir build-file))
          (throw 'found dir))
        (let ((sub (expand-file-name (file-relative-name src-dir dir)
                                     (concat dir "build/"))))
          (catch 'give-up
-           (loop
+           (cl-loop
              (when (file-exists-p (concat sub build-file))
                (throw 'found sub))
              (when (string= sub dir) (throw 'give-up nil))
@@ -689,22 +953,22 @@ (defun mdw-flymake-make-init ()
            #'flymake-get-make-cmdline)))))
 
 (setq flymake-allowed-file-name-masks
-      '(("\\.\\(?:[cC]\\|cc\\|cpp\\|cxx\\|c\\+\\+\\)\\'"
-        mdw-flymake-make-init)
-       ("\\.\\(?:[hH]\\|hh\\|hpp\\|hxx\\|h\\+\\+\\)\\'"
-        mdw-flymake-master-make-init)
-       ("\\.p[lm]" flymake-perl-init)))
+       '(("\\.\\(?:[cC]\\|cc\\|cpp\\|cxx\\|c\\+\\+\\)\\'"
+          mdw-flymake-make-init)
+         ("\\.\\(?:[hH]\\|hh\\|hpp\\|hxx\\|h\\+\\+\\)\\'"
+          mdw-flymake-master-make-init)
+         ("\\.p[lm]" flymake-perl-init)))
 
 (setq flymake-mode-map
-      (let ((map (if (boundp 'flymake-mode-map)
-                    flymake-mode-map
-                  (make-sparse-keymap))))
-       (define-key map [?\C-c ?\C-f ?\C-p] 'flymake-goto-prev-error)
-       (define-key map [?\C-c ?\C-f ?\C-n] 'flymake-goto-next-error)
-       (define-key map [?\C-c ?\C-f ?\C-c] 'flymake-compile)
-       (define-key map [?\C-c ?\C-f ?\C-k] 'flymake-stop-all-syntax-checks)
-       (define-key map [?\C-c ?\C-f ?\C-e] 'flymake-popup-current-error-menu)
-       map))
+       (let ((map (if (boundp 'flymake-mode-map)
+                      flymake-mode-map
+                    (make-sparse-keymap))))
+         (define-key map [?\C-c ?\C-f ?\C-p] 'flymake-goto-prev-error)
+         (define-key map [?\C-c ?\C-f ?\C-n] 'flymake-goto-next-error)
+         (define-key map [?\C-c ?\C-f ?\C-c] 'flymake-compile)
+         (define-key map [?\C-c ?\C-f ?\C-k] 'flymake-stop-all-syntax-checks)
+         (define-key map [?\C-c ?\C-f ?\C-e] 'flymake-popup-current-error-menu)
+         map))
 
 ;;;--------------------------------------------------------------------------
 ;;; Mail and news hacking.
@@ -724,8 +988,8 @@ (add-hook 'mdwail-mode-hook
            (make-local-variable 'paragraph-separate)
            (make-local-variable 'paragraph-start)
            (setq paragraph-start
-                 (concat "[ \t]*[-_][-_][-_]+$\\|^-- \\|-----\\|"
-                         paragraph-start))
+                   (concat "[ \t]*[-_][-_][-_]+$\\|^-- \\|-----\\|"
+                           paragraph-start))
            (setq paragraph-separate
                  (concat "[ \t]*[-_][-_][-_]+$\\|^-- \\|-----\\|"
                          paragraph-separate))))
@@ -781,10 +1045,13 @@ (let ((path exec-path))
 
 ;; AUTHINFO GENERIC kludge.
 
-(defvar nntp-authinfo-generic nil
+(defcustom nntp-authinfo-generic nil
   "Set to the `NNTPAUTH' string to pass on to `authinfo-kludge'.
 
-Use this to arrange for per-server settings.")
+Use this to arrange for per-server settings."
+  :type '(choice (const :tag "Use `NNTPAUTH' environment variable" nil)
+                string)
+  :safe 'stringp)
 
 (defun nntp-open-authinfo-kludge (buffer)
   "Open a connection to SERVER using `authinfo-kludge'."
@@ -808,12 +1075,12 @@ (eval-after-load "erc"
 (defun mdw-nnimap-transform-headers ()
   (goto-char (point-min))
   (let (article lines size string)
-    (block nil
+    (cl-block nil
       (while (not (eobp))
        (while (not (looking-at "\\* [0-9]+ FETCH"))
          (delete-region (point) (progn (forward-line 1) (point)))
          (when (eobp)
-           (return)))
+           (cl-return)))
        (goto-char (match-end 0))
        ;; Unfold quoted {number} strings.
        (while (re-search-forward
@@ -834,15 +1101,16 @@ (defun mdw-nnimap-transform-headers ()
          (backward-char 1))
        (beginning-of-line)
        (setq article
-             (and (re-search-forward "UID \\([0-9]+\\)" (line-end-position)
-                                     t)
-                  (match-string 1)))
+               (and (re-search-forward "UID \\([0-9]+\\)"
+                                       (line-end-position)
+                                       t)
+                    (match-string 1)))
        (setq lines nil)
        (setq size
-             (and (re-search-forward "RFC822.SIZE \\([0-9]+\\)"
-                                     (line-end-position)
-                                     t)
-                  (match-string 1)))
+               (and (re-search-forward "RFC822.SIZE \\([0-9]+\\)"
+                                       (line-end-position)
+                                       t)
+                    (match-string 1)))
        (beginning-of-line)
        (when (search-forward "BODYSTRUCTURE" (line-end-position) t)
          (let ((structure (ignore-errors
@@ -878,14 +1146,14 @@ (eval-after-load 'nnimap
 (defadvice gnus-other-frame (around mdw-hack-frame-width compile activate)
   "Always arrange for mail/news frames to be 80 columns wide."
   (let ((default-frame-alist (cons `(width . ,(+ 80 mdw-frame-width-fudge))
-                                  (cl-delete 'width default-frame-alist
-                                             :key #'car))))
+                                  (delete* 'width default-frame-alist
+                                           :key #'car))))
     ad-do-it))
 
 ;; Preferred programs.
 
 (setq mailcap-user-mime-data
-      '(((type . "application/pdf") (viewer . "mupdf %s"))))
+       '(((type . "application/pdf") (viewer . "mupdf %s"))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Utility functions.
@@ -972,8 +1240,10 @@ (defun uuencode (file &optional name)
   ;; Now actually do the thing.
   (call-process "uuencode" file t nil name))
 
-(defvar np-file "~/.np"
-  "*Where the `now-playing' file is.")
+(defcustom np-file "~/.np"
+  "Where the `now-playing' file is."
+  :type 'file
+  :safe 'stringp)
 
 (defun np (&optional arg)
   "Grabs a `now-playing' string."
@@ -1025,21 +1295,6 @@ (defun mdw-auto-revert ()
   (let ((auto-revert-check-vc-info t))
     (auto-revert-buffers)))
 
-(defun comint-send-and-indent ()
-  (interactive)
-  (comint-send-input)
-  (and mdw-auto-indent
-       (indent-for-tab-command)))
-
-(defadvice comint-line-beginning-position
-    (around mdw-calculate-it-properly () activate compile)
-  "Calculate the actual line start for multi-line input."
-  (if (or comint-use-prompt-regexp
-         (eq (field-at-pos (point)) 'output))
-      ad-do-it
-    (setq ad-return-value
-         (constrain-to-field (line-beginning-position) (point)))))
-
 ;;;--------------------------------------------------------------------------
 ;;; Dired hacking.
 
@@ -1104,14 +1359,15 @@ (defun mdw-w3m-browse-url (url &optional new-session-p)
 (eval-after-load 'w3m
   '(define-key w3m-mode-map [?\e ?\r] 'w3m-view-this-url-new-session))
 
-(defvar mdw-good-url-browsers
+(defcustom mdw-good-url-browsers
   '(browse-url-mozilla
     browse-url-generic
     (w3m . mdw-w3m-browse-url)
     browse-url-w3)
   "List of good browsers for mdw-good-url-browsers.
 Each item is a browser function name, or a cons (CHECK . FUNC).
-A symbol FOO stands for (FOO . FOO).")
+A symbol FOO stands for (FOO . FOO)."
+  :type '(repeat (choice function (cons function function))))
 
 (defun mdw-good-url-browser ()
   "Return a good URL browser.
@@ -1158,7 +1414,7 @@ (eval-after-load "w3m-search"
             "http://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=%s")
            ("ljlogin" "LJ login" "http://www.livejournal.com/login.bml")))
        (add-to-list 'w3m-search-engine-alist
-                   (list (cadr item) (caddr item) nil))
+                   (list (cadr item) (cl-caddr item) nil))
        (add-to-list 'w3m-uri-replace-alist
                    (list (concat "\\`" (car item) ":")
                          'w3m-search-uri-replace
@@ -1169,30 +1425,45 @@ (eval-after-load "w3m-search"
 
 ;; Useful variables.
 
-(defvar mdw-fill-prefix nil
-  "*Used by `mdw-line-prefix' and `mdw-fill-paragraph'.
+(defcustom mdw-fill-prefix nil
+  "Used by `mdw-line-prefix' and `mdw-fill-paragraph'.
 If there's no fill prefix currently set (by the `fill-prefix'
 variable) and there's a match from one of the regexps here, it
 gets used to set the fill-prefix for the current operation.
 
-The variable is a list of items of the form `REGEXP . PREFIX'; if
-the REGEXP matches, the PREFIX is used to set the fill prefix.
-It in turn is a list of things:
+The variable is a list of items of the form `PATTERN . PREFIX'; if
+the PATTERN matches, the PREFIX is used to set the fill prefix.
+
+A PATTERN is one of the following.
+
+  * STRING -- a regular expression, expected to match at point
+  * (eval . FORM) -- a Lisp form which must evaluate non-nil
+  * (if COND CONSEQ-PAT ALT-PAT) -- if COND evaluates non-nil, must match
+    CONSEQ-PAT; otherwise must match ALT-PAT
+  * (and PATTERN ...) -- must match all of the PATTERNs
+  * (or PATTERN ...) -- must match at least one PATTERN
+  * (not PATTERN) -- mustn't match (probably not useful)
+
+A PREFIX is a list of the following kinds of things:
 
-  STRING -- insert a literal string
-  (match . N) -- insert the thing matched by bracketed subexpression N
-  (pad . N) -- a string of whitespace the same width as subexpression N
-  (expr . FORM) -- the result of evaluating FORM")
+  * STRING -- insert a literal string
+  * (match . N) -- insert the thing matched by bracketed subexpression N
+  * (pad . N) -- a string of whitespace the same width as subexpression N
+  * (expr . FORM) -- the result of evaluating FORM
+
+Information about `bracketed subexpressions' comes from the match data,
+as modified during matching.")
 
 (make-variable-buffer-local 'mdw-fill-prefix)
 
-(defvar mdw-hanging-indents
+(defcustom mdw-hanging-indents
   (concat "\\(\\("
            "\\([*o+]\\|-[-#]?\\|[0-9]+\\.\\|\\[[0-9]+\\]\\|([a-zA-Z])\\)"
            "[ \t]+"
          "\\)?\\)")
-  "*Standard regexp matching parts of a hanging indent.
-This is mainly useful in `auto-fill-mode'.")
+  "Standard regexp matching parts of a hanging indent.
+This is mainly useful in `auto-fill-mode'."
+  :type 'regexp)
 
 ;; Utility functions.
 
@@ -1206,16 +1477,41 @@ (defun mdw-maybe-tabify (s)
          (funcall tabfun (point-min) (point-max))
          (setq s (buffer-substring (point-min) (1- (point-max)))))))))
 
-(defun mdw-examine-fill-prefixes (l)
-  "Given a list of dynamic fill prefixes, pick one which matches
-context and return the static fill prefix to use.  Point must be
-at the start of a line, and match data must be saved."
-  (cond ((not l) nil)
-       ((looking-at (car (car l)))
-        (mdw-maybe-tabify (apply #'concat
-                                 (mapcar #'mdw-do-prefix-match
-                                         (cdr (car l))))))
-       (t (mdw-examine-fill-prefixes (cdr l)))))
+(defun mdw-fill-prefix-match-p (pat)
+  "Return non-nil if PAT matches at the current position."
+  (cond ((stringp pat) (looking-at pat))
+       ((not (consp pat)) (error "Unknown pattern item `%S'" pat))
+       ((eq (car pat) 'eval) (eval (cdr pat)))
+       ((eq (car pat) 'if)
+        (if (or (null (cdr pat))
+                (null (cddr pat))
+                (null (cl-cdddr pat))
+                (cl-cddddr pat))
+            (error "Invalid `if' pattern `%S'" pat))
+        (mdw-fill-prefix-match-p (if (eval (cadr pat))
+                                     (cl-caddr pat)
+                                   (cl-cadddr pat))))
+       ((eq (car pat) 'and)
+        (let ((pats (cdr pat))
+              (ok t))
+          (while (and pats
+                      (or (mdw-fill-prefix-match-p (car pats))
+                          (setq ok nil)))
+            (setq pats (cdr pats)))
+          ok))
+       ((eq (car pat) 'or)
+        (let ((pats (cdr pat))
+              (ok nil))
+          (while (and pats
+                      (or (not (mdw-fill-prefix-match-p (car pats)))
+                          (progn (setq ok t) nil)))
+            (setq pats (cdr pats)))
+          ok))
+       ((eq (car pat) 'not)
+        (if (or (null (cdr pat)) (cddr pat))
+            (error "Invalid `not' pattern `%S'" pat))
+        (not (mdw-fill-prefix-match-p (car pats))))
+       (t (error "Unknown pattern form `%S'" pat))))
 
 (defun mdw-maybe-car (p)
   "If P is a pair, return (car P), otherwise just return P."
@@ -1240,6 +1536,22 @@ (defun mdw-do-prefix-match (m)
        ((eq (car m) 'eval) (eval (cdr m)))
        (t "")))
 
+(defun mdw-examine-fill-prefixes (l)
+  "Given a list of dynamic fill prefixes, pick one which matches
+context and return the static fill prefix to use.  Point must be
+at the start of a line, and match data must be saved."
+  (let ((prefix nil))
+    (while (cond ((null l) nil)
+                ((mdw-fill-prefix-match-p (caar l))
+                 (setq prefix
+                         (mdw-maybe-tabify
+                          (apply #'concat
+                                 (mapcar #'mdw-do-prefix-match
+                                         (cdr (car l))))))
+                 nil))
+      (setq l (cdr l)))
+    prefix))
+
 (defun mdw-choose-dynamic-fill-prefix ()
   "Work out the dynamic fill prefix based on the variable `mdw-fill-prefix'."
   (cond ((and fill-prefix (not (string= fill-prefix ""))) fill-prefix)
@@ -1261,23 +1573,108 @@ (defun mdw-fill-paragraph ()
   (let ((fill-prefix (mdw-choose-dynamic-fill-prefix)))
     (fill-paragraph nil)))
 
+(defun mdw-point-within-string-p ()
+  "Return non-nil if point is within a string."
+  (let ((state (syntax-ppss)))
+    (elt state 3)))
+
 (defun mdw-standard-fill-prefix (rx &optional mat)
   "Set the dynamic fill prefix, handling standard hanging indents and stuff.
 This is just a short-cut for setting the thing by hand, and by
 design it doesn't cope with anything approximating a complicated
 case."
   (setq mdw-fill-prefix
-       `((,(concat rx mdw-hanging-indents)
-          (match . 1)
-          (pad . ,(or mat 2))))))
+         `(((if (mdw-point-within-string-p)
+                ,(concat "\\(\\s-*\\)" mdw-hanging-indents)
+              ,(concat rx mdw-hanging-indents))
+            (match . 1)
+            (pad . ,(or mat 2))))))
+
+;;;--------------------------------------------------------------------------
+;;; Printing.
+
+;; Teach PostScript about a condensed variant of Courier.  I'm using 85% of
+;; the usual width, which happens to match `mdwfonts', and David Carlisle's
+;; `pslatex'.  (Once upon a time, I used 80%, but decided consistency with
+;; `pslatex' was useful.)
+(setq ps-user-defined-prologue "
+/CourierCondensed /Courier
+/CourierCondensed-Bold /Courier-Bold
+/CourierCondensed-Oblique /Courier-Oblique
+/CourierCondensed-BoldOblique /Courier-BoldOblique
+  4 { findfont [0.85 0 0 1 0 0] makefont definefont pop } repeat
+")
+
+;; Hack `ps-print''s settings.
+(eval-after-load 'ps-print
+  '(progn
+
+     ;; Notice that the comment-delimiters should be in italics too.
+     (cl-pushnew 'font-lock-comment-delimiter-face ps-italic-faces)
+
+     ;; Select more suitable colours for the main kinds of tokens.  The
+     ;; colours set on the Emacs faces are chosen for use against a dark
+     ;; background, and work very badly on white paper.
+     (ps-extend-face '(font-lock-comment-face "darkgreen" nil italic))
+     (ps-extend-face '(font-lock-comment-delimiter-face "darkgreen" nil italic))
+     (ps-extend-face '(font-lock-string-face "RoyalBlue4" nil))
+     (ps-extend-face '(mdw-punct-face "sienna" nil))
+     (ps-extend-face '(mdw-number-face "OrangeRed3" nil))
+
+     ;; Teach `ps-print' about my condensed varsions of Courier.
+     (setq ps-font-info-database
+            (append '((CourierCondensed
+                       (fonts (normal . "CourierCondensed")
+                              (bold . "CourierCondensed-Bold")
+                              (italic . "CourierCondensed-Oblique")
+                              (bold-italic . "CourierCondensed-BoldOblique"))
+                       (size . 10.0)
+                       (line-height . 10.55)
+                       (space-width . 5.1)
+                       (avg-char-width . 5.1)))
+                    (cl-remove 'CourierCondensed ps-font-info-database
+                               :key #'car)))))
+
+;; Arrange to strip overlays from the buffer before we print .  This will
+;; prevent `flyspell' from interfering with the printout.  (It would be less
+;; bad if `ps-print' could merge the `flyspell' overlay face with the
+;; underlying `font-lock' face, but it can't (and that seems hard).  So
+;; instead we have this hack.
+;;
+;; The basic trick is to copy the relevant text from the buffer being printed
+;; into a temporary buffer and... just print that.  The text properties come
+;; with the text and end up in the new buffer, and the overlays get lost
+;; along the way.  Only problem is that the headers identifying the file
+;; being printed get confused, so remember the original buffer and reinstate
+;; it when constructing the headers.
+(defvar mdw-printing-buffer)
+
+(defadvice ps-generate-header
+    (around mdw-use-correct-buffer () activate compile)
+  "Print the correct name of the buffer being printed."
+  (with-current-buffer mdw-printing-buffer
+    ad-do-it))
+
+(defadvice ps-generate
+    (around mdw-strip-overlays (buffer from to genfunc) activate compile)
+  "Strip overlays -- in particular, from `flyspell' -- before printout."
+  (with-temp-buffer
+    (let ((mdw-printing-buffer buffer))
+      (insert-buffer-substring buffer from to)
+      (ad-set-arg 0 (current-buffer))
+      (ad-set-arg 1 (point-min))
+      (ad-set-arg 2 (point-max))
+      ad-do-it)))
 
 ;;;--------------------------------------------------------------------------
 ;;; Other common declarations.
 
 ;; Common mode settings.
 
-(defvar mdw-auto-indent t
-  "Whether to indent automatically after a newline.")
+(defcustom mdw-auto-indent t
+  "Whether to indent automatically after a newline."
+  :type 'boolean
+  :safe 'booleanp)
 
 (defun mdw-whitespace-mode (&optional arg)
   "Turn on/off whitespace mode, but don't highlight trailing space."
@@ -1312,6 +1709,7 @@ (defun mdw-misc-mode-config ()
   (setq comment-column 40)
   (auto-fill-mode 1)
   (setq fill-column mdw-text-width)
+  (flyspell-prog-mode)
   (and (fboundp 'gtags-mode)
        (gtags-mode))
   (if (fboundp 'hs-minor-mode)
@@ -1355,9 +1753,10 @@        (define-key map [C-S-mouse-3] 'gtags-pop-stack))))
 
 ;; Backup file handling.
 
-(defvar mdw-backup-disable-regexps nil
-  "*List of regular expressions: if a file name matches any of
-these then the file is not backed up.")
+(defcustom mdw-backup-disable-regexps nil
+  "List of regular expressions: if a file name matches any of
+these then the file is not backed up."
+  :type '(repeat regexp))
 
 (defun mdw-backup-enable-predicate (name)
   "[mdw]'s default backup predicate.
@@ -1381,26 +1780,28 @@ (defun mdw-last-one-out-turn-off-the-lights (frame)
   (let ((frame-display (frame-parameter frame 'display)))
     (when (and frame-display
               (eq window-system 'x)
-              (not (some (lambda (fr)
-                           (and (not (eq fr frame))
-                                (string= (frame-parameter fr 'display)
-                                         frame-display)))
-                         (frame-list))))
+              (not (cl-some (lambda (fr)
+                              (and (not (eq fr frame))
+                                   (string= (frame-parameter fr 'display)
+                                            frame-display)))
+                            (frame-list))))
       (run-with-idle-timer 0 nil #'x-close-connection frame-display))))
 (add-hook 'delete-frame-functions 'mdw-last-one-out-turn-off-the-lights)
 
 ;;;--------------------------------------------------------------------------
 ;;; Fullscreen-ness.
 
-(defvar mdw-full-screen-parameters
+(defcustom mdw-full-screen-parameters
   '((menu-bar-lines . 0)
-    ;(vertical-scroll-bars . nil)
+    ;;(vertical-scroll-bars . nil)
     )
-  "Frame parameters to set when making a frame fullscreen.")
+  "Frame parameters to set when making a frame fullscreen."
+  :type '(alist :key-type symbol))
 
-(defvar mdw-full-screen-save
+(defcustom mdw-full-screen-save
   '(width height)
-  "Extra frame parameters to save when setting fullscreen.")
+  "Extra frame parameters to save when setting fullscreen."
+  :type '(repeat symbol))
 
 (defun mdw-toggle-full-screen (&optional frame)
   "Show the FRAME fullscreen."
@@ -1458,6 +1859,9 @@ (mdw-define-face region
   (((min-colors 64)) :background "grey30")
   (((class color)) :background "blue")
   (t :inverse-video t))
+(mdw-define-face error
+  (((class color)) :background "red")
+  (t :inverse-video t))
 (mdw-define-face match
   (((class color)) :background "blue")
   (t :inverse-video t))
@@ -1493,11 +1897,46 @@ (mdw-define-face highlight
   (((class color)) :background "cyan")
   (t :inverse-video t))
 
+(mdw-define-face viper-minibuffer-emacs (t nil))
+(mdw-define-face viper-minibuffer-insert (t nil))
+(mdw-define-face viper-minibuffer-vi (t nil))
+(mdw-define-face viper-replace-overlay
+  (((min-colors 64)) :background "darkred")
+  (((class color)) :background "red")
+  (t :inverse-video t))
+(mdw-define-face viper-search (t :inherit isearch))
+
+(mdw-define-face compilation-error
+  (((class color)) :foreground "red" :weight bold)
+  (t :weight bold))
+(mdw-define-face compilation-warning
+  (((class color)) :foreground "orange" :weight bold)
+  (t :weight bold))
+(mdw-define-face compilation-info
+  (((class color)) :foreground "green" :weight bold)
+  (t :weight bold))
+(mdw-define-face compilation-line-number
+  (t :weight bold))
+(mdw-define-face compilation-column-number
+  (((min-colors 64)) :foreground "lightgrey"))
+(setq compilation-message-face 'mdw-virgin-face)
+(setq compilation-enter-directory-face 'font-lock-comment-face)
+(setq compilation-leave-directory-face 'font-lock-comment-face)
+
 (mdw-define-face holiday-face
   (t :background "red"))
 (mdw-define-face calendar-today-face
   (t :foreground "yellow" :weight bold))
 
+(mdw-define-face flyspell-incorrect
+  (((type x)) :underline (:color "red" :style wave))
+  (((class color)) :foreground "red" :underline t)
+  (t :underline t))
+(mdw-define-face flyspell-duplicate
+  (((type x)) :underline (:color "orange" :style wave))
+  (((class color)) :foreground "orange" :underline t)
+  (t :underline t))
+
 (mdw-define-face comint-highlight-prompt
   (t :weight bold))
 (mdw-define-face comint-highlight-input
@@ -1543,18 +1982,18 @@ (mdw-define-face font-lock-reference-face
   (t :weight bold))
 (mdw-define-face font-lock-variable-name-face
   (t :slant italic))
-(mdw-define-face font-lock-comment-delimiter-face
-  (((min-colors 64)) :slant italic :foreground "SeaGreen1")
-  (((class color)) :foreground "green")
-  (t :weight bold))
 (mdw-define-face font-lock-comment-face
   (((min-colors 64)) :slant italic :foreground "SeaGreen1")
   (((class color)) :foreground "green")
   (t :weight bold))
+(mdw-define-face font-lock-comment-delimiter-face
+  (t :inherit font-lock-comment-face))
 (mdw-define-face font-lock-string-face
   (((min-colors 64)) :foreground "SkyBlue1")
   (((class color)) :foreground "cyan")
   (t :weight bold))
+(mdw-define-face font-lock-doc-face
+  (t :inherit font-lock-string-face))
 
 (mdw-define-face message-separator
   (t :background "red" :foreground "white" :weight bold))
@@ -1643,6 +2082,10 @@ (mdw-define-face gnus-cite-10
 (mdw-define-face gnus-cite-11
   (t :foreground "grey"))
 
+(mdw-define-face gnus-emphasis-underline
+  (((type tty)) :underline t)
+  (t :slant italic))
+
 (mdw-define-face diff-header
   (t nil))
 (mdw-define-face diff-index
@@ -1832,7 +2275,9 @@ (mdw-define-face mdw-point-overlay-face
   (((class color)) :background "blue")
   (((type tty) (class mono)) :inverse-video t))
 
-(defvar mdw-point-overlay-fringe-display '(vertical-bar . vertical-bar))
+(defcustom mdw-point-overlay-fringe-display '(vertical-bar . vertical-bar)
+  "Bitmaps to display in the left and right fringes in the current line."
+  :type '(cons symbol symbol))
 
 (defun mdw-configure-point-overlay ()
   (let ((ov (make-overlay 0 0)))
@@ -1881,14 +2326,14 @@ (define-minor-mode mdw-point-overlay-mode
   :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))
+           (cl-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))))
+               (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))
@@ -1911,11 +2356,23 @@ (defun mdw-update-terminal-title ()
       (unless (and old (equal (cdr old) new))
        (if old (rplacd old new)
          (setq mdw-terminal-title-alist
-               (cons (cons tty new) mdw-terminal-title-alist)))
+                 (cons (cons tty new) mdw-terminal-title-alist)))
        (send-string-to-terminal (concat "\e]2;" new "\e\\"))))))
 
 (add-hook 'post-command-hook 'mdw-update-terminal-title)
 
+;;;--------------------------------------------------------------------------
+;;; Ediff hacking.
+
+(defvar mdw-ediff-previous-windows)
+(defun mdw-ediff-setup ()
+  (setq mdw-ediff-previous-windows (current-window-configuration)))
+(defun mdw-ediff-suspend-or-quit ()
+  (set-window-configuration mdw-ediff-previous-windows))
+(add-hook 'ediff-before-setup-hook 'mdw-ediff-setup)
+(add-hook 'ediff-quit-hook 'mdw-ediff-suspend-or-quit t)
+(add-hook 'ediff-suspend-hook 'mdw-ediff-suspend-or-quit t)
+
 ;;;--------------------------------------------------------------------------
 ;;; C programming configuration.
 
@@ -1946,7 +2403,7 @@ (defun mdw-c-indent-arglist-nested (langelem)
        (should-indent-p t))
     (while (and context
                (eq (caar context) 'arglist-cont-nonempty))
-      (when (and (= (caddr (pop context)) pos)
+      (when (and (= (cl-caddr (pop context)) pos)
                 context
                 (memq (caar context) '(arglist-intro
                                        arglist-cont-nonempty)))
@@ -1956,50 +2413,50 @@ (defun mdw-c-indent-arglist-nested (langelem)
 (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.
+(defun mdw-merge-style-alists (first second)
+  (let ((output nil))
+    (dolist (item first)
+      (let ((key (car item)) (value (cdr item)))
+       (if (let* ((key-name (symbol-name key))
+                  (key-len (length key-name)))
+             (and (>= key-len 6)
+                  (string= (substring key-name (- key-len 6)) "-alist")))
+           (push (cons key
+                       (mdw-merge-style-alists value
+                                               (cdr (assoc key second))))
+                 output)
+         (push item output))))
+    (dolist (item second)
+      (unless (assoc (car item) first)
+       (push item output)))
+    (nreverse output)))
+
+(cl-defmacro mdw-define-c-style (name (&optional parent) &rest assocs)
+  "Define a C style, called NAME (a symbol) based on PARENT, 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))
+        (var (intern (concat "mdw-c-style/" name-string)))
         (func (intern (concat "mdw-define-c-style/" name-string))))
     `(progn
-       (defun ,func () (c-add-style ,name-string ',assocs))
+       (setq ,var
+              ,(if (null parent)
+                   `',assocs
+                 (let ((parent-list (intern (concat "mdw-c-style/"
+                                                    (symbol-name parent)))))
+                   `(mdw-merge-style-alists ',assocs ,parent-list))))
+       (defun ,func () (c-add-style ,name-string ,var))
        (and (featurep 'cc-mode) (,func))
-       (add-hook 'mdw-define-c-styles-hook ',func))))
+       (add-hook 'mdw-define-c-styles-hook ',func)
+       ',name)))
 
 (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
+(mdw-define-c-style mdw-c ()
   (c-basic-offset . 2)
   (comment-column . 40)
   (c-class-key . "class")
@@ -2020,6 +2477,18 @@             (defun-open . (add 0 c-indent-one-line-block))
                   (statement-cont . +)
                   (statement-case-intro . +)))
 
+(mdw-define-c-style mdw-trustonic-c (mdw-c)
+  (c-basic-offset . 4)
+  (c-offsets-alist (access-label . -2)))
+
+(mdw-define-c-style mdw-trustonic-alec-c (mdw-trustonic-c)
+  (comment-column . 0)
+  (c-indent-comment-alist (anchored-comment . (column . 0))
+                         (end-block . (space . 1))
+                         (cpp-end-block . (space . 1))
+                         (other . (space . 1)))
+  (c-offsets-alist (arglist-cont-nonempty . mdw-c-indent-arglist-nested)))
+
 (defun mdw-set-default-c-style (modes style)
   "Update the default CC Mode style for MODES to be STYLE.
 
@@ -2028,14 +2497,15 @@ (defun mdw-set-default-c-style (modes style)
   (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))))))))
+           (append (mapcar (lambda (mode)
+                             (cons mode style))
+                           modes)
+                   (cl-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)
@@ -2192,42 +2662,42 @@ (defun mdw-fontify-c-and-c++ ()
                      "selector")))
 
     (setq font-lock-keywords
-         (list
-
-          ;; Fontify include files as strings.
-          (list (concat "^[ \t]*\\#[ \t]*"
-                        "\\(include\\|import\\)"
-                        "[ \t]*\\(<[^>]+\\(>\\|\\)\\)")
-                '(2 font-lock-string-face))
-
-          ;; Preprocessor directives are `references'?.
-          (list (concat "^\\([ \t]*#[ \t]*\\(\\("
-                        preprocessor-keywords
-                        "\\)\\>\\|[0-9]+\\|$\\)\\)")
-                '(1 font-lock-keyword-face))
-
-          ;; Handle the keywords defined above.
-          (list (concat "@\\<\\(" objc-keywords "\\)\\>")
-                '(0 font-lock-keyword-face))
-
-          (list (concat "\\<\\(" c-keywords "\\)\\>")
-                '(0 font-lock-keyword-face))
-
-          (list (concat "\\<\\(" c-builtins "\\)\\>")
-                '(0 font-lock-variable-name-face))
-
-          ;; Handle numbers too.
-          ;;
-          ;; This looks strange, I know.  It corresponds to the
-          ;; preprocessor's idea of what a number looks like, rather than
-          ;; anything sensible.
-          (list (concat "\\(\\<[0-9]\\|\\.[0-9]\\)"
-                        "\\([Ee][+-]\\|[0-9A-Za-z_.]\\)*")
-                '(0 mdw-number-face))
-
-          ;; And anything else is punctuation.
-          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face))))))
+           (list
+
+            ;; Fontify include files as strings.
+            (list (concat "^[ \t]*\\#[ \t]*"
+                          "\\(include\\|import\\)"
+                          "[ \t]*\\(<[^>]+>?\\)")
+                  '(2 font-lock-string-face))
+
+            ;; Preprocessor directives are `references'?.
+            (list (concat "^\\([ \t]*#[ \t]*\\(\\("
+                          preprocessor-keywords
+                          "\\)\\>\\|[0-9]+\\|$\\)\\)")
+                  '(1 font-lock-keyword-face))
+
+            ;; Handle the keywords defined above.
+            (list (concat "@\\<\\(" objc-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
+
+            (list (concat "\\<\\(" c-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
+
+            (list (concat "\\<\\(" c-builtins "\\)\\>")
+                  '(0 font-lock-variable-name-face))
+
+            ;; Handle numbers too.
+            ;;
+            ;; This looks strange, I know.  It corresponds to the
+            ;; preprocessor's idea of what a number looks like, rather than
+            ;; anything sensible.
+            (list (concat "\\(\\<[0-9]\\|\\.[0-9]\\)"
+                          "\\([Ee][+-]\\|[0-9A-Za-z_.]\\)*")
+                  '(0 mdw-number-face))
+
+            ;; And anything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))))
 
 (define-derived-mode sod-mode c-mode "Sod"
   "Major mode for editing Sod code.")
@@ -2263,24 +2733,24 @@ (defun mdw-fontify-apcalc ()
                      "show" "static" "switch" "while" "write")))
 
     (setq font-lock-keywords
-         (list
+           (list
 
-          ;; Handle the keywords defined above.
-          (list (concat "\\<\\(" c-keywords "\\)\\>")
-                '(0 font-lock-keyword-face))
+            ;; Handle the keywords defined above.
+            (list (concat "\\<\\(" c-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
 
-          ;; Handle numbers too.
-          ;;
-          ;; This looks strange, I know.  It corresponds to the
-          ;; preprocessor's idea of what a number looks like, rather than
-          ;; anything sensible.
-          (list (concat "\\(\\<[0-9]\\|\\.[0-9]\\)"
-                        "\\([Ee][+-]\\|[0-9A-Za-z_.]\\)*")
-                '(0 mdw-number-face))
+            ;; Handle numbers too.
+            ;;
+            ;; This looks strange, I know.  It corresponds to the
+            ;; preprocessor's idea of what a number looks like, rather than
+            ;; anything sensible.
+            (list (concat "\\(\\<[0-9]\\|\\.[0-9]\\)"
+                          "\\([Ee][+-]\\|[0-9A-Za-z_.]\\)*")
+                  '(0 mdw-number-face))
 
-          ;; And anything else is punctuation.
-          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face))))))
+            ;; And anything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))))
 
 (progn
   (add-hook 'apcalc-mode-hook 'mdw-misc-mode-config t)
@@ -2291,7 +2761,7 @@ (progn
 
 ;; Make indentation nice.
 
-(mdw-define-c-style mdw-java
+(mdw-define-c-style mdw-java ()
   (c-basic-offset . 2)
   (c-backslash-column . 72)
   (c-offsets-alist (substatement-open . 0)
@@ -2338,29 +2808,29 @@ (defun mdw-fontify-java ()
         (mdw-regexps "false" "null" "super" "this" "true")))
 
     (setq font-lock-keywords
-         (list
-
-          ;; Handle the keywords defined above.
-          (list (concat "\\<\\(" java-keywords "\\)\\>")
-                '(0 font-lock-keyword-face))
-
-          ;; Handle the magic builtins defined above.
-          (list (concat "\\<\\(" java-builtins "\\)\\>")
-                '(0 font-lock-variable-name-face))
-
-          ;; Handle numbers too.
-          ;;
-          ;; The following isn't quite right, but it's close enough.
-          (list (concat "\\<\\("
-                        "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
-                        "[0-9]+\\(\\.[0-9]*\\|\\)"
-                        "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
-                        "[lLfFdD]?")
-                '(0 mdw-number-face))
-
-          ;; And anything else is punctuation.
-          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face))))))
+           (list
+
+            ;; Handle the keywords defined above.
+            (list (concat "\\<\\(" java-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
+
+            ;; Handle the magic builtins defined above.
+            (list (concat "\\<\\(" java-builtins "\\)\\>")
+                  '(0 font-lock-variable-name-face))
+
+            ;; Handle numbers too.
+            ;;
+            ;; The following isn't quite right, but it's close enough.
+            (list (concat "\\<\\("
+                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
+                          "[0-9]+\\(\\.[0-9]*\\)?"
+                          "\\([eE][-+]?[0-9]+\\)?\\)"
+                          "[lLfFdD]?")
+                  '(0 mdw-number-face))
+
+            ;; And anything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))))
 
 (progn
   (add-hook 'java-mode-hook 'mdw-misc-mode-config t)
@@ -2397,29 +2867,29 @@ (defun mdw-fontify-javascript ()
                      "arguments" "this")))
 
     (setq font-lock-keywords
-         (list
-
-          ;; Handle the keywords defined above.
-          (list (concat "\\_<\\(" javascript-keywords "\\)\\_>")
-                '(0 font-lock-keyword-face))
-
-          ;; Handle the predefined builtins defined above.
-          (list (concat "\\_<\\(" javascript-builtins "\\)\\_>")
-                '(0 font-lock-variable-name-face))
-
-          ;; Handle numbers too.
-          ;;
-          ;; The following isn't quite right, but it's close enough.
-          (list (concat "\\_<\\("
-                        "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
-                        "[0-9]+\\(\\.[0-9]*\\|\\)"
-                        "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
-                        "[lLfFdD]?")
-                '(0 mdw-number-face))
-
-          ;; And anything else is punctuation.
-          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face))))))
+           (list
+
+            ;; Handle the keywords defined above.
+            (list (concat "\\_<\\(" javascript-keywords "\\)\\_>")
+                  '(0 font-lock-keyword-face))
+
+            ;; Handle the predefined builtins defined above.
+            (list (concat "\\_<\\(" javascript-builtins "\\)\\_>")
+                  '(0 font-lock-variable-name-face))
+
+            ;; Handle numbers too.
+            ;;
+            ;; The following isn't quite right, but it's close enough.
+            (list (concat "\\_<\\("
+                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
+                          "[0-9]+\\(\\.[0-9]*\\)?"
+                          "\\([eE][-+]?[0-9]+\\)?\\)"
+                          "[lLfFdD]?")
+                  '(0 mdw-number-face))
+
+            ;; And anything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))))
 
 (progn
   (add-hook 'js-mode-hook 'mdw-misc-mode-config t)
@@ -2447,52 +2917,52 @@ (defun mdw-fontify-scala ()
        (punctuation "[-!%^&*=+:@#~/?\\|`]"))
 
     (setq font-lock-keywords
-         (list
-
-          ;; Magical identifiers between backticks.
-          (list (concat "`\\([^`]+\\)`")
-                '(1 font-lock-variable-name-face))
-
-          ;; Handle the keywords defined above.
-          (list (concat "\\_<\\(" scala-keywords "\\)\\_>")
-                '(0 font-lock-keyword-face))
-
-          ;; Handle the constants defined above.
-          (list (concat "\\_<\\(" scala-constants "\\)\\_>")
-                '(0 font-lock-variable-name-face))
-
-          ;; Magical identifiers between backticks.
-          (list (concat "`\\([^`]+\\)`")
-                '(1 font-lock-variable-name-face))
-
-          ;; Handle numbers too.
-          ;;
-          ;; As usual, not quite right.
-          (list (concat "\\_<\\("
-                        "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
-                        "[0-9]+\\(\\.[0-9]*\\|\\)"
-                        "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
-                        "[lLfFdD]?")
-                '(0 mdw-number-face))
-
-          ;; And everything else is punctuation.
-          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))
+           (list
+
+            ;; Magical identifiers between backticks.
+            (list (concat "`\\([^`]+\\)`")
+                  '(1 font-lock-variable-name-face))
+
+            ;; Handle the keywords defined above.
+            (list (concat "\\_<\\(" scala-keywords "\\)\\_>")
+                  '(0 font-lock-keyword-face))
+
+            ;; Handle the constants defined above.
+            (list (concat "\\_<\\(" scala-constants "\\)\\_>")
+                  '(0 font-lock-variable-name-face))
+
+            ;; Magical identifiers between backticks.
+            (list (concat "`\\([^`]+\\)`")
+                  '(1 font-lock-variable-name-face))
+
+            ;; Handle numbers too.
+            ;;
+            ;; As usual, not quite right.
+            (list (concat "\\_<\\("
+                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
+                          "[0-9]+\\(\\.[0-9]*\\)?"
+                          "\\([eE][-+]?[0-9]+\\)?\\)"
+                          "[lLfFdD]?")
+                  '(0 mdw-number-face))
+
+            ;; And everything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face)))
 
          font-lock-syntactic-keywords
-         (list
-
-          ;; Single quotes around characters.  But not when used to quote
-          ;; symbol names.  Ugh.
-          (list (concat "\\('\\)"
-                        "\\(" "."
-                        "\\|" "\\\\" "\\(" "\\\\\\\\" "\\)*"
-                              "u+" "[0-9a-fA-F]\\{4\\}"
-                        "\\|" "\\\\" "[0-7]\\{1,3\\}"
-                        "\\|" "\\\\" "." "\\)"
-                        "\\('\\)")
-                '(1 "\"")
-                '(4 "\""))))))
+           (list
+
+            ;; Single quotes around characters.  But not when used to quote
+            ;; symbol names.  Ugh.
+            (list (concat "\\('\\)"
+                          "\\(" "."
+                          "\\|" "\\\\" "\\(" "\\\\\\\\" "\\)*"
+                          "u+" "[0-9a-fA-F]\\{4\\}"
+                          "\\|" "\\\\" "[0-7]\\{1,3\\}"
+                          "\\|" "\\\\" "." "\\)"
+                          "\\('\\)")
+                  '(1 "\"")
+                  '(4 "\""))))))
 
 (progn
   (add-hook 'scala-mode-hook 'mdw-misc-mode-config t)
@@ -2503,7 +2973,7 @@ (progn
 
 ;; Make indentation nice.
 
-(mdw-define-c-style mdw-csharp
+(mdw-define-c-style mdw-csharp ()
   (c-basic-offset . 2)
   (c-backslash-column . 72)
   (c-offsets-alist (substatement-open . 0)
@@ -2542,29 +3012,29 @@ (defun mdw-fontify-csharp ()
         (mdw-regexps "base" "false" "null" "this" "true")))
 
     (setq font-lock-keywords
-         (list
-
-          ;; Handle the keywords defined above.
-          (list (concat "\\<\\(" csharp-keywords "\\)\\>")
-                '(0 font-lock-keyword-face))
-
-          ;; Handle the magic builtins defined above.
-          (list (concat "\\<\\(" csharp-builtins "\\)\\>")
-                '(0 font-lock-variable-name-face))
-
-          ;; Handle numbers too.
-          ;;
-          ;; The following isn't quite right, but it's close enough.
-          (list (concat "\\<\\("
-                        "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
-                        "[0-9]+\\(\\.[0-9]*\\|\\)"
-                        "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
-                        "[lLfFdD]?")
-                '(0 mdw-number-face))
-
-          ;; And anything else is punctuation.
-          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face))))))
+           (list
+
+            ;; Handle the keywords defined above.
+            (list (concat "\\<\\(" csharp-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
+
+            ;; Handle the magic builtins defined above.
+            (list (concat "\\<\\(" csharp-builtins "\\)\\>")
+                  '(0 font-lock-variable-name-face))
+
+            ;; Handle numbers too.
+            ;;
+            ;; The following isn't quite right, but it's close enough.
+            (list (concat "\\<\\("
+                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
+                          "[0-9]+\\(\\.[0-9]*\\)?"
+                          "\\([eE][-+]?[0-9]+\\)?\\)"
+                          "[lLfFdD]?")
+                  '(0 mdw-number-face))
+
+            ;; And anything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))))
 
 (define-derived-mode csharp-mode java-mode "C#"
   "Major mode for editing C# code.")
@@ -2579,7 +3049,7 @@ (setq fsharp-indent-offset 2)
 (defun mdw-fontify-fsharp ()
 
   (let ((punct "=<>+-*/|&%!@?"))
-    (do ((i 0 (1+ i)))
+    (cl-do ((i 0 (1+ i)))
        ((>= i (length punct)))
       (modify-syntax-entry (aref punct i) ".")))
 
@@ -2627,68 +3097,68 @@ (defun mdw-fontify-fsharp ()
         (mdw-regexps "if" "indent" "else" "endif")))
 
     (setq font-lock-keywords
-         (list (list (concat "\\(^\\|[^\"]\\)"
-                             "\\(" "(\\*"
-                                   "[^*]*\\*+"
-                                   "\\(" "[^)*]" "[^*]*" "\\*+" "\\)*"
-                                   ")"
-                             "\\|"
-                                   "//.*"
-                             "\\)")
-                     '(2 font-lock-comment-face))
-
-               (list (concat "'" "\\("
-                                   "\\\\"
-                                   "\\(" "[ntbr'\\]"
-                                   "\\|" "[0-9][0-9][0-9]"
-                                   "\\|" "u" "[0-9a-fA-F]\\{4\\}"
-                                   "\\|" "U" "[0-9a-fA-F]\\{8\\}"
-                                   "\\)"
-                                 "\\|"
-                                 "." "\\)" "'"
-                             "\\|"
-                             "\"" "[^\"\\]*"
-                                   "\\(" "\\\\" "\\(.\\|\n\\)"
-                                         "[^\"\\]*" "\\)*"
-                             "\\(\"\\|\\'\\)")
-                     '(0 font-lock-string-face))
-
-               (list (concat "\\_<\\(" bang-keywords "\\)!" "\\|"
-                             "^#[ \t]*\\(" preprocessor-keywords "\\)\\_>"
-                             "\\|"
-                             "\\_<\\(" fsharp-keywords "\\)\\_>")
-                     '(0 font-lock-keyword-face))
-               (list (concat "\\<\\(" fsharp-builtins "\\)\\_>")
-                     '(0 font-lock-variable-name-face))
-
-               (list (concat "\\_<"
-                             "\\(" "0[bB][01]+" "\\|"
-                                   "0[oO][0-7]+" "\\|"
-                                   "0[xX][0-9a-fA-F]+" "\\)"
-                             "\\(" "lf\\|LF" "\\|"
-                                   "[uU]?[ysnlL]?" "\\)"
-                             "\\|"
-                             "\\_<"
-                             "[0-9]+" "\\("
-                               "[mMQRZING]"
+           (list (list (concat "\\(^\\|[^\"]\\)"
+                               "\\(" "(\\*"
+                                     "[^*]*\\*+"
+                                     "\\(" "[^)*]" "[^*]*" "\\*+" "\\)*"
+                                     ")"
                                "\\|"
-                               "\\(\\.[0-9]*\\)?"
-                               "\\([eE][-+]?[0-9]+\\)?"
-                               "[fFmM]?"
+                                     "//.*"
+                               "\\)")
+                       '(2 font-lock-comment-face))
+
+                 (list (concat "'" "\\("
+                                     "\\\\"
+                                     "\\(" "[ntbr'\\]"
+                                     "\\|" "[0-9][0-9][0-9]"
+                                     "\\|" "u" "[0-9a-fA-F]\\{4\\}"
+                                     "\\|" "U" "[0-9a-fA-F]\\{8\\}"
+                                     "\\)"
+                                   "\\|"
+                                   "." "\\)" "'"
                                "\\|"
-                               "[uU]?[ysnlL]?"
-                             "\\)")
-                     '(0 mdw-number-face))
+                               "\"" "[^\"\\]*"
+                                     "\\(" "\\\\" "\\(.\\|\n\\)"
+                                           "[^\"\\]*" "\\)*"
+                               "\\(\"\\|\\'\\)")
+                       '(0 font-lock-string-face))
+
+                 (list (concat "\\_<\\(" bang-keywords "\\)!" "\\|"
+                               "^#[ \t]*\\(" preprocessor-keywords "\\)\\_>"
+                               "\\|"
+                               "\\_<\\(" fsharp-keywords "\\)\\_>")
+                       '(0 font-lock-keyword-face))
+                 (list (concat "\\<\\(" fsharp-builtins "\\)\\_>")
+                       '(0 font-lock-variable-name-face))
+
+                 (list (concat "\\_<"
+                               "\\(" "0[bB][01]+" "\\|"
+                                     "0[oO][0-7]+" "\\|"
+                                     "0[xX][0-9a-fA-F]+" "\\)"
+                               "\\(" "lf\\|LF" "\\|"
+                                     "[uU]?[ysnlL]?" "\\)"
+                               "\\|"
+                               "\\_<"
+                               "[0-9]+" "\\("
+                                 "[mMQRZING]"
+                                 "\\|"
+                                 "\\(\\.[0-9]*\\)?"
+                                 "\\([eE][-+]?[0-9]+\\)?"
+                                 "[fFmM]?"
+                                 "\\|"
+                                 "[uU]?[ysnlL]?"
+                               "\\)")
+                       '(0 mdw-number-face))
 
-               (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                     '(0 mdw-punct-face))))))
+                 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                       '(0 mdw-punct-face))))))
 
 (defun mdw-fontify-inferior-fsharp ()
   (mdw-fontify-fsharp)
   (setq font-lock-keywords
-       (append (list (list "^[#-]" '(0 font-lock-comment-face))
-                     (list "^>" '(0 font-lock-keyword-face)))
-               font-lock-keywords)))
+         (append (list (list "^[#-]" '(0 font-lock-comment-face))
+                       (list "^>" '(0 font-lock-keyword-face)))
+                 font-lock-keywords)))
 
 (progn
   (add-hook 'fsharp-mode-hook 'mdw-misc-mode-config t)
@@ -2718,44 +3188,44 @@ (defun mdw-fontify-go ()
                      "new" "panic" "real" "recover")))
 
     (setq font-lock-keywords
-         (list
-
-          ;; Handle the keywords defined above.
-          (list (concat "\\<\\(" go-keywords "\\)\\>")
-                '(0 font-lock-keyword-face))
-          (list (concat "\\<\\(" go-intrinsics "\\)\\>")
-                '(0 font-lock-variable-name-face))
-
-          ;; Strings and characters.
-          (list (concat "'"
-                        "\\(" "[^\\']" "\\|"
-                              "\\\\"
-                              "\\(" "[abfnrtv\\'\"]" "\\|"
-                                    "[0-7]\\{3\\}" "\\|"
-                                    "x" "[0-9A-Fa-f]\\{2\\}" "\\|"
-                                    "u" "[0-9A-Fa-f]\\{4\\}" "\\|"
-                                    "U" "[0-9A-Fa-f]\\{8\\}" "\\)" "\\)"
-                        "'"
-                        "\\|"
-                        "\""
-                        "\\(" "[^\n\\\"]+" "\\|" "\\\\." "\\)*"
-                        "\\(\"\\|$\\)"
-                        "\\|"
-                        "`" "[^`]+" "`")
-                '(0 font-lock-string-face))
-
-          ;; Handle numbers too.
-          ;;
-          ;; The following isn't quite right, but it's close enough.
-          (list (concat "\\<\\("
-                        "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
-                        "[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))))))
+           (list
+
+            ;; Handle the keywords defined above.
+            (list (concat "\\<\\(" go-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
+            (list (concat "\\<\\(" go-intrinsics "\\)\\>")
+                  '(0 font-lock-variable-name-face))
+
+            ;; Strings and characters.
+            (list (concat "'"
+                          "\\(" "[^\\']" "\\|"
+                                "\\\\"
+                                "\\(" "[abfnrtv\\'\"]" "\\|"
+                                      "[0-7]\\{3\\}" "\\|"
+                                      "x" "[0-9A-Fa-f]\\{2\\}" "\\|"
+                                      "u" "[0-9A-Fa-f]\\{4\\}" "\\|"
+                                      "U" "[0-9A-Fa-f]\\{8\\}" "\\)" "\\)"
+                          "'"
+                          "\\|"
+                          "\""
+                          "\\(" "[^\n\\\"]+" "\\|" "\\\\." "\\)*"
+                          "\\(\"\\|$\\)"
+                          "\\|"
+                          "`" "[^`]+" "`")
+                  '(0 font-lock-string-face))
+
+            ;; Handle numbers too.
+            ;;
+            ;; The following isn't quite right, but it's close enough.
+            (list (concat "\\<\\("
+                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
+                          "[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))))))
 (progn
   (add-hook 'go-mode-hook 'mdw-misc-mode-config t)
   (add-hook 'go-mode-hook 'mdw-fontify-go t))
@@ -2807,33 +3277,34 @@ (defun mdw-fontify-rust ()
                      "char" "str"
                      "self" "Self")))
     (setq font-lock-keywords
-         (list
-
-          ;; Handle the keywords defined above.
-          (list (concat "\\_<\\(" rust-keywords "\\)\\_>")
-                '(0 font-lock-keyword-face))
-          (list (concat "\\_<\\(" rust-builtins "\\)\\_>")
-                '(0 font-lock-variable-name-face))
-
-          ;; Handle numbers too.
-          (list (concat "\\_<\\("
-                              "[0-9][0-9_]*"
-                              "\\(" "\\(\\.[0-9_]+\\)?[eE][-+]?[0-9_]+"
-                              "\\|" "\\.[0-9_]+"
-                              "\\)"
-                              "\\(f32\\|f64\\)?"
-                        "\\|" "\\(" "[0-9][0-9_]*"
-                              "\\|" "0x[0-9a-fA-F_]+"
-                              "\\|" "0o[0-7_]+"
-                              "\\|" "0b[01_]+"
-                              "\\)"
-                              "\\([ui]\\(8\\|16\\|32\\|64\\|size\\)\\)?"
-                        "\\)\\_>")
-                '(0 mdw-number-face))
-
-          ;; And anything else is punctuation.
-          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face)))))
+           (list
+
+            ;; Handle the keywords defined above.
+            (list (concat "\\_<\\(" rust-keywords "\\)\\_>")
+                  '(0 font-lock-keyword-face))
+            (list (concat "\\_<\\(" rust-builtins "\\)\\_>")
+                  '(0 font-lock-variable-name-face))
+
+            ;; Handle numbers too.
+            (list (concat "\\_<\\("
+                                "[0-9][0-9_]*"
+                                "\\(" "\\(\\.[0-9_]+\\)?[eE][-+]?[0-9_]+"
+                                "\\|" "\\.[0-9_]+"
+                                "\\)"
+                                "\\(f32\\|f64\\)?"
+                          "\\|" "\\(" "[0-9][0-9_]*"
+                                "\\|" "0x[0-9a-fA-F_]+"
+                                "\\|" "0o[0-7_]+"
+                                "\\|" "0b[01_]+"
+                                "\\)"
+                                "\\([ui]\\(8\\|16\\|32\\|64\\|size\\)\\)?"
+                          "\\)\\_>")
+                  '(0 mdw-number-face))
+
+            ;; And anything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face)))
+           font-lock-syntactic-face-function nil))
 
   ;; Hack key bindings.
   (local-set-key [?{] 'mdw-self-insert-and-indent)
@@ -2848,7 +3319,7 @@ (progn
 
 ;; Make Awk indentation nice.
 
-(mdw-define-c-style mdw-awk
+(mdw-define-c-style mdw-awk ()
   (c-basic-offset . 2)
   (c-offsets-alist (substatement-open . 0)
                   (c-backslash-column . 72)
@@ -2879,25 +3350,25 @@ (defun mdw-fontify-awk ()
                      "systime" "tolower" "toupper" "while")))
 
     (setq font-lock-keywords
-         (list
-
-          ;; Handle the keywords defined above.
-          (list (concat "\\<\\(" c-keywords "\\)\\>")
-                '(0 font-lock-keyword-face))
-
-          ;; Handle numbers too.
-          ;;
-          ;; The following isn't quite right, but it's close enough.
-          (list (concat "\\<\\("
-                        "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
-                        "[0-9]+\\(\\.[0-9]*\\|\\)"
-                        "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
-                        "[uUlL]*")
-                '(0 mdw-number-face))
-
-          ;; And anything else is punctuation.
-          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face))))))
+           (list
+
+            ;; Handle the keywords defined above.
+            (list (concat "\\<\\(" c-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
+
+            ;; Handle numbers too.
+            ;;
+            ;; The following isn't quite right, but it's close enough.
+            (list (concat "\\<\\("
+                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
+                          "[0-9]+\\(\\.[0-9]*\\)?"
+                          "\\([eE][-+]?[0-9]+\\)?\\)"
+                          "[uUlL]*")
+                  '(0 mdw-number-face))
+
+            ;; And anything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))))
 
 (progn
   (add-hook 'awk-mode-hook 'mdw-misc-mode-config t)
@@ -2912,6 +3383,7 @@ (setq-default perl-indent-level 2)
 
 (setq-default cperl-indent-level 2
              cperl-continued-statement-offset 2
+             cperl-indent-region-fix-constructs nil
              cperl-continued-brace-offset 0
              cperl-brace-offset -2
              cperl-brace-imaginary-offset 0
@@ -2949,21 +3421,21 @@ (defun mdw-fontify-perl ()
                      "when" "while")))
 
     (setq font-lock-keywords
-         (list
+           (list
 
-          ;; Set up the keywords defined above.
-          (list (concat "\\<\\(" perl-keywords "\\)\\>")
-                '(0 font-lock-keyword-face))
+            ;; Set up the keywords defined above.
+            (list (concat "\\<\\(" perl-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
 
-          ;; At least numbers are simpler than C.
-          (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
-                        "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
-                        "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
-                '(0 mdw-number-face))
+            ;; At least numbers are simpler than C.
+            (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
+                          "\\<[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))))))
+            ;; And anything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))))
 
 (defun perl-number-tests (&optional arg)
   "Assign consecutive numbers to lines containing `#t'.  With ARG,
@@ -2992,40 +3464,166 @@ (setq-default py-indent-offset 2
              python-indent-offset 2
              python-fill-docstring-style 'symmetric)
 
-(defun mdw-fontify-pythonic (keywords)
+(defun mdw-fontify-pythonic (keywords soft-keywords builtins)
 
   ;; Miscellaneous fiddling.
   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
   (setq indent-tabs-mode nil)
+  (set (make-local-variable 'forward-sexp-function) nil)
 
   ;; Now define fontification things.
   (make-local-variable 'font-lock-keywords)
   (setq font-lock-keywords
-       (list
+         (list
 
-        ;; Set up the keywords defined above.
-        (list (concat "\\_<\\(" keywords "\\)\\_>")
-              '(0 font-lock-keyword-face))
+          ;; Set up the keywords defined above.
+          (list (concat "\\_<\\(" keywords "\\)\\_>")
+                '(0 font-lock-keyword-face))
+          (list (concat "\\(^\\|[^.]\\)\\_<\\(" soft-keywords "\\)\\_>")
+                '(2 font-lock-keyword-face))
+          (list (concat "\\(^\\|[^.]\\)\\_<\\(" builtins "\\)\\_>")
+                '(2 font-lock-variable-name-face))
+          (list (concat "\\_<\\(__\\(\\sw+\\|\\s_+\\)+__\\)\\_>")
+                '(0 font-lock-variable-name-face))
 
-        ;; At least numbers are simpler than C.
-        (list (concat "\\_<0\\([xX][0-9a-fA-F]+\\|[oO]?[0-7]+\\|[bB][01]+\\)\\|"
-                      "\\_<[0-9][0-9]*\\(\\.[0-9]*\\|\\)"
-                      "\\([eE]\\([-+]\\|\\)[0-9]+\\|[lL]\\|\\)")
-              '(0 mdw-number-face))
+          ;; At least numbers are simpler than C.
+          (list (concat "\\_<0\\([xX][0-9a-fA-F]+\\|[oO]?[0-7]+\\|[bB][01]+\\)\\|"
+                        "\\_<[0-9][0-9]*\\(\\.[0-9]*\\)?"
+                        "\\([eE][-+]?[0-9]+\\|[lL]\\)?")
+                '(0 mdw-number-face))
 
-        ;; And anything else is punctuation.
-        (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-              '(0 mdw-punct-face)))))
+          ;; And anything else is punctuation.
+          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                '(0 mdw-punct-face)))))
 
 ;; Define Python fontification styles.
 
 (defun mdw-fontify-python ()
   (mdw-fontify-pythonic
-   (mdw-regexps "and" "as" "assert" "break" "class" "continue" "def"
-               "del" "elif" "else" "except" "exec" "finally" "for"
-               "from" "global" "if" "import" "in" "is" "lambda"
-               "not" "or" "pass" "print" "raise" "return" "try"
-               "while" "with" "yield")))
+   (mdw-regexps "and" "as" "assert" "async" "await"
+               "break"
+               "class" "continue"
+               "def" "del"
+               "elif" "else" "except" ;"exec"
+               "finally" "for" "from"
+               "global"
+               "if" "import" "in" "is"
+               "lambda"
+               "nonlocal"
+               "not"
+               "or"
+               "pass" ;"print"
+               "raise" "return"
+               "try" ;"type"
+               "while" "with"
+               "yield")
+
+   (mdw-regexps "case"
+               "match")
+
+   (mdw-regexps "Ellipsis"
+               "False"
+               "None" "NotImplemented"
+               "True"
+               "__debug__"
+
+               "BaseException"
+                 "BaseExceptionGroup"
+                 "Exception"
+                   "StandardError"
+                     "ArithmeticError"
+                       "FloatingPointError"
+                       "OverflowError"
+                       "ZeroDivisionError"
+                     "AssertionError"
+                     "AttributeError"
+                     "BufferError"
+                     "EnvironmentError"
+                       "IOError"
+                       "OSError"
+                         "BlockingIOError"
+                         "ChildProcessError"
+                         "ConnectionError"
+                           "BrokenPipeError"
+                           "ConnectionAbortedError"
+                           "ConnectionRefusedError"
+                           "ConnectionResetError"
+                         "FileExistsError"
+                         "FileNotFoundError"
+                         "InterruptedError"
+                         "IsADirectoryError"
+                         "NotADirectoryError"
+                         "PermissionError"
+                         "TimeoutError"
+                     "EOFError"
+                     "ExceptionGroup"
+                     "ImportError"
+                       "ModuleNotFoundError"
+                     "LookupError"
+                       "IndexError"
+                       "KeyError"
+                     "MemoryError"
+                     "NameError"
+                       "UnboundLocalError"
+                     "ReferenceError"
+                     "RuntimeError"
+                       "NotImplementedError"
+                       "RecursionError"
+                     "SyntaxError"
+                       "IndentationError"
+                         "TabError"
+                     "SystemError"
+                     "TypeError"
+                     "ValueError"
+                       "UnicodeError"
+                         "UnicodeDecodeError"
+                         "UnicodeEncodeError"
+                         "UnicodeTranslateError"
+                   "StopIteration"
+                   "Warning"
+                     "BytesWarning"
+                     "DeprecationWarning"
+                     "EncodingWarning"
+                     "FutureWarning"
+                     "ImportWarning"
+                     "PendingDeprecationWarning"
+                     "ResourceWarning"
+                     "RuntimeWarning"
+                     "SyntaxWarning"
+                     "UnicodeWarning"
+                     "UserWarning"
+                 "GeneratorExit"
+                 "KeyboardInterrupt"
+                 "SystemExit"
+
+               "abs" "absolute_import" "aiter"
+                 "all" "anext" "any" "apply" "ascii"
+               "basestring" "bin" "bool" "breakpoint"
+                 "buffer" "bytearray" "bytes"
+               "callable" "coerce" "chr" "classmethod"
+                 "cmp" "compile" "complex"
+               "delattr" "dict" "dir" "divmod"
+               "enumerate" "eval" "exec" "execfile"
+               "file" "filter" "float" "format" "frozenset"
+               "getattr" "globals"
+               "hasattr" "hash" "help" "hex"
+               "id" "input" "int" "intern"
+                 "isinstance" "issubclass" "iter"
+               "len" "list" "locals" "long"
+               "map" "max" "memoryview" "min"
+               "next"
+               "object" "oct" "open" "ord"
+               "pow" "print" "property"
+               "range" "raw_input" "reduce" "reload"
+                 "repr" "reversed" "round"
+               "set" "setattr" "slice" "sorted"
+                 "staticmethod" "str" "sum" "super"
+               "tuple" "type"
+               "unichr" "unicode"
+               "vars"
+               "xrange"
+               "zip"
+               "__import__")))
 
 (defun mdw-fontify-pyrex ()
   (mdw-fontify-pythonic
@@ -3034,15 +3632,17 @@ (defun mdw-fontify-pyrex ()
                "extern" "finally" "for" "from" "global" "if"
                "import" "in" "is" "lambda" "not" "or" "pass" "print"
                "property" "raise" "return" "struct" "try" "while" "with"
-               "yield")))
+               "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))
+       (append '(("\\.pyx$" . pyrex-mode)
+                 ("\\.pxd$" . pyrex-mode)
+                 ("\\.pxi$" . pyrex-mode))
+               auto-mode-alist))
 
 (progn
   (add-hook 'python-mode-hook 'mdw-misc-mode-config t)
@@ -3067,30 +3667,30 @@ (defun mdw-fontify-lua ()
                      "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))))))
+           (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))))))
 
 (progn
   (add-hook 'lua-mode-hook 'mdw-misc-mode-config t)
@@ -3125,36 +3725,247 @@ (defun mdw-fontify-icon ()
         (mdw-regexps "define" "else" "endif" "error" "ifdef" "ifndef"
                      "include" "line" "undef")))
     (setq font-lock-keywords
-         (list
+           (list
 
-          ;; Set up the keywords defined above.
-          (list (concat "\\<\\(" icon-keywords "\\)\\>")
-                '(0 font-lock-keyword-face))
+            ;; Set up the keywords defined above.
+            (list (concat "\\<\\(" icon-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
 
-          ;; The things that Icon calls keywords.
-          (list "&\\sw+\\>" '(0 font-lock-variable-name-face))
+            ;; The things that Icon calls keywords.
+            (list "&\\sw+\\>" '(0 font-lock-variable-name-face))
 
-          ;; At least numbers are simpler than C.
-          (list (concat "\\<[0-9]+"
-                        "\\([rR][0-9a-zA-Z]+\\|"
-                        "\\.[0-9]+\\([eE][+-]?[0-9]+\\)?\\)\\>\\|"
-                        "\\.[0-9]+\\([eE][+-]?[0-9]+\\)?\\>")
-                '(0 mdw-number-face))
+            ;; At least numbers are simpler than C.
+            (list (concat "\\<[0-9]+"
+                          "\\([rR][0-9a-zA-Z]+\\|"
+                          "\\.[0-9]+\\([eE][+-]?[0-9]+\\)?\\)\\>\\|"
+                          "\\.[0-9]+\\([eE][+-]?[0-9]+\\)?\\>")
+                  '(0 mdw-number-face))
 
-          ;; Preprocessor.
-          (list (concat "^[ \t]*$[ \t]*\\<\\("
-                        preprocessor-keywords
-                        "\\)\\>")
-                '(0 font-lock-keyword-face))
+            ;; Preprocessor.
+            (list (concat "^[ \t]*$[ \t]*\\<\\("
+                          preprocessor-keywords
+                          "\\)\\>")
+                  '(0 font-lock-keyword-face))
 
-          ;; And anything else is punctuation.
-          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face))))))
+            ;; And anything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))))
 
 (progn
   (add-hook 'icon-mode-hook 'mdw-misc-mode-config t)
   (add-hook 'icon-mode-hook 'mdw-fontify-icon t))
 
+;;;--------------------------------------------------------------------------
+;;; Fortran mode.
+
+(defun mdw-fontify-fortran-common ()
+  (let ((fortran-keywords
+        (mdw-regexps "access"
+                     "assign"
+                     "associate"
+                     "backspace"
+                     "blank"
+                     "block\\s-*data"
+                     "call"
+                     "case"
+                     "character"
+                     "class"
+                     "close"
+                     "common"
+                     "complex"
+                     "continue"
+                     "critical"
+                     "data"
+                     "dimension"
+                     "do"
+                     "double\\s-*precision"
+                     "else" "elseif" "elsewhere"
+                     "end"
+                       "endblock" "endblockdata"
+                       "endcritical"
+                       "enddo"
+                       "endinterface"
+                       "endmodule"
+                       "endprocedure"
+                       "endprogram"
+                       "endselect"
+                       "endsubmodule"
+                       "endsubroutine"
+                       "endtype"
+                       "endwhere"
+                       "endenum"
+                       "end\\s-*file"
+                       "endforall"
+                       "endfunction"
+                       "endif"
+                     "entry"
+                     "enum"
+                     "equivalence"
+                     "err"
+                     "external"
+                     "file"
+                     "fmt"
+                     "forall"
+                     "form"
+                     "format"
+                     "function"
+                     "go\\s-*to"
+                     "if"
+                     "implicit"
+                     "in" "inout"
+                     "inquire"
+                     "include"
+                     "integer"
+                     "interface"
+                     "intrinsic"
+                     "iostat"
+                     "len"
+                     "logical"
+                     "module"
+                     "open"
+                     "out"
+                     "parameter"
+                     "pause"
+                     "procedure"
+                     "program"
+                     "precision"
+                     "program"
+                     "read"
+                     "real"
+                     "rec"
+                     "recl"
+                     "return"
+                     "rewind"
+                     "save"
+                     "select" "selectcase" "selecttype"
+                     "status"
+                     "stop"
+                     "submodule"
+                     "subroutine"
+                     "then"
+                     "to"
+                     "type"
+                     "unit"
+                     "where"
+                     "write"))
+       (fortran-operators (mdw-regexps "and"
+                                       "eq"
+                                       "eqv"
+                                       "false"
+                                       "ge"
+                                       "gt"
+                                       "le"
+                                       "lt"
+                                       "ne"
+                                       "neqv"
+                                       "not"
+                                       "or"
+                                       "true"))
+       (fortran-intrinsics (mdw-regexps "abs" "dabs" "iabs" "cabs"
+                                        "atan" "datan" "atan2" "datan2"
+                                        "cmplx"
+                                        "conjg"
+                                        "cos" "dcos" "ccos"
+                                        "dble"
+                                        "dim" "idim"
+                                        "exp" "dexp" "cexp"
+                                        "float"
+                                        "ifix"
+                                        "aimag"
+                                        "int" "aint" "idint"
+                                        "alog" "dlog" "clog"
+                                        "alog10" "dlog10"
+                                        "max"
+                                        "amax0" "amax1"
+                                        "max0" "max1"
+                                        "dmax1"
+                                        "min"
+                                        "amin0" "amin1"
+                                        "min0" "min1"
+                                        "dmin1"
+                                        "mod" "amod" "dmod"
+                                        "sin" "dsin" "csin"
+                                        "sign" "isign" "dsign"
+                                        "sngl"
+                                        "sqrt" "dsqrt" "csqrt"
+                                        "tanh"))
+       (preprocessor-keywords
+        (mdw-regexps "assert" "define" "elif" "else" "endif" "error"
+                     "ident" "if" "ifdef" "ifndef" "import" "include"
+                     "line" "pragma" "unassert" "undef" "warning")))
+    (setq font-lock-keywords-case-fold-search t
+           font-lock-keywords
+           (list
+
+            ;; Fontify include files as strings.
+            (list (concat "^[ \t]*\\#[ \t]*" "include"
+                          "[ \t]*\\(<[^>]+>?\\)")
+                  '(1 font-lock-string-face))
+
+            ;; Preprocessor directives are `references'?.
+            (list (concat "^\\([ \t]*#[ \t]*\\(\\("
+                          preprocessor-keywords
+                          "\\)\\>\\|[0-9]+\\|$\\)\\)")
+                  '(1 font-lock-keyword-face))
+
+            ;; Set up the keywords defined above.
+            (list (concat "\\<\\(" fortran-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
+
+            ;; Set up the `.foo.' operators.
+            (list (concat "\\.\\(" fortran-operators "\\)\\.")
+                  '(0 font-lock-keyword-face))
+
+            ;; Set up the intrinsic functions.
+            (list (concat "\\<\\(" fortran-intrinsics "\\)\\>")
+                  '(0 font-lock-variable-name-face))
+
+            ;; Numbers.
+            (list (concat       "\\(" "\\<" "[0-9]+" "\\(\\.[0-9]*\\)?"
+                                "\\|" "\\.[0-9]+"
+                                "\\)"
+                                "\\(" "[de]" "[+-]?" "[0-9]+" "\\)?"
+                                "\\(" "_" "\\sw+" "\\)?"
+                          "\\|" "b'[01]*'" "\\|" "'[01]*'b"
+                          "\\|" "b\"[01]*\"" "\\|" "\"[01]*\"b"
+                          "\\|" "o'[0-7]*'" "\\|" "'[0-7]*'o"
+                          "\\|" "o\"[0-7]*\"" "\\|" "\"[0-7]*\"o"
+                          "\\|" "[xz]'[0-9a-f]*'" "\\|" "'[0-9a-f]*'[xz]"
+                          "\\|" "[xz]\"[0-9a-f]*\"" "\\|" "\"[0-9a-f]*\"[xz]")
+                  '(0 mdw-number-face))
+
+            ;; Any anything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))
+
+    (modify-syntax-entry ?/ "." font-lock-syntax-table)
+    (modify-syntax-entry ?< ".")
+    (modify-syntax-entry ?> ".")))
+
+(defun mdw-fontify-fortran () (mdw-fontify-fortran-common))
+(defun mdw-fontify-f90 () (mdw-fontify-fortran-common))
+
+(setq fortran-do-indent 2
+      fortran-if-indent 2
+      fortran-structure-indent 2
+      fortran-comment-line-start "*"
+      fortran-comment-indent-style 'relative
+      fortran-continuation-string "&"
+      fortran-continuation-indent 4)
+
+(setq f90-do-indent 2
+      f90-if-indent 2
+      f90-program-indent 2
+      f90-continuation-indent 4
+      f90-smart-end-names nil
+      f90-smart-end 'no-blink)
+
+(progn
+  (add-hook 'fortran-mode-hook 'mdw-misc-mode-config t)
+  (add-hook 'fortran-mode-hook 'mdw-fontify-fortran t)
+  (add-hook 'f90-mode-hook 'mdw-misc-mode-config t)
+  (add-hook 'f90-mode-hook 'mdw-fontify-f90 t))
+
 ;;;--------------------------------------------------------------------------
 ;;; Assembler mode.
 
@@ -3193,13 +4004,13 @@ (defun mdw-fontify-tcl ()
   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
   (make-local-variable 'font-lock-keywords)
   (setq font-lock-keywords
-       (list
-        (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
-                      "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
-                      "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
-              '(0 mdw-number-face))
-        (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-              '(0 mdw-punct-face)))))
+         (list
+          (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
+                        "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\)?"
+                        "\\([eE][-+]?[0-9_]+\\)?")
+                '(0 mdw-number-face))
+          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                '(0 mdw-punct-face)))))
 
 (progn
   (add-hook 'tcl-mode-hook 'mdw-misc-mode-config t)
@@ -3247,29 +4058,29 @@ (defun mdw-fontify-dylan ()
                          "all-keys" "key" "next" "rest" "include"
                          "t" "f")))
     (setq font-lock-keywords
-         (list (list (concat "\\<\\(" dylan-keywords
-                             "\\|" "with\\(out\\)?-" word
-                             "\\)\\>")
-                     '(0 font-lock-keyword-face))
-               (list (concat "\\<" word ":" "\\|"
-                             "#\\(" sharp-keywords "\\)\\>")
-                     '(0 font-lock-variable-name-face))
-               (list (concat "\\("
-                             "\\([-+]\\|\\<\\)[0-9]+" "\\("
-                               "\\(\\.[0-9]+\\)?" "\\([eE][-+][0-9]+\\)?"
-                               "\\|" "/[0-9]+"
-                             "\\)"
-                             "\\|" "\\.[0-9]+" "\\([eE][-+][0-9]+\\)?"
-                             "\\|" "#b[01]+"
-                             "\\|" "#o[0-7]+"
-                             "\\|" "#x[0-9a-zA-Z]+"
-                             "\\)\\>")
-                     '(0 mdw-number-face))
-               (list (concat "\\("
-                             "\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\|"
-                             "\\_<[-+*/=<>:&|]+\\_>"
-                             "\\)")
-                     '(0 mdw-punct-face))))))
+           (list (list (concat "\\<\\(" dylan-keywords
+                               "\\|" "with\\(out\\)?-" word
+                               "\\)\\>")
+                       '(0 font-lock-keyword-face))
+                 (list (concat "\\<" word ":" "\\|"
+                               "#\\(" sharp-keywords "\\)\\>")
+                       '(0 font-lock-variable-name-face))
+                 (list (concat "\\("
+                               "\\([-+]\\|\\<\\)[0-9]+" "\\("
+                                 "\\(\\.[0-9]+\\)?" "\\([eE][-+][0-9]+\\)?"
+                                 "\\|" "/[0-9]+"
+                               "\\)"
+                               "\\|" "\\.[0-9]+" "\\([eE][-+][0-9]+\\)?"
+                               "\\|" "#b[01]+"
+                               "\\|" "#o[0-7]+"
+                               "\\|" "#x[0-9a-zA-Z]+"
+                               "\\)\\>")
+                       '(0 mdw-number-face))
+                 (list (concat "\\("
+                               "\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\|"
+                               "\\_<[-+*/=<>:&|]+\\_>"
+                               "\\)")
+                       '(0 mdw-punct-face))))))
 
 (progn
   (add-hook 'dylan-mode-hook 'mdw-misc-mode-config t)
@@ -3291,31 +4102,31 @@ (defun mdw-fontify-algol-68 ()
 
   (let ((not-comment
         (let ((word "COMMENT"))
-          (do ((regexp (concat "[^" (substring word 0 1) "]+")
-                       (concat regexp "\\|"
-                               (substring word 0 i)
-                               "[^" (substring word i (1+ i)) "]"))
-               (i 1 (1+ i)))
+          (cl-do ((regexp (concat "[^" (substring word 0 1) "]+")
+                          (concat regexp "\\|"
+                                  (substring word 0 i)
+                                  "[^" (substring word i (1+ i)) "]"))
+                  (i 1 (1+ i)))
               ((>= i (length word)) regexp)))))
     (setq font-lock-keywords
-         (list (list (concat "\\<COMMENT\\>"
-                             "\\(" not-comment "\\)\\{0,5\\}"
-                             "\\(\\'\\|\\<COMMENT\\>\\)")
-                     '(0 font-lock-comment-face))
-               (list (concat "\\<CO\\>"
-                             "\\([^C]+\\|C[^O]\\)\\{0,5\\}"
-                             "\\($\\|\\<CO\\>\\)")
-                     '(0 font-lock-comment-face))
-               (list "\\<[A-Z_]+\\>"
-                     '(0 font-lock-keyword-face))
-               (list (concat "\\<"
-                             "[0-9]+"
-                             "\\(\\.[0-9]+\\)?"
-                             "\\([eE][-+]?[0-9]+\\)?"
-                             "\\>")
-                     '(0 mdw-number-face))
-               (list "\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/"
-                     '(0 mdw-punct-face))))))
+           (list (list (concat "\\<COMMENT\\>"
+                               "\\(" not-comment "\\)\\{0,5\\}"
+                               "\\(\\'\\|\\<COMMENT\\>\\)")
+                       '(0 font-lock-comment-face))
+                 (list (concat "\\<CO\\>"
+                               "\\([^C]+\\|C[^O]\\)\\{0,5\\}"
+                               "\\($\\|\\<CO\\>\\)")
+                       '(0 font-lock-comment-face))
+                 (list "\\<[A-Z_]+\\>"
+                       '(0 font-lock-keyword-face))
+                 (list (concat "\\<"
+                               "[0-9]+"
+                               "\\(\\.[0-9]+\\)?"
+                               "\\([eE][-+]?[0-9]+\\)?"
+                               "\\>")
+                       '(0 mdw-number-face))
+                 (list "\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/"
+                       '(0 mdw-punct-face))))))
 
 (dolist (hook '(a68-mode-hook a68-mode-hooks))
   (add-hook hook 'mdw-misc-mode-config t)
@@ -3379,20 +4190,20 @@ (defun mdw-fontify-rexx ()
                      "x2d")))
 
     (setq font-lock-keywords
-         (list
+           (list
 
-          ;; Set up the keywords defined above.
-          (list (concat "\\<\\(" rexx-keywords "\\)\\>")
-                '(0 font-lock-keyword-face))
+            ;; Set up the keywords defined above.
+            (list (concat "\\<\\(" rexx-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
 
-          ;; Fontify all symbols the same way.
-          (list (concat "\\<\\([0-9.][A-Za-z0-9.!?_#@$]*[Ee][+-]?[0-9]+\\|"
-                        "[A-Za-z0-9.!?_#@$]+\\)")
-                '(0 font-lock-variable-name-face))
+            ;; Fontify all symbols the same way.
+            (list (concat "\\<\\([0-9.][A-Za-z0-9.!?_#@$]*[Ee][+-]?[0-9]+\\|"
+                          "[A-Za-z0-9.!?_#@$]+\\)")
+                  '(0 font-lock-variable-name-face))
 
-          ;; And everything else is punctuation.
-          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face))))))
+            ;; And everything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))))
 
 (progn
   (add-hook 'rexx-mode-hook 'mdw-misc-mode-config t)
@@ -3434,24 +4245,24 @@ (defun mdw-fontify-sml ()
                      "where" "while" "with" "withtype")))
 
     (setq font-lock-keywords
-         (list
+           (list
 
-          ;; Set up the keywords defined above.
-          (list (concat "\\<\\(" sml-keywords "\\)\\>")
-                '(0 font-lock-keyword-face))
+            ;; Set up the keywords defined above.
+            (list (concat "\\<\\(" sml-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
 
-          ;; At least numbers are simpler than C.
-          (list (concat "\\<\\(\\~\\|\\)"
-                           "\\(0\\(\\([wW]\\|\\)[xX][0-9a-fA-F]+\\|"
-                                  "[wW][0-9]+\\)\\|"
-                               "\\([0-9]+\\(\\.[0-9]+\\|\\)"
-                                        "\\([eE]\\(\\~\\|\\)"
-                                               "[0-9]+\\|\\)\\)\\)")
-                '(0 mdw-number-face))
+            ;; At least numbers are simpler than C.
+            (list (concat "\\<\\~?"
+                             "\\(0\\([wW]?[xX][0-9a-fA-F]+\\|"
+                                    "[wW][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))))))
+            ;; And anything else is punctuation.
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))))
 
 (progn
   (add-hook 'sml-mode-hook 'mdw-misc-mode-config t)
@@ -3461,6 +4272,8 @@ (progn
 ;;; Haskell configuration.
 
 (setq-default haskell-indent-offset 2)
+(setq haskell-doc-prettify-types nil
+      haskell-interactive-popup-errors nil)
 
 (defun mdw-fontify-haskell ()
 
@@ -3471,7 +4284,7 @@ (defun mdw-fontify-haskell ()
 
   ;; Make punctuation be punctuation
   (let ((punct "=<>+-*/|&%!@?$.^:#`"))
-    (do ((i 0 (1+ i)))
+    (cl-do ((i 0 (1+ i)))
        ((>= i (length punct)))
       (modify-syntax-entry (aref punct i) ".")))
 
@@ -3506,36 +4319,36 @@ (defun mdw-fontify-haskell ()
                      "SP" "STX" "SUB" "SYN" "US" "VT")))
 
     (setq font-lock-keywords
-         (list
-          (list (concat "{-" "[^-]*" "\\(-+[^-}][^-]*\\)*"
-                             "\\(-+}\\|-*\\'\\)"
-                        "\\|"
-                        "--.*$")
-                '(0 font-lock-comment-face))
-          (list (concat "\\_<\\(" haskell-keywords "\\)\\_>")
-                '(0 font-lock-keyword-face))
-          (list (concat "'\\("
-                        "[^\\]"
-                        "\\|"
-                        "\\\\"
-                        "\\(" "[abfnrtv\\\"']" "\\|"
-                              "^" "\\(" control-sequences "\\|"
-                                        "[]A-Z@[\\^_]" "\\)" "\\|"
-                              "\\|"
-                              "[0-9]+" "\\|"
-                              "[oO][0-7]+" "\\|"
-                              "[xX][0-9A-Fa-f]+"
-                        "\\)"
-                        "\\)'")
-                '(0 font-lock-string-face))
-          (list "\\_<[A-Z]\\(\\sw+\\|\\s_+\\)*\\_>"
-                '(0 font-lock-variable-name-face))
-          (list (concat "\\_<0\\([xX][0-9a-fA-F]+\\|[oO][0-7]+\\)\\|"
-                        "\\_<[0-9]+\\(\\.[0-9]*\\|\\)"
-                        "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)")
-                '(0 mdw-number-face))
-          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face))))))
+           (list
+            (list (concat "{-" "[^-]*" "\\(-+[^-}][^-]*\\)*"
+                               "\\(-+}\\|-*\\'\\)"
+                          "\\|"
+                          "--.*$")
+                  '(0 font-lock-comment-face))
+            (list (concat "\\_<\\(" haskell-keywords "\\)\\_>")
+                  '(0 font-lock-keyword-face))
+            (list (concat "'\\("
+                          "[^\\]"
+                          "\\|"
+                          "\\\\"
+                          "\\(" "[abfnrtv\\\"']" "\\|"
+                                "^" "\\(" control-sequences "\\|"
+                                          "[]A-Z@[\\^_]" "\\)" "\\|"
+                                "\\|"
+                                "[0-9]+" "\\|"
+                                "[oO][0-7]+" "\\|"
+                                "[xX][0-9A-Fa-f]+"
+                          "\\)"
+                          "\\)'")
+                  '(0 font-lock-string-face))
+            (list "\\_<[A-Z]\\(\\sw+\\|\\s_+\\)*\\_>"
+                  '(0 font-lock-variable-name-face))
+            (list (concat "\\_<0\\([xX][0-9a-fA-F]+\\|[oO][0-7]+\\)\\|"
+                          "\\_<[0-9]+\\(\\.[0-9]*\\)?"
+                          "\\([eE][-+]?[0-9]+\\)?")
+                  '(0 mdw-number-face))
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))))
 
 (progn
   (add-hook 'haskell-mode-hook 'mdw-misc-mode-config t)
@@ -3562,17 +4375,17 @@ (defun mdw-fontify-erlang ()
                      "query" "receive" "rem" "try" "when" "xor")))
 
     (setq font-lock-keywords
-         (list
-          (list "%.*$"
-                '(0 font-lock-comment-face))
-          (list (concat "\\<\\(" erlang-keywords "\\)\\>")
-                '(0 font-lock-keyword-face))
-          (list (concat "^-\\sw+\\>")
-                '(0 font-lock-keyword-face))
-          (list "\\<[0-9]+\\(\\|#[0-9a-zA-Z]+\\|[eE][+-]?[0-9]+\\)\\>"
-                '(0 mdw-number-face))
-          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                '(0 mdw-punct-face))))))
+           (list
+            (list "%.*$"
+                  '(0 font-lock-comment-face))
+            (list (concat "\\<\\(" erlang-keywords "\\)\\>")
+                  '(0 font-lock-keyword-face))
+            (list (concat "^-\\sw+\\>")
+                  '(0 font-lock-keyword-face))
+            (list "\\<[0-9]+\\(#[0-9a-zA-Z]+\\|[eE][+-]?[0-9]+\\)?\\>"
+                  '(0 mdw-number-face))
+            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                  '(0 mdw-punct-face))))))
 
 (progn
   (add-hook 'erlang-mode-hook 'mdw-misc-mode-config t)
@@ -3589,28 +4402,28 @@ (defun mdw-fontify-texinfo ()
   ;; Real fontification things.
   (make-local-variable 'font-lock-keywords)
   (setq font-lock-keywords
-       (list
+         (list
 
-        ;; Environment names are keywords.
-        (list "@\\(end\\)  *\\([a-zA-Z]*\\)?"
-              '(2 font-lock-keyword-face))
+          ;; Environment names are keywords.
+          (list "@\\(end\\)  *\\([a-zA-Z]*\\)?"
+                '(2 font-lock-keyword-face))
 
-        ;; Unmark escaped magic characters.
-        (list "\\(@\\)\\([@{}]\\)"
-              '(1 font-lock-keyword-face)
-              '(2 font-lock-variable-name-face))
+          ;; Unmark escaped magic characters.
+          (list "\\(@\\)\\([@{}]\\)"
+                '(1 font-lock-keyword-face)
+                '(2 font-lock-variable-name-face))
 
-        ;; Make sure we get comments properly.
-        (list "@c\\(\\|omment\\)\\( .*\\)?$"
-              '(0 font-lock-comment-face))
+          ;; Make sure we get comments properly.
+          (list "@c\\(omment\\)?\\( .*\\)?$"
+                '(0 font-lock-comment-face))
 
-        ;; Command names are keywords.
-        (list "@\\([^a-zA-Z@]\\|[a-zA-Z@]*\\)"
-              '(0 font-lock-keyword-face))
+          ;; Command names are keywords.
+          (list "@\\([^a-zA-Z@]\\|[a-zA-Z@]*\\)"
+                '(0 font-lock-keyword-face))
 
-        ;; Fontify TeX special characters as punctuation.
-        (list "[{}]+"
-              '(0 mdw-punct-face)))))
+          ;; Fontify TeX special characters as punctuation.
+          (list "[{}]+"
+                '(0 mdw-punct-face)))))
 
 (dolist (hook '(texinfo-mode-hook TeXinfo-mode-hook))
   (add-hook hook 'mdw-misc-mode-config t)
@@ -3643,53 +4456,53 @@ (defun mdw-fontify-tex ()
   ;; Real fontification things.
   (make-local-variable 'font-lock-keywords)
   (setq font-lock-keywords
-       (list
-
-        ;; Environment names are keywords.
-        (list (concat "\\\\\\(begin\\|end\\|newenvironment\\)"
-                      "{\\([^}\n]*\\)}")
-              '(2 font-lock-keyword-face))
-
-        ;; Suspended environment names are keywords too.
-        (list (concat "\\\\\\(suspend\\|resume\\)\\(\\[[^]]*\\]\\)?"
-                      "{\\([^}\n]*\\)}")
-              '(3 font-lock-keyword-face))
-
-        ;; Command names are keywords.
-        (list "\\\\\\([^a-zA-Z@]\\|[a-zA-Z@]*\\)"
-              '(0 font-lock-keyword-face))
-
-        ;; Handle @/.../ for italics.
-        ;; (list "\\(@/\\)\\([^/]*\\)\\(/\\)"
-        ;;       '(1 font-lock-keyword-face)
-        ;;       '(3 font-lock-keyword-face))
-
-        ;; Handle @*...* for boldness.
-        ;; (list "\\(@\\*\\)\\([^*]*\\)\\(\\*\\)"
-        ;;       '(1 font-lock-keyword-face)
-        ;;       '(3 font-lock-keyword-face))
-
-        ;; Handle @`...' for literal syntax things.
-        ;; (list "\\(@`\\)\\([^']*\\)\\('\\)"
-        ;;       '(1 font-lock-keyword-face)
-        ;;       '(3 font-lock-keyword-face))
-
-        ;; Handle @<...> for nonterminals.
-        ;; (list "\\(@<\\)\\([^>]*\\)\\(>\\)"
-        ;;       '(1 font-lock-keyword-face)
-        ;;       '(3 font-lock-keyword-face))
-
-        ;; Handle other @-commands.
-        ;; (list "@\\([^a-zA-Z]\\|[a-zA-Z]*\\)"
-        ;;       '(0 font-lock-keyword-face))
-
-        ;; Make sure we get comments properly.
-        (list "%.*"
-              '(0 font-lock-comment-face))
-
-        ;; Fontify TeX special characters as punctuation.
-        (list "[$^_{}#&]"
-              '(0 mdw-punct-face)))))
+         (list
+
+          ;; Environment names are keywords.
+          (list (concat "\\\\\\(begin\\|end\\|newenvironment\\)"
+                        "{\\([^}\n]*\\)}")
+                '(2 font-lock-keyword-face))
+
+          ;; Suspended environment names are keywords too.
+          (list (concat "\\\\\\(suspend\\|resume\\)\\(\\[[^]]*\\]\\)?"
+                        "{\\([^}\n]*\\)}")
+                '(3 font-lock-keyword-face))
+
+          ;; Command names are keywords.
+          (list "\\\\\\([^a-zA-Z@]\\|[a-zA-Z@]*\\)"
+                '(0 font-lock-keyword-face))
+
+          ;; Handle @/.../ for italics.
+          ;; (list "\\(@/\\)\\([^/]*\\)\\(/\\)"
+          ;;     '(1 font-lock-keyword-face)
+          ;;     '(3 font-lock-keyword-face))
+
+          ;; Handle @*...* for boldness.
+          ;; (list "\\(@\\*\\)\\([^*]*\\)\\(\\*\\)"
+          ;;     '(1 font-lock-keyword-face)
+          ;;     '(3 font-lock-keyword-face))
+
+          ;; Handle @`...' for literal syntax things.
+          ;; (list "\\(@`\\)\\([^']*\\)\\('\\)"
+          ;;     '(1 font-lock-keyword-face)
+          ;;     '(3 font-lock-keyword-face))
+
+          ;; Handle @<...> for nonterminals.
+          ;; (list "\\(@<\\)\\([^>]*\\)\\(>\\)"
+          ;;     '(1 font-lock-keyword-face)
+          ;;     '(3 font-lock-keyword-face))
+
+          ;; Handle other @-commands.
+          ;; (list "@\\([^a-zA-Z]\\|[a-zA-Z]*\\)"
+          ;;     '(0 font-lock-keyword-face))
+
+          ;; Make sure we get comments properly.
+          (list "%.*"
+                '(0 font-lock-comment-face))
+
+          ;; Fontify TeX special characters as punctuation.
+          (list "[$^_{}#&]"
+                '(0 mdw-punct-face)))))
 
 (setq TeX-install-font-lock 'tex-font-setup)
 
@@ -3713,36 +4526,36 @@ (eval-after-load 'font-latex
             (restore-buffer-modified-p nil)))))))
 
 (setq TeX-output-view-style
-      '(("^dvi$"
-        ("^landscape$" "^pstricks$\\|^pst-\\|^psfrag$")
-        "%(o?)dvips -t landscape %d -o && xdg-open %f")
-       ("^dvi$" "^pstricks$\\|^pst-\\|^psfrag$"
-        "%(o?)dvips %d -o && xdg-open %f")
-       ("^dvi$"
-        ("^a4\\(?:dutch\\|paper\\|wide\\)\\|sem-a4$" "^landscape$")
-        "%(o?)xdvi %dS -paper a4r -s 0 %d")
-       ("^dvi$" "^a4\\(?:dutch\\|paper\\|wide\\)\\|sem-a4$"
-        "%(o?)xdvi %dS -paper a4 %d")
-       ("^dvi$"
-        ("^a5\\(?:comb\\|paper\\)$" "^landscape$")
-        "%(o?)xdvi %dS -paper a5r -s 0 %d")
-       ("^dvi$" "^a5\\(?:comb\\|paper\\)$" "%(o?)xdvi %dS -paper a5 %d")
-       ("^dvi$" "^b5paper$" "%(o?)xdvi %dS -paper b5 %d")
-       ("^dvi$" "^letterpaper$" "%(o?)xdvi %dS -paper us %d")
-       ("^dvi$" "^legalpaper$" "%(o?)xdvi %dS -paper legal %d")
-       ("^dvi$" "^executivepaper$" "%(o?)xdvi %dS -paper 7.25x10.5in %d")
-       ("^dvi$" "." "%(o?)xdvi %dS %d")
-       ("^pdf$" "." "xdg-open %o")
-       ("^html?$" "." "sensible-browser %o")))
+       '(("^dvi$"
+          ("^landscape$" "^pstricks$\\|^pst-\\|^psfrag$")
+          "%(o?)dvips -t landscape %d -o && xdg-open %f")
+         ("^dvi$" "^pstricks$\\|^pst-\\|^psfrag$"
+          "%(o?)dvips %d -o && xdg-open %f")
+         ("^dvi$"
+          ("^a4\\(?:dutch\\|paper\\|wide\\)\\|sem-a4$" "^landscape$")
+          "%(o?)xdvi %dS -paper a4r -s 0 %d")
+         ("^dvi$" "^a4\\(?:dutch\\|paper\\|wide\\)\\|sem-a4$"
+          "%(o?)xdvi %dS -paper a4 %d")
+         ("^dvi$"
+          ("^a5\\(?:comb\\|paper\\)$" "^landscape$")
+          "%(o?)xdvi %dS -paper a5r -s 0 %d")
+         ("^dvi$" "^a5\\(?:comb\\|paper\\)$" "%(o?)xdvi %dS -paper a5 %d")
+         ("^dvi$" "^b5paper$" "%(o?)xdvi %dS -paper b5 %d")
+         ("^dvi$" "^letterpaper$" "%(o?)xdvi %dS -paper us %d")
+         ("^dvi$" "^legalpaper$" "%(o?)xdvi %dS -paper legal %d")
+         ("^dvi$" "^executivepaper$" "%(o?)xdvi %dS -paper 7.25x10.5in %d")
+         ("^dvi$" "." "%(o?)xdvi %dS %d")
+         ("^pdf$" "." "xdg-open %o")
+         ("^html?$" "." "sensible-browser %o")))
 
 (setq TeX-view-program-list
-      '(("mupdf" ("mupdf %o" (mode-io-correlate " %(outpage)")))))
+       '(("mupdf" ("mupdf %o" (mode-io-correlate " %(outpage)")))))
 
 (setq TeX-view-program-selection
-      '(((output-dvi style-pstricks) "dvips and gv")
-       (output-dvi "xdvi")
-       (output-pdf "mupdf")
-       (output-html "sensible-browser")))
+       '(((output-dvi style-pstricks) "dvips and gv")
+         (output-dvi "xdvi")
+         (output-pdf "mupdf")
+         (output-html "sensible-browser")))
 
 (setq TeX-open-quote "\""
       TeX-close-quote "\"")
@@ -3751,19 +4564,19 @@ (setq reftex-use-external-file-finders t
       reftex-auto-recenter-toc t)
 
 (setq reftex-label-alist
-      '(("theorem" ?T "th:" "~\\ref{%s}" t ("theorems?" "th\\.") -2)
-       ("axiom" ?A "ax:" "~\\ref{%s}" t ("axioms?" "ax\\.") -2)
-       ("definition" ?D "def:" "~\\ref{%s}" t ("definitions?" "def\\.") -2)
-       ("proposition" ?P "prop:" "~\\ref{%s}" t
-        ("propositions?" "prop\\.") -2)
-       ("lemma" ?L "lem:" "~\\ref{%s}" t ("lemmas?" "lem\\.") -2)
-       ("example" ?X "eg:" "~\\ref{%s}" t ("examples?") -2)
-       ("exercise" ?E "ex:" "~\\ref{%s}" t ("exercises?" "ex\\.") -2)
-       ("enumerate" ?i "i:" "~\\ref{%s}" item ("items?"))))
+       '(("theorem" ?T "th:" "~\\ref{%s}" t ("theorems?" "th\\.") -2)
+         ("axiom" ?A "ax:" "~\\ref{%s}" t ("axioms?" "ax\\.") -2)
+         ("definition" ?D "def:" "~\\ref{%s}" t ("definitions?" "def\\.") -2)
+         ("proposition" ?P "prop:" "~\\ref{%s}" t
+          ("propositions?" "prop\\.") -2)
+         ("lemma" ?L "lem:" "~\\ref{%s}" t ("lemmas?" "lem\\.") -2)
+         ("example" ?X "eg:" "~\\ref{%s}" t ("examples?") -2)
+         ("exercise" ?E "ex:" "~\\ref{%s}" t ("exercises?" "ex\\.") -2)
+         ("enumerate" ?i "i:" "~\\ref{%s}" item ("items?"))))
 (setq reftex-section-prefixes
-      '((0 . "part:")
-       (1 . "ch:")
-       (t . "sec:")))
+       '((0 . "part:")
+         (1 . "ch:")
+         (t . "sec:")))
 
 (setq bibtex-field-delimiters 'double-quotes
       bibtex-align-at-equal-sign t
@@ -3791,7 +4604,7 @@ (progn
 ;;;--------------------------------------------------------------------------
 ;;; HTML, CSS, and other web foolishness.
 
-(setq-default css-indent-offset 2)
+(setq-default css-indent-offset 8)
 
 ;;;--------------------------------------------------------------------------
 ;;; SGML hacking.
@@ -3804,14 +4617,14 @@ (defun mdw-sgml-mode ()
   (mdw-standard-fill-prefix "")
   (make-local-variable 'sgml-delimiters)
   (setq sgml-delimiters
-       '("AND" "&" "COM" "--" "CRO" "&#" "DSC" "]" "DSO" "[" "DTGC" "]"
-         "DTGO" "[" "ERO" "&" "ETAGO" ":e" "GRPC" ")" "GRPO" "(" "LIT" "\""
-         "LITA" "'" "MDC" ">" "MDO" "<!" "MINUS" "-" "MSC" "]]" "NESTC" "{"
-         "NET" "}" "OPT" "?" "OR" "|" "PERO" "%" "PIC" ">" "PIO" "<?"
-         "PLUS" "+" "REFC" "." "REP" "*" "RNI" "#" "SEQ" "," "STAGO" ":"
-         "TAGC" "." "VI" "=" "MS-START" "<![" "MS-END" "]]>"
-         "XML-ECOM" "-->" "XML-PIC" "?>" "XML-SCOM" "<!--" "XML-TAGCE" "/>"
-         "NULL" ""))
+         '("AND" "&" "COM" "--" "CRO" "&#" "DSC" "]" "DSO" "[" "DTGC" "]"
+           "DTGO" "[" "ERO" "&" "ETAGO" ":e" "GRPC" ")" "GRPO" "(" "LIT"
+           "\"" "LITA" "'" "MDC" ">" "MDO" "<!" "MINUS" "-" "MSC" "]]"
+           "NESTC" "{" "NET" "}" "OPT" "?" "OR" "|" "PERO" "%" "PIC" ">"
+           "PIO" "<?" "PLUS" "+" "REFC" "." "REP" "*" "RNI" "#" "SEQ" ","
+           "STAGO" ":" "TAGC" "." "VI" "=" "MS-START" "<![" "MS-END" "]]>"
+           "XML-ECOM" "-->" "XML-PIC" "?>" "XML-SCOM" "<!--" "XML-TAGCE"
+           "/>" "NULL" ""))
   (setq major-mode 'mdw-sgml-mode)
   (setq mode-name "[mdw] SGML")
   (run-hooks 'mdw-sgml-mode-hook))
@@ -3819,21 +4632,21 @@ (defun mdw-sgml-mode ()
 ;;;--------------------------------------------------------------------------
 ;;; Configuration files.
 
-(defvar mdw-conf-quote-normal nil
-  "*Control syntax category of quote characters `\"' and `''.
+(defcustom mdw-conf-quote-normal nil
+  "Control syntax category of quote characters `\"' and `''.
 If this is `t', consider quote characters to be normal
 punctuation, as for `conf-quote-normal'.  If this is `nil' then
 leave quote characters as quotes.  If this is a list, then
 consider the quote characters in the list to be normal
 punctuation.  If this is a single quote character, then consider
-that character only to be normal punctuation.")
+that character only to be normal punctuation."
+  :type '(choice boolean character (repeat character))
+  :safe 'mdw-conf-quote-normal-acceptable-value-p)
 (defun mdw-conf-quote-normal-acceptable-value-p (value)
   "Is the VALUE is an acceptable value for `mdw-conf-quote-normal'?"
   (or (booleanp value)
-      (every (lambda (v) (memq v '(?\" ?')))
-            (if (listp value) value (list value)))))
-(put 'mdw-conf-quote-normal 'safe-local-variable
-     'mdw-conf-quote-normal-acceptable-value-p)
+      (cl-every (lambda (v) (memq v '(?\" ?')))
+               (if (listp value) value (list value)))))
 
 (defun mdw-fix-up-quote ()
   "Apply the setting of `mdw-conf-quote-normal'."
@@ -3918,8 +4731,8 @@ (eval-after-load "sh-script"
         (if assoc
             (rplacd assoc frag)
           (setq sh-mode-syntax-table-input
-                (cons (cons 'rc frag)
-                      sh-mode-syntax-table-input))))))
+                  (cons (cons 'rc frag)
+                        sh-mode-syntax-table-input))))))
 
 (progn
   (add-hook 'sh-mode-hook 'mdw-misc-mode-config t)
@@ -3997,17 +4810,17 @@ (defun messages-mode-guts ()
                      "set" "table" "tagged-optional"   "union"
                      "variadic" "vector" "version" "version-tag")))
     (setq messages-mode-keywords
-         (list
-          (list (concat "\\<\\(" keywords "\\)\\>:")
-                '(0 font-lock-keyword-face))
-          '("\\([-a-zA-Z0-9]+:\\)" (0 font-lock-warning-face))
-          '("\\(\\<[a-z][-_a-zA-Z0-9]*\\)"
-            (0 font-lock-variable-name-face))
-          '("\\<\\([0-9]+\\)\\>" (0 mdw-number-face))
-          '("\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-            (0 mdw-punct-face)))))
+           (list
+            (list (concat "\\<\\(" keywords "\\)\\>:")
+                  '(0 font-lock-keyword-face))
+            '("\\([-a-zA-Z0-9]+:\\)" (0 font-lock-warning-face))
+            '("\\(\\<[a-z][-_a-zA-Z0-9]*\\)"
+              (0 font-lock-variable-name-face))
+            '("\\<\\([0-9]+\\)\\>" (0 mdw-number-face))
+            '("\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+              (0 mdw-punct-face)))))
   (setq font-lock-defaults
-       '(messages-mode-keywords nil nil nil nil))
+         '(messages-mode-keywords nil nil nil nil))
   (run-hooks 'messages-file-hook))
 
 (defun messages-mode ()
@@ -4037,15 +4850,15 @@ (defun cpp-messages-mode ()
                      "ident" "if" "ifdef" "ifndef" "import" "include"
                      "line" "pragma" "unassert" "undef" "warning")))
     (setq messages-mode-keywords
-         (append (list (list (concat "^[ \t]*\\#[ \t]*"
-                                     "\\(include\\|import\\)"
-                                     "[ \t]*\\(<[^>]+\\(>\\|\\)\\)")
-                             '(2 font-lock-string-face))
-                       (list (concat "^\\([ \t]*#[ \t]*\\(\\("
-                                     preprocessor-keywords
-                                     "\\)\\>\\|[0-9]+\\|$\\)\\)")
-                             '(1 font-lock-keyword-face)))
-                 messages-mode-keywords)))
+           (append (list (list (concat "^[ \t]*\\#[ \t]*"
+                                       "\\(include\\|import\\)"
+                                       "[ \t]*\\(<[^>]+\\(>\\)?\\)")
+                               '(2 font-lock-string-face))
+                         (list (concat "^\\([ \t]*#[ \t]*\\(\\("
+                                       preprocessor-keywords
+                                       "\\)\\>\\|[0-9]+\\|$\\)\\)")
+                               '(1 font-lock-keyword-face)))
+                   messages-mode-keywords)))
   (run-hooks 'cpp-messages-mode-hook))
 
 (progn
@@ -4082,16 +4895,16 @@ (defun mallow-driver-mode ()
         (mdw-regexps "each" "divert" "file" "if"
                      "perl" "set" "string" "type" "write")))
     (setq mallow-driver-mode-keywords
-         (list
-          (list (concat "^%\\s *\\(}\\|\\(" keywords "\\)\\>\\).*$")
-                '(0 font-lock-keyword-face))
-          (list "^%\\s *\\(#.*\\|\\)$"
-                '(0 font-lock-comment-face))
-          (list "^%"
-                '(0 font-lock-keyword-face))
-          (list "^|?\\(.+\\)$" '(1 mallow-driver-text-face))
-          (list "\\${[^}]*}"
-                '(0 mallow-driver-substitution-face t)))))
+           (list
+            (list (concat "^%\\s *\\(}\\|\\(" keywords "\\)\\>\\).*$")
+                  '(0 font-lock-keyword-face))
+            (list "^%\\s *\\(#.*\\)?$"
+                  '(0 font-lock-comment-face))
+            (list "^%"
+                  '(0 font-lock-keyword-face))
+            (list "^|?\\(.+\\)$" '(1 mallow-driver-text-face))
+            (list "\\${[^}]*}"
+                  '(0 mallow-driver-substitution-face t)))))
   (setq font-lock-defaults
        '(mallow-driver-mode-keywords nil nil nil nil))
   (modify-syntax-entry ?\" "_" mallow-driver-mode-syntax-table)
@@ -4117,30 +4930,30 @@ (defun nfast-debug-mode ()
   (make-local-variable 'nfast-debug-mode-keywords)
   (setq truncate-lines t)
   (setq nfast-debug-mode-keywords
-       (list
-        '("^\\(NFast_\\(Connect\\|Disconnect\\|Submit\\|Wait\\)\\)"
-          (0 font-lock-keyword-face))
-        (list (concat "^[ \t]+\\(\\("
-                      "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]"
-                      "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]"
-                      "[ \t]+\\)*"
-                      "[0-9a-fA-F]+\\)[ \t]*$")
-          '(0 mdw-number-face))
-        '("^[ \t]+\.status=[ \t]+\\<\\(OK\\)\\>"
-          (1 font-lock-keyword-face))
-        '("^[ \t]+\.status=[ \t]+\\<\\([a-zA-Z][0-9a-zA-Z]*\\)\\>"
-          (1 font-lock-warning-face))
-        '("^[ \t]+\.status[ \t]+\\<\\(zero\\)\\>"
-          (1 nil))
-        (list (concat "^[ \t]+\\.cmd=[ \t]+"
-                      "\\<\\([a-zA-Z][0-9a-zA-Z]*\\)\\>")
-          '(1 font-lock-keyword-face))
-        '("-?\\<\\([0-9]+\\|0x[0-9a-fA-F]+\\)\\>" (0 mdw-number-face))
-        '("^\\([ \t]+[a-z0-9.]+\\)" (0 font-lock-variable-name-face))
-        '("\\<\\([a-z][a-z0-9.]+\\)\\>=" (1 font-lock-variable-name-face))
-        '("\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)" (0 mdw-punct-face))))
+         (list
+          '("^\\(NFast_\\(Connect\\|Disconnect\\|Submit\\|Wait\\)\\)"
+            (0 font-lock-keyword-face))
+          (list (concat "^[ \t]+\\(\\("
+                        "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]"
+                        "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]"
+                        "[ \t]+\\)*"
+                        "[0-9a-fA-F]+\\)[ \t]*$")
+                '(0 mdw-number-face))
+          '("^[ \t]+\.status=[ \t]+\\<\\(OK\\)\\>"
+            (1 font-lock-keyword-face))
+          '("^[ \t]+\.status=[ \t]+\\<\\([a-zA-Z][0-9a-zA-Z]*\\)\\>"
+            (1 font-lock-warning-face))
+          '("^[ \t]+\.status[ \t]+\\<\\(zero\\)\\>"
+            (1 nil))
+          (list (concat "^[ \t]+\\.cmd=[ \t]+"
+                        "\\<\\([a-zA-Z][0-9a-zA-Z]*\\)\\>")
+                '(1 font-lock-keyword-face))
+          '("-?\\<\\([0-9]+\\|0x[0-9a-fA-F]+\\)\\>" (0 mdw-number-face))
+          '("^\\([ \t]+[a-z0-9.]+\\)" (0 font-lock-variable-name-face))
+          '("\\<\\([a-z][a-z0-9.]+\\)\\>=" (1 font-lock-variable-name-face))
+          '("\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)" (0 mdw-punct-face))))
   (setq font-lock-defaults
-       '(nfast-debug-mode-keywords nil nil nil nil))
+         '(nfast-debug-mode-keywords nil nil nil nil))
   (run-hooks 'nfast-debug-mode-hook))
 
 ;;;--------------------------------------------------------------------------
@@ -4168,10 +4981,6 @@ (defun mdw-common-lisp-indent ()
   (make-local-variable 'lisp-indent-function)
   (setq lisp-indent-function 'common-lisp-indent-function))
 
-(setq-default lisp-simple-loop-indentation 2
-             lisp-loop-keyword-indentation 6
-             lisp-loop-forms-indentation 6)
-
 (defmacro mdw-advise-hyperspec-lookup (func args)
   `(defadvice ,func (around mdw-browse-w3m ,args activate compile)
      (if (fboundp 'w3m)
@@ -4189,35 +4998,181 @@ (defun mdw-fontify-lispy ()
 
   ;; Not much fontification needed.
   (make-local-variable 'font-lock-keywords)
-  (setq font-lock-keywords
-       (list (list (concat "\\("
-                           "\\_<[-+]?"
-                           "\\(" "[0-9]+/[0-9]+"
-                           "\\|" "\\(" "[0-9]+" "\\(\\.[0-9]*\\)?" "\\|"
-                                       "\\.[0-9]+" "\\)"
-                                 "\\([dDeEfFlLsS][-+]?[0-9]+\\)?"
-                           "\\)"
-                           "\\|"
-                           "#"
-                           "\\(" "x" "[-+]?"
-                                 "[0-9A-Fa-f]+" "\\(/[0-9A-Fa-f]+\\)?"
-                           "\\|" "o" "[-+]?" "[0-7]+" "\\(/[0-7]+\\)?"
-                           "\\|" "b" "[-+]?" "[01]+" "\\(/[01]+\\)?"
-                           "\\|" "[0-9]+" "r" "[-+]?"
-                                 "[0-9a-zA-Z]+" "\\(/[0-9a-zA-Z]+\\)?"
-                           "\\)"
-                           "\\)\\_>")
-                   '(0 mdw-number-face))
-             (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-                   '(0 mdw-punct-face)))))
+    (setq font-lock-keywords
+         (list (list (concat "\\("
+                             "\\_<[-+]?"
+                             "\\(" "[0-9]+/[0-9]+"
+                             "\\|" "\\(" "[0-9]+" "\\(\\.[0-9]*\\)?" "\\|"
+                                         "\\.[0-9]+" "\\)"
+                                   "\\([dDeEfFlLsS][-+]?[0-9]+\\)?"
+                             "\\)"
+                             "\\|"
+                             "#"
+                             "\\(" "x" "[-+]?"
+                                   "[0-9A-Fa-f]+" "\\(/[0-9A-Fa-f]+\\)?"
+                             "\\|" "o" "[-+]?" "[0-7]+" "\\(/[0-7]+\\)?"
+                             "\\|" "b" "[-+]?" "[01]+" "\\(/[01]+\\)?"
+                             "\\|" "[0-9]+" "r" "[-+]?"
+                                   "[0-9a-zA-Z]+" "\\(/[0-9a-zA-Z]+\\)?"
+                             "\\)"
+                             "\\)\\_>")
+                     '(0 mdw-number-face))
+               (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                     '(0 mdw-punct-face)))))
+
+;; Special indentation.
+
+(defcustom mdw-lisp-loop-default-indent 2
+  "Default indent for simple `loop' body."
+  :type 'integer
+  :safe 'integerp)
+(defcustom mdw-lisp-setf-value-indent 2
+  "Default extra indent for `setf' values."
+  :type 'integer :safe 'integerp)
+
+(setq lisp-simple-loop-indentation 0
+      lisp-loop-keyword-indentation 0
+      lisp-loop-forms-indentation 2
+      lisp-lambda-list-keyword-parameter-alignment t)
+
+(defun mdw-indent-funcall
+    (path state &optional indent-point sexp-column normal-indent)
+  "Indent `funcall' more usefully.
+Essentially, treat `funcall foo' as a function name, and align the arguments
+to `foo'."
+  (and (or (not (consp path)) (null (cadr path)))
+       (save-excursion
+        (goto-char (cadr state))
+        (forward-char 1)
+        (let ((start-line (line-number-at-pos)))
+          (and (condition-case nil (progn (forward-sexp 3) t)
+                 (scan-error nil))
+               (progn
+                 (forward-sexp -1)
+                 (and (= start-line (line-number-at-pos))
+                      (current-column))))))))
+(progn
+  (put 'funcall 'common-lisp-indent-function 'mdw-indent-funcall)
+  (put 'funcall 'lisp-indent-function 'mdw-indent-funcall))
+
+(defun mdw-indent-setf
+    (path state &optional indent-point sexp-column normal-indent)
+  "Indent `setf' more usefully.
+If the values aren't on the same lines as their variables then indent them
+by `mdw-lisp-setf-value-indent' spaces."
+  (and (or (not (consp path)) (null (cadr path)))
+       (let ((basic-indent (save-excursion
+                            (goto-char (cadr state))
+                            (forward-char 1)
+                            (and (condition-case nil
+                                     (progn (forward-sexp 2) t)
+                                   (scan-error nil))
+                                 (progn
+                                   (forward-sexp -1)
+                                   (current-column)))))
+            (offset (if (consp path) (car path)
+                      (catch 'done
+                        (save-excursion
+                          (let ((start path)
+                                (count 0))
+                            (goto-char (cadr state))
+                            (forward-char 1)
+                            (while (< (point) start)
+                              (condition-case nil (forward-sexp 1)
+                                (scan-error (throw 'done nil)))
+                              (cl-incf count))
+                            (1- count)))))))
+        (and basic-indent offset
+             (list (+ basic-indent
+                      (if (cl-oddp offset) 0
+                        mdw-lisp-setf-value-indent))
+                   basic-indent)))))
+(progn
+  (put 'setf 'common-lisp-indent-functopion 'mdw-indent-setf)
+  (put 'psetf 'common-lisp-indent-function 'mdw-indent-setf)
+  (put 'setq 'common-lisp-indent-function 'mdw-indent-setf)
+  (put 'setf 'lisp-indent-function 'mdw-indent-setf)
+  (put 'setq 'lisp-indent-function 'mdw-indent-setf)
+  (put 'setq-local 'lisp-indent-function 'mdw-indent-setf)
+  (put 'setq-default 'lisp-indent-function 'mdw-indent-setf))
+
+(defadvice common-lisp-loop-part-indentation
+    (around mdw-fix-loop-indentation (indent-point state) activate compile)
+  "Improve `loop' indentation.
+If the first subform is on the same line as the `loop' keyword, then
+align the other subforms beneath it.  Otherwise, indent them
+`mdw-lisp-loop-default-indent' columns in from the opening parenthesis."
+
+  (let* ((loop-indentation (save-excursion
+                            (goto-char (elt state 1))
+                            (current-column))))
+
+    ;; Don't really care about this.
+    (when (and (boundp 'lisp-indent-backquote-substitution-mode)
+              (eq lisp-indent-backquote-substitution-mode 'corrected))
+      (save-excursion
+       (goto-char (elt state 1))
+       (cl-incf loop-indentation
+                  (cond ((eq (char-before) ?,) -1)
+                        ((and (eq (char-before) ?@)
+                              (progn (backward-char)
+                                     (eq (char-before) ?,)))
+                         -2)
+                        (t 0)))))
+
+    ;; If the first loop item is on the same line as the `loop' itself then
+    ;; use that as the baseline.  Otherwise advance by the default indent.
+    (goto-char (cadr state))
+    (forward-char 1)
+    (let ((baseline-indent
+          (if (= (line-number-at-pos)
+                 (if (condition-case nil (progn (forward-sexp 2) t)
+                       (scan-error nil))
+                     (progn (forward-sexp -1) (line-number-at-pos))
+                   -1))
+              (current-column)
+            (+ loop-indentation mdw-lisp-loop-default-indent))))
+
+      (goto-char indent-point)
+      (beginning-of-line)
+
+      (setq ad-return-value
+             (list
+              (cond ((condition-case ()
+                         (save-excursion
+                           (goto-char (elt state 1))
+                           (forward-char 1)
+                           (forward-sexp 2)
+                           (backward-sexp 1)
+                           (not (looking-at "\\(:\\|\\sw\\)")))
+                       (error nil))
+                     (+ baseline-indent lisp-simple-loop-indentation))
+                    ((looking-at "^\\s-*\\(:?\\sw+\\|;\\)")
+                     (+ baseline-indent lisp-loop-keyword-indentation))
+                    (t
+                     (+ baseline-indent lisp-loop-forms-indentation)))
+
+              ;; Tell the caller that the next line needs recomputation,
+              ;; even though it doesn't start a sexp.
+              loop-indentation)))))
 
 ;; SLIME setup.
 
-(trap
- (if (not mdw-fast-startup)
-     (progn
-       (require 'slime-autoloads)
-       (slime-setup '(slime-autodoc slime-c-p-c)))))
+(defcustom mdw-friendly-name "[mdw]"
+  "How I want to be addressed."
+  :type 'string
+  :safe 'stringp)
+(defadvice slime-user-first-name
+    (around mdw-use-friendly-name compile activate)
+  (if mdw-friendly-name (setq ad-return-value mdw-friendly-name)
+    ad-do-it))
+
+(eval-and-compile
+  (trap
+    (if (not mdw-fast-startup)
+       (progn
+         (require 'slime-autoloads)
+         (slime-setup '(slime-autodoc slime-c-p-c))))))
 
 (let ((stuff '((cmucl ("cmucl"))
               (sbcl ("sbcl") :coding-system utf-8-unix)
@@ -4231,7 +5186,7 @@ (let ((stuff '((cmucl ("cmucl"))
       (if found
          (rplacd found (cdr head))
        (setq slime-lisp-implementations
-             (cons head slime-lisp-implementations))))))
+               (cons head slime-lisp-implementations))))))
 (setq slime-default-lisp 'sbcl)
 
 ;; Hooks.
@@ -4265,15 +5220,15 @@ (defun mdw-setup-smalltalk ()
 (defun mdw-fontify-smalltalk ()
   (make-local-variable 'font-lock-keywords)
   (setq font-lock-keywords
-       (list
-        (list "\\<[A-Z][a-zA-Z0-9]*\\>"
-              '(0 font-lock-keyword-face))
-        (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
-                      "[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
-                      "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
-              '(0 mdw-number-face))
-        (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
-              '(0 mdw-punct-face)))))
+         (list
+          (list "\\<[A-Z][a-zA-Z0-9]*\\>"
+                '(0 font-lock-keyword-face))
+          (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
+                        "[0-9][0-9_]*\\(\\.[0-9_]*\\)?"
+                        "\\([eE][-+]?[0-9_]+\\)?")
+                '(0 mdw-number-face))
+          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
+                '(0 mdw-punct-face)))))
 
 (progn
   (add-hook 'smalltalk-mode 'mdw-misc-mode-config t)
@@ -4349,6 +5304,21 @@ (defun mdw-term-mode-setup ()
   (auto-fill-mode -1)
   (setq tab-width 8))
 
+(defun comint-send-and-indent ()
+  (interactive)
+  (comint-send-input)
+  (and mdw-auto-indent
+       (indent-for-tab-command)))
+
+(defadvice comint-line-beginning-position
+    (around mdw-calculate-it-properly () activate compile)
+  "Calculate the actual line start for multi-line input."
+  (if (or comint-use-prompt-regexp
+         (eq (field-at-pos (point)) 'output))
+      ad-do-it
+    (setq ad-return-value
+           (constrain-to-field (line-beginning-position) (point)))))
+
 (defun term-send-meta-right () (interactive) (term-send-raw-string "\e\e[C"))
 (defun term-send-meta-left  () (interactive) (term-send-raw-string "\e\e[D"))
 (defun term-send-ctrl-uscore () (interactive) (term-send-raw-string "\C-_"))
@@ -4392,9 +5362,10 @@ (defun ssh (host)
   (interactive "sHost: ")
   (ansi-term (list "ssh" host) (format "ssh@%s" host)))
 
-(defvar git-grep-command
+(defcustom git-grep-command
   "env GIT_PAGER=cat git grep --no-color -nH -e "
-  "*The default command for \\[git-grep].")
+  "The default command for \\[git-grep]."
+  :type 'string)
 
 (defvar git-grep-history nil)
 
@@ -4434,7 +5405,9 @@ (eval-after-load "magit"
                           magit-diff-refresh-popup
                           magit-diff-mode-refresh-popup
                           magit-revision-mode-refresh-popup))
-           (magit-define-popup-switch popup ?R "Reverse diff" "-R"))))
+           (magit-define-popup-switch popup ?R "Reverse diff" "-R"))
+         (magit-define-popup-switch 'magit-rebase-popup ?r
+                                    "Rebase merges" "--rebase-merges")))
 
 (defadvice magit-wip-commit-buffer-file
     (around mdw-just-this-buffer activate compile)
@@ -4448,12 +5421,12 @@ (defadvice magit-discard
     ad-do-it))
 
 (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)))
+       '(("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)))
@@ -4487,6 +5460,35 @@ (defun mdw-try-smerge ()
       (smerge-mode 1))))
 (add-hook 'find-file-hook 'mdw-try-smerge t)
 
+(defcustom mdw-magit-new-window-modes
+  '(magit-diff-mode
+    magit-log-mode
+    magit-process-mode
+    magit-revision-mode
+    magit-stash-mode
+    magit-status-mode)
+  "Magit modes which should cause a new window to be used."
+  :type '(repeat symbol))
+
+(defun mdw-display-magit-buffer (buffer)
+  "Like `magit-display-buffer-traditional'.
+But uses `mdw-magit-new-window-modes' for its list of modes
+rather than baking the list into the function."
+  (display-buffer buffer
+                 (let ((mode (with-current-buffer buffer major-mode)))
+                   (if (and (not mdw-designated-window)
+                            (derived-mode-p 'magit-mode)
+                            (mdw-submode-p mode 'magit-mode)
+                            (not (memq mode mdw-magit-new-window-modes)))
+                       '(display-buffer-same-window . nil)
+                     nil))))
+(setq magit-display-buffer-function 'mdw-display-magit-buffer)
+
+(defun mdw-display-magit-file-buffer (buffer)
+  "Show a file buffer from a diff."
+  (select-window (display-buffer buffer)))
+(setq magit-display-file-buffer-function 'mdw-display-magit-file-buffer)
+
 ;;;--------------------------------------------------------------------------
 ;;; GUD, and especially GDB.
 
@@ -4500,6 +5502,15 @@ (defadvice gdb-set-window-buffer
   "Don't make windows dedicated.  Seriously."
   (set-window-dedicated-p (or window (selected-window)) nil))
 
+;;;--------------------------------------------------------------------------
+;;; SQL stuff.
+
+(setq sql-postgres-options '("-n" "-P" "pager=off")
+      sql-postgres-login-params
+       '((user :default "mdw")
+         (database :default "mdw")
+         (server :default "db.distorted.org.uk")))
+
 ;;;--------------------------------------------------------------------------
 ;;; Man pages.
 
@@ -4510,15 +5521,16 @@ (defadvice Man-getpage-in-background
     (around mdw-inhibit-noip (topic) compile activate)
   "Inhibit the `noip' preload hack when invoking `man'."
   (let* ((old-preload (getenv "LD_PRELOAD"))
-        (preloads (save-match-data (split-string old-preload ":")))
+        (preloads (and old-preload
+                       (save-match-data (split-string old-preload ":"))))
         (any nil)
         (filtered nil))
-    (while preloads
-      (let ((item (pop preloads)))
-       (if (save-match-data
-             (string-match  "\\(/\\|^\\)noip\.so\\(:\\|$\\)" item))
-           (setq any t)
-         (push item filtered))))
+    (save-match-data
+      (while preloads
+       (let ((item (pop preloads)))
+         (if (string-match  "\\(/\\|^\\)noip\.so\\(:\\|$\\)" item)
+             (setq any t)
+           (push item filtered)))))
     (if any
        (unwind-protect
            (progn
@@ -4623,21 +5635,21 @@ (defun mdw-mpc-hack-lines (arg interactivep func)
          (funcall func)
          (forward-line)))
     (let ((n (prefix-numeric-value arg)))
-      (cond ((minusp n)
+      (cond ((cl-minusp n)
             (unless (bolp)
               (beginning-of-line)
               (funcall func)
-              (incf n))
-            (while (minusp n)
+              (cl-incf n))
+            (while (cl-minusp n)
               (forward-line -1)
               (funcall func)
-              (incf n)))
+              (cl-incf n)))
            (t
             (beginning-of-line)
-            (while (plusp n)
+            (while (cl-plusp n)
               (funcall func)
               (forward-line)
-              (decf n)))))))
+              (cl-decf n)))))))
 
 (defun mdw-mpc-select-one ()
   (when (and (get-char-property (point) 'mpc-file)
@@ -4696,9 +5708,9 @@ (defun mdw-mpc-playlist-delete (&optional arg interactivep)
 
 (defun mdw-mpc-hack-tagbrowsers ()
   (setq-local mode-line-format
-             '("%e"
-               mode-line-frame-identification
-               mode-line-buffer-identification)))
+               '("%e"
+                 mode-line-frame-identification
+                 mode-line-buffer-identification)))
 (add-hook 'mpc-tagbrowser-mode-hook 'mdw-mpc-hack-tagbrowsers)
 
 (defun mdw-mpc-hack-songs ()