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