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