*** empty log message ***
[bpt/emacs.git] / lisp / textmodes / tex-mode.el
CommitLineData
d501f516
ER
1;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands.
2
e5167999
ER
3;; Maintainer: Edward M. Reingold <reingold@cs.uiuc.edu>
4;; Last-Modified: 04 July 1992
d7b4d18f 5;; Keywords: tex
e5167999 6
528415e7
RS
7;; Contributions over the years by William F. Schelter, Dick King,
8;; Stephen Gildea, Michael Prange, and Edward M. Reingold.
9
e5167999 10;; Copyright (C) 1985, 1986, 1989, 1992 Free Software Foundation, Inc.
869bff31 11
12;; This file is part of GNU Emacs.
13
14;; GNU Emacs is free software; you can redistribute it and/or modify
15;; it under the terms of the GNU General Public License as published by
e5167999 16;; the Free Software Foundation; either version 2, or (at your option)
869bff31 17;; any later version.
18
19;; GNU Emacs is distributed in the hope that it will be useful,
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
25;; along with GNU Emacs; see the file COPYING. If not, write to
26;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
27
e5167999
ER
28;;; Code:
29
528415e7
RS
30(require 'comint)
31
32(defvar tex-shell-file-name nil
33 "*If non-nil, is file name to use for the subshell in which TeX is run.")
34
35(defvar tex-directory "."
36 "*Directory in which temporary files are left.
37You can make this /tmp if your TEXINPUTS has no relative directories in it
38and you don't try to apply \\[tex-region] or \\[tex-buffer] when there are
39\\input commands with relative directories.")
869bff31 40
528415e7
RS
41(defvar tex-offer-save t
42 "*If non-nil, ask about saving modified buffers before \\[tex-file] is run.")
869bff31 43
44(defvar tex-run-command "tex"
45 "*Command used to run TeX subjob.
528415e7
RS
46If this string contains an asterisk (*), it will be replaced by the
47filename; if not, the name of the file, preceded by blank, will be added to
48this string.")
869bff31 49
50(defvar latex-run-command "latex"
51 "*Command used to run LaTeX subjob.
528415e7
RS
52If this string contains an asterisk (*), it will be replaced by the
53filename; if not, the name of the file, preceded by blank, will be added to
54this string.")
55
56(defvar standard-latex-block-names
57 '("abstract" "array" "center" "description"
58 "displaymath" "document" "enumerate" "eqnarray"
59 "eqnarray*" "equation" "figure" "figure*"
60 "flushleft" "flushright" "itemize" "letter"
61 "list" "minipage" "picture" "quotation"
62 "quote" "slide" "sloppypar" "tabbing"
63 "table" "table*" "tabular" "tabular*"
64 "thebibliography" "theindex*" "titlepage" "trivlist"
65 "verbatim" "verbatim*" "verse")
66 "Standard LaTeX block names.")
67
68(defvar latex-block-names nil
69 "*User defined LaTeX block names.
70Combined with `standard-latex-block-names' for minibuffer completion.")
869bff31 71
72(defvar slitex-run-command "slitex"
73 "*Command used to run SliTeX subjob.
528415e7
RS
74If this string contains an asterisk (*), it will be replaced by the
75filename; if not, the name of the file, preceded by blank, will be added to
76this string.")
869bff31 77
78(defvar tex-bibtex-command "bibtex"
528415e7
RS
79 "*Command used by `tex-bibtex-file' to gather bibliographic data.
80If this string contains an asterisk (*), it will be replaced by the
81filename; if not, the name of the file, preceded by blank, will be added to
82this string.")
869bff31 83
84(defvar tex-dvi-print-command "lpr -d"
528415e7
RS
85 "*Command used by \\[tex-print] to print a .dvi file.
86If this string contains an asterisk (*), it will be replaced by the
87filename; if not, the name of the file, preceded by blank, will be added to
88this string.")
89
90(defvar tex-alt-dvi-print-command "lpr -d"
91 "*Command used by \\[tex-print] with a prefix arg to print a .dvi file.
92If this string contains an asterisk (*), it will be replaced by the
93filename; if not, the name of the file, preceded by blank, will be added to
94this string.
95
96If two printers are not enough of a choice, you can define the value
97of tex-alt-dvi-print-command to be an expression that asks what you want;
98for example,
99
100 (setq tex-alt-dvi-print-command
101 '(format \"lpr -P%s\" (read-string \"Use printer: \")))
102
103would tell \\[tex-print] with a prefix argument to ask you which printer to
104use.")
869bff31 105
106(defvar tex-dvi-view-command nil
528415e7
RS
107 "*Command used by \\[tex-view] to display a .dvi file.
108If this string contains an asterisk (*), it will be replaced by the
109filename; if not, the name of the file, preceded by blank, will be added to
110this string.
111
112This can be set conditionally so that the previewer used is suitable for the
113window system being used. For example,
114
115 (setq tex-dvi-view-command
116 (if (eq window-system 'x) \"xdvi\" \"dvi2tty * | cat -s\"))
117
118would tell \\[tex-view] use xdvi under X windows and to use dvi2tty
119otherwise.")
869bff31 120
121(defvar tex-show-queue-command "lpq"
528415e7
RS
122 "*Command used by \\[tex-show-print-queue] to show the print queue.
123Should show the queue(s) that \\[tex-print] puts jobs on.")
869bff31 124
125(defvar tex-default-mode 'plain-tex-mode
126 "*Mode to enter for a new file that might be either TeX or LaTeX.
127This variable is used when it can't be determined whether the file
128is plain TeX or LaTeX or what because the file contains no commands.
129Normally set to either 'plain-tex-mode or 'latex-mode.")
130
131(defvar tex-open-quote "``"
132 "*String inserted by typing \\[tex-insert-quote] to open a quotation.")
133
134(defvar tex-close-quote "''"
135 "*String inserted by typing \\[tex-insert-quote] to close a quotation.")
136
528415e7
RS
137(defvar tex-last-temp-file nil
138 "Latest temporary file generated by \\[tex-region] and \\[tex-buffer].
139Deleted when the \\[tex-region] or \\[tex-buffer] is next run, or when the
140tex-shell goes away.")
141
869bff31 142(defvar tex-command nil
143 "Command to run TeX.
528415e7 144The name of the file, preceded by a blank, will be added to this string.")
869bff31 145
146(defvar tex-trailer nil
147 "String appended after the end of a region sent to TeX by \\[tex-region].")
148
149(defvar tex-start-of-header nil
150 "String used by \\[tex-region] to delimit the start of the file's header.")
151
152(defvar tex-end-of-header nil
153 "String used by \\[tex-region] to delimit the end of the file's header.")
154
155(defvar tex-shell-cd-command "cd"
156 "Command to give to shell running TeX to change directory.
157The value of tex-directory will be appended to this, separated by a space.")
158
159(defvar tex-zap-file nil
160 "Temporary file name used for text being sent as input to TeX.
161Should be a simple file name with no extension or directory specification.")
162
163(defvar tex-last-buffer-texed nil
164 "Buffer which was last TeXed.")
165
166(defvar tex-print-file nil
167 "File name that \\[tex-print] prints.
168Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")
169
170(defvar tex-mode-syntax-table nil
171 "Syntax table used while in TeX mode.")
172
173(defun tex-define-common-keys (keymap)
174 "Define the keys that we want defined both in TeX mode and in the tex-shell."
175 (define-key keymap "\C-c\C-k" 'tex-kill-job)
176 (define-key keymap "\C-c\C-l" 'tex-recenter-output-buffer)
177 (define-key keymap "\C-c\C-q" 'tex-show-print-queue)
178 (define-key keymap "\C-c\C-p" 'tex-print)
179 (define-key keymap "\C-c\C-v" 'tex-view)
180 )
181
182(defvar tex-mode-map nil "Keymap for TeX mode.")
183
184(if tex-mode-map
185 nil
186 (setq tex-mode-map (make-sparse-keymap))
187 (tex-define-common-keys tex-mode-map)
188 (define-key tex-mode-map "\"" 'tex-insert-quote)
189 (define-key tex-mode-map "\n" 'tex-terminate-paragraph)
190 (define-key tex-mode-map "\C-c}" 'up-list)
191 (define-key tex-mode-map "\C-c{" 'tex-insert-braces)
192 (define-key tex-mode-map "\C-c\C-r" 'tex-region)
193 (define-key tex-mode-map "\C-c\C-b" 'tex-buffer)
194 (define-key tex-mode-map "\C-c\C-f" 'tex-file)
195 (define-key tex-mode-map "\C-c\C-i" 'tex-bibtex-file)
196 (define-key tex-mode-map "\C-c\C-o" 'tex-latex-block)
197 (define-key tex-mode-map "\C-c\C-e" 'tex-close-latex-block))
198
199(defvar tex-shell-map nil
528415e7 200 "Keymap for the tex-shell. A comint-mode-map with a few additions.")
869bff31 201
202;(fset 'TeX-mode 'tex-mode) ;in loaddefs.
203
204;;; This would be a lot simpler if we just used a regexp search,
205;;; but then it would be too slow.
7229064d 206;;;###autoload
869bff31 207(defun tex-mode ()
208 "Major mode for editing files of input for TeX, LaTeX, or SliTeX.
209Tries to determine (by looking at the beginning of the file) whether
210this file is for plain TeX, LaTeX, or SliTeX and calls plain-tex-mode,
211latex-mode, or slitex-mode, respectively. If it cannot be determined,
212such as if there are no commands in the file, the value of tex-default-mode
213is used."
214 (interactive)
215 (let (mode slash comment)
216 (save-excursion
217 (goto-char (point-min))
218 (while (and (setq slash (search-forward "\\" nil t))
219 (setq comment (let ((search-end (point)))
220 (save-excursion
221 (beginning-of-line)
222 (search-forward "%" search-end t))))))
223 (if (and slash (not comment))
224 (setq mode (if (looking-at "documentstyle")
225 (if (looking-at "documentstyle{slides}")
226 'slitex-mode
227 'latex-mode)
228 'plain-tex-mode))))
229 (if mode (funcall mode)
230 (funcall tex-default-mode))))
6503cec3
JB
231;;;###autoload
232(fset 'TeX-mode 'tex-mode)
233;;;###autoload
234(fset 'LaTeX-mode 'latex-mode)
869bff31 235
7229064d 236;;;###autoload
869bff31 237(defun plain-tex-mode ()
238 "Major mode for editing files of input for plain TeX.
239Makes $ and } display the characters they match.
240Makes \" insert `` when it seems to be the beginning of a quotation,
241and '' when it appears to be the end; it inserts \" only after a \\.
242
243Use \\[tex-region] to run TeX on the current region, plus a \"header\"
244copied from the top of the file (containing macro definitions, etc.),
245running TeX under a special subshell. \\[tex-buffer] does the whole buffer.
246\\[tex-file] saves the buffer and then processes the file.
247\\[tex-print] prints the .dvi file made by any of these.
248\\[tex-view] previews the .dvi file made by any of these.
249\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
250
251Use \\[validate-tex-buffer] to check buffer for paragraphs containing
252mismatched $'s or braces.
253
254Special commands:
255\\{tex-mode-map}
256
257Mode variables:
258tex-run-command
259 Command string used by \\[tex-region] or \\[tex-buffer].
260tex-directory
261 Directory in which to create temporary files for TeX jobs
262 run by \\[tex-region] or \\[tex-buffer].
263tex-dvi-print-command
264 Command string used by \\[tex-print] to print a .dvi file.
528415e7
RS
265tex-alt-dvi-print-command
266 Alternative command string used by \\[tex-print] (when given a prefix
267 argument) to print a .dvi file.
869bff31 268tex-dvi-view-command
269 Command string used by \\[tex-view] to preview a .dvi file.
270tex-show-queue-command
271 Command string used by \\[tex-show-print-queue] to show the print
272 queue that \\[tex-print] put your job on.
273
274Entering Plain-tex mode calls the value of text-mode-hook, then the value of
275tex-mode-hook, and then the value of plain-tex-mode-hook. When the special
276subshell is initiated, the value of tex-shell-hook is called."
277 (interactive)
278 (tex-common-initialization)
279 (setq mode-name "TeX")
280 (setq major-mode 'plain-tex-mode)
281 (setq tex-command tex-run-command)
282 (setq tex-start-of-header "%**start of header")
283 (setq tex-end-of-header "%**end of header")
284 (setq tex-trailer "\\bye\n")
285 (run-hooks 'text-mode-hook 'tex-mode-hook 'plain-tex-mode-hook))
6503cec3
JB
286;;;###autoload
287(fset 'plain-TeX-mode 'plain-tex-mode)
869bff31 288
7229064d 289;;;###autoload
869bff31 290(defun latex-mode ()
291 "Major mode for editing files of input for LaTeX.
292Makes $ and } display the characters they match.
293Makes \" insert `` when it seems to be the beginning of a quotation,
294and '' when it appears to be the end; it inserts \" only after a \\.
295
296Use \\[tex-region] to run LaTeX on the current region, plus the preamble
297copied from the top of the file (containing \\documentstyle, etc.),
298running LaTeX under a special subshell. \\[tex-buffer] does the whole buffer.
299\\[tex-file] saves the buffer and then processes the file.
300\\[tex-print] prints the .dvi file made by any of these.
301\\[tex-view] previews the .dvi file made by any of these.
302\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
303
304Use \\[validate-tex-buffer] to check buffer for paragraphs containing
305mismatched $'s or braces.
306
307Special commands:
308\\{tex-mode-map}
309
310Mode variables:
311latex-run-command
312 Command string used by \\[tex-region] or \\[tex-buffer].
313tex-directory
314 Directory in which to create temporary files for LaTeX jobs
315 run by \\[tex-region] or \\[tex-buffer].
316tex-dvi-print-command
317 Command string used by \\[tex-print] to print a .dvi file.
528415e7
RS
318tex-alt-dvi-print-command
319 Alternative command string used by \\[tex-print] (when given a prefix
320 argument) to print a .dvi file.
869bff31 321tex-dvi-view-command
322 Command string used by \\[tex-view] to preview a .dvi file.
323tex-show-queue-command
324 Command string used by \\[tex-show-print-queue] to show the print
325 queue that \\[tex-print] put your job on.
326
327Entering Latex mode calls the value of text-mode-hook, then the value of
328tex-mode-hook, and then the value of latex-mode-hook. When the special
329subshell is initiated, the value of tex-shell-hook is called."
330 (interactive)
331 (tex-common-initialization)
332 (setq mode-name "LaTeX")
333 (setq major-mode 'latex-mode)
334 (setq tex-command latex-run-command)
335 (setq tex-start-of-header "\\documentstyle")
336 (setq tex-end-of-header "\\begin{document}")
337 (setq tex-trailer "\\end{document}\n")
338 (run-hooks 'text-mode-hook 'tex-mode-hook 'latex-mode-hook))
339
340(defun slitex-mode ()
341 "Major mode for editing files of input for SliTeX.
342Makes $ and } display the characters they match.
343Makes \" insert `` when it seems to be the beginning of a quotation,
344and '' when it appears to be the end; it inserts \" only after a \\.
345
346Use \\[tex-region] to run SliTeX on the current region, plus the preamble
347copied from the top of the file (containing \\documentstyle, etc.),
348running SliTeX under a special subshell. \\[tex-buffer] does the whole buffer.
349\\[tex-file] saves the buffer and then processes the file.
350\\[tex-print] prints the .dvi file made by any of these.
351\\[tex-view] previews the .dvi file made by any of these.
352\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
353
354Use \\[validate-tex-buffer] to check buffer for paragraphs containing
355mismatched $'s or braces.
356
357Special commands:
358\\{tex-mode-map}
359
360Mode variables:
361slitex-run-command
362 Command string used by \\[tex-region] or \\[tex-buffer].
363tex-directory
364 Directory in which to create temporary files for SliTeX jobs
365 run by \\[tex-region] or \\[tex-buffer].
366tex-dvi-print-command
367 Command string used by \\[tex-print] to print a .dvi file.
528415e7
RS
368tex-alt-dvi-print-command
369 Alternative command string used by \\[tex-print] (when given a prefix
370 argument) to print a .dvi file.
869bff31 371tex-dvi-view-command
372 Command string used by \\[tex-view] to preview a .dvi file.
373tex-show-queue-command
374 Command string used by \\[tex-show-print-queue] to show the print
375 queue that \\[tex-print] put your job on.
376
528415e7 377Entering SliTeX mode calls the value of text-mode-hook, then the value of
869bff31 378tex-mode-hook, then the value of latex-mode-hook, and then the value of
379slitex-mode-hook. When the special subshell is initiated, the value of
380tex-shell-hook is called."
381 (interactive)
382 (tex-common-initialization)
383 (setq mode-name "SliTeX")
384 (setq major-mode 'slitex-mode)
385 (setq tex-command slitex-run-command)
386 (setq tex-start-of-header "\\documentstyle{slides}")
387 (setq tex-end-of-header "\\begin{document}")
388 (setq tex-trailer "\\end{document}\n")
389 (run-hooks
390 'text-mode-hook 'tex-mode-hook 'latex-mode-hook 'slitex-mode-hook))
391
392(defun tex-common-initialization ()
393 (kill-all-local-variables)
394 (use-local-map tex-mode-map)
395 (setq local-abbrev-table text-mode-abbrev-table)
396 (if (null tex-mode-syntax-table)
397 (let ((char 0))
398 (setq tex-mode-syntax-table (make-syntax-table))
399 (set-syntax-table tex-mode-syntax-table)
400 (while (< char ? )
401 (modify-syntax-entry char ".")
402 (setq char (1+ char)))
403 (modify-syntax-entry ?\C-@ "w")
404 (modify-syntax-entry ?\t " ")
405 (modify-syntax-entry ?\n ">")
406 (modify-syntax-entry ?\f ">")
407 (modify-syntax-entry ?$ "$$")
408 (modify-syntax-entry ?% "<")
409 (modify-syntax-entry ?\\ "/")
410 (modify-syntax-entry ?\" ".")
411 (modify-syntax-entry ?& ".")
412 (modify-syntax-entry ?_ ".")
413 (modify-syntax-entry ?@ "_")
414 (modify-syntax-entry ?~ " ")
415 (modify-syntax-entry ?' "w"))
416 (set-syntax-table tex-mode-syntax-table))
417 (make-local-variable 'paragraph-start)
418 (setq paragraph-start "^[ \t]*$\\|^[\f\\\\%]")
419 (make-local-variable 'paragraph-separate)
420 (setq paragraph-separate paragraph-start)
421 (make-local-variable 'comment-start)
422 (setq comment-start "%")
423 (make-local-variable 'comment-start-skip)
424 (setq comment-start-skip "\\(\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
425 (make-local-variable 'comment-indent-hook)
426 (setq comment-indent-hook 'tex-comment-indent)
427 (make-local-variable 'compare-windows-whitespace)
428 (setq compare-windows-whitespace 'tex-categorize-whitespace)
429 (make-local-variable 'tex-command)
430 (make-local-variable 'tex-start-of-header)
431 (make-local-variable 'tex-end-of-header)
432 (make-local-variable 'tex-trailer))
433
434(defun tex-comment-indent ()
435 (if (looking-at "%%%")
436 (current-column)
437 (skip-chars-backward " \t")
438 (max (if (bolp) 0 (1+ (current-column)))
439 comment-column)))
440
441(defun tex-categorize-whitespace (backward-limit)
442 ;; compare-windows-whitespace is set to this.
443 ;; This is basically a finite-state machine.
444 ;; Returns a symbol telling how TeX would treat
445 ;; the whitespace we are looking at: null, space, or par.
446 (let ((category 'null)
447 (not-finished t))
448 (skip-chars-backward " \t\n\f" backward-limit)
449 (while not-finished
450 (cond ((looking-at "[ \t]+")
451 (goto-char (match-end 0))
452 (if (eql category 'null)
453 (setq category 'space)))
454 ((looking-at "\n")
455 (cond ((eql category 'newline)
456 (setq category 'par)
457 (setq not-finished nil))
458 (t
459 (setq category 'newline) ;a strictly internal state
460 (goto-char (match-end 0)))))
461 ((looking-at "\f+")
462 (setq category 'par)
463 (setq not-finished nil))
464 (t
465 (setq not-finished nil))))
466 (skip-chars-forward " \t\n\f")
467 (if (eql category 'newline)
468 'space ;TeX doesn't distinguish
469 category)))
470
471(defun tex-insert-quote (arg)
472 "Insert the appropriate quote marks for TeX.
473Inserts the value of tex-open-quote (normally ``) or tex-close-quote
474(normally '') depending on the context. With prefix argument, always
475inserts \" characters."
528415e7 476 (interactive "*P")
869bff31 477 (if arg
478 (self-insert-command (prefix-numeric-value arg))
479 (insert
480 (cond ((or (bobp)
481 (save-excursion
482 (forward-char -1)
483 (looking-at "\\s(\\|\\s \\|\\s>")))
484 tex-open-quote)
485 ((= (preceding-char) ?\\)
486 ?\")
487 (t
488 tex-close-quote)))))
489
490(defun validate-tex-buffer ()
491 "Check current buffer for paragraphs containing mismatched $'s.
492As each such paragraph is found, a mark is pushed at its beginning,
493and the location is displayed for a few seconds."
494 (interactive)
495 (let ((opoint (point)))
496 (goto-char (point-max))
497 ;; Does not use save-excursion
498 ;; because we do not want to save the mark.
499 (unwind-protect
500 (while (and (not (input-pending-p)) (not (bobp)))
501 (let ((end (point)))
502 (search-backward "\n\n" nil 'move)
503 (or (tex-validate-region (point) end)
504 (progn
505 (push-mark (point))
506 (message "Mismatch found in pararaph starting here")
507 (sit-for 4)))))
508 (goto-char opoint))))
509
510(defun tex-validate-region (start end)
511 "Check for mismatched braces or $'s in region.
512Returns t if no mismatches. Returns nil and moves point to suspect
513area if a mismatch is found."
514 (interactive "r")
515 (let ((failure-point nil) (max-possible-sexps (- end start)))
516 (save-excursion
517 (condition-case ()
518 (save-restriction
519 (narrow-to-region start end)
520 (goto-char start)
521 (while (< 0 (setq max-possible-sexps (1- max-possible-sexps)))
522 (forward-sexp 1)))
523 (error
524 (setq failure-point (point)))))
525 (if failure-point
526 (progn
527 (goto-char failure-point)
528 nil)
529 t)))
530
531(defun tex-terminate-paragraph (inhibit-validation)
532 "Insert two newlines, breaking a paragraph for TeX.
533Check for mismatched braces/$'s in paragraph being terminated.
534A prefix arg inhibits the checking."
528415e7 535 (interactive "*P")
869bff31 536 (or inhibit-validation
537 (save-excursion
538 (tex-validate-region
539 (save-excursion
540 (search-backward "\n\n" nil 'move)
541 (point))
542 (point)))
543 (message "Paragraph being closed appears to contain a mismatch"))
544 (insert "\n\n"))
545
546(defun tex-insert-braces ()
547 "Make a pair of braces and be poised to type inside of them."
528415e7 548 (interactive "*")
869bff31 549 (insert ?\{)
550 (save-excursion
551 (insert ?})))
552
553;;; Like tex-insert-braces, but for LaTeX.
554(defun tex-latex-block (name)
555 "Creates a matching pair of lines \\begin{NAME} and \\end{NAME} at point.
556Puts point on a blank line between them."
528415e7
RS
557 (interactive
558 (prog2
559 (barf-if-buffer-read-only)
560 (list
561 (completing-read "LaTeX block name: "
562 (mapcar 'list
563 (append standard-latex-block-names
564 latex-block-names))))))
869bff31 565 (let ((col (current-column)))
566 (insert (format "\\begin{%s}\n" name))
567 (indent-to col)
568 (save-excursion
569 (insert ?\n)
570 (indent-to col)
571 (insert-string (format "\\end{%s}" name))
572 (if (eobp) (insert ?\n)))))
573
574(defun tex-last-unended-begin ()
575 "Leave point at the beginning of the last \\begin{...} that is unended."
576 (while (and (re-search-backward "\\(\\\\begin\\s *{\\)\\|\\(\\\\end\\s *{\\)")
577 (looking-at "\\\\end{"))
578 (tex-last-unended-begin)))
579
580(defun tex-close-latex-block ()
581 "Creates an \\end{...} to match the last unclosed \\begin{...}."
582 (interactive "*")
583 (let ((new-line-needed (bolp))
584 text indentation)
585 (save-excursion
528415e7 586 (condition-case nil
869bff31 587 (tex-last-unended-begin)
588 (error (error "Couldn't find unended \\begin")))
589 (setq indentation (current-column))
590 (re-search-forward "\\\\begin\\(\\s *{[^}\n]*}\\)")
591 (setq text (buffer-substring (match-beginning 1) (match-end 1))))
592 (indent-to indentation)
593 (insert "\\end" text)
594 (if new-line-needed (insert ?\n))))
595\f
596;;; Invoking TeX in an inferior shell.
597
598;;; Why use a shell instead of running TeX directly? Because if TeX
599;;; gets stuck, the user can switch to the shell window and type at it.
600
601;;; The utility functions:
602
603(defun tex-start-shell ()
604 (save-excursion
528415e7
RS
605 (set-buffer
606 (make-comint
607 "tex-shell"
608 (or tex-shell-file-name (getenv "ESHELL") (getenv "SHELL") "/bin/sh")
609 nil "-v"))
610 (let ((proc (get-process "tex-shell")))
611 (set-process-sentinel proc 'tex-shell-sentinel)
612 (process-kill-without-query proc)
613 (setq tex-shell-map (copy-keymap comint-mode-map))
614 (tex-define-common-keys tex-shell-map)
615 (use-local-map tex-shell-map)
616 (run-hooks 'tex-shell-hook)
617 (while (zerop (buffer-size))
618 (sleep-for 1)))))
619
620(defun tex-shell-sentinel (proc msg)
621 (cond ((null (buffer-name (process-buffer proc)))
622 ;; buffer killed
623 (set-process-buffer proc nil)
624 (tex-delete-last-temp-files))
625 ((memq (process-status proc) '(signal exit))
626 (tex-delete-last-temp-files))))
627
628(defun tex-set-buffer-directory (buffer directory)
869bff31 629 "Set BUFFER's default directory to be DIRECTORY."
630 (setq directory (file-name-as-directory (expand-file-name directory)))
631 (if (not (file-directory-p directory))
632 (error "%s is not a directory" directory)
633 (save-excursion
634 (set-buffer buffer)
635 (setq default-directory directory))))
636
528415e7
RS
637(defun tex-send-command (command &optional file background)
638 "Send COMMAND to tex-shell, substituting optional FILE for *; in background
639if optional BACKGROUND is t. If COMMAND has no *, FILE will be appended,
640preceded by a blank, to COMMAND. If FILE is nil, no substitution will be made
641in COMMAND. COMMAND can be any expression that evaluates to a command string."
642 (save-excursion
643 (let* ((cmd (eval command))
644 (star (string-match "\\*" cmd)))
645 (comint-proc-query (get-process "tex-shell")
646 (concat (substring cmd 0 star)
647 (if file (concat " " file) "")
648 (if star (substring cmd (1+ star) nil) "")
649 (if background "&\n" "\n"))))))
650
651(defun tex-delete-last-temp-files ()
652 "Delete any junk files from last temp file."
653 (if tex-last-temp-file
654 (let* ((dir (file-name-directory tex-last-temp-file))
655 (list (file-name-all-completions
656 (file-name-nondirectory tex-last-temp-file) dir)))
657 (while list
658 (delete-file (concat dir (car list)))
659 (setq list (cdr list))))))
660
99621a14 661(add-hook 'kill-emacs-hook 'tex-delete-last-temp-files)
869bff31 662
528415e7 663;;; The commands:
869bff31 664
665(defun tex-region (beg end)
666 "Run TeX on the current region, via a temporary file.
667The file's name comes from the variable `tex-zap-file' and the
668variable `tex-directory' says where to put it.
669
670If the buffer has a header, the header is given to TeX before the
671region itself. The buffer's header is all lines between the strings
672defined by `tex-start-of-header' and `tex-end-of-header' inclusive.
673The header must start in the first 100 lines of the buffer.
674
675The value of `tex-trailer' is given to TeX as input after the region.
676
677The value of `tex-command' specifies the command to use to run TeX."
678 (interactive "r")
679 (if (tex-shell-running)
680 (tex-kill-job)
681 (tex-start-shell))
682 (or tex-zap-file
683 (setq tex-zap-file (tex-generate-zap-file-name)))
528415e7
RS
684 (let* ((temp-buffer (get-buffer-create " TeX-Output-Buffer"))
685 ; Temp file will be written and TeX will be run in zap-directory.
686 ; If the TEXINPUTS file has relative directories or if the region has
687 ; \input of files, this must be the same directory as the file for
688 ; TeX to access the correct inputs. That's why it's safest if
689 ; tex-directory is ".".
690 (zap-directory
691 (file-name-as-directory (expand-file-name tex-directory)))
692 (tex-out-file (concat zap-directory tex-zap-file)))
693 (tex-delete-last-temp-files)
869bff31 694 ;; Write the new temp file.
695 (save-excursion
696 (save-restriction
697 (widen)
698 (goto-char (point-min))
699 (forward-line 100)
700 (let ((search-end (point))
701 (hbeg (point-min)) (hend (point-min))
702 (default-directory zap-directory))
703 (goto-char (point-min))
704 ;; Initialize the temp file with either the header or nothing
705 (if (search-forward tex-start-of-header search-end t)
706 (progn
707 (beginning-of-line)
708 (setq hbeg (point)) ;mark beginning of header
709 (if (search-forward tex-end-of-header nil t)
710 (progn (forward-line 1)
711 (setq hend (point))) ;mark end of header
712 (setq hbeg (point-min))))) ;no header
528415e7
RS
713 (write-region (min hbeg beg) hend
714 (concat tex-out-file ".tex") nil nil)
715 (write-region (max beg hend) end (concat tex-out-file ".tex") t nil))
869bff31 716 (let ((local-tex-trailer tex-trailer))
717 (set-buffer temp-buffer)
718 (erase-buffer)
719 ;; make sure trailer isn't hidden by a comment
720 (insert-string "\n")
721 (if local-tex-trailer (insert-string local-tex-trailer))
528415e7
RS
722 (tex-set-buffer-directory temp-buffer zap-directory)
723 (write-region (point-min) (point-max)
724 (concat tex-out-file ".tex") t nil))))
725 ;; Record the file name to be deleted afterward.
726 (setq tex-last-temp-file tex-out-file)
727 (tex-send-command tex-shell-cd-command zap-directory)
728 (tex-send-command tex-command tex-out-file)
729 (setq tex-print-file tex-out-file)
730 (setq tex-last-buffer-texed (current-buffer))))
869bff31 731
732(defun tex-buffer ()
733 "Run TeX on current buffer. See \\[tex-region] for more information.
528415e7
RS
734Does not save the buffer, so it's useful for trying experimental versions.
735See \\[tex-file] for an alternative."
869bff31 736 (interactive)
737 (tex-region (point-min) (point-max)))
738
739(defun tex-file ()
740 "Prompt to save all buffers and run TeX (or LaTeX) on current buffer's file.
741This function is more useful than \\[tex-buffer] when you need the
742`.aux' file of LaTeX to have the correct name."
743 (interactive)
744 (let ((tex-out-file
745 (if (buffer-file-name)
746 (file-name-nondirectory (buffer-file-name))
747 (error "Buffer does not seem to be associated with any file")))
748 (file-dir (file-name-directory (buffer-file-name))))
7047ec77 749 (if tex-offer-save
99621a14 750 (save-some-buffers))
869bff31 751 (if (tex-shell-running)
752 (tex-kill-job)
753 (tex-start-shell))
528415e7
RS
754 (tex-send-command tex-shell-cd-command file-dir)
755 (tex-send-command tex-command tex-out-file))
869bff31 756 (setq tex-last-buffer-texed (current-buffer))
528415e7 757 (setq tex-print-file (buffer-file-name)))
869bff31 758
759(defun tex-generate-zap-file-name ()
760 "Generate a unique name suitable for use as a file name."
761 ;; Include the shell process number and host name
762 ;; in case there are multiple shells (for same or different user).
763 (format "#tz%d%s"
764 (process-id (get-buffer-process "*tex-shell*"))
765 (tex-strip-dots (system-name))))
766
767(defun tex-strip-dots (s)
768 (setq s (copy-sequence s))
769 (while (string-match "\\." s)
770 (aset s (match-beginning 0) ?-))
771 s)
772
773;; This will perhaps be useful for modifying TEXINPUTS.
774;; Expand each file name, separated by colons, in the string S.
775(defun tex-expand-files (s)
776 (let (elts (start 0))
777 (while (string-match ":" s start)
778 (setq elts (cons (substring s start (match-beginning 0)) elts))
779 (setq start (match-end 0)))
780 (or (= start 0)
781 (setq elts (cons (substring s start) elts)))
782 (mapconcat 'expand-file-name (nreverse elts) ":")))
783
784(defun tex-shell-running ()
785 (and (get-process "tex-shell")
786 (eq (process-status (get-process "tex-shell")) 'run)))
787
788(defun tex-kill-job ()
789 "Kill the currently running TeX job."
790 (interactive)
528415e7 791 (quit-process (get-process "tex-shell") t))
869bff31 792
793(defun tex-recenter-output-buffer (linenum)
794 "Redisplay buffer of TeX job output so that most recent output can be seen.
795The last line of the buffer is displayed on
796line LINE of the window, or centered if LINE is nil."
797 (interactive "P")
798 (let ((tex-shell (get-buffer "*tex-shell*"))
799 (old-buffer (current-buffer)))
800 (if (null tex-shell)
801 (message "No TeX output buffer")
802 (pop-to-buffer tex-shell)
803 (bury-buffer tex-shell)
804 (goto-char (point-max))
805 (recenter (if linenum
806 (prefix-numeric-value linenum)
807 (/ (window-height) 2)))
528415e7 808 (pop-to-buffer old-buffer))))
869bff31 809
528415e7 810(defun tex-print (&optional alt)
869bff31 811 "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file].
528415e7
RS
812Runs the shell command defined by tex-dvi-print-command. If prefix argument
813is provided, use the alternative command, tex-alt-dvi-print-command."
814 (interactive "P")
869bff31 815 (let ((print-file-name-dvi (tex-append tex-print-file ".dvi"))
816 test-name)
817 (if (and (not (equal (current-buffer) tex-last-buffer-texed))
818 (file-newer-than-file-p
819 (setq test-name (tex-append (buffer-file-name) ".dvi"))
528415e7 820 print-file-name-dvi))
869bff31 821 (setq print-file-name-dvi test-name))
528415e7
RS
822 (if (not (file-exists-p print-file-name-dvi))
823 (error "No appropriate `.dvi' file could be found")
824 (tex-send-command
825 (if alt tex-alt-dvi-print-command tex-dvi-print-command)
826 print-file-name-dvi t))))
869bff31 827
828(defun tex-view ()
829 "Preview the last `.dvi' file made by running TeX under Emacs.
830This means, made using \\[tex-region], \\[tex-buffer] or \\[tex-file].
831The variable `tex-dvi-view-command' specifies the shell command for preview."
832 (interactive)
833 (let ((tex-dvi-print-command tex-dvi-view-command))
834 (tex-print)))
835
836(defun tex-append (file-name suffix)
837 "Append to FILENAME the suffix SUFFIX, using same algorithm TeX uses.
838Scans for the first (not last) period.
839No period is retained immediately before SUFFIX,
840so normally SUFFIX starts with one."
841 (if (stringp file-name)
842 (let ((file (file-name-nondirectory file-name)))
843 (concat (file-name-directory file-name)
844 (substring file 0
845 (string-match "\\." file))
846 suffix))
847 " "))
848
849(defun tex-show-print-queue ()
850 "Show the print queue that \\[tex-print] put your job on.
851Runs the shell command defined by tex-show-queue-command."
852 (interactive)
853 (if (tex-shell-running)
854 (tex-kill-job)
855 (tex-start-shell))
528415e7 856 (tex-send-command tex-show-queue-command))
869bff31 857
858(defun tex-bibtex-file ()
859 "Run BibTeX on the current buffer's file."
860 (interactive)
861 (if (tex-shell-running)
862 (tex-kill-job)
863 (tex-start-shell))
864 (let ((tex-out-file
865 (tex-append (file-name-nondirectory (buffer-file-name)) ""))
866 (file-dir (file-name-directory (buffer-file-name))))
528415e7
RS
867 (tex-send-command tex-shell-cd-command file-dir)
868 (tex-send-command bibtex-command tex-out-file)))
869
870(run-hooks 'tex-mode-load-hook)
869bff31 871
49116ac0
JB
872(provide 'tex-mode)
873
d501f516 874;;; tex-mode.el ends here
99621a14 875