chiark / gitweb /
el/dot-emacs.el: Fix the eshell prompt algorithm.
[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 ;; Some error trapping.
56 ;;
57 ;; If individual bits of this file go tits-up, we don't particularly want
58 ;; the whole lot to stop right there and then, because it's bloody annoying.
59
60 (defmacro trap (&rest forms)
61   "Execute FORMS without allowing errors to propagate outside."
62   (declare (indent 0)
63            (debug t))
64   `(condition-case err
65        ,(if (cdr forms) (cons 'progn forms) (car forms))
66      (error (message "Error (trapped): %s in %s"
67                      (error-message-string err)
68                      ',forms))))
69
70 ;; Configuration reading.
71
72 (defvar mdw-config nil)
73 (defun mdw-config (sym)
74   "Read the configuration variable named SYM."
75   (unless mdw-config
76     (setq mdw-config
77           (flet ((replace (what with)
78                    (goto-char (point-min))
79                    (while (re-search-forward what nil t)
80                      (replace-match with t))))
81             (with-temp-buffer
82               (insert-file-contents "~/.mdw.conf")
83               (replace  "^[ \t]*\\(#.*\\|\\)\n" "")
84               (replace (concat "^[ \t]*"
85                                "\\([-a-zA-Z0-9_.]*\\)"
86                                "[ \t]*=[ \t]*"
87                                "\\(.*[^ \t\n]\\|\\)"
88                                "[ \t]**\\(\n\\|$\\)")
89                        "(\\1 . \"\\2\")\n")
90               (car (read-from-string
91                     (concat "(" (buffer-string) ")")))))))
92   (cdr (assq sym mdw-config)))
93
94 ;; Set up the load path convincingly.
95
96 (dolist (dir (append (and (boundp 'debian-emacs-flavor)
97                           (list (concat "/usr/share/"
98                                         (symbol-name debian-emacs-flavor)
99                                         "/site-lisp")))))
100   (dolist (sub (directory-files dir t))
101     (when (and (file-accessible-directory-p sub)
102                (not (member sub load-path)))
103       (setq load-path (nconc load-path (list sub))))))
104
105 ;; Is an Emacs library available?
106
107 (defun library-exists-p (name)
108   "Return non-nil if NAME is an available library.
109 Return non-nil if NAME.el (or NAME.elc) somewhere on the Emacs
110 load path.  The non-nil value is the filename we found for the
111 library."
112   (let ((path load-path) elt (foundp nil))
113     (while (and path (not foundp))
114       (setq elt (car path))
115       (setq path (cdr path))
116       (setq foundp (or (let ((file (concat elt "/" name ".elc")))
117                          (and (file-exists-p file) file))
118                        (let ((file (concat elt "/" name ".el")))
119                          (and (file-exists-p file) file)))))
120     foundp))
121
122 (defun maybe-autoload (symbol file &optional docstring interactivep type)
123   "Set an autoload if the file actually exists."
124   (and (library-exists-p file)
125        (autoload symbol file docstring interactivep type)))
126
127 ;; Splitting windows.
128
129 (unless (fboundp 'scroll-bar-columns)
130   (defun scroll-bar-columns (side)
131     (cond ((eq side 'left) 0)
132           (window-system 3)
133           (t 1))))
134 (unless (fboundp 'fringe-columns)
135   (defun fringe-columns (side)
136     (cond ((not window-system) 0)
137           ((eq side 'left) 1)
138           (t 2))))
139
140 (defun mdw-horizontal-window-overhead ()
141   "Computes the horizontal window overhead.
142 This is the number of columns used by fringes, scroll bars and other such
143 cruft."
144   (if (not window-system)
145       1
146     (let ((tot 0))
147       (dolist (what '(scroll-bar fringe))
148         (dolist (side '(left right))
149           (incf tot (funcall (intern (concat (symbol-name what) "-columns"))
150                              side))))
151       tot)))
152
153 (defun mdw-split-window-horizontally (&optional width)
154   "Split a window horizontally.
155 Without a numeric argument, split the window approximately in
156 half.  With a numeric argument WIDTH, allocate WIDTH columns to
157 the left-hand window (if positive) or -WIDTH columns to the
158 right-hand window (if negative).  Space for scroll bars and
159 fringes is not taken out of the allowance for WIDTH, unlike
160 \\[split-window-horizontally]."
161   (interactive "P")
162   (split-window-horizontally
163    (cond ((null width) nil)
164          ((>= width 0) (+ width (mdw-horizontal-window-overhead)))
165          ((< width 0) width))))
166
167 (defun mdw-divvy-window (&optional width)
168   "Split a wide window into appropriate widths."
169   (interactive "P")
170   (setq width (cond (width (prefix-numeric-value width))
171                     ((and window-system
172                           (>= emacs-major-version 22))
173                      77)
174                     (t 78)))
175   (let* ((win (selected-window))
176          (sb-width (mdw-horizontal-window-overhead))
177          (c (/ (+ (window-width) sb-width)
178                (+ width sb-width))))
179     (while (> c 1)
180       (setq c (1- c))
181       (split-window-horizontally (+ width sb-width))
182       (other-window 1))
183     (select-window win)))
184
185 ;; Transient mark mode hacks.
186
187 (defadvice exchange-point-and-mark
188     (around mdw-highlight (&optional arg) activate compile)
189   "Maybe don't actually exchange point and mark.
190 If `transient-mark-mode' is on and the mark is inactive, then
191 just activate it.  A non-trivial prefix argument will force the
192 usual behaviour.  A trivial prefix argument (i.e., just C-u) will
193 activate the mark and temporarily enable `transient-mark-mode' if
194 it's currently off."
195   (cond ((or mark-active
196              (and (not transient-mark-mode) (not arg))
197              (and arg (or (not (consp arg))
198                           (not (= (car arg) 4)))))
199          ad-do-it)
200         (t
201          (or transient-mark-mode (setq transient-mark-mode 'only))
202          (set-mark (mark t)))))
203
204 ;; Functions for sexp diary entries.
205
206 (defun mdw-weekday (l)
207   "Return non-nil if `date' falls on one of the days of the week in L.
208 L is a list of day numbers (from 0 to 6 for Sunday through to
209 Saturday) or symbols `sunday', `monday', etc. (or a mixture).  If
210 the date stored in `date' falls on a listed day, then the
211 function returns non-nil."
212   (let ((d (calendar-day-of-week date)))
213     (or (memq d l)
214         (memq (nth d '(sunday monday tuesday wednesday
215                               thursday friday saturday)) l))))
216
217 (defun mdw-todo (&optional when)
218   "Return non-nil today, or on WHEN, whichever is later."
219   (let ((w (calendar-absolute-from-gregorian (calendar-current-date)))
220         (d (calendar-absolute-from-gregorian date)))
221     (if when
222         (setq w (max w (calendar-absolute-from-gregorian
223                         (cond
224                          ((not european-calendar-style)
225                           when)
226                          ((> (car when) 100)
227                           (list (nth 1 when)
228                                 (nth 2 when)
229                                 (nth 0 when)))
230                          (t
231                           (list (nth 1 when)
232                                 (nth 0 when)
233                                 (nth 2 when))))))))
234     (eq w d)))
235
236 ;; Fighting with Org-mode's evil key maps.
237
238 (defvar mdw-evil-keymap-keys
239   '(([S-up] . [?\C-c up])
240     ([S-down] . [?\C-c down])
241     ([S-left] . [?\C-c left])
242     ([S-right] . [?\C-c right])
243     (([M-up] [?\e up]) . [C-up])
244     (([M-down] [?\e down]) . [C-down])
245     (([M-left] [?\e left]) . [C-left])
246     (([M-right] [?\e right]) . [C-right]))
247   "Defines evil keybindings to clobber in `mdw-clobber-evil-keymap'.
248 The value is an alist mapping evil keys (as a list, or singleton)
249 to good keys (in the same form).")
250
251 (defun mdw-clobber-evil-keymap (keymap)
252   "Replace evil key bindings in the KEYMAP.
253 Evil key bindings are defined in `mdw-evil-keymap-keys'."
254   (dolist (entry mdw-evil-keymap-keys)
255     (let ((binding nil)
256           (keys (if (listp (car entry))
257                     (car entry)
258                   (list (car entry))))
259           (replacements (if (listp (cdr entry))
260                             (cdr entry)
261                           (list (cdr entry)))))
262       (catch 'found
263         (dolist (key keys)
264           (setq binding (lookup-key keymap key))
265           (when binding
266             (throw 'found nil))))
267       (when binding
268         (dolist (key keys)
269           (define-key keymap key nil))
270         (dolist (key replacements)
271           (define-key keymap key binding))))))
272
273 (eval-after-load "org-latex"
274   '(progn
275      (push '("strayman"
276              "\\documentclass{strayman}
277 \\usepackage[utf8]{inputenc}
278 \\usepackage[palatino, helvetica, courier, maths=cmr]{mdwfonts}
279 \\usepackage[T1]{fontenc}
280 \\usepackage{graphicx, tikz, mdwtab, mdwmath, crypto, longtable}"
281              ("\\section{%s}" . "\\section*{%s}")
282              ("\\subsection{%s}" . "\\subsection*{%s}")
283              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
284              ("\\paragraph{%s}" . "\\paragraph*{%s}")
285              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
286            org-export-latex-classes)))
287
288 ;;;--------------------------------------------------------------------------
289 ;;; Mail and news hacking.
290
291 (define-derived-mode  mdwmail-mode mail-mode "[mdw] mail"
292   "Major mode for editing news and mail messages from external programs.
293 Not much right now.  Just support for doing MailCrypt stuff."
294   :syntax-table nil
295   :abbrev-table nil
296   (run-hooks 'mail-setup-hook))
297
298 (define-key mdwmail-mode-map [?\C-c ?\C-c] 'disabled-operation)
299
300 (add-hook 'mdwail-mode-hook
301           (lambda ()
302             (set-buffer-file-coding-system 'utf-8)
303             (make-local-variable 'paragraph-separate)
304             (make-local-variable 'paragraph-start)
305             (setq paragraph-start
306                   (concat "[ \t]*[-_][-_][-_]+$\\|^-- \\|-----\\|"
307                           paragraph-start))
308             (setq paragraph-separate
309                   (concat "[ \t]*[-_][-_][-_]+$\\|^-- \\|-----\\|"
310                           paragraph-separate))))
311
312 ;; How to encrypt in mdwmail.
313
314 (defun mdwmail-mc-encrypt (&optional recip scm start end from sign)
315   (or start
316       (setq start (save-excursion
317                     (goto-char (point-min))
318                     (or (search-forward "\n\n" nil t) (point-min)))))
319   (or end
320       (setq end (point-max)))
321   (mc-encrypt-generic recip scm start end from sign))
322
323 ;; How to sign in mdwmail.
324
325 (defun mdwmail-mc-sign (key scm start end uclr)
326   (or start
327       (setq start (save-excursion
328                     (goto-char (point-min))
329                     (or (search-forward "\n\n" nil t) (point-min)))))
330   (or end
331       (setq end (point-max)))
332   (mc-sign-generic key scm start end uclr))
333
334 ;; Some signature mangling.
335
336 (defun mdwmail-mangle-signature ()
337   (save-excursion
338     (goto-char (point-min))
339     (perform-replace "\n-- \n" "\n-- " nil nil nil)))
340 (add-hook 'mail-setup-hook 'mdwmail-mangle-signature)
341 (add-hook 'message-setup-hook 'mdwmail-mangle-signature)
342
343 ;; Insert my login name into message-ids, so I can score replies.
344
345 (defadvice message-unique-id (after mdw-user-name last activate compile)
346   "Ensure that the user's name appears at the end of the message-id string,
347 so that it can be used for convenient filtering."
348   (setq ad-return-value (concat ad-return-value "." (user-login-name))))
349
350 ;; Tell my movemail hack where movemail is.
351 ;;
352 ;; This is needed to shup up warnings about LD_PRELOAD.
353
354 (let ((path exec-path))
355   (while path
356     (let ((try (expand-file-name "movemail" (car path))))
357       (if (file-executable-p try)
358           (setenv "REAL_MOVEMAIL" try))
359       (setq path (cdr path)))))
360
361 ;;;--------------------------------------------------------------------------
362 ;;; Utility functions.
363
364 (or (fboundp 'line-number-at-pos)
365     (defun line-number-at-pos (&optional pos)
366       (let ((opoint (or pos (point))) start)
367         (save-excursion
368           (save-restriction
369             (goto-char (point-min))
370             (widen)
371             (forward-line 0)
372             (setq start (point))
373             (goto-char opoint)
374             (forward-line 0)
375             (1+ (count-lines 1 (point))))))))
376
377 (defun mdw-uniquify-alist (&rest alists)
378   "Return the concatenation of the ALISTS with duplicate elements removed.
379 The first association with a given key prevails; others are
380 ignored.  The input lists are not modified, although they'll
381 probably become garbage."
382   (and alists
383        (let ((start-list (cons nil nil)))
384          (mdw-do-uniquify start-list
385                           start-list
386                           (car alists)
387                           (cdr alists)))))
388
389 (defun mdw-do-uniquify (done end l rest)
390   "A helper function for mdw-uniquify-alist.
391 The DONE argument is a list whose first element is `nil'.  It
392 contains the uniquified alist built so far.  The leading `nil' is
393 stripped off at the end of the operation; it's only there so that
394 DONE always references a cons cell.  END refers to the final cons
395 cell in the DONE list; it is modified in place each time to avoid
396 the overheads of `append'ing all the time.  The L argument is the
397 alist we're currently processing; the remaining alists are given
398 in REST."
399
400   ;; There are several different cases to deal with here.
401   (cond
402
403    ;; Current list isn't empty.  Add the first item to the DONE list if
404    ;; there's not an item with the same KEY already there.
405    (l (or (assoc (car (car l)) done)
406           (progn
407             (setcdr end (cons (car l) nil))
408             (setq end (cdr end))))
409       (mdw-do-uniquify done end (cdr l) rest))
410
411    ;; The list we were working on is empty.  Shunt the next list into the
412    ;; current list position and go round again.
413    (rest (mdw-do-uniquify done end (car rest) (cdr rest)))
414
415    ;; Everything's done.  Remove the leading `nil' from the DONE list and
416    ;; return it.  Finished!
417    (t (cdr done))))
418
419 (defun date ()
420   "Insert the current date in a pleasing way."
421   (interactive)
422   (insert (save-excursion
423             (let ((buffer (get-buffer-create "*tmp*")))
424               (unwind-protect (progn (set-buffer buffer)
425                                      (erase-buffer)
426                                      (shell-command "date +%Y-%m-%d" t)
427                                      (goto-char (mark))
428                                      (delete-backward-char 1)
429                                      (buffer-string))
430                 (kill-buffer buffer))))))
431
432 (defun uuencode (file &optional name)
433   "UUencodes a file, maybe calling it NAME, into the current buffer."
434   (interactive "fInput file name: ")
435
436   ;; If NAME isn't specified, then guess from the filename.
437   (if (not name)
438       (setq name
439             (substring file
440                        (or (string-match "[^/]*$" file) 0))))
441   (print (format "uuencode `%s' `%s'" file name))
442
443   ;; Now actually do the thing.
444   (call-process "uuencode" file t nil name))
445
446 (defvar np-file "~/.np"
447   "*Where the `now-playing' file is.")
448
449 (defun np (&optional arg)
450   "Grabs a `now-playing' string."
451   (interactive)
452   (save-excursion
453     (or arg (progn
454               (goto-char (point-max))
455               (insert "\nNP: ")
456               (insert-file-contents np-file)))))
457
458 (defun mdw-version-< (ver-a ver-b)
459   "Answer whether VER-A is strictly earlier than VER-B.
460 VER-A and VER-B are version numbers, which are strings containing digit
461 sequences separated by `.'."
462   (let* ((la (mapcar (lambda (x) (car (read-from-string x)))
463                      (split-string ver-a "\\.")))
464          (lb (mapcar (lambda (x) (car (read-from-string x)))
465                      (split-string ver-b "\\."))))
466     (catch 'done
467       (while t
468         (cond ((null la) (throw 'done lb))
469               ((null lb) (throw 'done nil))
470               ((< (car la) (car lb)) (throw 'done t))
471               ((= (car la) (car lb)) (setq la (cdr la) lb (cdr lb))))))))
472
473 (defun mdw-check-autorevert ()
474   "Sets global-auto-revert-ignore-buffer appropriately for this buffer.
475 This takes into consideration whether it's been found using
476 tramp, which seems to get itself into a twist."
477   (cond ((not (boundp 'global-auto-revert-ignore-buffer))
478          nil)
479         ((and (buffer-file-name)
480               (fboundp 'tramp-tramp-file-p)
481               (tramp-tramp-file-p (buffer-file-name)))
482          (unless global-auto-revert-ignore-buffer
483            (setq global-auto-revert-ignore-buffer 'tramp)))
484         ((eq global-auto-revert-ignore-buffer 'tramp)
485          (setq global-auto-revert-ignore-buffer nil))))
486
487 (defadvice find-file (after mdw-autorevert activate)
488   (mdw-check-autorevert))
489 (defadvice write-file (after mdw-autorevert activate)
490   (mdw-check-autorevert))
491
492 ;;;--------------------------------------------------------------------------
493 ;;; Dired hacking.
494
495 (defadvice dired-maybe-insert-subdir
496     (around mdw-marked-insertion first activate)
497   "The DIRNAME may be a list of directory names to insert.
498 Interactively, if files are marked, then insert all of them.
499 With a numeric prefix argument, select that many entries near
500 point; with a non-numeric prefix argument, prompt for listing
501 options."
502   (interactive
503    (list (dired-get-marked-files nil
504                                  (and (integerp current-prefix-arg)
505                                       current-prefix-arg)
506                                  #'file-directory-p)
507          (and current-prefix-arg
508               (not (integerp current-prefix-arg))
509               (read-string "Switches for listing: "
510                            (or dired-subdir-switches
511                                dired-actual-switches)))))
512   (let ((dirs (ad-get-arg 0)))
513     (dolist (dir (if (listp dirs) dirs (list dirs)))
514       (ad-set-arg 0 dir)
515       ad-do-it)))
516
517 ;;;--------------------------------------------------------------------------
518 ;;; URL viewing.
519
520 (defun mdw-w3m-browse-url (url &optional new-session-p)
521   "Invoke w3m on the URL in its current window, or at least a different one.
522 If NEW-SESSION-P, start a new session."
523   (interactive "sURL: \nP")
524   (save-excursion
525     (let ((window (selected-window)))
526       (unwind-protect
527           (progn
528             (select-window (or (and (not new-session-p)
529                                     (get-buffer-window "*w3m*"))
530                                (progn
531                                  (if (one-window-p t) (split-window))
532                                  (get-lru-window))))
533             (w3m-browse-url url new-session-p))
534         (select-window window)))))
535
536 (defvar mdw-good-url-browsers
537   '(browse-url-generic
538     (w3m . mdw-w3m-browse-url)
539     browse-url-w3
540     browse-url-mozilla)
541   "List of good browsers for mdw-good-url-browsers.
542 Each item is a browser function name, or a cons (CHECK . FUNC).
543 A symbol FOO stands for (FOO . FOO).")
544
545 (defun mdw-good-url-browser ()
546   "Return a good URL browser.
547 Trundle the list of such things, finding the first item for which
548 CHECK is fboundp, and returning the correponding FUNC."
549   (let ((bs mdw-good-url-browsers) b check func answer)
550     (while (and bs (not answer))
551       (setq b (car bs)
552             bs (cdr bs))
553       (if (consp b)
554           (setq check (car b) func (cdr b))
555         (setq check b func b))
556       (if (fboundp check)
557           (setq answer func)))
558     answer))
559
560 (eval-after-load "w3m-search"
561   '(progn
562      (dolist
563          (item
564           '(("g" "Google" "http://www.google.co.uk/search?q=%s")
565             ("gd" "Google Directory"
566              "http://www.google.com/search?cat=gwd/Top&q=%s")
567             ("gg" "Google Groups" "http://groups.google.com/groups?q=%s")
568             ("ward" "Ward's wiki" "http://c2.com/cgi/wiki?%s")
569             ("gi" "Images" "http://images.google.com/images?q=%s")
570             ("rfc" "RFC"
571              "http://metalzone.distorted.org.uk/ftp/pub/mirrors/rfc/rfc%s.txt.gz")
572             ("wp" "Wikipedia"
573              "http://en.wikipedia.org/wiki/Special:Search?go=Go&search=%s")
574             ("imdb" "IMDb" "http://www.imdb.com/Find?%s")
575             ("nc-wiki" "nCipher wiki"
576              "http://wiki.ncipher.com/wiki/bin/view/Devel/?topic=%s")
577             ("map" "Google maps" "http://maps.google.co.uk/maps?q=%s&hl=en")
578             ("lp" "Launchpad bug by number"
579              "https://bugs.launchpad.net/bugs/%s")
580             ("lppkg" "Launchpad bugs by package"
581              "https://bugs.launchpad.net/%s")
582             ("msdn" "MSDN"
583              "http://social.msdn.microsoft.com/Search/en-GB/?query=%s&ac=8")
584             ("debbug" "Debian bug by number"
585              "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%s")
586             ("debbugpkg" "Debian bugs by package"
587              "http://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=%s")
588             ("ljlogin" "LJ login" "http://www.livejournal.com/login.bml")))
589        (add-to-list 'w3m-search-engine-alist
590                     (list (cadr item) (caddr item) nil))
591        (add-to-list 'w3m-uri-replace-alist
592                     (list (concat "\\`" (car item) ":")
593                           'w3m-search-uri-replace
594                           (cadr item))))))
595
596 ;;;--------------------------------------------------------------------------
597 ;;; Paragraph filling.
598
599 ;; Useful variables.
600
601 (defvar mdw-fill-prefix nil
602   "*Used by `mdw-line-prefix' and `mdw-fill-paragraph'.
603 If there's no fill prefix currently set (by the `fill-prefix'
604 variable) and there's a match from one of the regexps here, it
605 gets used to set the fill-prefix for the current operation.
606
607 The variable is a list of items of the form `REGEXP . PREFIX'; if
608 the REGEXP matches, the PREFIX is used to set the fill prefix.
609 It in turn is a list of things:
610
611   STRING -- insert a literal string
612   (match . N) -- insert the thing matched by bracketed subexpression N
613   (pad . N) -- a string of whitespace the same width as subexpression N
614   (expr . FORM) -- the result of evaluating FORM")
615
616 (make-variable-buffer-local 'mdw-fill-prefix)
617
618 (defvar mdw-hanging-indents
619   (concat "\\(\\("
620             "\\([*o+]\\|-[-#]?\\|[0-9]+\\.\\|\\[[0-9]+\\]\\|([a-zA-Z])\\)"
621             "[ \t]+"
622           "\\)?\\)")
623   "*Standard regexp matching parts of a hanging indent.
624 This is mainly useful in `auto-fill-mode'.")
625
626 ;; Setting things up.
627
628 (fset 'mdw-do-auto-fill (symbol-function 'do-auto-fill))
629
630 ;; Utility functions.
631
632 (defun mdw-tabify (s)
633   "Tabify the string S.  This is a horrid hack."
634   (save-excursion
635     (save-match-data
636       (let (start end)
637         (beginning-of-line)
638         (setq start (point-marker))
639         (insert s "\n")
640         (setq end (point-marker))
641         (tabify start end)
642         (setq s (buffer-substring start (1- end)))
643         (delete-region start end)
644         (set-marker start nil)
645         (set-marker end nil)
646         s))))
647
648 (defun mdw-examine-fill-prefixes (l)
649   "Given a list of dynamic fill prefixes, pick one which matches
650 context and return the static fill prefix to use.  Point must be
651 at the start of a line, and match data must be saved."
652   (cond ((not l) nil)
653                ((looking-at (car (car l)))
654                 (mdw-tabify (apply (function concat)
655                                    (mapcar (function mdw-do-prefix-match)
656                                            (cdr (car l))))))
657                (t (mdw-examine-fill-prefixes (cdr l)))))
658
659 (defun mdw-maybe-car (p)
660   "If P is a pair, return (car P), otherwise just return P."
661   (if (consp p) (car p) p))
662
663 (defun mdw-padding (s)
664   "Return a string the same width as S but made entirely from whitespace."
665   (let* ((l (length s)) (i 0) (n (make-string l ? )))
666     (while (< i l)
667       (if (= 9 (aref s i))
668           (aset n i 9))
669       (setq i (1+ i)))
670     n))
671
672 (defun mdw-do-prefix-match (m)
673   "Expand a dynamic prefix match element.
674 See `mdw-fill-prefix' for details."
675   (cond ((not (consp m)) (format "%s" m))
676            ((eq (car m) 'match) (match-string (mdw-maybe-car (cdr m))))
677            ((eq (car m) 'pad) (mdw-padding (match-string
678                                             (mdw-maybe-car (cdr m)))))
679            ((eq (car m) 'eval) (eval (cdr m)))
680            (t "")))
681
682 (defun mdw-choose-dynamic-fill-prefix ()
683   "Work out the dynamic fill prefix based on the variable `mdw-fill-prefix'."
684   (cond ((and fill-prefix (not (string= fill-prefix ""))) fill-prefix)
685            ((not mdw-fill-prefix) fill-prefix)
686            (t (save-excursion
687                 (beginning-of-line)
688                 (save-match-data
689                   (mdw-examine-fill-prefixes mdw-fill-prefix))))))
690
691 (defun do-auto-fill ()
692   "Handle auto-filling, working out a dynamic fill prefix in the
693 case where there isn't a sensible static one."
694   (let ((fill-prefix (mdw-choose-dynamic-fill-prefix)))
695     (mdw-do-auto-fill)))
696
697 (defun mdw-fill-paragraph ()
698   "Fill paragraph, getting a dynamic fill prefix."
699   (interactive)
700   (let ((fill-prefix (mdw-choose-dynamic-fill-prefix)))
701     (fill-paragraph nil)))
702
703 (defun mdw-standard-fill-prefix (rx &optional mat)
704   "Set the dynamic fill prefix, handling standard hanging indents and stuff.
705 This is just a short-cut for setting the thing by hand, and by
706 design it doesn't cope with anything approximating a complicated
707 case."
708   (setq mdw-fill-prefix
709            `((,(concat rx mdw-hanging-indents)
710               (match . 1)
711               (pad . ,(or mat 2))))))
712
713 ;;;--------------------------------------------------------------------------
714 ;;; Other common declarations.
715
716 ;; Common mode settings.
717
718 (defvar mdw-auto-indent t
719   "Whether to indent automatically after a newline.")
720
721 (defun mdw-whitespace-mode (&optional arg)
722   "Turn on/off whitespace mode, but don't highlight trailing space."
723   (interactive "P")
724   (when (and (boundp 'whitespace-style)
725              (fboundp 'whitespace-mode))
726     (let ((whitespace-style (remove 'trailing whitespace-style)))
727       (whitespace-mode arg))
728     (setq show-trailing-whitespace whitespace-mode)))
729
730 (defun mdw-misc-mode-config ()
731   (and mdw-auto-indent
732        (cond ((eq major-mode 'lisp-mode)
733               (local-set-key "\C-m" 'mdw-indent-newline-and-indent))
734              ((or (eq major-mode 'slime-repl-mode)
735                   (eq major-mode 'asm-mode))
736               nil)
737              (t
738               (local-set-key "\C-m" 'newline-and-indent))))
739   (local-set-key [C-return] 'newline)
740   (make-local-variable 'page-delimiter)
741   (setq page-delimiter "\f\\|^.*-\\{6\\}.*$")
742   (setq comment-column 40)
743   (auto-fill-mode 1)
744   (setq fill-column 77)
745   (setq show-trailing-whitespace t)
746   (mdw-whitespace-mode 1)
747   (and (fboundp 'gtags-mode)
748        (gtags-mode))
749   (if (fboundp 'hs-minor-mode)
750       (hs-minor-mode t)
751     (outline-minor-mode t))
752   (reveal-mode t)
753   (trap (turn-on-font-lock)))
754
755 (defun mdw-post-config-mode-hack ()
756   (mdw-whitespace-mode 1))
757
758 (eval-after-load 'gtags
759   '(progn
760      (dolist (key '([mouse-2] [mouse-3]))
761        (define-key gtags-mode-map key nil))
762      (define-key gtags-mode-map [C-S-mouse-2] 'gtags-find-tag-by-event)
763      (define-key gtags-select-mode-map [C-S-mouse-2]
764        'gtags-select-tag-by-event)
765      (dolist (map (list gtags-mode-map gtags-select-mode-map))
766        (define-key map [C-S-mouse-3] 'gtags-pop-stack))))
767
768 ;; Backup file handling.
769
770 (defvar mdw-backup-disable-regexps nil
771   "*List of regular expressions: if a file name matches any of
772 these then the file is not backed up.")
773
774 (defun mdw-backup-enable-predicate (name)
775   "[mdw]'s default backup predicate.
776 Allows a backup if the standard predicate would allow it, and it
777 doesn't match any of the regular expressions in
778 `mdw-backup-disable-regexps'."
779   (and (normal-backup-enable-predicate name)
780        (let ((answer t) (list mdw-backup-disable-regexps))
781          (save-match-data
782            (while list
783              (if (string-match (car list) name)
784                  (setq answer nil))
785              (setq list (cdr list)))
786            answer))))
787 (setq backup-enable-predicate 'mdw-backup-enable-predicate)
788
789 ;; Frame cleanup.
790
791 (defun mdw-last-one-out-turn-off-the-lights (frame)
792   "Disconnect from an X display if this was the last frame on that display."
793   (let ((frame-display (frame-parameter frame 'display)))
794     (when (and frame-display
795                (eq window-system 'x)
796                (not (some (lambda (fr)
797                             (and (not (eq fr frame))
798                                  (string= (frame-parameter fr 'display)
799                                           frame-display)))
800                           (frame-list))))
801       (run-with-idle-timer 0 nil #'x-close-connection frame-display))))
802 (add-hook 'delete-frame-functions 'mdw-last-one-out-turn-off-the-lights)
803
804 ;;;--------------------------------------------------------------------------
805 ;;; General fontification.
806
807 (defmacro mdw-define-face (name &rest body)
808   "Define a face, and make sure it's actually set as the definition."
809   (declare (indent 1)
810            (debug 0))
811   `(progn
812      (make-face ',name)
813      (defvar ,name ',name)
814      (put ',name 'face-defface-spec ',body)
815      (face-spec-set ',name ',body nil)))
816
817 (mdw-define-face default
818   (((type w32)) :family "courier new" :height 85)
819   (((type x)) :family "6x13" :height 130)
820   (((type color)) :foreground "white" :background "black")
821   (t nil))
822 (mdw-define-face fixed-pitch
823   (((type w32)) :family "courier new" :height 85)
824   (((type x)) :family "6x13" :height 130)
825   (t :foreground "white" :background "black"))
826 (if (>= emacs-major-version 23)
827     (mdw-define-face variable-pitch
828       (((type x)) :family "sans" :height 100))
829   (mdw-define-face variable-pitch
830     (((type x)) :family "helvetica" :height 90)))
831 (mdw-define-face region
832   (((type tty) (class color)) :background "blue")
833   (((type tty) (class mono)) :inverse-video t)
834   (t :background "grey30"))
835 (mdw-define-face minibuffer-prompt
836   (t :weight bold))
837 (mdw-define-face mode-line
838   (((class color)) :foreground "blue" :background "yellow"
839                    :box (:line-width 1 :style released-button))
840   (t :inverse-video t))
841 (mdw-define-face mode-line-inactive
842   (((class color)) :foreground "yellow" :background "blue"
843                    :box (:line-width 1 :style released-button))
844   (t :inverse-video t))
845 (mdw-define-face scroll-bar
846   (t :foreground "black" :background "lightgrey"))
847 (mdw-define-face fringe
848   (t :foreground "yellow"))
849 (mdw-define-face show-paren-match
850   (((class color)) :background "darkgreen")
851   (t :underline t))
852 (mdw-define-face show-paren-mismatch
853   (((class color)) :background "red")
854   (t :inverse-video t))
855 (mdw-define-face highlight
856   (((class color)) :background "DarkSeaGreen4")
857   (t :inverse-video t))
858
859 (mdw-define-face holiday-face
860   (t :background "red"))
861 (mdw-define-face calendar-today-face
862   (t :foreground "yellow" :weight bold))
863
864 (mdw-define-face comint-highlight-prompt
865   (t :weight bold))
866 (mdw-define-face comint-highlight-input
867   (t nil))
868
869 (mdw-define-face dired-directory
870   (t :foreground "cyan" :weight bold))
871 (mdw-define-face dired-symlink
872   (t :foreground "cyan"))
873 (mdw-define-face dired-perm-write
874   (t nil))
875
876 (mdw-define-face trailing-whitespace
877   (((class color)) :background "red")
878   (t :inverse-video t))
879 (mdw-define-face mdw-punct-face
880   (((type tty)) :foreground "yellow") (t :foreground "burlywood2"))
881 (mdw-define-face mdw-number-face
882   (t :foreground "yellow"))
883 (mdw-define-face font-lock-function-name-face
884   (t :slant italic))
885 (mdw-define-face font-lock-keyword-face
886   (t :weight bold))
887 (mdw-define-face font-lock-constant-face
888   (t :slant italic))
889 (mdw-define-face font-lock-builtin-face
890   (t :weight bold))
891 (mdw-define-face font-lock-type-face
892   (t :weight bold :slant italic))
893 (mdw-define-face font-lock-reference-face
894   (t :weight bold))
895 (mdw-define-face font-lock-variable-name-face
896   (t :slant italic))
897 (mdw-define-face font-lock-comment-delimiter-face
898   (((class mono)) :weight bold)
899   (((type tty) (class color)) :foreground "green")
900   (t :slant italic :foreground "SeaGreen1"))
901 (mdw-define-face font-lock-comment-face
902   (((class mono)) :weight bold)
903   (((type tty) (class color)) :foreground "green")
904   (t :slant italic :foreground "SeaGreen1"))
905 (mdw-define-face font-lock-string-face
906   (((class mono)) :weight bold)
907   (((class color)) :foreground "SkyBlue1"))
908 (mdw-define-face message-separator
909   (t :background "red" :foreground "white" :weight bold))
910 (mdw-define-face message-cited-text
911   (default :slant italic)
912   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
913 (mdw-define-face message-header-cc
914   (default :weight bold)
915   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
916 (mdw-define-face message-header-newsgroups
917   (default :weight bold)
918   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
919 (mdw-define-face message-header-subject
920   (default :weight bold)
921   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
922 (mdw-define-face message-header-to
923   (default :weight bold)
924   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
925 (mdw-define-face message-header-xheader
926   (default :weight bold)
927   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
928 (mdw-define-face message-header-other
929   (default :weight bold)
930   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
931 (mdw-define-face message-header-name
932   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
933 (mdw-define-face which-func
934   (t nil))
935
936 (mdw-define-face diff-index
937   (t :weight bold))
938 (mdw-define-face diff-file-header
939   (t :weight bold))
940 (mdw-define-face diff-hunk-header
941   (t :foreground "SkyBlue1"))
942 (mdw-define-face diff-function
943   (t :foreground "SkyBlue1" :weight bold))
944 (mdw-define-face diff-header
945   (t :background "grey10"))
946 (mdw-define-face diff-added
947   (t :foreground "green"))
948 (mdw-define-face diff-removed
949   (t :foreground "red"))
950 (mdw-define-face diff-context
951   (t nil))
952
953 (mdw-define-face erc-input-face
954   (t :foreground "red"))
955
956 (mdw-define-face woman-bold
957   (t :weight bold))
958 (mdw-define-face woman-italic
959   (t :slant italic))
960
961 (mdw-define-face p4-depot-added-face
962   (t :foreground "green"))
963 (mdw-define-face p4-depot-branch-op-face
964   (t :foreground "yellow"))
965 (mdw-define-face p4-depot-deleted-face
966   (t :foreground "red"))
967 (mdw-define-face p4-depot-unmapped-face
968   (t :foreground "SkyBlue1"))
969 (mdw-define-face p4-diff-change-face
970   (t :foreground "yellow"))
971 (mdw-define-face p4-diff-del-face
972   (t :foreground "red"))
973 (mdw-define-face p4-diff-file-face
974   (t :foreground "SkyBlue1"))
975 (mdw-define-face p4-diff-head-face
976   (t :background "grey10"))
977 (mdw-define-face p4-diff-ins-face
978   (t :foreground "green"))
979
980 (mdw-define-face whizzy-slice-face
981   (t :background "grey10"))
982 (mdw-define-face whizzy-error-face
983   (t :background "darkred"))
984
985 ;;;--------------------------------------------------------------------------
986 ;;; C programming configuration.
987
988 ;; Linux kernel hacking.
989
990 (defvar linux-c-mode-hook)
991
992 (defun linux-c-mode ()
993   (interactive)
994   (c-mode)
995   (setq major-mode 'linux-c-mode)
996   (setq mode-name "Linux C")
997   (run-hooks 'linux-c-mode-hook))
998
999 ;; Make C indentation nice.
1000
1001 (defun mdw-c-lineup-arglist (langelem)
1002   "Hack for DWIMmery in c-lineup-arglist."
1003   (if (save-excursion
1004         (c-block-in-arglist-dwim (c-langelem-2nd-pos c-syntactic-element)))
1005       0
1006     (c-lineup-arglist langelem)))
1007
1008 (defun mdw-c-indent-extern-mumble (langelem)
1009   "Indent `extern \"...\" {' lines."
1010   (save-excursion
1011     (back-to-indentation)
1012     (if (looking-at
1013          "\\s-*\\<extern\\>\\s-*\"\\([^\\\\\"]+\\|\\.\\)*\"\\s-*{")
1014         c-basic-offset
1015       nil)))
1016
1017 (defun mdw-c-style ()
1018   (c-add-style "[mdw] C and C++ style"
1019                '((c-basic-offset . 2)
1020                  (comment-column . 40)
1021                  (c-class-key . "class")
1022                  (c-backslash-column . 72)
1023                  (c-offsets-alist
1024                   (substatement-open . (add 0 c-indent-one-line-block))
1025                   (defun-open . (add 0 c-indent-one-line-block))
1026                   (arglist-cont-nonempty . mdw-c-lineup-arglist)
1027                   (topmost-intro . mdw-c-indent-extern-mumble)
1028                   (cpp-define-intro . 0)
1029                   (inextern-lang . [0])
1030                   (label . 0)
1031                   (case-label . +)
1032                   (access-label . -)
1033                   (inclass . +)
1034                   (inline-open . ++)
1035                   (statement-cont . 0)
1036                   (statement-case-intro . +)))
1037                t))
1038
1039 (defvar mdw-c-comment-fill-prefix
1040   `((,(concat "\\([ \t]*/?\\)"
1041               "\\(\*\\|//]\\)"
1042               "\\([ \t]*\\)"
1043               "\\([A-Za-z]+:[ \t]*\\)?"
1044               mdw-hanging-indents)
1045      (pad . 1) (match . 2) (pad . 3) (pad . 4) (pad . 5)))
1046   "Fill prefix matching C comments (both kinds).")
1047
1048 (defun mdw-fontify-c-and-c++ ()
1049
1050   ;; Fiddle with some syntax codes.
1051   (modify-syntax-entry ?* ". 23")
1052   (modify-syntax-entry ?/ ". 124b")
1053   (modify-syntax-entry ?\n "> b")
1054
1055   ;; Other stuff.
1056   (mdw-c-style)
1057   (setq c-hanging-comment-ender-p nil)
1058   (setq c-backslash-column 72)
1059   (setq c-label-minimum-indentation 0)
1060   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
1061
1062   ;; Now define things to be fontified.
1063   (make-local-variable 'font-lock-keywords)
1064   (let ((c-keywords
1065          (mdw-regexps "and"             ;C++
1066                       "and_eq"          ;C++
1067                       "asm"             ;K&R, GCC
1068                       "auto"            ;K&R, C89
1069                       "bitand"          ;C++
1070                       "bitor"           ;C++
1071                       "bool"            ;C++, C9X macro
1072                       "break"           ;K&R, C89
1073                       "case"            ;K&R, C89
1074                       "catch"           ;C++
1075                       "char"            ;K&R, C89
1076                       "class"           ;C++
1077                       "complex"         ;C9X macro, C++ template type
1078                       "compl"           ;C++
1079                       "const"           ;C89
1080                       "const_cast"      ;C++
1081                       "continue"        ;K&R, C89
1082                       "defined"         ;C89 preprocessor
1083                       "default"         ;K&R, C89
1084                       "delete"          ;C++
1085                       "do"              ;K&R, C89
1086                       "double"          ;K&R, C89
1087                       "dynamic_cast"    ;C++
1088                       "else"            ;K&R, C89
1089                       ;; "entry"        ;K&R -- never used
1090                       "enum"            ;C89
1091                       "explicit"        ;C++
1092                       "export"          ;C++
1093                       "extern"          ;K&R, C89
1094                       "false"           ;C++, C9X macro
1095                       "float"           ;K&R, C89
1096                       "for"             ;K&R, C89
1097                       ;; "fortran"      ;K&R
1098                       "friend"          ;C++
1099                       "goto"            ;K&R, C89
1100                       "if"              ;K&R, C89
1101                       "imaginary"       ;C9X macro
1102                       "inline"          ;C++, C9X, GCC
1103                       "int"             ;K&R, C89
1104                       "long"            ;K&R, C89
1105                       "mutable"         ;C++
1106                       "namespace"       ;C++
1107                       "new"             ;C++
1108                       "operator"        ;C++
1109                       "or"              ;C++
1110                       "or_eq"           ;C++
1111                       "private"         ;C++
1112                       "protected"       ;C++
1113                       "public"          ;C++
1114                       "register"        ;K&R, C89
1115                       "reinterpret_cast" ;C++
1116                       "restrict"         ;C9X
1117                       "return"           ;K&R, C89
1118                       "short"            ;K&R, C89
1119                       "signed"           ;C89
1120                       "sizeof"           ;K&R, C89
1121                       "static"           ;K&R, C89
1122                       "static_cast"      ;C++
1123                       "struct"           ;K&R, C89
1124                       "switch"           ;K&R, C89
1125                       "template"         ;C++
1126                       "this"             ;C++
1127                       "throw"            ;C++
1128                       "true"             ;C++, C9X macro
1129                       "try"              ;C++
1130                       "this"             ;C++
1131                       "typedef"          ;C89
1132                       "typeid"           ;C++
1133                       "typeof"           ;GCC
1134                       "typename"         ;C++
1135                       "union"            ;K&R, C89
1136                       "unsigned"         ;K&R, C89
1137                       "using"            ;C++
1138                       "virtual"          ;C++
1139                       "void"             ;C89
1140                       "volatile"         ;C89
1141                       "wchar_t"          ;C++, C89 library type
1142                       "while"            ;K&R, C89
1143                       "xor"              ;C++
1144                       "xor_eq"           ;C++
1145                       "_Bool"            ;C9X
1146                       "_Complex"         ;C9X
1147                       "_Imaginary"       ;C9X
1148                       "_Pragma"          ;C9X preprocessor
1149                       "__alignof__"      ;GCC
1150                       "__asm__"          ;GCC
1151                       "__attribute__"    ;GCC
1152                       "__complex__"      ;GCC
1153                       "__const__"        ;GCC
1154                       "__extension__"    ;GCC
1155                       "__imag__"         ;GCC
1156                       "__inline__"       ;GCC
1157                       "__label__"        ;GCC
1158                       "__real__"         ;GCC
1159                       "__signed__"       ;GCC
1160                       "__typeof__"       ;GCC
1161                       "__volatile__"     ;GCC
1162                       ))
1163         (preprocessor-keywords
1164          (mdw-regexps "assert" "define" "elif" "else" "endif" "error"
1165                       "ident" "if" "ifdef" "ifndef" "import" "include"
1166                       "line" "pragma" "unassert" "undef" "warning"))
1167         (objc-keywords
1168          (mdw-regexps "class" "defs" "encode" "end" "implementation"
1169                       "interface" "private" "protected" "protocol" "public"
1170                       "selector")))
1171
1172     (setq font-lock-keywords
1173           (list
1174
1175            ;; Fontify include files as strings.
1176            (list (concat "^[ \t]*\\#[ \t]*"
1177                          "\\(include\\|import\\)"
1178                          "[ \t]*\\(<[^>]+\\(>\\|\\)\\)")
1179                  '(2 font-lock-string-face))
1180
1181            ;; Preprocessor directives are `references'?.
1182            (list (concat "^\\([ \t]*#[ \t]*\\(\\("
1183                          preprocessor-keywords
1184                          "\\)\\>\\|[0-9]+\\|$\\)\\)")
1185                  '(1 font-lock-keyword-face))
1186
1187            ;; Handle the keywords defined above.
1188            (list (concat "@\\<\\(" objc-keywords "\\)\\>")
1189                  '(0 font-lock-keyword-face))
1190
1191            (list (concat "\\<\\(" c-keywords "\\)\\>")
1192                  '(0 font-lock-keyword-face))
1193
1194            ;; Handle numbers too.
1195            ;;
1196            ;; This looks strange, I know.  It corresponds to the
1197            ;; preprocessor's idea of what a number looks like, rather than
1198            ;; anything sensible.
1199            (list (concat "\\(\\<[0-9]\\|\\.[0-9]\\)"
1200                          "\\([Ee][+-]\\|[0-9A-Za-z_.]\\)*")
1201                  '(0 mdw-number-face))
1202
1203            ;; And anything else is punctuation.
1204            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1205                  '(0 mdw-punct-face))))
1206
1207     (mdw-post-config-mode-hack)))
1208
1209 ;;;--------------------------------------------------------------------------
1210 ;;; AP calc mode.
1211
1212 (defun apcalc-mode ()
1213   (interactive)
1214   (c-mode)
1215   (setq major-mode 'apcalc-mode)
1216   (setq mode-name "AP Calc")
1217   (run-hooks 'apcalc-mode-hook))
1218
1219 (defun mdw-fontify-apcalc ()
1220
1221   ;; Fiddle with some syntax codes.
1222   (modify-syntax-entry ?* ". 23")
1223   (modify-syntax-entry ?/ ". 14")
1224
1225   ;; Other stuff.
1226   (mdw-c-style)
1227   (setq c-hanging-comment-ender-p nil)
1228   (setq c-backslash-column 72)
1229   (setq comment-start "/* ")
1230   (setq comment-end " */")
1231   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
1232
1233   ;; Now define things to be fontified.
1234   (make-local-variable 'font-lock-keywords)
1235   (let ((c-keywords
1236          (mdw-regexps "break" "case" "cd" "continue" "define" "default"
1237                       "do" "else" "exit" "for" "global" "goto" "help" "if"
1238                       "local" "mat" "obj" "print" "quit" "read" "return"
1239                       "show" "static" "switch" "while" "write")))
1240
1241     (setq font-lock-keywords
1242           (list
1243
1244            ;; Handle the keywords defined above.
1245            (list (concat "\\<\\(" c-keywords "\\)\\>")
1246                  '(0 font-lock-keyword-face))
1247
1248            ;; Handle numbers too.
1249            ;;
1250            ;; This looks strange, I know.  It corresponds to the
1251            ;; preprocessor's idea of what a number looks like, rather than
1252            ;; anything sensible.
1253            (list (concat "\\(\\<[0-9]\\|\\.[0-9]\\)"
1254                          "\\([Ee][+-]\\|[0-9A-Za-z_.]\\)*")
1255                  '(0 mdw-number-face))
1256
1257            ;; And anything else is punctuation.
1258            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1259                  '(0 mdw-punct-face)))))
1260
1261   (mdw-post-config-mode-hack))
1262
1263 ;;;--------------------------------------------------------------------------
1264 ;;; Java programming configuration.
1265
1266 ;; Make indentation nice.
1267
1268 (defun mdw-java-style ()
1269   (c-add-style "[mdw] Java style"
1270                '((c-basic-offset . 2)
1271                  (c-offsets-alist (substatement-open . 0)
1272                                   (label . +)
1273                                   (case-label . +)
1274                                   (access-label . 0)
1275                                   (inclass . +)
1276                                   (statement-case-intro . +)))
1277                t))
1278
1279 ;; Declare Java fontification style.
1280
1281 (defun mdw-fontify-java ()
1282
1283   ;; Other stuff.
1284   (mdw-java-style)
1285   (setq c-hanging-comment-ender-p nil)
1286   (setq c-backslash-column 72)
1287   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
1288
1289   ;; Now define things to be fontified.
1290   (make-local-variable 'font-lock-keywords)
1291   (let ((java-keywords
1292          (mdw-regexps "abstract" "boolean" "break" "byte" "case" "catch"
1293                       "char" "class" "const" "continue" "default" "do"
1294                       "double" "else" "extends" "final" "finally" "float"
1295                       "for" "goto" "if" "implements" "import" "instanceof"
1296                       "int" "interface" "long" "native" "new" "package"
1297                       "private" "protected" "public" "return" "short"
1298                       "static" "super" "switch" "synchronized" "this"
1299                       "throw" "throws" "transient" "try" "void" "volatile"
1300                       "while"
1301
1302                       "false" "null" "true")))
1303
1304     (setq font-lock-keywords
1305           (list
1306
1307            ;; Handle the keywords defined above.
1308            (list (concat "\\<\\(" java-keywords "\\)\\>")
1309                  '(0 font-lock-keyword-face))
1310
1311            ;; Handle numbers too.
1312            ;;
1313            ;; The following isn't quite right, but it's close enough.
1314            (list (concat "\\<\\("
1315                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
1316                          "[0-9]+\\(\\.[0-9]*\\|\\)"
1317                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
1318                          "[lLfFdD]?")
1319                  '(0 mdw-number-face))
1320
1321            ;; And anything else is punctuation.
1322            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1323                  '(0 mdw-punct-face)))))
1324
1325   (mdw-post-config-mode-hack))
1326
1327 ;;;--------------------------------------------------------------------------
1328 ;;; C# programming configuration.
1329
1330 ;; Make indentation nice.
1331
1332 (defun mdw-csharp-style ()
1333   (c-add-style "[mdw] C# style"
1334                '((c-basic-offset . 2)
1335                  (c-offsets-alist (substatement-open . 0)
1336                                   (label . 0)
1337                                   (case-label . +)
1338                                   (access-label . 0)
1339                                   (inclass . +)
1340                                   (statement-case-intro . +)))
1341                t))
1342
1343 ;; Declare C# fontification style.
1344
1345 (defun mdw-fontify-csharp ()
1346
1347   ;; Other stuff.
1348   (mdw-csharp-style)
1349   (setq c-hanging-comment-ender-p nil)
1350   (setq c-backslash-column 72)
1351   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
1352
1353   ;; Now define things to be fontified.
1354   (make-local-variable 'font-lock-keywords)
1355   (let ((csharp-keywords
1356          (mdw-regexps "abstract" "as" "base" "bool" "break"
1357                       "byte" "case" "catch" "char" "checked"
1358                       "class" "const" "continue" "decimal" "default"
1359                       "delegate" "do" "double" "else" "enum"
1360                       "event" "explicit" "extern" "false" "finally"
1361                       "fixed" "float" "for" "foreach" "goto"
1362                       "if" "implicit" "in" "int" "interface"
1363                       "internal" "is" "lock" "long" "namespace"
1364                       "new" "null" "object" "operator" "out"
1365                       "override" "params" "private" "protected" "public"
1366                       "readonly" "ref" "return" "sbyte" "sealed"
1367                       "short" "sizeof" "stackalloc" "static" "string"
1368                       "struct" "switch" "this" "throw" "true"
1369                       "try" "typeof" "uint" "ulong" "unchecked"
1370                       "unsafe" "ushort" "using" "virtual" "void"
1371                       "volatile" "while" "yield")))
1372
1373     (setq font-lock-keywords
1374           (list
1375
1376            ;; Handle the keywords defined above.
1377            (list (concat "\\<\\(" csharp-keywords "\\)\\>")
1378                  '(0 font-lock-keyword-face))
1379
1380            ;; Handle numbers too.
1381            ;;
1382            ;; The following isn't quite right, but it's close enough.
1383            (list (concat "\\<\\("
1384                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
1385                          "[0-9]+\\(\\.[0-9]*\\|\\)"
1386                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
1387                          "[lLfFdD]?")
1388                  '(0 mdw-number-face))
1389
1390            ;; And anything else is punctuation.
1391            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1392                  '(0 mdw-punct-face)))))
1393
1394   (mdw-post-config-mode-hack))
1395
1396 (define-derived-mode csharp-mode java-mode "C#"
1397   "Major mode for editing C# code.")
1398
1399 ;;;--------------------------------------------------------------------------
1400 ;;; Go programming configuration.
1401
1402 (defun mdw-fontify-go ()
1403
1404   (make-local-variable 'font-lock-keywords)
1405   (let ((go-keywords
1406          (mdw-regexps "break" "case" "chan" "const" "continue"
1407                       "default" "defer" "else" "fallthrough" "for"
1408                       "func" "go" "goto" "if" "import"
1409                       "interface" "map" "package" "range" "return"
1410                       "select" "struct" "switch" "type" "var")))
1411
1412     (setq font-lock-keywords
1413           (list
1414
1415            ;; Handle the keywords defined above.
1416            (list (concat "\\<\\(" go-keywords "\\)\\>")
1417                  '(0 font-lock-keyword-face))
1418
1419            ;; Handle numbers too.
1420            ;;
1421            ;; The following isn't quite right, but it's close enough.
1422            (list (concat "\\<\\("
1423                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
1424                          "[0-9]+\\(\\.[0-9]*\\|\\)"
1425                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)")
1426                  '(0 mdw-number-face))
1427
1428            ;; And anything else is punctuation.
1429            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1430                  '(0 mdw-punct-face)))))
1431
1432   (mdw-post-config-mode-hack))
1433
1434 ;;;--------------------------------------------------------------------------
1435 ;;; Awk programming configuration.
1436
1437 ;; Make Awk indentation nice.
1438
1439 (defun mdw-awk-style ()
1440   (c-add-style "[mdw] Awk style"
1441                '((c-basic-offset . 2)
1442                  (c-offsets-alist (substatement-open . 0)
1443                                   (statement-cont . 0)
1444                                   (statement-case-intro . +)))
1445                t))
1446
1447 ;; Declare Awk fontification style.
1448
1449 (defun mdw-fontify-awk ()
1450
1451   ;; Miscellaneous fiddling.
1452   (mdw-awk-style)
1453   (setq c-backslash-column 72)
1454   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
1455
1456   ;; Now define things to be fontified.
1457   (make-local-variable 'font-lock-keywords)
1458   (let ((c-keywords
1459          (mdw-regexps "BEGIN" "END" "ARGC" "ARGIND" "ARGV" "CONVFMT"
1460                       "ENVIRON" "ERRNO" "FIELDWIDTHS" "FILENAME" "FNR"
1461                       "FS" "IGNORECASE" "NF" "NR" "OFMT" "OFS" "ORS" "RS"
1462                       "RSTART" "RLENGTH" "RT"   "SUBSEP"
1463                       "atan2" "break" "close" "continue" "cos" "delete"
1464                       "do" "else" "exit" "exp" "fflush" "file" "for" "func"
1465                       "function" "gensub" "getline" "gsub" "if" "in"
1466                       "index" "int" "length" "log" "match" "next" "rand"
1467                       "return" "print" "printf" "sin" "split" "sprintf"
1468                       "sqrt" "srand" "strftime" "sub" "substr" "system"
1469                       "systime" "tolower" "toupper" "while")))
1470
1471     (setq font-lock-keywords
1472           (list
1473
1474            ;; Handle the keywords defined above.
1475            (list (concat "\\<\\(" c-keywords "\\)\\>")
1476                  '(0 font-lock-keyword-face))
1477
1478            ;; Handle numbers too.
1479            ;;
1480            ;; The following isn't quite right, but it's close enough.
1481            (list (concat "\\<\\("
1482                          "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
1483                          "[0-9]+\\(\\.[0-9]*\\|\\)"
1484                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
1485                          "[uUlL]*")
1486                  '(0 mdw-number-face))
1487
1488            ;; And anything else is punctuation.
1489            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1490                  '(0 mdw-punct-face)))))
1491
1492   (mdw-post-config-mode-hack))
1493
1494 ;;;--------------------------------------------------------------------------
1495 ;;; Perl programming style.
1496
1497 ;; Perl indentation style.
1498
1499 (setq cperl-indent-level 2)
1500 (setq cperl-continued-statement-offset 2)
1501 (setq cperl-continued-brace-offset 0)
1502 (setq cperl-brace-offset -2)
1503 (setq cperl-brace-imaginary-offset 0)
1504 (setq cperl-label-offset 0)
1505
1506 ;; Define perl fontification style.
1507
1508 (defun mdw-fontify-perl ()
1509
1510   ;; Miscellaneous fiddling.
1511   (modify-syntax-entry ?$ "\\")
1512   (modify-syntax-entry ?$ "\\" font-lock-syntax-table)
1513   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
1514
1515   ;; Now define fontification things.
1516   (make-local-variable 'font-lock-keywords)
1517   (let ((perl-keywords
1518          (mdw-regexps "and" "cmp" "continue" "do" "else" "elsif" "eq"
1519                       "for" "foreach" "ge" "gt" "goto" "if"
1520                       "last" "le" "lt" "local" "my" "ne" "next" "or"
1521                       "package" "redo" "require" "return" "sub"
1522                       "undef" "unless" "until" "use" "while")))
1523
1524     (setq font-lock-keywords
1525           (list
1526
1527            ;; Set up the keywords defined above.
1528            (list (concat "\\<\\(" perl-keywords "\\)\\>")
1529                  '(0 font-lock-keyword-face))
1530
1531            ;; At least numbers are simpler than C.
1532            (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
1533                          "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
1534                          "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
1535                  '(0 mdw-number-face))
1536
1537            ;; And anything else is punctuation.
1538            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1539                  '(0 mdw-punct-face)))))
1540
1541   (mdw-post-config-mode-hack))
1542
1543 (defun perl-number-tests (&optional arg)
1544   "Assign consecutive numbers to lines containing `#t'.  With ARG,
1545 strip numbers instead."
1546   (interactive "P")
1547   (save-excursion
1548     (goto-char (point-min))
1549     (let ((i 0) (fmt (if arg "" " %4d")))
1550       (while (search-forward "#t" nil t)
1551         (delete-region (point) (line-end-position))
1552         (setq i (1+ i))
1553         (insert (format fmt i)))
1554       (goto-char (point-min))
1555       (if (re-search-forward "\\(tests\\s-*=>\\s-*\\)\\w*" nil t)
1556           (replace-match (format "\\1%d" i))))))
1557
1558 ;;;--------------------------------------------------------------------------
1559 ;;; Python programming style.
1560
1561 (defun mdw-fontify-pythonic (keywords)
1562
1563   ;; Miscellaneous fiddling.
1564   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
1565   (setq indent-tabs-mode nil)
1566
1567   ;; Now define fontification things.
1568   (make-local-variable 'font-lock-keywords)
1569   (setq font-lock-keywords
1570         (list
1571
1572          ;; Set up the keywords defined above.
1573          (list (concat "\\<\\(" keywords "\\)\\>")
1574                '(0 font-lock-keyword-face))
1575
1576          ;; At least numbers are simpler than C.
1577          (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
1578                        "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
1579                        "\\([eE]\\([-+]\\|\\)[0-9_]+\\|[lL]\\|\\)")
1580                '(0 mdw-number-face))
1581
1582          ;; And anything else is punctuation.
1583          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1584                '(0 mdw-punct-face))))
1585
1586   (mdw-post-config-mode-hack))
1587
1588 ;; Define Python fontification styles.
1589
1590 (defun mdw-fontify-python ()
1591   (mdw-fontify-pythonic
1592    (mdw-regexps "and" "as" "assert" "break" "class" "continue" "def"
1593                 "del" "elif" "else" "except" "exec" "finally" "for"
1594                 "from" "global" "if" "import" "in" "is" "lambda"
1595                 "not" "or" "pass" "print" "raise" "return" "try"
1596                 "while" "with" "yield")))
1597
1598 (defun mdw-fontify-pyrex ()
1599   (mdw-fontify-pythonic
1600    (mdw-regexps "and" "as" "assert" "break" "cdef" "class" "continue"
1601                 "ctypedef" "def" "del" "elif" "else" "except" "exec"
1602                 "extern" "finally" "for" "from" "global" "if"
1603                 "import" "in" "is" "lambda" "not" "or" "pass" "print"
1604                 "raise" "return" "struct" "try" "while" "with"
1605                 "yield")))
1606
1607 ;;;--------------------------------------------------------------------------
1608 ;;; Icon programming style.
1609
1610 ;; Icon indentation style.
1611
1612 (setq icon-brace-offset 0
1613       icon-continued-brace-offset 0
1614       icon-continued-statement-offset 2
1615       icon-indent-level 2)
1616
1617 ;; Define Icon fontification style.
1618
1619 (defun mdw-fontify-icon ()
1620
1621   ;; Miscellaneous fiddling.
1622   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
1623
1624   ;; Now define fontification things.
1625   (make-local-variable 'font-lock-keywords)
1626   (let ((icon-keywords
1627          (mdw-regexps "break" "by" "case" "create" "default" "do" "else"
1628                       "end" "every" "fail" "global" "if" "initial"
1629                       "invocable" "link" "local" "next" "not" "of"
1630                       "procedure" "record" "repeat" "return" "static"
1631                       "suspend" "then" "to" "until" "while"))
1632         (preprocessor-keywords
1633          (mdw-regexps "define" "else" "endif" "error" "ifdef" "ifndef"
1634                       "include" "line" "undef")))
1635     (setq font-lock-keywords
1636           (list
1637
1638            ;; Set up the keywords defined above.
1639            (list (concat "\\<\\(" icon-keywords "\\)\\>")
1640                  '(0 font-lock-keyword-face))
1641
1642            ;; The things that Icon calls keywords.
1643            (list "&\\sw+\\>" '(0 font-lock-variable-name-face))
1644
1645            ;; At least numbers are simpler than C.
1646            (list (concat "\\<[0-9]+"
1647                          "\\([rR][0-9a-zA-Z]+\\|"
1648                          "\\.[0-9]+\\([eE][+-]?[0-9]+\\)?\\)\\>\\|"
1649                          "\\.[0-9]+\\([eE][+-]?[0-9]+\\)?\\>")
1650                  '(0 mdw-number-face))
1651
1652            ;; Preprocessor.
1653            (list (concat "^[ \t]*$[ \t]*\\<\\("
1654                          preprocessor-keywords
1655                          "\\)\\>")
1656                  '(0 font-lock-keyword-face))
1657
1658            ;; And anything else is punctuation.
1659            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1660                  '(0 mdw-punct-face)))))
1661
1662   (mdw-post-config-mode-hack))
1663
1664 ;;;--------------------------------------------------------------------------
1665 ;;; ARM assembler programming configuration.
1666
1667 ;; There doesn't appear to be an Emacs mode for this yet.
1668 ;;
1669 ;; Better do something about that, I suppose.
1670
1671 (defvar arm-assembler-mode-map nil)
1672 (defvar arm-assembler-abbrev-table nil)
1673 (defvar arm-assembler-mode-syntax-table (make-syntax-table))
1674
1675 (or arm-assembler-mode-map
1676     (progn
1677       (setq arm-assembler-mode-map (make-sparse-keymap))
1678       (define-key arm-assembler-mode-map "\C-m" 'arm-assembler-newline)
1679       (define-key arm-assembler-mode-map [C-return] 'newline)
1680       (define-key arm-assembler-mode-map "\t" 'tab-to-tab-stop)))
1681
1682 (defun arm-assembler-mode ()
1683   "Major mode for ARM assembler programs"
1684   (interactive)
1685
1686   ;; Do standard major mode things.
1687   (kill-all-local-variables)
1688   (use-local-map arm-assembler-mode-map)
1689   (setq local-abbrev-table arm-assembler-abbrev-table)
1690   (setq major-mode 'arm-assembler-mode)
1691   (setq mode-name "ARM assembler")
1692
1693   ;; Set up syntax table.
1694   (set-syntax-table arm-assembler-mode-syntax-table)
1695   (modify-syntax-entry ?;   ; Nasty hack
1696                        "<" arm-assembler-mode-syntax-table)
1697   (modify-syntax-entry ?\n ">" arm-assembler-mode-syntax-table)
1698   (modify-syntax-entry ?_ "_" arm-assembler-mode-syntax-table)
1699
1700   (make-local-variable 'comment-start)
1701   (setq comment-start ";")
1702   (make-local-variable 'comment-end)
1703   (setq comment-end "")
1704   (make-local-variable 'comment-column)
1705   (setq comment-column 48)
1706   (make-local-variable 'comment-start-skip)
1707   (setq comment-start-skip ";+[ \t]*")
1708
1709   ;; Play with indentation.
1710   (make-local-variable 'indent-line-function)
1711   (setq indent-line-function 'indent-relative-maybe)
1712
1713   ;; Set fill prefix.
1714   (mdw-standard-fill-prefix "\\([ \t]*;+[ \t]*\\)")
1715
1716   ;; Fiddle with fontification.
1717   (make-local-variable 'font-lock-keywords)
1718   (setq font-lock-keywords
1719         (list
1720
1721          ;; Handle numbers too.
1722          ;;
1723          ;; The following isn't quite right, but it's close enough.
1724          (list (concat "\\("
1725                        "&[0-9a-fA-F]+\\|"
1726                        "\\<[0-9]+\\(\\.[0-9]*\\|_[0-9a-zA-Z]+\\|\\)"
1727                        "\\)")
1728                '(0 mdw-number-face))
1729
1730          ;; Do something about operators.
1731          (list "^[^ \t]*[ \t]+\\(GET\\|LNK\\)[ \t]+\\([^;\n]*\\)"
1732                '(1 font-lock-keyword-face)
1733                '(2 font-lock-string-face))
1734          (list ":[a-zA-Z]+:"
1735                '(0 font-lock-keyword-face))
1736
1737          ;; Do menemonics and directives.
1738          (list "^[^ \t]*[ \t]+\\([a-zA-Z]+\\)"
1739                '(1 font-lock-keyword-face))
1740
1741          ;; And anything else is punctuation.
1742          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1743                '(0 mdw-punct-face)))
1744
1745   (mdw-post-config-mode-hack))
1746   (run-hooks 'arm-assembler-mode-hook))
1747
1748 ;;;--------------------------------------------------------------------------
1749 ;;; Assembler mode.
1750
1751 (defun mdw-fontify-asm ()
1752   (modify-syntax-entry ?' "\"")
1753   (modify-syntax-entry ?. "w")
1754   (setf fill-prefix nil)
1755   (mdw-standard-fill-prefix "\\([ \t]*;+[ \t]*\\)"))
1756
1757 ;;;--------------------------------------------------------------------------
1758 ;;; TCL configuration.
1759
1760 (defun mdw-fontify-tcl ()
1761   (mapcar #'(lambda (ch) (modify-syntax-entry ch ".")) '(?$))
1762   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
1763   (make-local-variable 'font-lock-keywords)
1764   (setq font-lock-keywords
1765         (list
1766          (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
1767                        "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
1768                        "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
1769                '(0 mdw-number-face))
1770          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1771                '(0 mdw-punct-face))))
1772   (mdw-post-config-mode-hack))
1773
1774 ;;;--------------------------------------------------------------------------
1775 ;;; REXX configuration.
1776
1777 (defun mdw-rexx-electric-* ()
1778   (interactive)
1779   (insert ?*)
1780   (rexx-indent-line))
1781
1782 (defun mdw-rexx-indent-newline-indent ()
1783   (interactive)
1784   (rexx-indent-line)
1785   (if abbrev-mode (expand-abbrev))
1786   (newline-and-indent))
1787
1788 (defun mdw-fontify-rexx ()
1789
1790   ;; Various bits of fiddling.
1791   (setq mdw-auto-indent nil)
1792   (local-set-key [?\C-m] 'mdw-rexx-indent-newline-indent)
1793   (local-set-key [?*] 'mdw-rexx-electric-*)
1794   (mapcar #'(lambda (ch) (modify-syntax-entry ch "w"))
1795           '(?! ?? ?# ?@ ?$))
1796   (mdw-standard-fill-prefix "\\([ \t]*/?\*[ \t]*\\)")
1797
1798   ;; Set up keywords and things for fontification.
1799   (make-local-variable 'font-lock-keywords-case-fold-search)
1800   (setq font-lock-keywords-case-fold-search t)
1801
1802   (setq rexx-indent 2)
1803   (setq rexx-end-indent rexx-indent)
1804   (setq rexx-cont-indent rexx-indent)
1805
1806   (make-local-variable 'font-lock-keywords)
1807   (let ((rexx-keywords
1808          (mdw-regexps "address" "arg" "by" "call" "digits" "do" "drop"
1809                       "else" "end" "engineering" "exit" "expose" "for"
1810                       "forever" "form" "fuzz" "if" "interpret" "iterate"
1811                       "leave" "linein" "name" "nop" "numeric" "off" "on"
1812                       "options" "otherwise" "parse" "procedure" "pull"
1813                       "push" "queue" "return" "say" "select" "signal"
1814                       "scientific" "source" "then" "trace" "to" "until"
1815                       "upper" "value" "var" "version" "when" "while"
1816                       "with"
1817
1818                       "abbrev" "abs" "bitand" "bitor" "bitxor" "b2x"
1819                       "center" "center" "charin" "charout" "chars"
1820                       "compare" "condition" "copies" "c2d" "c2x"
1821                       "datatype" "date" "delstr" "delword" "d2c" "d2x"
1822                       "errortext" "format" "fuzz" "insert" "lastpos"
1823                       "left" "length" "lineout" "lines" "max" "min"
1824                       "overlay" "pos" "queued" "random" "reverse" "right"
1825                       "sign" "sourceline" "space" "stream" "strip"
1826                       "substr" "subword" "symbol" "time" "translate"
1827                       "trunc" "value" "verify" "word" "wordindex"
1828                       "wordlength" "wordpos" "words" "xrange" "x2b" "x2c"
1829                       "x2d")))
1830
1831     (setq font-lock-keywords
1832           (list
1833
1834            ;; Set up the keywords defined above.
1835            (list (concat "\\<\\(" rexx-keywords "\\)\\>")
1836                  '(0 font-lock-keyword-face))
1837
1838            ;; Fontify all symbols the same way.
1839            (list (concat "\\<\\([0-9.][A-Za-z0-9.!?_#@$]*[Ee][+-]?[0-9]+\\|"
1840                          "[A-Za-z0-9.!?_#@$]+\\)")
1841                  '(0 font-lock-variable-name-face))
1842
1843            ;; And everything else is punctuation.
1844            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1845                  '(0 mdw-punct-face)))))
1846
1847   (mdw-post-config-mode-hack))
1848
1849 ;;;--------------------------------------------------------------------------
1850 ;;; Standard ML programming style.
1851
1852 (defun mdw-fontify-sml ()
1853
1854   ;; Make underscore an honorary letter.
1855   (modify-syntax-entry ?' "w")
1856
1857   ;; Set fill prefix.
1858   (mdw-standard-fill-prefix "\\([ \t]*(\*[ \t]*\\)")
1859
1860   ;; Now define fontification things.
1861   (make-local-variable 'font-lock-keywords)
1862   (let ((sml-keywords
1863          (mdw-regexps "abstype" "and" "andalso" "as"
1864                       "case"
1865                       "datatype" "do"
1866                       "else" "end" "eqtype" "exception"
1867                       "fn" "fun" "functor"
1868                       "handle"
1869                       "if" "in" "include" "infix" "infixr"
1870                       "let" "local"
1871                       "nonfix"
1872                       "of" "op" "open" "orelse"
1873                       "raise" "rec"
1874                       "sharing" "sig" "signature" "struct" "structure"
1875                       "then" "type"
1876                       "val"
1877                       "where" "while" "with" "withtype")))
1878
1879     (setq font-lock-keywords
1880           (list
1881
1882            ;; Set up the keywords defined above.
1883            (list (concat "\\<\\(" sml-keywords "\\)\\>")
1884                  '(0 font-lock-keyword-face))
1885
1886            ;; At least numbers are simpler than C.
1887            (list (concat "\\<\\(\\~\\|\\)"
1888                             "\\(0\\(\\([wW]\\|\\)[xX][0-9a-fA-F]+\\|"
1889                                    "[wW][0-9]+\\)\\|"
1890                                 "\\([0-9]+\\(\\.[0-9]+\\|\\)"
1891                                          "\\([eE]\\(\\~\\|\\)"
1892                                                 "[0-9]+\\|\\)\\)\\)")
1893                  '(0 mdw-number-face))
1894
1895            ;; And anything else is punctuation.
1896            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1897                  '(0 mdw-punct-face)))))
1898
1899   (mdw-post-config-mode-hack))
1900
1901 ;;;--------------------------------------------------------------------------
1902 ;;; Haskell configuration.
1903
1904 (defun mdw-fontify-haskell ()
1905
1906   ;; Fiddle with syntax table to get comments right.
1907   (modify-syntax-entry ?' "\"")
1908   (modify-syntax-entry ?- ". 123")
1909   (modify-syntax-entry ?{ ". 1b")
1910   (modify-syntax-entry ?} ". 4b")
1911   (modify-syntax-entry ?\n ">")
1912
1913   ;; Set fill prefix.
1914   (mdw-standard-fill-prefix "\\([ \t]*{?--?[ \t]*\\)")
1915
1916   ;; Fiddle with fontification.
1917   (make-local-variable 'font-lock-keywords)
1918   (let ((haskell-keywords
1919          (mdw-regexps "as" "case" "ccall" "class" "data" "default"
1920                       "deriving" "do" "else" "foreign" "hiding" "if"
1921                       "import" "in" "infix" "infixl" "infixr" "instance"
1922                       "let" "module" "newtype" "of" "qualified" "safe"
1923                       "stdcall" "then" "type" "unsafe" "where")))
1924
1925     (setq font-lock-keywords
1926           (list
1927            (list "--.*$"
1928                  '(0 font-lock-comment-face))
1929            (list (concat "\\<\\(" haskell-keywords "\\)\\>")
1930                  '(0 font-lock-keyword-face))
1931            (list (concat "\\<0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
1932                          "\\<[0-9][0-9_]*\\(\\.[0-9]*\\|\\)"
1933                          "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)")
1934                  '(0 mdw-number-face))
1935            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1936                  '(0 mdw-punct-face)))))
1937
1938   (mdw-post-config-mode-hack))
1939
1940 ;;;--------------------------------------------------------------------------
1941 ;;; Erlang configuration.
1942
1943 (setq erlang-electric-commands nil)
1944
1945 (defun mdw-fontify-erlang ()
1946
1947   ;; Set fill prefix.
1948   (mdw-standard-fill-prefix "\\([ \t]*{?%*[ \t]*\\)")
1949
1950   ;; Fiddle with fontification.
1951   (make-local-variable 'font-lock-keywords)
1952   (let ((erlang-keywords
1953          (mdw-regexps "after" "and" "andalso"
1954                       "band" "begin" "bnot" "bor" "bsl" "bsr" "bxor"
1955                       "case" "catch" "cond"
1956                       "div" "end" "fun" "if" "let" "not"
1957                       "of" "or" "orelse"
1958                       "query" "receive" "rem" "try" "when" "xor")))
1959
1960     (setq font-lock-keywords
1961           (list
1962            (list "%.*$"
1963                  '(0 font-lock-comment-face))
1964            (list (concat "\\<\\(" erlang-keywords "\\)\\>")
1965                  '(0 font-lock-keyword-face))
1966            (list (concat "^-\\sw+\\>")
1967                  '(0 font-lock-keyword-face))
1968            (list "\\<[0-9]+\\(\\|#[0-9a-zA-Z]+\\|[eE][+-]?[0-9]+\\)\\>"
1969                  '(0 mdw-number-face))
1970            (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1971                  '(0 mdw-punct-face)))))
1972
1973   (mdw-post-config-mode-hack))
1974
1975 ;;;--------------------------------------------------------------------------
1976 ;;; Texinfo configuration.
1977
1978 (defun mdw-fontify-texinfo ()
1979
1980   ;; Set fill prefix.
1981   (mdw-standard-fill-prefix "\\([ \t]*@c[ \t]+\\)")
1982
1983   ;; Real fontification things.
1984   (make-local-variable 'font-lock-keywords)
1985   (setq font-lock-keywords
1986         (list
1987
1988          ;; Environment names are keywords.
1989          (list "@\\(end\\)  *\\([a-zA-Z]*\\)?"
1990                '(2 font-lock-keyword-face))
1991
1992          ;; Unmark escaped magic characters.
1993          (list "\\(@\\)\\([@{}]\\)"
1994                '(1 font-lock-keyword-face)
1995                '(2 font-lock-variable-name-face))
1996
1997          ;; Make sure we get comments properly.
1998          (list "@c\\(\\|omment\\)\\( .*\\)?$"
1999                '(0 font-lock-comment-face))
2000
2001          ;; Command names are keywords.
2002          (list "@\\([^a-zA-Z@]\\|[a-zA-Z@]*\\)"
2003                '(0 font-lock-keyword-face))
2004
2005          ;; Fontify TeX special characters as punctuation.
2006          (list "[{}]+"
2007                '(0 mdw-punct-face))))
2008
2009   (mdw-post-config-mode-hack))
2010
2011 ;;;--------------------------------------------------------------------------
2012 ;;; TeX and LaTeX configuration.
2013
2014 (defun mdw-fontify-tex ()
2015   (setq ispell-parser 'tex)
2016   (turn-on-reftex)
2017
2018   ;; Don't make maths into a string.
2019   (modify-syntax-entry ?$ ".")
2020   (modify-syntax-entry ?$ "." font-lock-syntax-table)
2021   (local-set-key [?$] 'self-insert-command)
2022
2023   ;; Set fill prefix.
2024   (mdw-standard-fill-prefix "\\([ \t]*%+[ \t]*\\)")
2025
2026   ;; Real fontification things.
2027   (make-local-variable 'font-lock-keywords)
2028   (setq font-lock-keywords
2029         (list
2030
2031          ;; Environment names are keywords.
2032          (list (concat "\\\\\\(begin\\|end\\|newenvironment\\)"
2033                        "{\\([^}\n]*\\)}")
2034                '(2 font-lock-keyword-face))
2035
2036          ;; Suspended environment names are keywords too.
2037          (list (concat "\\\\\\(suspend\\|resume\\)\\(\\[[^]]*\\]\\)?"
2038                        "{\\([^}\n]*\\)}")
2039                '(3 font-lock-keyword-face))
2040
2041          ;; Command names are keywords.
2042          (list "\\\\\\([^a-zA-Z@]\\|[a-zA-Z@]*\\)"
2043                '(0 font-lock-keyword-face))
2044
2045          ;; Handle @/.../ for italics.
2046          ;; (list "\\(@/\\)\\([^/]*\\)\\(/\\)"
2047          ;;       '(1 font-lock-keyword-face)
2048          ;;       '(3 font-lock-keyword-face))
2049
2050          ;; Handle @*...* for boldness.
2051          ;; (list "\\(@\\*\\)\\([^*]*\\)\\(\\*\\)"
2052          ;;       '(1 font-lock-keyword-face)
2053          ;;       '(3 font-lock-keyword-face))
2054
2055          ;; Handle @`...' for literal syntax things.
2056          ;; (list "\\(@`\\)\\([^']*\\)\\('\\)"
2057          ;;       '(1 font-lock-keyword-face)
2058          ;;       '(3 font-lock-keyword-face))
2059
2060          ;; Handle @<...> for nonterminals.
2061          ;; (list "\\(@<\\)\\([^>]*\\)\\(>\\)"
2062          ;;       '(1 font-lock-keyword-face)
2063          ;;       '(3 font-lock-keyword-face))
2064
2065          ;; Handle other @-commands.
2066          ;; (list "@\\([^a-zA-Z]\\|[a-zA-Z]*\\)"
2067          ;;       '(0 font-lock-keyword-face))
2068
2069          ;; Make sure we get comments properly.
2070          (list "%.*"
2071                '(0 font-lock-comment-face))
2072
2073          ;; Fontify TeX special characters as punctuation.
2074          (list "[$^_{}#&]"
2075                '(0 mdw-punct-face))))
2076
2077   (mdw-post-config-mode-hack))
2078
2079 ;;;--------------------------------------------------------------------------
2080 ;;; SGML hacking.
2081
2082 (defun mdw-sgml-mode ()
2083   (interactive)
2084   (sgml-mode)
2085   (mdw-standard-fill-prefix "")
2086   (make-local-variable 'sgml-delimiters)
2087   (setq sgml-delimiters
2088         '("AND" "&" "COM" "--" "CRO" "&#" "DSC" "]" "DSO" "[" "DTGC" "]"
2089           "DTGO" "[" "ERO" "&" "ETAGO" ":e" "GRPC" ")" "GRPO" "(" "LIT" "\""
2090           "LITA" "'" "MDC" ">" "MDO" "<!" "MINUS" "-" "MSC" "]]" "NESTC" "{"
2091           "NET" "}" "OPT" "?" "OR" "|" "PERO" "%" "PIC" ">" "PIO" "<?"
2092           "PLUS" "+" "REFC" "." "REP" "*" "RNI" "#" "SEQ" "," "STAGO" ":"
2093           "TAGC" "." "VI" "=" "MS-START" "<![" "MS-END" "]]>"
2094           "XML-ECOM" "-->" "XML-PIC" "?>" "XML-SCOM" "<!--" "XML-TAGCE" "/>"
2095           "NULL" ""))
2096   (setq major-mode 'mdw-sgml-mode)
2097   (setq mode-name "[mdw] SGML")
2098   (run-hooks 'mdw-sgml-mode-hook))
2099
2100 ;;;--------------------------------------------------------------------------
2101 ;;; Shell scripts.
2102
2103 (defun mdw-setup-sh-script-mode ()
2104
2105   ;; Fetch the shell interpreter's name.
2106   (let ((shell-name sh-shell-file))
2107
2108     ;; Try reading the hash-bang line.
2109     (save-excursion
2110       (goto-char (point-min))
2111       (if (looking-at "#![ \t]*\\([^ \t\n]*\\)")
2112           (setq shell-name (match-string 1))))
2113
2114     ;; Now try to set the shell.
2115     ;;
2116     ;; Don't let `sh-set-shell' bugger up my script.
2117     (let ((executable-set-magic #'(lambda (s &rest r) s)))
2118       (sh-set-shell shell-name)))
2119
2120   ;; Now enable my keys and the fontification.
2121   (mdw-misc-mode-config)
2122
2123   ;; Set the indentation level correctly.
2124   (setq sh-indentation 2)
2125   (setq sh-basic-offset 2))
2126
2127 ;;;--------------------------------------------------------------------------
2128 ;;; Emacs shell mode.
2129
2130 (defun mdw-eshell-prompt ()
2131   (let ((left "[") (right "]"))
2132     (when (= (user-uid) 0)
2133       (setq left "«" right "»"))
2134     (concat left
2135             (save-match-data
2136               (replace-regexp-in-string "\\..*$" "" (system-name)))
2137             " "
2138             (let* ((pwd (eshell/pwd)) (npwd (length pwd))
2139                    (home (expand-file-name "~")) (nhome (length home)))
2140               (if (and (>= npwd nhome)
2141                        (or (= nhome npwd)
2142                            (= (elt pwd nhome) ?/))
2143                        (string= (substring pwd 0 nhome) home))
2144                   (concat "~" (substring pwd (length home)))
2145                 pwd))
2146             right)))
2147 (setq eshell-prompt-function 'mdw-eshell-prompt)
2148 (setq eshell-prompt-regexp "^\\[[^]>]+\\(\\]\\|>>?\\)")
2149
2150 (defun eshell/e (file) (find-file file) nil)
2151 (defun eshell/ee (file) (find-file-other-window file) nil)
2152 (defun eshell/w3m (url) (w3m-goto-url url) nil)
2153
2154 (mdw-define-face eshell-prompt (t :weight bold))
2155 (mdw-define-face eshell-ls-archive (t :weight bold :foreground "red"))
2156 (mdw-define-face eshell-ls-backup (t :foreground "lightgrey" :slant italic))
2157 (mdw-define-face eshell-ls-product (t :foreground "lightgrey" :slant italic))
2158 (mdw-define-face eshell-ls-clutter (t :foreground "lightgrey" :slant italic))
2159 (mdw-define-face eshell-ls-executable (t :weight bold))
2160 (mdw-define-face eshell-ls-directory (t :foreground "cyan" :weight bold))
2161 (mdw-define-face eshell-ls-readonly (t nil))
2162 (mdw-define-face eshell-ls-symlink (t :foreground "cyan"))
2163
2164 ;;;--------------------------------------------------------------------------
2165 ;;; Messages-file mode.
2166
2167 (defun messages-mode-guts ()
2168   (setq messages-mode-syntax-table (make-syntax-table))
2169   (set-syntax-table messages-mode-syntax-table)
2170   (modify-syntax-entry ?0 "w" messages-mode-syntax-table)
2171   (modify-syntax-entry ?1 "w" messages-mode-syntax-table)
2172   (modify-syntax-entry ?2 "w" messages-mode-syntax-table)
2173   (modify-syntax-entry ?3 "w" messages-mode-syntax-table)
2174   (modify-syntax-entry ?4 "w" messages-mode-syntax-table)
2175   (modify-syntax-entry ?5 "w" messages-mode-syntax-table)
2176   (modify-syntax-entry ?6 "w" messages-mode-syntax-table)
2177   (modify-syntax-entry ?7 "w" messages-mode-syntax-table)
2178   (modify-syntax-entry ?8 "w" messages-mode-syntax-table)
2179   (modify-syntax-entry ?9 "w" messages-mode-syntax-table)
2180   (make-local-variable 'comment-start)
2181   (make-local-variable 'comment-end)
2182   (make-local-variable 'indent-line-function)
2183   (setq indent-line-function 'indent-relative)
2184   (mdw-standard-fill-prefix "\\([ \t]*\\(;\\|/?\\*\\)+[ \t]*\\)")
2185   (make-local-variable 'font-lock-defaults)
2186   (make-local-variable 'messages-mode-keywords)
2187   (let ((keywords
2188          (mdw-regexps "array" "bitmap" "callback" "docs[ \t]+enum"
2189                       "export" "enum" "fixed-octetstring" "flags"
2190                       "harmless" "map" "nested" "optional"
2191                       "optional-tagged" "package" "primitive"
2192                       "primitive-nullfree" "relaxed[ \t]+enum"
2193                       "set" "table" "tagged-optional"   "union"
2194                       "variadic" "vector" "version" "version-tag")))
2195     (setq messages-mode-keywords
2196           (list
2197            (list (concat "\\<\\(" keywords "\\)\\>:")
2198                  '(0 font-lock-keyword-face))
2199            '("\\([-a-zA-Z0-9]+:\\)" (0 font-lock-warning-face))
2200            '("\\(\\<[a-z][-_a-zA-Z0-9]*\\)"
2201              (0 font-lock-variable-name-face))
2202            '("\\<\\([0-9]+\\)\\>" (0 mdw-number-face))
2203            '("\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2204              (0 mdw-punct-face)))))
2205   (setq font-lock-defaults
2206         '(messages-mode-keywords nil nil nil nil))
2207   (run-hooks 'messages-file-hook))
2208
2209 (defun messages-mode ()
2210   (interactive)
2211   (fundamental-mode)
2212   (setq major-mode 'messages-mode)
2213   (setq mode-name "Messages")
2214   (messages-mode-guts)
2215   (modify-syntax-entry ?# "<" messages-mode-syntax-table)
2216   (modify-syntax-entry ?\n ">" messages-mode-syntax-table)
2217   (setq comment-start "# ")
2218   (setq comment-end "")
2219   (run-hooks 'messages-mode-hook))
2220
2221 (defun cpp-messages-mode ()
2222   (interactive)
2223   (fundamental-mode)
2224   (setq major-mode 'cpp-messages-mode)
2225   (setq mode-name "CPP Messages")
2226   (messages-mode-guts)
2227   (modify-syntax-entry ?* ". 23" messages-mode-syntax-table)
2228   (modify-syntax-entry ?/ ". 14" messages-mode-syntax-table)
2229   (setq comment-start "/* ")
2230   (setq comment-end " */")
2231   (let ((preprocessor-keywords
2232          (mdw-regexps "assert" "define" "elif" "else" "endif" "error"
2233                       "ident" "if" "ifdef" "ifndef" "import" "include"
2234                       "line" "pragma" "unassert" "undef" "warning")))
2235     (setq messages-mode-keywords
2236           (append (list (list (concat "^[ \t]*\\#[ \t]*"
2237                                       "\\(include\\|import\\)"
2238                                       "[ \t]*\\(<[^>]+\\(>\\|\\)\\)")
2239                               '(2 font-lock-string-face))
2240                         (list (concat "^\\([ \t]*#[ \t]*\\(\\("
2241                                       preprocessor-keywords
2242                                       "\\)\\>\\|[0-9]+\\|$\\)\\)")
2243                               '(1 font-lock-keyword-face)))
2244                   messages-mode-keywords)))
2245   (run-hooks 'cpp-messages-mode-hook))
2246
2247 (add-hook 'messages-mode-hook 'mdw-misc-mode-config t)
2248 (add-hook 'cpp-messages-mode-hook 'mdw-misc-mode-config t)
2249 ; (add-hook 'messages-file-hook 'mdw-fontify-messages t)
2250
2251 ;;;--------------------------------------------------------------------------
2252 ;;; Messages-file mode.
2253
2254 (defvar mallow-driver-substitution-face 'mallow-driver-substitution-face
2255   "Face to use for subsittution directives.")
2256 (make-face 'mallow-driver-substitution-face)
2257 (defvar mallow-driver-text-face 'mallow-driver-text-face
2258   "Face to use for body text.")
2259 (make-face 'mallow-driver-text-face)
2260
2261 (defun mallow-driver-mode ()
2262   (interactive)
2263   (fundamental-mode)
2264   (setq major-mode 'mallow-driver-mode)
2265   (setq mode-name "Mallow driver")
2266   (setq mallow-driver-mode-syntax-table (make-syntax-table))
2267   (set-syntax-table mallow-driver-mode-syntax-table)
2268   (make-local-variable 'comment-start)
2269   (make-local-variable 'comment-end)
2270   (make-local-variable 'indent-line-function)
2271   (setq indent-line-function 'indent-relative)
2272   (mdw-standard-fill-prefix "\\([ \t]*\\(;\\|/?\\*\\)+[ \t]*\\)")
2273   (make-local-variable 'font-lock-defaults)
2274   (make-local-variable 'mallow-driver-mode-keywords)
2275   (let ((keywords
2276          (mdw-regexps "each" "divert" "file" "if"
2277                       "perl" "set" "string" "type" "write")))
2278     (setq mallow-driver-mode-keywords
2279           (list
2280            (list (concat "^%\\s *\\(}\\|\\(" keywords "\\)\\>\\).*$")
2281                  '(0 font-lock-keyword-face))
2282            (list "^%\\s *\\(#.*\\|\\)$"
2283                  '(0 font-lock-comment-face))
2284            (list "^%"
2285                  '(0 font-lock-keyword-face))
2286            (list "^|?\\(.+\\)$" '(1 mallow-driver-text-face))
2287            (list "\\${[^}]*}"
2288                  '(0 mallow-driver-substitution-face t)))))
2289   (setq font-lock-defaults
2290         '(mallow-driver-mode-keywords nil nil nil nil))
2291   (modify-syntax-entry ?\" "_" mallow-driver-mode-syntax-table)
2292   (modify-syntax-entry ?\n ">" mallow-driver-mode-syntax-table)
2293   (setq comment-start "%# ")
2294   (setq comment-end "")
2295   (run-hooks 'mallow-driver-mode-hook))
2296
2297 (add-hook 'mallow-driver-hook 'mdw-misc-mode-config t)
2298
2299 ;;;--------------------------------------------------------------------------
2300 ;;; NFast debugs.
2301
2302 (defun nfast-debug-mode ()
2303   (interactive)
2304   (fundamental-mode)
2305   (setq major-mode 'nfast-debug-mode)
2306   (setq mode-name "NFast debug")
2307   (setq messages-mode-syntax-table (make-syntax-table))
2308   (set-syntax-table messages-mode-syntax-table)
2309   (make-local-variable 'font-lock-defaults)
2310   (make-local-variable 'nfast-debug-mode-keywords)
2311   (setq truncate-lines t)
2312   (setq nfast-debug-mode-keywords
2313         (list
2314          '("^\\(NFast_\\(Connect\\|Disconnect\\|Submit\\|Wait\\)\\)"
2315            (0 font-lock-keyword-face))
2316          (list (concat "^[ \t]+\\(\\("
2317                        "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]"
2318                        "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]"
2319                        "[ \t]+\\)*"
2320                        "[0-9a-fA-F]+\\)[ \t]*$")
2321            '(0 mdw-number-face))
2322          '("^[ \t]+\.status=[ \t]+\\<\\(OK\\)\\>"
2323            (1 font-lock-keyword-face))
2324          '("^[ \t]+\.status=[ \t]+\\<\\([a-zA-Z][0-9a-zA-Z]*\\)\\>"
2325            (1 font-lock-warning-face))
2326          '("^[ \t]+\.status[ \t]+\\<\\(zero\\)\\>"
2327            (1 nil))
2328          (list (concat "^[ \t]+\\.cmd=[ \t]+"
2329                        "\\<\\([a-zA-Z][0-9a-zA-Z]*\\)\\>")
2330            '(1 font-lock-keyword-face))
2331          '("-?\\<\\([0-9]+\\|0x[0-9a-fA-F]+\\)\\>" (0 mdw-number-face))
2332          '("^\\([ \t]+[a-z0-9.]+\\)" (0 font-lock-variable-name-face))
2333          '("\\<\\([a-z][a-z0-9.]+\\)\\>=" (1 font-lock-variable-name-face))
2334          '("\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)" (0 mdw-punct-face))))
2335   (setq font-lock-defaults
2336         '(nfast-debug-mode-keywords nil nil nil nil))
2337   (run-hooks 'nfast-debug-mode-hook))
2338
2339 ;;;--------------------------------------------------------------------------
2340 ;;; Other languages.
2341
2342 ;; Smalltalk.
2343
2344 (defun mdw-setup-smalltalk ()
2345   (and mdw-auto-indent
2346        (local-set-key "\C-m" 'smalltalk-newline-and-indent))
2347   (make-local-variable 'mdw-auto-indent)
2348   (setq mdw-auto-indent nil)
2349   (local-set-key "\C-i" 'smalltalk-reindent))
2350
2351 (defun mdw-fontify-smalltalk ()
2352   (make-local-variable 'font-lock-keywords)
2353   (setq font-lock-keywords
2354         (list
2355          (list "\\<[A-Z][a-zA-Z0-9]*\\>"
2356                '(0 font-lock-keyword-face))
2357          (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
2358                        "[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
2359                        "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
2360                '(0 mdw-number-face))
2361          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2362                '(0 mdw-punct-face))))
2363   (mdw-post-config-mode-hack))
2364
2365 ;; Lispy languages.
2366
2367 ;; Unpleasant bodge.
2368 (unless (boundp 'slime-repl-mode-map)
2369   (setq slime-repl-mode-map (make-sparse-keymap)))
2370
2371 (defun mdw-indent-newline-and-indent ()
2372   (interactive)
2373   (indent-for-tab-command)
2374   (newline-and-indent))
2375
2376 (eval-after-load "cl-indent"
2377   '(progn
2378      (mapc #'(lambda (pair)
2379                (put (car pair)
2380                     'common-lisp-indent-function
2381                     (cdr pair)))
2382       '((destructuring-bind . ((&whole 4 &rest 1) 4 &body))
2383         (multiple-value-bind . ((&whole 4 &rest 1) 4 &body))))))
2384
2385 (defun mdw-common-lisp-indent ()
2386   (make-local-variable 'lisp-indent-function)
2387   (setq lisp-indent-function 'common-lisp-indent-function))
2388
2389 (setq lisp-simple-loop-indentation 2
2390       lisp-loop-keyword-indentation 6
2391       lisp-loop-forms-indentation 6)
2392
2393 (defun mdw-fontify-lispy ()
2394
2395   ;; Set fill prefix.
2396   (mdw-standard-fill-prefix "\\([ \t]*;+[ \t]*\\)")
2397
2398   ;; Not much fontification needed.
2399   (make-local-variable 'font-lock-keywords)
2400   (setq font-lock-keywords
2401         (list
2402          (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
2403                '(0 mdw-punct-face))))
2404
2405   (mdw-post-config-mode-hack))
2406
2407 (defun comint-send-and-indent ()
2408   (interactive)
2409   (comint-send-input)
2410   (and mdw-auto-indent
2411        (indent-for-tab-command)))
2412
2413 (defun mdw-setup-m4 ()
2414   (mdw-standard-fill-prefix "\\([ \t]*\\(?:#+\\|\\<dnl\\>\\)[ \t]*\\)"))
2415
2416 ;;;--------------------------------------------------------------------------
2417 ;;; Text mode.
2418
2419 (defun mdw-text-mode ()
2420   (setq fill-column 72)
2421   (flyspell-mode t)
2422   (mdw-standard-fill-prefix
2423    "\\([ \t]*\\([>#|:] ?\\)*[ \t]*\\)" 3)
2424   (auto-fill-mode 1))
2425
2426 ;;;--------------------------------------------------------------------------
2427 ;;; Outline and hide/show modes.
2428
2429 (defun mdw-outline-collapse-all ()
2430   "Completely collapse everything in the entire buffer."
2431   (interactive)
2432   (save-excursion
2433     (goto-char (point-min))
2434     (while (< (point) (point-max))
2435       (hide-subtree)
2436       (forward-line))))
2437
2438 (setq hs-hide-comments-when-hiding-all nil)
2439
2440 (defadvice hs-hide-all (after hide-first-comment activate)
2441   (save-excursion (hs-hide-initial-comment-block)))
2442
2443 ;;;--------------------------------------------------------------------------
2444 ;;; Shell mode.
2445
2446 (defun mdw-sh-mode-setup ()
2447   (local-set-key [?\C-a] 'comint-bol)
2448   (add-hook 'comint-output-filter-functions
2449             'comint-watch-for-password-prompt))
2450
2451 (defun mdw-term-mode-setup ()
2452   (setq term-prompt-regexp shell-prompt-pattern)
2453   (make-local-variable 'mouse-yank-at-point)
2454   (make-local-variable 'transient-mark-mode)
2455   (setq mouse-yank-at-point t)
2456   (auto-fill-mode -1)
2457   (setq tab-width 8))
2458
2459 (defun term-send-meta-right () (interactive) (term-send-raw-string "\e\e[C"))
2460 (defun term-send-meta-left  () (interactive) (term-send-raw-string "\e\e[D"))
2461 (defun term-send-ctrl-uscore () (interactive) (term-send-raw-string "\C-_"))
2462 (defun term-send-meta-meta-something ()
2463   (interactive)
2464   (term-send-raw-string "\e\e")
2465   (term-send-raw))
2466 (eval-after-load 'term
2467   '(progn
2468      (define-key term-raw-map [?\e ?\e] nil)
2469      (define-key term-raw-map [?\e ?\e t] 'term-send-meta-meta-something)
2470      (define-key term-raw-map [?\C-/] 'term-send-ctrl-uscore)
2471      (define-key term-raw-map [M-right] 'term-send-meta-right)
2472      (define-key term-raw-map [?\e ?\M-O ?C] 'term-send-meta-right)
2473      (define-key term-raw-map [M-left] 'term-send-meta-left)
2474      (define-key term-raw-map [?\e ?\M-O ?D] 'term-send-meta-left)))
2475
2476 ;;;--------------------------------------------------------------------------
2477 ;;; Inferior Emacs Lisp.
2478
2479 (setq comint-prompt-read-only t)
2480
2481 (eval-after-load "comint"
2482   '(progn
2483      (define-key comint-mode-map "\C-w" 'comint-kill-region)
2484      (define-key comint-mode-map [C-S-backspace] 'comint-kill-whole-line)))
2485
2486 (eval-after-load "ielm"
2487   '(progn
2488      (define-key ielm-map "\C-w" 'comint-kill-region)
2489      (define-key ielm-map [C-S-backspace] 'comint-kill-whole-line)))
2490
2491 ;;;----- That's all, folks --------------------------------------------------
2492
2493 (provide 'dot-emacs)