tentative fix for issue 3 (ex 53)
[mplib] / src / texk / web2c / cwebdir / cweb.el
1 ;; This file contains extensions to GNU-Emacs, to wit:
2 ; (1) some WEB-oriented functions that are also of general use
3 ; (2) changes to the GNU-distributed TeX mode
4 ; (3) definitions of simple WEB and CWEB modes
5
6 ; To use: Put this in your EMACS-lisp library and say (load-library "cweb")
7 ; in your .emacs init file.
8
9 ; Contributed by Don Knuth, July 1990
10
11 ;; OK, here's part (1): some WEB-oriented functions whose main purpose is
12 ; to maintain a stack of module names that are "pending" as you are writing
13 ; a program. When you first think of a module that needs to be written later,
14 ; put it into the pending list (by typing CTL-Z instead of @> after the
15 ; name). Later you can say CTL-\ to retrieve a pending name (and if
16 ; you want to cycle through the pending names, ESC-y after CTL-\ will
17 ; do it, just as ESC-y works after a yank).
18 ; After you've said CTL-\, the current region is the name just removed from
19 ; the pending list. If you change your mind, you can put it back again by
20 ; saying ESC-\. If you had put it into the pending list by mistake, you
21 ; can get rid of it by using the normal CTL-W operation (kill-region).
22 ; The following code binds the new commands to CTL-Z, CTL-\, and ESC-\
23 ; in all modes. You may prefer other bindings, of course.
24 ; CTL-Z is normally "suspend emacs", but it is best not used when emacs
25 ; has its own window as it usually does nowadays; if you need the
26 ; old CTL-Z, you might rather bind it to CTL-X CTL-Z.
27 ; CTL-\ is normally undefined.
28 ; ESC-\ is normally "delete space", but ESC-space DEL does that easily too.
29
30 (defvar pending-list nil
31  "List of strings (usually WEB module names) still pending.")
32
33 (defun into-pending-list (beg end)
34  "Copy region into pending-list."
35  (interactive "r")
36  (indicate-region)
37  (setq pending-list (cons (buffer-substring beg end) pending-list)))
38
39 (defun new-module-name-pending ()
40  "Insert @> to complete a module name, then put it into pending-list."
41  (interactive)
42  (insert "@>")
43  (push-mark)
44  (if (search-backward "@<" nil t)
45      (progn
46        (exchange-point-and-mark)
47        (into-pending-list (point) (mark))
48        )
49    (message "There's no @< to begin the module name!")))
50 (global-set-key "\C-z" 'new-module-name-pending)
51
52 (defun pop-pending-list (arg)
53  "Remove first element of pending-list and insert it as current region.
54 With argument, put point at left; otherwise point will follow the insertion.
55 Say \\[new-yank-pop] to replace this by another element of the list.
56 Say \\[into-pending-list] to put it back in the list."
57  (interactive "*P")
58  (if (consp pending-list)
59      (progn
60        (push-mark (point))
61        (insert (car pending-list))
62        (setq pending-list (cdr pending-list))
63        (if arg
64            (exchange-point-and-mark)))
65    (message "Nothing is pending.")
66    (setq this-command nil)))
67 (global-set-key "\C-\\" 'pop-pending-list)
68 (global-set-key "\M-\\" 'into-pending-list)
69
70 (defun new-yank-pop (arg)
71  "If previous command was \\[pop-pending-list], pop a different string;
72 otherwise do an ordinary Meta-y."
73  (interactive "*p")
74  (if (eq last-command 'pop-pending-list)
75      (let (xch)
76        (setq xch (< (point) (mark)))
77        (setq pending-list (append pending-list
78                                  (list (buffer-substring (point) (mark)))))
79        (delete-region (point) (mark))
80        (setq this-command 'pop-pending-list)
81        (pop-pending-list xch))
82    (yank-pop arg)))
83 (global-set-key "\M-y" 'new-yank-pop)
84
85 (defun indicate-region ()
86   "Bounce cursor to mark and back again"
87   (let ((point-save (point)))
88     (unwind-protect
89         (progn (goto-char (mark))
90                (sit-for 0 300)) ;; wait 300 milliseconds
91       (goto-char point-save))))
92
93 ; I prefer to change the standard copy-region command to the following,
94 ; which gives me visual feedback about what I've copied to the kill ring:
95 (defun indicate-and-copy-region (beg end)
96   "Indicate current region, then copy it to the kill ring."
97   (interactive "r")(indicate-region)(copy-region-as-kill beg end))
98 (global-set-key "\M-w" 'indicate-and-copy-region)
99
100 ; Here's another convenient command, bound to the usually unused ESC-".
101 (defun ditto (arg)
102   "Copy ARG characters from the line above."
103   (interactive "*p")
104   (let (ch)
105     (while (> arg 0)
106       (setq temporary-goal-column (current-column))
107       (save-excursion
108         (previous-line 1)
109         (setq ch (following-char)))
110       (insert ch)
111       (setq arg (1- arg)))))
112 (global-set-key "\M-\"" 'ditto)
113
114 ;; OK, here's part (2): Changes to TeX mode.
115 ; The WEB modes below are very much like TeX mode, but some improvements were
116 ; desirable in TeX mode:
117 ; I made newline act as it does in indented-text mode, since this
118 ; works nicely for both TeX and WEB (Pascal or C code).
119 ; I made RET check for unmatched delimiters if it ends a paragraph.
120 ; Otherwise TeX mode remains as it was before.
121
122 (setq TeX-mode-map (make-sparse-keymap))
123 (define-key TeX-mode-map "\C-c\C-k" 'TeX-kill-job)
124 (define-key TeX-mode-map "\C-c\C-l" 'TeX-recenter-output-buffer)
125 (define-key TeX-mode-map "\C-c\C-q" 'TeX-show-print-queue)
126 (define-key TeX-mode-map "\C-c\C-p" 'TeX-print)
127 (define-key TeX-mode-map "\"" 'TeX-insert-quote)
128 (define-key TeX-mode-map "\e}" 'up-list)
129 (define-key TeX-mode-map "\e{" 'TeX-insert-braces)
130 (define-key TeX-mode-map "\C-c\C-r" 'TeX-region)
131 (define-key TeX-mode-map "\C-c\C-b" 'TeX-buffer)
132 (define-key TeX-mode-map "\C-c\C-f" 'TeX-close-LaTeX-block)
133 (define-key TeX-mode-map "\r" 'TeX-newline)
134 (define-key TeX-mode-map "\t" 'indent-relative)
135 (setq TeX-mode-hook '(lambda ()
136   (make-local-variable 'indent-line-function)
137   (setq indent-line-function 'indent-relative-maybe)))
138
139 (defun TeX-newline (arg)
140 "If previous character is newline and no ARG, check for unbalanced braces
141 and/or dollar signs in previous paragraph. If ARG is \\[universal-argument],
142 do a single newline; otherwise do ordinary newline."
143  (interactive "*P")
144  (if (and (eq (preceding-char) ?\n) (not arg))
145      (TeX-check-paragraph)
146    (if (listp arg)
147        (newline)
148      (newline arg))))
149
150 (defun TeX-check-paragraph ()
151 "Insert a newline following a newline, breaking a paragraph for TeX.
152 Check for mismatched delimiters in paragraph being terminated."
153   (interactive)
154   (if (TeX-validate-paragraph
155            (save-excursion
156              (search-backward "\n\n" nil 'move)
157              (point))
158            (point))
159       (insert ?\n)
160     (insert ?\n)
161     (error "Mismatched delimiters in that paragraph?")))
162
163 ;; and now, part (3): WEB and CWEB modes.
164 ; These are like plain TeX mode except that the automatic conversion of
165 ; " to `` or '' is disabled. (Personally I never liked that feature anyway,
166 ; since it's easy to get used to typing `` and ''. In WEB modes, the
167 ; feature soon becomes intolerable, unless you never use string constants!)
168 ; Another thing distinguishing WEB mode from TeX is ESC-p and ESC-n, to
169 ; move to previous or next module. These keys are usually unbound, except
170 ; when processing email.
171
172 (defun forward-module (arg)
173 "Advance past next WEB module beginning; with ARG, repeat ARG times."
174  (interactive "p")
175  (move-to-module arg))
176 (defun backward-module (arg)
177 "Advance to previous WEB module beginning; with ARG, repeat ARG times."
178  (interactive "p")
179  (move-to-module (- arg)))
180 (defun move-to-module (arg)
181  (while (> arg 0)
182    (re-search-forward "@ \\|@\\*\\|@\n")
183    (setq arg (1- arg)))
184  (while (< arg 0)
185    (re-search-backward "@ \\|@\\*\\|@\n")
186    (setq arg (1+ arg))))
187
188 (defun web-mode ()
189   "Major mode like TeX mode plus \\[forward-module] and \\[backward-module]
190 for relative module movement. The automatic \" feature is disabled."
191   (interactive)
192   (plain-tex-mode)
193   (local-set-key "\M-n" 'forward-module)
194   (local-set-key "\M-p" 'backward-module)
195   (local-set-key "\"" 'self-insert-command)
196   (setq mode-name "WEB")
197   (setq major-mode 'web-mode)
198   (run-hooks 'web-mode-hook))
199 (setq auto-mode-alist (cons '("\\.web$" . web-mode) auto-mode-alist))
200
201 (defun cweb-mode ()
202   "Major mode like TeX mode plus \\[forward-module] and \\[backward-module]
203 for relative module movement. The automatic \" feature is disabled."
204   (interactive)
205   (plain-tex-mode)
206   (local-set-key "\M-n" 'forward-module)
207   (local-set-key "\M-p" 'backward-module)
208   (local-set-key "\"" 'self-insert-command)
209   (setq comment-start nil)
210   (modify-syntax-entry ?% "@")
211   (setq mode-name "CWEB")
212   (setq major-mode 'cweb-mode)
213   (run-hooks 'cweb-mode-hook))
214 (setq auto-mode-alist (cons '("\\.w$" . cweb-mode) auto-mode-alist))
215 (setq auto-mode-alist (cons '("\\.ch$" . cweb-mode) auto-mode-alist))