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