|
|
1.1 root 1: ;; TeX mode commands.
2: ;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
3: ;; Rewritten following contributions by William F. Schelter
4: ;; and Dick King (king@kestrel).
5: ;; Modified August 1986 by Stephen Gildea <mit-erl!gildea> and
6: ;; Michael Prange <mit-erl!prange> to add LaTeX support and enhance
7: ;; TeX-region.
8: ;; Added TeX-directory and reorganized somewhat gildea 21 Nov 86
9:
10: ;; This file is part of GNU Emacs.
11:
12: ;; GNU Emacs is distributed in the hope that it will be useful,
13: ;; but WITHOUT ANY WARRANTY. No author or distributor
14: ;; accepts responsibility to anyone for the consequences of using it
15: ;; or for whether it serves any particular purpose or works at all,
16: ;; unless he says so in writing. Refer to the GNU Emacs General Public
17: ;; License for full details.
18:
19: ;; Everyone is granted permission to copy, modify and redistribute
20: ;; GNU Emacs, but only under the conditions described in the
21: ;; GNU Emacs General Public License. A copy of this license is
22: ;; supposed to have been given to you along with GNU Emacs so you
23: ;; can know your rights and responsibilities. It should be in a
24: ;; file named COPYING. Among other things, the copyright notice
25: ;; and this notice must be preserved on all copies.
26:
27: ;; Still to do:
28: ;; Make TAB indent correctly for TeX code. Then we can make linefeed
29: ;; do something more useful.
30: ;;
31: ;; Have spell understand TeX instead of assuming the entire world
32: ;; uses nroff.
33: ;;
34: ;; The code for finding matching $ needs to be fixed.
35:
36: (provide 'tex-mode)
37:
38: (defvar TeX-directory "/tmp/"
39: "*Directory in which to run TeX subjob. Temporary files are
40: created in this directory.")
41: (defvar TeX-dvi-print-command "lpr -d"
42: "*Command string used by \\[TeX-print] to print a .dvi file.")
43: (defvar TeX-show-queue-command "lpq"
44: "*Command string used by \\[TeX-show-print-queue] to show the print queue
45: that \\[TeX-print] put your job on.")
46: (defvar TeX-default-mode 'plain-TeX-mode
47: "*Mode to enter for a new file when it can't be determined whether
48: the file is plain TeX or LaTeX or what.")
49:
50: (defvar TeX-command nil
51: "The command to run TeX on a file. The name of the file will be appended
52: to this string, separated by a space.")
53: (defvar TeX-trailer nil
54: "String appended after the end of a region sent to TeX by \\[TeX-region].")
55: (defvar TeX-start-of-header nil
56: "String used by \\[TeX-region] to delimit the start of the file's header.")
57: (defvar TeX-end-of-header nil
58: "String used by \\[TeX-region] to delimit the end of the file's header.")
59: (defvar TeX-shell-cd-command "cd"
60: "Command to give to shell running TeX to change directory. The value of
61: TeX-directory will be appended to this, separated by a space.")
62: (defvar TeX-zap-file nil
63: "Temporary file name used for text being sent as input to TeX.
64: Should be a simple file name with no extension or directory specification.")
65:
66: (defvar TeX-mode-syntax-table nil
67: "Syntax table used while in TeX mode.")
68:
69: (defun TeX-define-common-keys (keymap)
70: "Define the keys that we want defined both in TeX-mode
71: and in the TeX-shell."
72: (define-key keymap "\C-c\C-k" 'TeX-kill-job)
73: (define-key keymap "\C-c\C-l" 'TeX-recenter-output-buffer)
74: (define-key keymap "\C-c\C-q" 'TeX-show-print-queue)
75: (define-key keymap "\C-c\C-p" 'TeX-print)
76: )
77:
78: (defvar TeX-mode-map nil "Keymap for TeX mode")
79:
80: (if TeX-mode-map
81: nil
82: (setq TeX-mode-map (make-sparse-keymap))
83: (TeX-define-common-keys TeX-mode-map)
84: (define-key TeX-mode-map "\"" 'TeX-insert-quote)
85: (define-key TeX-mode-map "\n" 'TeX-terminate-paragraph)
86: (define-key TeX-mode-map "\e}" 'up-list)
87: (define-key TeX-mode-map "\e{" 'TeX-insert-braces)
88: (define-key TeX-mode-map "\C-c\C-r" 'TeX-region)
89: (define-key TeX-mode-map "\C-c\C-b" 'TeX-buffer)
90: (define-key TeX-mode-map "\C-c\C-f" 'TeX-close-LaTeX-block)
91: )
92:
93: (defvar TeX-shell-map nil
94: "Keymap for the TeX shell. A shell-mode-map with a few additions")
95:
96: ;(fset 'TeX-mode 'tex-mode) ;in loaddefs.
97:
98: ;;; This would be a lot simpler if we just used a regexp search,
99: ;;; but then it would be too slow.
100: (defun tex-mode ()
101: "Major mode for editing files of input for TeX or LaTeX.
102: Trys to intuit whether this file is for plain TeX or LaTeX and
103: calls plain-tex-mode or latex-mode. If it cannot be determined
104: \(e.g., there are no commands in the file), the value of
105: TeX-default-mode is used."
106: (interactive)
107: (let (mode slash comment)
108: (save-excursion
109: (goto-char (point-min))
110: (while (and (setq slash (search-forward "\\" nil t))
111: (setq comment (let ((search-end (point)))
112: (save-excursion
113: (beginning-of-line)
114: (search-forward "%" search-end t))))))
115: (if (and slash (not comment))
116: (setq mode (if (looking-at "documentstyle")
117: 'latex-mode
118: 'plain-tex-mode))))
119: (if mode (funcall mode)
120: (funcall TeX-default-mode))))
121:
122: (fset 'plain-TeX-mode 'plain-tex-mode)
123: (fset 'LaTeX-mode 'latex-mode)
124:
125: (defun plain-tex-mode ()
126: "Major mode for editing files of input for plain TeX.
127: Makes $ and } display the characters they match.
128: Makes \" insert `` when it seems to be the beginning of a quotation,
129: and '' when it appears to be the end; it inserts \" only after a \\.
130:
131: Use \\[TeX-region] to run TeX on the current region, plus a \"header\"
132: copied from the top of the file (containing macro definitions, etc.),
133: running TeX under a special subshell. \\[TeX-buffer] does the whole buffer.
134: \\[TeX-print] prints the .dvi file made by either of these.
135:
136: Use \\[validate-TeX-buffer] to check buffer for paragraphs containing
137: mismatched $'s or braces.
138:
139: Special commands:
140: \\{TeX-mode-map}
141:
142: Mode variables:
143: TeX-directory
144: Directory in which to create temporary files for TeX jobs
145: run by \\[TeX-region] or \\[TeX-buffer].
146: TeX-dvi-print-command
147: Command string used by \\[TeX-print] to print a .dvi file.
148: TeX-show-queue-command
149: Command string used by \\[TeX-show-print-queue] to show the print
150: queue that \\[TeX-print] put your job on.
151:
152: Entering plain-TeX mode calls the value of text-mode-hook,
153: then the value of TeX-mode-hook, and then the value
154: of plain-TeX-mode-hook."
155: (interactive)
156: (TeX-common-initialization)
157: (setq mode-name "TeX")
158: (setq major-mode 'plain-TeX-mode)
159: (setq TeX-command "tex")
160: (setq TeX-start-of-header "%**start of header")
161: (setq TeX-end-of-header "%**end of header")
162: (setq TeX-trailer "\\bye\n")
163: (run-hooks 'text-mode-hook 'TeX-mode-hook 'plain-TeX-mode-hook))
164:
165: (defun latex-mode ()
166: "Major mode for editing files of input for LaTeX.
167: Makes $ and } display the characters they match.
168: Makes \" insert `` when it seems to be the beginning of a quotation,
169: and '' when it appears to be the end; it inserts \" only after a \\.
170:
171: Use \\[TeX-region] to run LaTeX on the current region, plus the preamble
172: copied from the top of the file (containing \\documentstyle, etc.),
173: running LaTeX under a special subshell. \\[TeX-buffer] does the whole buffer.
174: \\[TeX-print] prints the .dvi file made by either of these.
175:
176: Use \\[validate-TeX-buffer] to check buffer for paragraphs containing
177: mismatched $'s or braces.
178:
179: Special commands:
180: \\{TeX-mode-map}
181:
182: Mode variables:
183: TeX-directory
184: Directory in which to create temporary files for TeX jobs
185: run by \\[TeX-region] or \\[TeX-buffer].
186: TeX-dvi-print-command
187: Command string used by \\[TeX-print] to print a .dvi file.
188: TeX-show-queue-command
189: Command string used by \\[TeX-show-print-queue] to show the print
190: queue that \\[TeX-print] put your job on.
191:
192: Entering LaTeX mode calls the value of text-mode-hook,
193: then the value of TeX-mode-hook, and then the value
194: of LaTeX-mode-hook."
195: (interactive)
196: (TeX-common-initialization)
197: (setq mode-name "LaTeX")
198: (setq major-mode 'LaTeX-mode)
199: (setq TeX-command "latex")
200: (setq TeX-start-of-header "\\documentstyle")
201: (setq TeX-end-of-header "\\begin{document}")
202: (setq TeX-trailer "\\end{document}\n")
203: (run-hooks 'text-mode-hook 'TeX-mode-hook 'LaTeX-mode-hook))
204:
205: (defun TeX-common-initialization ()
206: (kill-all-local-variables)
207: (use-local-map TeX-mode-map)
208: (setq local-abbrev-table text-mode-abbrev-table)
209: (if (null TeX-mode-syntax-table)
210: (progn
211: (setq TeX-mode-syntax-table (make-syntax-table))
212: (set-syntax-table TeX-mode-syntax-table)
213: (modify-syntax-entry ?\\ ".")
214: (modify-syntax-entry ?\f ">")
215: (modify-syntax-entry ?\n ">")
216: (modify-syntax-entry ?$ "$$")
217: (modify-syntax-entry ?% "<")
218: (modify-syntax-entry ?\" ".")
219: (modify-syntax-entry ?& ".")
220: (modify-syntax-entry ?_ ".")
221: (modify-syntax-entry ?@ "_")
222: (modify-syntax-entry ?~ " ")
223: (modify-syntax-entry ?' "w"))
224: (set-syntax-table TeX-mode-syntax-table))
225: (make-local-variable 'paragraph-start)
226: (setq paragraph-start "^[ \t]*$\\|^[\f\\\\%]")
227: (make-local-variable 'paragraph-separate)
228: (setq paragraph-separate paragraph-start)
229: (make-local-variable 'comment-start)
230: (setq comment-start "%")
231: (make-local-variable 'comment-start-skip)
232: (setq comment-start-skip "\\(\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
233: (make-local-variable 'comment-indent-hook)
234: (setq comment-indent-hook 'TeX-comment-indent)
235: (make-local-variable 'TeX-command)
236: (make-local-variable 'TeX-start-of-header)
237: (make-local-variable 'TeX-end-of-header)
238: (make-local-variable 'TeX-trailer))
239:
240: (defun TeX-comment-indent ()
241: (if (looking-at "%%%")
242: (current-column)
243: (skip-chars-backward " \t")
244: (max (if (bolp) 0 (1+ (current-column)))
245: comment-column)))
246:
247: (defun TeX-insert-quote (arg)
248: "Insert ``, '' or \" according to preceding character.
249: With prefix argument, always insert \" characters."
250: (interactive "P")
251: (if arg
252: (let ((count (prefix-numeric-value arg)))
253: (if (listp arg)
254: (self-insert-command 1) ;C-u always inserts just one
255: (self-insert-command count)))
256: (insert
257: (cond
258: ((or (bobp)
259: (save-excursion
260: (forward-char -1)
261: (looking-at "[ \t\n]\\|\\s(")))
262: "``")
263: ((= (preceding-char) ?\\)
264: ?\")
265: (t "''")))))
266:
267: (defun validate-TeX-buffer ()
268: "Check current buffer for paragraphs containing mismatched $'s.
269: As each such paragraph is found, a mark is pushed at its beginning,
270: and the location is displayed for a few seconds."
271: (interactive)
272: (let ((opoint (point)))
273: (goto-char (point-max))
274: ;; Does not use save-excursion
275: ;; because we do not want to save the mark.
276: (unwind-protect
277: (while (and (not (input-pending-p)) (not (bobp)))
278: (let ((end (point)))
279: (search-backward "\n\n" nil 'move)
280: (or (TeX-validate-paragraph (point) end)
281: (progn
282: (push-mark (point))
283: (message "Mismatch found in pararaph starting here")
284: (sit-for 4)))))
285: (goto-char opoint))))
286:
287: (defun TeX-validate-paragraph (start end)
288: (condition-case ()
289: (save-excursion
290: (save-restriction
291: (narrow-to-region start end)
292: (goto-char start)
293: (forward-sexp (- end start))
294: t))
295: (error nil)))
296:
297: (defun TeX-terminate-paragraph (inhibit-validation)
298: "Insert two newlines, breaking a paragraph for TeX.
299: Check for mismatched braces/$'s in paragraph being terminated.
300: A prefix arg inhibits the checking."
301: (interactive "P")
302: (or inhibit-validation
303: (TeX-validate-paragraph
304: (save-excursion
305: (search-backward "\n\n" nil 'move)
306: (point))
307: (point))
308: (message "Paragraph being closed appears to contain a mismatch"))
309: (insert "\n\n"))
310:
311: (defun TeX-insert-braces ()
312: "Make a pair of braces and be poised to type inside of them."
313: (interactive)
314: (insert ?\{)
315: (save-excursion
316: (insert ?})))
317:
318: ;;; Like TeX-insert-braces, but for LaTeX.
319: (defun TeX-close-LaTeX-block ()
320: "Creates an \\end{...} to match \\begin{...} on the current line and
321: puts point on the blank line between them."
322: (interactive "*")
323: (let ((fail-point (point)))
324: (end-of-line)
325: (if (re-search-backward "\\\\begin{\\([^}\n]*\\)}"
326: (save-excursion (beginning-of-line) (point)) t)
327: (let ((text (buffer-substring (match-beginning 1) (match-end 1)))
328: (indentation (current-column)))
329: (end-of-line)
330: (delete-horizontal-space)
331: (insert "\n\n")
332: (indent-to indentation)
333: (insert "\\end{" text "}")
334: (forward-line -1))
335: (goto-char fail-point)
336: (ding))))
337:
338: ;;; Invoking TeX in an inferior shell.
339:
340: ;;; Why use a shell instead of running TeX directly? Because if TeX
341: ;;; gets stuck, the user can switch to the shell window and type at it.
342:
343: ;;; The utility functions:
344:
345: (defun TeX-start-shell ()
346: (require 'shell)
347: (save-excursion
348: (set-buffer (make-shell "TeX-shell" nil nil "-v"))
349: (setq TeX-shell-map (copy-keymap shell-mode-map))
350: (TeX-define-common-keys TeX-shell-map)
351: (use-local-map TeX-shell-map)
352: (if (zerop (buffer-size))
353: (sleep-for 1))))
354:
355: (defun set-buffer-directory (buffer directory)
356: "Set BUFFER's default directory to be DIRECTORY."
357: (setq directory (file-name-as-directory (expand-file-name directory)))
358: (if (not (file-directory-p directory))
359: (error "%s is not a directory" directory)
360: (save-excursion
361: (set-buffer buffer)
362: (setq default-directory directory))))
363:
364: ;;; The commands:
365:
366: ;;; It's a kludge that we have to create a special buffer just
367: ;;; to write out the TeX-trailer. It would nice if there were a
368: ;;; function like write-region that would write literal strings.
369:
370: (defun TeX-region (beg end)
371: "Run TeX on the current region. A temporary file (TeX-zap-file) is
372: written in directory TeX-directory, and TeX is run in that directory.
373: If the buffer has a header, it is written to the temporary file before
374: the region itself. The buffer's header is all lines between the
375: strings defined by TeX-start-of-header and TeX-end-of-header
376: inclusive. The header must start in the first 100 lines. The value
377: of TeX-trailer is appended to the temporary file after the region."
378: (interactive "r")
379: (if (get-buffer "*TeX-shell*")
380: (TeX-kill-job)
381: (TeX-start-shell))
382: (or TeX-zap-file (setq TeX-zap-file (make-temp-name "#tz")))
383: (let ((tex-out-file (concat TeX-zap-file ".tex"))
384: (temp-buffer (get-buffer-create " TeX-Output-Buffer"))
385: (zap-directory
386: (file-name-as-directory (expand-file-name TeX-directory))))
387: (save-excursion
388: (save-restriction
389: (widen)
390: (goto-char (point-min))
391: (forward-line 100)
392: (let ((search-end (point))
393: (hbeg (point-min)) (hend (point-min))
394: (default-directory zap-directory))
395: (goto-char (point-min))
396: ;; Initialize the temp file with either the header or nothing
397: (if (search-forward TeX-start-of-header search-end t)
398: (progn
399: (beginning-of-line)
400: (setq hbeg (point)) ;mark beginning of header
401: (if (search-forward TeX-end-of-header nil t)
402: (progn (forward-line 1)
403: (setq hend (point))) ;mark end of header
404: (setq hbeg (point-min))))) ;no header
405: (write-region (min hbeg beg) hend tex-out-file nil nil)
406: (write-region (max beg hend) end tex-out-file t nil))
407: (let ((local-tex-trailer TeX-trailer))
408: (set-buffer temp-buffer)
409: (erase-buffer)
410: ;; make sure trailer isn't hidden by a comment
411: (insert-string "\n")
412: (if local-tex-trailer (insert-string local-tex-trailer))
413: (set-buffer-directory temp-buffer zap-directory)
414: (write-region (point-min) (point-max) tex-out-file t nil))))
415: (set-buffer-directory "*TeX-shell*" zap-directory)
416: (send-string "TeX-shell" (concat TeX-shell-cd-command " "
417: zap-directory "\n"))
418: (send-string "TeX-shell" (concat TeX-command " \""
419: tex-out-file "\"\n")))
420: (TeX-recenter-output-buffer 0))
421:
422: (defun TeX-buffer ()
423: "Run TeX on current buffer. See \\[TeX-region] for more information."
424: (interactive)
425: (TeX-region (point-min) (point-max)))
426:
427: (defun TeX-kill-job ()
428: "Kill the currently running TeX job."
429: (interactive)
430: (quit-process "TeX-shell" t))
431:
432: (defun TeX-recenter-output-buffer (linenum)
433: "Redisplay buffer of TeX job output so that most recent output can be seen.
434: The last line of the buffer is displayed on
435: line LINE of the window, or centered if LINE is nil."
436: (interactive "P")
437: (let ((tex-shell (get-buffer "*TeX-shell*"))
438: (old-buffer (current-buffer)))
439: (if (null tex-shell)
440: (message "No TeX output buffer")
441: (pop-to-buffer tex-shell)
442: (bury-buffer tex-shell)
443: (goto-char (point-max))
444: (recenter (if linenum
445: (prefix-numeric-value linenum)
446: (/ (window-height) 2)))
447: (pop-to-buffer old-buffer)
448: )))
449:
450: (defun TeX-print ()
451: "Print the .dvi file made by \\[TeX-region] or \\[TeX-buffer].
452: Runs the shell command defined by TeX-dvi-print-command."
453: (interactive)
454: (send-string "TeX-shell"
455: (concat TeX-dvi-print-command " \"" TeX-zap-file ".dvi\"\n"))
456: (TeX-recenter-output-buffer nil))
457:
458: (defun TeX-show-print-queue ()
459: "Show the print queue that \\[TeX-print] put your job on.
460: Runs the shell command defined by TeX-show-queue-command."
461: (interactive)
462: (if (not (get-buffer "*TeX-shell*"))
463: (TeX-start-shell))
464: (send-string "TeX-shell" (concat TeX-show-queue-command "\n"))
465: (TeX-recenter-output-buffer nil))
466:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.