chiark / gitweb /
el/dot-emacs.el: Hack Gnus to cope with IMAP literals properly.
[profile] / el / dot-emacs.el
1 ;;; -*- mode: emacs-lisp; coding: utf-8 -*-
2 ;;;
3 ;;; Functions and macros for .emacs
4 ;;;
5 ;;; (c) 2004 Mark Wooding
6 ;;;
7
8 ;;;----- Licensing notice ---------------------------------------------------
9 ;;;
10 ;;; This program is free software; you can redistribute it and/or modify
11 ;;; it under the terms of the GNU General Public License as published by
12 ;;; the Free Software Foundation; either version 2 of the License, or
13 ;;; (at your option) any later version.
14 ;;;
15 ;;; This program is distributed in the hope that it will be useful,
16 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;;; GNU General Public License for more details.
19 ;;;
20 ;;; You should have received a copy of the GNU General Public License
21 ;;; along with this program; if not, write to the Free Software Foundation,
22 ;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 ;;;--------------------------------------------------------------------------
25 ;;; Check command-line.
26
27 (defvar mdw-fast-startup nil
28   "Whether .emacs should optimize for rapid startup.
29 This may be at the expense of cool features.")
30 (let ((probe nil) (next command-line-args))
31   (while next
32     (cond ((string= (car next) "--mdw-fast-startup")
33            (setq mdw-fast-startup t)
34            (if probe
35                (rplacd probe (cdr next))
36              (setq command-line-args (cdr next))))
37           (t
38            (setq probe next)))
39     (setq next (cdr next))))
40
41 ;;;--------------------------------------------------------------------------
42 ;;; Some general utilities.
43
44 (eval-when-compile
45   (unless (fboundp 'make-regexp)
46     (load "make-regexp"))
47   (require 'cl))
48
49 (defmacro mdw-regexps (&rest list)
50   "Turn a LIST of strings into a single regular expression at compile-time."
51   (declare (indent nil)
52            (debug 0))
53   `',(make-regexp list))
54
55 (defun mdw-wrong ()
56   "This is not the key sequence you're looking for."
57   (interactive)
58   (error "wrong button"))
59
60 (defun mdw-emacs-version-p (major &optional minor)
61   "Return non-nil if the running Emacs is at least version MAJOR.MINOR."
62   (or (> emacs-major-version major)
63       (and (= emacs-major-version major)
64            (>= emacs-minor-version (or minor 0)))))
65
66 ;; Some error trapping.
67 ;;
68 ;; If individual bits of this file go tits-up, we don't particularly want
69 ;; the whole lot to stop right there and then, because it's bloody annoying.
70
71 (defmacro trap (&rest forms)
72   "Execute FORMS without allowing errors to propagate outside."
73   (declare (indent 0)
74            (debug t))
75   `(condition-case err
76        ,(if (cdr forms) (cons 'progn forms) (car forms))
77      (error (message "Error (trapped): %s in %s"
78                      (error-message-string err)
79                      ',forms))))
80
81 ;; Configuration reading.
82
83 (defvar mdw-config nil)
84 (defun mdw-config (sym)
85   "Read the configuration variable named SYM."
86   (unless mdw-config
87     (setq mdw-config
88           (flet ((replace (what with)
89                    (goto-char (point-min))
90                    (while (re-search-forward what nil t)
91                      (replace-match with t))))
92             (with-temp-buffer
93               (insert-file-contents "~/.mdw.conf")
94               (replace  "^[ \t]*\\(#.*\\|\\)\n" "")
95               (replace (concat "^[ \t]*"
96                                "\\([-a-zA-Z0-9_.]*\\)"
97                                "[ \t]*=[ \t]*"
98                                "\\(.*[^ \t\n]\\|\\)"
99                                "[ \t]**\\(\n\\|$\\)")
100                        "(\\1 . \"\\2\")\n")
101               (car (read-from-string
102                     (concat "(" (buffer-string) ")")))))))
103   (cdr (assq sym mdw-config)))
104
105 ;; Width configuration.
106
107 (defvar mdw-column-width
108   (string-to-number (or (mdw-config 'emacs-width) "77"))
109   "Width of Emacs columns.")
110 (defvar mdw-text-width mdw-column-width
111   "Expected width of text within columns.")
112 (put 'mdw-text-width 'safe-local-variable 'integerp)
113
114 ;; Local variables hacking.
115
116 (defun run-local-vars-mode-hook ()
117   "Run a hook for the major-mode after local variables have been processed."
118   (run-hooks (intern (concat (symbol-name major-mode)
119                              "-local-variables-hook"))))
120 (add-hook 'hack-local-variables-hook 'run-local-vars-mode-hook)
121
122 ;; Set up the load path convincingly.
123
124 (dolist (dir (append (and (boundp 'debian-emacs-flavor)
125                           (list (concat "/usr/share/"
126                                         (symbol-name debian-emacs-flavor)
127                                         "/site-lisp")))))
128   (dolist (sub (directory-files dir t))
129     (when (and (file-accessible-directory-p sub)
130                (not (member sub load-path)))
131       (setq load-path (nconc load-path (list sub))))))
132
133 ;; Is an Emacs library available?
134
135 (defun library-exists-p (name)
136   "Return non-nil if NAME is an available library.
137 Return non-nil if NAME.el (or NAME.elc) somewhere on the Emacs
138 load path.  The non-nil value is the filename we found for the
139 library."
140   (let ((path load-path) elt (foundp nil))
141     (while (and path (not foundp))
142       (setq elt (car path))
143       (setq path (cdr path))
144       (setq foundp (or (let ((file (concat elt "/" name ".elc")))
145                          (and (file-exists-p file) file))
146                        (let ((file (concat elt "/" name ".el")))
147                          (and (file-exists-p file) file)))))
148     foundp))
149
150 (defun maybe-autoload (symbol file &optional docstring interactivep type)
151   "Set an autoload if the file actually exists."
152   (and (library-exists-p file)
153        (autoload symbol file docstring interactivep type)))
154
155 (defun mdw-kick-menu-bar (&optional frame)
156   "Regenerate FRAME's menu bar so it doesn't have empty menus."
157   (interactive)
158   (unless frame (setq frame (selected-frame)))
159   (let ((old (frame-parameter frame 'menu-bar-lines)))
160     (set-frame-parameter frame 'menu-bar-lines 0)
161     (set-frame-parameter frame 'menu-bar-lines old)))
162
163 ;; Splitting windows.
164
165 (unless (fboundp 'scroll-bar-columns)
166   (defun scroll-bar-columns (side)
167     (cond ((eq side 'left) 0)
168           (window-system 3)
169           (t 1))))
170 (unless (fboundp 'fringe-columns)
171   (defun fringe-columns (side)
172     (cond ((not window-system) 0)
173           ((eq side 'left) 1)
174           (t 2))))
175
176 (defun mdw-horizontal-window-overhead ()
177   "Computes the horizontal window overhead.
178 This is the number of columns used by fringes, scroll bars and other such
179 cruft."
180   (if (not window-system)
181       1
182     (let ((tot 0))
183       (dolist (what '(scroll-bar fringe))
184         (dolist (side '(left right))
185           (incf tot (funcall (intern (concat (symbol-name what) "-columns"))
186                              side))))
187       tot)))
188
189 (defun mdw-split-window-horizontally (&optional width)
190   "Split a window horizontally.
191 Without a numeric argument, split the window approximately in
192 half.  With a numeric argument WIDTH, allocate WIDTH columns to
193 the left-hand window (if positive) or -WIDTH columns to the
194 right-hand window (if negative).  Space for scroll bars and
195 fringes is not taken out of the allowance for WIDTH, unlike
196 \\[split-window-horizontally]."
197   (interactive "P")
198   (split-window-horizontally
199    (cond ((null width) nil)
200          ((>= width 0) (+ width (mdw-horizontal-window-overhead)))
201          ((< width 0) width))))
202
203 (defun mdw-divvy-window (&optional width)
204   "Split a wide window into appropriate widths."
205   (interactive "P")
206   (setq width (cond (width (prefix-numeric-value width))
207                     ((and window-system (mdw-emacs-version-p 22))
208                      mdw-column-width)
209                     (t (1+ mdw-column-width))))
210   (let* ((win (selected-window))
211          (sb-width (mdw-horizontal-window-overhead))
212          (c (/ (+ (window-width) sb-width)
213                (+ width sb-width))))
214     (while (> c 1)
215       (setq c (1- c))
216       (split-window-horizontally (+ width sb-width))
217       (other-window 1))
218     (select-window win)))
219
220 (defun mdw-set-frame-width (columns &optional width)
221   (interactive "nColumns: 
222 P")
223   (setq width (cond (width (prefix-numeric-value width))
224                     ((and window-system (mdw-emacs-version-p 22))
225                      mdw-column-width)
226                     (t (1+ mdw-column-width))))
227   (let ((sb-width (mdw-horizontal-window-overhead)))
228     (set-frame-width (selected-frame)
229                      (- (* columns (+ width sb-width))
230                         sb-width))
231     (mdw-divvy-window width)))
232
233 ;; Don't raise windows unless I say so.
234
235 (defvar mdw-inhibit-raise-frame nil
236   "*Whether `raise-frame' should do nothing when the frame is mapped.")
237
238 (defadvice raise-frame
239     (around mdw-inhibit (&optional frame) activate compile)
240   "Don't actually do anything if `mdw-inhibit-raise-frame' is true, and the
241 frame is actually mapped on the screen."
242   (if mdw-inhibit-raise-frame
243       (make-frame-visible frame)
244     ad-do-it))
245
246 (defmacro mdw-advise-to-inhibit-raise-frame (function)
247   "Advise the FUNCTION not to raise frames, even if it wants to."
248   `(defadvice ,function
249        (around mdw-inhibit-raise (&rest hunoz) activate compile)
250      "Don't raise the window unless you have to."
251      (let ((mdw-inhibit-raise-frame t))
252        ad-do-it)))
253
254 (mdw-advise-to-inhibit-raise-frame select-frame-set-input-focus)
255 (mdw-advise-to-inhibit-raise-frame appt-disp-window)
256
257 ;; Bug fix for markdown-mode, which breaks point positioning during
258 ;; `query-replace'.
259 (defadvice markdown-check-change-for-wiki-link
260     (around mdw-save-match activate compile)
261   "Save match data around the `markdown-mode' `after-change-functions' hook."
262   (save-match-data ad-do-it))
263
264 ;; Bug fix for `bbdb-canonicalize-address': on Emacs 24, `run-hook-with-args'
265 ;; always returns nil, with the result that all email addresses are lost.
266 ;; Replace the function entirely.
267 (defadvice bbdb-canonicalize-address
268     (around mdw-bug-fix activate compile)
269   "Don't use `run-hook-with-args', because that doesn't work."
270   (let ((net (ad-get-arg 0)))
271
272     ;; Make sure this is a proper hook list.
273     (if (functionp bbdb-canonicalize-net-hook)
274         (setq bbdb-canonicalize-net-hook (list bbdb-canonicalize-net-hook)))
275
276     ;; Iterate over the hooks until things converge.
277     (let ((donep nil))
278       (while (not donep)
279         (let (next (changep nil)
280               hook (hooks bbdb-canonicalize-net-hook))
281           (while hooks
282             (setq hook (pop hooks))
283             (setq next (funcall hook net))
284             (if (not (equal next net))
285                 (setq changep t
286                       net next)))
287           (setq donep (not changep)))))
288     (setq ad-return-value net)))
289
290 ;; Transient mark mode hacks.
291
292 (defadvice exchange-point-and-mark
293     (around mdw-highlight (&optional arg) activate compile)
294   "Maybe don't actually exchange point and mark.
295 If `transient-mark-mode' is on and the mark is inactive, then
296 just activate it.  A non-trivial prefix argument will force the
297 usual behaviour.  A trivial prefix argument (i.e., just C-u) will
298 activate the mark and temporarily enable `transient-mark-mode' if
299 it's currently off."
300   (cond ((or mark-active
301              (and (not transient-mark-mode) (not arg))
302              (and arg (or (not (consp arg))
303                           (not (= (car arg) 4)))))
304          ad-do-it)
305         (t
306          (or transient-mark-mode (setq transient-mark-mode 'only))
307          (set-mark (mark t)))))
308
309 ;; Functions for sexp diary entries.
310
311 (defun mdw-not-org-mode (form)
312   "As FORM, but not in Org mode agenda."
313   (and (not mdw-diary-for-org-mode-p)
314        (eval form)))
315
316 (defun mdw-weekday (l)
317   "Return non-nil if `date' falls on one of the days of the week in L.
318 L is a list of day numbers (from 0 to 6 for Sunday through to
319 Saturday) or symbols `sunday', `monday', etc. (or a mixture).  If
320 the date stored in `date' falls on a listed day, then the
321 function returns non-nil."
322   (let ((d (calendar-day-of-week date)))
323     (or (memq d l)
324         (memq (nth d '(sunday monday tuesday wednesday
325                               thursday friday saturday)) l))))
326
327 (defun mdw-discordian-date (date)
328   "Return the Discordian calendar date corresponding to DATE.
329
330 The return value is (YOLD . st-tibs-day) or (YOLD SEASON DAYNUM DOW).
331
332 The original is by David Pearson.  I modified it to produce date components
333 as output rather than a string."
334   (let* ((days ["Sweetmorn" "Boomtime" "Pungenday"
335                 "Prickle-Prickle" "Setting Orange"])
336          (months ["Chaos" "Discord" "Confusion"
337                   "Bureaucracy" "Aftermath"])
338          (day-count [0 31 59 90 120 151 181 212 243 273 304 334])
339          (year (- (extract-calendar-year date) 1900))
340          (month (1- (extract-calendar-month date)))
341          (day (1- (extract-calendar-day date)))
342          (julian (+ (aref day-count month) day))
343          (dyear (+ year 3066)))
344     (if (and (= month 1) (= day 28))
345         (cons dyear 'st-tibs-day)
346       (list dyear
347             (aref months (floor (/ julian 73)))
348             (1+ (mod julian 73))
349             (aref days (mod julian 5))))))
350
351 (defun mdw-diary-discordian-date ()
352   "Convert the date in `date' to a string giving the Discordian date."
353   (let* ((ddate (mdw-discordian-date date))
354          (tail (format "in the YOLD %d" (car ddate))))
355     (if (eq (cdr ddate) 'st-tibs-day)
356         (format "St Tib's Day %s" tail)
357       (let ((season (cadr ddate))
358             (daynum (caddr ddate))
359             (dayname (cadddr ddate)))
360       (format "%s, the %d%s day of %s %s"
361               dayname
362               daynum
363               (let ((ldig (mod daynum 10)))
364                 (cond ((= ldig 1) "st")
365                       ((= ldig 2) "nd")
366                       ((= ldig 3) "rd")
367                       (t "th")))
368               season
369               tail)))))
370
371 (defun mdw-todo (&optional when)
372   "Return non-nil today, or on WHEN, whichever is later."
373   (let ((w (calendar-absolute-from-gregorian (calendar-current-date)))
374         (d (calendar-absolute-from-gregorian date)))
375     (if when
376         (setq w (max w (calendar-absolute-from-gregorian
377                         (cond
378                          ((not european-calendar-style)
379                           when)
380                          ((> (car when) 100)
381                           (list (nth 1 when)
382                                 (nth 2 when)
383                                 (nth 0 when)))
384                          (t
385                           (list (nth 1 when)
386                                 (nth 0 when)
387                                 (nth 2 when))))))))
388     (eq w d)))
389
390 (defvar mdw-diary-for-org-mode-p nil)
391
392 (defadvice org-agenda-list (around mdw-preserve-links activate)
393   (let ((mdw-diary-for-org-mode-p t))
394     ad-do-it))
395
396 (defadvice diary-add-to-list (before mdw-trim-leading-space compile activate)
397   "Trim leading space from the diary entry string."
398   (save-match-data
399     (let ((str (ad-get-arg 1))
400           (done nil) old)
401       (while (not done)
402         (setq old str)
403         (setq str (cond ((null str) nil)
404                         ((string-match "\\(^\\|\n\\)[ \t]+" str)
405                          (replace-match "\\1" nil nil str))
406                         ((and mdw-diary-for-org-mode-p
407                               (string-match (concat
408                                              "\\(^\\|\n\\)"
409                                              "\\(" diary-time-regexp
410                                              "\\(-" diary-time-regexp "\\)?"
411                                              "\\)"
412                                              "\\(\t[ \t]*\\| [ \t]+\\)")
413                                             str))
414                          (replace-match "\\1\\2 " nil nil str))
415                         ((and (not mdw-diary-for-org-mode-p)
416                               (string-match "\\[\\[[^][]*]\\[\\([^][]*\\)]]"
417                                             str))
418                          (replace-match "\\1" nil nil str))
419                         (t str)))
420         (if (equal str old) (setq done t)))
421       (ad-set-arg 1 str))))
422
423 (defadvice org-bbdb-anniversaries (after mdw-fixup-list compile activate)
424   "Return a string rather than a list."
425   (with-temp-buffer
426     (let ((anyp nil))
427       (dolist (e (let ((ee ad-return-value))
428                    (if (atom ee) (list ee) ee)))
429         (when e
430           (when anyp (insert ?\n))
431           (insert e)
432           (setq anyp t)))
433       (setq ad-return-value
434             (and anyp (buffer-string))))))
435
436 ;; Fighting with Org-mode's evil key maps.
437
438 (defvar mdw-evil-keymap-keys
439   '(([S-up] . [?\C-c up])
440     ([S-down] . [?\C-c down])
441     ([S-left] . [?\C-c left])
442     ([S-right] . [?\C-c right])
443     (([M-up] [?\e up]) . [C-up])
444     (([M-down] [?\e down]) . [C-down])
445     (([M-left] [?\e left]) . [C-left])
446     (([M-right] [?\e right]) . [C-right]))
447   "Defines evil keybindings to clobber in `mdw-clobber-evil-keymap'.
448 The value is an alist mapping evil keys (as a list, or singleton)
449 to good keys (in the same form).")
450
451 (defun mdw-clobber-evil-keymap (keymap)
452   "Replace evil key bindings in the KEYMAP.
453 Evil key bindings are defined in `mdw-evil-keymap-keys'."
454   (dolist (entry mdw-evil-keymap-keys)
455     (let ((binding nil)
456           (keys (if (listp (car entry))
457                     (car entry)
458                   (list (car entry))))
459           (replacements (if (listp (cdr entry))
460                             (cdr entry)
461                           (list (cdr entry)))))
462       (catch 'found
463         (dolist (key keys)
464           (setq binding (lookup-key keymap key))
465           (when binding
466             (throw 'found nil))))
467       (when binding
468         (dolist (key keys)
469           (define-key keymap key nil))
470         (dolist (key replacements)
471           (define-key keymap key binding))))))
472
473 (defvar mdw-org-latex-defs
474   '(("strayman"
475      "\\documentclass{strayman}
476 \\usepackage[utf8]{inputenc}
477 \\usepackage[palatino, helvetica, courier, maths=cmr]{mdwfonts}
478 \\usepackage{graphicx, tikz, mdwtab, mdwmath, crypto, longtable}"
479      ("\\section{%s}" . "\\section*{%s}")
480      ("\\subsection{%s}" . "\\subsection*{%s}")
481      ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
482      ("\\paragraph{%s}" . "\\paragraph*{%s}")
483      ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))))
484
485 (eval-after-load "org-latex"
486   '(setq org-export-latex-classes
487          (append mdw-org-latex-defs org-export-latex-classes)))
488
489 (eval-after-load "ox-latex"
490   '(setq org-latex-classes (append mdw-org-latex-defs org-latex-classes)
491          org-latex-default-packages-alist '(("AUTO" "inputenc" t)
492                                             ("T1" "fontenc" t)
493                                             ("" "fixltx2e" nil)
494                                             ("" "graphicx" t)
495                                             ("" "longtable" nil)
496                                             ("" "float" nil)
497                                             ("" "wrapfig" nil)
498                                             ("" "rotating" nil)
499                                             ("normalem" "ulem" t)
500                                             ("" "textcomp" t)
501                                             ("" "marvosym" t)
502                                             ("" "wasysym" t)
503                                             ("" "amssymb" t)
504                                             ("" "hyperref" nil)
505                                             "\\tolerance=1000")))
506
507
508 (setq org-export-docbook-xslt-proc-command "xsltproc --output %o %s %i"
509       org-export-docbook-xsl-fo-proc-command "fop %i.safe %o"
510       org-export-docbook-xslt-stylesheet
511       "/usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl")
512
513 ;; Some hacks to do with window placement.
514
515 (defun mdw-clobber-other-windows-showing-buffer (buffer-or-name)
516   "Arrange that no windows on other frames are showing BUFFER-OR-NAME."
517   (interactive "bBuffer: ")
518   (let ((home-frame (selected-frame))
519         (buffer (get-buffer buffer-or-name))
520         (safe-buffer (get-buffer "*scratch*")))
521     (mapc (lambda (frame)
522             (or (eq frame home-frame)
523                 (mapc (lambda (window)
524                         (and (eq (window-buffer window) buffer)
525                              (set-window-buffer window safe-buffer)))
526                       (window-list frame))))
527           (frame-list))))
528
529 (defvar mdw-inhibit-walk-windows nil
530   "If non-nil, then `walk-windows' does nothing.
531 This is used by advice on `switch-to-buffer-other-frame' to inhibit finding
532 buffers in random frames.")
533
534 (defadvice walk-windows (around mdw-inhibit activate)
535   "If `mdw-inhibit-walk-windows' is non-nil, then do nothing."
536   (and (not mdw-inhibit-walk-windows)
537        ad-do-it))
538
539 (defadvice switch-to-buffer-other-frame
540     (around mdw-always-new-frame activate)
541   "Always make a new frame.
542 Even if an existing window in some random frame looks tempting."
543   (let ((mdw-inhibit-walk-windows t)) ad-do-it))
544
545 (defadvice display-buffer (before mdw-inhibit-other-frames activate)
546   "Don't try to do anything fancy with other frames.
547 Pretend they don't exist.  They might be on other display devices."
548   (ad-set-arg 2 nil))
549
550 ;;;--------------------------------------------------------------------------
551 ;;; Improved compilation machinery.
552
553 ;; Uprated version of M-x compile.
554
555 (setq compile-command
556       (let ((ncpu (with-temp-buffer
557                     (insert-file-contents "/proc/cpuinfo")
558                     (buffer-string)
559                     (count-matches "^processor\\s-*:"))))
560         (format "make -j%d -k" (* 2 ncpu))))
561
562 (defun mdw-compilation-buffer-name (mode)
563   (concat "*" (downcase mode) ": "
564           (abbreviate-file-name default-directory) "*"))
565 (setq compilation-buffer-name-function 'mdw-compilation-buffer-name)
566
567 (eval-after-load "compile"
568   '(progn
569      (define-key compilation-shell-minor-mode-map "\C-c\M-g" 'recompile)))
570
571 (defadvice compile (around hack-environment compile activate)
572   "Hack the environment inherited by inferiors in the compilation."
573   (let ((process-environment process-environment))
574     (setenv "LD_PRELOAD" nil)
575     ad-do-it))
576
577 (defun mdw-compile (command &optional directory comint)
578   "Initiate a compilation COMMAND, maybe in a different DIRECTORY.
579 The DIRECTORY may be nil to not change.  If COMINT is t, then
580 start an interactive compilation.
581
582 Interactively, prompt for the command if the variable
583 `compilation-read-command' is non-nil, or if requested through
584 the prefix argument.  Prompt for the directory, and run
585 interactively, if requested through the prefix.
586
587 Use a prefix of 4, 6, 12, or 14, or type C-u between one and three times, to
588 force prompting for a directory.
589
590 Use a prefix of 2, 6, 10, or 14, or type C-u three times, to force
591 prompting for the command.
592
593 Use a prefix of 8, 10, 12, or 14, or type C-u twice or three times,
594 to force interactive compilation."
595   (interactive
596    (let* ((prefix (prefix-numeric-value current-prefix-arg))
597           (command (eval compile-command))
598           (dir (and (plusp (logand prefix #x54))
599                     (read-directory-name "Compile in directory: "))))
600      (list (if (or compilation-read-command
601                    (plusp (logand prefix #x42)))
602                (compilation-read-command command)
603              command)
604            dir
605            (plusp (logand prefix #x58)))))
606   (let ((default-directory (or directory default-directory)))
607     (compile command comint)))
608
609 ;; Flymake support.
610
611 (defun mdw-find-build-dir (build-file)
612   (catch 'found
613     (let* ((src-dir (file-name-as-directory (expand-file-name ".")))
614            (dir src-dir))
615       (loop
616         (when (file-exists-p (concat dir build-file))
617           (throw 'found dir))
618         (let ((sub (expand-file-name (file-relative-name src-dir dir)
619                                      (concat dir "build/"))))
620           (catch 'give-up
621             (loop
622               (when (file-exists-p (concat sub build-file))
623                 (throw 'found sub))
624               (when (string= sub dir) (throw 'give-up nil))
625               (setq sub (file-name-directory (directory-file-name sub))))))
626         (when (string= dir
627                        (setq dir (file-name-directory
628                                   (directory-file-name dir))))
629           (throw 'found nil))))))
630
631 (defun mdw-flymake-make-init ()
632   (let ((build-dir (mdw-find-build-dir "Makefile")))
633     (and build-dir
634          (let ((tmp-src (flymake-init-create-temp-buffer-copy
635                          #'flymake-create-temp-inplace)))
636            (flymake-get-syntax-check-program-args
637             tmp-src build-dir t t
638             #'flymake-get-make-cmdline)))))
639
640 (setq flymake-allowed-file-name-masks
641       '(("\\.\\(?:[cC]\\|cc\\|cpp\\|cxx\\|c\\+\\+\\)\\'"
642          mdw-flymake-make-init)
643         ("\\.\\(?:[hH]\\|hh\\|hpp\\|hxx\\|h\\+\\+\\)\\'"
644          mdw-flymake-master-make-init)
645         ("\\.p[lm]" flymake-perl-init)))
646
647 (setq flymake-mode-map
648       (let ((map (if (boundp 'flymake-mode-map)
649                      flymake-mode-map
650                    (make-sparse-keymap))))
651         (define-key map [?\C-c ?\C-f ?\C-p] 'flymake-goto-prev-error)
652         (define-key map [?\C-c ?\C-f ?\C-n] 'flymake-goto-next-error)
653         (define-key map [?\C-c ?\C-f ?\C-c] 'flymake-compile)
654         (define-key map [?\C-c ?\C-f ?\C-k] 'flymake-stop-all-syntax-checks)
655         (define-key map [?\C-c ?\C-f ?\C-e] 'flymake-popup-current-error-menu)
656         map))
657
658 ;;;--------------------------------------------------------------------------
659 ;;; Mail and news hacking.
660
661 (define-derived-mode  mdwmail-mode mail-mode "[mdw] mail"
662   "Major mode for editing news and mail messages from external programs.
663 Not much right now.  Just support for doing MailCrypt stuff."
664   :syntax-table nil
665   :abbrev-table nil
666   (run-hooks 'mail-setup-hook))
667
668 (define-key mdwmail-mode-map [?\C-c ?\C-c] 'disabled-operation)
669
670 (add-hook 'mdwail-mode-hook
671           (lambda ()
672             (set-buffer-file-coding-system 'utf-8)
673             (make-local-variable 'paragraph-separate)
674             (make-local-variable 'paragraph-start)
675             (setq paragraph-start
676                   (concat "[ \t]*[-_][-_][-_]+$\\|^-- \\|-----\\|"
677                           paragraph-start))
678             (setq paragraph-separate
679                   (concat "[ \t]*[-_][-_][-_]+$\\|^-- \\|-----\\|"
680                           paragraph-separate))))
681
682 ;; How to encrypt in mdwmail.
683
684 (defun mdwmail-mc-encrypt (&optional recip scm start end from sign)
685   (or start
686       (setq start (save-excursion
687                     (goto-char (point-min))
688                     (or (search-forward "\n\n" nil t) (point-min)))))
689   (or end
690       (setq end (point-max)))
691   (mc-encrypt-generic recip scm start end from sign))
692
693 ;; How to sign in mdwmail.
694
695 (defun mdwmail-mc-sign (key scm start end uclr)
696   (or start
697       (setq start (save-excursion
698                     (goto-char (point-min))
699                     (or (search-forward "\n\n" nil t) (point-min)))))
700   (or end
701       (setq end (point-max)))
702   (mc-sign-generic key scm start end uclr))
703
704 ;; Some signature mangling.
705
706 (defun mdwmail-mangle-signature ()
707   (save-excursion
708     (goto-char (point-min))
709     (perform-replace "\n-- \n" "\n-- " nil nil nil)))
710 (add-hook 'mail-setup-hook 'mdwmail-mangle-signature)
711 (add-hook 'message-setup-hook 'mdwmail-mangle-signature)
712
713 ;; Insert my login name into message-ids, so I can score replies.
714
715 (defadvice message-unique-id (after mdw-user-name last activate compile)
716   "Ensure that the user's name appears at the end of the message-id string,
717 so that it can be used for convenient filtering."
718   (setq ad-return-value (concat ad-return-value "." (user-login-name))))
719
720 ;; Tell my movemail hack where movemail is.
721 ;;
722 ;; This is needed to shup up warnings about LD_PRELOAD.
723
724 (let ((path exec-path))
725   (while path
726     (let ((try (expand-file-name "movemail" (car path))))
727       (if (file-executable-p try)
728           (setenv "REAL_MOVEMAIL" try))
729       (setq path (cdr path)))))
730
731 ;; AUTHINFO GENERIC kludge.
732
733 (defvar nntp-authinfo-generic nil
734   "Set to the `NNTPAUTH' string to pass on to `authinfo-kludge'.
735
736 Use this to arrange for per-server settings.")
737
738 (defun nntp-open-authinfo-kludge (buffer)
739   "Open a connection to SERVER using `authinfo-kludge'."
740   (let ((proc (start-process "nntpd" buffer
741                              "env" (concat "NNTPAUTH="
742                                            (or nntp-authinfo-generic
743                                                (getenv "NNTPAUTH")
744                                                (error "NNTPAUTH unset")))
745                              "authinfo-kludge" nntp-address)))
746     (set-buffer buffer)
747     (nntp-wait-for-string "^\r*200")
748     (beginning-of-line)
749     (delete-region (point-min) (point))
750     proc))
751
752 (eval-after-load "erc"
753   '(load "~/.ercrc.el"))
754
755 ;; Heavy-duty Gnus patching.
756
757 (defun mdw-nnimap-transform-headers ()
758   (goto-char (point-min))
759   (let (article lines size string)
760     (block nil
761       (while (not (eobp))
762         (while (not (looking-at "\\* [0-9]+ FETCH"))
763           (delete-region (point) (progn (forward-line 1) (point)))
764           (when (eobp)
765             (return)))
766         (goto-char (match-end 0))
767         ;; Unfold quoted {number} strings.
768         (while (re-search-forward
769                 "[^]][ (]{\\([0-9]+\\)}\r?\n"
770                 (save-excursion
771                   ;; Start of the header section.
772                   (or (re-search-forward "] {[0-9]+}\r?\n" nil t)
773                       ;; Start of the next FETCH.
774                       (re-search-forward "\\* [0-9]+ FETCH" nil t)
775                       (point-max)))
776                 t)
777           (setq size (string-to-number (match-string 1)))
778           (delete-region (+ (match-beginning 0) 2) (point))
779           (setq string (buffer-substring (point) (+ (point) size)))
780           (delete-region (point) (+ (point) size))
781           (insert (format "%S" (mm-subst-char-in-string ?\n ?\s string)))
782           ;; [mdw] missing from upstream
783           (backward-char 1))
784         (beginning-of-line)
785         (setq article
786               (and (re-search-forward "UID \\([0-9]+\\)" (line-end-position)
787                                       t)
788                    (match-string 1)))
789         (setq lines nil)
790         (setq size
791               (and (re-search-forward "RFC822.SIZE \\([0-9]+\\)"
792                                       (line-end-position)
793                                       t)
794                    (match-string 1)))
795         (beginning-of-line)
796         (when (search-forward "BODYSTRUCTURE" (line-end-position) t)
797           (let ((structure (ignore-errors
798                              (read (current-buffer)))))
799             (while (and (consp structure)
800                         (not (atom (car structure))))
801               (setq structure (car structure)))
802             (setq lines (if (and
803                              (stringp (car structure))
804                              (equal (upcase (nth 0 structure)) "MESSAGE")
805                              (equal (upcase (nth 1 structure)) "RFC822"))
806                             (nth 9 structure)
807                           (nth 7 structure)))))
808         (delete-region (line-beginning-position) (line-end-position))
809         (insert (format "211 %s Article retrieved." article))
810         (forward-line 1)
811         (when size
812           (insert (format "Chars: %s\n" size)))
813         (when lines
814           (insert (format "Lines: %s\n" lines)))
815         ;; Most servers have a blank line after the headers, but
816         ;; Davmail doesn't.
817         (unless (re-search-forward "^\r$\\|^)\r?$" nil t)
818           (goto-char (point-max)))
819         (delete-region (line-beginning-position) (line-end-position))
820         (insert ".")
821         (forward-line 1)))))
822
823 (eval-after-load 'nnimap
824   '(defalias 'nnimap-transform-headers
825      (symbol-function 'mdw-nnimap-transform-headers)))
826
827 ;;;--------------------------------------------------------------------------
828 ;;; Utility functions.
829
830 (or (fboundp 'line-number-at-pos)
831     (defun line-number-at-pos (&optional pos)
832       (let ((opoint (or pos (point))) start)
833         (save-excursion
834           (save-restriction
835             (goto-char (point-min))
836             (widen)
837             (forward-line 0)
838             (setq start (point))
839             (goto-char opoint)
840             (forward-line 0)
841             (1+ (count-lines 1 (point))))))))
842
843 (defun mdw-uniquify-alist (&rest alists)
844   "Return the concatenation of the ALISTS with duplicate elements removed.
845 The first association with a given key prevails; others are
846 ignored.  The input lists are not modified, although they'll
847 probably become garbage."
848   (and alists
849        (let ((start-list (cons nil nil)))
850          (mdw-do-uniquify start-list
851                           start-list
852                           (car alists)
853                           (cdr alists)))))
854
855 (defun mdw-do-uniquify (done end l rest)
856   "A helper function for mdw-uniquify-alist.
857 The DONE argument is a list whose first element is `nil'.  It
858 contains the uniquified alist built so far.  The leading `nil' is
859 stripped off at the end of the operation; it's only there so that
860 DONE always references a cons cell.  END refers to the final cons
861 cell in the DONE list; it is modified in place each time to avoid
862 the overheads of `append'ing all the time.  The L argument is the
863 alist we're currently processing; the remaining alists are given
864 in REST."
865
866   ;; There are several different cases to deal with here.
867   (cond
868
869    ;; Current list isn't empty.  Add the first item to the DONE list if
870    ;; there's not an item with the same KEY already there.
871    (l (or (assoc (car (car l)) done)
872           (progn
873             (setcdr end (cons (car l) nil))
874             (setq end (cdr end))))
875       (mdw-do-uniquify done end (cdr l) rest))
876
877    ;; The list we were working on is empty.  Shunt the next list into the
878    ;; current list position and go round again.
879    (rest (mdw-do-uniquify done end (car rest) (cdr rest)))
880
881    ;; Everything's done.  Remove the leading `nil' from the DONE list and
882    ;; return it.  Finished!
883    (t (cdr done))))
884
885 (defun date ()
886   "Insert the current date in a pleasing way."
887   (interactive)
888   (insert (save-excursion
889             (let ((buffer (get-buffer-create "*tmp*")))
890               (unwind-protect (progn (set-buffer buffer)
891                                      (erase-buffer)
892                                      (shell-command "date +%Y-%m-%d" t)
893                                      (goto-char (mark))
894                                      (delete-backward-char 1)
895                                      (buffer-string))
896                 (kill-buffer buffer))))))
897
898 (defun uuencode (file &optional name)
899   "UUencodes a file, maybe calling it NAME, into the current buffer."
900   (interactive "fInput file name: ")
901
902   ;; If NAME isn't specified, then guess from the filename.
903   (if (not name)
904       (setq name
905             (substring file
906                        (or (string-match "[^/]*$" file) 0))))
907   (print (format "uuencode `%s' `%s'" file name))
908
909   ;; Now actually do the thing.
910   (call-process "uuencode" file t nil name))
911
912 (defvar np-file "~/.np"
913   "*Where the `now-playing' file is.")
914
915 (defun np (&optional arg)
916   "Grabs a `now-playing' string."
917   (interactive)
918   (save-excursion
919     (or arg (progn
920               (goto-char (point-max))
921               (insert "\nNP: ")
922               (insert-file-contents np-file)))))
923
924 (defun mdw-version-< (ver-a ver-b)
925   "Answer whether VER-A is strictly earlier than VER-B.
926 VER-A and VER-B are version numbers, which are strings containing digit
927 sequences separated by `.'."
928   (let* ((la (mapcar (lambda (x) (car (read-from-string x)))
929                      (split-string ver-a "\\.")))
930          (lb (mapcar (lambda (x) (car (read-from-string x)))
931                      (split-string ver-b "\\."))))
932     (catch 'done
933       (while t
934         (cond ((null la) (throw 'done lb))
935               ((null lb) (throw 'done nil))
936               ((< (car la) (car lb)) (throw 'done t))
937               ((= (car la) (car lb)) (setq la (cdr la) lb (cdr lb)))
938               (t (throw 'done nil)))))))
939
940 (defun mdw-check-autorevert ()
941   "Sets global-auto-revert-ignore-buffer appropriately for this buffer.
942 This takes into consideration whether it's been found using
943 tramp, which seems to get itself into a twist."
944   (cond ((not (boundp 'global-auto-revert-ignore-buffer))
945          nil)
946         ((and (buffer-file-name)
947               (fboundp 'tramp-tramp-file-p)
948               (tramp-tramp-file-p (buffer-file-name)))
949          (unless global-auto-revert-ignore-buffer
950            (setq global-auto-revert-ignore-buffer 'tramp)))
951         ((eq global-auto-revert-ignore-buffer 'tramp)
952          (setq global-auto-revert-ignore-buffer nil))))
953
954 (defadvice find-file (after mdw-autorevert activate)
955   (mdw-check-autorevert))
956 (defadvice write-file (after mdw-autorevert activate)
957   (mdw-check-autorevert))
958
959 ;;;--------------------------------------------------------------------------
960 ;;; Dired hacking.
961
962 (defadvice dired-maybe-insert-subdir
963     (around mdw-marked-insertion first activate)
964   "The DIRNAME may be a list of directory names to insert.
965 Interactively, if files are marked, then insert all of them.
966 With a numeric prefix argument, select that many entries near
967 point; with a non-numeric prefix argument, prompt for listing
968 options."
969   (interactive
970    (list (dired-get-marked-files nil
971                                  (and (integerp current-prefix-arg)
972                                       current-prefix-arg)
973                                  #'file-directory-p)
974          (and current-prefix-arg
975               (not (integerp current-prefix-arg))
976               (read-string "Switches for listing: "
977                            (or dired-subdir-switches
978                                dired-actual-switches)))))
979   (let ((dirs (ad-get-arg 0)))
980     (dolist (dir (if (listp dirs) dirs (list dirs)))
981       (ad-set-arg 0 dir)
982       ad-do-it)))
983
984 (defun mdw-dired-run (args &optional syncp)
985   (interactive (let ((file (dired-get-filename t)))
986                  (list (read-string (format "Arguments for %s: " file))
987                        current-prefix-arg)))
988   (funcall (if syncp 'shell-command 'async-shell-command)
989            (concat (shell-quote-argument (dired-get-filename nil))
990                    " " args)))
991
992 (eval-after-load "dired"
993   '(define-key dired-mode-map "X" 'mdw-dired-run))
994
995 ;;;--------------------------------------------------------------------------
996 ;;; URL viewing.
997
998 (defun mdw-w3m-browse-url (url &optional new-session-p)
999   "Invoke w3m on the URL in its current window, or at least a different one.
1000 If NEW-SESSION-P, start a new session."
1001   (interactive "sURL: \nP")
1002   (save-excursion
1003     (let ((window (selected-window)))
1004       (unwind-protect
1005           (progn
1006             (select-window (or (and (not new-session-p)
1007                                     (get-buffer-window "*w3m*"))
1008                                (progn
1009                                  (if (one-window-p t) (split-window))
1010                                  (get-lru-window))))
1011             (w3m-browse-url url new-session-p))
1012         (select-window window)))))
1013
1014 (defvar mdw-good-url-browsers
1015   '(browse-url-chromium
1016     browse-url-mozilla
1017     browse-url-generic
1018     (w3m . mdw-w3m-browse-url)
1019     browse-url-w3)
1020   "List of good browsers for mdw-good-url-browsers.
1021 Each item is a browser function name, or a cons (CHECK . FUNC).
1022 A symbol FOO stands for (FOO . FOO).")
1023
1024 (defun mdw-good-url-browser ()
1025   "Return a good URL browser.
1026 Trundle the list of such things, finding the first item for which
1027 CHECK is fboundp, and returning the correponding FUNC."
1028   (let ((bs mdw-good-url-browsers) b check func answer)
1029     (while (and bs (not answer))
1030       (setq b (car bs)
1031             bs (cdr bs))
1032       (if (consp b)
1033           (setq check (car b) func (cdr b))
1034         (setq check b func b))
1035       (if (fboundp check)
1036           (setq answer func)))
1037     answer))
1038
1039 (eval-after-load "w3m-search"
1040   '(progn
1041      (dolist
1042          (item
1043           '(("g" "Google" "http://www.google.co.uk/search?q=%s")
1044             ("gd" "Google Directory"
1045              "http://www.google.com/search?cat=gwd/Top&q=%s")
1046             ("gg" "Google Groups" "http://groups.google.com/groups?q=%s")
1047             ("ward" "Ward's wiki" "http://c2.com/cgi/wiki?%s")
1048             ("gi" "Images" "http://images.google.com/images?q=%s")
1049             ("rfc" "RFC"
1050              "http://metalzone.distorted.org.uk/ftp/pub/mirrors/rfc/rfc%s.txt.gz")
1051             ("wp" "Wikipedia"
1052              "http://en.wikipedia.org/wiki/Special:Search?go=Go&search=%s")
1053             ("imdb" "IMDb" "http://www.imdb.com/Find?%s")
1054             ("nc-wiki" "nCipher wiki"
1055              "http://wiki.ncipher.com/wiki/bin/view/Devel/?topic=%s")
1056             ("map" "Google maps" "http://maps.google.co.uk/maps?q=%s&hl=en")
1057             ("lp" "Launchpad bug by number"
1058              "https://bugs.launchpad.net/bugs/%s")
1059             ("lppkg" "Launchpad bugs by package"
1060              "https://bugs.launchpad.net/%s")
1061             ("msdn" "MSDN"
1062              "http://social.msdn.microsoft.com/Search/en-GB/?query=%s&ac=8")
1063             ("debbug" "Debian bug by number"
1064              "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%s")
1065             ("debbugpkg" "Debian bugs by package"
1066              "http://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=%s")
1067             ("ljlogin" "LJ login" "http://www.livejournal.com/login.bml")))
1068        (add-to-list 'w3m-search-engine-alist
1069                     (list (cadr item) (caddr item) nil))
1070        (add-to-list 'w3m-uri-replace-alist
1071                     (list (concat "\\`" (car item) ":")
1072                           'w3m-search-uri-replace
1073                           (cadr item))))))
1074
1075 ;;;--------------------------------------------------------------------------
1076 ;;; Paragraph filling.
1077
1078 ;; Useful variables.
1079
1080 (defvar mdw-fill-prefix nil
1081   "*Used by `mdw-line-prefix' and `mdw-fill-paragraph'.
1082 If there's no fill prefix currently set (by the `fill-prefix'
1083 variable) and there's a match from one of the regexps here, it
1084 gets used to set the fill-prefix for the current operation.
1085
1086 The variable is a list of items of the form `REGEXP . PREFIX'; if
1087 the REGEXP matches, the PREFIX is used to set the fill prefix.
1088 It in turn is a list of things:
1089
1090   STRING -- insert a literal string
1091   (match . N) -- insert the thing matched by bracketed subexpression N
1092   (pad . N) -- a string of whitespace the same width as subexpression N
1093   (expr . FORM) -- the result of evaluating FORM")
1094
1095 (make-variable-buffer-local 'mdw-fill-prefix)
1096
1097 (defvar mdw-hanging-indents
1098   (concat "\\(\\("
1099             "\\([*o+]\\|-[-#]?\\|[0-9]+\\.\\|\\[[0-9]+\\]\\|([a-zA-Z])\\)"
1100             "[ \t]+"
1101           "\\)?\\)")
1102   "*Standard regexp matching parts of a hanging indent.
1103 This is mainly useful in `auto-fill-mode'.")
1104
1105 ;; Utility functions.
1106
1107 (defun mdw-maybe-tabify (s)
1108   "Tabify or untabify the string S, according to `indent-tabs-mode'."
1109   (let ((tabfun (if indent-tabs-mode #'tabify #'untabify)))
1110     (with-temp-buffer
1111       (save-match-data
1112         (insert s "\n")
1113         (let ((start (point-min)) (end (point-max)))
1114           (funcall tabfun (point-min) (point-max))
1115           (setq s (buffer-substring (point-min) (1- (point-max)))))))))
1116
1117 (defun mdw-examine-fill-prefixes (l)
1118   "Given a list of dynamic fill prefixes, pick one which matches
1119 context and return the static fill prefix to use.  Point must be
1120 at the start of a line, and match data must be saved."
1121   (cond ((not l) nil)
1122         ((looking-at (car (car l)))
1123          (mdw-maybe-tabify (apply #'concat
1124                                   (mapcar #'mdw-do-prefix-match
1125                                           (cdr (car l))))))
1126         (t (mdw-examine-fill-prefixes (cdr l)))))
1127
1128 (defun mdw-maybe-car (p)
1129   "If P is a pair, return (car P), otherwise just return P."
1130   (if (consp p) (car p) p))
1131
1132 (defun mdw-padding (s)
1133   "Return a string the same width as S but made entirely from whitespace."
1134   (let* ((l (length s)) (i 0) (n (make-string l ? )))
1135     (while (< i l)
1136       (if (= 9 (aref s i))
1137           (aset n i 9))
1138       (setq i (1+ i)))
1139     n))
1140
1141 (defun mdw-do-prefix-match (m)
1142   "Expand a dynamic prefix match element.
1143 See `mdw-fill-prefix' for details."
1144   (cond ((not (consp m)) (format "%s" m))
1145         ((eq (car m) 'match) (match-string (mdw-maybe-car (cdr m))))
1146         ((eq (car m) 'pad) (mdw-padding (match-string
1147                                          (mdw-maybe-car (cdr m)))))
1148         ((eq (car m) 'eval) (eval (cdr m)))
1149         (t "")))
1150
1151 (defun mdw-choose-dynamic-fill-prefix ()
1152   "Work out the dynamic fill prefix based on the variable `mdw-fill-prefix'."
1153   (cond ((and fill-prefix (not (string= fill-prefix ""))) fill-prefix)
1154         ((not mdw-fill-prefix) fill-prefix)
1155         (t (save-excursion
1156              (beginning-of-line)
1157              (save-match-data
1158                (mdw-examine-fill-prefixes mdw-fill-prefix))))))
1159
1160 (defadvice do-auto-fill (around mdw-dynamic-fill-prefix () activate compile)
1161   "Handle auto-filling, working out a dynamic fill prefix in the
1162 case where there isn't a sensible static one."
1163   (let ((fill-prefix (mdw-choose-dynamic-fill-prefix)))
1164     ad-do-it))
1165
1166 (defun mdw-fill-paragraph ()
1167   "Fill paragraph, getting a dynamic fill prefix."
1168   (interactive)
1169   (let ((fill-prefix (mdw-choose-dynamic-fill-prefix)))
1170     (fill-paragraph nil)))
1171
1172 (defun mdw-standard-fill-prefix (rx &optional mat)
1173   "Set the dynamic fill prefix, handling standard hanging indents and stuff.
1174 This is just a short-cut for setting the thing by hand, and by
1175 design it doesn't cope with anything approximating a complicated
1176 case."
1177   (setq mdw-fill-prefix
1178         `((,(concat rx mdw-hanging-indents)
1179            (match . 1)
1180            (pad . ,(or mat 2))))))
1181
1182 ;;;--------------------------------------------------------------------------
1183 ;;; Other common declarations.
1184
1185 ;; Common mode settings.
1186
1187 (defvar mdw-auto-indent t
1188   "Whether to indent automatically after a newline.")
1189
1190 (defun mdw-whitespace-mode (&optional arg)
1191   "Turn on/off whitespace mode, but don't highlight trailing space."
1192   (interactive "P")
1193   (when (and (boundp 'whitespace-style)
1194              (fboundp 'whitespace-mode))
1195     (let ((whitespace-style (remove 'trailing whitespace-style)))
1196       (whitespace-mode arg))
1197     (setq show-trailing-whitespace whitespace-mode)))
1198
1199 (defvar mdw-do-misc-mode-hacking nil)
1200
1201 (defun mdw-misc-mode-config ()
1202   (and mdw-auto-indent
1203        (cond ((eq major-mode 'lisp-mode)
1204               (local-set-key "\C-m" 'mdw-indent-newline-and-indent))
1205              ((derived-mode-p 'slime-repl-mode 'asm-mode 'comint-mode)
1206               nil)
1207              (t
1208               (local-set-key "\C-m" 'newline-and-indent))))
1209   (set (make-local-variable 'mdw-do-misc-mode-hacking) t)
1210   (local-set-key [C-return] 'newline)
1211   (make-local-variable 'page-delimiter)
1212   (setq page-delimiter "\f\\|^.*-\\{6\\}.*$")
1213   (setq comment-column 40)
1214   (auto-fill-mode 1)
1215   (setq fill-column mdw-text-width)
1216   (and (fboundp 'gtags-mode)
1217        (gtags-mode))
1218   (if (fboundp 'hs-minor-mode)
1219       (trap (hs-minor-mode t))
1220     (outline-minor-mode t))
1221   (reveal-mode t)
1222   (trap (turn-on-font-lock)))
1223
1224 (defun mdw-post-local-vars-misc-mode-config ()
1225   (setq whitespace-line-column mdw-text-width)
1226   (when (and mdw-do-misc-mode-hacking
1227              (not buffer-read-only))
1228     (setq show-trailing-whitespace t)
1229     (mdw-whitespace-mode 1)))
1230 (add-hook 'hack-local-variables-hook 'mdw-post-local-vars-misc-mode-config)
1231
1232 (defmacro mdw-advise-update-angry-fruit-salad (&rest funcs)
1233   `(progn ,@(mapcar (lambda (func)
1234                       `(defadvice ,func
1235                            (after mdw-angry-fruit-salad activate)
1236                          (when mdw-do-misc-mode-hacking
1237                            (setq show-trailing-whitespace
1238                                  (not buffer-read-only))
1239                            (mdw-whitespace-mode (if buffer-read-only 0 1)))))
1240                     funcs)))
1241 (mdw-advise-update-angry-fruit-salad toggle-read-only
1242                                      read-only-mode
1243                                      view-mode
1244                                      view-mode-enable
1245                                      view-mode-disable)
1246
1247 (eval-after-load 'gtags
1248   '(progn
1249      (dolist (key '([mouse-2] [mouse-3]))
1250        (define-key gtags-mode-map key nil))
1251      (define-key gtags-mode-map [C-S-mouse-2] 'gtags-find-tag-by-event)
1252      (define-key gtags-select-mode-map [C-S-mouse-2]
1253        'gtags-select-tag-by-event)
1254      (dolist (map (list gtags-mode-map gtags-select-mode-map))
1255        (define-key map [C-S-mouse-3] 'gtags-pop-stack))))
1256
1257 ;; Backup file handling.
1258
1259 (defvar mdw-backup-disable-regexps nil
1260   "*List of regular expressions: if a file name matches any of
1261 these then the file is not backed up.")
1262
1263 (defun mdw-backup-enable-predicate (name)
1264   "[mdw]'s default backup predicate.
1265 Allows a backup if the standard predicate would allow it, and it
1266 doesn't match any of the regular expressions in
1267 `mdw-backup-disable-regexps'."
1268   (and (normal-backup-enable-predicate name)
1269        (let ((answer t) (list mdw-backup-disable-regexps))
1270          (save-match-data
1271            (while list
1272              (if (string-match (car list) name)
1273                  (setq answer nil))
1274              (setq list (cdr list)))
1275            answer))))
1276 (setq backup-enable-predicate 'mdw-backup-enable-predicate)
1277
1278 ;; Frame cleanup.
1279
1280 (defun mdw-last-one-out-turn-off-the-lights (frame)
1281   "Disconnect from an X display if this was the last frame on that display."
1282   (let ((frame-display (frame-parameter frame 'display)))
1283     (when (and frame-display
1284                (eq window-system 'x)
1285                (not (some (lambda (fr)
1286                             (and (not (eq fr frame))
1287                                  (string= (frame-parameter fr 'display)
1288                                           frame-display)))
1289                           (frame-list))))
1290       (run-with-idle-timer 0 nil #'x-close-connection frame-display))))
1291 (add-hook 'delete-frame-functions 'mdw-last-one-out-turn-off-the-lights)
1292
1293 ;;;--------------------------------------------------------------------------
1294 ;;; Fullscreen-ness.
1295
1296 (defvar mdw-full-screen-parameters
1297   '((menu-bar-lines . 0)
1298     ;(vertical-scroll-bars . nil)
1299     )
1300   "Frame parameters to set when making a frame fullscreen.")
1301
1302 (defvar mdw-full-screen-save
1303   '(width height)
1304   "Extra frame parameters to save when setting fullscreen.")
1305
1306 (defun mdw-toggle-full-screen (&optional frame)
1307   "Show the FRAME fullscreen."
1308   (interactive)
1309   (when window-system
1310     (cond ((frame-parameter frame 'fullscreen)
1311            (set-frame-parameter frame 'fullscreen nil)
1312            (modify-frame-parameters
1313             nil
1314             (or (frame-parameter frame 'mdw-full-screen-saved)
1315                 (mapcar (lambda (assoc)
1316                           (assq (car assoc) default-frame-alist))
1317                         mdw-full-screen-parameters))))
1318           (t
1319            (let ((saved (mapcar (lambda (param)
1320                                   (cons param (frame-parameter frame param)))
1321                                 (append (mapcar #'car
1322                                                 mdw-full-screen-parameters)
1323                                         mdw-full-screen-save))))
1324              (set-frame-parameter frame 'mdw-full-screen-saved saved))
1325            (modify-frame-parameters frame mdw-full-screen-parameters)
1326            (set-frame-parameter frame 'fullscreen 'fullboth)))))
1327
1328 ;;;--------------------------------------------------------------------------
1329 ;;; General fontification.
1330
1331 (make-face 'mdw-virgin-face)
1332
1333 (defmacro mdw-define-face (name &rest body)
1334   "Define a face, and make sure it's actually set as the definition."
1335   (declare (indent 1)
1336            (debug 0))
1337   `(progn
1338      (copy-face 'mdw-virgin-face ',name)
1339      (defvar ,name ',name)
1340      (put ',name 'face-defface-spec ',body)
1341      (face-spec-set ',name ',body nil)))
1342
1343 (mdw-define-face default
1344   (((type w32)) :family "courier new" :height 85)
1345   (((type x)) :family "6x13" :foundry "trad" :height 130)
1346   (((type color)) :foreground "white" :background "black")
1347   (t nil))
1348 (mdw-define-face fixed-pitch
1349   (((type w32)) :family "courier new" :height 85)
1350   (((type x)) :family "6x13" :foundry "trad" :height 130)
1351   (t :foreground "white" :background "black"))
1352 (if (mdw-emacs-version-p 23)
1353     (mdw-define-face variable-pitch
1354       (((type x)) :family "sans" :height 100))
1355   (mdw-define-face variable-pitch
1356     (((type x)) :family "helvetica" :height 90)))
1357 (mdw-define-face region
1358   (((min-colors 64)) :background "grey30")
1359   (((class color)) :background "blue")
1360   (t :inverse-video t))
1361 (mdw-define-face match
1362   (((class color)) :background "blue")
1363   (t :inverse-video t))
1364 (mdw-define-face mc/cursor-face
1365   (((class color)) :background "red")
1366   (t :inverse-video t))
1367 (mdw-define-face minibuffer-prompt
1368   (t :weight bold))
1369 (mdw-define-face mode-line
1370   (((class color)) :foreground "blue" :background "yellow"
1371                    :box (:line-width 1 :style released-button))
1372   (t :inverse-video t))
1373 (mdw-define-face mode-line-inactive
1374   (((class color)) :foreground "yellow" :background "blue"
1375                    :box (:line-width 1 :style released-button))
1376   (t :inverse-video t))
1377 (mdw-define-face nobreak-space
1378   (((type tty)))
1379   (t :inherit escape-glyph :underline t))
1380 (mdw-define-face scroll-bar
1381   (t :foreground "black" :background "lightgrey"))
1382 (mdw-define-face fringe
1383   (t :foreground "yellow"))
1384 (mdw-define-face show-paren-match
1385   (((min-colors 64)) :background "darkgreen")
1386   (((class color)) :background "green")
1387   (t :underline t))
1388 (mdw-define-face show-paren-mismatch
1389   (((class color)) :background "red")
1390   (t :inverse-video t))
1391 (mdw-define-face highlight
1392   (((min-colors 64)) :background "DarkSeaGreen4")
1393   (((class color)) :background "cyan")
1394   (t :inverse-video t))
1395
1396 (mdw-define-face holiday-face
1397   (t :background "red"))
1398 (mdw-define-face calendar-today-face
1399   (t :foreground "yellow" :weight bold))
1400
1401 (mdw-define-face comint-highlight-prompt
1402   (t :weight bold))
1403 (mdw-define-face comint-highlight-input
1404   (t nil))
1405
1406 (mdw-define-face ido-subdir
1407   (t :foreground "cyan" :weight bold))
1408
1409 (mdw-define-face dired-directory
1410   (t :foreground "cyan" :weight bold))
1411 (mdw-define-face dired-symlink
1412   (t :foreground "cyan"))
1413 (mdw-define-face dired-perm-write
1414   (t nil))
1415
1416 (mdw-define-face trailing-whitespace
1417   (((class color)) :background "red")
1418   (t :inverse-video t))
1419 (mdw-define-face whitespace-line
1420   (((class color)) :background "darkred")
1421   (t :inverse-video t))
1422 (mdw-define-face mdw-punct-face
1423   (((min-colors 64)) :foreground "burlywood2")
1424   (((class color)) :foreground "yellow"))
1425 (mdw-define-face mdw-number-face
1426   (t :foreground "yellow"))
1427 (mdw-define-face mdw-trivial-face)
1428 (mdw-define-face font-lock-function-name-face
1429   (t :slant italic))
1430 (mdw-define-face font-lock-keyword-face
1431   (t :weight bold))
1432 (mdw-define-face font-lock-constant-face
1433   (t :slant italic))
1434 (mdw-define-face font-lock-builtin-face
1435   (t :weight bold))
1436 (mdw-define-face font-lock-type-face
1437   (t :weight bold :slant italic))
1438 (mdw-define-face font-lock-reference-face
1439   (t :weight bold))
1440 (mdw-define-face font-lock-variable-name-face
1441   (t :slant italic))
1442 (mdw-define-face font-lock-comment-delimiter-face
1443   (((min-colors 64)) :slant italic :foreground "SeaGreen1")
1444   (((class color)) :foreground "green")
1445   (t :weight bold))
1446 (mdw-define-face font-lock-comment-face
1447   (((min-colors 64)) :slant italic :foreground "SeaGreen1")
1448   (((class color)) :foreground "green")
1449   (t :weight bold))
1450 (mdw-define-face font-lock-string-face
1451   (((min-colors 64)) :foreground "SkyBlue1")
1452   (((class color)) :foreground "cyan")
1453   (t :weight bold))
1454
1455 (mdw-define-face message-separator
1456   (t :background "red" :foreground "white" :weight bold))
1457 (mdw-define-face message-cited-text
1458   (default :slant italic)
1459   (((min-colors 64)) :foreground "SkyBlue1")
1460   (((class color)) :foreground "cyan"))
1461 (mdw-define-face message-header-cc
1462   (default :slant italic)
1463   (((min-colors 64)) :foreground "SeaGreen1")
1464   (((class color)) :foreground "green"))
1465 (mdw-define-face message-header-newsgroups
1466   (default :slant italic)
1467   (((min-colors 64)) :foreground "SeaGreen1")
1468   (((class color)) :foreground "green"))
1469 (mdw-define-face message-header-subject
1470   (((min-colors 64)) :foreground "SeaGreen1")
1471   (((class color)) :foreground "green"))
1472 (mdw-define-face message-header-to
1473   (((min-colors 64)) :foreground "SeaGreen1")
1474   (((class color)) :foreground "green"))
1475 (mdw-define-face message-header-xheader
1476   (default :slant italic)
1477   (((min-colors 64)) :foreground "SeaGreen1")
1478   (((class color)) :foreground "green"))
1479 (mdw-define-face message-header-other
1480   (default :slant italic)
1481   (((min-colors 64)) :foreground "SeaGreen1")
1482   (((class color)) :foreground "green"))
1483 (mdw-define-face message-header-name
1484   (default :weight bold)
1485   (((min-colors 64)) :foreground "SeaGreen1")
1486   (((class color)) :foreground "green"))
1487
1488 (mdw-define-face which-func
1489   (t nil))
1490
1491 (mdw-define-face gnus-header-name
1492   (default :weight bold)
1493   (((min-colors 64)) :foreground "SeaGreen1")
1494   (((class color)) :foreground "green"))
1495 (mdw-define-face gnus-header-subject
1496   (((min-colors 64)) :foreground "SeaGreen1")
1497   (((class color)) :foreground "green"))
1498 (mdw-define-face gnus-header-from
1499   (((min-colors 64)) :foreground "SeaGreen1")
1500   (((class color)) :foreground "green"))
1501 (mdw-define-face gnus-header-to
1502   (((min-colors 64)) :foreground "SeaGreen1")
1503   (((class color)) :foreground "green"))
1504 (mdw-define-face gnus-header-content
1505   (default :slant italic)
1506   (((min-colors 64)) :foreground "SeaGreen1")
1507   (((class color)) :foreground "green"))
1508
1509 (mdw-define-face gnus-cite-1
1510   (((min-colors 64)) :foreground "SkyBlue1")
1511   (((class color)) :foreground "cyan"))
1512 (mdw-define-face gnus-cite-2
1513   (((min-colors 64)) :foreground "RoyalBlue2")
1514   (((class color)) :foreground "blue"))
1515 (mdw-define-face gnus-cite-3
1516   (((min-colors 64)) :foreground "MediumOrchid")
1517   (((class color)) :foreground "magenta"))
1518 (mdw-define-face gnus-cite-4
1519   (((min-colors 64)) :foreground "firebrick2")
1520   (((class color)) :foreground "red"))
1521 (mdw-define-face gnus-cite-5
1522   (((min-colors 64)) :foreground "burlywood2")
1523   (((class color)) :foreground "yellow"))
1524 (mdw-define-face gnus-cite-6
1525   (((min-colors 64)) :foreground "SeaGreen1")
1526   (((class color)) :foreground "green"))
1527 (mdw-define-face gnus-cite-7
1528   (((min-colors 64)) :foreground "SlateBlue1")
1529   (((class color)) :foreground "cyan"))
1530 (mdw-define-face gnus-cite-8
1531   (((min-colors 64)) :foreground "RoyalBlue2")
1532   (((class color)) :foreground "blue"))
1533 (mdw-define-face gnus-cite-9
1534   (((min-colors 64)) :foreground "purple2")
1535   (((class color)) :foreground "magenta"))
1536 (mdw-define-face gnus-cite-10
1537   (((min-colors 64)) :foreground "DarkOrange2")
1538   (((class color)) :foreground "red"))
1539 (mdw-define-face gnus-cite-11
1540   (t :foreground "grey"))
1541
1542 (mdw-define-face diff-header
1543   (t nil))
1544 (mdw-define-face diff-index
1545   (t :weight bold))
1546 (mdw-define-face diff-file-header
1547   (t :weight bold))
1548 (mdw-define-face diff-hunk-header
1549   (((min-colors 64)) :foreground "SkyBlue1")
1550   (((class color)) :foreground "cyan"))
1551 (mdw-define-face diff-function
1552   (default :weight bold)
1553   (((min-colors 64)) :foreground "SkyBlue1")
1554   (((class color)) :foreground "cyan"))
1555 (mdw-define-face diff-header
1556   (((min-colors 64)) :background "grey10"))
1557 (mdw-define-face diff-added
1558   (((class color)) :foreground "green"))
1559 (mdw-define-face diff-removed
1560   (((class color)) :foreground "red"))
1561 (mdw-define-face diff-context
1562   (t nil))
1563 (mdw-define-face diff-refine-change
1564   (((min-colors 64)) :background "RoyalBlue4")
1565   (t :underline t))
1566 (mdw-define-face diff-refine-removed
1567   (((min-colors 64)) :background "#500")
1568   (t :underline t))
1569 (mdw-define-face diff-refine-added
1570   (((min-colors 64)) :background "#050")
1571   (t :underline t))
1572
1573 (setq ediff-force-faces t)
1574 (mdw-define-face ediff-current-diff-A
1575   (((min-colors 64)) :background "darkred")
1576   (((class color)) :background "red")
1577   (t :inverse-video t))
1578 (mdw-define-face ediff-fine-diff-A
1579   (((min-colors 64)) :background "red3")
1580   (((class color)) :inverse-video t)
1581   (t :inverse-video nil))
1582 (mdw-define-face ediff-even-diff-A
1583   (((min-colors 64)) :background "#300"))
1584 (mdw-define-face ediff-odd-diff-A
1585   (((min-colors 64)) :background "#300"))
1586 (mdw-define-face ediff-current-diff-B
1587   (((min-colors 64)) :background "darkgreen")
1588   (((class color)) :background "magenta")
1589   (t :inverse-video t))
1590 (mdw-define-face ediff-fine-diff-B
1591   (((min-colors 64)) :background "green4")
1592   (((class color)) :inverse-video t)
1593   (t :inverse-video nil))
1594 (mdw-define-face ediff-even-diff-B
1595   (((min-colors 64)) :background "#020"))
1596 (mdw-define-face ediff-odd-diff-B
1597   (((min-colors 64)) :background "#020"))
1598 (mdw-define-face ediff-current-diff-C
1599   (((min-colors 64)) :background "darkblue")
1600   (((class color)) :background "blue")
1601   (t :inverse-video t))
1602 (mdw-define-face ediff-fine-diff-C
1603   (((min-colors 64)) :background "blue1")
1604   (((class color)) :inverse-video t)
1605   (t :inverse-video nil))
1606 (mdw-define-face ediff-even-diff-C
1607   (((min-colors 64)) :background "#004"))
1608 (mdw-define-face ediff-odd-diff-C
1609   (((min-colors 64)) :background "#004"))
1610 (mdw-define-face ediff-current-diff-Ancestor
1611   (((min-colors 64)) :background "#630")
1612   (((class color)) :background "blue")
1613   (t :inverse-video t))
1614 (mdw-define-face ediff-even-diff-Ancestor
1615   (((min-colors 64)) :background "#320"))
1616 (mdw-define-face ediff-odd-diff-Ancestor
1617   (((min-colors 64)) :background "#320"))
1618
1619 (mdw-define-face magit-hash
1620   (((min-colors 64)) :foreground "grey40")
1621   (((class color)) :foreground "blue"))
1622 (mdw-define-face magit-diff-hunk-heading
1623   (((min-colors 64)) :foreground "grey70" :background "grey25")
1624   (((class color)) :foreground "yellow"))
1625 (mdw-define-face magit-diff-hunk-heading-highlight
1626   (((min-colors 64)) :foreground "grey70" :background "grey35")
1627   (((class color)) :foreground "yellow" :background "blue"))
1628 (mdw-define-face magit-diff-added
1629   (((min-colors 64)) :foreground "#ddffdd" :background "#335533")
1630   (((class color)) :foreground "green"))
1631 (mdw-define-face magit-diff-added-highlight
1632   (((min-colors 64)) :foreground "#cceecc" :background "#336633")
1633   (((class color)) :foreground "green" :background "blue"))
1634 (mdw-define-face magit-diff-removed
1635   (((min-colors 64)) :foreground "#ffdddd" :background "#553333")
1636   (((class color)) :foreground "red"))
1637 (mdw-define-face magit-diff-removed-highlight
1638   (((min-colors 64)) :foreground "#eecccc" :background "#663333")
1639   (((class color)) :foreground "red" :background "blue"))
1640 (mdw-define-face magit-blame-heading
1641   (((min-colors 64)) :foreground "white" :background "grey25"
1642                      :weight normal :slant normal)
1643   (((class color)) :foreground "white" :background "blue"
1644                    :weight normal :slant normal))
1645 (mdw-define-face magit-blame-name
1646   (t :inherit magit-blame-heading :slant italic))
1647 (mdw-define-face magit-blame-date
1648   (((min-colors 64)) :inherit magit-blame-heading :foreground "grey60")
1649   (((class color)) :inherit magit-blame-heading :foreground "cyan"))
1650 (mdw-define-face magit-blame-summary
1651   (t :inherit magit-blame-heading :weight bold))
1652
1653 (mdw-define-face dylan-header-background
1654   (((min-colors 64)) :background "NavyBlue")
1655   (((class color)) :background "blue"))
1656
1657 (mdw-define-face erc-input-face
1658   (t :foreground "red"))
1659
1660 (mdw-define-face woman-bold
1661   (t :weight bold))
1662 (mdw-define-face woman-italic
1663   (t :slant italic))
1664
1665 (eval-after-load "rst"
1666   '(progn
1667      (mdw-define-face rst-level-1-face
1668        (t :foreground "SkyBlue1" :weight bold))
1669      (mdw-define-face rst-level-2-face
1670        (t :foreground "SeaGreen1" :weight bold))
1671      (mdw-define-face rst-level-3-face
1672        (t :weight bold))
1673      (mdw-define-face rst-level-4-face
1674        (t :slant italic))
1675      (mdw-define-face rst-level-5-face
1676        (t :underline t))
1677      (mdw-define-face rst-level-6-face
1678        ())))
1679
1680 (mdw-define-face p4-depot-added-face
1681   (t :foreground "green"))
1682 (mdw-define-face p4-depot-branch-op-face
1683   (t :foreground "yellow"))
1684 (mdw-define-face p4-depot-deleted-face
1685   (t :foreground "red"))
1686 (mdw-define-face p4-depot-unmapped-face
1687   (t :foreground "SkyBlue1"))
1688 (mdw-define-face p4-diff-change-face
1689   (t :foreground "yellow"))
1690 (mdw-define-face p4-diff-del-face
1691   (t :foreground "red"))
1692 (mdw-define-face p4-diff-file-face
1693   (t :foreground "SkyBlue1"))
1694 (mdw-define-face p4-diff-head-face
1695   (t :background "grey10"))
1696 (mdw-define-face p4-diff-ins-face
1697   (t :foreground "green"))
1698
1699 (mdw-define-face w3m-anchor-face
1700   (t :foreground "SkyBlue1" :underline t))
1701 (mdw-define-face w3m-arrived-anchor-face
1702   (t :foreground "SkyBlue1" :underline t))
1703
1704 (mdw-define-face whizzy-slice-face
1705   (t :background "grey10"))
1706 (mdw-define-face whizzy-error-face
1707   (t :background "darkred"))
1708
1709 ;; Ellipses used to indicate hidden text (and similar).
1710 (mdw-define-face mdw-ellipsis-face
1711   (((type tty)) :foreground "blue") (t :foreground "grey60"))
1712 (let ((dollar (make-glyph-code ?$ 'mdw-ellipsis-face))
1713       (backslash (make-glyph-code ?\\ 'mdw-ellipsis-face))
1714       (dot (make-glyph-code ?. 'mdw-ellipsis-face))
1715       (bar (make-glyph-code ?| mdw-ellipsis-face)))
1716   (set-display-table-slot standard-display-table 0 dollar)
1717   (set-display-table-slot standard-display-table 1 backslash)
1718   (set-display-table-slot standard-display-table 4
1719                           (vector dot dot dot))
1720   (set-display-table-slot standard-display-table 5 bar))
1721
1722 ;;;--------------------------------------------------------------------------
1723 ;;; Where is point?
1724
1725 (mdw-define-face mdw-point-overlay-face
1726   (((type graphic)))
1727   (((min-colors 64)) :background "darkblue")
1728   (((class color)) :background "blue")
1729   (((type tty) (class mono)) :inverse-video t))
1730
1731 (defvar mdw-point-overlay-fringe-display '(vertical-bar . vertical-bar))
1732
1733 (defun mdw-configure-point-overlay ()
1734   (let ((ov (make-overlay 0 0)))
1735     (overlay-put ov 'priority 0)
1736     (let* ((fringe (or mdw-point-overlay-fringe-display (cons nil nil)))
1737            (left (car fringe)) (right (cdr fringe))
1738            (s ""))
1739       (when left
1740         (let ((ss "."))
1741           (put-text-property 0 1 'display `(left-fringe ,left) ss)
1742           (setq s (concat s ss))))
1743       (when right
1744         (let ((ss "."))
1745           (put-text-property 0 1 'display `(right-fringe ,right) ss)
1746           (setq s (concat s ss))))
1747       (when (or left right)
1748         (overlay-put ov 'before-string s)))
1749     (overlay-put ov 'face 'mdw-point-overlay-face)
1750     (delete-overlay ov)
1751     ov))
1752
1753 (defvar mdw-point-overlay (mdw-configure-point-overlay)
1754   "An overlay used for showing where point is in the selected window.")
1755 (defun mdw-reconfigure-point-overlay ()
1756   (interactive)
1757   (setq mdw-point-overlay (mdw-configure-point-overlay)))
1758
1759 (defun mdw-remove-point-overlay ()
1760   "Remove the current-point overlay."
1761   (delete-overlay mdw-point-overlay))
1762
1763 (defun mdw-update-point-overlay ()
1764   "Mark the current point position with an overlay."
1765   (if (not mdw-point-overlay-mode)
1766       (mdw-remove-point-overlay)
1767     (overlay-put mdw-point-overlay 'window (selected-window))
1768     (move-overlay mdw-point-overlay
1769                   (line-beginning-position)
1770                   (+ (line-end-position) 1))))
1771
1772 (defvar mdw-point-overlay-buffers nil
1773   "List of buffers using `mdw-point-overlay-mode'.")
1774
1775 (define-minor-mode mdw-point-overlay-mode
1776   "Indicate current line with an overlay."
1777   :global nil
1778   (let ((buffer (current-buffer)))
1779     (setq mdw-point-overlay-buffers
1780           (mapcan (lambda (buf)
1781                     (if (and (buffer-live-p buf)
1782                              (not (eq buf buffer)))
1783                         (list buf)))
1784                   mdw-point-overlay-buffers))
1785     (if mdw-point-overlay-mode
1786         (setq mdw-point-overlay-buffers
1787               (cons buffer mdw-point-overlay-buffers))))
1788   (cond (mdw-point-overlay-buffers
1789          (add-hook 'pre-command-hook 'mdw-remove-point-overlay)
1790          (add-hook 'post-command-hook 'mdw-update-point-overlay))
1791         (t
1792          (mdw-remove-point-overlay)
1793          (remove-hook 'pre-command-hook 'mdw-remove-point-overlay)
1794          (remove-hook 'post-command-hook 'mdw-update-point-overlay))))
1795
1796 (define-globalized-minor-mode mdw-global-point-overlay-mode
1797   mdw-point-overlay-mode
1798   (lambda () (if (not (minibufferp)) (mdw-point-overlay-mode t))))
1799
1800 ;;;--------------------------------------------------------------------------
1801 ;;; C programming configuration.
1802
1803 ;; Make C indentation nice.
1804
1805 (defun mdw-c-lineup-arglist (langelem)
1806   "Hack for DWIMmery in c-lineup-arglist."
1807   (if (save-excursion
1808         (c-block-in-arglist-dwim (c-langelem-2nd-pos c-syntactic-element)))
1809       0
1810     (c-lineup-arglist langelem)))
1811
1812 (defun mdw-c-indent-extern-mumble (langelem)
1813   "Indent `extern \"...\" {' lines."
1814   (save-excursion
1815     (back-to-indentation)
1816     (if (looking-at
1817          "\\s-*\\<extern\\>\\s-*\"\\([^\\\\\"]+\\|\\.\\)*\"\\s-*{")
1818         c-basic-offset
1819       nil)))
1820
1821 (defun mdw-c-indent-arglist-nested (langelem)
1822   "Indent continued argument lists.
1823 If we've nested more than one argument list, then only introduce a single
1824 indentation anyway."
1825   (let ((context c-syntactic-context)
1826         (pos (c-langelem-2nd-pos c-syntactic-element))
1827         (should-indent-p t))
1828     (while (and context
1829                 (eq (caar context) 'arglist-cont-nonempty))
1830       (when (and (= (caddr (pop context)) pos)
1831                  context
1832                  (memq (caar context) '(arglist-intro
1833                                         arglist-cont-nonempty)))
1834         (setq should-indent-p nil)))
1835     (if should-indent-p '+ 0)))
1836
1837 (defvar mdw-define-c-styles-hook nil
1838   "Hook run when `cc-mode' starts up to define styles.")
1839
1840 (defmacro mdw-define-c-style (name &rest assocs)
1841   "Define a C style, called NAME (a symbol), setting ASSOCs.
1842 A function, named `mdw-define-c-style/NAME', is defined to actually install
1843 the style using `c-add-style', and added to the hook
1844 `mdw-define-c-styles-hook'.  If CC Mode is already loaded, then the style is
1845 set."
1846   (declare (indent defun))
1847   (let* ((name-string (symbol-name name))
1848          (func (intern (concat "mdw-define-c-style/" name-string))))
1849     `(progn
1850        (defun ,func () (c-add-style ,name-string ',assocs))
1851        (and (featurep 'cc-mode) (,func))
1852        (add-hook 'mdw-define-c-styles-hook ',func))))
1853
1854 (eval-after-load "cc-mode"
1855   '(run-hooks 'mdw-define-c-styles-hook))
1856
1857 (mdw-define-c-style mdw-trustonic-c
1858   (c-basic-offset . 4)
1859   (comment-column . 0)
1860   (c-indent-comment-alist (anchored-comment . (column . 0))
1861                           (end-block . (space . 1))
1862                           (cpp-end-block . (space . 1))
1863                           (other . (space . 1)))
1864   (c-class-key . "class")
1865   (c-backslash-column . 0)
1866   (c-auto-align-backslashes . nil)
1867   (c-label-minimum-indentation . 0)
1868   (c-offsets-alist (substatement-open . (add 0 c-indent-one-line-block))
1869                    (defun-open . (add 0 c-indent-one-line-block))
1870                    (arglist-cont-nonempty . mdw-c-indent-arglist-nested)
1871                    (topmost-intro . mdw-c-indent-extern-mumble)
1872                    (cpp-define-intro . 0)
1873                    (knr-argdecl . 0)
1874                    (inextern-lang . [0])
1875                    (label . 0)
1876                    (case-label . +)
1877                    (access-label . -2)
1878                    (inclass . +)
1879                    (inline-open . ++)
1880                    (statement-cont . +)
1881                    (statement-case-intro . +)))
1882
1883 (mdw-define-c-style mdw-c
1884   (c-basic-offset . 2)
1885   (comment-column . 40)
1886   (c-class-key . "class")
1887   (c-backslash-column . 72)
1888   (c-label-minimum-indentation . 0)
1889   (c-offsets-alist (substatement-open . (add 0 c-indent-one-line-block))
1890                    (defun-open . (add 0 c-indent-one-line-block))
1891                    (arglist-cont-nonempty . mdw-c-lineup-arglist)
1892                    (topmost-intro . mdw-c-indent-extern-mumble)
1893                    (cpp-define-intro . 0)
1894                    (knr-argdecl . 0)
1895                    (inextern-lang . [0])
1896                    (label . 0)
1897                    (case-label . +)
1898                    (access-label . -)
1899                    (inclass . +)
1900                    (inline-open . ++)
1901                    (statement-cont . +)
1902                    (statement-case-intro . +)))
1903
1904 (defun mdw-set-default-c-style (modes style)
1905   "Update the default CC Mode style for MODES to be STYLE.
1906
1907 MODES may be a list of major mode names or a singleton.  STYLE is a style
1908 name, as a symbol."
1909   (let ((modes (if (listp modes) modes (list modes)))
1910         (style (symbol-name style)))
1911     (setq c-default-style
1912           (append (mapcar (lambda (mode)
1913                             (cons mode style))
1914                           modes)
1915                   (remove-if (lambda (assoc)
1916                                (memq (car assoc) modes))
1917                              (if (listp c-default-style)
1918                                  c-default-style
1919                                (list (cons 'other c-default-style))))))))
1920 (setq c-default-style "mdw-c")
1921
1922 (mdw-set-default-c-style '(c-mode c++-mode) 'mdw-c)
1923
1924 (defvar mdw-c-comment-fill-prefix
1925   `((,(concat "\\([ \t]*/?\\)"
1926               "\\(\*\\|//]\\)"
1927               "\\([ \t]*\\)"
1928               "\\([A-Za-z]+:[ \t]*\\)?"
1929               mdw-hanging-indents)
1930      (pad . 1) (match . 2) (pad . 3) (pad . 4) (pad . 5)))
1931   "Fill prefix matching C comments (both kinds).")
1932
1933 (defun mdw-fontify-c-and-c++ ()
1934
1935   ;; Fiddle with some syntax codes.
1936   (modify-syntax-entry ?* ". 23")
1937   (modify-syntax-entry ?/ ". 124b")
1938   (modify-syntax-entry ?\n "> b")
1939
1940   ;; Other stuff.
1941   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
1942
1943   ;; Now define things to be fontified.
1944   (make-local-variable 'font-lock-keywords)
1945   (let ((c-keywords
1946          (mdw-regexps "alignas"          ;C11 macro, C++11
1947                       "alignof"          ;C++11
1948                       "and"              ;C++, C95 macro
1949                       "and_eq"           ;C++, C95 macro
1950                       "asm"              ;K&R, C++, GCC
1951                       "atomic"           ;C11 macro, C++11 template type
1952                       "auto"             ;K&R, C89
1953                       "bitand"           ;C++, C95 macro
1954                       "bitor"            ;C++, C95 macro
1955                       "bool"             ;C++, C99 macro
1956                       "break"            ;K&R, C89
1957                       "case"             ;K&R, C89
1958                       "catch"            ;C++
1959                       "char"             ;K&R, C89
1960                       "char16_t"         ;C++11, C11 library type
1961                       "char32_t"         ;C++11, C11 library type
1962                       "class"            ;C++
1963                       "complex"          ;C99 macro, C++ template type
1964                       "compl"            ;C++, C95 macro
1965                       "const"            ;C89
1966                       "constexpr"        ;C++11
1967                       "const_cast"       ;C++
1968                       "continue"         ;K&R, C89
1969                       "decltype"         ;C++11
1970                       "defined"          ;C89 preprocessor
1971                       "default"          ;K&R, C89
1972                       "delete"           ;C++
1973                       "do"               ;K&R, C89
1974                       "double"           ;K&R, C89
1975                       "dynamic_cast"     ;C++
1976                       "else"             ;K&R, C89
1977                       ;; "entry"         ;K&R -- never used
1978                       "enum"             ;C89
1979                       "explicit"         ;C++
1980                       "export"           ;C++
1981                       "extern"           ;K&R, C89
1982                       "float"            ;K&R, C89
1983                       "for"              ;K&R, C89
1984                       ;; "fortran"       ;K&R
1985                       "friend"           ;C++
1986                       "goto"             ;K&R, C89
1987                       "if"               ;K&R, C89
1988                       "imaginary"        ;C99 macro
1989                       "inline"           ;C++, C99, GCC
1990                       "int"              ;K&R, C89
1991                       "long"             ;K&R, C89
1992                       "mutable"          ;C++
1993                       "namespace"        ;C++
1994                       "new"              ;C++
1995                       "noexcept"         ;C++11
1996                       "noreturn"         ;C11 macro
1997                       "not"              ;C++, C95 macro
1998                       "not_eq"           ;C++, C95 macro
1999                       "nullptr"          ;C++11
2000                       "operator"         ;C++
2001                       "or"               ;C++, C95 macro
2002                       "or_eq"            ;C++, C95 macro
2003                       "private"          ;C++
2004                       "protected"        ;C++
2005                       "public"           ;C++
2006                       "register"         ;K&R, C89
2007                       "reinterpret_cast" ;C++
2008                       "restrict"         ;C99
2009                       "return"           ;K&R, C89
2010                       "short"            ;K&R, C89
2011                       "signed"           ;C89
2012                       "sizeof"           ;K&R, C89
2013                       "static"           ;K&R, C89
2014                       "static_assert"    ;C11 macro, C++11
2015                       "static_cast"      ;C++
2016                       "struct"           ;K&R, C89
2017                       "switch"           ;K&R, C89
2018                       "template"         ;C++
2019                       "throw"            ;C++
2020                       "try"              ;C++
2021                       "thread_local"     ;C11 macro, C++11
2022                       "typedef"          ;C89
2023                       "typeid"           ;C++
2024                       "typeof"           ;GCC
2025                       "typename"         ;C++
2026                       "union"            ;K&R, C89
2027                       "unsigned"         ;K&R, C89
2028                       "using"            ;C++
2029                       "virtual"          ;C++
2030                       "void"             ;C89
2031                       "volatile"         ;C89
2032                       "wchar_t"          ;C++, C89 library type
2033                       "while"            ;K&R, C89
2034                       "xor"              ;C++, C95 macro
2035                       "xor_eq"           ;C++, C95 macro
2036                       "_Alignas"         ;C11
2037                       "_Alignof"         ;C11
2038                       "_Atomic"          ;C11
2039                       "_Bool"            ;C99
2040                       "_Complex"         ;C99
2041                       "_Generic"         ;C11
2042                       "_Imaginary"       ;C99
2043                       "_Noreturn"        ;C11
2044                       "_Pragma"          ;C99 preprocessor
2045                       "_Static_assert"   ;C11
2046                       "_Thread_local"    ;C11
2047                       "__alignof__"      ;GCC
2048                       "__asm__"          ;GCC
2049                       "__attribute__"    ;GCC
2050                       "__complex__"      ;GCC
2051                       "__const__"        ;GCC
2052                       "__extension__"    ;GCC
2053                       "__imag__"         ;GCC
2054                       "__inline__"       ;GCC
2055                       "__label__"        ;GCC
2056                       "__real__"         ;GCC
2057                       "__signed__"       ;GCC
2058                       "__typeof__"       ;GCC
2059                       "__volatile__"     ;GCC
2060                       ))
2061         (c-constants
2062          (mdw-regexps "false"            ;C++, C99 macro
2063                       "this"             ;C++
2064                       "true"             ;C++, C99 macro
2065                       ))
2066         (preprocessor-keywords
2067          (mdw-regexps "assert" "define" "elif" "else" "endif" "error"
2068                       "ident" "if" "ifdef" "ifndef" "import" "include"
2069                       "line" "pragma" "unassert" "undef" "warning"))
2070         (objc-keywords
2071          (mdw-regexps "class" "defs" "encode" "end" "implementation"
2072                       "interface" "private" "protected" "protocol" "public"
2073                       "selector")))
2074
2075     (setq font-lock-keywords
2076           (list
2077
2078            ;; Fontify include files as strings.
2079            (list (concat "^[ \t]*\\#[ \t]*"
2080                          "\\(include\\|import\\)"
2081                          "[ \t]*\\(<[^>]+\\(>\\|\\)\\)")
2082                  '(2 font-lock-string-face))
2083
2084            ;; Preprocessor directives are `references'?.
2085            (list (concat "^\\([ \t]*#[ \t]*\\(\\("
2086                          preprocessor-keywords
2087                          "\\)\\>\\|[0-9]+\\|$\\)\\)")
2088                  '(1 font-lock-keyword-face))
2089
2090            ;; Handle the keywords defined above.
2091            (list (concat "@\\<\\(" objc-keywords "\\)\\>")
2092                  '(0 font-lock-keyword-face))
2093
2094            (list (concat "\\<\\(" c-keywords "\\)\\>")
2095                  '(0 font-lock-keyword-face))
2096
2097            (list (concat "\\<\\(" c-constants "\\)\\>")
2098                  '(0 font-lock-variable-name-face))
2099
2100            ;; Handle numbers too.
2101            ;;
2102            ;; This looks strange, I know.  It corresponds to the
2103            ;; preprocessor's idea of what a number looks like, rather than
2104            ;; anything sensible.
2105            (list (concat "\\(\\<[0-9]\\|\\.[0-9]\\)"
2106                          "\\([Ee][+-]\\|[0-9A-Za-z_.]\\)*")
2107                  '(0 mdw-number-face))
2108
2109            ;; And anything else is punctuation.
2110            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2111                  '(0 mdw-punct-face))))))
2112
2113 (define-derived-mode sod-mode c-mode "Sod"
2114   "Major mode for editing Sod code.")
2115 (push '("\\.sod$" . sod-mode) auto-mode-alist)
2116
2117 ;;;--------------------------------------------------------------------------
2118 ;;; AP calc mode.
2119
2120 (define-derived-mode apcalc-mode c-mode "AP Calc"
2121   "Major mode for editing Calc code.")
2122
2123 (defun mdw-fontify-apcalc ()
2124
2125   ;; Fiddle with some syntax codes.
2126   (modify-syntax-entry ?* ". 23")
2127   (modify-syntax-entry ?/ ". 14")
2128
2129   ;; Other stuff.
2130   (setq comment-start "/* ")
2131   (setq comment-end " */")
2132   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
2133
2134   ;; Now define things to be fontified.
2135   (make-local-variable 'font-lock-keywords)
2136   (let ((c-keywords
2137          (mdw-regexps "break" "case" "cd" "continue" "define" "default"
2138                       "do" "else" "exit" "for" "global" "goto" "help" "if"
2139                       "local" "mat" "obj" "print" "quit" "read" "return"
2140                       "show" "static" "switch" "while" "write")))
2141
2142     (setq font-lock-keywords
2143           (list
2144
2145            ;; Handle the keywords defined above.
2146            (list (concat "\\<\\(" c-keywords "\\)\\>")
2147                  '(0 font-lock-keyword-face))
2148
2149            ;; Handle numbers too.
2150            ;;
2151            ;; This looks strange, I know.  It corresponds to the
2152            ;; preprocessor's idea of what a number looks like, rather than
2153            ;; anything sensible.
2154            (list (concat "\\(\\<[0-9]\\|\\.[0-9]\\)"
2155                          "\\([Ee][+-]\\|[0-9A-Za-z_.]\\)*")
2156                  '(0 mdw-number-face))
2157
2158            ;; And anything else is punctuation.
2159            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2160                  '(0 mdw-punct-face))))))
2161
2162 ;;;--------------------------------------------------------------------------
2163 ;;; Java programming configuration.
2164
2165 ;; Make indentation nice.
2166
2167 (mdw-define-c-style mdw-java
2168   (c-basic-offset . 2)
2169   (c-backslash-column . 72)
2170   (c-offsets-alist (substatement-open . 0)
2171                    (label . +)
2172                    (case-label . +)
2173                    (access-label . 0)
2174                    (inclass . +)
2175                    (statement-case-intro . +)))
2176 (mdw-set-default-c-style 'java-mode 'mdw-java)
2177
2178 ;; Declare Java fontification style.
2179
2180 (defun mdw-fontify-java ()
2181
2182   ;; Other stuff.
2183   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
2184
2185   ;; Now define things to be fontified.
2186   (make-local-variable 'font-lock-keywords)
2187   (let ((java-keywords
2188          (mdw-regexps "abstract" "boolean" "break" "byte" "case" "catch"
2189                       "char" "class" "const" "continue" "default" "do"
2190                       "double" "else" "extends" "final" "finally" "float"
2191                       "for" "goto" "if" "implements" "import" "instanceof"
2192                       "int" "interface" "long" "native" "new" "package"
2193                       "private" "protected" "public" "return" "short"
2194                       "static" "switch" "synchronized" "throw" "throws"
2195                       "transient" "try" "void" "volatile" "while"))
2196
2197         (java-constants
2198          (mdw-regexps "false" "null" "super" "this" "true")))
2199
2200     (setq font-lock-keywords
2201           (list
2202
2203            ;; Handle the keywords defined above.
2204            (list (concat "\\<\\(" java-keywords "\\)\\>")
2205                  '(0 font-lock-keyword-face))
2206
2207            ;; Handle the magic constants defined above.
2208            (list (concat "\\<\\(" java-constants "\\)\\>")
2209                  '(0 font-lock-variable-name-face))
2210
2211            ;; Handle numbers too.
2212            ;;
2213            ;; The following isn't quite right, but it's close enough.
2214            (list (concat "\\<\\("
2215                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
2216                          "[0-9]+\\(\\.[0-9]*\\|\\)"
2217                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
2218                          "[lLfFdD]?")
2219                  '(0 mdw-number-face))
2220
2221            ;; And anything else is punctuation.
2222            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2223                  '(0 mdw-punct-face))))))
2224
2225 ;;;--------------------------------------------------------------------------
2226 ;;; Javascript programming configuration.
2227
2228 (defun mdw-javascript-style ()
2229   (setq js-indent-level 2)
2230   (setq js-expr-indent-offset 0))
2231
2232 (defun mdw-fontify-javascript ()
2233
2234   ;; Other stuff.
2235   (mdw-javascript-style)
2236   (setq js-auto-indent-flag t)
2237
2238   ;; Now define things to be fontified.
2239   (make-local-variable 'font-lock-keywords)
2240   (let ((javascript-keywords
2241          (mdw-regexps "abstract" "boolean" "break" "byte" "case" "catch"
2242                       "char" "class" "const" "continue" "debugger" "default"
2243                       "delete" "do" "double" "else" "enum" "export" "extends"
2244                       "final" "finally" "float" "for" "function" "goto" "if"
2245                       "implements" "import" "in" "instanceof" "int"
2246                       "interface" "let" "long" "native" "new" "package"
2247                       "private" "protected" "public" "return" "short"
2248                       "static" "super" "switch" "synchronized" "throw"
2249                       "throws" "transient" "try" "typeof" "var" "void"
2250                       "volatile" "while" "with" "yield"
2251
2252                       "boolean" "byte" "char" "double" "float" "int" "long"
2253                       "short" "void"))
2254         (javascript-constants
2255          (mdw-regexps "false" "null" "undefined" "Infinity" "NaN" "true"
2256                       "arguments" "this")))
2257
2258     (setq font-lock-keywords
2259           (list
2260
2261            ;; Handle the keywords defined above.
2262            (list (concat "\\_<\\(" javascript-keywords "\\)\\_>")
2263                  '(0 font-lock-keyword-face))
2264
2265            ;; Handle the predefined constants defined above.
2266            (list (concat "\\_<\\(" javascript-constants "\\)\\_>")
2267                  '(0 font-lock-variable-name-face))
2268
2269            ;; Handle numbers too.
2270            ;;
2271            ;; The following isn't quite right, but it's close enough.
2272            (list (concat "\\_<\\("
2273                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
2274                          "[0-9]+\\(\\.[0-9]*\\|\\)"
2275                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
2276                          "[lLfFdD]?")
2277                  '(0 mdw-number-face))
2278
2279            ;; And anything else is punctuation.
2280            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2281                  '(0 mdw-punct-face))))))
2282
2283 ;;;--------------------------------------------------------------------------
2284 ;;; Scala programming configuration.
2285
2286 (defun mdw-fontify-scala ()
2287
2288   ;; Comment filling.
2289   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
2290
2291   ;; Define things to be fontified.
2292   (make-local-variable 'font-lock-keywords)
2293   (let ((scala-keywords
2294          (mdw-regexps "abstract" "case" "catch" "class" "def" "do" "else"
2295                       "extends" "final" "finally" "for" "forSome" "if"
2296                       "implicit" "import" "lazy" "match" "new" "object"
2297                       "override" "package" "private" "protected" "return"
2298                       "sealed" "throw" "trait" "try" "type" "val"
2299                       "var" "while" "with" "yield"))
2300         (scala-constants
2301          (mdw-regexps "false" "null" "super" "this" "true"))
2302         (punctuation "[-!%^&*=+:@#~/?\\|`]"))
2303
2304     (setq font-lock-keywords
2305           (list
2306
2307            ;; Magical identifiers between backticks.
2308            (list (concat "`\\([^`]+\\)`")
2309                  '(1 font-lock-variable-name-face))
2310
2311            ;; Handle the keywords defined above.
2312            (list (concat "\\_<\\(" scala-keywords "\\)\\_>")
2313                  '(0 font-lock-keyword-face))
2314
2315            ;; Handle the constants defined above.
2316            (list (concat "\\_<\\(" scala-constants "\\)\\_>")
2317                  '(0 font-lock-variable-name-face))
2318
2319            ;; Magical identifiers between backticks.
2320            (list (concat "`\\([^`]+\\)`")
2321                  '(1 font-lock-variable-name-face))
2322
2323            ;; Handle numbers too.
2324            ;;
2325            ;; As usual, not quite right.
2326            (list (concat "\\_<\\("
2327                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
2328                          "[0-9]+\\(\\.[0-9]*\\|\\)"
2329                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
2330                          "[lLfFdD]?")
2331                  '(0 mdw-number-face))
2332
2333            ;; Identifiers with trailing operators.
2334            (list (concat "_\\(" punctuation "\\)+")
2335                  '(0 mdw-trivial-face))
2336
2337            ;; And everything else is punctuation.
2338            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2339                  '(0 mdw-punct-face)))
2340
2341           font-lock-syntactic-keywords
2342           (list
2343
2344            ;; Single quotes around characters.  But not when used to quote
2345            ;; symbol names.  Ugh.
2346            (list (concat "\\('\\)"
2347                          "\\(" "."
2348                          "\\|" "\\\\" "\\(" "\\\\\\\\" "\\)*"
2349                                "u+" "[0-9a-fA-F]\\{4\\}"
2350                          "\\|" "\\\\" "[0-7]\\{1,3\\}"
2351                          "\\|" "\\\\" "." "\\)"
2352                          "\\('\\)")
2353                  '(1 "\"")
2354                  '(4 "\""))))))
2355
2356 ;;;--------------------------------------------------------------------------
2357 ;;; C# programming configuration.
2358
2359 ;; Make indentation nice.
2360
2361 (mdw-define-c-style mdw-csharp
2362   (c-basic-offset . 2)
2363   (c-backslash-column . 72)
2364   (c-offsets-alist (substatement-open . 0)
2365                    (label . 0)
2366                    (case-label . +)
2367                    (access-label . 0)
2368                    (inclass . +)
2369                    (statement-case-intro . +)))
2370 (mdw-set-default-c-style 'csharp-mode 'mdw-csharp)
2371
2372 ;; Declare C# fontification style.
2373
2374 (defun mdw-fontify-csharp ()
2375
2376   ;; Other stuff.
2377   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
2378
2379   ;; Now define things to be fontified.
2380   (make-local-variable 'font-lock-keywords)
2381   (let ((csharp-keywords
2382          (mdw-regexps "abstract" "as" "bool" "break" "byte" "case" "catch"
2383                       "char" "checked" "class" "const" "continue" "decimal"
2384                       "default" "delegate" "do" "double" "else" "enum"
2385                       "event" "explicit" "extern" "finally" "fixed" "float"
2386                       "for" "foreach" "goto" "if" "implicit" "in" "int"
2387                       "interface" "internal" "is" "lock" "long" "namespace"
2388                       "new" "object" "operator" "out" "override" "params"
2389                       "private" "protected" "public" "readonly" "ref"
2390                       "return" "sbyte" "sealed" "short" "sizeof"
2391                       "stackalloc" "static" "string" "struct" "switch"
2392                       "throw" "try" "typeof" "uint" "ulong" "unchecked"
2393                       "unsafe" "ushort" "using" "virtual" "void" "volatile"
2394                       "while" "yield"))
2395
2396         (csharp-constants
2397          (mdw-regexps "base" "false" "null" "this" "true")))
2398
2399     (setq font-lock-keywords
2400           (list
2401
2402            ;; Handle the keywords defined above.
2403            (list (concat "\\<\\(" csharp-keywords "\\)\\>")
2404                  '(0 font-lock-keyword-face))
2405
2406            ;; Handle the magic constants defined above.
2407            (list (concat "\\<\\(" csharp-constants "\\)\\>")
2408                  '(0 font-lock-variable-name-face))
2409
2410            ;; Handle numbers too.
2411            ;;
2412            ;; The following isn't quite right, but it's close enough.
2413            (list (concat "\\<\\("
2414                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
2415                          "[0-9]+\\(\\.[0-9]*\\|\\)"
2416                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
2417                          "[lLfFdD]?")
2418                  '(0 mdw-number-face))
2419
2420            ;; And anything else is punctuation.
2421            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2422                  '(0 mdw-punct-face))))))
2423
2424 (define-derived-mode csharp-mode java-mode "C#"
2425   "Major mode for editing C# code.")
2426
2427 ;;;--------------------------------------------------------------------------
2428 ;;; F# programming configuration.
2429
2430 (setq fsharp-indent-offset 2)
2431
2432 (defun mdw-fontify-fsharp ()
2433
2434   (let ((punct "=<>+-*/|&%!@?"))
2435     (do ((i 0 (1+ i)))
2436         ((>= i (length punct)))
2437       (modify-syntax-entry (aref punct i) ".")))
2438
2439   (modify-syntax-entry ?_ "_")
2440   (modify-syntax-entry ?( "(")
2441   (modify-syntax-entry ?) ")")
2442
2443   (setq indent-tabs-mode nil)
2444
2445   (let ((fsharp-keywords
2446          (mdw-regexps "abstract" "and" "as" "assert" "atomic"
2447                       "begin" "break"
2448                       "checked" "class" "component" "const" "constraint"
2449                       "constructor" "continue"
2450                       "default" "delegate" "do" "done" "downcast" "downto"
2451                       "eager" "elif" "else" "end" "exception" "extern"
2452                       "finally" "fixed" "for" "fori" "fun" "function"
2453                       "functor"
2454                       "global"
2455                       "if" "in" "include" "inherit" "inline" "interface"
2456                       "internal"
2457                       "lazy" "let"
2458                       "match" "measure" "member" "method" "mixin" "module"
2459                       "mutable"
2460                       "namespace" "new"
2461                       "object" "of" "open" "or" "override"
2462                       "parallel" "params" "private" "process" "protected"
2463                       "public" "pure"
2464                       "rec" "recursive" "return"
2465                       "sealed" "sig" "static" "struct"
2466                       "tailcall" "then" "to" "trait" "try" "type"
2467                       "upcast" "use"
2468                       "val" "virtual" "void" "volatile"
2469                       "when" "while" "with"
2470                       "yield"))
2471
2472         (fsharp-builtins
2473          (mdw-regexps "asr" "land" "lor" "lsl" "lsr" "lxor" "mod"
2474                       "base" "false" "null" "true"))
2475
2476         (bang-keywords
2477          (mdw-regexps "do" "let" "return" "use" "yield"))
2478
2479         (preprocessor-keywords
2480          (mdw-regexps "if" "indent" "else" "endif")))
2481
2482     (setq font-lock-keywords
2483           (list (list (concat "\\(^\\|[^\"]\\)"
2484                               "\\(" "(\\*"
2485                                     "[^*]*\\*+"
2486                                     "\\(" "[^)*]" "[^*]*" "\\*+" "\\)*"
2487                                     ")"
2488                               "\\|"
2489                                     "//.*"
2490                               "\\)")
2491                       '(2 font-lock-comment-face))
2492
2493                 (list (concat "'" "\\("
2494                                     "\\\\"
2495                                     "\\(" "[ntbr'\\]"
2496                                     "\\|" "[0-9][0-9][0-9]"
2497                                     "\\|" "u" "[0-9a-fA-F]\\{4\\}"
2498                                     "\\|" "U" "[0-9a-fA-F]\\{8\\}"
2499                                     "\\)"
2500                                   "\\|"
2501                                   "." "\\)" "'"
2502                               "\\|"
2503                               "\"" "[^\"\\]*"
2504                                     "\\(" "\\\\" "\\(.\\|\n\\)"
2505                                           "[^\"\\]*" "\\)*"
2506                               "\\(\"\\|\\'\\)")
2507                       '(0 font-lock-string-face))
2508
2509                 (list (concat "\\_<\\(" bang-keywords "\\)!" "\\|"
2510                               "^#[ \t]*\\(" preprocessor-keywords "\\)\\_>"
2511                               "\\|"
2512                               "\\_<\\(" fsharp-keywords "\\)\\_>")
2513                       '(0 font-lock-keyword-face))
2514                 (list (concat "\\<\\(" fsharp-builtins "\\)\\_>")
2515                       '(0 font-lock-variable-name-face))
2516
2517                 (list (concat "\\_<"
2518                               "\\(" "0[bB][01]+" "\\|"
2519                                     "0[oO][0-7]+" "\\|"
2520                                     "0[xX][0-9a-fA-F]+" "\\)"
2521                               "\\(" "lf\\|LF" "\\|"
2522                                     "[uU]?[ysnlL]?" "\\)"
2523                               "\\|"
2524                               "\\_<"
2525                               "[0-9]+" "\\("
2526                                 "[mMQRZING]"
2527                                 "\\|"
2528                                 "\\(\\.[0-9]*\\)?"
2529                                 "\\([eE][-+]?[0-9]+\\)?"
2530                                 "[fFmM]?"
2531                                 "\\|"
2532                                 "[uU]?[ysnlL]?"
2533                               "\\)")
2534                       '(0 mdw-number-face))
2535
2536                 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2537                       '(0 mdw-punct-face))))))
2538
2539 (defun mdw-fontify-inferior-fsharp ()
2540   (mdw-fontify-fsharp)
2541   (setq font-lock-keywords
2542         (append (list (list "^[#-]" '(0 font-lock-comment-face))
2543                       (list "^>" '(0 font-lock-keyword-face)))
2544                 font-lock-keywords)))
2545
2546 ;;;--------------------------------------------------------------------------
2547 ;;; Go programming configuration.
2548
2549 (defun mdw-fontify-go ()
2550
2551   (make-local-variable 'font-lock-keywords)
2552   (let ((go-keywords
2553          (mdw-regexps "break" "case" "chan" "const" "continue"
2554                       "default" "defer" "else" "fallthrough" "for"
2555                       "func" "go" "goto" "if" "import"
2556                       "interface" "map" "package" "range" "return"
2557                       "select" "struct" "switch" "type" "var"))
2558         (go-intrinsics
2559          (mdw-regexps "bool" "byte" "complex64" "complex128" "error"
2560                       "float32" "float64" "int" "uint8" "int16" "int32"
2561                       "int64" "rune" "string" "uint" "uint8" "uint16"
2562                       "uint32" "uint64" "uintptr" "void"
2563                       "false" "iota" "nil" "true"
2564                       "init" "main"
2565                       "append" "cap" "copy" "delete" "imag" "len" "make"
2566                       "new" "panic" "real" "recover")))
2567
2568     (setq font-lock-keywords
2569           (list
2570
2571            ;; Handle the keywords defined above.
2572            (list (concat "\\<\\(" go-keywords "\\)\\>")
2573                  '(0 font-lock-keyword-face))
2574            (list (concat "\\<\\(" go-intrinsics "\\)\\>")
2575                  '(0 font-lock-variable-name-face))
2576
2577            ;; Strings and characters.
2578            (list (concat "'"
2579                          "\\(" "[^\\']" "\\|"
2580                                "\\\\"
2581                                "\\(" "[abfnrtv\\'\"]" "\\|"
2582                                      "[0-7]\\{3\\}" "\\|"
2583                                      "x" "[0-9A-Fa-f]\\{2\\}" "\\|"
2584                                      "u" "[0-9A-Fa-f]\\{4\\}" "\\|"
2585                                      "U" "[0-9A-Fa-f]\\{8\\}" "\\)" "\\)"
2586                          "'"
2587                          "\\|"
2588                          "\""
2589                          "\\(" "[^\n\\\"]+" "\\|" "\\\\." "\\)*"
2590                          "\\(\"\\|$\\)"
2591                          "\\|"
2592                          "`" "[^`]+" "`")
2593                  '(0 font-lock-string-face))
2594
2595            ;; Handle numbers too.
2596            ;;
2597            ;; The following isn't quite right, but it's close enough.
2598            (list (concat "\\<\\("
2599                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
2600                          "[0-9]+\\(\\.[0-9]*\\|\\)"
2601                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)")
2602                  '(0 mdw-number-face))
2603
2604            ;; And anything else is punctuation.
2605            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2606                  '(0 mdw-punct-face))))))
2607
2608 ;;;--------------------------------------------------------------------------
2609 ;;; Rust programming configuration.
2610
2611 (setq-default rust-indent-offset 2)
2612
2613 (defun mdw-self-insert-and-indent (count)
2614   (interactive "p")
2615   (self-insert-command count)
2616   (indent-according-to-mode))
2617
2618 (defun mdw-fontify-rust ()
2619
2620   ;; Hack syntax categories.
2621   (modify-syntax-entry ?= ".")
2622
2623   ;; Fontify keywords and things.
2624   (make-local-variable 'font-lock-keywords)
2625   (let ((rust-keywords
2626          (mdw-regexps "abstract" "alignof" "as"
2627                       "become" "box" "break"
2628                       "const" "continue" "create"
2629                       "do"
2630                       "else" "enum" "extern"
2631                       "false" "final" "fn" "for"
2632                       "if" "impl" "in"
2633                       "let" "loop"
2634                       "macro" "match" "mod" "move" "mut"
2635                       "offsetof" "override"
2636                       "priv" "pub" "pure"
2637                       "ref" "return"
2638                       "self" "sizeof" "static" "struct" "super"
2639                       "true" "trait" "type" "typeof"
2640                       "unsafe" "unsized" "use"
2641                       "virtual"
2642                       "where" "while"
2643                       "yield"))
2644         (rust-builtins
2645          (mdw-regexps "array" "pointer" "slice" "tuple"
2646                       "bool" "true" "false"
2647                       "f32" "f64"
2648                       "i8" "i16" "i32" "i64" "isize"
2649                       "u8" "u16" "u32" "u64" "usize"
2650                       "char" "str")))
2651     (setq font-lock-keywords
2652           (list
2653
2654            ;; Handle the keywords defined above.
2655            (list (concat "\\_<\\(" rust-keywords "\\)\\_>")
2656                  '(0 font-lock-keyword-face))
2657            (list (concat "\\_<\\(" rust-builtins "\\)\\_>")
2658                  '(0 font-lock-variable-name-face))
2659
2660            ;; Handle numbers too.
2661            (list (concat "\\_<\\("
2662                                "[0-9][0-9_]*"
2663                                "\\(" "\\(\\.[0-9_]+\\)?[eE][-+]?[0-9_]+"
2664                                "\\|" "\\.[0-9_]+"
2665                                "\\)"
2666                                "\\(f32\\|f64\\)?"
2667                          "\\|" "\\(" "[0-9][0-9_]*"
2668                                "\\|" "0x[0-9a-fA-F_]+"
2669                                "\\|" "0o[0-7_]+"
2670                                "\\|" "0b[01_]+"
2671                                "\\)"
2672                                "\\([ui]\\(8\\|16\\|32\\|64\\|s\\|size\\)\\)?"
2673                          "\\)\\_>")
2674                  '(0 mdw-number-face))
2675
2676            ;; And anything else is punctuation.
2677            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2678                  '(0 mdw-punct-face)))))
2679
2680   ;; Hack key bindings.
2681   (local-set-key [?{] 'mdw-self-insert-and-indent)
2682   (local-set-key [?}] 'mdw-self-insert-and-indent))
2683
2684 ;;;--------------------------------------------------------------------------
2685 ;;; Awk programming configuration.
2686
2687 ;; Make Awk indentation nice.
2688
2689 (mdw-define-c-style mdw-awk
2690   (c-basic-offset . 2)
2691   (c-offsets-alist (substatement-open . 0)
2692                    (c-backslash-column . 72)
2693                    (statement-cont . 0)
2694                    (statement-case-intro . +)))
2695 (mdw-set-default-c-style 'awk-mode 'mdw-awk)
2696
2697 ;; Declare Awk fontification style.
2698
2699 (defun mdw-fontify-awk ()
2700
2701   ;; Miscellaneous fiddling.
2702   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
2703
2704   ;; Now define things to be fontified.
2705   (make-local-variable 'font-lock-keywords)
2706   (let ((c-keywords
2707          (mdw-regexps "BEGIN" "END" "ARGC" "ARGIND" "ARGV" "CONVFMT"
2708                       "ENVIRON" "ERRNO" "FIELDWIDTHS" "FILENAME" "FNR"
2709                       "FS" "IGNORECASE" "NF" "NR" "OFMT" "OFS" "ORS" "RS"
2710                       "RSTART" "RLENGTH" "RT"   "SUBSEP"
2711                       "atan2" "break" "close" "continue" "cos" "delete"
2712                       "do" "else" "exit" "exp" "fflush" "file" "for" "func"
2713                       "function" "gensub" "getline" "gsub" "if" "in"
2714                       "index" "int" "length" "log" "match" "next" "rand"
2715                       "return" "print" "printf" "sin" "split" "sprintf"
2716                       "sqrt" "srand" "strftime" "sub" "substr" "system"
2717                       "systime" "tolower" "toupper" "while")))
2718
2719     (setq font-lock-keywords
2720           (list
2721
2722            ;; Handle the keywords defined above.
2723            (list (concat "\\<\\(" c-keywords "\\)\\>")
2724                  '(0 font-lock-keyword-face))
2725
2726            ;; Handle numbers too.
2727            ;;
2728            ;; The following isn't quite right, but it's close enough.
2729            (list (concat "\\<\\("
2730                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
2731                          "[0-9]+\\(\\.[0-9]*\\|\\)"
2732                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
2733                          "[uUlL]*")
2734                  '(0 mdw-number-face))
2735
2736            ;; And anything else is punctuation.
2737            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2738                  '(0 mdw-punct-face))))))
2739
2740 ;;;--------------------------------------------------------------------------
2741 ;;; Perl programming style.
2742
2743 ;; Perl indentation style.
2744
2745 (setq perl-indent-level 2)
2746
2747 (setq cperl-indent-level 2)
2748 (setq cperl-continued-statement-offset 2)
2749 (setq cperl-continued-brace-offset 0)
2750 (setq cperl-brace-offset -2)
2751 (setq cperl-brace-imaginary-offset 0)
2752 (setq cperl-label-offset 0)
2753
2754 ;; Define perl fontification style.
2755
2756 (defun mdw-fontify-perl ()
2757
2758   ;; Miscellaneous fiddling.
2759   (modify-syntax-entry ?$ "\\")
2760   (modify-syntax-entry ?$ "\\" font-lock-syntax-table)
2761   (modify-syntax-entry ?: "." font-lock-syntax-table)
2762   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
2763
2764   ;; Now define fontification things.
2765   (make-local-variable 'font-lock-keywords)
2766   (let ((perl-keywords
2767          (mdw-regexps "and"
2768                       "break"
2769                       "cmp" "continue"
2770                       "default" "do"
2771                       "else" "elsif" "eq"
2772                       "for" "foreach"
2773                       "ge" "given" "gt" "goto"
2774                       "if"
2775                       "last" "le" "local" "lt"
2776                       "my"
2777                       "ne" "next"
2778                       "or" "our"
2779                       "package"
2780                       "redo" "require" "return"
2781                       "sub"
2782                       "undef" "unless" "until" "use"
2783                       "when" "while")))
2784
2785     (setq font-lock-keywords
2786           (list
2787
2788            ;; Set up the keywords defined above.
2789            (list (concat "\\<\\(" perl-keywords "\\)\\>")
2790                  '(0 font-lock-keyword-face))
2791
2792            ;; At least numbers are simpler than C.
2793            (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
2794                          "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
2795                          "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
2796                  '(0 mdw-number-face))
2797
2798            ;; And anything else is punctuation.
2799            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2800                  '(0 mdw-punct-face))))))
2801
2802 (defun perl-number-tests (&optional arg)
2803   "Assign consecutive numbers to lines containing `#t'.  With ARG,
2804 strip numbers instead."
2805   (interactive "P")
2806   (save-excursion
2807     (goto-char (point-min))
2808     (let ((i 0) (fmt (if arg "" " %4d")))
2809       (while (search-forward "#t" nil t)
2810         (delete-region (point) (line-end-position))
2811         (setq i (1+ i))
2812         (insert (format fmt i)))
2813       (goto-char (point-min))
2814       (if (re-search-forward "\\(tests\\s-*=>\\s-*\\)\\w*" nil t)
2815           (replace-match (format "\\1%d" i))))))
2816
2817 ;;;--------------------------------------------------------------------------
2818 ;;; Python programming style.
2819
2820 (defun mdw-fontify-pythonic (keywords)
2821
2822   ;; Miscellaneous fiddling.
2823   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
2824   (setq indent-tabs-mode nil)
2825
2826   ;; Now define fontification things.
2827   (make-local-variable 'font-lock-keywords)
2828   (setq font-lock-keywords
2829         (list
2830
2831          ;; Set up the keywords defined above.
2832          (list (concat "\\_<\\(" keywords "\\)\\_>")
2833                '(0 font-lock-keyword-face))
2834
2835          ;; At least numbers are simpler than C.
2836          (list (concat "\\_<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
2837                        "\\_<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
2838                        "\\([eE]\\([-+]\\|\\)[0-9_]+\\|[lL]\\|\\)")
2839                '(0 mdw-number-face))
2840
2841          ;; And anything else is punctuation.
2842          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2843                '(0 mdw-punct-face)))))
2844
2845 ;; Define Python fontification styles.
2846
2847 (defun mdw-fontify-python ()
2848   (mdw-fontify-pythonic
2849    (mdw-regexps "and" "as" "assert" "break" "class" "continue" "def"
2850                 "del" "elif" "else" "except" "exec" "finally" "for"
2851                 "from" "global" "if" "import" "in" "is" "lambda"
2852                 "not" "or" "pass" "print" "raise" "return" "try"
2853                 "while" "with" "yield")))
2854
2855 (defun mdw-fontify-pyrex ()
2856   (mdw-fontify-pythonic
2857    (mdw-regexps "and" "as" "assert" "break" "cdef" "class" "continue"
2858                 "ctypedef" "def" "del" "elif" "else" "enum" "except" "exec"
2859                 "extern" "finally" "for" "from" "global" "if"
2860                 "import" "in" "is" "lambda" "not" "or" "pass" "print"
2861                 "property" "raise" "return" "struct" "try" "while" "with"
2862                 "yield")))
2863
2864 (define-derived-mode pyrex-mode python-mode "Pyrex"
2865   "Major mode for editing Pyrex source code")
2866 (setq auto-mode-alist
2867       (append '(("\\.pyx$" . pyrex-mode)
2868                 ("\\.pxd$" . pyrex-mode)
2869                 ("\\.pxi$" . pyrex-mode))
2870               auto-mode-alist))
2871
2872 ;;;--------------------------------------------------------------------------
2873 ;;; Lua programming style.
2874
2875 (setq lua-indent-level 2)
2876
2877 (defun mdw-fontify-lua ()
2878
2879   ;; Miscellaneous fiddling.
2880   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
2881
2882   ;; Now define fontification things.
2883   (make-local-variable 'font-lock-keywords)
2884   (let ((lua-keywords
2885          (mdw-regexps "and" "break" "do" "else" "elseif" "end"
2886                       "false" "for" "function" "goto" "if" "in" "local"
2887                       "nil" "not" "or" "repeat" "return" "then" "true"
2888                       "until" "while")))
2889     (setq font-lock-keywords
2890           (list
2891
2892            ;; Set up the keywords defined above.
2893            (list (concat "\\_<\\(" lua-keywords "\\)\\_>")
2894                  '(0 font-lock-keyword-face))
2895
2896            ;; At least numbers are simpler than C.
2897            (list (concat "\\_<\\(" "0[xX]"
2898                                    "\\(" "[0-9a-fA-F]+"
2899                                          "\\(\\.[0-9a-fA-F]*\\)?"
2900                                    "\\|" "\\.[0-9a-fA-F]+"
2901                                    "\\)"
2902                                    "\\([pP][-+]?[0-9]+\\)?"
2903                              "\\|" "\\(" "[0-9]+"
2904                                          "\\(\\.[0-9]*\\)?"
2905                                    "\\|" "\\.[0-9]+"
2906                                    "\\)"
2907                                    "\\([eE][-+]?[0-9]+\\)?"
2908                              "\\)")
2909                  '(0 mdw-number-face))
2910
2911            ;; And anything else is punctuation.
2912            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2913                  '(0 mdw-punct-face))))))
2914
2915 ;;;--------------------------------------------------------------------------
2916 ;;; Icon programming style.
2917
2918 ;; Icon indentation style.
2919
2920 (setq icon-brace-offset 0
2921       icon-continued-brace-offset 0
2922       icon-continued-statement-offset 2
2923       icon-indent-level 2)
2924
2925 ;; Define Icon fontification style.
2926
2927 (defun mdw-fontify-icon ()
2928
2929   ;; Miscellaneous fiddling.
2930   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
2931
2932   ;; Now define fontification things.
2933   (make-local-variable 'font-lock-keywords)
2934   (let ((icon-keywords
2935          (mdw-regexps "break" "by" "case" "create" "default" "do" "else"
2936                       "end" "every" "fail" "global" "if" "initial"
2937                       "invocable" "link" "local" "next" "not" "of"
2938                       "procedure" "record" "repeat" "return" "static"
2939                       "suspend" "then" "to" "until" "while"))
2940         (preprocessor-keywords
2941          (mdw-regexps "define" "else" "endif" "error" "ifdef" "ifndef"
2942                       "include" "line" "undef")))
2943     (setq font-lock-keywords
2944           (list
2945
2946            ;; Set up the keywords defined above.
2947            (list (concat "\\<\\(" icon-keywords "\\)\\>")
2948                  '(0 font-lock-keyword-face))
2949
2950            ;; The things that Icon calls keywords.
2951            (list "&\\sw+\\>" '(0 font-lock-variable-name-face))
2952
2953            ;; At least numbers are simpler than C.
2954            (list (concat "\\<[0-9]+"
2955                          "\\([rR][0-9a-zA-Z]+\\|"
2956                          "\\.[0-9]+\\([eE][+-]?[0-9]+\\)?\\)\\>\\|"
2957                          "\\.[0-9]+\\([eE][+-]?[0-9]+\\)?\\>")
2958                  '(0 mdw-number-face))
2959
2960            ;; Preprocessor.
2961            (list (concat "^[ \t]*$[ \t]*\\<\\("
2962                          preprocessor-keywords
2963                          "\\)\\>")
2964                  '(0 font-lock-keyword-face))
2965
2966            ;; And anything else is punctuation.
2967            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2968                  '(0 mdw-punct-face))))))
2969
2970 ;;;--------------------------------------------------------------------------
2971 ;;; Assembler mode.
2972
2973 (defun mdw-fontify-asm ()
2974   (modify-syntax-entry ?' "\"")
2975   (modify-syntax-entry ?. "w")
2976   (modify-syntax-entry ?\n ">")
2977   (setf fill-prefix nil)
2978   (local-set-key ";" 'self-insert-command)
2979   (mdw-standard-fill-prefix "\\([ \t]*;+[ \t]*\\)"))
2980
2981 (defun mdw-asm-set-comment ()
2982   (modify-syntax-entry ?; "."
2983                        )
2984   (modify-syntax-entry asm-comment-char "<b")
2985   (setq comment-start (string asm-comment-char ? )))
2986 (add-hook 'asm-mode-local-variables-hook 'mdw-asm-set-comment)
2987 (put 'asm-comment-char 'safe-local-variable 'characterp)
2988
2989 ;;;--------------------------------------------------------------------------
2990 ;;; TCL configuration.
2991
2992 (defun mdw-fontify-tcl ()
2993   (mapcar #'(lambda (ch) (modify-syntax-entry ch ".")) '(?$))
2994   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
2995   (make-local-variable 'font-lock-keywords)
2996   (setq font-lock-keywords
2997         (list
2998          (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
2999                        "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
3000                        "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
3001                '(0 mdw-number-face))
3002          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
3003                '(0 mdw-punct-face)))))
3004
3005 ;;;--------------------------------------------------------------------------
3006 ;;; Dylan programming configuration.
3007
3008 (defun mdw-fontify-dylan ()
3009
3010   (make-local-variable 'font-lock-keywords)
3011
3012   ;; Horrors.  `dylan-mode' sets the `major-mode' name after calling this
3013   ;; hook, which undoes all of our configuration.
3014   (setq major-mode 'dylan-mode)
3015   (font-lock-set-defaults)
3016
3017   (let* ((word "[-_a-zA-Z!*@<>$%]+")
3018          (dylan-keywords (mdw-regexps
3019
3020                           "C-address" "C-callable-wrapper" "C-function"
3021                           "C-mapped-subtype" "C-pointer-type" "C-struct"
3022                           "C-subtype" "C-union" "C-variable"
3023
3024                           "above" "abstract" "afterwards" "all"
3025                           "begin" "below" "block" "by"
3026                           "case" "class" "cleanup" "constant" "create"
3027                           "define" "domain"
3028                           "else" "elseif" "end" "exception" "export"
3029                           "finally" "for" "from" "function"
3030                           "generic"
3031                           "handler"
3032                           "if" "in" "instance" "interface" "iterate"
3033                           "keyed-by"
3034                           "let" "library" "local"
3035                           "macro" "method" "module"
3036                           "otherwise"
3037                           "profiling"
3038                           "select" "slot" "subclass"
3039                           "table" "then" "to"
3040                           "unless" "until" "use"
3041                           "variable" "virtual"
3042                           "when" "while"))
3043          (sharp-keywords (mdw-regexps
3044                           "all-keys" "key" "next" "rest" "include"
3045                           "t" "f")))
3046     (setq font-lock-keywords
3047           (list (list (concat "\\<\\(" dylan-keywords
3048                               "\\|" "with\\(out\\)?-" word
3049                               "\\)\\>")
3050                       '(0 font-lock-keyword-face))
3051                 (list (concat "\\<" word ":" "\\|"
3052                               "#\\(" sharp-keywords "\\)\\>")
3053                       '(0 font-lock-variable-name-face))
3054                 (list (concat "\\("
3055                               "\\([-+]\\|\\<\\)[0-9]+" "\\("
3056                                 "\\(\\.[0-9]+\\)?" "\\([eE][-+][0-9]+\\)?"
3057                                 "\\|" "/[0-9]+"
3058                               "\\)"
3059                               "\\|" "\\.[0-9]+" "\\([eE][-+][0-9]+\\)?"
3060                               "\\|" "#b[01]+"
3061                               "\\|" "#o[0-7]+"
3062                               "\\|" "#x[0-9a-zA-Z]+"
3063                               "\\)\\>")
3064                       '(0 mdw-number-face))
3065                 (list (concat "\\("
3066                               "\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\|"
3067                               "\\_<[-+*/=<>:&|]+\\_>"
3068                               "\\)")
3069                       '(0 mdw-punct-face))))))
3070
3071 ;;;--------------------------------------------------------------------------
3072 ;;; Algol 68 configuration.
3073
3074 (setq a68-indent-step 2)
3075
3076 (defun mdw-fontify-algol-68 ()
3077
3078   ;; Fix up the syntax table.
3079   (modify-syntax-entry ?# "!" a68-mode-syntax-table)
3080   (dolist (ch '(?- ?+ ?= ?< ?> ?* ?/ ?| ?&))
3081     (modify-syntax-entry ch "." a68-mode-syntax-table))
3082
3083   (make-local-variable 'font-lock-keywords)
3084
3085   (let ((not-comment
3086          (let ((word "COMMENT"))
3087            (do ((regexp (concat "[^" (substring word 0 1) "]+")
3088                         (concat regexp "\\|"
3089                                 (substring word 0 i)
3090                                 "[^" (substring word i (1+ i)) "]"))
3091                 (i 1 (1+ i)))
3092                ((>= i (length word)) regexp)))))
3093     (setq font-lock-keywords
3094           (list (list (concat "\\<COMMENT\\>"
3095                               "\\(" not-comment "\\)\\{0,5\\}"
3096                               "\\(\\'\\|\\<COMMENT\\>\\)")
3097                       '(0 font-lock-comment-face))
3098                 (list (concat "\\<CO\\>"
3099                               "\\([^C]+\\|C[^O]\\)\\{0,5\\}"
3100                               "\\($\\|\\<CO\\>\\)")
3101                       '(0 font-lock-comment-face))
3102                 (list "\\<[A-Z_]+\\>"
3103                       '(0 font-lock-keyword-face))
3104                 (list (concat "\\<"
3105                               "[0-9]+"
3106                               "\\(\\.[0-9]+\\)?"
3107                               "\\([eE][-+]?[0-9]+\\)?"
3108                               "\\>")
3109                       '(0 mdw-number-face))
3110                 (list "\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/"
3111                       '(0 mdw-punct-face))))))
3112
3113 ;;;--------------------------------------------------------------------------
3114 ;;; REXX configuration.
3115
3116 (defun mdw-rexx-electric-* ()
3117   (interactive)
3118   (insert ?*)
3119   (rexx-indent-line))
3120
3121 (defun mdw-rexx-indent-newline-indent ()
3122   (interactive)
3123   (rexx-indent-line)
3124   (if abbrev-mode (expand-abbrev))
3125   (newline-and-indent))
3126
3127 (defun mdw-fontify-rexx ()
3128
3129   ;; Various bits of fiddling.
3130   (setq mdw-auto-indent nil)
3131   (local-set-key [?\C-m] 'mdw-rexx-indent-newline-indent)
3132   (local-set-key [?*] 'mdw-rexx-electric-*)
3133   (mapcar #'(lambda (ch) (modify-syntax-entry ch "w"))
3134           '(?! ?? ?# ?@ ?$))
3135   (mdw-standard-fill-prefix "\\([ \t]*/?\*[ \t]*\\)")
3136
3137   ;; Set up keywords and things for fontification.
3138   (make-local-variable 'font-lock-keywords-case-fold-search)
3139   (setq font-lock-keywords-case-fold-search t)
3140
3141   (setq rexx-indent 2)
3142   (setq rexx-end-indent rexx-indent)
3143   (setq rexx-cont-indent rexx-indent)
3144
3145   (make-local-variable 'font-lock-keywords)
3146   (let ((rexx-keywords
3147          (mdw-regexps "address" "arg" "by" "call" "digits" "do" "drop"
3148                       "else" "end" "engineering" "exit" "expose" "for"
3149                       "forever" "form" "fuzz" "if" "interpret" "iterate"
3150                       "leave" "linein" "name" "nop" "numeric" "off" "on"
3151                       "options" "otherwise" "parse" "procedure" "pull"
3152                       "push" "queue" "return" "say" "select" "signal"
3153                       "scientific" "source" "then" "trace" "to" "until"
3154                       "upper" "value" "var" "version" "when" "while"
3155                       "with"
3156
3157                       "abbrev" "abs" "bitand" "bitor" "bitxor" "b2x"
3158                       "center" "center" "charin" "charout" "chars"
3159                       "compare" "condition" "copies" "c2d" "c2x"
3160                       "datatype" "date" "delstr" "delword" "d2c" "d2x"
3161                       "errortext" "format" "fuzz" "insert" "lastpos"
3162                       "left" "length" "lineout" "lines" "max" "min"
3163                       "overlay" "pos" "queued" "random" "reverse" "right"
3164                       "sign" "sourceline" "space" "stream" "strip"
3165                       "substr" "subword" "symbol" "time" "translate"
3166                       "trunc" "value" "verify" "word" "wordindex"
3167                       "wordlength" "wordpos" "words" "xrange" "x2b" "x2c"
3168                       "x2d")))
3169
3170     (setq font-lock-keywords
3171           (list
3172
3173            ;; Set up the keywords defined above.
3174            (list (concat "\\<\\(" rexx-keywords "\\)\\>")
3175                  '(0 font-lock-keyword-face))
3176
3177            ;; Fontify all symbols the same way.
3178            (list (concat "\\<\\([0-9.][A-Za-z0-9.!?_#@$]*[Ee][+-]?[0-9]+\\|"
3179                          "[A-Za-z0-9.!?_#@$]+\\)")
3180                  '(0 font-lock-variable-name-face))
3181
3182            ;; And everything else is punctuation.
3183            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
3184                  '(0 mdw-punct-face))))))
3185
3186 ;;;--------------------------------------------------------------------------
3187 ;;; Standard ML programming style.
3188
3189 (defun mdw-fontify-sml ()
3190
3191   ;; Make underscore an honorary letter.
3192   (modify-syntax-entry ?' "w")
3193
3194   ;; Set fill prefix.
3195   (mdw-standard-fill-prefix "\\([ \t]*(\*[ \t]*\\)")
3196
3197   ;; Now define fontification things.
3198   (make-local-variable 'font-lock-keywords)
3199   (let ((sml-keywords
3200          (mdw-regexps "abstype" "and" "andalso" "as"
3201                       "case"
3202                       "datatype" "do"
3203                       "else" "end" "eqtype" "exception"
3204                       "fn" "fun" "functor"
3205                       "handle"
3206                       "if" "in" "include" "infix" "infixr"
3207                       "let" "local"
3208                       "nonfix"
3209                       "of" "op" "open" "orelse"
3210                       "raise" "rec"
3211                       "sharing" "sig" "signature" "struct" "structure"
3212                       "then" "type"
3213                       "val"
3214                       "where" "while" "with" "withtype")))
3215
3216     (setq font-lock-keywords
3217           (list
3218
3219            ;; Set up the keywords defined above.
3220            (list (concat "\\<\\(" sml-keywords "\\)\\>")
3221                  '(0 font-lock-keyword-face))
3222
3223            ;; At least numbers are simpler than C.
3224            (list (concat "\\<\\(\\~\\|\\)"
3225                             "\\(0\\(\\([wW]\\|\\)[xX][0-9a-fA-F]+\\|"
3226                                    "[wW][0-9]+\\)\\|"
3227                                 "\\([0-9]+\\(\\.[0-9]+\\|\\)"
3228                                          "\\([eE]\\(\\~\\|\\)"
3229                                                 "[0-9]+\\|\\)\\)\\)")
3230                  '(0 mdw-number-face))
3231
3232            ;; And anything else is punctuation.
3233            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
3234                  '(0 mdw-punct-face))))))
3235
3236 ;;;--------------------------------------------------------------------------
3237 ;;; Haskell configuration.
3238
3239 (defun mdw-fontify-haskell ()
3240
3241   ;; Fiddle with syntax table to get comments right.
3242   (modify-syntax-entry ?' "_")
3243   (modify-syntax-entry ?- ". 12")
3244   (modify-syntax-entry ?\n ">")
3245
3246   ;; Make punctuation be punctuation
3247   (let ((punct "=<>+-*/|&%!@?$.^:#`"))
3248     (do ((i 0 (1+ i)))
3249         ((>= i (length punct)))
3250       (modify-syntax-entry (aref punct i) ".")))
3251
3252   ;; Set fill prefix.
3253   (mdw-standard-fill-prefix "\\([ \t]*{?--?[ \t]*\\)")
3254
3255   ;; Fiddle with fontification.
3256   (make-local-variable 'font-lock-keywords)
3257   (let ((haskell-keywords
3258          (mdw-regexps "as"
3259                       "case" "ccall" "class"
3260                       "data" "default" "deriving" "do"
3261                       "else" "exists"
3262                       "forall" "foreign"
3263                       "hiding"
3264                       "if" "import" "in" "infix" "infixl" "infixr" "instance"
3265                       "let"
3266                       "mdo" "module"
3267                       "newtype"
3268                       "of"
3269                       "proc"
3270                       "qualified"
3271                       "rec"
3272                       "safe" "stdcall"
3273                       "then" "type"
3274                       "unsafe"
3275                       "where"))
3276         (control-sequences
3277          (mdw-regexps "ACK" "BEL" "BS" "CAN" "CR" "DC1" "DC2" "DC3" "DC4"
3278                       "DEL" "DLE" "EM" "ENQ" "EOT" "ESC" "ETB" "ETX" "FF"
3279                       "FS" "GS" "HT" "LF" "NAK" "NUL" "RS" "SI" "SO" "SOH"
3280                       "SP" "STX" "SUB" "SYN" "US" "VT")))
3281
3282     (setq font-lock-keywords
3283           (list
3284            (list (concat "{-" "[^-]*" "\\(-+[^-}][^-]*\\)*"
3285                               "\\(-+}\\|-*\\'\\)"
3286                          "\\|"
3287                          "--.*$")
3288                  '(0 font-lock-comment-face))
3289            (list (concat "\\_<\\(" haskell-keywords "\\)\\_>")
3290                  '(0 font-lock-keyword-face))
3291            (list (concat "'\\("
3292                          "[^\\]"
3293                          "\\|"
3294                          "\\\\"
3295                          "\\(" "[abfnrtv\\\"']" "\\|"
3296                                "^" "\\(" control-sequences "\\|"
3297                                          "[]A-Z@[\\^_]" "\\)" "\\|"
3298                                "\\|"
3299                                "[0-9]+" "\\|"
3300                                "[oO][0-7]+" "\\|"
3301                                "[xX][0-9A-Fa-f]+"
3302                          "\\)"
3303                          "\\)'")
3304                  '(0 font-lock-string-face))
3305            (list "\\_<[A-Z]\\(\\sw+\\|\\s_+\\)*\\_>"
3306                  '(0 font-lock-variable-name-face))
3307            (list (concat "\\_<0\\([xX][0-9a-fA-F]+\\|[oO][0-7]+\\)\\|"
3308                          "\\_<[0-9]+\\(\\.[0-9]*\\|\\)"
3309                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)")
3310                  '(0 mdw-number-face))
3311            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
3312                  '(0 mdw-punct-face))))))
3313
3314 ;;;--------------------------------------------------------------------------
3315 ;;; Erlang configuration.
3316
3317 (setq erlang-electric-commands nil)
3318
3319 (defun mdw-fontify-erlang ()
3320
3321   ;; Set fill prefix.
3322   (mdw-standard-fill-prefix "\\([ \t]*{?%*[ \t]*\\)")
3323
3324   ;; Fiddle with fontification.
3325   (make-local-variable 'font-lock-keywords)
3326   (let ((erlang-keywords
3327          (mdw-regexps "after" "and" "andalso"
3328                       "band" "begin" "bnot" "bor" "bsl" "bsr" "bxor"
3329                       "case" "catch" "cond"
3330                       "div" "end" "fun" "if" "let" "not"
3331                       "of" "or" "orelse"
3332                       "query" "receive" "rem" "try" "when" "xor")))
3333
3334     (setq font-lock-keywords
3335           (list
3336            (list "%.*$"
3337                  '(0 font-lock-comment-face))
3338            (list (concat "\\<\\(" erlang-keywords "\\)\\>")
3339                  '(0 font-lock-keyword-face))
3340            (list (concat "^-\\sw+\\>")
3341                  '(0 font-lock-keyword-face))
3342            (list "\\<[0-9]+\\(\\|#[0-9a-zA-Z]+\\|[eE][+-]?[0-9]+\\)\\>"
3343                  '(0 mdw-number-face))
3344            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
3345                  '(0 mdw-punct-face))))))
3346
3347 ;;;--------------------------------------------------------------------------
3348 ;;; Texinfo configuration.
3349
3350 (defun mdw-fontify-texinfo ()
3351
3352   ;; Set fill prefix.
3353   (mdw-standard-fill-prefix "\\([ \t]*@c[ \t]+\\)")
3354
3355   ;; Real fontification things.
3356   (make-local-variable 'font-lock-keywords)
3357   (setq font-lock-keywords
3358         (list
3359
3360          ;; Environment names are keywords.
3361          (list "@\\(end\\)  *\\([a-zA-Z]*\\)?"
3362                '(2 font-lock-keyword-face))
3363
3364          ;; Unmark escaped magic characters.
3365          (list "\\(@\\)\\([@{}]\\)"
3366                '(1 font-lock-keyword-face)
3367                '(2 font-lock-variable-name-face))
3368
3369          ;; Make sure we get comments properly.
3370          (list "@c\\(\\|omment\\)\\( .*\\)?$"
3371                '(0 font-lock-comment-face))
3372
3373          ;; Command names are keywords.
3374          (list "@\\([^a-zA-Z@]\\|[a-zA-Z@]*\\)"
3375                '(0 font-lock-keyword-face))
3376
3377          ;; Fontify TeX special characters as punctuation.
3378          (list "[{}]+"
3379                '(0 mdw-punct-face)))))
3380
3381 ;;;--------------------------------------------------------------------------
3382 ;;; TeX and LaTeX configuration.
3383
3384 (defun mdw-fontify-tex ()
3385   (setq ispell-parser 'tex)
3386   (turn-on-reftex)
3387
3388   ;; Don't make maths into a string.
3389   (modify-syntax-entry ?$ ".")
3390   (modify-syntax-entry ?$ "." font-lock-syntax-table)
3391   (local-set-key [?$] 'self-insert-command)
3392
3393   ;; Make `tab' be useful, given that tab stops in TeX don't work well.
3394   (local-set-key "\C-\M-i" 'indent-relative)
3395   (setq indent-tabs-mode nil)
3396
3397   ;; Set fill prefix.
3398   (mdw-standard-fill-prefix "\\([ \t]*%+[ \t]*\\)")
3399
3400   ;; Real fontification things.
3401   (make-local-variable 'font-lock-keywords)
3402   (setq font-lock-keywords
3403         (list
3404
3405          ;; Environment names are keywords.
3406          (list (concat "\\\\\\(begin\\|end\\|newenvironment\\)"
3407                        "{\\([^}\n]*\\)}")
3408                '(2 font-lock-keyword-face))
3409
3410          ;; Suspended environment names are keywords too.
3411          (list (concat "\\\\\\(suspend\\|resume\\)\\(\\[[^]]*\\]\\)?"
3412                        "{\\([^}\n]*\\)}")
3413                '(3 font-lock-keyword-face))
3414
3415          ;; Command names are keywords.
3416          (list "\\\\\\([^a-zA-Z@]\\|[a-zA-Z@]*\\)"
3417                '(0 font-lock-keyword-face))
3418
3419          ;; Handle @/.../ for italics.
3420          ;; (list "\\(@/\\)\\([^/]*\\)\\(/\\)"
3421          ;;       '(1 font-lock-keyword-face)
3422          ;;       '(3 font-lock-keyword-face))
3423
3424          ;; Handle @*...* for boldness.
3425          ;; (list "\\(@\\*\\)\\([^*]*\\)\\(\\*\\)"
3426          ;;       '(1 font-lock-keyword-face)
3427          ;;       '(3 font-lock-keyword-face))
3428
3429          ;; Handle @`...' for literal syntax things.
3430          ;; (list "\\(@`\\)\\([^']*\\)\\('\\)"
3431          ;;       '(1 font-lock-keyword-face)
3432          ;;       '(3 font-lock-keyword-face))
3433
3434          ;; Handle @<...> for nonterminals.
3435          ;; (list "\\(@<\\)\\([^>]*\\)\\(>\\)"
3436          ;;       '(1 font-lock-keyword-face)
3437          ;;       '(3 font-lock-keyword-face))
3438
3439          ;; Handle other @-commands.
3440          ;; (list "@\\([^a-zA-Z]\\|[a-zA-Z]*\\)"
3441          ;;       '(0 font-lock-keyword-face))
3442
3443          ;; Make sure we get comments properly.
3444          (list "%.*"
3445                '(0 font-lock-comment-face))
3446
3447          ;; Fontify TeX special characters as punctuation.
3448          (list "[$^_{}#&]"
3449                '(0 mdw-punct-face)))))
3450
3451 (eval-after-load 'font-latex
3452   '(defun font-latex-jit-lock-force-redisplay (buf start end)
3453      "Compatibility for Emacsen not offering `jit-lock-force-redisplay'."
3454      ;; The following block is an expansion of `jit-lock-force-redisplay'
3455      ;; and involved macros taken from CVS Emacs on 2007-04-28.
3456      (with-current-buffer buf
3457        (let ((modified (buffer-modified-p)))
3458          (unwind-protect
3459              (let ((buffer-undo-list t)
3460                    (inhibit-read-only t)
3461                    (inhibit-point-motion-hooks t)
3462                    (inhibit-modification-hooks t)
3463                    deactivate-mark
3464                    buffer-file-name
3465                    buffer-file-truename)
3466                (put-text-property start end 'fontified t))
3467            (unless modified
3468              (restore-buffer-modified-p nil)))))))
3469
3470 (setq LaTeX-syntactic-comments nil
3471       LaTeX-fill-break-at-separators '(\\\[))
3472
3473 ;;;--------------------------------------------------------------------------
3474 ;;; SGML hacking.
3475
3476 (defun mdw-sgml-mode ()
3477   (interactive)
3478   (sgml-mode)
3479   (mdw-standard-fill-prefix "")
3480   (make-local-variable 'sgml-delimiters)
3481   (setq sgml-delimiters
3482         '("AND" "&" "COM" "--" "CRO" "&#" "DSC" "]" "DSO" "[" "DTGC" "]"
3483           "DTGO" "[" "ERO" "&" "ETAGO" ":e" "GRPC" ")" "GRPO" "(" "LIT" "\""
3484           "LITA" "'" "MDC" ">" "MDO" "<!" "MINUS" "-" "MSC" "]]" "NESTC" "{"
3485           "NET" "}" "OPT" "?" "OR" "|" "PERO" "%" "PIC" ">" "PIO" "<?"
3486           "PLUS" "+" "REFC" "." "REP" "*" "RNI" "#" "SEQ" "," "STAGO" ":"
3487           "TAGC" "." "VI" "=" "MS-START" "<![" "MS-END" "]]>"
3488           "XML-ECOM" "-->" "XML-PIC" "?>" "XML-SCOM" "<!--" "XML-TAGCE" "/>"
3489           "NULL" ""))
3490   (setq major-mode 'mdw-sgml-mode)
3491   (setq mode-name "[mdw] SGML")
3492   (run-hooks 'mdw-sgml-mode-hook))
3493
3494 ;;;--------------------------------------------------------------------------
3495 ;;; Configuration files.
3496
3497 (defvar mdw-conf-quote-normal nil
3498   "*Control syntax category of quote characters `\"' and `''.
3499 If this is `t', consider quote characters to be normal
3500 punctuation, as for `conf-quote-normal'.  If this is `nil' then
3501 leave quote characters as quotes.  If this is a list, then
3502 consider the quote characters in the list to be normal
3503 punctuation.  If this is a single quote character, then consider
3504 that character only to be normal punctuation.")
3505 (defun mdw-conf-quote-normal-acceptable-value-p (value)
3506   "Is the VALUE is an acceptable value for `mdw-conf-quote-normal'?"
3507   (or (booleanp value)
3508       (every (lambda (v) (memq v '(?\" ?')))
3509              (if (listp value) value (list value)))))
3510 (put 'mdw-conf-quote-normal 'safe-local-variable
3511      'mdw-conf-quote-normal-acceptable-value-p)
3512
3513 (defun mdw-fix-up-quote ()
3514   "Apply the setting of `mdw-conf-quote-normal'."
3515   (let ((flag mdw-conf-quote-normal))
3516     (cond ((eq flag t)
3517            (conf-quote-normal t))
3518           ((not flag)
3519            nil)
3520           (t
3521            (let ((table (copy-syntax-table (syntax-table))))
3522              (mapc (lambda (ch) (modify-syntax-entry ch "." table))
3523                    (if (listp flag) flag (list flag)))
3524              (set-syntax-table table)
3525              (and font-lock-mode (font-lock-fontify-buffer)))))))
3526 (add-hook 'conf-mode-local-variables-hook 'mdw-fix-up-quote t t)
3527
3528 ;;;--------------------------------------------------------------------------
3529 ;;; Shell scripts.
3530
3531 (defun mdw-setup-sh-script-mode ()
3532
3533   ;; Fetch the shell interpreter's name.
3534   (let ((shell-name sh-shell-file))
3535
3536     ;; Try reading the hash-bang line.
3537     (save-excursion
3538       (goto-char (point-min))
3539       (if (looking-at "#![ \t]*\\([^ \t\n]*\\)")
3540           (setq shell-name (match-string 1))))
3541
3542     ;; Now try to set the shell.
3543     ;;
3544     ;; Don't let `sh-set-shell' bugger up my script.
3545     (let ((executable-set-magic #'(lambda (s &rest r) s)))
3546       (sh-set-shell shell-name)))
3547
3548   ;; Don't insert here-document scaffolding automatically.
3549   (local-set-key "<" 'self-insert-command)
3550
3551   ;; Now enable my keys and the fontification.
3552   (mdw-misc-mode-config)
3553
3554   ;; Set the indentation level correctly.
3555   (setq sh-indentation 2)
3556   (setq sh-basic-offset 2))
3557
3558 (setq sh-shell-file "/bin/sh")
3559
3560 ;; Awful hacking to override the shell detection for particular scripts.
3561 (defmacro define-custom-shell-mode (name shell)
3562   `(defun ,name ()
3563      (interactive)
3564      (set (make-local-variable 'sh-shell-file) ,shell)
3565      (sh-mode)))
3566 (define-custom-shell-mode bash-mode "/bin/bash")
3567 (define-custom-shell-mode rc-mode "/usr/bin/rc")
3568 (put 'sh-shell-file 'permanent-local t)
3569
3570 ;; Hack the rc syntax table.  Backquotes aren't paired in rc.
3571 (eval-after-load "sh-script"
3572   '(or (assq 'rc sh-mode-syntax-table-input)
3573        (let ((frag '(nil
3574                      ?# "<"
3575                      ?\n ">#"
3576                      ?\" "\"\""
3577                      ?\' "\"\'"
3578                      ?$ "'"
3579                      ?\` "."
3580                      ?! "_"
3581                      ?% "_"
3582                      ?. "_"
3583                      ?^ "_"
3584                      ?~ "_"
3585                      ?, "_"
3586                      ?= "."
3587                      ?< "."
3588                      ?> "."))
3589              (assoc (assq 'rc sh-mode-syntax-table-input)))
3590          (if assoc
3591              (rplacd assoc frag)
3592            (setq sh-mode-syntax-table-input
3593                  (cons (cons 'rc frag)
3594                        sh-mode-syntax-table-input))))))
3595
3596 ;;;--------------------------------------------------------------------------
3597 ;;; Emacs shell mode.
3598
3599 (defun mdw-eshell-prompt ()
3600   (let ((left "[") (right "]"))
3601     (when (= (user-uid) 0)
3602       (setq left "«" right "»"))
3603     (concat left
3604             (save-match-data
3605               (replace-regexp-in-string "\\..*$" "" (system-name)))
3606             " "
3607             (let* ((pwd (eshell/pwd)) (npwd (length pwd))
3608                    (home (expand-file-name "~")) (nhome (length home)))
3609               (if (and (>= npwd nhome)
3610                        (or (= nhome npwd)
3611                            (= (elt pwd nhome) ?/))
3612                        (string= (substring pwd 0 nhome) home))
3613                   (concat "~" (substring pwd (length home)))
3614                 pwd))
3615             right)))
3616 (setq eshell-prompt-function 'mdw-eshell-prompt)
3617 (setq eshell-prompt-regexp "^\\[[^]>]+\\(\\]\\|>>?\\)")
3618
3619 (defun eshell/e (file) (find-file file) nil)
3620 (defun eshell/ee (file) (find-file-other-window file) nil)
3621 (defun eshell/w3m (url) (w3m-goto-url url) nil)
3622
3623 (mdw-define-face eshell-prompt (t :weight bold))
3624 (mdw-define-face eshell-ls-archive (t :weight bold :foreground "red"))
3625 (mdw-define-face eshell-ls-backup (t :foreground "lightgrey" :slant italic))
3626 (mdw-define-face eshell-ls-product (t :foreground "lightgrey" :slant italic))
3627 (mdw-define-face eshell-ls-clutter (t :foreground "lightgrey" :slant italic))
3628 (mdw-define-face eshell-ls-executable (t :weight bold))
3629 (mdw-define-face eshell-ls-directory (t :foreground "cyan" :weight bold))
3630 (mdw-define-face eshell-ls-readonly (t nil))
3631 (mdw-define-face eshell-ls-symlink (t :foreground "cyan"))
3632
3633 (defun mdw-eshell-hack () (setenv "LD_PRELOAD" nil))
3634 (add-hook 'eshell-mode-hook 'mdw-eshell-hack)
3635
3636 ;;;--------------------------------------------------------------------------
3637 ;;; Messages-file mode.
3638
3639 (defun messages-mode-guts ()
3640   (setq messages-mode-syntax-table (make-syntax-table))
3641   (set-syntax-table messages-mode-syntax-table)
3642   (modify-syntax-entry ?0 "w" messages-mode-syntax-table)
3643   (modify-syntax-entry ?1 "w" messages-mode-syntax-table)
3644   (modify-syntax-entry ?2 "w" messages-mode-syntax-table)
3645   (modify-syntax-entry ?3 "w" messages-mode-syntax-table)
3646   (modify-syntax-entry ?4 "w" messages-mode-syntax-table)
3647   (modify-syntax-entry ?5 "w" messages-mode-syntax-table)
3648   (modify-syntax-entry ?6 "w" messages-mode-syntax-table)
3649   (modify-syntax-entry ?7 "w" messages-mode-syntax-table)
3650   (modify-syntax-entry ?8 "w" messages-mode-syntax-table)
3651   (modify-syntax-entry ?9 "w" messages-mode-syntax-table)
3652   (make-local-variable 'comment-start)
3653   (make-local-variable 'comment-end)
3654   (make-local-variable 'indent-line-function)
3655   (setq indent-line-function 'indent-relative)
3656   (mdw-standard-fill-prefix "\\([ \t]*\\(;\\|/?\\*\\)+[ \t]*\\)")
3657   (make-local-variable 'font-lock-defaults)
3658   (make-local-variable 'messages-mode-keywords)
3659   (let ((keywords
3660          (mdw-regexps "array" "bitmap" "callback" "docs[ \t]+enum"
3661                       "export" "enum" "fixed-octetstring" "flags"
3662                       "harmless" "map" "nested" "optional"
3663                       "optional-tagged" "package" "primitive"
3664                       "primitive-nullfree" "relaxed[ \t]+enum"
3665                       "set" "table" "tagged-optional"   "union"
3666                       "variadic" "vector" "version" "version-tag")))
3667     (setq messages-mode-keywords
3668           (list
3669            (list (concat "\\<\\(" keywords "\\)\\>:")
3670                  '(0 font-lock-keyword-face))
3671            '("\\([-a-zA-Z0-9]+:\\)" (0 font-lock-warning-face))
3672            '("\\(\\<[a-z][-_a-zA-Z0-9]*\\)"
3673              (0 font-lock-variable-name-face))
3674            '("\\<\\([0-9]+\\)\\>" (0 mdw-number-face))
3675            '("\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
3676              (0 mdw-punct-face)))))
3677   (setq font-lock-defaults
3678         '(messages-mode-keywords nil nil nil nil))
3679   (run-hooks 'messages-file-hook))
3680
3681 (defun messages-mode ()
3682   (interactive)
3683   (fundamental-mode)
3684   (setq major-mode 'messages-mode)
3685   (setq mode-name "Messages")
3686   (messages-mode-guts)
3687   (modify-syntax-entry ?# "<" messages-mode-syntax-table)
3688   (modify-syntax-entry ?\n ">" messages-mode-syntax-table)
3689   (setq comment-start "# ")
3690   (setq comment-end "")
3691   (run-hooks 'messages-mode-hook))
3692
3693 (defun cpp-messages-mode ()
3694   (interactive)
3695   (fundamental-mode)
3696   (setq major-mode 'cpp-messages-mode)
3697   (setq mode-name "CPP Messages")
3698   (messages-mode-guts)
3699   (modify-syntax-entry ?* ". 23" messages-mode-syntax-table)
3700   (modify-syntax-entry ?/ ". 14" messages-mode-syntax-table)
3701   (setq comment-start "/* ")
3702   (setq comment-end " */")
3703   (let ((preprocessor-keywords
3704          (mdw-regexps "assert" "define" "elif" "else" "endif" "error"
3705                       "ident" "if" "ifdef" "ifndef" "import" "include"
3706                       "line" "pragma" "unassert" "undef" "warning")))
3707     (setq messages-mode-keywords
3708           (append (list (list (concat "^[ \t]*\\#[ \t]*"
3709                                       "\\(include\\|import\\)"
3710                                       "[ \t]*\\(<[^>]+\\(>\\|\\)\\)")
3711                               '(2 font-lock-string-face))
3712                         (list (concat "^\\([ \t]*#[ \t]*\\(\\("
3713                                       preprocessor-keywords
3714                                       "\\)\\>\\|[0-9]+\\|$\\)\\)")
3715                               '(1 font-lock-keyword-face)))
3716                   messages-mode-keywords)))
3717   (run-hooks 'cpp-messages-mode-hook))
3718
3719 (add-hook 'messages-mode-hook 'mdw-misc-mode-config t)
3720 (add-hook 'cpp-messages-mode-hook 'mdw-misc-mode-config t)
3721 ; (add-hook 'messages-file-hook 'mdw-fontify-messages t)
3722
3723 ;;;--------------------------------------------------------------------------
3724 ;;; Messages-file mode.
3725
3726 (defvar mallow-driver-substitution-face 'mallow-driver-substitution-face
3727   "Face to use for subsittution directives.")
3728 (make-face 'mallow-driver-substitution-face)
3729 (defvar mallow-driver-text-face 'mallow-driver-text-face
3730   "Face to use for body text.")
3731 (make-face 'mallow-driver-text-face)
3732
3733 (defun mallow-driver-mode ()
3734   (interactive)
3735   (fundamental-mode)
3736   (setq major-mode 'mallow-driver-mode)
3737   (setq mode-name "Mallow driver")
3738   (setq mallow-driver-mode-syntax-table (make-syntax-table))
3739   (set-syntax-table mallow-driver-mode-syntax-table)
3740   (make-local-variable 'comment-start)
3741   (make-local-variable 'comment-end)
3742   (make-local-variable 'indent-line-function)
3743   (setq indent-line-function 'indent-relative)
3744   (mdw-standard-fill-prefix "\\([ \t]*\\(;\\|/?\\*\\)+[ \t]*\\)")
3745   (make-local-variable 'font-lock-defaults)
3746   (make-local-variable 'mallow-driver-mode-keywords)
3747   (let ((keywords
3748          (mdw-regexps "each" "divert" "file" "if"
3749                       "perl" "set" "string" "type" "write")))
3750     (setq mallow-driver-mode-keywords
3751           (list
3752            (list (concat "^%\\s *\\(}\\|\\(" keywords "\\)\\>\\).*$")
3753                  '(0 font-lock-keyword-face))
3754            (list "^%\\s *\\(#.*\\|\\)$"
3755                  '(0 font-lock-comment-face))
3756            (list "^%"
3757                  '(0 font-lock-keyword-face))
3758            (list "^|?\\(.+\\)$" '(1 mallow-driver-text-face))
3759            (list "\\${[^}]*}"
3760                  '(0 mallow-driver-substitution-face t)))))
3761   (setq font-lock-defaults
3762         '(mallow-driver-mode-keywords nil nil nil nil))
3763   (modify-syntax-entry ?\" "_" mallow-driver-mode-syntax-table)
3764   (modify-syntax-entry ?\n ">" mallow-driver-mode-syntax-table)
3765   (setq comment-start "%# ")
3766   (setq comment-end "")
3767   (run-hooks 'mallow-driver-mode-hook))
3768
3769 (add-hook 'mallow-driver-hook 'mdw-misc-mode-config t)
3770
3771 ;;;--------------------------------------------------------------------------
3772 ;;; NFast debugs.
3773
3774 (defun nfast-debug-mode ()
3775   (interactive)
3776   (fundamental-mode)
3777   (setq major-mode 'nfast-debug-mode)
3778   (setq mode-name "NFast debug")
3779   (setq messages-mode-syntax-table (make-syntax-table))
3780   (set-syntax-table messages-mode-syntax-table)
3781   (make-local-variable 'font-lock-defaults)
3782   (make-local-variable 'nfast-debug-mode-keywords)
3783   (setq truncate-lines t)
3784   (setq nfast-debug-mode-keywords
3785         (list
3786          '("^\\(NFast_\\(Connect\\|Disconnect\\|Submit\\|Wait\\)\\)"
3787            (0 font-lock-keyword-face))
3788          (list (concat "^[ \t]+\\(\\("
3789                        "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]"
3790                        "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]"
3791                        "[ \t]+\\)*"
3792                        "[0-9a-fA-F]+\\)[ \t]*$")
3793            '(0 mdw-number-face))
3794          '("^[ \t]+\.status=[ \t]+\\<\\(OK\\)\\>"
3795            (1 font-lock-keyword-face))
3796          '("^[ \t]+\.status=[ \t]+\\<\\([a-zA-Z][0-9a-zA-Z]*\\)\\>"
3797            (1 font-lock-warning-face))
3798          '("^[ \t]+\.status[ \t]+\\<\\(zero\\)\\>"
3799            (1 nil))
3800          (list (concat "^[ \t]+\\.cmd=[ \t]+"
3801                        "\\<\\([a-zA-Z][0-9a-zA-Z]*\\)\\>")
3802            '(1 font-lock-keyword-face))
3803          '("-?\\<\\([0-9]+\\|0x[0-9a-fA-F]+\\)\\>" (0 mdw-number-face))
3804          '("^\\([ \t]+[a-z0-9.]+\\)" (0 font-lock-variable-name-face))
3805          '("\\<\\([a-z][a-z0-9.]+\\)\\>=" (1 font-lock-variable-name-face))
3806          '("\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)" (0 mdw-punct-face))))
3807   (setq font-lock-defaults
3808         '(nfast-debug-mode-keywords nil nil nil nil))
3809   (run-hooks 'nfast-debug-mode-hook))
3810
3811 ;;;--------------------------------------------------------------------------
3812 ;;; Other languages.
3813
3814 ;; Smalltalk.
3815
3816 (defun mdw-setup-smalltalk ()
3817   (and mdw-auto-indent
3818        (local-set-key "\C-m" 'smalltalk-newline-and-indent))
3819   (make-local-variable 'mdw-auto-indent)
3820   (setq mdw-auto-indent nil)
3821   (local-set-key "\C-i" 'smalltalk-reindent))
3822
3823 (defun mdw-fontify-smalltalk ()
3824   (make-local-variable 'font-lock-keywords)
3825   (setq font-lock-keywords
3826         (list
3827          (list "\\<[A-Z][a-zA-Z0-9]*\\>"
3828                '(0 font-lock-keyword-face))
3829          (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
3830                        "[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
3831                        "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
3832                '(0 mdw-number-face))
3833          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
3834                '(0 mdw-punct-face)))))
3835
3836 ;; Lispy languages.
3837
3838 ;; Unpleasant bodge.
3839 (unless (boundp 'slime-repl-mode-map)
3840   (setq slime-repl-mode-map (make-sparse-keymap)))
3841
3842 (defun mdw-indent-newline-and-indent ()
3843   (interactive)
3844   (indent-for-tab-command)
3845   (newline-and-indent))
3846
3847 (eval-after-load "cl-indent"
3848   '(progn
3849      (mapc #'(lambda (pair)
3850                (put (car pair)
3851                     'common-lisp-indent-function
3852                     (cdr pair)))
3853       '((destructuring-bind . ((&whole 4 &rest 1) 4 &body))
3854         (multiple-value-bind . ((&whole 4 &rest 1) 4 &body))))))
3855
3856 (defun mdw-common-lisp-indent ()
3857   (make-local-variable 'lisp-indent-function)
3858   (setq lisp-indent-function 'common-lisp-indent-function))
3859
3860 (setq lisp-simple-loop-indentation 2
3861       lisp-loop-keyword-indentation 6
3862       lisp-loop-forms-indentation 6)
3863
3864 (defun mdw-fontify-lispy ()
3865
3866   ;; Set fill prefix.
3867   (mdw-standard-fill-prefix "\\([ \t]*;+[ \t]*\\)")
3868
3869   ;; Not much fontification needed.
3870   (make-local-variable 'font-lock-keywords)
3871   (setq font-lock-keywords
3872         (list (list (concat "\\("
3873                             "\\_<[-+]?"
3874                             "\\(" "[0-9]+/[0-9]+"
3875                             "\\|" "\\(" "[0-9]+" "\\(\\.[0-9]*\\)?" "\\|"
3876                                         "\\.[0-9]+" "\\)"
3877                                   "\\([dDeEfFlLsS][-+]?[0-9]+\\)?"
3878                             "\\)"
3879                             "\\|"
3880                             "#"
3881                             "\\(" "x" "[-+]?"
3882                                   "[0-9A-Fa-f]+" "\\(/[0-9A-Fa-f]+\\)?"
3883                             "\\|" "o" "[-+]?" "[0-7]+" "\\(/[0-7]+\\)?"
3884                             "\\|" "b" "[-+]?" "[01]+" "\\(/[01]+\\)?"
3885                             "\\|" "[0-9]+" "r" "[-+]?"
3886                                   "[0-9a-zA-Z]+" "\\(/[0-9a-zA-Z]+\\)?"
3887                             "\\)"
3888                             "\\)\\_>")
3889                     '(0 mdw-number-face))
3890               (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
3891                     '(0 mdw-punct-face)))))
3892
3893 (defun comint-send-and-indent ()
3894   (interactive)
3895   (comint-send-input)
3896   (and mdw-auto-indent
3897        (indent-for-tab-command)))
3898
3899 (defadvice comint-line-beginning-position
3900     (around mdw-calculate-it-properly () activate compile)
3901   "Calculate the actual line start for multi-line input."
3902   (if (or comint-use-prompt-regexp
3903           (eq (field-at-pos (point)) 'output))
3904       ad-do-it
3905     (setq ad-return-value
3906           (constrain-to-field (line-beginning-position) (point)))))
3907
3908 (defun mdw-setup-m4 ()
3909
3910   ;; Inexplicably, Emacs doesn't match braces in m4 mode.  This is very
3911   ;; annoying: fix it.
3912   (modify-syntax-entry ?{ "(")
3913   (modify-syntax-entry ?} ")")
3914
3915   ;; Fill prefix.
3916   (mdw-standard-fill-prefix "\\([ \t]*\\(?:#+\\|\\<dnl\\>\\)[ \t]*\\)"))
3917
3918 ;;;--------------------------------------------------------------------------
3919 ;;; Text mode.
3920
3921 (defun mdw-text-mode ()
3922   (setq fill-column 72)
3923   (flyspell-mode t)
3924   (mdw-standard-fill-prefix
3925    "\\([ \t]*\\([>#|:] ?\\)*[ \t]*\\)" 3)
3926   (auto-fill-mode 1))
3927
3928 (eval-after-load "flyspell"
3929   '(define-key flyspell-mode-map "\C-\M-i" nil))
3930
3931 ;;;--------------------------------------------------------------------------
3932 ;;; Outline and hide/show modes.
3933
3934 (defun mdw-outline-collapse-all ()
3935   "Completely collapse everything in the entire buffer."
3936   (interactive)
3937   (save-excursion
3938     (goto-char (point-min))
3939     (while (< (point) (point-max))
3940       (hide-subtree)
3941       (forward-line))))
3942
3943 (setq hs-hide-comments-when-hiding-all nil)
3944
3945 (defadvice hs-hide-all (after hide-first-comment activate)
3946   (save-excursion (hs-hide-initial-comment-block)))
3947
3948 ;;;--------------------------------------------------------------------------
3949 ;;; Shell mode.
3950
3951 (defun mdw-sh-mode-setup ()
3952   (local-set-key [?\C-a] 'comint-bol)
3953   (add-hook 'comint-output-filter-functions
3954             'comint-watch-for-password-prompt))
3955
3956 (defun mdw-term-mode-setup ()
3957   (setq term-prompt-regexp shell-prompt-pattern)
3958   (make-local-variable 'mouse-yank-at-point)
3959   (make-local-variable 'transient-mark-mode)
3960   (setq mouse-yank-at-point t)
3961   (auto-fill-mode -1)
3962   (setq tab-width 8))
3963
3964 (defun term-send-meta-right () (interactive) (term-send-raw-string "\e\e[C"))
3965 (defun term-send-meta-left  () (interactive) (term-send-raw-string "\e\e[D"))
3966 (defun term-send-ctrl-uscore () (interactive) (term-send-raw-string "\C-_"))
3967 (defun term-send-meta-meta-something ()
3968   (interactive)
3969   (term-send-raw-string "\e\e")
3970   (term-send-raw))
3971 (eval-after-load 'term
3972   '(progn
3973      (define-key term-raw-map [?\e ?\e] nil)
3974      (define-key term-raw-map [?\e ?\e t] 'term-send-meta-meta-something)
3975      (define-key term-raw-map [?\C-/] 'term-send-ctrl-uscore)
3976      (define-key term-raw-map [M-right] 'term-send-meta-right)
3977      (define-key term-raw-map [?\e ?\M-O ?C] 'term-send-meta-right)
3978      (define-key term-raw-map [M-left] 'term-send-meta-left)
3979      (define-key term-raw-map [?\e ?\M-O ?D] 'term-send-meta-left)))
3980
3981 (defadvice term-exec (before program-args-list compile activate)
3982   "If the PROGRAM argument is a list, interpret it as (PROGRAM . SWITCHES).
3983 This allows you to pass a list of arguments through `ansi-term'."
3984   (let ((program (ad-get-arg 2)))
3985     (if (listp program)
3986         (progn
3987           (ad-set-arg 2 (car program))
3988           (ad-set-arg 4 (cdr program))))))
3989
3990 (defadvice term-exec-1 (around hack-environment compile activate)
3991   "Hack the environment inherited by inferiors in the terminal."
3992   (let ((process-environment process-environment))
3993     (setenv "LD_PRELOAD" nil)
3994     ad-do-it))
3995
3996 (defadvice shell (around hack-environment compile activate)
3997   "Hack the environment inherited by inferiors in the shell."
3998   (let ((process-environment process-environment))
3999     (setenv "LD_PRELOAD" nil)
4000     ad-do-it))
4001
4002 (defun ssh (host)
4003   "Open a terminal containing an ssh session to the HOST."
4004   (interactive "sHost: ")
4005   (ansi-term (list "ssh" host) (format "ssh@%s" host)))
4006
4007 (defvar git-grep-command
4008   "env PAGER=cat git grep --no-color -nH -e "
4009   "*The default command for \\[git-grep].")
4010
4011 (defvar git-grep-history nil)
4012
4013 (defun git-grep (command-args)
4014   "Run `git grep' with user-specified args and collect output in a buffer."
4015   (interactive
4016    (list (read-shell-command "Run git grep (like this): "
4017                              git-grep-command 'git-grep-history)))
4018   (grep command-args))
4019
4020 ;;;--------------------------------------------------------------------------
4021 ;;; Magit configuration.
4022
4023 (setq magit-diff-refine-hunk 'all
4024       magit-view-git-manual-method 'man
4025       magit-log-margin '(nil age magit-log-margin-width t 18)
4026       magit-wip-after-save-local-mode-lighter ""
4027       magit-wip-after-apply-mode-lighter ""
4028       magit-wip-before-change-mode-lighter "")
4029 (eval-after-load "magit"
4030   '(progn (global-magit-file-mode 1)
4031           (magit-wip-after-save-mode 1)
4032           (magit-wip-after-apply-mode 1)
4033           (magit-wip-before-change-mode 1)
4034           (add-to-list 'magit-no-confirm 'safe-with-wip)
4035           (push '(:eval (if (or magit-wip-after-save-local-mode
4036                                 magit-wip-after-apply-mode
4037                                 magit-wip-before-change-mode)
4038                             (format " wip:%s%s%s"
4039                                     (if magit-wip-after-apply-mode "A" "")
4040                                     (if magit-wip-before-change-mode "C" "")
4041                                     (if magit-wip-after-save-local-mode "S" ""))))
4042                 minor-mode-alist)
4043           (dolist (popup '(magit-diff-popup
4044                            magit-diff-refresh-popup
4045                            magit-diff-mode-refresh-popup
4046                            magit-revision-mode-refresh-popup))
4047             (magit-define-popup-switch popup ?R "Reverse diff" "-R"))))
4048
4049 (defadvice magit-wip-commit-buffer-file
4050     (around mdw-just-this-buffer activate compile)
4051   (let ((magit-save-repository-buffers nil)) ad-do-it))
4052
4053 (setq magit-repolist-columns
4054       '(("Name" 16 magit-repolist-column-ident nil)
4055         ("Version" 18 magit-repolist-column-version nil)
4056         ("St" 2 magit-repolist-column-dirty nil)
4057         ("L<U" 3 mdw-repolist-column-unpulled-from-upstream nil)
4058         ("L>U" 3 mdw-repolist-column-unpushed-to-upstream nil)
4059         ("Path" 32 magit-repolist-column-path nil)))
4060
4061 (setq magit-repository-directories '(("~/etc/profile" . 0)
4062                                      ("~/src/" . 1)))
4063
4064 (defadvice magit-list-repos (around mdw-dirname () activate compile)
4065   "Make sure the returned names are directory names.
4066 Otherwise child processes get started in the wrong directory and
4067 there is sadness."
4068   (setq ad-return-value (mapcar #'file-name-as-directory ad-do-it)))
4069
4070 (defun mdw-repolist-column-unpulled-from-upstream (_id)
4071   "Insert number of upstream commits not in the current branch."
4072   (let ((upstream (magit-get-upstream-branch (magit-get-current-branch) t)))
4073     (and upstream
4074          (let ((n (cadr (magit-rev-diff-count "HEAD" upstream))))
4075            (propertize (number-to-string n) 'face
4076                        (if (> n 0) 'bold 'shadow))))))
4077
4078 (defun mdw-repolist-column-unpushed-to-upstream (_id)
4079   "Insert number of commits in the current branch but not its upstream."
4080   (let ((upstream (magit-get-upstream-branch (magit-get-current-branch) t)))
4081     (and upstream
4082          (let ((n (car (magit-rev-diff-count "HEAD" upstream))))
4083            (propertize (number-to-string n) 'face
4084                        (if (> n 0) 'bold 'shadow))))))
4085
4086 (defun mdw-try-smerge ()
4087   (save-excursion
4088     (goto-char (point-min))
4089     (when (re-search-forward "^<<<<<<< " nil t)
4090       (smerge-mode 1))))
4091 (add-hook 'find-file-hook 'mdw-try-smerge t)
4092
4093 ;;;--------------------------------------------------------------------------
4094 ;;; MPC configuration.
4095
4096 (eval-when-compile (trap (require 'mpc)))
4097
4098 (setq mpc-browser-tags '(Artist|Composer|Performer Album|Playlist))
4099
4100 (defun mdw-mpc-now-playing ()
4101   (interactive)
4102   (require 'mpc)
4103   (save-excursion
4104     (set-buffer (mpc-proc-cmd (mpc-proc-cmd-list '("status" "currentsong"))))
4105     (mpc--status-callback))
4106   (let ((state (cdr (assq 'state mpc-status))))
4107     (cond ((member state '("stop"))
4108            (message "mpd stopped."))
4109           ((member state '("play" "pause"))
4110            (let* ((artist (cdr (assq 'Artist mpc-status)))
4111                   (album (cdr (assq 'Album mpc-status)))
4112                   (title (cdr (assq 'Title mpc-status)))
4113                   (file (cdr (assq 'file mpc-status)))
4114                   (duration-string (cdr (assq 'Time mpc-status)))
4115                   (time-string (cdr (assq 'time mpc-status)))
4116                   (time (and time-string
4117                              (string-to-number
4118                               (if (string-match ":" time-string)
4119                                   (substring time-string
4120                                              0 (match-beginning 0))
4121                                 (time-string)))))
4122                   (duration (and duration-string
4123                                  (string-to-number duration-string)))
4124                   (pos (and time duration
4125                             (format " [%d:%02d/%d:%02d]"
4126                                     (/ time 60) (mod time 60)
4127                                     (/ duration 60) (mod duration 60))))
4128                   (fmt (cond ((and artist title)
4129                               (format "`%s' by %s%s" title artist
4130                                       (if album (format ", from `%s'" album)
4131                                         "")))
4132                              (file
4133                               (format "`%s' (no tags)" file))
4134                              (t
4135                               "(no idea what's playing!)"))))
4136              (if (string= state "play")
4137                  (message "mpd playing %s%s" fmt (or pos ""))
4138                (message "mpd paused in %s%s" fmt (or pos "")))))
4139           (t
4140            (message "mpd in unknown state `%s'" state)))))
4141
4142 (defmacro mdw-define-mpc-wrapper (func bvl interactive &rest body)
4143   `(defun ,func ,bvl
4144      (interactive ,@interactive)
4145      (require 'mpc)
4146      ,@body
4147      (mdw-mpc-now-playing)))
4148
4149 (mdw-define-mpc-wrapper mdw-mpc-play-or-pause () nil
4150   (if (member (cdr (assq 'state (mpc-cmd-status))) '("play"))
4151       (mpc-pause)
4152     (mpc-play)))
4153
4154 (mdw-define-mpc-wrapper mdw-mpc-next () nil (mpc-next))
4155 (mdw-define-mpc-wrapper mdw-mpc-prev () nil (mpc-prev))
4156 (mdw-define-mpc-wrapper mdw-mpc-stop () nil (mpc-stop))
4157
4158 (defun mdw-mpc-louder (step)
4159   (interactive (list (if current-prefix-arg
4160                          (prefix-numeric-value current-prefix-arg)
4161                        +10)))
4162   (mpc-proc-cmd (format "volume %+d" step)))
4163
4164 (defun mdw-mpc-quieter (step)
4165   (interactive (list (if current-prefix-arg
4166                          (prefix-numeric-value current-prefix-arg)
4167                        +10)))
4168   (mpc-proc-cmd (format "volume %+d" (- step))))
4169
4170 (defun mdw-mpc-hack-lines (arg interactivep func)
4171   (if (and interactivep (use-region-p))
4172       (let ((from (region-beginning)) (to (region-end)))
4173         (goto-char from)
4174         (beginning-of-line)
4175         (funcall func)
4176         (forward-line)
4177         (while (< (point) to)
4178           (funcall func)
4179           (forward-line)))
4180     (let ((n (prefix-numeric-value arg)))
4181       (cond ((minusp n)
4182              (unless (bolp)
4183                (beginning-of-line)
4184                (funcall func)
4185                (incf n))
4186              (while (minusp n)
4187                (forward-line -1)
4188                (funcall func)
4189                (incf n)))
4190             (t
4191              (beginning-of-line)
4192              (while (plusp n)
4193                (funcall func)
4194                (forward-line)
4195                (decf n)))))))
4196
4197 (defun mdw-mpc-select-one ()
4198   (when (and (get-char-property (point) 'mpc-file)
4199              (not (get-char-property (point) 'mpc-select)))
4200     (mpc-select-toggle)))
4201
4202 (defun mdw-mpc-unselect-one ()
4203   (when (get-char-property (point) 'mpc-select)
4204     (mpc-select-toggle)))
4205
4206 (defun mdw-mpc-select (&optional arg interactivep)
4207   (interactive (list current-prefix-arg t))
4208   (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-select-one))
4209
4210 (defun mdw-mpc-unselect (&optional arg interactivep)
4211   (interactive (list current-prefix-arg t))
4212   (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-unselect-one))
4213
4214 (defun mdw-mpc-unselect-backwards (arg)
4215   (interactive "p")
4216   (mdw-mpc-hack-lines (- arg) t 'mdw-mpc-unselect-one))
4217
4218 (defun mdw-mpc-unselect-all ()
4219   (interactive)
4220   (setq mpc-select nil)
4221   (mpc-selection-refresh))
4222
4223 (defun mdw-mpc-next-line (arg)
4224   (interactive "p")
4225   (beginning-of-line)
4226   (forward-line arg))
4227
4228 (defun mdw-mpc-previous-line (arg)
4229   (interactive "p")
4230   (beginning-of-line)
4231   (forward-line (- arg)))
4232
4233 (defun mdw-mpc-playlist-add (&optional arg interactivep)
4234   (interactive (list current-prefix-arg t))
4235   (let ((mpc-select mpc-select))
4236     (when (or arg (and interactivep (use-region-p)))
4237       (setq mpc-select nil)
4238       (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-select-one))
4239     (setq mpc-select (reverse mpc-select))
4240     (mpc-playlist-add)))
4241
4242 (defun mdw-mpc-playlist-delete (&optional arg interactivep)
4243   (interactive (list current-prefix-arg t))
4244   (setq mpc-select (nreverse mpc-select))
4245   (mpc-select-save
4246     (when (or arg (and interactivep (use-region-p)))
4247       (setq mpc-select nil)
4248       (mpc-selection-refresh)
4249       (mdw-mpc-hack-lines arg interactivep 'mdw-mpc-select-one))
4250       (mpc-playlist-delete)))
4251
4252 (defun mdw-mpc-hack-tagbrowsers ()
4253   (setq-local mode-line-format
4254               '("%e"
4255                 mode-line-frame-identification
4256                 mode-line-buffer-identification)))
4257 (add-hook 'mpc-tagbrowser-mode-hook 'mdw-mpc-hack-tagbrowsers)
4258
4259 (defun mdw-mpc-hack-songs ()
4260   (setq-local header-line-format
4261               ;; '("MPC " mpc-volume " " mpc-current-song)
4262               (list (propertize " " 'display '(space :align-to 0))
4263                     ;; 'mpc-songs-format-description
4264                     '(:eval
4265                       (let ((deactivate-mark) (hscroll (window-hscroll)))
4266                         (with-temp-buffer
4267                           (mpc-format mpc-songs-format 'self hscroll)
4268                           ;; That would be simpler than the hscroll handling in
4269                           ;; mpc-format, but currently move-to-column does not
4270                           ;; recognize :space display properties.
4271                           ;; (move-to-column hscroll)
4272                           ;; (delete-region (point-min) (point))
4273                           (buffer-string)))))))
4274 (add-hook 'mpc-songs-mode-hook 'mdw-mpc-hack-songs)
4275
4276 (eval-after-load "mpc"
4277   '(progn
4278      (define-key mpc-mode-map "m" 'mdw-mpc-select)
4279      (define-key mpc-mode-map "u" 'mdw-mpc-unselect)
4280      (define-key mpc-mode-map "\177" 'mdw-mpc-unselect-backwards)
4281      (define-key mpc-mode-map "\e\177" 'mdw-mpc-unselect-all)
4282      (define-key mpc-mode-map "n" 'mdw-mpc-next-line)
4283      (define-key mpc-mode-map "p" 'mdw-mpc-previous-line)
4284      (define-key mpc-mode-map "/" 'mpc-songs-search)
4285      (setq mpc-songs-mode-map (make-sparse-keymap))
4286      (set-keymap-parent mpc-songs-mode-map mpc-mode-map)
4287      (define-key mpc-songs-mode-map "l" 'mpc-playlist)
4288      (define-key mpc-songs-mode-map "+" 'mdw-mpc-playlist-add)
4289      (define-key mpc-songs-mode-map "-" 'mdw-mpc-playlist-delete)
4290      (define-key mpc-songs-mode-map "\r" 'mpc-songs-jump-to)))
4291
4292 ;;;--------------------------------------------------------------------------
4293 ;;; Inferior Emacs Lisp.
4294
4295 (setq comint-prompt-read-only t)
4296
4297 (eval-after-load "comint"
4298   '(progn
4299      (define-key comint-mode-map "\C-w" 'comint-kill-region)
4300      (define-key comint-mode-map [C-S-backspace] 'comint-kill-whole-line)))
4301
4302 (eval-after-load "ielm"
4303   '(progn
4304      (define-key ielm-map "\C-w" 'comint-kill-region)
4305      (define-key ielm-map [C-S-backspace] 'comint-kill-whole-line)))
4306
4307 ;;;----- That's all, folks --------------------------------------------------
4308
4309 (provide 'dot-emacs)