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