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