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