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