chiark / gitweb /
el/dot-emacs.el: Fix bogus indentation.
[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-chromium
924     browse-url-mozilla
925     browse-url-generic
926     (w3m . mdw-w3m-browse-url)
927     browse-url-w3)
928   "List of good browsers for mdw-good-url-browsers.
929 Each item is a browser function name, or a cons (CHECK . FUNC).
930 A symbol FOO stands for (FOO . FOO).")
931
932 (defun mdw-good-url-browser ()
933   "Return a good URL browser.
934 Trundle the list of such things, finding the first item for which
935 CHECK is fboundp, and returning the correponding FUNC."
936   (let ((bs mdw-good-url-browsers) b check func answer)
937     (while (and bs (not answer))
938       (setq b (car bs)
939             bs (cdr bs))
940       (if (consp b)
941           (setq check (car b) func (cdr b))
942         (setq check b func b))
943       (if (fboundp check)
944           (setq answer func)))
945     answer))
946
947 (eval-after-load "w3m-search"
948   '(progn
949      (dolist
950          (item
951           '(("g" "Google" "http://www.google.co.uk/search?q=%s")
952             ("gd" "Google Directory"
953              "http://www.google.com/search?cat=gwd/Top&q=%s")
954             ("gg" "Google Groups" "http://groups.google.com/groups?q=%s")
955             ("ward" "Ward's wiki" "http://c2.com/cgi/wiki?%s")
956             ("gi" "Images" "http://images.google.com/images?q=%s")
957             ("rfc" "RFC"
958              "http://metalzone.distorted.org.uk/ftp/pub/mirrors/rfc/rfc%s.txt.gz")
959             ("wp" "Wikipedia"
960              "http://en.wikipedia.org/wiki/Special:Search?go=Go&search=%s")
961             ("imdb" "IMDb" "http://www.imdb.com/Find?%s")
962             ("nc-wiki" "nCipher wiki"
963              "http://wiki.ncipher.com/wiki/bin/view/Devel/?topic=%s")
964             ("map" "Google maps" "http://maps.google.co.uk/maps?q=%s&hl=en")
965             ("lp" "Launchpad bug by number"
966              "https://bugs.launchpad.net/bugs/%s")
967             ("lppkg" "Launchpad bugs by package"
968              "https://bugs.launchpad.net/%s")
969             ("msdn" "MSDN"
970              "http://social.msdn.microsoft.com/Search/en-GB/?query=%s&ac=8")
971             ("debbug" "Debian bug by number"
972              "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%s")
973             ("debbugpkg" "Debian bugs by package"
974              "http://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=%s")
975             ("ljlogin" "LJ login" "http://www.livejournal.com/login.bml")))
976        (add-to-list 'w3m-search-engine-alist
977                     (list (cadr item) (caddr item) nil))
978        (add-to-list 'w3m-uri-replace-alist
979                     (list (concat "\\`" (car item) ":")
980                           'w3m-search-uri-replace
981                           (cadr item))))))
982
983 ;;;--------------------------------------------------------------------------
984 ;;; Paragraph filling.
985
986 ;; Useful variables.
987
988 (defvar mdw-fill-prefix nil
989   "*Used by `mdw-line-prefix' and `mdw-fill-paragraph'.
990 If there's no fill prefix currently set (by the `fill-prefix'
991 variable) and there's a match from one of the regexps here, it
992 gets used to set the fill-prefix for the current operation.
993
994 The variable is a list of items of the form `REGEXP . PREFIX'; if
995 the REGEXP matches, the PREFIX is used to set the fill prefix.
996 It in turn is a list of things:
997
998   STRING -- insert a literal string
999   (match . N) -- insert the thing matched by bracketed subexpression N
1000   (pad . N) -- a string of whitespace the same width as subexpression N
1001   (expr . FORM) -- the result of evaluating FORM")
1002
1003 (make-variable-buffer-local 'mdw-fill-prefix)
1004
1005 (defvar mdw-hanging-indents
1006   (concat "\\(\\("
1007             "\\([*o+]\\|-[-#]?\\|[0-9]+\\.\\|\\[[0-9]+\\]\\|([a-zA-Z])\\)"
1008             "[ \t]+"
1009           "\\)?\\)")
1010   "*Standard regexp matching parts of a hanging indent.
1011 This is mainly useful in `auto-fill-mode'.")
1012
1013 ;; Utility functions.
1014
1015 (defun mdw-maybe-tabify (s)
1016   "Tabify or untabify the string S, according to `indent-tabs-mode'."
1017   (let ((tabfun (if indent-tabs-mode #'tabify #'untabify)))
1018     (with-temp-buffer
1019       (save-match-data
1020         (insert s "\n")
1021         (let ((start (point-min)) (end (point-max)))
1022           (funcall tabfun (point-min) (point-max))
1023           (setq s (buffer-substring (point-min) (1- (point-max)))))))))
1024
1025 (defun mdw-examine-fill-prefixes (l)
1026   "Given a list of dynamic fill prefixes, pick one which matches
1027 context and return the static fill prefix to use.  Point must be
1028 at the start of a line, and match data must be saved."
1029   (cond ((not l) nil)
1030         ((looking-at (car (car l)))
1031          (mdw-maybe-tabify (apply #'concat
1032                                   (mapcar #'mdw-do-prefix-match
1033                                           (cdr (car l))))))
1034         (t (mdw-examine-fill-prefixes (cdr l)))))
1035
1036 (defun mdw-maybe-car (p)
1037   "If P is a pair, return (car P), otherwise just return P."
1038   (if (consp p) (car p) p))
1039
1040 (defun mdw-padding (s)
1041   "Return a string the same width as S but made entirely from whitespace."
1042   (let* ((l (length s)) (i 0) (n (make-string l ? )))
1043     (while (< i l)
1044       (if (= 9 (aref s i))
1045           (aset n i 9))
1046       (setq i (1+ i)))
1047     n))
1048
1049 (defun mdw-do-prefix-match (m)
1050   "Expand a dynamic prefix match element.
1051 See `mdw-fill-prefix' for details."
1052   (cond ((not (consp m)) (format "%s" m))
1053         ((eq (car m) 'match) (match-string (mdw-maybe-car (cdr m))))
1054         ((eq (car m) 'pad) (mdw-padding (match-string
1055                                          (mdw-maybe-car (cdr m)))))
1056         ((eq (car m) 'eval) (eval (cdr m)))
1057         (t "")))
1058
1059 (defun mdw-choose-dynamic-fill-prefix ()
1060   "Work out the dynamic fill prefix based on the variable `mdw-fill-prefix'."
1061   (cond ((and fill-prefix (not (string= fill-prefix ""))) fill-prefix)
1062         ((not mdw-fill-prefix) fill-prefix)
1063         (t (save-excursion
1064              (beginning-of-line)
1065              (save-match-data
1066                (mdw-examine-fill-prefixes mdw-fill-prefix))))))
1067
1068 (defadvice do-auto-fill (around mdw-dynamic-fill-prefix () activate compile)
1069   "Handle auto-filling, working out a dynamic fill prefix in the
1070 case where there isn't a sensible static one."
1071   (let ((fill-prefix (mdw-choose-dynamic-fill-prefix)))
1072     ad-do-it))
1073
1074 (defun mdw-fill-paragraph ()
1075   "Fill paragraph, getting a dynamic fill prefix."
1076   (interactive)
1077   (let ((fill-prefix (mdw-choose-dynamic-fill-prefix)))
1078     (fill-paragraph nil)))
1079
1080 (defun mdw-standard-fill-prefix (rx &optional mat)
1081   "Set the dynamic fill prefix, handling standard hanging indents and stuff.
1082 This is just a short-cut for setting the thing by hand, and by
1083 design it doesn't cope with anything approximating a complicated
1084 case."
1085   (setq mdw-fill-prefix
1086         `((,(concat rx mdw-hanging-indents)
1087            (match . 1)
1088            (pad . ,(or mat 2))))))
1089
1090 ;;;--------------------------------------------------------------------------
1091 ;;; Other common declarations.
1092
1093 ;; Common mode settings.
1094
1095 (defvar mdw-auto-indent t
1096   "Whether to indent automatically after a newline.")
1097
1098 (defun mdw-whitespace-mode (&optional arg)
1099   "Turn on/off whitespace mode, but don't highlight trailing space."
1100   (interactive "P")
1101   (when (and (boundp 'whitespace-style)
1102              (fboundp 'whitespace-mode))
1103     (let ((whitespace-style (remove 'trailing whitespace-style)))
1104       (whitespace-mode arg))
1105     (setq show-trailing-whitespace whitespace-mode)))
1106
1107 (defvar mdw-do-misc-mode-hacking nil)
1108
1109 (defun mdw-misc-mode-config ()
1110   (and mdw-auto-indent
1111        (cond ((eq major-mode 'lisp-mode)
1112               (local-set-key "\C-m" 'mdw-indent-newline-and-indent))
1113              ((derived-mode-p 'slime-repl-mode 'asm-mode 'comint-mode)
1114               nil)
1115              (t
1116               (local-set-key "\C-m" 'newline-and-indent))))
1117   (set (make-local-variable 'mdw-do-misc-mode-hacking) t)
1118   (local-set-key [C-return] 'newline)
1119   (make-local-variable 'page-delimiter)
1120   (setq page-delimiter "\f\\|^.*-\\{6\\}.*$")
1121   (setq comment-column 40)
1122   (auto-fill-mode 1)
1123   (setq fill-column mdw-text-width)
1124   (and (fboundp 'gtags-mode)
1125        (gtags-mode))
1126   (if (fboundp 'hs-minor-mode)
1127       (trap (hs-minor-mode t))
1128     (outline-minor-mode t))
1129   (reveal-mode t)
1130   (trap (turn-on-font-lock)))
1131
1132 (defun mdw-post-local-vars-misc-mode-config ()
1133   (setq whitespace-line-column mdw-text-width)
1134   (when (and mdw-do-misc-mode-hacking
1135              (not buffer-read-only))
1136     (setq show-trailing-whitespace t)
1137     (mdw-whitespace-mode 1)))
1138 (add-hook 'hack-local-variables-hook 'mdw-post-local-vars-misc-mode-config)
1139
1140 (defmacro mdw-advise-update-angry-fruit-salad (&rest funcs)
1141   `(progn ,@(mapcar (lambda (func)
1142                       `(defadvice ,func
1143                            (after mdw-angry-fruit-salad activate)
1144                          (when mdw-do-misc-mode-hacking
1145                            (setq show-trailing-whitespace
1146                                  (not buffer-read-only))
1147                            (mdw-whitespace-mode (if buffer-read-only 0 1)))))
1148                     funcs)))
1149 (mdw-advise-update-angry-fruit-salad toggle-read-only
1150                                      read-only-mode
1151                                      view-mode
1152                                      view-mode-enable
1153                                      view-mode-disable)
1154
1155 (eval-after-load 'gtags
1156   '(progn
1157      (dolist (key '([mouse-2] [mouse-3]))
1158        (define-key gtags-mode-map key nil))
1159      (define-key gtags-mode-map [C-S-mouse-2] 'gtags-find-tag-by-event)
1160      (define-key gtags-select-mode-map [C-S-mouse-2]
1161        'gtags-select-tag-by-event)
1162      (dolist (map (list gtags-mode-map gtags-select-mode-map))
1163        (define-key map [C-S-mouse-3] 'gtags-pop-stack))))
1164
1165 ;; Backup file handling.
1166
1167 (defvar mdw-backup-disable-regexps nil
1168   "*List of regular expressions: if a file name matches any of
1169 these then the file is not backed up.")
1170
1171 (defun mdw-backup-enable-predicate (name)
1172   "[mdw]'s default backup predicate.
1173 Allows a backup if the standard predicate would allow it, and it
1174 doesn't match any of the regular expressions in
1175 `mdw-backup-disable-regexps'."
1176   (and (normal-backup-enable-predicate name)
1177        (let ((answer t) (list mdw-backup-disable-regexps))
1178          (save-match-data
1179            (while list
1180              (if (string-match (car list) name)
1181                  (setq answer nil))
1182              (setq list (cdr list)))
1183            answer))))
1184 (setq backup-enable-predicate 'mdw-backup-enable-predicate)
1185
1186 ;; Frame cleanup.
1187
1188 (defun mdw-last-one-out-turn-off-the-lights (frame)
1189   "Disconnect from an X display if this was the last frame on that display."
1190   (let ((frame-display (frame-parameter frame 'display)))
1191     (when (and frame-display
1192                (eq window-system 'x)
1193                (not (some (lambda (fr)
1194                             (and (not (eq fr frame))
1195                                  (string= (frame-parameter fr 'display)
1196                                           frame-display)))
1197                           (frame-list))))
1198       (run-with-idle-timer 0 nil #'x-close-connection frame-display))))
1199 (add-hook 'delete-frame-functions 'mdw-last-one-out-turn-off-the-lights)
1200
1201 ;;;--------------------------------------------------------------------------
1202 ;;; Fullscreen-ness.
1203
1204 (defvar mdw-full-screen-parameters
1205   '((menu-bar-lines . 0)
1206     ;(vertical-scroll-bars . nil)
1207     )
1208   "Frame parameters to set when making a frame fullscreen.")
1209
1210 (defvar mdw-full-screen-save
1211   '(width height)
1212   "Extra frame parameters to save when setting fullscreen.")
1213
1214 (defun mdw-toggle-full-screen (&optional frame)
1215   "Show the FRAME fullscreen."
1216   (interactive)
1217   (when window-system
1218     (cond ((frame-parameter frame 'fullscreen)
1219            (set-frame-parameter frame 'fullscreen nil)
1220            (modify-frame-parameters
1221             nil
1222             (or (frame-parameter frame 'mdw-full-screen-saved)
1223                 (mapcar (lambda (assoc)
1224                           (assq (car assoc) default-frame-alist))
1225                         mdw-full-screen-parameters))))
1226           (t
1227            (let ((saved (mapcar (lambda (param)
1228                                   (cons param (frame-parameter frame param)))
1229                                 (append (mapcar #'car
1230                                                 mdw-full-screen-parameters)
1231                                         mdw-full-screen-save))))
1232              (set-frame-parameter frame 'mdw-full-screen-saved saved))
1233            (modify-frame-parameters frame mdw-full-screen-parameters)
1234            (set-frame-parameter frame 'fullscreen 'fullboth)))))
1235
1236 ;;;--------------------------------------------------------------------------
1237 ;;; General fontification.
1238
1239 (make-face 'mdw-virgin-face)
1240
1241 (defmacro mdw-define-face (name &rest body)
1242   "Define a face, and make sure it's actually set as the definition."
1243   (declare (indent 1)
1244            (debug 0))
1245   `(progn
1246      (copy-face 'mdw-virgin-face ',name)
1247      (defvar ,name ',name)
1248      (put ',name 'face-defface-spec ',body)
1249      (face-spec-set ',name ',body nil)))
1250
1251 (mdw-define-face default
1252   (((type w32)) :family "courier new" :height 85)
1253   (((type x)) :family "6x13" :foundry "trad" :height 130)
1254   (((type color)) :foreground "white" :background "black")
1255   (t nil))
1256 (mdw-define-face fixed-pitch
1257   (((type w32)) :family "courier new" :height 85)
1258   (((type x)) :family "6x13" :foundry "trad" :height 130)
1259   (t :foreground "white" :background "black"))
1260 (if (mdw-emacs-version-p 23)
1261     (mdw-define-face variable-pitch
1262       (((type x)) :family "sans" :height 100))
1263   (mdw-define-face variable-pitch
1264     (((type x)) :family "helvetica" :height 90)))
1265 (mdw-define-face region
1266   (((min-colors 64)) :background "grey30")
1267   (((class color)) :background "blue")
1268   (t :inverse-video t))
1269 (mdw-define-face match
1270   (((class color)) :background "blue")
1271   (t :inverse-video t))
1272 (mdw-define-face mc/cursor-face
1273   (((class color)) :background "red")
1274   (t :inverse-video t))
1275 (mdw-define-face minibuffer-prompt
1276   (t :weight bold))
1277 (mdw-define-face mode-line
1278   (((class color)) :foreground "blue" :background "yellow"
1279                    :box (:line-width 1 :style released-button))
1280   (t :inverse-video t))
1281 (mdw-define-face mode-line-inactive
1282   (((class color)) :foreground "yellow" :background "blue"
1283                    :box (:line-width 1 :style released-button))
1284   (t :inverse-video t))
1285 (mdw-define-face nobreak-space
1286   (((type tty)))
1287   (t :inherit escape-glyph :underline t))
1288 (mdw-define-face scroll-bar
1289   (t :foreground "black" :background "lightgrey"))
1290 (mdw-define-face fringe
1291   (t :foreground "yellow"))
1292 (mdw-define-face show-paren-match
1293   (((min-colors 64)) :background "darkgreen")
1294   (((class color)) :background "green")
1295   (t :underline t))
1296 (mdw-define-face show-paren-mismatch
1297   (((class color)) :background "red")
1298   (t :inverse-video t))
1299 (mdw-define-face highlight
1300   (((min-colors 64)) :background "DarkSeaGreen4")
1301   (((class color)) :background "cyan")
1302   (t :inverse-video t))
1303
1304 (mdw-define-face holiday-face
1305   (t :background "red"))
1306 (mdw-define-face calendar-today-face
1307   (t :foreground "yellow" :weight bold))
1308
1309 (mdw-define-face comint-highlight-prompt
1310   (t :weight bold))
1311 (mdw-define-face comint-highlight-input
1312   (t nil))
1313
1314 (mdw-define-face ido-subdir
1315   (t :foreground "cyan" :weight bold))
1316
1317 (mdw-define-face dired-directory
1318   (t :foreground "cyan" :weight bold))
1319 (mdw-define-face dired-symlink
1320   (t :foreground "cyan"))
1321 (mdw-define-face dired-perm-write
1322   (t nil))
1323
1324 (mdw-define-face trailing-whitespace
1325   (((class color)) :background "red")
1326   (t :inverse-video t))
1327 (mdw-define-face whitespace-line
1328   (((class color)) :background "darkred")
1329   (t :inverse-video t))
1330 (mdw-define-face mdw-punct-face
1331   (((min-colors 64)) :foreground "burlywood2")
1332   (((class color)) :foreground "yellow"))
1333 (mdw-define-face mdw-number-face
1334   (t :foreground "yellow"))
1335 (mdw-define-face mdw-trivial-face)
1336 (mdw-define-face font-lock-function-name-face
1337   (t :slant italic))
1338 (mdw-define-face font-lock-keyword-face
1339   (t :weight bold))
1340 (mdw-define-face font-lock-constant-face
1341   (t :slant italic))
1342 (mdw-define-face font-lock-builtin-face
1343   (t :weight bold))
1344 (mdw-define-face font-lock-type-face
1345   (t :weight bold :slant italic))
1346 (mdw-define-face font-lock-reference-face
1347   (t :weight bold))
1348 (mdw-define-face font-lock-variable-name-face
1349   (t :slant italic))
1350 (mdw-define-face font-lock-comment-delimiter-face
1351   (((min-colors 64)) :slant italic :foreground "SeaGreen1")
1352   (((class color)) :foreground "green")
1353   (t :weight bold))
1354 (mdw-define-face font-lock-comment-face
1355   (((min-colors 64)) :slant italic :foreground "SeaGreen1")
1356   (((class color)) :foreground "green")
1357   (t :weight bold))
1358 (mdw-define-face font-lock-string-face
1359   (((min-colors 64)) :foreground "SkyBlue1")
1360   (((class color)) :foreground "cyan")
1361   (t :weight bold))
1362
1363 (mdw-define-face message-separator
1364   (t :background "red" :foreground "white" :weight bold))
1365 (mdw-define-face message-cited-text
1366   (default :slant italic)
1367   (((min-colors 64)) :foreground "SkyBlue1")
1368   (((class color)) :foreground "cyan"))
1369 (mdw-define-face message-header-cc
1370   (default :slant italic)
1371   (((min-colors 64)) :foreground "SeaGreen1")
1372   (((class color)) :foreground "green"))
1373 (mdw-define-face message-header-newsgroups
1374   (default :slant italic)
1375   (((min-colors 64)) :foreground "SeaGreen1")
1376   (((class color)) :foreground "green"))
1377 (mdw-define-face message-header-subject
1378   (((min-colors 64)) :foreground "SeaGreen1")
1379   (((class color)) :foreground "green"))
1380 (mdw-define-face message-header-to
1381   (((min-colors 64)) :foreground "SeaGreen1")
1382   (((class color)) :foreground "green"))
1383 (mdw-define-face message-header-xheader
1384   (default :slant italic)
1385   (((min-colors 64)) :foreground "SeaGreen1")
1386   (((class color)) :foreground "green"))
1387 (mdw-define-face message-header-other
1388   (default :slant italic)
1389   (((min-colors 64)) :foreground "SeaGreen1")
1390   (((class color)) :foreground "green"))
1391 (mdw-define-face message-header-name
1392   (default :weight bold)
1393   (((min-colors 64)) :foreground "SeaGreen1")
1394   (((class color)) :foreground "green"))
1395
1396 (mdw-define-face which-func
1397   (t nil))
1398
1399 (mdw-define-face gnus-header-name
1400   (default :weight bold)
1401   (((min-colors 64)) :foreground "SeaGreen1")
1402   (((class color)) :foreground "green"))
1403 (mdw-define-face gnus-header-subject
1404   (((min-colors 64)) :foreground "SeaGreen1")
1405   (((class color)) :foreground "green"))
1406 (mdw-define-face gnus-header-from
1407   (((min-colors 64)) :foreground "SeaGreen1")
1408   (((class color)) :foreground "green"))
1409 (mdw-define-face gnus-header-to
1410   (((min-colors 64)) :foreground "SeaGreen1")
1411   (((class color)) :foreground "green"))
1412 (mdw-define-face gnus-header-content
1413   (default :slant italic)
1414   (((min-colors 64)) :foreground "SeaGreen1")
1415   (((class color)) :foreground "green"))
1416
1417 (mdw-define-face gnus-cite-1
1418   (((min-colors 64)) :foreground "SkyBlue1")
1419   (((class color)) :foreground "cyan"))
1420 (mdw-define-face gnus-cite-2
1421   (((min-colors 64)) :foreground "RoyalBlue2")
1422   (((class color)) :foreground "blue"))
1423 (mdw-define-face gnus-cite-3
1424   (((min-colors 64)) :foreground "MediumOrchid")
1425   (((class color)) :foreground "magenta"))
1426 (mdw-define-face gnus-cite-4
1427   (((min-colors 64)) :foreground "firebrick2")
1428   (((class color)) :foreground "red"))
1429 (mdw-define-face gnus-cite-5
1430   (((min-colors 64)) :foreground "burlywood2")
1431   (((class color)) :foreground "yellow"))
1432 (mdw-define-face gnus-cite-6
1433   (((min-colors 64)) :foreground "SeaGreen1")
1434   (((class color)) :foreground "green"))
1435 (mdw-define-face gnus-cite-7
1436   (((min-colors 64)) :foreground "SlateBlue1")
1437   (((class color)) :foreground "cyan"))
1438 (mdw-define-face gnus-cite-8
1439   (((min-colors 64)) :foreground "RoyalBlue2")
1440   (((class color)) :foreground "blue"))
1441 (mdw-define-face gnus-cite-9
1442   (((min-colors 64)) :foreground "purple2")
1443   (((class color)) :foreground "magenta"))
1444 (mdw-define-face gnus-cite-10
1445   (((min-colors 64)) :foreground "DarkOrange2")
1446   (((class color)) :foreground "red"))
1447 (mdw-define-face gnus-cite-11
1448   (t :foreground "grey"))
1449
1450 (mdw-define-face diff-header
1451   (t nil))
1452 (mdw-define-face diff-index
1453   (t :weight bold))
1454 (mdw-define-face diff-file-header
1455   (t :weight bold))
1456 (mdw-define-face diff-hunk-header
1457   (((min-colors 64)) :foreground "SkyBlue1")
1458   (((class color)) :foreground "cyan"))
1459 (mdw-define-face diff-function
1460   (default :weight bold)
1461   (((min-colors 64)) :foreground "SkyBlue1")
1462   (((class color)) :foreground "cyan"))
1463 (mdw-define-face diff-header
1464   (((min-colors 64)) :background "grey10"))
1465 (mdw-define-face diff-added
1466   (((class color)) :foreground "green"))
1467 (mdw-define-face diff-removed
1468   (((class color)) :foreground "red"))
1469 (mdw-define-face diff-context
1470   (t nil))
1471 (mdw-define-face diff-refine-change
1472   (((min-colors 64)) :background "RoyalBlue4")
1473   (t :underline t))
1474 (mdw-define-face diff-refine-removed
1475   (((min-colors 64)) :background "#500")
1476   (t :underline t))
1477 (mdw-define-face diff-refine-added
1478   (((min-colors 64)) :background "#050")
1479   (t :underline t))
1480
1481 (setq ediff-force-faces t)
1482 (mdw-define-face ediff-current-diff-A
1483   (((min-colors 64)) :background "darkred")
1484   (((class color)) :background "red")
1485   (t :inverse-video t))
1486 (mdw-define-face ediff-fine-diff-A
1487   (((min-colors 64)) :background "red3")
1488   (((class color)) :inverse-video t)
1489   (t :inverse-video nil))
1490 (mdw-define-face ediff-even-diff-A
1491   (((min-colors 64)) :background "#300"))
1492 (mdw-define-face ediff-odd-diff-A
1493   (((min-colors 64)) :background "#300"))
1494 (mdw-define-face ediff-current-diff-B
1495   (((min-colors 64)) :background "darkgreen")
1496   (((class color)) :background "magenta")
1497   (t :inverse-video t))
1498 (mdw-define-face ediff-fine-diff-B
1499   (((min-colors 64)) :background "green4")
1500   (((class color)) :inverse-video t)
1501   (t :inverse-video nil))
1502 (mdw-define-face ediff-even-diff-B
1503   (((min-colors 64)) :background "#020"))
1504 (mdw-define-face ediff-odd-diff-B
1505   (((min-colors 64)) :background "#020"))
1506 (mdw-define-face ediff-current-diff-C
1507   (((min-colors 64)) :background "darkblue")
1508   (((class color)) :background "blue")
1509   (t :inverse-video t))
1510 (mdw-define-face ediff-fine-diff-C
1511   (((min-colors 64)) :background "blue1")
1512   (((class color)) :inverse-video t)
1513   (t :inverse-video nil))
1514 (mdw-define-face ediff-even-diff-C
1515   (((min-colors 64)) :background "#004"))
1516 (mdw-define-face ediff-odd-diff-C
1517   (((min-colors 64)) :background "#004"))
1518 (mdw-define-face ediff-current-diff-Ancestor
1519   (((min-colors 64)) :background "#630")
1520   (((class color)) :background "blue")
1521   (t :inverse-video t))
1522 (mdw-define-face ediff-even-diff-Ancestor
1523   (((min-colors 64)) :background "#320"))
1524 (mdw-define-face ediff-odd-diff-Ancestor
1525   (((min-colors 64)) :background "#320"))
1526
1527 (mdw-define-face magit-hash
1528   (((min-colors 64)) :foreground "grey40")
1529   (((class color)) :foreground "blue"))
1530 (mdw-define-face magit-diff-hunk-heading
1531   (((min-colors 64)) :foreground "grey70" :background "grey25")
1532   (((class color)) :foreground "yellow"))
1533 (mdw-define-face magit-diff-hunk-heading-highlight
1534   (((min-colors 64)) :foreground "grey70" :background "grey35")
1535   (((class color)) :foreground "yellow" :background "blue"))
1536 (mdw-define-face magit-diff-added
1537   (((min-colors 64)) :foreground "#ddffdd" :background "#335533")
1538   (((class color)) :foreground "green"))
1539 (mdw-define-face magit-diff-added-highlight
1540   (((min-colors 64)) :foreground "#cceecc" :background "#336633")
1541   (((class color)) :foreground "green" :background "blue"))
1542 (mdw-define-face magit-diff-removed
1543   (((min-colors 64)) :foreground "#ffdddd" :background "#553333")
1544   (((class color)) :foreground "red"))
1545 (mdw-define-face magit-diff-removed-highlight
1546   (((min-colors 64)) :foreground "#eecccc" :background "#663333")
1547   (((class color)) :foreground "red" :background "blue"))
1548 (mdw-define-face magit-blame-heading
1549   (((min-colors 64)) :foreground "white" :background "grey25"
1550                      :weight normal :slant normal)
1551   (((class color)) :foreground "white" :background "blue"
1552                    :weight normal :slant normal))
1553 (mdw-define-face magit-blame-name
1554   (t :inherit magit-blame-heading :slant italic))
1555 (mdw-define-face magit-blame-date
1556   (((min-colors 64)) :inherit magit-blame-heading :foreground "grey60")
1557   (((class color)) :inherit magit-blame-heading :foreground "cyan"))
1558 (mdw-define-face magit-blame-summary
1559   (t :inherit magit-blame-heading :weight bold))
1560
1561 (mdw-define-face dylan-header-background
1562   (((min-colors 64)) :background "NavyBlue")
1563   (((class color)) :background "blue"))
1564
1565 (mdw-define-face erc-input-face
1566   (t :foreground "red"))
1567
1568 (mdw-define-face woman-bold
1569   (t :weight bold))
1570 (mdw-define-face woman-italic
1571   (t :slant italic))
1572
1573 (eval-after-load "rst"
1574   '(progn
1575      (mdw-define-face rst-level-1-face
1576        (t :foreground "SkyBlue1" :weight bold))
1577      (mdw-define-face rst-level-2-face
1578        (t :foreground "SeaGreen1" :weight bold))
1579      (mdw-define-face rst-level-3-face
1580        (t :weight bold))
1581      (mdw-define-face rst-level-4-face
1582        (t :slant italic))
1583      (mdw-define-face rst-level-5-face
1584        (t :underline t))
1585      (mdw-define-face rst-level-6-face
1586        ())))
1587
1588 (mdw-define-face p4-depot-added-face
1589   (t :foreground "green"))
1590 (mdw-define-face p4-depot-branch-op-face
1591   (t :foreground "yellow"))
1592 (mdw-define-face p4-depot-deleted-face
1593   (t :foreground "red"))
1594 (mdw-define-face p4-depot-unmapped-face
1595   (t :foreground "SkyBlue1"))
1596 (mdw-define-face p4-diff-change-face
1597   (t :foreground "yellow"))
1598 (mdw-define-face p4-diff-del-face
1599   (t :foreground "red"))
1600 (mdw-define-face p4-diff-file-face
1601   (t :foreground "SkyBlue1"))
1602 (mdw-define-face p4-diff-head-face
1603   (t :background "grey10"))
1604 (mdw-define-face p4-diff-ins-face
1605   (t :foreground "green"))
1606
1607 (mdw-define-face w3m-anchor-face
1608   (t :foreground "SkyBlue1" :underline t))
1609 (mdw-define-face w3m-arrived-anchor-face
1610   (t :foreground "SkyBlue1" :underline t))
1611
1612 (mdw-define-face whizzy-slice-face
1613   (t :background "grey10"))
1614 (mdw-define-face whizzy-error-face
1615   (t :background "darkred"))
1616
1617 ;; Ellipses used to indicate hidden text (and similar).
1618 (mdw-define-face mdw-ellipsis-face
1619   (((type tty)) :foreground "blue") (t :foreground "grey60"))
1620 (let ((dollar (make-glyph-code ?$ 'mdw-ellipsis-face))
1621       (backslash (make-glyph-code ?\\ 'mdw-ellipsis-face))
1622       (dot (make-glyph-code ?. 'mdw-ellipsis-face))
1623       (bar (make-glyph-code ?| mdw-ellipsis-face)))
1624   (set-display-table-slot standard-display-table 0 dollar)
1625   (set-display-table-slot standard-display-table 1 backslash)
1626   (set-display-table-slot standard-display-table 4
1627                           (vector dot dot dot))
1628   (set-display-table-slot standard-display-table 5 bar))
1629
1630 ;;;--------------------------------------------------------------------------
1631 ;;; Where is point?
1632
1633 (mdw-define-face mdw-point-overlay-face
1634   (((type graphic)))
1635   (((min-colors 64)) :background "darkblue")
1636   (((class color)) :background "blue")
1637   (((type tty) (class mono)) :inverse-video t))
1638
1639 (defvar mdw-point-overlay-fringe-display '(vertical-bar . vertical-bar))
1640
1641 (defun mdw-configure-point-overlay ()
1642   (let ((ov (make-overlay 0 0)))
1643     (overlay-put ov 'priority 0)
1644     (let* ((fringe (or mdw-point-overlay-fringe-display (cons nil nil)))
1645            (left (car fringe)) (right (cdr fringe))
1646            (s ""))
1647       (when left
1648         (let ((ss "."))
1649           (put-text-property 0 1 'display `(left-fringe ,left) ss)
1650           (setq s (concat s ss))))
1651       (when right
1652         (let ((ss "."))
1653           (put-text-property 0 1 'display `(right-fringe ,right) ss)
1654           (setq s (concat s ss))))
1655       (when (or left right)
1656         (overlay-put ov 'before-string s)))
1657     (overlay-put ov 'face 'mdw-point-overlay-face)
1658     (delete-overlay ov)
1659     ov))
1660
1661 (defvar mdw-point-overlay (mdw-configure-point-overlay)
1662   "An overlay used for showing where point is in the selected window.")
1663 (defun mdw-reconfigure-point-overlay ()
1664   (interactive)
1665   (setq mdw-point-overlay (mdw-configure-point-overlay)))
1666
1667 (defun mdw-remove-point-overlay ()
1668   "Remove the current-point overlay."
1669   (delete-overlay mdw-point-overlay))
1670
1671 (defun mdw-update-point-overlay ()
1672   "Mark the current point position with an overlay."
1673   (if (not mdw-point-overlay-mode)
1674       (mdw-remove-point-overlay)
1675     (overlay-put mdw-point-overlay 'window (selected-window))
1676     (move-overlay mdw-point-overlay
1677                   (line-beginning-position)
1678                   (+ (line-end-position) 1))))
1679
1680 (defvar mdw-point-overlay-buffers nil
1681   "List of buffers using `mdw-point-overlay-mode'.")
1682
1683 (define-minor-mode mdw-point-overlay-mode
1684   "Indicate current line with an overlay."
1685   :global nil
1686   (let ((buffer (current-buffer)))
1687     (setq mdw-point-overlay-buffers
1688           (mapcan (lambda (buf)
1689                     (if (and (buffer-live-p buf)
1690                              (not (eq buf buffer)))
1691                         (list buf)))
1692                   mdw-point-overlay-buffers))
1693     (if mdw-point-overlay-mode
1694         (setq mdw-point-overlay-buffers
1695               (cons buffer mdw-point-overlay-buffers))))
1696   (cond (mdw-point-overlay-buffers
1697          (add-hook 'pre-command-hook 'mdw-remove-point-overlay)
1698          (add-hook 'post-command-hook 'mdw-update-point-overlay))
1699         (t
1700          (mdw-remove-point-overlay)
1701          (remove-hook 'pre-command-hook 'mdw-remove-point-overlay)
1702          (remove-hook 'post-command-hook 'mdw-update-point-overlay))))
1703
1704 (define-globalized-minor-mode mdw-global-point-overlay-mode
1705   mdw-point-overlay-mode
1706   (lambda () (if (not (minibufferp)) (mdw-point-overlay-mode t))))
1707
1708 ;;;--------------------------------------------------------------------------
1709 ;;; C programming configuration.
1710
1711 ;; Make C indentation nice.
1712
1713 (defun mdw-c-lineup-arglist (langelem)
1714   "Hack for DWIMmery in c-lineup-arglist."
1715   (if (save-excursion
1716         (c-block-in-arglist-dwim (c-langelem-2nd-pos c-syntactic-element)))
1717       0
1718     (c-lineup-arglist langelem)))
1719
1720 (defun mdw-c-indent-extern-mumble (langelem)
1721   "Indent `extern \"...\" {' lines."
1722   (save-excursion
1723     (back-to-indentation)
1724     (if (looking-at
1725          "\\s-*\\<extern\\>\\s-*\"\\([^\\\\\"]+\\|\\.\\)*\"\\s-*{")
1726         c-basic-offset
1727       nil)))
1728
1729 (defun mdw-c-indent-arglist-nested (langelem)
1730   "Indent continued argument lists.
1731 If we've nested more than one argument list, then only introduce a single
1732 indentation anyway."
1733   (let ((context c-syntactic-context)
1734         (pos (c-langelem-2nd-pos c-syntactic-element))
1735         (should-indent-p t))
1736     (while (and context
1737                 (eq (caar context) 'arglist-cont-nonempty))
1738       (when (and (= (caddr (pop context)) pos)
1739                  context
1740                  (memq (caar context) '(arglist-intro
1741                                         arglist-cont-nonempty)))
1742         (setq should-indent-p nil)))
1743     (if should-indent-p '+ 0)))
1744
1745 (defvar mdw-define-c-styles-hook nil
1746   "Hook run when `cc-mode' starts up to define styles.")
1747
1748 (defmacro mdw-define-c-style (name &rest assocs)
1749   "Define a C style, called NAME (a symbol), setting ASSOCs.
1750 A function, named `mdw-define-c-style/NAME', is defined to actually install
1751 the style using `c-add-style', and added to the hook
1752 `mdw-define-c-styles-hook'.  If CC Mode is already loaded, then the style is
1753 set."
1754   (declare (indent defun))
1755   (let* ((name-string (symbol-name name))
1756          (func (intern (concat "mdw-define-c-style/" name-string))))
1757     `(progn
1758        (defun ,func () (c-add-style ,name-string ',assocs))
1759        (and (featurep 'cc-mode) (,func))
1760        (add-hook 'mdw-define-c-styles-hook ',func))))
1761
1762 (eval-after-load "cc-mode"
1763   '(run-hooks 'mdw-define-c-styles-hook))
1764
1765 (mdw-define-c-style mdw-trustonic-c
1766   (c-basic-offset . 4)
1767   (comment-column . 0)
1768   (c-indent-comment-alist (anchored-comment . (column . 0))
1769                           (end-block . (space . 1))
1770                           (cpp-end-block . (space . 1))
1771                           (other . (space . 1)))
1772   (c-class-key . "class")
1773   (c-backslash-column . 0)
1774   (c-auto-align-backslashes . nil)
1775   (c-label-minimum-indentation . 0)
1776   (c-offsets-alist (substatement-open . (add 0 c-indent-one-line-block))
1777                    (defun-open . (add 0 c-indent-one-line-block))
1778                    (arglist-cont-nonempty . mdw-c-indent-arglist-nested)
1779                    (topmost-intro . mdw-c-indent-extern-mumble)
1780                    (cpp-define-intro . 0)
1781                    (knr-argdecl . 0)
1782                    (inextern-lang . [0])
1783                    (label . 0)
1784                    (case-label . +)
1785                    (access-label . -2)
1786                    (inclass . +)
1787                    (inline-open . ++)
1788                    (statement-cont . +)
1789                    (statement-case-intro . +)))
1790
1791 (mdw-define-c-style mdw-c
1792   (c-basic-offset . 2)
1793   (comment-column . 40)
1794   (c-class-key . "class")
1795   (c-backslash-column . 72)
1796   (c-label-minimum-indentation . 0)
1797   (c-offsets-alist (substatement-open . (add 0 c-indent-one-line-block))
1798                    (defun-open . (add 0 c-indent-one-line-block))
1799                    (arglist-cont-nonempty . mdw-c-lineup-arglist)
1800                    (topmost-intro . mdw-c-indent-extern-mumble)
1801                    (cpp-define-intro . 0)
1802                    (knr-argdecl . 0)
1803                    (inextern-lang . [0])
1804                    (label . 0)
1805                    (case-label . +)
1806                    (access-label . -)
1807                    (inclass . +)
1808                    (inline-open . ++)
1809                    (statement-cont . +)
1810                    (statement-case-intro . +)))
1811
1812 (defun mdw-set-default-c-style (modes style)
1813   "Update the default CC Mode style for MODES to be STYLE.
1814
1815 MODES may be a list of major mode names or a singleton.  STYLE is a style
1816 name, as a symbol."
1817   (let ((modes (if (listp modes) modes (list modes)))
1818         (style (symbol-name style)))
1819     (setq c-default-style
1820           (append (mapcar (lambda (mode)
1821                             (cons mode style))
1822                           modes)
1823                   (remove-if (lambda (assoc)
1824                                (memq (car assoc) modes))
1825                              (if (listp c-default-style)
1826                                  c-default-style
1827                                (list (cons 'other c-default-style))))))))
1828 (setq c-default-style "mdw-c")
1829
1830 (mdw-set-default-c-style '(c-mode c++-mode) 'mdw-c)
1831
1832 (defvar mdw-c-comment-fill-prefix
1833   `((,(concat "\\([ \t]*/?\\)"
1834               "\\(\*\\|//]\\)"
1835               "\\([ \t]*\\)"
1836               "\\([A-Za-z]+:[ \t]*\\)?"
1837               mdw-hanging-indents)
1838      (pad . 1) (match . 2) (pad . 3) (pad . 4) (pad . 5)))
1839   "Fill prefix matching C comments (both kinds).")
1840
1841 (defun mdw-fontify-c-and-c++ ()
1842
1843   ;; Fiddle with some syntax codes.
1844   (modify-syntax-entry ?* ". 23")
1845   (modify-syntax-entry ?/ ". 124b")
1846   (modify-syntax-entry ?\n "> b")
1847
1848   ;; Other stuff.
1849   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
1850
1851   ;; Now define things to be fontified.
1852   (make-local-variable 'font-lock-keywords)
1853   (let ((c-keywords
1854          (mdw-regexps "alignas"          ;C11 macro, C++11
1855                       "alignof"          ;C++11
1856                       "and"              ;C++, C95 macro
1857                       "and_eq"           ;C++, C95 macro
1858                       "asm"              ;K&R, C++, GCC
1859                       "atomic"           ;C11 macro, C++11 template type
1860                       "auto"             ;K&R, C89
1861                       "bitand"           ;C++, C95 macro
1862                       "bitor"            ;C++, C95 macro
1863                       "bool"             ;C++, C99 macro
1864                       "break"            ;K&R, C89
1865                       "case"             ;K&R, C89
1866                       "catch"            ;C++
1867                       "char"             ;K&R, C89
1868                       "char16_t"         ;C++11, C11 library type
1869                       "char32_t"         ;C++11, C11 library type
1870                       "class"            ;C++
1871                       "complex"          ;C99 macro, C++ template type
1872                       "compl"            ;C++, C95 macro
1873                       "const"            ;C89
1874                       "constexpr"        ;C++11
1875                       "const_cast"       ;C++
1876                       "continue"         ;K&R, C89
1877                       "decltype"         ;C++11
1878                       "defined"          ;C89 preprocessor
1879                       "default"          ;K&R, C89
1880                       "delete"           ;C++
1881                       "do"               ;K&R, C89
1882                       "double"           ;K&R, C89
1883                       "dynamic_cast"     ;C++
1884                       "else"             ;K&R, C89
1885                       ;; "entry"         ;K&R -- never used
1886                       "enum"             ;C89
1887                       "explicit"         ;C++
1888                       "export"           ;C++
1889                       "extern"           ;K&R, C89
1890                       "float"            ;K&R, C89
1891                       "for"              ;K&R, C89
1892                       ;; "fortran"       ;K&R
1893                       "friend"           ;C++
1894                       "goto"             ;K&R, C89
1895                       "if"               ;K&R, C89
1896                       "imaginary"        ;C99 macro
1897                       "inline"           ;C++, C99, GCC
1898                       "int"              ;K&R, C89
1899                       "long"             ;K&R, C89
1900                       "mutable"          ;C++
1901                       "namespace"        ;C++
1902                       "new"              ;C++
1903                       "noexcept"         ;C++11
1904                       "noreturn"         ;C11 macro
1905                       "not"              ;C++, C95 macro
1906                       "not_eq"           ;C++, C95 macro
1907                       "nullptr"          ;C++11
1908                       "operator"         ;C++
1909                       "or"               ;C++, C95 macro
1910                       "or_eq"            ;C++, C95 macro
1911                       "private"          ;C++
1912                       "protected"        ;C++
1913                       "public"           ;C++
1914                       "register"         ;K&R, C89
1915                       "reinterpret_cast" ;C++
1916                       "restrict"         ;C99
1917                       "return"           ;K&R, C89
1918                       "short"            ;K&R, C89
1919                       "signed"           ;C89
1920                       "sizeof"           ;K&R, C89
1921                       "static"           ;K&R, C89
1922                       "static_assert"    ;C11 macro, C++11
1923                       "static_cast"      ;C++
1924                       "struct"           ;K&R, C89
1925                       "switch"           ;K&R, C89
1926                       "template"         ;C++
1927                       "throw"            ;C++
1928                       "try"              ;C++
1929                       "thread_local"     ;C11 macro, C++11
1930                       "typedef"          ;C89
1931                       "typeid"           ;C++
1932                       "typeof"           ;GCC
1933                       "typename"         ;C++
1934                       "union"            ;K&R, C89
1935                       "unsigned"         ;K&R, C89
1936                       "using"            ;C++
1937                       "virtual"          ;C++
1938                       "void"             ;C89
1939                       "volatile"         ;C89
1940                       "wchar_t"          ;C++, C89 library type
1941                       "while"            ;K&R, C89
1942                       "xor"              ;C++, C95 macro
1943                       "xor_eq"           ;C++, C95 macro
1944                       "_Alignas"         ;C11
1945                       "_Alignof"         ;C11
1946                       "_Atomic"          ;C11
1947                       "_Bool"            ;C99
1948                       "_Complex"         ;C99
1949                       "_Generic"         ;C11
1950                       "_Imaginary"       ;C99
1951                       "_Noreturn"        ;C11
1952                       "_Pragma"          ;C99 preprocessor
1953                       "_Static_assert"   ;C11
1954                       "_Thread_local"    ;C11
1955                       "__alignof__"      ;GCC
1956                       "__asm__"          ;GCC
1957                       "__attribute__"    ;GCC
1958                       "__complex__"      ;GCC
1959                       "__const__"        ;GCC
1960                       "__extension__"    ;GCC
1961                       "__imag__"         ;GCC
1962                       "__inline__"       ;GCC
1963                       "__label__"        ;GCC
1964                       "__real__"         ;GCC
1965                       "__signed__"       ;GCC
1966                       "__typeof__"       ;GCC
1967                       "__volatile__"     ;GCC
1968                       ))
1969         (c-constants
1970          (mdw-regexps "false"            ;C++, C99 macro
1971                       "this"             ;C++
1972                       "true"             ;C++, C99 macro
1973                       ))
1974         (preprocessor-keywords
1975          (mdw-regexps "assert" "define" "elif" "else" "endif" "error"
1976                       "ident" "if" "ifdef" "ifndef" "import" "include"
1977                       "line" "pragma" "unassert" "undef" "warning"))
1978         (objc-keywords
1979          (mdw-regexps "class" "defs" "encode" "end" "implementation"
1980                       "interface" "private" "protected" "protocol" "public"
1981                       "selector")))
1982
1983     (setq font-lock-keywords
1984           (list
1985
1986            ;; Fontify include files as strings.
1987            (list (concat "^[ \t]*\\#[ \t]*"
1988                          "\\(include\\|import\\)"
1989                          "[ \t]*\\(<[^>]+\\(>\\|\\)\\)")
1990                  '(2 font-lock-string-face))
1991
1992            ;; Preprocessor directives are `references'?.
1993            (list (concat "^\\([ \t]*#[ \t]*\\(\\("
1994                          preprocessor-keywords
1995                          "\\)\\>\\|[0-9]+\\|$\\)\\)")
1996                  '(1 font-lock-keyword-face))
1997
1998            ;; Handle the keywords defined above.
1999            (list (concat "@\\<\\(" objc-keywords "\\)\\>")
2000                  '(0 font-lock-keyword-face))
2001
2002            (list (concat "\\<\\(" c-keywords "\\)\\>")
2003                  '(0 font-lock-keyword-face))
2004
2005            (list (concat "\\<\\(" c-constants "\\)\\>")
2006                  '(0 font-lock-variable-name-face))
2007
2008            ;; Handle numbers too.
2009            ;;
2010            ;; This looks strange, I know.  It corresponds to the
2011            ;; preprocessor's idea of what a number looks like, rather than
2012            ;; anything sensible.
2013            (list (concat "\\(\\<[0-9]\\|\\.[0-9]\\)"
2014                          "\\([Ee][+-]\\|[0-9A-Za-z_.]\\)*")
2015                  '(0 mdw-number-face))
2016
2017            ;; And anything else is punctuation.
2018            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2019                  '(0 mdw-punct-face))))))
2020
2021 (define-derived-mode sod-mode c-mode "Sod"
2022   "Major mode for editing Sod code.")
2023 (push '("\\.sod$" . sod-mode) auto-mode-alist)
2024
2025 ;;;--------------------------------------------------------------------------
2026 ;;; AP calc mode.
2027
2028 (define-derived-mode apcalc-mode c-mode "AP Calc"
2029   "Major mode for editing Calc code.")
2030
2031 (defun mdw-fontify-apcalc ()
2032
2033   ;; Fiddle with some syntax codes.
2034   (modify-syntax-entry ?* ". 23")
2035   (modify-syntax-entry ?/ ". 14")
2036
2037   ;; Other stuff.
2038   (setq comment-start "/* ")
2039   (setq comment-end " */")
2040   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
2041
2042   ;; Now define things to be fontified.
2043   (make-local-variable 'font-lock-keywords)
2044   (let ((c-keywords
2045          (mdw-regexps "break" "case" "cd" "continue" "define" "default"
2046                       "do" "else" "exit" "for" "global" "goto" "help" "if"
2047                       "local" "mat" "obj" "print" "quit" "read" "return"
2048                       "show" "static" "switch" "while" "write")))
2049
2050     (setq font-lock-keywords
2051           (list
2052
2053            ;; Handle the keywords defined above.
2054            (list (concat "\\<\\(" c-keywords "\\)\\>")
2055                  '(0 font-lock-keyword-face))
2056
2057            ;; Handle numbers too.
2058            ;;
2059            ;; This looks strange, I know.  It corresponds to the
2060            ;; preprocessor's idea of what a number looks like, rather than
2061            ;; anything sensible.
2062            (list (concat "\\(\\<[0-9]\\|\\.[0-9]\\)"
2063                          "\\([Ee][+-]\\|[0-9A-Za-z_.]\\)*")
2064                  '(0 mdw-number-face))
2065
2066            ;; And anything else is punctuation.
2067            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2068                  '(0 mdw-punct-face))))))
2069
2070 ;;;--------------------------------------------------------------------------
2071 ;;; Java programming configuration.
2072
2073 ;; Make indentation nice.
2074
2075 (mdw-define-c-style mdw-java
2076   (c-basic-offset . 2)
2077   (c-backslash-column . 72)
2078   (c-offsets-alist (substatement-open . 0)
2079                    (label . +)
2080                    (case-label . +)
2081                    (access-label . 0)
2082                    (inclass . +)
2083                    (statement-case-intro . +)))
2084 (mdw-set-default-c-style 'java-mode 'mdw-java)
2085
2086 ;; Declare Java fontification style.
2087
2088 (defun mdw-fontify-java ()
2089
2090   ;; Other stuff.
2091   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
2092
2093   ;; Now define things to be fontified.
2094   (make-local-variable 'font-lock-keywords)
2095   (let ((java-keywords
2096          (mdw-regexps "abstract" "boolean" "break" "byte" "case" "catch"
2097                       "char" "class" "const" "continue" "default" "do"
2098                       "double" "else" "extends" "final" "finally" "float"
2099                       "for" "goto" "if" "implements" "import" "instanceof"
2100                       "int" "interface" "long" "native" "new" "package"
2101                       "private" "protected" "public" "return" "short"
2102                       "static" "switch" "synchronized" "throw" "throws"
2103                       "transient" "try" "void" "volatile" "while"))
2104
2105         (java-constants
2106          (mdw-regexps "false" "null" "super" "this" "true")))
2107
2108     (setq font-lock-keywords
2109           (list
2110
2111            ;; Handle the keywords defined above.
2112            (list (concat "\\<\\(" java-keywords "\\)\\>")
2113                  '(0 font-lock-keyword-face))
2114
2115            ;; Handle the magic constants defined above.
2116            (list (concat "\\<\\(" java-constants "\\)\\>")
2117                  '(0 font-lock-variable-name-face))
2118
2119            ;; Handle numbers too.
2120            ;;
2121            ;; The following isn't quite right, but it's close enough.
2122            (list (concat "\\<\\("
2123                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
2124                          "[0-9]+\\(\\.[0-9]*\\|\\)"
2125                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
2126                          "[lLfFdD]?")
2127                  '(0 mdw-number-face))
2128
2129            ;; And anything else is punctuation.
2130            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2131                  '(0 mdw-punct-face))))))
2132
2133 ;;;--------------------------------------------------------------------------
2134 ;;; Javascript programming configuration.
2135
2136 (defun mdw-javascript-style ()
2137   (setq js-indent-level 2)
2138   (setq js-expr-indent-offset 0))
2139
2140 (defun mdw-fontify-javascript ()
2141
2142   ;; Other stuff.
2143   (mdw-javascript-style)
2144   (setq js-auto-indent-flag t)
2145
2146   ;; Now define things to be fontified.
2147   (make-local-variable 'font-lock-keywords)
2148   (let ((javascript-keywords
2149          (mdw-regexps "abstract" "boolean" "break" "byte" "case" "catch"
2150                       "char" "class" "const" "continue" "debugger" "default"
2151                       "delete" "do" "double" "else" "enum" "export" "extends"
2152                       "final" "finally" "float" "for" "function" "goto" "if"
2153                       "implements" "import" "in" "instanceof" "int"
2154                       "interface" "let" "long" "native" "new" "package"
2155                       "private" "protected" "public" "return" "short"
2156                       "static" "super" "switch" "synchronized" "throw"
2157                       "throws" "transient" "try" "typeof" "var" "void"
2158                       "volatile" "while" "with" "yield"
2159
2160                       "boolean" "byte" "char" "double" "float" "int" "long"
2161                       "short" "void"))
2162         (javascript-constants
2163          (mdw-regexps "false" "null" "undefined" "Infinity" "NaN" "true"
2164                       "arguments" "this")))
2165
2166     (setq font-lock-keywords
2167           (list
2168
2169            ;; Handle the keywords defined above.
2170            (list (concat "\\_<\\(" javascript-keywords "\\)\\_>")
2171                  '(0 font-lock-keyword-face))
2172
2173            ;; Handle the predefined constants defined above.
2174            (list (concat "\\_<\\(" javascript-constants "\\)\\_>")
2175                  '(0 font-lock-variable-name-face))
2176
2177            ;; Handle numbers too.
2178            ;;
2179            ;; The following isn't quite right, but it's close enough.
2180            (list (concat "\\_<\\("
2181                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
2182                          "[0-9]+\\(\\.[0-9]*\\|\\)"
2183                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
2184                          "[lLfFdD]?")
2185                  '(0 mdw-number-face))
2186
2187            ;; And anything else is punctuation.
2188            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2189                  '(0 mdw-punct-face))))))
2190
2191 ;;;--------------------------------------------------------------------------
2192 ;;; Scala programming configuration.
2193
2194 (defun mdw-fontify-scala ()
2195
2196   ;; Comment filling.
2197   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
2198
2199   ;; Define things to be fontified.
2200   (make-local-variable 'font-lock-keywords)
2201   (let ((scala-keywords
2202          (mdw-regexps "abstract" "case" "catch" "class" "def" "do" "else"
2203                       "extends" "final" "finally" "for" "forSome" "if"
2204                       "implicit" "import" "lazy" "match" "new" "object"
2205                       "override" "package" "private" "protected" "return"
2206                       "sealed" "throw" "trait" "try" "type" "val"
2207                       "var" "while" "with" "yield"))
2208         (scala-constants
2209          (mdw-regexps "false" "null" "super" "this" "true"))
2210         (punctuation "[-!%^&*=+:@#~/?\\|`]"))
2211
2212     (setq font-lock-keywords
2213           (list
2214
2215            ;; Magical identifiers between backticks.
2216            (list (concat "`\\([^`]+\\)`")
2217                  '(1 font-lock-variable-name-face))
2218
2219            ;; Handle the keywords defined above.
2220            (list (concat "\\_<\\(" scala-keywords "\\)\\_>")
2221                  '(0 font-lock-keyword-face))
2222
2223            ;; Handle the constants defined above.
2224            (list (concat "\\_<\\(" scala-constants "\\)\\_>")
2225                  '(0 font-lock-variable-name-face))
2226
2227            ;; Magical identifiers between backticks.
2228            (list (concat "`\\([^`]+\\)`")
2229                  '(1 font-lock-variable-name-face))
2230
2231            ;; Handle numbers too.
2232            ;;
2233            ;; As usual, not quite right.
2234            (list (concat "\\_<\\("
2235                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
2236                          "[0-9]+\\(\\.[0-9]*\\|\\)"
2237                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
2238                          "[lLfFdD]?")
2239                  '(0 mdw-number-face))
2240
2241            ;; Identifiers with trailing operators.
2242            (list (concat "_\\(" punctuation "\\)+")
2243                  '(0 mdw-trivial-face))
2244
2245            ;; And everything else is punctuation.
2246            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2247                  '(0 mdw-punct-face)))
2248
2249           font-lock-syntactic-keywords
2250           (list
2251
2252            ;; Single quotes around characters.  But not when used to quote
2253            ;; symbol names.  Ugh.
2254            (list (concat "\\('\\)"
2255                          "\\(" "."
2256                          "\\|" "\\\\" "\\(" "\\\\\\\\" "\\)*"
2257                                "u+" "[0-9a-fA-F]\\{4\\}"
2258                          "\\|" "\\\\" "[0-7]\\{1,3\\}"
2259                          "\\|" "\\\\" "." "\\)"
2260                          "\\('\\)")
2261                  '(1 "\"")
2262                  '(4 "\""))))))
2263
2264 ;;;--------------------------------------------------------------------------
2265 ;;; C# programming configuration.
2266
2267 ;; Make indentation nice.
2268
2269 (mdw-define-c-style mdw-csharp
2270   (c-basic-offset . 2)
2271   (c-backslash-column . 72)
2272   (c-offsets-alist (substatement-open . 0)
2273                    (label . 0)
2274                    (case-label . +)
2275                    (access-label . 0)
2276                    (inclass . +)
2277                    (statement-case-intro . +)))
2278 (mdw-set-default-c-style 'csharp-mode 'mdw-csharp)
2279
2280 ;; Declare C# fontification style.
2281
2282 (defun mdw-fontify-csharp ()
2283
2284   ;; Other stuff.
2285   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
2286
2287   ;; Now define things to be fontified.
2288   (make-local-variable 'font-lock-keywords)
2289   (let ((csharp-keywords
2290          (mdw-regexps "abstract" "as" "bool" "break" "byte" "case" "catch"
2291                       "char" "checked" "class" "const" "continue" "decimal"
2292                       "default" "delegate" "do" "double" "else" "enum"
2293                       "event" "explicit" "extern" "finally" "fixed" "float"
2294                       "for" "foreach" "goto" "if" "implicit" "in" "int"
2295                       "interface" "internal" "is" "lock" "long" "namespace"
2296                       "new" "object" "operator" "out" "override" "params"
2297                       "private" "protected" "public" "readonly" "ref"
2298                       "return" "sbyte" "sealed" "short" "sizeof"
2299                       "stackalloc" "static" "string" "struct" "switch"
2300                       "throw" "try" "typeof" "uint" "ulong" "unchecked"
2301                       "unsafe" "ushort" "using" "virtual" "void" "volatile"
2302                       "while" "yield"))
2303
2304         (csharp-constants
2305          (mdw-regexps "base" "false" "null" "this" "true")))
2306
2307     (setq font-lock-keywords
2308           (list
2309
2310            ;; Handle the keywords defined above.
2311            (list (concat "\\<\\(" csharp-keywords "\\)\\>")
2312                  '(0 font-lock-keyword-face))
2313
2314            ;; Handle the magic constants defined above.
2315            (list (concat "\\<\\(" csharp-constants "\\)\\>")
2316                  '(0 font-lock-variable-name-face))
2317
2318            ;; Handle numbers too.
2319            ;;
2320            ;; The following isn't quite right, but it's close enough.
2321            (list (concat "\\<\\("
2322                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
2323                          "[0-9]+\\(\\.[0-9]*\\|\\)"
2324                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
2325                          "[lLfFdD]?")
2326                  '(0 mdw-number-face))
2327
2328            ;; And anything else is punctuation.
2329            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2330                  '(0 mdw-punct-face))))))
2331
2332 (define-derived-mode csharp-mode java-mode "C#"
2333   "Major mode for editing C# code.")
2334
2335 ;;;--------------------------------------------------------------------------
2336 ;;; F# programming configuration.
2337
2338 (setq fsharp-indent-offset 2)
2339
2340 (defun mdw-fontify-fsharp ()
2341
2342   (let ((punct "=<>+-*/|&%!@?"))
2343     (do ((i 0 (1+ i)))
2344         ((>= i (length punct)))
2345       (modify-syntax-entry (aref punct i) ".")))
2346
2347   (modify-syntax-entry ?_ "_")
2348   (modify-syntax-entry ?( "(")
2349   (modify-syntax-entry ?) ")")
2350
2351   (setq indent-tabs-mode nil)
2352
2353   (let ((fsharp-keywords
2354          (mdw-regexps "abstract" "and" "as" "assert" "atomic"
2355                       "begin" "break"
2356                       "checked" "class" "component" "const" "constraint"
2357                       "constructor" "continue"
2358                       "default" "delegate" "do" "done" "downcast" "downto"
2359                       "eager" "elif" "else" "end" "exception" "extern"
2360                       "finally" "fixed" "for" "fori" "fun" "function"
2361                       "functor"
2362                       "global"
2363                       "if" "in" "include" "inherit" "inline" "interface"
2364                       "internal"
2365                       "lazy" "let"
2366                       "match" "measure" "member" "method" "mixin" "module"
2367                       "mutable"
2368                       "namespace" "new"
2369                       "object" "of" "open" "or" "override"
2370                       "parallel" "params" "private" "process" "protected"
2371                       "public" "pure"
2372                       "rec" "recursive" "return"
2373                       "sealed" "sig" "static" "struct"
2374                       "tailcall" "then" "to" "trait" "try" "type"
2375                       "upcast" "use"
2376                       "val" "virtual" "void" "volatile"
2377                       "when" "while" "with"
2378                       "yield"))
2379
2380         (fsharp-builtins
2381          (mdw-regexps "asr" "land" "lor" "lsl" "lsr" "lxor" "mod"
2382                       "base" "false" "null" "true"))
2383
2384         (bang-keywords
2385          (mdw-regexps "do" "let" "return" "use" "yield"))
2386
2387         (preprocessor-keywords
2388          (mdw-regexps "if" "indent" "else" "endif")))
2389
2390     (setq font-lock-keywords
2391           (list (list (concat "\\(^\\|[^\"]\\)"
2392                               "\\(" "(\\*"
2393                                     "[^*]*\\*+"
2394                                     "\\(" "[^)*]" "[^*]*" "\\*+" "\\)*"
2395                                     ")"
2396                               "\\|"
2397                                     "//.*"
2398                               "\\)")
2399                       '(2 font-lock-comment-face))
2400
2401                 (list (concat "'" "\\("
2402                                     "\\\\"
2403                                     "\\(" "[ntbr'\\]"
2404                                     "\\|" "[0-9][0-9][0-9]"
2405                                     "\\|" "u" "[0-9a-fA-F]\\{4\\}"
2406                                     "\\|" "U" "[0-9a-fA-F]\\{8\\}"
2407                                     "\\)"
2408                                   "\\|"
2409                                   "." "\\)" "'"
2410                               "\\|"
2411                               "\"" "[^\"\\]*"
2412                                     "\\(" "\\\\" "\\(.\\|\n\\)"
2413                                           "[^\"\\]*" "\\)*"
2414                               "\\(\"\\|\\'\\)")
2415                       '(0 font-lock-string-face))
2416
2417                 (list (concat "\\_<\\(" bang-keywords "\\)!" "\\|"
2418                               "^#[ \t]*\\(" preprocessor-keywords "\\)\\_>"
2419                               "\\|"
2420                               "\\_<\\(" fsharp-keywords "\\)\\_>")
2421                       '(0 font-lock-keyword-face))
2422                 (list (concat "\\<\\(" fsharp-builtins "\\)\\_>")
2423                       '(0 font-lock-variable-name-face))
2424
2425                 (list (concat "\\_<"
2426                               "\\(" "0[bB][01]+" "\\|"
2427                                     "0[oO][0-7]+" "\\|"
2428                                     "0[xX][0-9a-fA-F]+" "\\)"
2429                               "\\(" "lf\\|LF" "\\|"
2430                                     "[uU]?[ysnlL]?" "\\)"
2431                               "\\|"
2432                               "\\_<"
2433                               "[0-9]+" "\\("
2434                                 "[mMQRZING]"
2435                                 "\\|"
2436                                 "\\(\\.[0-9]*\\)?"
2437                                 "\\([eE][-+]?[0-9]+\\)?"
2438                                 "[fFmM]?"
2439                                 "\\|"
2440                                 "[uU]?[ysnlL]?"
2441                               "\\)")
2442                       '(0 mdw-number-face))
2443
2444                 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2445                       '(0 mdw-punct-face))))))
2446
2447 (defun mdw-fontify-inferior-fsharp ()
2448   (mdw-fontify-fsharp)
2449   (setq font-lock-keywords
2450         (append (list (list "^[#-]" '(0 font-lock-comment-face))
2451                       (list "^>" '(0 font-lock-keyword-face)))
2452                 font-lock-keywords)))
2453
2454 ;;;--------------------------------------------------------------------------
2455 ;;; Go programming configuration.
2456
2457 (defun mdw-fontify-go ()
2458
2459   (make-local-variable 'font-lock-keywords)
2460   (let ((go-keywords
2461          (mdw-regexps "break" "case" "chan" "const" "continue"
2462                       "default" "defer" "else" "fallthrough" "for"
2463                       "func" "go" "goto" "if" "import"
2464                       "interface" "map" "package" "range" "return"
2465                       "select" "struct" "switch" "type" "var"))
2466         (go-intrinsics
2467          (mdw-regexps "bool" "byte" "complex64" "complex128" "error"
2468                       "float32" "float64" "int" "uint8" "int16" "int32"
2469                       "int64" "rune" "string" "uint" "uint8" "uint16"
2470                       "uint32" "uint64" "uintptr" "void"
2471                       "false" "iota" "nil" "true"
2472                       "init" "main"
2473                       "append" "cap" "copy" "delete" "imag" "len" "make"
2474                       "new" "panic" "real" "recover")))
2475
2476     (setq font-lock-keywords
2477           (list
2478
2479            ;; Handle the keywords defined above.
2480            (list (concat "\\<\\(" go-keywords "\\)\\>")
2481                  '(0 font-lock-keyword-face))
2482            (list (concat "\\<\\(" go-intrinsics "\\)\\>")
2483                  '(0 font-lock-variable-name-face))
2484
2485            ;; Strings and characters.
2486            (list (concat "'"
2487                          "\\(" "[^\\']" "\\|"
2488                                "\\\\"
2489                                "\\(" "[abfnrtv\\'\"]" "\\|"
2490                                      "[0-7]\\{3\\}" "\\|"
2491                                      "x" "[0-9A-Fa-f]\\{2\\}" "\\|"
2492                                      "u" "[0-9A-Fa-f]\\{4\\}" "\\|"
2493                                      "U" "[0-9A-Fa-f]\\{8\\}" "\\)" "\\)"
2494                          "'"
2495                          "\\|"
2496                          "\""
2497                          "\\(" "[^\n\\\"]+" "\\|" "\\\\." "\\)*"
2498                          "\\(\"\\|$\\)"
2499                          "\\|"
2500                          "`" "[^`]+" "`")
2501                  '(0 font-lock-string-face))
2502
2503            ;; Handle numbers too.
2504            ;;
2505            ;; The following isn't quite right, but it's close enough.
2506            (list (concat "\\<\\("
2507                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
2508                          "[0-9]+\\(\\.[0-9]*\\|\\)"
2509                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)")
2510                  '(0 mdw-number-face))
2511
2512            ;; And anything else is punctuation.
2513            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2514                  '(0 mdw-punct-face))))))
2515
2516 ;;;--------------------------------------------------------------------------
2517 ;;; Rust programming configuration.
2518
2519 (setq-default rust-indent-offset 2)
2520
2521 (defun mdw-self-insert-and-indent (count)
2522   (interactive "p")
2523   (self-insert-command count)
2524   (indent-according-to-mode))
2525
2526 (defun mdw-fontify-rust ()
2527
2528   ;; Hack syntax categories.
2529   (modify-syntax-entry ?= ".")
2530
2531   ;; Fontify keywords and things.
2532   (make-local-variable 'font-lock-keywords)
2533   (let ((rust-keywords
2534          (mdw-regexps "abstract" "alignof" "as"
2535                       "become" "box" "break"
2536                       "const" "continue" "create"
2537                       "do"
2538                       "else" "enum" "extern"
2539                       "false" "final" "fn" "for"
2540                       "if" "impl" "in"
2541                       "let" "loop"
2542                       "macro" "match" "mod" "move" "mut"
2543                       "offsetof" "override"
2544                       "priv" "pub" "pure"
2545                       "ref" "return"
2546                       "self" "sizeof" "static" "struct" "super"
2547                       "true" "trait" "type" "typeof"
2548                       "unsafe" "unsized" "use"
2549                       "virtual"
2550                       "where" "while"
2551                       "yield"))
2552         (rust-builtins
2553          (mdw-regexps "array" "pointer" "slice" "tuple"
2554                       "bool" "true" "false"
2555                       "f32" "f64"
2556                       "i8" "i16" "i32" "i64" "isize"
2557                       "u8" "u16" "u32" "u64" "usize"
2558                       "char" "str")))
2559     (setq font-lock-keywords
2560           (list
2561
2562            ;; Handle the keywords defined above.
2563            (list (concat "\\_<\\(" rust-keywords "\\)\\_>")
2564                  '(0 font-lock-keyword-face))
2565            (list (concat "\\_<\\(" rust-builtins "\\)\\_>")
2566                  '(0 font-lock-variable-name-face))
2567
2568            ;; Handle numbers too.
2569            (list (concat "\\_<\\("
2570                                "[0-9][0-9_]*"
2571                                "\\(" "\\(\\.[0-9_]+\\)?[eE][-+]?[0-9_]+"
2572                                "\\|" "\\.[0-9_]+"
2573                                "\\)"
2574                                "\\(f32\\|f64\\)?"
2575                          "\\|" "\\(" "[0-9][0-9_]*"
2576                                "\\|" "0x[0-9a-fA-F_]+"
2577                                "\\|" "0o[0-7_]+"
2578                                "\\|" "0b[01_]+"
2579                                "\\)"
2580                                "\\([ui]\\(8\\|16\\|32\\|64\\|s\\|size\\)\\)?"
2581                          "\\)\\_>")
2582                  '(0 mdw-number-face))
2583
2584            ;; And anything else is punctuation.
2585            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2586                  '(0 mdw-punct-face)))))
2587
2588   ;; Hack key bindings.
2589   (local-set-key [?{] 'mdw-self-insert-and-indent)
2590   (local-set-key [?}] 'mdw-self-insert-and-indent))
2591
2592 ;;;--------------------------------------------------------------------------
2593 ;;; Awk programming configuration.
2594
2595 ;; Make Awk indentation nice.
2596
2597 (mdw-define-c-style mdw-awk
2598   (c-basic-offset . 2)
2599   (c-offsets-alist (substatement-open . 0)
2600                    (c-backslash-column . 72)
2601                    (statement-cont . 0)
2602                    (statement-case-intro . +)))
2603 (mdw-set-default-c-style 'awk-mode 'mdw-awk)
2604
2605 ;; Declare Awk fontification style.
2606
2607 (defun mdw-fontify-awk ()
2608
2609   ;; Miscellaneous fiddling.
2610   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
2611
2612   ;; Now define things to be fontified.
2613   (make-local-variable 'font-lock-keywords)
2614   (let ((c-keywords
2615          (mdw-regexps "BEGIN" "END" "ARGC" "ARGIND" "ARGV" "CONVFMT"
2616                       "ENVIRON" "ERRNO" "FIELDWIDTHS" "FILENAME" "FNR"
2617                       "FS" "IGNORECASE" "NF" "NR" "OFMT" "OFS" "ORS" "RS"
2618                       "RSTART" "RLENGTH" "RT"   "SUBSEP"
2619                       "atan2" "break" "close" "continue" "cos" "delete"
2620                       "do" "else" "exit" "exp" "fflush" "file" "for" "func"
2621                       "function" "gensub" "getline" "gsub" "if" "in"
2622                       "index" "int" "length" "log" "match" "next" "rand"
2623                       "return" "print" "printf" "sin" "split" "sprintf"
2624                       "sqrt" "srand" "strftime" "sub" "substr" "system"
2625                       "systime" "tolower" "toupper" "while")))
2626
2627     (setq font-lock-keywords
2628           (list
2629
2630            ;; Handle the keywords defined above.
2631            (list (concat "\\<\\(" c-keywords "\\)\\>")
2632                  '(0 font-lock-keyword-face))
2633
2634            ;; Handle numbers too.
2635            ;;
2636            ;; The following isn't quite right, but it's close enough.
2637            (list (concat "\\<\\("
2638                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
2639                          "[0-9]+\\(\\.[0-9]*\\|\\)"
2640                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
2641                          "[uUlL]*")
2642                  '(0 mdw-number-face))
2643
2644            ;; And anything else is punctuation.
2645            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2646                  '(0 mdw-punct-face))))))
2647
2648 ;;;--------------------------------------------------------------------------
2649 ;;; Perl programming style.
2650
2651 ;; Perl indentation style.
2652
2653 (setq perl-indent-level 2)
2654
2655 (setq cperl-indent-level 2)
2656 (setq cperl-continued-statement-offset 2)
2657 (setq cperl-continued-brace-offset 0)
2658 (setq cperl-brace-offset -2)
2659 (setq cperl-brace-imaginary-offset 0)
2660 (setq cperl-label-offset 0)
2661
2662 ;; Define perl fontification style.
2663
2664 (defun mdw-fontify-perl ()
2665
2666   ;; Miscellaneous fiddling.
2667   (modify-syntax-entry ?$ "\\")
2668   (modify-syntax-entry ?$ "\\" font-lock-syntax-table)
2669   (modify-syntax-entry ?: "." font-lock-syntax-table)
2670   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
2671
2672   ;; Now define fontification things.
2673   (make-local-variable 'font-lock-keywords)
2674   (let ((perl-keywords
2675          (mdw-regexps "and"
2676                       "break"
2677                       "cmp" "continue"
2678                       "default" "do"
2679                       "else" "elsif" "eq"
2680                       "for" "foreach"
2681                       "ge" "given" "gt" "goto"
2682                       "if"
2683                       "last" "le" "local" "lt"
2684                       "my"
2685                       "ne" "next"
2686                       "or" "our"
2687                       "package"
2688                       "redo" "require" "return"
2689                       "sub"
2690                       "undef" "unless" "until" "use"
2691                       "when" "while")))
2692
2693     (setq font-lock-keywords
2694           (list
2695
2696            ;; Set up the keywords defined above.
2697            (list (concat "\\<\\(" perl-keywords "\\)\\>")
2698                  '(0 font-lock-keyword-face))
2699
2700            ;; At least numbers are simpler than C.
2701            (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
2702                          "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
2703                          "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
2704                  '(0 mdw-number-face))
2705
2706            ;; And anything else is punctuation.
2707            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2708                  '(0 mdw-punct-face))))))
2709
2710 (defun perl-number-tests (&optional arg)
2711   "Assign consecutive numbers to lines containing `#t'.  With ARG,
2712 strip numbers instead."
2713   (interactive "P")
2714   (save-excursion
2715     (goto-char (point-min))
2716     (let ((i 0) (fmt (if arg "" " %4d")))
2717       (while (search-forward "#t" nil t)
2718         (delete-region (point) (line-end-position))
2719         (setq i (1+ i))
2720         (insert (format fmt i)))
2721       (goto-char (point-min))
2722       (if (re-search-forward "\\(tests\\s-*=>\\s-*\\)\\w*" nil t)
2723           (replace-match (format "\\1%d" i))))))
2724
2725 ;;;--------------------------------------------------------------------------
2726 ;;; Python programming style.
2727
2728 (defun mdw-fontify-pythonic (keywords)
2729
2730   ;; Miscellaneous fiddling.
2731   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
2732   (setq indent-tabs-mode nil)
2733
2734   ;; Now define fontification things.
2735   (make-local-variable 'font-lock-keywords)
2736   (setq font-lock-keywords
2737         (list
2738
2739          ;; Set up the keywords defined above.
2740          (list (concat "\\_<\\(" keywords "\\)\\_>")
2741                '(0 font-lock-keyword-face))
2742
2743          ;; At least numbers are simpler than C.
2744          (list (concat "\\_<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
2745                        "\\_<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
2746                        "\\([eE]\\([-+]\\|\\)[0-9_]+\\|[lL]\\|\\)")
2747                '(0 mdw-number-face))
2748
2749          ;; And anything else is punctuation.
2750          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2751                '(0 mdw-punct-face)))))
2752
2753 ;; Define Python fontification styles.
2754
2755 (defun mdw-fontify-python ()
2756   (mdw-fontify-pythonic
2757    (mdw-regexps "and" "as" "assert" "break" "class" "continue" "def"
2758                 "del" "elif" "else" "except" "exec" "finally" "for"
2759                 "from" "global" "if" "import" "in" "is" "lambda"
2760                 "not" "or" "pass" "print" "raise" "return" "try"
2761                 "while" "with" "yield")))
2762
2763 (defun mdw-fontify-pyrex ()
2764   (mdw-fontify-pythonic
2765    (mdw-regexps "and" "as" "assert" "break" "cdef" "class" "continue"
2766                 "ctypedef" "def" "del" "elif" "else" "enum" "except" "exec"
2767                 "extern" "finally" "for" "from" "global" "if"
2768                 "import" "in" "is" "lambda" "not" "or" "pass" "print"
2769                 "property" "raise" "return" "struct" "try" "while" "with"
2770                 "yield")))
2771
2772 (define-derived-mode pyrex-mode python-mode "Pyrex"
2773   "Major mode for editing Pyrex source code")
2774 (setq auto-mode-alist
2775       (append '(("\\.pyx$" . pyrex-mode)
2776                 ("\\.pxd$" . pyrex-mode)
2777                 ("\\.pxi$" . pyrex-mode))
2778               auto-mode-alist))
2779
2780 ;;;--------------------------------------------------------------------------
2781 ;;; Lua programming style.
2782
2783 (setq lua-indent-level 2)
2784
2785 (defun mdw-fontify-lua ()
2786
2787   ;; Miscellaneous fiddling.
2788   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
2789
2790   ;; Now define fontification things.
2791   (make-local-variable 'font-lock-keywords)
2792   (let ((lua-keywords
2793          (mdw-regexps "and" "break" "do" "else" "elseif" "end"
2794                       "false" "for" "function" "goto" "if" "in" "local"
2795                       "nil" "not" "or" "repeat" "return" "then" "true"
2796                       "until" "while")))
2797     (setq font-lock-keywords
2798           (list
2799
2800            ;; Set up the keywords defined above.
2801            (list (concat "\\_<\\(" lua-keywords "\\)\\_>")
2802                  '(0 font-lock-keyword-face))
2803
2804            ;; At least numbers are simpler than C.
2805            (list (concat "\\_<\\(" "0[xX]"
2806                                    "\\(" "[0-9a-fA-F]+"
2807                                          "\\(\\.[0-9a-fA-F]*\\)?"
2808                                    "\\|" "\\.[0-9a-fA-F]+"
2809                                    "\\)"
2810                                    "\\([pP][-+]?[0-9]+\\)?"
2811                              "\\|" "\\(" "[0-9]+"
2812                                          "\\(\\.[0-9]*\\)?"
2813                                    "\\|" "\\.[0-9]+"
2814                                    "\\)"
2815                                    "\\([eE][-+]?[0-9]+\\)?"
2816                              "\\)")
2817                  '(0 mdw-number-face))
2818
2819            ;; And anything else is punctuation.
2820            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2821                  '(0 mdw-punct-face))))))
2822
2823 ;;;--------------------------------------------------------------------------
2824 ;;; Icon programming style.
2825
2826 ;; Icon indentation style.
2827
2828 (setq icon-brace-offset 0
2829       icon-continued-brace-offset 0
2830       icon-continued-statement-offset 2
2831       icon-indent-level 2)
2832
2833 ;; Define Icon fontification style.
2834
2835 (defun mdw-fontify-icon ()
2836
2837   ;; Miscellaneous fiddling.
2838   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
2839
2840   ;; Now define fontification things.
2841   (make-local-variable 'font-lock-keywords)
2842   (let ((icon-keywords
2843          (mdw-regexps "break" "by" "case" "create" "default" "do" "else"
2844                       "end" "every" "fail" "global" "if" "initial"
2845                       "invocable" "link" "local" "next" "not" "of"
2846                       "procedure" "record" "repeat" "return" "static"
2847                       "suspend" "then" "to" "until" "while"))
2848         (preprocessor-keywords
2849          (mdw-regexps "define" "else" "endif" "error" "ifdef" "ifndef"
2850                       "include" "line" "undef")))
2851     (setq font-lock-keywords
2852           (list
2853
2854            ;; Set up the keywords defined above.
2855            (list (concat "\\<\\(" icon-keywords "\\)\\>")
2856                  '(0 font-lock-keyword-face))
2857
2858            ;; The things that Icon calls keywords.
2859            (list "&\\sw+\\>" '(0 font-lock-variable-name-face))
2860
2861            ;; At least numbers are simpler than C.
2862            (list (concat "\\<[0-9]+"
2863                          "\\([rR][0-9a-zA-Z]+\\|"
2864                          "\\.[0-9]+\\([eE][+-]?[0-9]+\\)?\\)\\>\\|"
2865                          "\\.[0-9]+\\([eE][+-]?[0-9]+\\)?\\>")
2866                  '(0 mdw-number-face))
2867
2868            ;; Preprocessor.
2869            (list (concat "^[ \t]*$[ \t]*\\<\\("
2870                          preprocessor-keywords
2871                          "\\)\\>")
2872                  '(0 font-lock-keyword-face))
2873
2874            ;; And anything else is punctuation.
2875            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2876                  '(0 mdw-punct-face))))))
2877
2878 ;;;--------------------------------------------------------------------------
2879 ;;; Assembler mode.
2880
2881 (defun mdw-fontify-asm ()
2882   (modify-syntax-entry ?' "\"")
2883   (modify-syntax-entry ?. "w")
2884   (modify-syntax-entry ?\n ">")
2885   (setf fill-prefix nil)
2886   (local-set-key ";" 'self-insert-command)
2887   (mdw-standard-fill-prefix "\\([ \t]*;+[ \t]*\\)"))
2888
2889 (defun mdw-asm-set-comment ()
2890   (modify-syntax-entry ?; "."
2891                        )
2892   (modify-syntax-entry asm-comment-char "<b")
2893   (setq comment-start (string asm-comment-char ? )))
2894 (add-hook 'asm-mode-local-variables-hook 'mdw-asm-set-comment)
2895 (put 'asm-comment-char 'safe-local-variable 'characterp)
2896
2897 ;;;--------------------------------------------------------------------------
2898 ;;; TCL configuration.
2899
2900 (defun mdw-fontify-tcl ()
2901   (mapcar #'(lambda (ch) (modify-syntax-entry ch ".")) '(?$))
2902   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
2903   (make-local-variable 'font-lock-keywords)
2904   (setq font-lock-keywords
2905         (list
2906          (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
2907                        "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
2908                        "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
2909                '(0 mdw-number-face))
2910          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2911                '(0 mdw-punct-face)))))
2912
2913 ;;;--------------------------------------------------------------------------
2914 ;;; Dylan programming configuration.
2915
2916 (defun mdw-fontify-dylan ()
2917
2918   (make-local-variable 'font-lock-keywords)
2919
2920   ;; Horrors.  `dylan-mode' sets the `major-mode' name after calling this
2921   ;; hook, which undoes all of our configuration.
2922   (setq major-mode 'dylan-mode)
2923   (font-lock-set-defaults)
2924
2925   (let* ((word "[-_a-zA-Z!*@<>$%]+")
2926          (dylan-keywords (mdw-regexps
2927
2928                           "C-address" "C-callable-wrapper" "C-function"
2929                           "C-mapped-subtype" "C-pointer-type" "C-struct"
2930                           "C-subtype" "C-union" "C-variable"
2931
2932                           "above" "abstract" "afterwards" "all"
2933                           "begin" "below" "block" "by"
2934                           "case" "class" "cleanup" "constant" "create"
2935                           "define" "domain"
2936                           "else" "elseif" "end" "exception" "export"
2937                           "finally" "for" "from" "function"
2938                           "generic"
2939                           "handler"
2940                           "if" "in" "instance" "interface" "iterate"
2941                           "keyed-by"
2942                           "let" "library" "local"
2943                           "macro" "method" "module"
2944                           "otherwise"
2945                           "profiling"
2946                           "select" "slot" "subclass"
2947                           "table" "then" "to"
2948                           "unless" "until" "use"
2949                           "variable" "virtual"
2950                           "when" "while"))
2951          (sharp-keywords (mdw-regexps
2952                           "all-keys" "key" "next" "rest" "include"
2953                           "t" "f")))
2954     (setq font-lock-keywords
2955           (list (list (concat "\\<\\(" dylan-keywords
2956                               "\\|" "with\\(out\\)?-" word
2957                               "\\)\\>")
2958                       '(0 font-lock-keyword-face))
2959                 (list (concat "\\<" word ":" "\\|"
2960                               "#\\(" sharp-keywords "\\)\\>")
2961                       '(0 font-lock-variable-name-face))
2962                 (list (concat "\\("
2963                               "\\([-+]\\|\\<\\)[0-9]+" "\\("
2964                                 "\\(\\.[0-9]+\\)?" "\\([eE][-+][0-9]+\\)?"
2965                                 "\\|" "/[0-9]+"
2966                               "\\)"
2967                               "\\|" "\\.[0-9]+" "\\([eE][-+][0-9]+\\)?"
2968                               "\\|" "#b[01]+"
2969                               "\\|" "#o[0-7]+"
2970                               "\\|" "#x[0-9a-zA-Z]+"
2971                               "\\)\\>")
2972                       '(0 mdw-number-face))
2973                 (list (concat "\\("
2974                               "\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\|"
2975                               "\\_<[-+*/=<>:&|]+\\_>"
2976                               "\\)")
2977                       '(0 mdw-punct-face))))))
2978
2979 ;;;--------------------------------------------------------------------------
2980 ;;; Algol 68 configuration.
2981
2982 (setq a68-indent-step 2)
2983
2984 (defun mdw-fontify-algol-68 ()
2985
2986   ;; Fix up the syntax table.
2987   (modify-syntax-entry ?# "!" a68-mode-syntax-table)
2988   (dolist (ch '(?- ?+ ?= ?< ?> ?* ?/ ?| ?&))
2989     (modify-syntax-entry ch "." a68-mode-syntax-table))
2990
2991   (make-local-variable 'font-lock-keywords)
2992
2993   (let ((not-comment
2994          (let ((word "COMMENT"))
2995            (do ((regexp (concat "[^" (substring word 0 1) "]+")
2996                         (concat regexp "\\|"
2997                                 (substring word 0 i)
2998                                 "[^" (substring word i (1+ i)) "]"))
2999                 (i 1 (1+ i)))
3000                ((>= i (length word)) regexp)))))
3001     (setq font-lock-keywords
3002           (list (list (concat "\\<COMMENT\\>"
3003                               "\\(" not-comment "\\)\\{0,5\\}"
3004                               "\\(\\'\\|\\<COMMENT\\>\\)")
3005                       '(0 font-lock-comment-face))
3006                 (list (concat "\\<CO\\>"
3007                               "\\([^C]+\\|C[^O]\\)\\{0,5\\}"
3008                               "\\($\\|\\<CO\\>\\)")
3009                       '(0 font-lock-comment-face))
3010                 (list "\\<[A-Z_]+\\>"
3011                       '(0 font-lock-keyword-face))
3012                 (list (concat "\\<"
3013                               "[0-9]+"
3014                               "\\(\\.[0-9]+\\)?"
3015                               "\\([eE][-+]?[0-9]+\\)?"
3016                               "\\>")
3017                       '(0 mdw-number-face))
3018                 (list "\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/"
3019                       '(0 mdw-punct-face))))))
3020
3021 ;;;--------------------------------------------------------------------------
3022 ;;; REXX configuration.
3023
3024 (defun mdw-rexx-electric-* ()
3025   (interactive)
3026   (insert ?*)
3027   (rexx-indent-line))
3028
3029 (defun mdw-rexx-indent-newline-indent ()
3030   (interactive)
3031   (rexx-indent-line)
3032   (if abbrev-mode (expand-abbrev))
3033   (newline-and-indent))
3034
3035 (defun mdw-fontify-rexx ()
3036
3037   ;; Various bits of fiddling.
3038   (setq mdw-auto-indent nil)
3039   (local-set-key [?\C-m] 'mdw-rexx-indent-newline-indent)
3040   (local-set-key [?*] 'mdw-rexx-electric-*)
3041   (mapcar #'(lambda (ch) (modify-syntax-entry ch "w"))
3042           '(?! ?? ?# ?@ ?$))
3043   (mdw-standard-fill-prefix "\\([ \t]*/?\*[ \t]*\\)")
3044
3045   ;; Set up keywords and things for fontification.
3046   (make-local-variable 'font-lock-keywords-case-fold-search)
3047   (setq font-lock-keywords-case-fold-search t)
3048
3049   (setq rexx-indent 2)
3050   (setq rexx-end-indent rexx-indent)
3051   (setq rexx-cont-indent rexx-indent)
3052
3053   (make-local-variable 'font-lock-keywords)
3054   (let ((rexx-keywords
3055          (mdw-regexps "address" "arg" "by" "call" "digits" "do" "drop"
3056                       "else" "end" "engineering" "exit" "expose" "for"
3057                       "forever" "form" "fuzz" "if" "interpret" "iterate"
3058                       "leave" "linein" "name" "nop" "numeric" "off" "on"
3059                       "options" "otherwise" "parse" "procedure" "pull"
3060                       "push" "queue" "return" "say" "select" "signal"
3061                       "scientific" "source" "then" "trace" "to" "until"
3062                       "upper" "value" "var" "version" "when" "while"
3063                       "with"
3064
3065                       "abbrev" "abs" "bitand" "bitor" "bitxor" "b2x"
3066                       "center" "center" "charin" "charout" "chars"
3067                       "compare" "condition" "copies" "c2d" "c2x"
3068                       "datatype" "date" "delstr" "delword" "d2c" "d2x"
3069                       "errortext" "format" "fuzz" "insert" "lastpos"
3070                       "left" "length" "lineout" "lines" "max" "min"
3071                       "overlay" "pos" "queued" "random" "reverse" "right"
3072                       "sign" "sourceline" "space" "stream" "strip"
3073                       "substr" "subword" "symbol" "time" "translate"
3074                       "trunc" "value" "verify" "word" "wordindex"
3075                       "wordlength" "wordpos" "words" "xrange" "x2b" "x2c"
3076                       "x2d")))
3077
3078     (setq font-lock-keywords
3079           (list
3080
3081            ;; Set up the keywords defined above.
3082            (list (concat "\\<\\(" rexx-keywords "\\)\\>")
3083                  '(0 font-lock-keyword-face))
3084
3085            ;; Fontify all symbols the same way.
3086            (list (concat "\\<\\([0-9.][A-Za-z0-9.!?_#@$]*[Ee][+-]?[0-9]+\\|"
3087                          "[A-Za-z0-9.!?_#@$]+\\)")
3088                  '(0 font-lock-variable-name-face))
3089
3090            ;; And everything else is punctuation.
3091            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
3092                  '(0 mdw-punct-face))))))
3093
3094 ;;;--------------------------------------------------------------------------
3095 ;;; Standard ML programming style.
3096
3097 (defun mdw-fontify-sml ()
3098
3099   ;; Make underscore an honorary letter.
3100   (modify-syntax-entry ?' "w")
3101
3102   ;; Set fill prefix.
3103   (mdw-standard-fill-prefix "\\([ \t]*(\*[ \t]*\\)")
3104
3105   ;; Now define fontification things.
3106   (make-local-variable 'font-lock-keywords)
3107   (let ((sml-keywords
3108          (mdw-regexps "abstype" "and" "andalso" "as"
3109                       "case"
3110                       "datatype" "do"
3111                       "else" "end" "eqtype" "exception"
3112                       "fn" "fun" "functor"
3113                       "handle"
3114                       "if" "in" "include" "infix" "infixr"
3115                       "let" "local"
3116                       "nonfix"
3117                       "of" "op" "open" "orelse"
3118                       "raise" "rec"
3119                       "sharing" "sig" "signature" "struct" "structure"
3120                       "then" "type"
3121                       "val"
3122                       "where" "while" "with" "withtype")))
3123
3124     (setq font-lock-keywords
3125           (list
3126
3127            ;; Set up the keywords defined above.
3128            (list (concat "\\<\\(" sml-keywords "\\)\\>")
3129                  '(0 font-lock-keyword-face))
3130
3131            ;; At least numbers are simpler than C.
3132            (list (concat "\\<\\(\\~\\|\\)"
3133                             "\\(0\\(\\([wW]\\|\\)[xX][0-9a-fA-F]+\\|"
3134                                    "[wW][0-9]+\\)\\|"
3135                                 "\\([0-9]+\\(\\.[0-9]+\\|\\)"
3136                                          "\\([eE]\\(\\~\\|\\)"
3137                                                 "[0-9]+\\|\\)\\)\\)")
3138                  '(0 mdw-number-face))
3139
3140            ;; And anything else is punctuation.
3141            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
3142                  '(0 mdw-punct-face))))))
3143
3144 ;;;--------------------------------------------------------------------------
3145 ;;; Haskell configuration.
3146
3147 (defun mdw-fontify-haskell ()
3148
3149   ;; Fiddle with syntax table to get comments right.
3150   (modify-syntax-entry ?' "_")
3151   (modify-syntax-entry ?- ". 12")
3152   (modify-syntax-entry ?\n ">")
3153
3154   ;; Make punctuation be punctuation
3155   (let ((punct "=<>+-*/|&%!@?$.^:#`"))
3156     (do ((i 0 (1+ i)))
3157         ((>= i (length punct)))
3158       (modify-syntax-entry (aref punct i) ".")))
3159
3160   ;; Set fill prefix.
3161   (mdw-standard-fill-prefix "\\([ \t]*{?--?[ \t]*\\)")
3162
3163   ;; Fiddle with fontification.
3164   (make-local-variable 'font-lock-keywords)
3165   (let ((haskell-keywords
3166          (mdw-regexps "as"
3167                       "case" "ccall" "class"
3168                       "data" "default" "deriving" "do"
3169                       "else" "exists"
3170                       "forall" "foreign"
3171                       "hiding"
3172                       "if" "import" "in" "infix" "infixl" "infixr" "instance"
3173                       "let"
3174                       "mdo" "module"
3175                       "newtype"
3176                       "of"
3177                       "proc"
3178                       "qualified"
3179                       "rec"
3180                       "safe" "stdcall"
3181                       "then" "type"
3182                       "unsafe"
3183                       "where"))
3184         (control-sequences
3185          (mdw-regexps "ACK" "BEL" "BS" "CAN" "CR" "DC1" "DC2" "DC3" "DC4"
3186                       "DEL" "DLE" "EM" "ENQ" "EOT" "ESC" "ETB" "ETX" "FF"
3187                       "FS" "GS" "HT" "LF" "NAK" "NUL" "RS" "SI" "SO" "SOH"
3188                       "SP" "STX" "SUB" "SYN" "US" "VT")))
3189
3190     (setq font-lock-keywords
3191           (list
3192            (list (concat "{-" "[^-]*" "\\(-+[^-}][^-]*\\)*"
3193                               "\\(-+}\\|-*\\'\\)"
3194                          "\\|"
3195                          "--.*$")
3196                  '(0 font-lock-comment-face))
3197            (list (concat "\\_<\\(" haskell-keywords "\\)\\_>")
3198                  '(0 font-lock-keyword-face))
3199            (list (concat "'\\("
3200                          "[^\\]"
3201                          "\\|"
3202                          "\\\\"
3203                          "\\(" "[abfnrtv\\\"']" "\\|"
3204                                "^" "\\(" control-sequences "\\|"
3205                                          "[]A-Z@[\\^_]" "\\)" "\\|"
3206                                "\\|"
3207                                "[0-9]+" "\\|"
3208                                "[oO][0-7]+" "\\|"
3209                                "[xX][0-9A-Fa-f]+"
3210                          "\\)"
3211                          "\\)'")
3212                  '(0 font-lock-string-face))
3213            (list "\\_<[A-Z]\\(\\sw+\\|\\s_+\\)*\\_>"
3214                  '(0 font-lock-variable-name-face))
3215            (list (concat "\\_<0\\([xX][0-9a-fA-F]+\\|[oO][0-7]+\\)\\|"
3216                          "\\_<[0-9]+\\(\\.[0-9]*\\|\\)"
3217                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)")
3218                  '(0 mdw-number-face))
3219            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
3220                  '(0 mdw-punct-face))))))
3221
3222 ;;;--------------------------------------------------------------------------
3223 ;;; Erlang configuration.
3224
3225 (setq erlang-electric-commands nil)
3226
3227 (defun mdw-fontify-erlang ()
3228
3229   ;; Set fill prefix.
3230   (mdw-standard-fill-prefix "\\([ \t]*{?%*[ \t]*\\)")
3231
3232   ;; Fiddle with fontification.
3233   (make-local-variable 'font-lock-keywords)
3234   (let ((erlang-keywords
3235          (mdw-regexps "after" "and" "andalso"
3236                       "band" "begin" "bnot" "bor" "bsl" "bsr" "bxor"
3237                       "case" "catch" "cond"
3238                       "div" "end" "fun" "if" "let" "not"
3239                       "of" "or" "orelse"
3240                       "query" "receive" "rem" "try" "when" "xor")))
3241
3242     (setq font-lock-keywords
3243           (list
3244            (list "%.*$"
3245                  '(0 font-lock-comment-face))
3246            (list (concat "\\<\\(" erlang-keywords "\\)\\>")
3247                  '(0 font-lock-keyword-face))
3248            (list (concat "^-\\sw+\\>")
3249                  '(0 font-lock-keyword-face))
3250            (list "\\<[0-9]+\\(\\|#[0-9a-zA-Z]+\\|[eE][+-]?[0-9]+\\)\\>"
3251                  '(0 mdw-number-face))
3252            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
3253                  '(0 mdw-punct-face))))))
3254
3255 ;;;--------------------------------------------------------------------------
3256 ;;; Texinfo configuration.
3257
3258 (defun mdw-fontify-texinfo ()
3259
3260   ;; Set fill prefix.
3261   (mdw-standard-fill-prefix "\\([ \t]*@c[ \t]+\\)")
3262
3263   ;; Real fontification things.
3264   (make-local-variable 'font-lock-keywords)
3265   (setq font-lock-keywords
3266         (list
3267
3268          ;; Environment names are keywords.
3269          (list "@\\(end\\)  *\\([a-zA-Z]*\\)?"
3270                '(2 font-lock-keyword-face))
3271
3272          ;; Unmark escaped magic characters.
3273          (list "\\(@\\)\\([@{}]\\)"
3274                '(1 font-lock-keyword-face)
3275                '(2 font-lock-variable-name-face))
3276
3277          ;; Make sure we get comments properly.
3278          (list "@c\\(\\|omment\\)\\( .*\\)?$"
3279                '(0 font-lock-comment-face))
3280
3281          ;; Command names are keywords.
3282          (list "@\\([^a-zA-Z@]\\|[a-zA-Z@]*\\)"
3283                '(0 font-lock-keyword-face))
3284
3285          ;; Fontify TeX special characters as punctuation.
3286          (list "[{}]+"
3287                '(0 mdw-punct-face)))))
3288
3289 ;;;--------------------------------------------------------------------------
3290 ;;; TeX and LaTeX configuration.
3291
3292 (defun mdw-fontify-tex ()
3293   (setq ispell-parser 'tex)
3294   (turn-on-reftex)
3295
3296   ;; Don't make maths into a string.
3297   (modify-syntax-entry ?$ ".")
3298   (modify-syntax-entry ?$ "." font-lock-syntax-table)
3299   (local-set-key [?$] 'self-insert-command)
3300
3301   ;; Make `tab' be useful, given that tab stops in TeX don't work well.
3302   (local-set-key "\C-\M-i" 'indent-relative)
3303   (setq indent-tabs-mode nil)
3304
3305   ;; Set fill prefix.
3306   (mdw-standard-fill-prefix "\\([ \t]*%+[ \t]*\\)")
3307
3308   ;; Real fontification things.
3309   (make-local-variable 'font-lock-keywords)
3310   (setq font-lock-keywords
3311         (list
3312
3313          ;; Environment names are keywords.
3314          (list (concat "\\\\\\(begin\\|end\\|newenvironment\\)"
3315                        "{\\([^}\n]*\\)}")
3316                '(2 font-lock-keyword-face))
3317
3318          ;; Suspended environment names are keywords too.
3319          (list (concat "\\\\\\(suspend\\|resume\\)\\(\\[[^]]*\\]\\)?"
3320                        "{\\([^}\n]*\\)}")
3321                '(3 font-lock-keyword-face))
3322
3323          ;; Command names are keywords.
3324          (list "\\\\\\([^a-zA-Z@]\\|[a-zA-Z@]*\\)"
3325                '(0 font-lock-keyword-face))
3326
3327          ;; Handle @/.../ for italics.
3328          ;; (list "\\(@/\\)\\([^/]*\\)\\(/\\)"
3329          ;;       '(1 font-lock-keyword-face)
3330          ;;       '(3 font-lock-keyword-face))
3331
3332          ;; Handle @*...* for boldness.
3333          ;; (list "\\(@\\*\\)\\([^*]*\\)\\(\\*\\)"
3334          ;;       '(1 font-lock-keyword-face)
3335          ;;       '(3 font-lock-keyword-face))
3336
3337          ;; Handle @`...' for literal syntax things.
3338          ;; (list "\\(@`\\)\\([^']*\\)\\('\\)"
3339          ;;       '(1 font-lock-keyword-face)
3340          ;;       '(3 font-lock-keyword-face))
3341
3342          ;; Handle @<...> for nonterminals.
3343          ;; (list "\\(@<\\)\\([^>]*\\)\\(>\\)"
3344          ;;       '(1 font-lock-keyword-face)
3345          ;;       '(3 font-lock-keyword-face))
3346
3347          ;; Handle other @-commands.
3348          ;; (list "@\\([^a-zA-Z]\\|[a-zA-Z]*\\)"
3349          ;;       '(0 font-lock-keyword-face))
3350
3351          ;; Make sure we get comments properly.
3352          (list "%.*"
3353                '(0 font-lock-comment-face))
3354
3355          ;; Fontify TeX special characters as punctuation.
3356          (list "[$^_{}#&]"
3357                '(0 mdw-punct-face)))))
3358
3359 (eval-after-load 'font-latex
3360   '(defun font-latex-jit-lock-force-redisplay (buf start end)
3361      "Compatibility for Emacsen not offering `jit-lock-force-redisplay'."
3362      ;; The following block is an expansion of `jit-lock-force-redisplay'
3363      ;; and involved macros taken from CVS Emacs on 2007-04-28.
3364      (with-current-buffer buf
3365        (let ((modified (buffer-modified-p)))
3366          (unwind-protect
3367              (let ((buffer-undo-list t)
3368                    (inhibit-read-only t)
3369                    (inhibit-point-motion-hooks t)
3370                    (inhibit-modification-hooks t)
3371                    deactivate-mark
3372                    buffer-file-name
3373                    buffer-file-truename)
3374                (put-text-property start end 'fontified t))
3375            (unless modified
3376              (restore-buffer-modified-p nil)))))))
3377
3378 (setq LaTeX-syntactic-comments nil
3379       LaTeX-fill-break-at-separators '(\\\[))
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)