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. 54With argument, put point at left; otherwise point will follow the insertion. 55Say \\[new-yank-pop] to replace this by another element of the list. 56Say \\[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; 72otherwise 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 141and/or dollar signs in previous paragraph. If ARG is \\[universal-argument], 142do 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. 152Check 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] 190for 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] 203for 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)) 216