Merge branch 'master' of git+ssh://ponder.ncipher.com/~mwooding/etc/profile
[profile] / dot-emacs.el
CommitLineData
f617db13
MW
1;;; -*-emacs-lisp-*-
2;;;
3;;; $Id$
4;;;
5;;; Functions and macros for .emacs
6;;;
7;;; (c) 2004 Mark Wooding
8;;;
9
10;;;----- Licensing notice ---------------------------------------------------
11;;;
12;;; This program is free software; you can redistribute it and/or modify
13;;; it under the terms of the GNU General Public License as published by
14;;; the Free Software Foundation; either version 2 of the License, or
15;;; (at your option) any later version.
16;;;
17;;; This program is distributed in the hope that it will be useful,
18;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;;; GNU General Public License for more details.
21;;;
22;;; You should have received a copy of the GNU General Public License
23;;; along with this program; if not, write to the Free Software Foundation,
24;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26;;;----- Some general utilities ---------------------------------------------
27
28;; --- Some error trapping ---
29;;
30;; If individual bits of this file go tits-up, we don't particularly want
31;; the whole lot to stop right there and then, because it's bloody annoying.
32
33(defmacro trap (&rest forms)
34 "Execute FORMS without allowing errors to propagate outside."
35 `(condition-case err
36 ,(if (cdr forms) (cons 'progn forms) (car forms))
37 (error (message "Error (trapped): %s" (error-message-string err)))))
38
f141fe0f
MW
39;; --- Configuration reading ---
40
41(defvar mdw-config nil)
42(defun mdw-config (sym)
43 "Read the configuration variable named SYM."
44 (unless mdw-config
45 (setq mdw-config (with-temp-buffer
46 (insert-file-contents "~/.mdw.conf")
47 (replace-regexp "^[ \t]*\\(#.*\\|\\)\n" ""
48 nil (point-min) (point-max))
49 (replace-regexp (concat "^[ \t]*"
50 "\\([-a-zA-Z0-9_.]*\\)"
51 "[ \t]*=[ \t]*"
52 "\\(.*[^ \t\n]\\|\\)"
53 "[ \t]**\\(\n\\|$\\)")
54 "(\\1 . \"\\2\") "
55 nil (point-min) (point-max))
56 (car (read-from-string
57 (concat "(" (buffer-string) ")"))))))
58 (cdr (assq sym mdw-config)))
59
cb6e2cd1
MW
60;; --- Is an Emacs library available? ---
61
62(defun library-exists-p (name)
63 "Return non-nil if NAME.el (or NAME.elc) is somewhere on the Emacs load
64path. The non-nil value is the filename we found for the library."
65 (let ((path load-path) elt (foundp nil))
66 (while (and path (not foundp))
67 (setq elt (car path))
68 (setq path (cdr path))
69 (setq foundp (or (let ((file (concat elt "/" name ".elc")))
70 (and (file-exists-p file) file))
71 (let ((file (concat elt "/" name ".el")))
72 (and (file-exists-p file) file)))))
73 foundp))
74
75(defun maybe-autoload (symbol file &optional docstring interactivep type)
76 "Set an autoload if the file actually exists."
77 (and (library-exists-p file)
78 (autoload symbol file docstring interactivep type)))
79
f617db13
MW
80;; --- Splitting windows ---
81
82(defconst mdw-scrollbar-width (if window-system 6 1)
83 "Guessed width of scroll bar.")
84(defun mdw-divvy-window (&optional w)
85 "Split a wide window into appropriate widths."
86 (interactive)
87 (or w (setq w 78))
88 (let ((win (selected-window))
89 (c (/ (+ (window-width) mdw-scrollbar-width)
90 (+ w mdw-scrollbar-width))))
91 (while (> c 1)
92 (setq c (1- c))
93 (split-window-horizontally (+ w mdw-scrollbar-width))
94 (other-window 1))
95 (select-window win)))
96
97;; --- Functions for sexp diary entries ---
98
99(defun mdw-weekday (l)
100 "Return non-nil if `date' falls on one of the days of the week in L.
101
102L is a list of day numbers (from 0 to 6 for Sunday through to Saturday) or
103symbols `sunday', `monday', etc. (or a mixture). If the date stored in
104`date' falls on a listed day, then the function returns non-nil."
105 (let ((d (calendar-day-of-week date)))
106 (or (memq d l)
107 (memq (nth d '(sunday monday tuesday wednesday
108 thursday friday saturday)) l))))
109
110(defun mdw-todo (&optional when)
111 "Return non-nil today, or on WHEN, whichever is later."
112 (let ((w (calendar-absolute-from-gregorian (calendar-current-date)))
113 (d (calendar-absolute-from-gregorian date)))
114 (if when
115 (setq w (max w (calendar-absolute-from-gregorian
116 (cond
117 ((not european-calendar-style)
118 when)
119 ((> (car when) 100)
120 (list (nth 1 when)
121 (nth 2 when)
122 (nth 0 when)))
123 (t
124 (list (nth 1 when)
125 (nth 0 when)
126 (nth 2 when))))))))
127 (eq w d)))
128
129;;;----- Utility functions --------------------------------------------------
130
131;; --- mdw-uniquify-alist ---
132
133(defun mdw-uniquify-alist (&rest alists)
134
135 "Return the concatenation of the ALISTS with duplicate elements removed.
136
137The first association with a given key prevails; others are ignored. The
138input lists are not modified, although they'll probably become garbage."
139
140 (and alists
141 (let ((start-list (cons nil nil)))
142 (mdw-do-uniquify start-list
143 start-list
144 (car alists)
145 (cdr alists)))))
146
147;; --- mdw-do-uniquify ---
148;;
149;; The DONE argument is a list whose first element is `nil'. It contains the
150;; uniquified alist built so far. The leading `nil' is stripped off at the
151;; end of the operation; it's only there so that DONE always references a
152;; cons cell. END refers to the final cons cell in the DONE list; it is
153;; modified in place each time to avoid the overheads of `append'ing all the
154;; time. The L argument is the alist we're currently processing; the
155;; remaining alists are given in REST.
156
157(defun mdw-do-uniquify (done end l rest)
158 "A helper function for mdw-uniquify-alist."
159
160 ;; --- There are several different cases to deal with here ---
161
162 (cond
163
164 ;; --- Current list isn't empty ---
165 ;;
166 ;; Add the first item to the DONE list if there's not an item with the
167 ;; same KEY already there.
168
169 (l (or (assoc (car (car l)) done)
170 (progn
171 (setcdr end (cons (car l) nil))
172 (setq end (cdr end))))
173 (mdw-do-uniquify done end (cdr l) rest))
174
175 ;; --- The list we were working on is empty ---
176 ;;
177 ;; Shunt the next list into the current list position and go round again.
178
179 (rest (mdw-do-uniquify done end (car rest) (cdr rest)))
180
181 ;; --- Everything's done ---
182 ;;
183 ;; Remove the leading `nil' from the DONE list and return it. Finished!
184
185 (t (cdr done))))
186
187;; --- Insert a date ---
188
189(defun date ()
190 "Insert the current date in a pleasing way."
191 (interactive)
192 (insert (save-excursion
193 (let ((buffer (get-buffer-create "*tmp*")))
194 (unwind-protect (progn (set-buffer buffer)
195 (erase-buffer)
196 (shell-command "date +%Y-%m-%d" t)
197 (goto-char (mark))
198 (delete-backward-char 1)
199 (buffer-string))
200 (kill-buffer buffer))))))
201
202;; --- UUencoding ---
203
204(defun uuencode (file &optional name)
205 "UUencodes a file, maybe calling it NAME, into the current buffer."
206 (interactive "fInput file name: ")
207
208 ;; --- If NAME isn't specified, then guess from the filename ---
209
210 (if (not name)
211 (setq name
212 (substring file
213 (or (string-match "[^/]*$" file) 0))))
214
215 (print (format "uuencode `%s' `%s'" file name))
216
217 ;; --- Now actually do the thing ---
218
219 (call-process "uuencode" file t nil name))
220
221(defvar np-file "~/.np"
222 "*Where the `now-playing' file is.")
223
224(defun np (&optional arg)
225 "Grabs a `now-playing' string."
226 (interactive)
227 (save-excursion
228 (or arg (progn
229 (goto-char (point-max))
230 (insert "\nNP: ")
231 (insert-file np-file)))))
232
233(trap
234 (require 'tramp)
235 (require 'autorevert)
236 (defun mdw-check-autorevert ()
237 (if (and (buffer-file-name)
238 (tramp-tramp-file-p (buffer-file-name)))
239 (unless global-auto-revert-ignore-buffer
240 (setq global-auto-revert-ignore-buffer 'tramp))
241 (if (eq global-auto-revert-ignore-buffer 'tramp)
242 (setq global-auto-revert-ignore-buffer nil))))
243 (defadvice find-file (after mdw-autorevert activate)
244 (mdw-check-autorevert))
245 (defadvice write-file (after mdw-autorevert activate)
246 (mdw-check-autorevert)))
247
248(defun mdwmail-mode ()
249 "Major mode for editing news and mail messages from external programs
250Not much right now. Just support for doing MailCrypt stuff."
251 (interactive)
252 (kill-all-local-variables)
253 (use-local-map text-mode-map)
254 (setq local-abbrev-table text-mode-abbrev-table)
255 (setq major-mode 'mdwmail-mode)
256 (setq mode-name "[mdw] mail")
257 (make-local-variable 'paragraph-separate)
258 (make-local-variable 'paragraph-start)
259 (setq paragraph-start (concat "[ \t]*[-_][-_][-_]+$\\|^-- \\|-----\\|"
260 paragraph-start))
261 (setq paragraph-separate (concat "[ \t]*[-_][-_][-_]+$\\|^-- \\|-----\\|"
262 paragraph-separate))
263 (run-hooks 'text-mode-hook 'mdwmail-mode-hook 'mail-setup-hook))
264
265;; --- How to encrypt in mdwmail ---
266
267(defun mdwmail-mc-encrypt (&optional recip scm start end from sign)
268 (or start
269 (setq start (save-excursion
270 (goto-char (point-min))
271 (or (search-forward "\n\n" nil t) (point-min)))))
272 (or end
273 (setq end (point-max)))
274 (mc-encrypt-generic recip scm start end from sign))
275
276;; --- How to sign in mdwmail ---
277
278(defun mdwmail-mc-sign (key scm start end uclr)
279 (or start
280 (setq start (save-excursion
281 (goto-char (point-min))
282 (or (search-forward "\n\n" nil t) (point-min)))))
283 (or end
284 (setq end (point-max)))
285 (mc-sign-generic key scm start end uclr))
286
287;; --- Some signature mangling ---
288
289(defun mdwmail-mangle-signature ()
290 (save-excursion
291 (goto-char (point-min))
292 (perform-replace "\n-- \n" "\n-- " nil nil nil)))
293(add-hook 'mail-setup-hook 'mdwmail-mangle-signature)
294
295;;;----- Paragraph filling --------------------------------------------------
296
297;; --- Useful variables ---
298
299(defvar mdw-fill-prefix nil
300 "*Used by `mdw-line-prefix' and `mdw-fill-paragraph'. If there's
301no fill prefix currently set (by the `fill-prefix' variable) and there's
302a match from one of the regexps here, it gets used to set the fill-prefix
303for the current operation.
304
305The variable is a list of items of the form `REGEXP . PREFIX'; if the
306REGEXP matches, the PREFIX is used to set the fill prefix. It in turn is
307a list of things:
308
309 STRING -- insert a literal string
310 (match . N) -- insert the thing matched by bracketed subexpression N
311 (pad . N) -- a string of whitespace the same width as subexpression N
312 (expr . FORM) -- the result of evaluating FORM")
313
314(make-variable-buffer-local 'mdw-fill-prefix)
315
316(defvar mdw-hanging-indents
317 "\\(\\(\\([*o]\\|--\\|[0-9]+\\.\\|\\[[0-9]+\\]\\|([a-zA-Z])\\)[ \t]+\\)?\\)"
318 "*Standard regular expression matching things which might be part of a
319hanging indent. This is mainly useful in `auto-fill-mode'.")
320
321;; --- Setting things up ---
322
323(fset 'mdw-do-auto-fill (symbol-function 'do-auto-fill))
324
325;; --- Utility functions ---
326
327(defun mdw-tabify (s)
328 "Tabify the string S. This is a horrid hack."
329 (save-excursion
330 (save-match-data
331 (let (start end)
332 (beginning-of-line)
333 (setq start (point-marker))
334 (insert s "\n")
335 (setq end (point-marker))
336 (tabify start end)
337 (setq s (buffer-substring start (1- end)))
338 (delete-region start end)
339 (set-marker start nil)
340 (set-marker end nil)
341 s))))
342
343(defun mdw-examine-fill-prefixes (l)
344 "Given a list of dynamic fill prefixes, pick one which matches context and
345return the static fill prefix to use. Point must be at the start of a line,
346and match data must be saved."
347 (cond ((not l) nil)
348 ((looking-at (car (car l)))
349 (mdw-tabify (apply (function concat)
350 (mapcar (function mdw-do-prefix-match)
351 (cdr (car l))))))
352 (t (mdw-examine-fill-prefixes (cdr l)))))
353
354(defun mdw-maybe-car (p)
355 "If P is a pair, return (car P), otherwise just return P."
356 (if (consp p) (car p) p))
357
358(defun mdw-padding (s)
359 "Return a string the same width as S but made entirely from whitespace."
360 (let* ((l (length s)) (i 0) (n (make-string l ? )))
361 (while (< i l)
362 (if (= 9 (aref s i))
363 (aset n i 9))
364 (setq i (1+ i)))
365 n))
366
367(defun mdw-do-prefix-match (m)
368 "Expand a dynamic prefix match element. See `mdw-fill-prefix' for
369details."
370 (cond ((not (consp m)) (format "%s" m))
371 ((eq (car m) 'match) (match-string (mdw-maybe-car (cdr m))))
372 ((eq (car m) 'pad) (mdw-padding (match-string
373 (mdw-maybe-car (cdr m)))))
374 ((eq (car m) 'eval) (eval (cdr m)))
375 (t "")))
376
377(defun mdw-choose-dynamic-fill-prefix ()
378 "Work out the dynamic fill prefix based on the variable `mdw-fill-prefix'."
379 (cond ((and fill-prefix (not (string= fill-prefix ""))) fill-prefix)
380 ((not mdw-fill-prefix) fill-prefix)
381 (t (save-excursion
382 (beginning-of-line)
383 (save-match-data
384 (mdw-examine-fill-prefixes mdw-fill-prefix))))))
385
386(defun do-auto-fill ()
387 "Handle auto-filling, working out a dynamic fill prefix in the case where
388there isn't a sensible static one."
389 (let ((fill-prefix (mdw-choose-dynamic-fill-prefix)))
390 (mdw-do-auto-fill)))
391
392(defun mdw-fill-paragraph ()
393 "Fill paragraph, getting a dynamic fill prefix."
394 (interactive)
395 (let ((fill-prefix (mdw-choose-dynamic-fill-prefix)))
396 (fill-paragraph nil)))
397
398(defun mdw-standard-fill-prefix (rx &optional mat)
399 "Set the dynamic fill prefix, handling standard hanging indents and stuff.
400This is just a short-cut for setting the thing by hand, and by design it
401doesn't cope with anything approximating a complicated case."
402 (setq mdw-fill-prefix
403 `((,(concat rx mdw-hanging-indents)
404 (match . 1)
405 (pad . ,(or mat 2))))))
406
407;;;----- Other common declarations ------------------------------------------
408
409(defun mdw-set-frame-transparency (&optional n)
410 (interactive "P")
411 (let* ((alist (frame-parameters))
412 (trans (assq 'transparency alist)))
413 (if trans
414 (rplacd trans (not (if n (zerop n) (cdr trans))))
415 (setq trans (cons 'transparency (not (equal 0 n)))))
416 (modify-frame-parameters (selected-frame) (list trans))))
417
418;; --- Mouse wheel support ---
419
420(defconst mdw-wheel-scroll-amount 15)
421(defun mdw-wheel-up (click)
422 (interactive "@e")
423 (mdw-wheel-scroll click (function scroll-down)))
424(defun mdw-wheel-down (click)
425 (interactive "@e")
426 (mdw-wheel-scroll click (function scroll-up)))
427
428(defun mdw-wheel-scroll (click func)
429 (let ((win (selected-window)))
430 (unwind-protect
431 (progn
432 (select-window (posn-window (event-start click)))
433 (let ((arg 2))
434 (funcall func (/ (window-height) 2))))
435 (select-window win))))
436
437;; --- Going backwards ---
438
439(defun other-window-backwards (arg)
440 (interactive "p")
441 (other-window (- arg)))
442
443;; --- Common mode settings ---
444
445(defvar mdw-auto-indent t
446 "Whether to indent automatically after a newline.")
447
448(defun mdw-misc-mode-config ()
449 (and mdw-auto-indent
450 (cond ((eq major-mode 'lisp-mode)
451 (local-set-key "\C-m" 'mdw-indent-newline-and-indent))
452 ((eq major-mode 'slime-repl-mode) nil)
453 (t
454 (local-set-key "\C-m" 'newline-and-indent))))
455 (local-set-key [C-return] 'newline)
456 (local-set-key [?\;] 'self-insert-command)
457 (local-set-key [?\#] 'self-insert-command)
458 (local-set-key [?\"] 'self-insert-command)
459 (setq comment-column 40)
460 (auto-fill-mode 1)
461 (setq fill-column 77)
462 (mdw-set-font))
463
464;; --- Set up all sorts of faces ---
465
466(defvar mdw-set-font nil)
467
468(defvar mdw-punct-face 'mdw-punct-face "Face to use for punctuation")
469(make-face 'mdw-punct-face)
470(defvar mdw-number-face 'mdw-number-face "Face to use for numbers")
471(make-face 'mdw-number-face)
472
473;;;----- General fontification ----------------------------------------------
474
475(defun mdw-set-fonts (frame ff)
476 (if ff (progn (set-face-attribute (caar ff) frame
477 :family 'unspecified
478 :width 'unspecified
479 :height 'unspecified
480 :weight 'unspecified
481 :slant 'unspecified
482 :foreground 'unspecified
483 :background 'unspecified
484 :underline 'unspecified
485 :overline 'unspecified
486 :strike-through 'unspecified
487 :box 'unspecified
488 :inverse-video 'unspecified
489 :stipple 'unspecified
490; :font 'unspecified
491 :inherit 'unspecified
492 )
493 (apply 'set-face-attribute (caar ff) frame (cdar ff))
494 (mdw-set-fonts frame (cdr ff)))))
495
496(defun mdw-do-set-font (&optional frame)
497 (interactive)
498 (mdw-set-fonts (and (boundp 'frame) frame) `(
499 (default :foreground "white" :background "black"
500 ,@(cond ((eq window-system 'w32)
501 '(:family "courier new" :height 85))
502 ((eq window-system 'x)
503 '(:family "misc-fixed" :width semi-condensed))))
504 (modeline :foreground "blue" :background "yellow"
505 :box (:line-width 1 :style released-button))
506 (scroll-bar :foreground "black" :background "lightgrey")
507 (fringe :foreground "yellow" :background "grey30")
508 (show-paren-match-face :background "darkgreen")
509 (show-paren-mismatch-face :background "red")
510 (font-lock-warning-face :background "red" :weight bold)
511 (highlight :background "DarkSeaGreen4")
512 (holiday-face :background "red")
513 (calendar-today-face :foreground "yellow" :weight bold)
514 (comint-highlight-prompt :weight bold)
515 (comint-highlight-input)
516 (font-lock-builtin-face :weight bold)
517 (font-lock-type-face :weight bold)
518 (region :background "grey30")
519 (isearch :background "palevioletred2")
520 (mdw-punct-face :foreground ,(if window-system "burlywood2" "yellow"))
521 (mdw-number-face :foreground "yellow")
522 (font-lock-function-name-face :weight bold)
523 (font-lock-variable-name-face :slant italic)
524 (font-lock-comment-face
525 :foreground ,(if window-system "SeaGreen1" "green")
526 :slant italic)
527 (font-lock-string-face :foreground ,(if window-system "SkyBlue1" "cyan"))
528 (font-lock-keyword-face :weight bold)
529 (font-lock-constant-face :weight bold)
530 (font-lock-reference-face :weight bold)
531 (woman-bold-face :weight bold)
532 (woman-italic-face :slant italic)
533 (diff-header-face :foreground "skyblue1")
534 (diff-index-face :weight bold)
535 (diff-file-header-face)
536 (diff-context-face :foreground "grey70")
537 (diff-added-face :foreground "white")
538 (diff-removed-face :foreground "white" :slant italic)
539 (whizzy-slice-face :background "grey10")
540 (whizzy-error-face :background "darkred")
541)))
542
543(defun mdw-set-font ()
544 (trap
545 (turn-on-font-lock)
546 (if (not mdw-set-font)
547 (progn
548 (setq mdw-set-font t)
549 (mdw-do-set-font nil)))))
550
551;;;----- C programming configuration ----------------------------------------
552
553;; --- Linux kernel hacking ---
554
555(defvar linux-c-mode-hook)
556
557(defun linux-c-mode ()
558 (interactive)
559 (c-mode)
560 (setq major-mode 'linux-c-mode)
561 (setq mode-name "Linux C")
562 (run-hooks 'linux-c-mode-hook))
563
564;; --- Make C indentation nice ---
565
566(defun mdw-c-style ()
567 (c-add-style "[mdw] C and C++ style"
568 '((c-basic-offset . 2)
569 (c-tab-always-indent . nil)
570 (comment-column . 40)
571 (c-class-key . "class")
572 (c-offsets-alist (substatement-open . 0)
573 (label . 0)
574 (case-label . +)
575 (access-label . -)
576 (inclass . ++)
577 (inline-open . ++)
578 (statement-cont . 0)
579 (statement-case-intro . +)))
580 t))
581
582(defun mdw-fontify-c-and-c++ ()
583
584 ;; --- Fiddle with some syntax codes ---
585
586 (modify-syntax-entry ?_ "w")
587 (modify-syntax-entry ?* ". 23")
588 (modify-syntax-entry ?/ ". 124b")
589 (modify-syntax-entry ?\n "> b")
590
591 ;; --- Other stuff ---
592
593 (mdw-c-style)
594 (setq c-hanging-comment-ender-p nil)
595 (setq c-backslash-column 72)
596 (setq c-label-minimum-indentation 0)
597 (setq comment-start "/* ")
598 (setq comment-end " */")
599 (setq mdw-fill-prefix
600 `((,(concat "\\([ \t]*/?\\)"
601 "\\([\*/][ \t]*\\)"
602 "\\([A-Za-z]+:[ \t]*\\)?"
603 mdw-hanging-indents)
604 (pad . 1) (match . 2) (pad . 3) (pad . 4))))
605
606 ;; --- Now define things to be fontified ---
607
608 (make-local-variable 'font-lock-keywords)
609 (let ((c-keywords
610 (make-regexp '(
611 ;; "and" ;C++
612 ;; "and_eq" ;C++
613 "asm" ;K&R, GCC
614 "auto" ;K&R, C89
615 ;; "bitand" ;C++
616 ;; "bitor" ;C++
617 "bool" ;C++, C9X macro
618 "break" ;K&R, C89
619 "case" ;K&R, C89
620 "catch" ;C++
621 "char" ;K&R, C89
622 "class" ;C++
623 "complex" ;C9X macro, C++ template type
624 ;; "compl" ;C++
625 "const" ;C89
626 "const_cast" ;C++
627 "continue" ;K&R, C89
628 "defined" ;C89 preprocessor
629 "default" ;K&R, C89
630 "delete" ;C++
631 "do" ;K&R, C89
632 "double" ;K&R, C89
633 "dynamic_cast" ;C++
634 "else" ;K&R, C89
635 ;; "entry" ;K&R -- never used
636 "enum" ;C89
637 "explicit" ;C++
638 ;; "export" ;C++
639 "extern" ;K&R, C89
640 "false" ;C++, C9X macro
641 "float" ;K&R, C89
642 "for" ;K&R, C89
643 "fortran" ;K&R
644 "friend" ;C++
645 "goto" ;K&R, C89
646 "if" ;K&R, C89
647 "imaginary" ;C9X macro
648 "inline" ;C++, C9X, GCC
649 "int" ;K&R, C89
650 "long" ;K&R, C89
651 "mutable" ;C++
652 "namespace" ;C++
653 "new" ;C++
654 "operator" ;C++
655 ;; "or" ;C++
656 ;; "or_eq" ;C++
657 "private" ;C++
658 "protected" ;C++
659 "public" ;C++
660 "register" ;K&R, C89
661 "reinterpret_cast" ;C++
662 "restrict" ;C9X
663 "return" ;K&R, C89
664 "short" ;K&R, C89
665 "signed" ;C89
666 "sizeof" ;K&R, C89
667 "static" ;K&R, C89
668 "static_cast" ;C++
669 "struct" ;K&R, C89
670 "switch" ;K&R, C89
671 "template" ;C++
672 "this" ;C++
673 "throw" ;C++
674 "true" ;C++, C9X macro
675 "try" ;C++
676 "this" ;C++
677 "typedef" ;C89
678 "typeid" ;C++
679 "typeof" ;GCC
680 "typename" ;C++
681 "union" ;K&R, C89
682 "unsigned" ;K&R, C89
683 "using" ;C++
684 "virtual" ;C++
685 "void" ;C89
686 "volatile" ;C89
687 "wchar_t" ;C++, C89 library type
688 "while" ;K&R, C89
689 ;; "xor" ;C++
690 ;; "xor_eq" ;C++
691 "_Bool" ;C9X
692 "_Complex" ;C9X
693 "_Imaginary" ;C9X
694 "_Pragma" ;C9X preprocessor
695 "__alignof__" ;GCC
696 "__asm__" ;GCC
697 "__attribute__" ;GCC
698 "__complex__" ;GCC
699 "__const__" ;GCC
700 "__extension__" ;GCC
701 "__imag__" ;GCC
702 "__inline__" ;GCC
703 "__label__" ;GCC
704 "__real__" ;GCC
705 "__signed__" ;GCC
706 "__typeof__" ;GCC
707 "__volatile__" ;GCC
708 )))
709 (preprocessor-keywords
710 (make-regexp '("assert" "define" "elif" "else" "endif" "error"
711 "ident" "if" "ifdef" "ifndef" "import" "include"
712 "line" "pragma" "unassert" "undef" "warning")))
713 (objc-keywords
714 (make-regexp '("class" "defs" "encode" "end" "implementation"
715 "interface" "private" "protected" "protocol" "public"
716 "selector"))))
717
718 (setq font-lock-keywords
719 (list
720 't
721
722 ;; --- Fontify include files as strings ---
723
724 (list (concat "^[ \t]*\\#[ \t]*"
725 "\\(include\\|import\\)"
726 "[ \t]*\\(<[^>]+\\(>\\|\\)\\)")
727 '(2 font-lock-string-face))
728
729 ;; --- Preprocessor directives are `references'? ---
730
731 (list (concat "^\\([ \t]*#[ \t]*\\(\\("
732 preprocessor-keywords
733 "\\)\\>\\|[0-9]+\\|$\\)\\)")
734 '(1 font-lock-keyword-face))
735
736 ;; --- Handle the keywords defined above ---
737
738 (list (concat "@\\<\\(" objc-keywords "\\)\\>")
739 '(0 font-lock-keyword-face))
740
741 (list (concat "\\<\\(" c-keywords "\\)\\>")
742 '(0 font-lock-keyword-face))
743
744 ;; --- Handle numbers too ---
745 ;;
746 ;; This looks strange, I know. It corresponds to the
747 ;; preprocessor's idea of what a number looks like, rather than
748 ;; anything sensible.
749
750 (list (concat "\\(\\<[0-9]\\|\\.[0-9]\\)"
751 "\\([Ee][+-]\\|[0-9A-Za-z_.]\\)*")
752 '(0 mdw-number-face))
753
754 ;; --- And anything else is punctuation ---
755
756 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
757 '(0 mdw-punct-face))))))
758
759;;;----- AP calc mode -------------------------------------------------------
760
761(defun apcalc-mode ()
762 (interactive)
763 (c-mode)
764 (setq major-mode 'apcalc-mode)
765 (setq mode-name "AP Calc")
766 (run-hooks 'apcalc-mode-hook))
767
768(defun mdw-fontify-apcalc ()
769
770 ;; --- Fiddle with some syntax codes ---
771
772 (modify-syntax-entry ?_ "w")
773 (modify-syntax-entry ?* ". 23")
774 (modify-syntax-entry ?/ ". 14")
775
776 ;; --- Other stuff ---
777
778 (mdw-c-style)
779 (setq c-hanging-comment-ender-p nil)
780 (setq c-backslash-column 72)
781 (setq comment-start "/* ")
782 (setq comment-end " */")
783 (setq mdw-fill-prefix
784 `((,(concat "\\([ \t]*/?\\)"
785 "\\([\*/][ \t]*\\)"
786 "\\([A-Za-z]+:[ \t]*\\)?"
787 mdw-hanging-indents)
788 (pad . 1) (match . 2) (pad . 3) (pad . 4))))
789
790 ;; --- Now define things to be fontified ---
791
792 (make-local-variable 'font-lock-keywords)
793 (let ((c-keywords
794 (make-regexp '("break" "case" "cd" "continue" "define" "default"
795 "do" "else" "exit" "for" "global" "goto" "help" "if"
796 "local" "mat" "obj" "print" "quit" "read" "return"
797 "show" "static" "switch" "while" "write"))))
798
799 (setq font-lock-keywords
800 (list
801 't
802
803 ;; --- Handle the keywords defined above ---
804
805 (list (concat "\\<\\(" c-keywords "\\)\\>")
806 '(0 font-lock-keyword-face))
807
808 ;; --- Handle numbers too ---
809 ;;
810 ;; This looks strange, I know. It corresponds to the
811 ;; preprocessor's idea of what a number looks like, rather than
812 ;; anything sensible.
813
814 (list (concat "\\(\\<[0-9]\\|\\.[0-9]\\)"
815 "\\([Ee][+-]\\|[0-9A-Za-z_.]\\)*")
816 '(0 mdw-number-face))
817
818 ;; --- And anything else is punctuation ---
819
820 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
821 '(0 mdw-punct-face))))))
822
823;;;----- Java programming configuration -------------------------------------
824
825;; --- Make indentation nice ---
826
827(defun mdw-java-style ()
828 (c-add-style "[mdw] Java style"
829 '((c-basic-offset . 2)
830 (c-tab-always-indent . nil)
831 (c-offsets-alist (substatement-open . 0)
832 (label . +)
833 (case-label . +)
834 (access-label . 0)
835 (inclass . +)
836 (statement-case-intro . +)))
837 t))
838
839;; --- Declare Java fontification style ---
840
841(defun mdw-fontify-java ()
842
843 ;; --- Other stuff ---
844
845 (mdw-java-style)
846 (modify-syntax-entry ?_ "w")
847 (setq c-hanging-comment-ender-p nil)
848 (setq c-backslash-column 72)
849 (setq comment-start "/* ")
850 (setq comment-end " */")
851 (setq mdw-fill-prefix
852 `((,(concat "\\([ \t]*/?\\)"
853 "\\([\*/][ \t]*\\)"
854 "\\([A-Za-z]+:[ \t]*\\)?"
855 mdw-hanging-indents)
856 (pad . 1) (match . 2) (pad . 3) (pad . 4))))
857
858 ;; --- Now define things to be fontified ---
859
860 (make-local-variable 'font-lock-keywords)
861 (let ((java-keywords
862 (make-regexp '("abstract" "boolean" "break" "byte" "case" "catch"
863 "char" "class" "const" "continue" "default" "do"
864 "double" "else" "extends" "final" "finally" "float"
865 "for" "goto" "if" "implements" "import" "instanceof"
866 "int" "interface" "long" "native" "new" "package"
867 "private" "protected" "public" "return" "short"
868 "static" "super" "switch" "synchronized" "this"
869 "throw" "throws" "transient" "try" "void" "volatile"
870 "while"
871
872 "false" "null" "true"))))
873
874 (setq font-lock-keywords
875 (list
876 't
877
878 ;; --- Handle the keywords defined above ---
879
880 (list (concat "\\<\\(" java-keywords "\\)\\>")
881 '(0 font-lock-keyword-face))
882
883 ;; --- Handle numbers too ---
884 ;;
885 ;; The following isn't quite right, but it's close enough.
886
887 (list (concat "\\<\\("
888 "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
889 "[0-9]+\\(\\.[0-9]*\\|\\)"
890 "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
891 "[lLfFdD]?")
892 '(0 mdw-number-face))
893
894 ;; --- And anything else is punctuation ---
895
896 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
897 '(0 mdw-punct-face))))))
898
899;;;----- Awk programming configuration --------------------------------------
900
901;; --- Make Awk indentation nice ---
902
903(defun mdw-awk-style ()
904 (c-add-style "[mdw] Awk style"
905 '((c-basic-offset . 2)
906 (c-tab-always-indent . nil)
907 (c-offsets-alist (substatement-open . 0)
908 (statement-cont . 0)
909 (statement-case-intro . +)))
910 t))
911
912;; --- Declare Awk fontification style ---
913
914(defun mdw-fontify-awk ()
915
916 ;; --- Miscellaneous fiddling ---
917
918 (modify-syntax-entry ?_ "w")
919 (mdw-awk-style)
920 (setq c-backslash-column 72)
921 (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
922
923 ;; --- Now define things to be fontified ---
924
925 (make-local-variable 'font-lock-keywords)
926 (let ((c-keywords
927 (make-regexp '("BEGIN" "END" "ARGC" "ARGIND" "ARGV" "CONVFMT"
928 "ENVIRON" "ERRNO" "FIELDWIDTHS" "FILENAME" "FNR"
929 "FS" "IGNORECASE" "NF" "NR" "OFMT" "OFS" "ORS" "RS"
930 "RSTART" "RLENGTH" "RT" "SUBSEP"
931 "atan2" "break" "close" "continue" "cos" "delete"
932 "do" "else" "exit" "exp" "fflush" "file" "for" "func"
933 "function" "gensub" "getline" "gsub" "if" "in"
934 "index" "int" "length" "log" "match" "next" "rand"
935 "return" "print" "printf" "sin" "split" "sprintf"
936 "sqrt" "srand" "strftime" "sub" "substr" "system"
937 "systime" "tolower" "toupper" "while"))))
938
939 (setq font-lock-keywords
940 (list
941 't
942
943 ;; --- Handle the keywords defined above ---
944
945 (list (concat "\\<\\(" c-keywords "\\)\\>")
946 '(0 font-lock-keyword-face))
947
948 ;; --- Handle numbers too ---
949 ;;
950 ;; The following isn't quite right, but it's close enough.
951
952 (list (concat "\\<\\("
953 "0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
954 "[0-9]+\\(\\.[0-9]*\\|\\)"
955 "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)\\)"
956 "[uUlL]*")
957 '(0 mdw-number-face))
958
959 ;; --- And anything else is punctuation ---
960
961 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
962 '(0 mdw-punct-face))))))
963
964;;;----- Perl programming style ---------------------------------------------
965
966;; --- Perl indentation style ---
967
968(setq cperl-tab-always-indent nil)
969
970(setq cperl-indent-level 2)
971(setq cperl-continued-statement-offset 2)
972(setq cperl-continued-brace-offset 0)
973(setq cperl-brace-offset -2)
974(setq cperl-brace-imaginary-offset 0)
975(setq cperl-label-offset 0)
976
977;; --- Define perl fontification style ---
978
979(defun mdw-fontify-perl ()
980
981 ;; --- Miscellaneous fiddling ---
982
983 (modify-syntax-entry ?_ "w")
984 (modify-syntax-entry ?$ "\\")
985 (modify-syntax-entry ?$ "\\" font-lock-syntax-table)
986 (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
987
988 ;; --- Now define fontification things ---
989
990 (make-local-variable 'font-lock-keywords)
991 (let ((perl-keywords
992 (make-regexp '("and" "cmp" "continue" "do" "else" "elsif" "eq"
993 "for" "foreach" "ge" "gt" "goto" "if"
994 "last" "le" "lt" "local" "my" "ne" "next" "or"
995 "package" "redo" "require" "return" "sub"
996 "undef" "unless" "until" "use" "while"))))
997
998 (setq font-lock-keywords
999 (list
1000 't
1001
1002 ;; --- Set up the keywords defined above ---
1003
1004 (list (concat "\\<\\(" perl-keywords "\\)\\>")
1005 '(0 font-lock-keyword-face))
1006
1007 ;; --- At least numbers are simpler than C ---
1008
1009 (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
1010 "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
1011 "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
1012 '(0 mdw-number-face))
1013
1014 ;; --- And anything else is punctuation ---
1015
1016 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1017 '(0 mdw-punct-face))))))
1018
1019(defun perl-number-tests (&optional arg)
1020 "Assign consecutive numbers to lines containing `#t'. With ARG,
1021strip numbers instead."
1022 (interactive "P")
1023 (save-excursion
1024 (goto-char (point-min))
1025 (let ((i 0) (fmt (if arg "" " %4d")))
1026 (while (search-forward "#t" nil t)
1027 (delete-region (point) (line-end-position))
1028 (setq i (1+ i))
1029 (insert (format fmt i)))
1030 (goto-char (point-min))
1031 (if (re-search-forward "\\(tests\\s-*=>\\s-*\\)\\w*" nil t)
1032 (replace-match (format "\\1%d" i))))))
1033
1034;;;----- Python programming style -------------------------------------------
1035
1036;; --- Define Python fontification style ---
1037
1038(trap (require 'pyrex-mode))
1039(defun mdw-fontify-python ()
1040
1041 ;; --- Miscellaneous fiddling ---
1042
1043 (modify-syntax-entry ?_ "w")
1044 (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
1045
1046 ;; --- Now define fontification things ---
1047
1048 (make-local-variable 'font-lock-keywords)
1049 (let ((python-keywords
1050 (make-regexp '("and" "as" "assert" "break" "class" "continue" "def"
1051 "del" "elif" "else" "except" "exec" "finally" "for"
1052 "from" "global" "if" "import" "in" "is" "lambda"
1053 "not" "or" "pass" "print" "raise" "return" "try"
043e413b 1054 "while" "yield"))))
f617db13
MW
1055 (setq font-lock-keywords
1056 (list
1057 't
1058
1059 ;; --- Set up the keywords defined above ---
1060
1061 (list (concat "\\<\\(" python-keywords "\\)\\>")
1062 '(0 font-lock-keyword-face))
1063
1064 ;; --- At least numbers are simpler than C ---
1065
1066 (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
1067 "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
1068 "\\([eE]\\([-+]\\|\\)[0-9_]+\\|[lL]\\|\\)")
1069 '(0 mdw-number-face))
1070
1071 ;; --- And anything else is punctuation ---
1072
1073 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1074 '(0 mdw-punct-face))))))
1075
1076;;;----- ARM assembler programming configuration ----------------------------
1077
1078;; --- There doesn't appear to be an Emacs mode for this yet ---
1079;;
1080;; Better do something about that, I suppose.
1081
1082(defvar arm-assembler-mode-map nil)
1083(defvar arm-assembler-abbrev-table nil)
1084(defvar arm-assembler-mode-syntax-table (make-syntax-table))
1085
1086(or arm-assembler-mode-map
1087 (progn
1088 (setq arm-assembler-mode-map (make-sparse-keymap))
1089 (define-key arm-assembler-mode-map "\C-m" 'arm-assembler-newline)
1090 (define-key arm-assembler-mode-map [C-return] 'newline)
1091 (define-key arm-assembler-mode-map "\t" 'tab-to-tab-stop)))
1092
1093(defun arm-assembler-mode ()
1094 "Major mode for ARM assembler programs"
1095 (interactive)
1096
1097 ;; --- Do standard major mode things ---
1098
1099 (kill-all-local-variables)
1100 (use-local-map arm-assembler-mode-map)
1101 (setq local-abbrev-table arm-assembler-abbrev-table)
1102 (setq major-mode 'arm-assembler-mode)
1103 (setq mode-name "ARM assembler")
1104
1105 ;; --- Set up syntax table ---
1106
1107 (set-syntax-table arm-assembler-mode-syntax-table)
1108 (modify-syntax-entry ?; ; Nasty hack
1109 "<" arm-assembler-mode-syntax-table)
1110 (modify-syntax-entry ?\n ">" arm-assembler-mode-syntax-table)
1111 (modify-syntax-entry ?_ "_" arm-assembler-mode-syntax-table)
1112
1113 (make-local-variable 'comment-start)
1114 (setq comment-start ";")
1115 (make-local-variable 'comment-end)
1116 (setq comment-end "")
1117 (make-local-variable 'comment-column)
1118 (setq comment-column 48)
1119 (make-local-variable 'comment-start-skip)
1120 (setq comment-start-skip ";+[ \t]*")
1121
1122 ;; --- Play with indentation ---
1123
1124 (make-local-variable 'indent-line-function)
1125 (setq indent-line-function 'indent-relative-maybe)
1126
1127 ;; --- Set fill prefix ---
1128
1129 (mdw-standard-fill-prefix "\\([ \t]*;+[ \t]*\\)")
1130
1131 ;; --- Fiddle with fontification ---
1132
1133 (make-local-variable 'font-lock-keywords)
1134 (setq font-lock-keywords
1135 (list
1136 't
1137
1138 ;; --- Handle numbers too ---
1139 ;;
1140 ;; The following isn't quite right, but it's close enough.
1141
1142 (list (concat "\\("
1143 "&[0-9a-fA-F]+\\|"
1144 "\\<[0-9]+\\(\\.[0-9]*\\|_[0-9a-zA-Z]+\\|\\)"
1145 "\\)")
1146 '(0 mdw-number-face))
1147
1148 ;; --- Do something about operators ---
1149
1150 (list "^[^ \t]*[ \t]+\\(GET\\|LNK\\)[ \t]+\\([^;\n]*\\)"
1151 '(1 font-lock-keyword-face)
1152 '(2 font-lock-string-face))
1153 (list ":[a-zA-Z]+:"
1154 '(0 font-lock-keyword-face))
1155
1156 ;; --- Do menemonics and directives ---
1157
1158 (list "^[^ \t]*[ \t]+\\([a-zA-Z]+\\)"
1159 '(1 font-lock-keyword-face))
1160
1161 ;; --- And anything else is punctuation ---
1162
1163 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1164 '(0 mdw-punct-face))))
1165
1166 (run-hooks 'arm-assembler-mode-hook))
1167
1168;;;----- TCL configuration --------------------------------------------------
1169
1170(defun mdw-fontify-tcl ()
1171 (mapcar #'(lambda (ch) (modify-syntax-entry ch ".")) '(?$))
1172 (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
1173 (make-local-variable 'font-lock-keywords)
1174 (setq font-lock-keywords
1175 (list
1176 't
1177 (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
1178 "\\<[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
1179 "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
1180 '(0 mdw-number-face))
1181 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1182 '(0 mdw-punct-face)))))
1183
1184;;;----- REXX configuration -------------------------------------------------
1185
1186(defun mdw-rexx-electric-* ()
1187 (interactive)
1188 (insert ?*)
1189 (rexx-indent-line))
1190
1191(defun mdw-rexx-indent-newline-indent ()
1192 (interactive)
1193 (rexx-indent-line)
1194 (if abbrev-mode (expand-abbrev))
1195 (newline-and-indent))
1196
1197(defun mdw-fontify-rexx ()
1198
1199 ;; --- Various bits of fiddling ---
1200
1201 (setq mdw-auto-indent nil)
1202 (local-set-key [?\C-m] 'mdw-rexx-indent-newline-indent)
1203 (local-set-key [?*] 'mdw-rexx-electric-*)
1204 (mapcar #'(lambda (ch) (modify-syntax-entry ch "w"))
1205 '(?. ?! ?? ?_ ?# ?@ ?$))
1206 (mdw-standard-fill-prefix "\\([ \t]*/?\*[ \t]*\\)")
1207
1208 ;; --- Set up keywords and things for fontification ---
1209
1210 (make-local-variable 'font-lock-keywords-case-fold-search)
1211 (setq font-lock-keywords-case-fold-search t)
1212
1213 (setq rexx-indent 2)
1214 (setq rexx-end-indent rexx-indent)
1215 (setq rexx-tab-always-indent nil)
1216 (setq rexx-cont-indent rexx-indent)
1217
1218 (make-local-variable 'font-lock-keywords)
1219 (let ((rexx-keywords
1220 (make-regexp '("address" "arg" "by" "call" "digits" "do" "drop"
1221 "else" "end" "engineering" "exit" "expose" "for"
1222 "forever" "form" "fuzz" "if" "interpret" "iterate"
1223 "leave" "linein" "name" "nop" "numeric" "off" "on"
1224 "options" "otherwise" "parse" "procedure" "pull"
1225 "push" "queue" "return" "say" "select" "signal"
1226 "scientific" "source" "then" "trace" "to" "until"
1227 "upper" "value" "var" "version" "when" "while"
1228 "with"
1229
1230 "abbrev" "abs" "bitand" "bitor" "bitxor" "b2x"
1231 "center" "center" "charin" "charout" "chars"
1232 "compare" "condition" "copies" "c2d" "c2x"
1233 "datatype" "date" "delstr" "delword" "d2c" "d2x"
1234 "errortext" "format" "fuzz" "insert" "lastpos"
1235 "left" "length" "lineout" "lines" "max" "min"
1236 "overlay" "pos" "queued" "random" "reverse" "right"
1237 "sign" "sourceline" "space" "stream" "strip"
1238 "substr" "subword" "symbol" "time" "translate"
1239 "trunc" "value" "verify" "word" "wordindex"
1240 "wordlength" "wordpos" "words" "xrange" "x2b" "x2c"
1241 "x2d"))))
1242
1243 (setq font-lock-keywords
1244 (list
1245 't
1246
1247 ;; --- Set up the keywords defined above ---
1248
1249 (list (concat "\\<\\(" rexx-keywords "\\)\\>")
1250 '(0 font-lock-keyword-face))
1251
1252 ;; --- Fontify all symbols the same way ---
1253
1254 (list (concat "\\<\\([0-9.][A-Za-z0-9.!?_#@$]*[Ee][+-]?[0-9]+\\|"
1255 "[A-Za-z0-9.!?_#@$]+\\)")
1256 '(0 font-lock-variable-name-face))
1257
1258 ;; --- And everything else is punctuation ---
1259
1260 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1261 '(0 mdw-punct-face))))))
1262
1263;;;----- Standard ML programming style --------------------------------------
1264
1265(defun mdw-fontify-sml ()
1266
1267 ;; --- Make underscore an honorary letter ---
1268
1269 (modify-syntax-entry ?_ "w")
1270 (modify-syntax-entry ?' "w")
1271
1272 ;; --- Set fill prefix ---
1273
1274 (mdw-standard-fill-prefix "\\([ \t]*(\*[ \t]*\\)")
1275
1276 ;; --- Now define fontification things ---
1277
1278 (make-local-variable 'font-lock-keywords)
1279 (let ((sml-keywords
1280 (make-regexp '("abstype" "and" "andalso" "as"
1281 "case"
1282 "datatype" "do"
1283 "else" "end" "eqtype" "exception"
1284 "fn" "fun" "functor"
1285 "handle"
1286 "if" "in" "include" "infix" "infixr"
1287 "let" "local"
1288 "nonfix"
1289 "of" "op" "open" "orelse"
1290 "raise" "rec"
1291 "sharing" "sig" "signature" "struct" "structure"
1292 "then" "type"
1293 "val"
1294 "where" "while" "with" "withtype"))))
1295
1296 (setq font-lock-keywords
1297 (list
1298 't
1299
1300 ;; --- Set up the keywords defined above ---
1301
1302 (list (concat "\\<\\(" sml-keywords "\\)\\>")
1303 '(0 font-lock-keyword-face))
1304
1305 ;; --- At least numbers are simpler than C ---
1306
1307 (list (concat "\\<\\(\\~\\|\\)"
1308 "\\(0\\(\\([wW]\\|\\)[xX][0-9a-fA-F]+\\|"
1309 "[wW][0-9]+\\)\\|"
1310 "\\([0-9]+\\(\\.[0-9]+\\|\\)"
1311 "\\([eE]\\(\\~\\|\\)"
1312 "[0-9]+\\|\\)\\)\\)")
1313 '(0 mdw-number-face))
1314
1315 ;; --- And anything else is punctuation ---
1316
1317 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1318 '(0 mdw-punct-face))))))
1319
1320;;;----- Haskell configuration ----------------------------------------------
1321
1322(defun mdw-fontify-haskell ()
1323
1324 ;; --- Fiddle with syntax table to get comments right ---
1325
1326 (modify-syntax-entry ?_ "w")
1327 (modify-syntax-entry ?' "\"")
1328 (modify-syntax-entry ?- ". 123")
1329 (modify-syntax-entry ?{ ". 1b")
1330 (modify-syntax-entry ?} ". 4b")
1331 (modify-syntax-entry ?\n ">")
1332
1333 ;; --- Set fill prefix ---
1334
1335 (mdw-standard-fill-prefix "\\([ \t]*{?--?[ \t]*\\)")
1336
1337 ;; --- Fiddle with fontification ---
1338
1339 (make-local-variable 'font-lock-keywords)
1340 (let ((haskell-keywords
1341 (make-regexp '("as" "case" "ccall" "class" "data" "default"
1342 "deriving" "do" "else" "foreign" "hiding" "if"
1343 "import" "in" "infix" "infixl" "infixr" "instance"
1344 "let" "module" "newtype" "of" "qualified" "safe"
1345 "stdcall" "then" "type" "unsafe" "where"))))
1346
1347 (setq font-lock-keywords
1348 (list
1349 't
1350 (list "--.*$"
1351 '(0 font-lock-comment-face))
1352 (list (concat "\\<\\(" haskell-keywords "\\)\\>")
1353 '(0 font-lock-keyword-face))
1354 (list (concat "\\<0\\([xX][0-9a-fA-F]+\\|[0-7]+\\)\\|"
1355 "\\<[0-9][0-9_]*\\(\\.[0-9]*\\|\\)"
1356 "\\([eE]\\([-+]\\|\\)[0-9]+\\|\\)")
1357 '(0 mdw-number-face))
1358 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1359 '(0 mdw-punct-face))))))
1360
1361;;;----- Texinfo configuration ----------------------------------------------
1362
1363(defun mdw-fontify-texinfo ()
1364
1365 ;; --- Set fill prefix ---
1366
1367 (mdw-standard-fill-prefix "\\([ \t]*@c[ \t]+\\)")
1368
1369 ;; --- Real fontification things ---
1370
1371 (make-local-variable 'font-lock-keywords)
1372 (setq font-lock-keywords
1373 (list
1374 't
1375
1376 ;; --- Environment names are keywords ---
1377
1378 (list "@\\(end\\) *\\([a-zA-Z]*\\)?"
1379 '(2 font-lock-keyword-face))
1380
1381 ;; --- Unmark escaped magic characters ---
1382
1383 (list "\\(@\\)\\([@{}]\\)"
1384 '(1 font-lock-keyword-face)
1385 '(2 font-lock-variable-name-face))
1386
1387 ;; --- Make sure we get comments properly ---
1388
1389 (list "@c\\(\\|omment\\)\\( .*\\)?$"
1390 '(0 font-lock-comment-face))
1391
1392 ;; --- Command names are keywords ---
1393
1394 (list "@\\([^a-zA-Z@]\\|[a-zA-Z@]*\\)"
1395 '(0 font-lock-keyword-face))
1396
1397 ;; --- Fontify TeX special characters as punctuation ---
1398
1399 (list "[{}]+"
1400 '(0 mdw-punct-face)))))
1401
1402;;;----- TeX and LaTeX configuration ----------------------------------------
1403
1404(defun mdw-fontify-tex ()
1405 (setq ispell-parser 'tex)
1406
1407 ;; --- Don't make maths into a string ---
1408
1409 (modify-syntax-entry ?$ ".")
1410 (modify-syntax-entry ?$ "." font-lock-syntax-table)
1411 (local-set-key [?$] 'self-insert-command)
1412
1413 ;; --- Set fill prefix ---
1414
1415 (mdw-standard-fill-prefix "\\([ \t]*%+[ \t]*\\)")
1416
1417 ;; --- Real fontification things ---
1418
1419 (make-local-variable 'font-lock-keywords)
1420 (setq font-lock-keywords
1421 (list
1422 't
1423
1424 ;; --- Environment names are keywords ---
1425
1426 (list (concat "\\\\\\(begin\\|end\\|newenvironment\\)"
1427 "{\\([^}\n]*\\)}")
1428 '(2 font-lock-keyword-face))
1429
1430 ;; --- Suspended environment names are keywords too ---
1431
1432 (list (concat "\\\\\\(suspend\\|resume\\)\\(\\[[^]]*\\]\\)?"
1433 "{\\([^}\n]*\\)}")
1434 '(3 font-lock-keyword-face))
1435
1436 ;; --- Command names are keywords ---
1437
1438 (list "\\\\\\([^a-zA-Z@]\\|[a-zA-Z@]*\\)"
1439 '(0 font-lock-keyword-face))
1440
1441 ;; --- Handle @/.../ for italics ---
1442
1443 ;; (list "\\(@/\\)\\([^/]*\\)\\(/\\)"
1444 ;; '(1 font-lock-keyword-face)
1445 ;; '(3 font-lock-keyword-face))
1446
1447 ;; --- Handle @*...* for boldness ---
1448
1449 ;; (list "\\(@\\*\\)\\([^*]*\\)\\(\\*\\)"
1450 ;; '(1 font-lock-keyword-face)
1451 ;; '(3 font-lock-keyword-face))
1452
1453 ;; --- Handle @`...' for literal syntax things ---
1454
1455 ;; (list "\\(@`\\)\\([^']*\\)\\('\\)"
1456 ;; '(1 font-lock-keyword-face)
1457 ;; '(3 font-lock-keyword-face))
1458
1459 ;; --- Handle @<...> for nonterminals ---
1460
1461 ;; (list "\\(@<\\)\\([^>]*\\)\\(>\\)"
1462 ;; '(1 font-lock-keyword-face)
1463 ;; '(3 font-lock-keyword-face))
1464
1465 ;; --- Handle other @-commands ---
1466
1467 ;; (list "@\\([^a-zA-Z]\\|[a-zA-Z]*\\)"
1468 ;; '(0 font-lock-keyword-face))
1469
1470 ;; --- Make sure we get comments properly ---
1471
1472 (list "%.*"
1473 '(0 font-lock-comment-face))
1474
1475 ;; --- Fontify TeX special characters as punctuation ---
1476
1477 (list "[$^_{}#&]"
1478 '(0 mdw-punct-face)))))
1479
1480;;;----- Shell scripts ------------------------------------------------------
1481
1482(defun mdw-setup-sh-script-mode ()
1483
1484 ;; --- Fetch the shell interpreter's name ---
1485
1486 (let ((shell-name sh-shell-file))
1487
1488 ;; --- Try reading the hash-bang line ---
1489
1490 (save-excursion
1491 (goto-char (point-min))
1492 (if (looking-at "#![ \t]*\\([^ \t\n]*\\)")
1493 (setq shell-name (match-string 1))))
1494
1495 ;; --- Now try to set the shell ---
1496 ;;
1497 ;; Don't let `sh-set-shell' bugger up my script.
1498
1499 (let ((executable-set-magic #'(lambda (s &rest r) s)))
1500 (sh-set-shell shell-name)))
1501
1502 ;; --- Now enable my keys and the fontification ---
1503
1504 (mdw-misc-mode-config)
1505
1506 ;; --- Set the indentation level correctly ---
1507
1508 (setq sh-indentation 2)
1509 (setq sh-basic-offset 2))
1510
1511;;;----- Messages-file mode -------------------------------------------------
1512
1513(defun message-mode-guts ()
1514 (setq messages-mode-syntax-table (make-syntax-table))
1515 (set-syntax-table messages-mode-syntax-table)
1516 (modify-syntax-entry ?_ "w" messages-mode-syntax-table)
1517 (modify-syntax-entry ?- "w" messages-mode-syntax-table)
1518 (modify-syntax-entry ?0 "w" messages-mode-syntax-table)
1519 (modify-syntax-entry ?1 "w" messages-mode-syntax-table)
1520 (modify-syntax-entry ?2 "w" messages-mode-syntax-table)
1521 (modify-syntax-entry ?3 "w" messages-mode-syntax-table)
1522 (modify-syntax-entry ?4 "w" messages-mode-syntax-table)
1523 (modify-syntax-entry ?5 "w" messages-mode-syntax-table)
1524 (modify-syntax-entry ?6 "w" messages-mode-syntax-table)
1525 (modify-syntax-entry ?7 "w" messages-mode-syntax-table)
1526 (modify-syntax-entry ?8 "w" messages-mode-syntax-table)
1527 (modify-syntax-entry ?9 "w" messages-mode-syntax-table)
1528 (make-local-variable 'comment-start)
1529 (make-local-variable 'comment-end)
1530 (make-local-variable 'indent-line-function)
1531 (setq indent-line-function 'indent-relative)
1532 (mdw-standard-fill-prefix "\\([ \t]*\\(;\\|/?\\*\\)+[ \t]*\\)")
1533 (make-local-variable 'font-lock-defaults)
1534 (make-local-variable 'message-mode-keywords)
1535 (let ((keywords
1536 (make-regexp '("array" "bitmap" "callback" "docs[ \t]+enum"
1537 "export" "enum" "fixed-octetstring" "flags"
1538 "harmless" "map" "nested" "optional"
1539 "optional-tagged" "package" "primitive"
1540 "primitive-nullfree" "relaxed[ \t]+enum"
1541 "set" "table" "tagged-optional" "union"
1542 "variadic" "vector" "version" "version-tag"))))
1543 (setq message-mode-keywords
1544 (list
1545 (list (concat "\\<\\(" keywords "\\)\\>:")
1546 '(0 font-lock-keyword-face))
1547 '("\\([-a-zA-Z0-9]+:\\)" (0 font-lock-warning-face))
1548 '("\\(\\<[a-z][-_a-zA-Z0-9]*\\)"
1549 (0 font-lock-variable-name-face))
1550 '("\\<\\([0-9]+\\)\\>" (0 mdw-number-face))
1551 '("\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1552 (0 mdw-punct-face)))))
1553 (setq font-lock-defaults
1554 '(message-mode-keywords nil nil nil nil))
1555 (run-hooks 'messages-file-hook))
1556
1557(defun messages-mode ()
1558 (interactive)
1559 (fundamental-mode)
1560 (setq major-mode 'messages-mode)
1561 (setq mode-name "Messages")
1562 (message-mode-guts)
1563 (modify-syntax-entry ?# "<" messages-mode-syntax-table)
1564 (modify-syntax-entry ?\n ">" messages-mode-syntax-table)
1565 (setq comment-start "# ")
1566 (setq comment-end "")
1567 (turn-on-font-lock-if-enabled)
1568 (run-hooks 'messages-mode-hook))
1569
1570(defun cpp-messages-mode ()
1571 (interactive)
1572 (fundamental-mode)
1573 (setq major-mode 'cpp-messages-mode)
1574 (setq mode-name "CPP Messages")
1575 (message-mode-guts)
1576 (modify-syntax-entry ?* ". 23" messages-mode-syntax-table)
1577 (modify-syntax-entry ?/ ". 14" messages-mode-syntax-table)
1578 (setq comment-start "/* ")
1579 (setq comment-end " */")
1580 (let ((preprocessor-keywords
1581 (make-regexp '("assert" "define" "elif" "else" "endif" "error"
1582 "ident" "if" "ifdef" "ifndef" "import" "include"
1583 "line" "pragma" "unassert" "undef" "warning"))))
1584 (setq message-mode-keywords
1585 (append (list (list (concat "^[ \t]*\\#[ \t]*"
1586 "\\(include\\|import\\)"
1587 "[ \t]*\\(<[^>]+\\(>\\|\\)\\)")
1588 '(2 font-lock-string-face))
1589 (list (concat "^\\([ \t]*#[ \t]*\\(\\("
1590 preprocessor-keywords
1591 "\\)\\>\\|[0-9]+\\|$\\)\\)")
1592 '(1 font-lock-keyword-face)))
1593 message-mode-keywords)))
f617db13 1594 (turn-on-font-lock-if-enabled)
297d60aa 1595 (run-hooks 'cpp-messages-mode-hook))
f617db13 1596
297d60aa
MW
1597(add-hook 'messages-mode-hook 'mdw-misc-mode-config t)
1598(add-hook 'cpp-messages-mode-hook 'mdw-misc-mode-config t)
f617db13
MW
1599; (add-hook 'messages-file-hook 'mdw-fontify-messages t)
1600
1601;;;----- Messages-file mode -------------------------------------------------
1602
1603(defvar mallow-driver-substitution-face 'mallow-driver-substitution-face
1604 "Face to use for subsittution directives.")
1605(make-face 'mallow-driver-substitution-face)
1606(defvar mallow-driver-text-face 'mallow-driver-text-face
1607 "Face to use for body text.")
1608(make-face 'mallow-driver-text-face)
1609
1610(defun mallow-driver-mode ()
1611 (interactive)
1612 (fundamental-mode)
1613 (setq major-mode 'mallow-driver-mode)
1614 (setq mode-name "Mallow driver")
1615 (setq mallow-driver-mode-syntax-table (make-syntax-table))
1616 (set-syntax-table mallow-driver-mode-syntax-table)
1617 (make-local-variable 'comment-start)
1618 (make-local-variable 'comment-end)
1619 (make-local-variable 'indent-line-function)
1620 (setq indent-line-function 'indent-relative)
1621 (mdw-standard-fill-prefix "\\([ \t]*\\(;\\|/?\\*\\)+[ \t]*\\)")
1622 (make-local-variable 'font-lock-defaults)
1623 (make-local-variable 'mallow-driver-mode-keywords)
1624 (let ((keywords
1625 (make-regexp '("each" "divert" "file" "if"
1626 "perl" "set" "string" "type" "write"))))
1627 (setq mallow-driver-mode-keywords
1628 (list
1629 (list (concat "^%\\s *\\(}\\|\\(" keywords "\\)\\>\\).*$")
1630 '(0 font-lock-keyword-face))
1631 (list "^%\\s *\\(#.*\\|\\)$"
1632 '(0 font-lock-comment-face))
1633 (list "^%"
1634 '(0 font-lock-keyword-face))
1635 (list "^|?\\(.+\\)$" '(1 mallow-driver-text-face))
1636 (list "\\${[^}]*}"
1637 '(0 mallow-driver-substitution-face t)))))
1638 (setq font-lock-defaults
1639 '(mallow-driver-mode-keywords nil nil nil nil))
1640 (modify-syntax-entry ?\" "_" mallow-driver-mode-syntax-table)
1641 (modify-syntax-entry ?\n ">" mallow-driver-mode-syntax-table)
1642 (setq comment-start "%# ")
1643 (setq comment-end "")
1644 (turn-on-font-lock-if-enabled)
1645 (run-hooks 'mallow-driver-mode-hook))
1646
1647(add-hook 'mallow-driver-hook 'mdw-misc-mode-config t)
1648
1649;;;----- NFast debugs -------------------------------------------------------
1650
1651(defun nfast-debug-mode ()
1652 (interactive)
1653 (fundamental-mode)
1654 (setq major-mode 'nfast-debug-mode)
1655 (setq mode-name "NFast debug")
1656 (setq messages-mode-syntax-table (make-syntax-table))
1657 (set-syntax-table messages-mode-syntax-table)
1658 (make-local-variable 'font-lock-defaults)
1659 (make-local-variable 'nfast-debug-mode-keywords)
1660 (setq truncate-lines t)
1661 (setq nfast-debug-mode-keywords
1662 (list
1663 '("^\\(NFast_\\(Connect\\|Disconnect\\|Submit\\|Wait\\)\\)"
1664 (0 font-lock-keyword-face))
1665 (list (concat "^[ \t]+\\(\\("
1666 "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]"
1667 "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]"
1668 "[ \t]+\\)*"
1669 "[0-9a-fA-F]+\\)[ \t]*$")
1670 '(0 mdw-number-face))
1671 '("^[ \t]+\.status=[ \t]+\\<\\(OK\\)\\>"
1672 (1 font-lock-keyword-face))
1673 '("^[ \t]+\.status=[ \t]+\\<\\([a-zA-Z][0-9a-zA-Z]*\\)\\>"
1674 (1 font-lock-warning-face))
1675 '("^[ \t]+\.status[ \t]+\\<\\(zero\\)\\>"
1676 (1 nil))
1677 (list (concat "^[ \t]+\\.cmd=[ \t]+"
1678 "\\<\\([a-zA-Z][0-9a-zA-Z]*\\)\\>")
1679 '(1 font-lock-keyword-face))
1680 '("-?\\<\\([0-9]+\\|0x[0-9a-fA-F]+\\)\\>" (0 mdw-number-face))
1681 '("^\\([ \t]+[a-z0-9.]+\\)" (0 font-lock-variable-name-face))
1682 '("\\<\\([a-z][a-z0-9.]+\\)\\>=" (1 font-lock-variable-name-face))
1683 '("\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)" (0 mdw-punct-face))))
1684 (setq font-lock-defaults
1685 '(nfast-debug-mode-keywords nil nil nil nil))
1686 (turn-on-font-lock-if-enabled)
1687 (run-hooks 'nfast-debug-mode-hook))
1688
1689;;;----- Other languages ----------------------------------------------------
1690
1691;; --- Smalltalk ---
1692
1693(defun mdw-setup-smalltalk ()
1694 (and mdw-auto-indent
1695 (local-set-key "\C-m" 'smalltalk-newline-and-indent))
1696 (make-variable-buffer-local 'mdw-auto-indent)
1697 (setq mdw-auto-indent nil)
1698 (local-set-key "\C-i" 'smalltalk-reindent))
1699
1700(defun mdw-fontify-smalltalk ()
1701 (make-local-variable 'font-lock-keywords)
1702 (setq font-lock-keywords
1703 (list
1704 't
1705 (list "\\<[A-Z][a-zA-Z0-9]*\\>"
1706 '(0 font-lock-keyword-face))
1707 (list (concat "\\<0\\([xX][0-9a-fA-F_]+\\|[0-7_]+\\)\\|"
1708 "[0-9][0-9_]*\\(\\.[0-9_]*\\|\\)"
1709 "\\([eE]\\([-+]\\|\\)[0-9_]+\\|\\)")
1710 '(0 mdw-number-face))
1711 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1712 '(0 mdw-punct-face)))))
1713
1714;; --- Lispy languages ---
1715
1716(defun mdw-indent-newline-and-indent ()
1717 (interactive)
1718 (indent-for-tab-command)
1719 (newline-and-indent))
1720
1721(eval-after-load "cl-indent"
1722 '(progn
1723 (mapc #'(lambda (pair)
1724 (put (car pair)
1725 'common-lisp-indent-function
1726 (cdr pair)))
1727 '((destructuring-bind . ((&whole 4 &rest 1) 4 &body))
1728 (multiple-value-bind . ((&whole 4 &rest 1) 4 &body))))))
1729
1730(defun mdw-common-lisp-indent ()
1731 (make-variable-buffer-local 'lisp-indent-function)
1732 (setq lisp-indent-function 'common-lisp-indent-function))
1733
1734(defun mdw-fontify-lispy ()
1735
1736 ;; --- Set fill prefix ---
1737
1738 (mdw-standard-fill-prefix "\\([ \t]*;+[ \t]*\\)")
1739
1740 ;; --- Not much fontification needed ---
1741
1742 (make-local-variable 'font-lock-keywords)
1743 (setq font-lock-keywords
1744 (list
1745 't
1746 (list "\\(\\s.\\|\\s(\\|\\s)\\|\\s\\\\|\\s/\\)"
1747 '(0 mdw-punct-face)))))
1748
1749(defun comint-send-and-indent ()
1750 (interactive)
1751 (comint-send-input)
1752 (and mdw-auto-indent
1753 (indent-for-tab-command)))
1754
1755;;;----- Text mode ----------------------------------------------------------
1756
1757(defun mdw-text-mode ()
1758 (setq fill-column 72)
1759 (flyspell-mode t)
1760 (mdw-standard-fill-prefix
1761 "\\([ \t]*\\([A-Za-z0-9]*[>#|:] ?\\)*[ \t]*\\)" 3)
1762 (auto-fill-mode 1))
1763
1764;;;----- Shell mode ---------------------------------------------------------
1765
1766(defun mdw-sh-mode-setup ()
1767 (local-set-key [?\C-a] 'comint-bol)
1768 (add-hook 'comint-output-filter-functions
1769 'comint-watch-for-password-prompt))
1770
1771(defun mdw-term-mode-setup ()
9a3fa88e 1772