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