(completion-ignored-extensions):
[bpt/emacs.git] / lisp / textmodes / tex-mode.el
CommitLineData
d501f516
ER
1;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands.
2
9596811a 3;; Copyright (C) 1985, 86, 89, 92, 94, 95, 96 Free Software Foundation, Inc.
eea8d4ef 4
70f20973 5;; Maintainer: FSF
d7b4d18f 6;; Keywords: tex
e5167999 7
528415e7 8;; Contributions over the years by William F. Schelter, Dick King,
70f20973 9;; Stephen Gildea, Michael Prange, Jacob Gore, and Edward M. Reingold.
528415e7 10
869bff31 11;; This file is part of GNU Emacs.
12
13;; GNU Emacs is free software; you can redistribute it and/or modify
14;; it under the terms of the GNU General Public License as published by
e5167999 15;; the Free Software Foundation; either version 2, or (at your option)
869bff31 16;; any later version.
17
18;; GNU Emacs is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
6da9bbd6
RS
24;; along with GNU Emacs; see the file COPYING. If not, write to the
25;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26;; Boston, MA 02111-1307, USA.
869bff31 27
e5167999
ER
28;;; Code:
29
a0e9c22a 30(require 'shell)
2f3067de 31(require 'compile)
528415e7 32
7e1dae73 33;;;###autoload
528415e7 34(defvar tex-shell-file-name nil
81c735c0 35 "*If non-nil, the shell file name to run in the subshell used to run TeX.")
528415e7 36
7e1dae73 37;;;###autoload
528415e7 38(defvar tex-directory "."
f73741fc 39 "*Directory in which temporary files are written.
81c735c0 40You can make this `/tmp' if your TEXINPUTS has no relative directories in it
528415e7 41and you don't try to apply \\[tex-region] or \\[tex-buffer] when there are
81c735c0 42`\\input' commands with relative directories.")
869bff31 43
f73741fc 44;;;###autoload
ebe15e27 45(defvar tex-main-file nil
f73741fc
RS
46 "*The main TeX source file which includes this buffer's file.
47The command `tex-buffer' runs TeX on `tex-main-file'if that is non-nil.")
48
7e1dae73 49;;;###autoload
528415e7
RS
50(defvar tex-offer-save t
51 "*If non-nil, ask about saving modified buffers before \\[tex-file] is run.")
869bff31 52
7e1dae73 53;;;###autoload
869bff31 54(defvar tex-run-command "tex"
55 "*Command used to run TeX subjob.
81c735c0
RS
56If this string contains an asterisk (`*'), that is replaced by the file name;
57otherwise, the file name, preceded by blank, is added at the end.")
869bff31 58
7e1dae73 59;;;###autoload
869bff31 60(defvar latex-run-command "latex"
61 "*Command used to run LaTeX subjob.
81c735c0
RS
62If this string contains an asterisk (`*'), that is replaced by the file name;
63otherwise, the file name, preceded by blank, is added at the end.")
528415e7
RS
64
65(defvar standard-latex-block-names
66 '("abstract" "array" "center" "description"
67 "displaymath" "document" "enumerate" "eqnarray"
68 "eqnarray*" "equation" "figure" "figure*"
69 "flushleft" "flushright" "itemize" "letter"
70 "list" "minipage" "picture" "quotation"
71 "quote" "slide" "sloppypar" "tabbing"
72 "table" "table*" "tabular" "tabular*"
73 "thebibliography" "theindex*" "titlepage" "trivlist"
74 "verbatim" "verbatim*" "verse")
75 "Standard LaTeX block names.")
76
7e1dae73 77;;;###autoload
528415e7
RS
78(defvar latex-block-names nil
79 "*User defined LaTeX block names.
80Combined with `standard-latex-block-names' for minibuffer completion.")
869bff31 81
7e1dae73 82;;;###autoload
869bff31 83(defvar slitex-run-command "slitex"
84 "*Command used to run SliTeX subjob.
81c735c0
RS
85If this string contains an asterisk (`*'), that is replaced by the file name;
86otherwise, the file name, preceded by blank, is added at the end.")
869bff31 87
7e1dae73 88;;;###autoload
869bff31 89(defvar tex-bibtex-command "bibtex"
528415e7 90 "*Command used by `tex-bibtex-file' to gather bibliographic data.
81c735c0
RS
91If this string contains an asterisk (`*'), that is replaced by the file name;
92otherwise, the file name, preceded by blank, is added at the end.")
869bff31 93
7e1dae73 94;;;###autoload
869bff31 95(defvar tex-dvi-print-command "lpr -d"
528415e7 96 "*Command used by \\[tex-print] to print a .dvi file.
81c735c0
RS
97If this string contains an asterisk (`*'), that is replaced by the file name;
98otherwise, the file name, preceded by blank, is added at the end.")
528415e7 99
7e1dae73 100;;;###autoload
528415e7
RS
101(defvar tex-alt-dvi-print-command "lpr -d"
102 "*Command used by \\[tex-print] with a prefix arg to print a .dvi file.
81c735c0
RS
103If this string contains an asterisk (`*'), that is replaced by the file name;
104otherwise, the file name, preceded by blank, is added at the end.
528415e7 105
81c735c0
RS
106If two printers are not enough of a choice, you can set the variable
107`tex-alt-dvi-print-command' to an expression that asks what you want;
528415e7
RS
108for example,
109
110 (setq tex-alt-dvi-print-command
111 '(format \"lpr -P%s\" (read-string \"Use printer: \")))
112
113would tell \\[tex-print] with a prefix argument to ask you which printer to
114use.")
869bff31 115
7e1dae73 116;;;###autoload
869bff31 117(defvar tex-dvi-view-command nil
81c735c0
RS
118 "*Command used by \\[tex-view] to display a `.dvi' file.
119If this string contains an asterisk (`*'), that is replaced by the file name;
120otherwise, the file name, preceded by blank, is added at the end.
528415e7
RS
121
122This can be set conditionally so that the previewer used is suitable for the
123window system being used. For example,
124
125 (setq tex-dvi-view-command
126 (if (eq window-system 'x) \"xdvi\" \"dvi2tty * | cat -s\"))
127
81c735c0 128would tell \\[tex-view] to use xdvi under X windows and to use dvi2tty
528415e7 129otherwise.")
869bff31 130
7e1dae73 131;;;###autoload
869bff31 132(defvar tex-show-queue-command "lpq"
528415e7
RS
133 "*Command used by \\[tex-show-print-queue] to show the print queue.
134Should show the queue(s) that \\[tex-print] puts jobs on.")
869bff31 135
7e1dae73 136;;;###autoload
869bff31 137(defvar tex-default-mode 'plain-tex-mode
138 "*Mode to enter for a new file that might be either TeX or LaTeX.
139This variable is used when it can't be determined whether the file
140is plain TeX or LaTeX or what because the file contains no commands.
81c735c0 141Normally set to either `plain-tex-mode' or `latex-mode'.")
869bff31 142
7e1dae73 143;;;###autoload
869bff31 144(defvar tex-open-quote "``"
145 "*String inserted by typing \\[tex-insert-quote] to open a quotation.")
146
7e1dae73 147;;;###autoload
869bff31 148(defvar tex-close-quote "''"
149 "*String inserted by typing \\[tex-insert-quote] to close a quotation.")
150
528415e7
RS
151(defvar tex-last-temp-file nil
152 "Latest temporary file generated by \\[tex-region] and \\[tex-buffer].
153Deleted when the \\[tex-region] or \\[tex-buffer] is next run, or when the
81c735c0 154tex shell terminates.")
528415e7 155
869bff31 156(defvar tex-command nil
157 "Command to run TeX.
528415e7 158The name of the file, preceded by a blank, will be added to this string.")
869bff31 159
160(defvar tex-trailer nil
161 "String appended after the end of a region sent to TeX by \\[tex-region].")
162
163(defvar tex-start-of-header nil
898b9ac1 164 "Regular expression used by \\[tex-region] to find start of file's header.")
869bff31 165
166(defvar tex-end-of-header nil
898b9ac1 167 "Regular expression used by \\[tex-region] to find end of file's header.")
869bff31 168
169(defvar tex-shell-cd-command "cd"
170 "Command to give to shell running TeX to change directory.
81c735c0 171The value of `tex-directory' is appended to this, separated by a space.")
869bff31 172
173(defvar tex-zap-file nil
174 "Temporary file name used for text being sent as input to TeX.
175Should be a simple file name with no extension or directory specification.")
176
177(defvar tex-last-buffer-texed nil
178 "Buffer which was last TeXed.")
179
180(defvar tex-print-file nil
181 "File name that \\[tex-print] prints.
182Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")
183
184(defvar tex-mode-syntax-table nil
185 "Syntax table used while in TeX mode.")
186
a5e2ae01
RS
187(defun latex-imenu-create-index ()
188 "Generates an alist for imenu from a LaTeX buffer."
189 (let (result temp)
190 (goto-char (point-max))
191 (while (re-search-backward "\\\\\\(part\\|chapter\\|\
192\\(sub\\)?\\(\\(sub\\)?section\\|paragraph\\)\\)\\*?[ \t\n]*{\\([^}]*\\)}" nil t)
193 (setq temp
194 (assoc (buffer-substring-no-properties (match-beginning 1)
195 (match-end 1))
196 '(("part" . "") ("chapter" . " ")
197 ("section" . " ") ("subsection" . " ")
198 ("subsubsection" . " ")
199 ("paragraph" . " ") ("subparagraph" . " "))))
200 (setq result (cons (cons (concat (cdr temp) (match-string 5))
201 (match-beginning 0))
202 result)))
203 result))
0fb4f245 204
869bff31 205(defun tex-define-common-keys (keymap)
81c735c0 206 "Define the keys that we want defined both in TeX mode and in the TeX shell."
869bff31 207 (define-key keymap "\C-c\C-k" 'tex-kill-job)
208 (define-key keymap "\C-c\C-l" 'tex-recenter-output-buffer)
209 (define-key keymap "\C-c\C-q" 'tex-show-print-queue)
210 (define-key keymap "\C-c\C-p" 'tex-print)
211 (define-key keymap "\C-c\C-v" 'tex-view)
62a24cb5
RS
212
213 (define-key keymap [menu-bar tex] (cons "TeX" (make-sparse-keymap "TeX")))
214
215 (define-key keymap [menu-bar tex tex-kill-job] '("Tex Kill" . tex-kill-job))
cf6d6e8a
RS
216 (define-key keymap [menu-bar tex tex-recenter-output-buffer]
217 '("Tex Recenter" . tex-recenter-output-buffer))
62a24cb5
RS
218 (define-key keymap [menu-bar tex tex-show-print-queue]
219 '("Show Print Queue" . tex-show-print-queue))
cf6d6e8a
RS
220 (define-key keymap [menu-bar tex tex-alt-print]
221 '("Tex Print (alt printer)" . tex-alt-print))
62a24cb5 222 (define-key keymap [menu-bar tex tex-print] '("Tex Print" . tex-print))
cf6d6e8a 223 (define-key keymap [menu-bar tex tex-view] '("Tex View" . tex-view))
869bff31 224 )
225
226(defvar tex-mode-map nil "Keymap for TeX mode.")
227
228(if tex-mode-map
229 nil
230 (setq tex-mode-map (make-sparse-keymap))
231 (tex-define-common-keys tex-mode-map)
232 (define-key tex-mode-map "\"" 'tex-insert-quote)
233 (define-key tex-mode-map "\n" 'tex-terminate-paragraph)
234 (define-key tex-mode-map "\C-c}" 'up-list)
235 (define-key tex-mode-map "\C-c{" 'tex-insert-braces)
236 (define-key tex-mode-map "\C-c\C-r" 'tex-region)
237 (define-key tex-mode-map "\C-c\C-b" 'tex-buffer)
238 (define-key tex-mode-map "\C-c\C-f" 'tex-file)
239 (define-key tex-mode-map "\C-c\C-i" 'tex-bibtex-file)
240 (define-key tex-mode-map "\C-c\C-o" 'tex-latex-block)
cf6d6e8a 241 (define-key tex-mode-map "\C-c\C-e" 'tex-close-latex-block)
6a900cf1 242 (define-key tex-mode-map "\C-c\C-u" 'tex-goto-last-unclosed-latex-block)
002b0d00
RS
243 (define-key tex-mode-map [menu-bar tex tex-bibtex-file]
244 '("BibTeX File" . tex-bibtex-file))
cf6d6e8a
RS
245 (define-key tex-mode-map [menu-bar tex tex-validate-region]
246 '("Validate Region" . tex-validate-region))
247 (define-key tex-mode-map [menu-bar tex validate-tex-buffer]
248 '("Validate Buffer" . validate-tex-buffer))
249 (define-key tex-mode-map [menu-bar tex tex-region]
002b0d00 250 '("TeX Region" . tex-region))
cf6d6e8a 251 (define-key tex-mode-map [menu-bar tex tex-buffer]
002b0d00
RS
252 '("TeX Buffer" . tex-buffer))
253 (define-key tex-mode-map [menu-bar tex tex-file] '("TeX File" . tex-file)))
cf6d6e8a
RS
254
255(put 'tex-region 'menu-enable 'mark-active)
256(put 'tex-validate-region 'menu-enable 'mark-active)
257(put 'tex-print 'menu-enable '(stringp tex-print-file))
258(put 'tex-alt-print 'menu-enable '(stringp tex-print-file))
259(put 'tex-view 'menu-enable '(stringp tex-print-file))
260(put 'tex-recenter-output-buffer 'menu-enable '(get-buffer "*tex-shell*"))
261(put 'tex-kill-job 'menu-enable '(tex-shell-running))
262
869bff31 263
264(defvar tex-shell-map nil
81c735c0 265 "Keymap for the TeX shell.
dca5ea48 266Inherits `shell-mode-map' with a few additions.")
869bff31 267
6da9bbd6
RS
268(defvar tex-face-alist
269 '((bold . "{\\bf ")
270 (italic . "{\\it ")
271 (bold-italic . "{\\bi ") ; hypothetical
272 (underline . "\\underline{")
273 (default . "{\\rm "))
274 "Alist of face and TeX font name for facemenu.")
275
276(defvar tex-latex-face-alist
277 `((italic . "{\\em ")
278 ,@tex-face-alist)
279 "Alist of face and LaTeX font name for facemenu.")
280
281
0d548e5d 282(defvar compare-windows-whitespace) ; Pacify the byte-compiler
8241d7b9 283
869bff31 284;;; This would be a lot simpler if we just used a regexp search,
285;;; but then it would be too slow.
7229064d 286;;;###autoload
869bff31 287(defun tex-mode ()
288 "Major mode for editing files of input for TeX, LaTeX, or SliTeX.
289Tries to determine (by looking at the beginning of the file) whether
81c735c0
RS
290this file is for plain TeX, LaTeX, or SliTeX and calls `plain-tex-mode',
291`latex-mode', or `slitex-mode', respectively. If it cannot be determined,
292such as if there are no commands in the file, the value of `tex-default-mode'
293says which mode to use."
869bff31 294 (interactive)
295 (let (mode slash comment)
296 (save-excursion
297 (goto-char (point-min))
298 (while (and (setq slash (search-forward "\\" nil t))
299 (setq comment (let ((search-end (point)))
300 (save-excursion
301 (beginning-of-line)
302 (search-forward "%" search-end t))))))
303 (if (and slash (not comment))
c0bcb239 304 (setq mode (if (looking-at "documentstyle\\|documentclass\\|begin\\b\\|NeedsTeXFormat{LaTeX")
0edb9815
RS
305 (if (looking-at
306 "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")
869bff31 307 'slitex-mode
308 'latex-mode)
309 'plain-tex-mode))))
310 (if mode (funcall mode)
311 (funcall tex-default-mode))))
e4c8c838 312
6503cec3 313;;;###autoload
31e1d920 314(defalias 'TeX-mode 'tex-mode)
6503cec3 315;;;###autoload
31e1d920 316(defalias 'LaTeX-mode 'latex-mode)
869bff31 317
7229064d 318;;;###autoload
869bff31 319(defun plain-tex-mode ()
320 "Major mode for editing files of input for plain TeX.
321Makes $ and } display the characters they match.
322Makes \" insert `` when it seems to be the beginning of a quotation,
323and '' when it appears to be the end; it inserts \" only after a \\.
324
325Use \\[tex-region] to run TeX on the current region, plus a \"header\"
326copied from the top of the file (containing macro definitions, etc.),
327running TeX under a special subshell. \\[tex-buffer] does the whole buffer.
328\\[tex-file] saves the buffer and then processes the file.
329\\[tex-print] prints the .dvi file made by any of these.
330\\[tex-view] previews the .dvi file made by any of these.
331\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
332
333Use \\[validate-tex-buffer] to check buffer for paragraphs containing
334mismatched $'s or braces.
335
336Special commands:
337\\{tex-mode-map}
338
339Mode variables:
340tex-run-command
341 Command string used by \\[tex-region] or \\[tex-buffer].
342tex-directory
343 Directory in which to create temporary files for TeX jobs
344 run by \\[tex-region] or \\[tex-buffer].
345tex-dvi-print-command
346 Command string used by \\[tex-print] to print a .dvi file.
528415e7
RS
347tex-alt-dvi-print-command
348 Alternative command string used by \\[tex-print] (when given a prefix
349 argument) to print a .dvi file.
869bff31 350tex-dvi-view-command
351 Command string used by \\[tex-view] to preview a .dvi file.
352tex-show-queue-command
353 Command string used by \\[tex-show-print-queue] to show the print
354 queue that \\[tex-print] put your job on.
355
81c735c0
RS
356Entering Plain-tex mode runs the hook `text-mode-hook', then the hook
357`tex-mode-hook', and finally the hook `plain-tex-mode-hook'. When the
358special subshell is initiated, the hook `tex-shell-hook' is run."
8241d7b9 359
869bff31 360 (interactive)
361 (tex-common-initialization)
362 (setq mode-name "TeX")
363 (setq major-mode 'plain-tex-mode)
364 (setq tex-command tex-run-command)
898b9ac1
RS
365 (setq tex-start-of-header "%\\*\\*start of header")
366 (setq tex-end-of-header "%\\*\\*end of header")
869bff31 367 (setq tex-trailer "\\bye\n")
368 (run-hooks 'text-mode-hook 'tex-mode-hook 'plain-tex-mode-hook))
6503cec3 369;;;###autoload
31e1d920 370(defalias 'plain-TeX-mode 'plain-tex-mode)
869bff31 371
7229064d 372;;;###autoload
869bff31 373(defun latex-mode ()
374 "Major mode for editing files of input for LaTeX.
375Makes $ and } display the characters they match.
376Makes \" insert `` when it seems to be the beginning of a quotation,
377and '' when it appears to be the end; it inserts \" only after a \\.
378
379Use \\[tex-region] to run LaTeX on the current region, plus the preamble
380copied from the top of the file (containing \\documentstyle, etc.),
381running LaTeX under a special subshell. \\[tex-buffer] does the whole buffer.
382\\[tex-file] saves the buffer and then processes the file.
383\\[tex-print] prints the .dvi file made by any of these.
384\\[tex-view] previews the .dvi file made by any of these.
385\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
386
387Use \\[validate-tex-buffer] to check buffer for paragraphs containing
388mismatched $'s or braces.
389
390Special commands:
391\\{tex-mode-map}
392
393Mode variables:
394latex-run-command
395 Command string used by \\[tex-region] or \\[tex-buffer].
396tex-directory
397 Directory in which to create temporary files for LaTeX jobs
398 run by \\[tex-region] or \\[tex-buffer].
399tex-dvi-print-command
400 Command string used by \\[tex-print] to print a .dvi file.
528415e7
RS
401tex-alt-dvi-print-command
402 Alternative command string used by \\[tex-print] (when given a prefix
403 argument) to print a .dvi file.
869bff31 404tex-dvi-view-command
405 Command string used by \\[tex-view] to preview a .dvi file.
406tex-show-queue-command
407 Command string used by \\[tex-show-print-queue] to show the print
408 queue that \\[tex-print] put your job on.
409
81c735c0
RS
410Entering Latex mode runs the hook `text-mode-hook', then
411`tex-mode-hook', and finally `latex-mode-hook'. When the special
412subshell is initiated, `tex-shell-hook' is run."
869bff31 413 (interactive)
414 (tex-common-initialization)
415 (setq mode-name "LaTeX")
416 (setq major-mode 'latex-mode)
417 (setq tex-command latex-run-command)
898b9ac1
RS
418 (setq tex-start-of-header "\\\\documentstyle\\|\\\\documentclass")
419 (setq tex-end-of-header "\\\\begin{document}")
869bff31 420 (setq tex-trailer "\\end{document}\n")
ab2c9f54
RS
421 ;; A line containing just $$ is treated as a paragraph separator.
422 ;; A line starting with $$ starts a paragraph,
423 ;; but does not separate paragraphs if it has more stuff on it.
02202839
BG
424 (setq paragraph-start "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$\\|\
425\\\\begin\\>\\|\\\\label\\>\\|\\\\end\\>\\|\\\\\\[\\|\\\\\\]\\|\
426\\\\chapter\\>\\|\\\\section\\>\\|\
427\\\\subsection\\>\\|\\\\subsubsection\\>\\|\
428\\\\paragraph\\>\\|\\\\subparagraph\\>\\|\
429\\\\item\\>\\|\\\\bibitem\\>\\|\\\\newline\\>\\|\\\\noindent\\>\\|\
430\\\\[a-z]*space\\>\\|\\\\[a-z]*skip\\>\\|\
431\\\\newpage\\>\\|\\\\[a-z]*page\\|\\\\footnote\\>\\|\
432\\\\marginpar\\>\\|\\\\parbox\\>\\|\\\\caption\\>")
433 (setq paragraph-separate "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$[ \t]*$\\|\
434\\\\begin\\>\\|\\\\label\\>\\|\\\\end\\>\\|\\\\\\[\\|\\\\\\]\\|\
435\\\\chapter\\>\\|\\\\section\\>\\|\
436\\\\subsection\\>\\|\\\\subsubsection\\>\\|\
437\\\\paragraph\\>\\|\\\\subparagraph\\>\\|\
438\\(\\\\item\\|\\\\bibitem\\|\\\\newline\\|\\\\noindent\\|\
439\\\\[a-z]*space\\|\\\\[a-z]*skip\\|\
440\\\\newpage\\|\\\\[a-z]*page[a-z]*\\|\\\\footnote\\|\
441\\\\marginpar\\|\\\\parbox\\|\\\\caption\\)[ \t]*\\($\\|%\\)")
a5e2ae01
RS
442 (make-local-variable 'imenu-create-index-function)
443 (setq imenu-create-index-function 'latex-imenu-create-index)
6da9bbd6
RS
444 (make-local-variable 'tex-face-alist)
445 (setq tex-face-alist tex-latex-face-alist)
869bff31 446 (run-hooks 'text-mode-hook 'tex-mode-hook 'latex-mode-hook))
447
bd2f2323 448;;;###autoload
869bff31 449(defun slitex-mode ()
450 "Major mode for editing files of input for SliTeX.
451Makes $ and } display the characters they match.
452Makes \" insert `` when it seems to be the beginning of a quotation,
453and '' when it appears to be the end; it inserts \" only after a \\.
454
455Use \\[tex-region] to run SliTeX on the current region, plus the preamble
456copied from the top of the file (containing \\documentstyle, etc.),
457running SliTeX under a special subshell. \\[tex-buffer] does the whole buffer.
458\\[tex-file] saves the buffer and then processes the file.
459\\[tex-print] prints the .dvi file made by any of these.
460\\[tex-view] previews the .dvi file made by any of these.
461\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
462
463Use \\[validate-tex-buffer] to check buffer for paragraphs containing
464mismatched $'s or braces.
465
466Special commands:
467\\{tex-mode-map}
468
469Mode variables:
470slitex-run-command
471 Command string used by \\[tex-region] or \\[tex-buffer].
472tex-directory
473 Directory in which to create temporary files for SliTeX jobs
474 run by \\[tex-region] or \\[tex-buffer].
475tex-dvi-print-command
476 Command string used by \\[tex-print] to print a .dvi file.
528415e7
RS
477tex-alt-dvi-print-command
478 Alternative command string used by \\[tex-print] (when given a prefix
479 argument) to print a .dvi file.
869bff31 480tex-dvi-view-command
481 Command string used by \\[tex-view] to preview a .dvi file.
482tex-show-queue-command
483 Command string used by \\[tex-show-print-queue] to show the print
484 queue that \\[tex-print] put your job on.
485
81c735c0
RS
486Entering SliTeX mode runs the hook `text-mode-hook', then the hook
487`tex-mode-hook', then the hook `latex-mode-hook', and finally the hook
488`slitex-mode-hook'. When the special subshell is initiated, the hook
489`tex-shell-hook' is run."
869bff31 490 (interactive)
491 (tex-common-initialization)
492 (setq mode-name "SliTeX")
493 (setq major-mode 'slitex-mode)
494 (setq tex-command slitex-run-command)
6da9bbd6 495 (setq tex-start-of-header "\\\\documentstyle{slides}\\|\\\\documentclass{slides}")
898b9ac1 496 (setq tex-end-of-header "\\\\begin{document}")
869bff31 497 (setq tex-trailer "\\end{document}\n")
ab2c9f54
RS
498 ;; A line containing just $$ is treated as a paragraph separator.
499 ;; A line starting with $$ starts a paragraph,
500 ;; but does not separate paragraphs if it has more stuff on it.
02202839
BG
501 (setq paragraph-start "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$\\|\
502\\\\begin\\>\\|\\\\label\\>\\|\\\\end\\>\\|\\\\\\[\\|\\\\\\]\\|\
503\\\\chapter\\>\\|\\\\section\\>\\|\
504\\\\subsection\\>\\|\\\\subsubsection\\>\\|\
505\\\\paragraph\\>\\|\\\\subparagraph\\>\\|\
506\\\\item\\>\\|\\\\bibitem\\>\\|\\\\newline\\>\\|\\\\noindent\\>\\|\
507\\\\[a-z]*space\\>\\|\\\\[a-z]*skip\\>\\|\
508\\\\newpage\\>\\|\\\\[a-z]*page\\|\\\\footnote\\>\\|\
509\\\\marginpar\\>\\|\\\\parbox\\>\\|\\\\caption\\>")
510 (setq paragraph-separate "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$[ \t]*$\\|\
511\\\\begin\\>\\|\\\\label\\>\\|\\\\end\\>\\|\\\\\\[\\|\\\\\\]\\|\
512\\\\chapter\\>\\|\\\\section\\>\\|\
513\\\\subsection\\>\\|\\\\subsubsection\\>\\|\
514\\\\paragraph\\>\\|\\\\subparagraph\\>\\|\
515\\\\item[ \t]*$\\|\\\\bibitem[ \t]*$\\|\\\\newline[ \t]*$\\|\\\\noindent[ \t]*$\\|\
516\\\\[a-z]*space[ \t]*$\\|\\\\[a-z]*skip[ \t]*$\\|\
517\\\\newpage[ \t]*$\\|\\\\[a-z]*page[a-z]*[ \t]*$\\|\\\\footnote[ \t]*$\\|\
518\\\\marginpar[ \t]*$\\|\\\\parbox[ \t]*$\\|\\\\caption[ \t]*$")
869bff31 519 (run-hooks
520 'text-mode-hook 'tex-mode-hook 'latex-mode-hook 'slitex-mode-hook))
521
522(defun tex-common-initialization ()
523 (kill-all-local-variables)
524 (use-local-map tex-mode-map)
525 (setq local-abbrev-table text-mode-abbrev-table)
526 (if (null tex-mode-syntax-table)
527 (let ((char 0))
528 (setq tex-mode-syntax-table (make-syntax-table))
529 (set-syntax-table tex-mode-syntax-table)
530 (while (< char ? )
531 (modify-syntax-entry char ".")
532 (setq char (1+ char)))
533 (modify-syntax-entry ?\C-@ "w")
534 (modify-syntax-entry ?\t " ")
535 (modify-syntax-entry ?\n ">")
536 (modify-syntax-entry ?\f ">")
537 (modify-syntax-entry ?$ "$$")
538 (modify-syntax-entry ?% "<")
539 (modify-syntax-entry ?\\ "/")
540 (modify-syntax-entry ?\" ".")
541 (modify-syntax-entry ?& ".")
542 (modify-syntax-entry ?_ ".")
543 (modify-syntax-entry ?@ "_")
544 (modify-syntax-entry ?~ " ")
545 (modify-syntax-entry ?' "w"))
546 (set-syntax-table tex-mode-syntax-table))
547 (make-local-variable 'paragraph-start)
64db2461 548 ;; A line containing just $$ is treated as a paragraph separator.
02202839 549 (setq paragraph-start "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$")
869bff31 550 (make-local-variable 'paragraph-separate)
ab2c9f54
RS
551 ;; A line starting with $$ starts a paragraph,
552 ;; but does not separate paragraphs if it has more stuff on it.
02202839 553 (setq paragraph-separate "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$[ \t]*$")
869bff31 554 (make-local-variable 'comment-start)
555 (setq comment-start "%")
556 (make-local-variable 'comment-start-skip)
557 (setq comment-start-skip "\\(\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
e41b2db1
ER
558 (make-local-variable 'comment-indent-function)
559 (setq comment-indent-function 'tex-comment-indent)
2e0b53ad
RS
560 (make-local-variable 'parse-sexp-ignore-comments)
561 (setq parse-sexp-ignore-comments t)
869bff31 562 (make-local-variable 'compare-windows-whitespace)
563 (setq compare-windows-whitespace 'tex-categorize-whitespace)
cf149bdf
RS
564 (make-local-variable 'skeleton-further-elements)
565 (setq skeleton-further-elements
566 '((indent-line-function 'indent-relative-maybe)))
6da9bbd6
RS
567 (make-local-variable 'facemenu-add-face-function)
568 (make-local-variable 'facemenu-end-add-face)
569 (make-local-variable 'facemenu-remove-face-function)
570 (setq facemenu-add-face-function
571 (lambda (face end)
572 (let ((face-text (cdr (assq face tex-face-alist))))
573 (if face-text
574 face-text
575 (error "Face %s not configured for %s mode" face mode-name))))
576 facemenu-end-add-face "}"
577 facemenu-remove-face-function t)
869bff31 578 (make-local-variable 'tex-command)
579 (make-local-variable 'tex-start-of-header)
580 (make-local-variable 'tex-end-of-header)
581 (make-local-variable 'tex-trailer))
582
583(defun tex-comment-indent ()
584 (if (looking-at "%%%")
585 (current-column)
586 (skip-chars-backward " \t")
587 (max (if (bolp) 0 (1+ (current-column)))
588 comment-column)))
589
590(defun tex-categorize-whitespace (backward-limit)
591 ;; compare-windows-whitespace is set to this.
592 ;; This is basically a finite-state machine.
593 ;; Returns a symbol telling how TeX would treat
594 ;; the whitespace we are looking at: null, space, or par.
595 (let ((category 'null)
596 (not-finished t))
597 (skip-chars-backward " \t\n\f" backward-limit)
598 (while not-finished
599 (cond ((looking-at "[ \t]+")
600 (goto-char (match-end 0))
601 (if (eql category 'null)
602 (setq category 'space)))
603 ((looking-at "\n")
604 (cond ((eql category 'newline)
605 (setq category 'par)
606 (setq not-finished nil))
607 (t
608 (setq category 'newline) ;a strictly internal state
609 (goto-char (match-end 0)))))
610 ((looking-at "\f+")
611 (setq category 'par)
612 (setq not-finished nil))
613 (t
614 (setq not-finished nil))))
615 (skip-chars-forward " \t\n\f")
616 (if (eql category 'newline)
617 'space ;TeX doesn't distinguish
618 category)))
619
620(defun tex-insert-quote (arg)
621 "Insert the appropriate quote marks for TeX.
08348502
RS
622Inserts the value of `tex-open-quote' (normally ``) or `tex-close-quote'
623\(normally '') depending on the context. With prefix argument, always
869bff31 624inserts \" characters."
528415e7 625 (interactive "*P")
869bff31 626 (if arg
627 (self-insert-command (prefix-numeric-value arg))
628 (insert
629 (cond ((or (bobp)
630 (save-excursion
631 (forward-char -1)
632 (looking-at "\\s(\\|\\s \\|\\s>")))
633 tex-open-quote)
634 ((= (preceding-char) ?\\)
635 ?\")
636 (t
637 tex-close-quote)))))
638
639(defun validate-tex-buffer ()
8241d7b9 640 "Check current buffer for paragraphs containing mismatched $s.
bbd93e41
RS
641Their positions are recorded in the buffer `*Occur*'.
642To find a particular invalidity from `*Occur*',
643switch to to that buffer and type C-c C-c on the line
644for the invalidity you want to see."
869bff31 645 (interactive)
bbd93e41
RS
646 (let ((buffer (current-buffer))
647 (prevpos (point-min))
648 (linenum nil))
649 (with-output-to-temp-buffer "*Occur*"
650 (princ "Mismatches:\n")
651 (save-excursion
652 (set-buffer standard-output)
653 (occur-mode)
654 (setq occur-buffer buffer)
655 (setq occur-nlines 0)
656 (setq occur-pos-list nil))
657 (save-excursion
658 (goto-char (point-max))
869bff31 659 (while (and (not (input-pending-p)) (not (bobp)))
710a0f53
KH
660 (let ((end (point))
661 prev-end)
bbd93e41 662 ;; Scan the previous paragraph for invalidities.
710a0f53
KH
663 (if (search-backward "\n\n" nil t)
664 (progn
665 (setq prev-end (point))
666 (forward-char 2))
667 (goto-char (setq prev-end (point-min))))
869bff31 668 (or (tex-validate-region (point) end)
710a0f53
KH
669 (let* ((oend end)
670 (end (save-excursion (forward-line 1) (point)))
bbd93e41
RS
671 start tem)
672 (beginning-of-line)
673 (setq start (point))
674 ;; Keep track of line number as we scan,
675 ;; in a cumulative fashion.
676 (if linenum
677 (setq linenum (- linenum (count-lines prevpos (point))))
678 (setq linenum (1+ (count-lines 1 start))))
679 (setq prevpos (point))
680 ;; Mention this mismatch in *Occur*.
681 ;; Since we scan from end of buffer to beginning,
682 ;; add each mismatch at the beginning of *Occur*
683 ;; and at the beginning of occur-pos-list.
684 (save-excursion
685 (setq tem (point-marker))
686 (set-buffer standard-output)
687 (goto-char (point-min))
688 ;; Skip "Mismatches:" header line.
689 (forward-line 1)
690 (setq occur-pos-list (cons tem occur-pos-list))
691 (insert-buffer-substring buffer start end)
692 (forward-char (- start end))
710a0f53
KH
693 (insert (format "%3d: " linenum)))))
694 (goto-char prev-end))))
bbd93e41
RS
695 (save-excursion
696 (set-buffer standard-output)
697 (if (null occur-pos-list)
698 (insert "None!\n"))
699 (if (interactive-p)
700 (message "%d mismatches found" (length occur-pos-list)))))))
869bff31 701
702(defun tex-validate-region (start end)
703 "Check for mismatched braces or $'s in region.
704Returns t if no mismatches. Returns nil and moves point to suspect
705area if a mismatch is found."
706 (interactive "r")
707 (let ((failure-point nil) (max-possible-sexps (- end start)))
708 (save-excursion
709 (condition-case ()
710 (save-restriction
711 (narrow-to-region start end)
712 (goto-char start)
713 (while (< 0 (setq max-possible-sexps (1- max-possible-sexps)))
714 (forward-sexp 1)))
715 (error
710a0f53 716 (skip-syntax-forward " .>")
869bff31 717 (setq failure-point (point)))))
718 (if failure-point
719 (progn
720 (goto-char failure-point)
721 nil)
722 t)))
723
724(defun tex-terminate-paragraph (inhibit-validation)
725 "Insert two newlines, breaking a paragraph for TeX.
81c735c0 726Check for mismatched braces or $s in paragraph being terminated.
869bff31 727A prefix arg inhibits the checking."
528415e7 728 (interactive "*P")
869bff31 729 (or inhibit-validation
730 (save-excursion
731 (tex-validate-region
732 (save-excursion
733 (search-backward "\n\n" nil 'move)
734 (point))
735 (point)))
736 (message "Paragraph being closed appears to contain a mismatch"))
737 (insert "\n\n"))
738
739(defun tex-insert-braces ()
740 "Make a pair of braces and be poised to type inside of them."
528415e7 741 (interactive "*")
869bff31 742 (insert ?\{)
743 (save-excursion
744 (insert ?})))
745
746;;; Like tex-insert-braces, but for LaTeX.
cf149bdf
RS
747(define-skeleton tex-latex-block
748 "Create a matching pair of lines \\begin[OPT]{NAME} and \\end{NAME} at point.
869bff31 749Puts point on a blank line between them."
cf149bdf
RS
750 (completing-read "LaTeX block name: "
751 (mapcar 'list
752 (append standard-latex-block-names
753 latex-block-names)))
754 "\\begin["
755 (skeleton-read "[options]: ") & ?\] | -1
756 ?\{
757 str
758 ?\} \n
759 _ \n
760 "\\end{" str ?\})
869bff31 761
762(defun tex-last-unended-begin ()
81c735c0 763 "Leave point at the beginning of the last `\\begin{...}' that is unended."
869bff31 764 (while (and (re-search-backward "\\(\\\\begin\\s *{\\)\\|\\(\\\\end\\s *{\\)")
765 (looking-at "\\\\end{"))
766 (tex-last-unended-begin)))
767
6a900cf1
ER
768(defun tex-goto-last-unclosed-latex-block ()
769 "Move point to the last unclosed \\begin{...}.
770Mark is left at original location."
771 (interactive)
772 (let ((spot))
773 (save-excursion
774 (condition-case nil
775 (tex-last-unended-begin)
776 (error (error "Couldn't find unended \\begin")))
777 (setq spot (point)))
778 (push-mark)
779 (goto-char spot)))
780
869bff31 781(defun tex-close-latex-block ()
782 "Creates an \\end{...} to match the last unclosed \\begin{...}."
783 (interactive "*")
784 (let ((new-line-needed (bolp))
785 text indentation)
786 (save-excursion
528415e7 787 (condition-case nil
869bff31 788 (tex-last-unended-begin)
789 (error (error "Couldn't find unended \\begin")))
790 (setq indentation (current-column))
791 (re-search-forward "\\\\begin\\(\\s *{[^}\n]*}\\)")
792 (setq text (buffer-substring (match-beginning 1) (match-end 1))))
793 (indent-to indentation)
794 (insert "\\end" text)
795 (if new-line-needed (insert ?\n))))
796\f
2f3067de
ER
797(defun tex-compilation-parse-errors ()
798 "Parse the current buffer as error messages.
799This makes a list of error descriptors, compilation-error-list.
800For each source-file, line-number pair in the buffer,
801the source file is read in, and the text location is saved in
8241d7b9 802compilation-error-list. The function `next-error', assigned to
2f3067de
ER
803\\[next-error], takes the next error off the list and visits its location.
804
805This function works on TeX compilations only. It is necessary for
806that purpose, since TeX does not put file names on the same line as
807line numbers for the errors."
808 (setq compilation-error-list nil)
809 (message "Parsing error messages...")
810 (modify-syntax-entry ?\{ "_")
811 (modify-syntax-entry ?\} "_")
812 (modify-syntax-entry ?\[ "_")
813 (modify-syntax-entry ?\] "_")
2f3067de
ER
814 (let (text-buffer
815 last-filename last-linenum)
816 ;; Don't reparse messages already seen at last parse.
817 (goto-char compilation-parsing-end)
818 ;; Don't parse the first two lines as error messages.
819 ;; This matters for grep.
820 (if (bobp)
821 (forward-line 2))
8241d7b9 822 (while (re-search-forward "^l\.[0-9]+ " nil t)
2f3067de
ER
823 (let (linenum filename
824 error-marker text-marker)
825 ;; Extract file name and line number from error message.
826 ;; Line number is 2 away from beginning of line: "l.23"
827 (beginning-of-line)
828 (goto-char (+ (point) 2))
829 (setq linenum (read (current-buffer)))
830 ;; The file is the one that was opened last and is still open.
831 ;; We need to find the last open parenthesis.
832 (insert ?\))
833 (backward-sexp)
834 (forward-char)
8241d7b9 835 (setq filename (current-word))
2f3067de
ER
836 ;; Locate the erring file and line.
837 (if (and (equal filename last-filename)
838 (= linenum last-linenum))
839 nil
840 (skip-chars-backward "^(")
841 (backward-char)
842 (forward-sexp)
843 (backward-delete-char 1)
844 (setq error-marker (point-marker))
845 ;; text-buffer gets the buffer containing this error's file.
846 (if (not (equal filename last-filename))
847 (setq text-buffer
848 (and (file-exists-p (setq last-filename filename))
849 (find-file-noselect filename))
850 last-linenum 0))
851 (if text-buffer
852 ;; Go to that buffer and find the erring line.
853 (save-excursion
854 (set-buffer text-buffer)
855 (if (zerop last-linenum)
856 (progn
857 (goto-char 1)
858 (setq last-linenum 1)))
859 (forward-line (- linenum last-linenum))
860 (setq last-linenum linenum)
861 (setq text-marker (point-marker))
862 (setq compilation-error-list
863 (cons (list error-marker text-marker)
864 compilation-error-list)))))
865 (forward-line 1)))
866 (setq compilation-parsing-end (point-max)))
867 (message "Parsing error messages...done")
868 (setq compilation-error-list (nreverse compilation-error-list)))
869\f
869bff31 870;;; Invoking TeX in an inferior shell.
871
872;;; Why use a shell instead of running TeX directly? Because if TeX
873;;; gets stuck, the user can switch to the shell window and type at it.
874
875;;; The utility functions:
876
d974af30 877;;;###autoload
869bff31 878(defun tex-start-shell ()
879 (save-excursion
528415e7
RS
880 (set-buffer
881 (make-comint
882 "tex-shell"
883 (or tex-shell-file-name (getenv "ESHELL") (getenv "SHELL") "/bin/sh")
4cdc1d4b 884 nil))
528415e7
RS
885 (let ((proc (get-process "tex-shell")))
886 (set-process-sentinel proc 'tex-shell-sentinel)
887 (process-kill-without-query proc)
e8c04c88 888 (setq comint-prompt-regexp shell-prompt-pattern)
191cda94 889 (setq tex-shell-map (nconc (make-sparse-keymap) shell-mode-map))
528415e7
RS
890 (tex-define-common-keys tex-shell-map)
891 (use-local-map tex-shell-map)
892 (run-hooks 'tex-shell-hook)
893 (while (zerop (buffer-size))
51b2c841
RS
894 (sleep-for 1)))))
895
896(defun tex-display-shell ()
897 "Make the TeX shell buffer visible in a window."
898 (display-buffer (process-buffer (get-process "tex-shell")))
899 (tex-recenter-output-buffer nil))
528415e7
RS
900
901(defun tex-shell-sentinel (proc msg)
902 (cond ((null (buffer-name (process-buffer proc)))
903 ;; buffer killed
904 (set-process-buffer proc nil)
905 (tex-delete-last-temp-files))
906 ((memq (process-status proc) '(signal exit))
907 (tex-delete-last-temp-files))))
908
909(defun tex-set-buffer-directory (buffer directory)
869bff31 910 "Set BUFFER's default directory to be DIRECTORY."
911 (setq directory (file-name-as-directory (expand-file-name directory)))
912 (if (not (file-directory-p directory))
913 (error "%s is not a directory" directory)
914 (save-excursion
915 (set-buffer buffer)
916 (setq default-directory directory))))
917
30803a05
RS
918(defvar tex-send-command-modified-tick 0)
919(make-variable-buffer-local 'tex-send-command-modified-tick)
920
528415e7 921(defun tex-send-command (command &optional file background)
4cdc1d4b 922 "Send COMMAND to TeX shell process, substituting optional FILE for *.
8241d7b9
ER
923Do this in background if optional BACKGROUND is t. If COMMAND has no *,
924FILE will be appended, preceded by a blank, to COMMAND. If FILE is nil, no
925substitution will be made in COMMAND. COMMAND can be any expression that
926evaluates to a command string."
528415e7
RS
927 (save-excursion
928 (let* ((cmd (eval command))
c93931c3 929 (proc (or (get-process "tex-shell") (error "No TeX subprocess")))
64db2461 930 (buf (process-buffer proc))
4f45adda 931 (star (string-match "\\*" cmd))
4cdc1d4b
RS
932 (string
933 (concat
934 (if file
935 (if star (concat (substring cmd 0 star)
936 file (substring cmd (1+ star)))
937 (concat cmd " " file))
938 cmd)
939 (if background "&" ""))))
64db2461
RS
940 ;; Switch to buffer before checking for subproc output in it.
941 (set-buffer buf)
30803a05
RS
942 ;; If text is unchanged since previous tex-send-command,
943 ;; we haven't got any output. So wait for output now.
64db2461 944 (if (= (buffer-modified-tick buf) tex-send-command-modified-tick)
30803a05 945 (accept-process-output proc))
4cdc1d4b
RS
946 (goto-char (process-mark proc))
947 (insert string)
30803a05 948 (comint-send-input)
64db2461 949 (setq tex-send-command-modified-tick (buffer-modified-tick buf)))))
528415e7 950
a15849cb
RS
951(defun tex-delete-last-temp-files (&optional not-all)
952 "Delete any junk files from last temp file.
953If NOT-ALL is non-nil, save the `.dvi' file."
528415e7
RS
954 (if tex-last-temp-file
955 (let* ((dir (file-name-directory tex-last-temp-file))
adf6b7f9
KH
956 (list (and (file-directory-p dir)
957 (file-name-all-completions
958 (file-name-nondirectory tex-last-temp-file) dir))))
959 (while list
a15849cb
RS
960 (if not-all
961 (and
962 ;; If arg is non-nil, don't delete the .dvi file.
963 (not (string-match "\\.dvi$" (car list)))
964 (delete-file (concat dir (car list))))
965 (delete-file (concat dir (car list))))
528415e7
RS
966 (setq list (cdr list))))))
967
99621a14 968(add-hook 'kill-emacs-hook 'tex-delete-last-temp-files)
869bff31 969
528415e7 970;;; The commands:
869bff31 971
972(defun tex-region (beg end)
973 "Run TeX on the current region, via a temporary file.
974The file's name comes from the variable `tex-zap-file' and the
975variable `tex-directory' says where to put it.
976
977If the buffer has a header, the header is given to TeX before the
978region itself. The buffer's header is all lines between the strings
979defined by `tex-start-of-header' and `tex-end-of-header' inclusive.
980The header must start in the first 100 lines of the buffer.
981
982The value of `tex-trailer' is given to TeX as input after the region.
983
984The value of `tex-command' specifies the command to use to run TeX."
985 (interactive "r")
986 (if (tex-shell-running)
987 (tex-kill-job)
988 (tex-start-shell))
989 (or tex-zap-file
990 (setq tex-zap-file (tex-generate-zap-file-name)))
528415e7
RS
991 (let* ((temp-buffer (get-buffer-create " TeX-Output-Buffer"))
992 ; Temp file will be written and TeX will be run in zap-directory.
993 ; If the TEXINPUTS file has relative directories or if the region has
994 ; \input of files, this must be the same directory as the file for
995 ; TeX to access the correct inputs. That's why it's safest if
996 ; tex-directory is ".".
997 (zap-directory
998 (file-name-as-directory (expand-file-name tex-directory)))
999 (tex-out-file (concat zap-directory tex-zap-file)))
0d548e5d
RS
1000 ;; Don't delete temp files if we do the same buffer twice in a row.
1001 (or (eq (current-buffer) tex-last-buffer-texed)
1002 (tex-delete-last-temp-files t))
869bff31 1003 ;; Write the new temp file.
1004 (save-excursion
1005 (save-restriction
1006 (widen)
1007 (goto-char (point-min))
1008 (forward-line 100)
1009 (let ((search-end (point))
1010 (hbeg (point-min)) (hend (point-min))
1011 (default-directory zap-directory))
1012 (goto-char (point-min))
1013 ;; Initialize the temp file with either the header or nothing
898b9ac1 1014 (if (re-search-forward tex-start-of-header search-end t)
869bff31 1015 (progn
1016 (beginning-of-line)
1017 (setq hbeg (point)) ;mark beginning of header
898b9ac1 1018 (if (re-search-forward tex-end-of-header nil t)
869bff31 1019 (progn (forward-line 1)
1020 (setq hend (point))) ;mark end of header
1021 (setq hbeg (point-min))))) ;no header
528415e7
RS
1022 (write-region (min hbeg beg) hend
1023 (concat tex-out-file ".tex") nil nil)
1024 (write-region (max beg hend) end (concat tex-out-file ".tex") t nil))
869bff31 1025 (let ((local-tex-trailer tex-trailer))
1026 (set-buffer temp-buffer)
1027 (erase-buffer)
1028 ;; make sure trailer isn't hidden by a comment
1029 (insert-string "\n")
1030 (if local-tex-trailer (insert-string local-tex-trailer))
528415e7
RS
1031 (tex-set-buffer-directory temp-buffer zap-directory)
1032 (write-region (point-min) (point-max)
1033 (concat tex-out-file ".tex") t nil))))
1034 ;; Record the file name to be deleted afterward.
1035 (setq tex-last-temp-file tex-out-file)
1036 (tex-send-command tex-shell-cd-command zap-directory)
1037 (tex-send-command tex-command tex-out-file)
51b2c841 1038 (tex-display-shell)
528415e7
RS
1039 (setq tex-print-file tex-out-file)
1040 (setq tex-last-buffer-texed (current-buffer))))
869bff31 1041
1042(defun tex-buffer ()
1043 "Run TeX on current buffer. See \\[tex-region] for more information.
528415e7
RS
1044Does not save the buffer, so it's useful for trying experimental versions.
1045See \\[tex-file] for an alternative."
869bff31 1046 (interactive)
1047 (tex-region (point-min) (point-max)))
1048
1049(defun tex-file ()
1050 "Prompt to save all buffers and run TeX (or LaTeX) on current buffer's file.
1051This function is more useful than \\[tex-buffer] when you need the
1052`.aux' file of LaTeX to have the correct name."
1053 (interactive)
f73741fc
RS
1054 (let ((source-file
1055 (or tex-main-file
1056 (if (buffer-file-name)
1057 (file-name-nondirectory (buffer-file-name))
1058 (error "Buffer does not seem to be associated with any file"))))
869bff31 1059 (file-dir (file-name-directory (buffer-file-name))))
7047ec77 1060 (if tex-offer-save
99621a14 1061 (save-some-buffers))
869bff31 1062 (if (tex-shell-running)
1063 (tex-kill-job)
1064 (tex-start-shell))
528415e7 1065 (tex-send-command tex-shell-cd-command file-dir)
23b64225
RS
1066 (tex-send-command tex-command source-file)
1067 (tex-display-shell)
1068 (setq tex-last-buffer-texed (current-buffer))
1069 (setq tex-print-file source-file)))
869bff31 1070
1071(defun tex-generate-zap-file-name ()
1072 "Generate a unique name suitable for use as a file name."
1073 ;; Include the shell process number and host name
1074 ;; in case there are multiple shells (for same or different user).
1075 (format "#tz%d%s"
1076 (process-id (get-buffer-process "*tex-shell*"))
1077 (tex-strip-dots (system-name))))
1078
1079(defun tex-strip-dots (s)
1080 (setq s (copy-sequence s))
1081 (while (string-match "\\." s)
1082 (aset s (match-beginning 0) ?-))
1083 s)
1084
1085;; This will perhaps be useful for modifying TEXINPUTS.
1086;; Expand each file name, separated by colons, in the string S.
1087(defun tex-expand-files (s)
1088 (let (elts (start 0))
1089 (while (string-match ":" s start)
1090 (setq elts (cons (substring s start (match-beginning 0)) elts))
1091 (setq start (match-end 0)))
1092 (or (= start 0)
1093 (setq elts (cons (substring s start) elts)))
1094 (mapconcat 'expand-file-name (nreverse elts) ":")))
1095
1096(defun tex-shell-running ()
1097 (and (get-process "tex-shell")
1098 (eq (process-status (get-process "tex-shell")) 'run)))
1099
1100(defun tex-kill-job ()
1101 "Kill the currently running TeX job."
1102 (interactive)
528415e7 1103 (quit-process (get-process "tex-shell") t))
869bff31 1104
1105(defun tex-recenter-output-buffer (linenum)
1106 "Redisplay buffer of TeX job output so that most recent output can be seen.
1107The last line of the buffer is displayed on
1108line LINE of the window, or centered if LINE is nil."
1109 (interactive "P")
1110 (let ((tex-shell (get-buffer "*tex-shell*"))
23b64225
RS
1111 (old-buffer (current-buffer))
1112 (window))
869bff31 1113 (if (null tex-shell)
1114 (message "No TeX output buffer")
23b64225
RS
1115 (setq window (display-buffer tex-shell))
1116 (save-selected-window
1117 (select-window window)
1118 (bury-buffer tex-shell)
1119 (goto-char (point-max))
1120 (recenter (if linenum
1121 (prefix-numeric-value linenum)
1122 (/ (window-height) 2)))))))
869bff31 1123
528415e7 1124(defun tex-print (&optional alt)
869bff31 1125 "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file].
1433a222
CZ
1126Runs the shell command defined by `tex-dvi-print-command'. If prefix argument
1127is provided, use the alternative command, `tex-alt-dvi-print-command'."
528415e7 1128 (interactive "P")
869bff31 1129 (let ((print-file-name-dvi (tex-append tex-print-file ".dvi"))
1130 test-name)
1131 (if (and (not (equal (current-buffer) tex-last-buffer-texed))
45c3304d
RS
1132 (buffer-file-name)
1133 ;; Check that this buffer's printed file is up to date.
869bff31 1134 (file-newer-than-file-p
1135 (setq test-name (tex-append (buffer-file-name) ".dvi"))
45c3304d 1136 (buffer-file-name)))
869bff31 1137 (setq print-file-name-dvi test-name))
528415e7
RS
1138 (if (not (file-exists-p print-file-name-dvi))
1139 (error "No appropriate `.dvi' file could be found")
1140 (tex-send-command
1141 (if alt tex-alt-dvi-print-command tex-dvi-print-command)
1142 print-file-name-dvi t))))
869bff31 1143
cf6d6e8a
RS
1144(defun tex-alt-print ()
1145 "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file].
002b0d00 1146Runs the shell command defined by `tex-alt-dvi-print-command'."
cf6d6e8a
RS
1147 (interactive)
1148 (tex-print t))
1149
869bff31 1150(defun tex-view ()
1151 "Preview the last `.dvi' file made by running TeX under Emacs.
1152This means, made using \\[tex-region], \\[tex-buffer] or \\[tex-file].
2b7971c9
RS
1153The variable `tex-dvi-view-command' specifies the shell command for preview.
1154You must set that variable yourself before using this command,
1155because there is no standard value that would generally work."
869bff31 1156 (interactive)
2b7971c9
RS
1157 (or tex-dvi-view-command
1158 (error "You must set `tex-dvi-view-command'"))
869bff31 1159 (let ((tex-dvi-print-command tex-dvi-view-command))
1160 (tex-print)))
1161
1162(defun tex-append (file-name suffix)
1163 "Append to FILENAME the suffix SUFFIX, using same algorithm TeX uses.
cf6d6e8a 1164Pascal-based TeX scans for the first period, C TeX uses the last.
869bff31 1165No period is retained immediately before SUFFIX,
1166so normally SUFFIX starts with one."
1167 (if (stringp file-name)
cf6d6e8a
RS
1168 (let ((file (file-name-nondirectory file-name))
1169 trial-name)
6da9bbd6 1170 ;; Try splitting on last period.
7d0ca249
RS
1171 ;; The first-period split can get fooled when two files
1172 ;; named a.tex and a.b.tex are both tex'd;
1173 ;; the last-period split must be right if it matches at all.
cf6d6e8a
RS
1174 (setq trial-name
1175 (concat (file-name-directory file-name)
1176 (substring file 0
7d0ca249 1177 (string-match "\\.[^.]*$" file))
cf6d6e8a
RS
1178 suffix))
1179 (if (or (file-exists-p trial-name)
1180 (file-exists-p (concat trial-name ".aux"))) ;for BibTeX files
1181 trial-name
7d0ca249 1182 ;; Not found, so split on first period.
cf6d6e8a
RS
1183 (concat (file-name-directory file-name)
1184 (substring file 0
7d0ca249 1185 (string-match "\\." file))
cf6d6e8a 1186 suffix)))
869bff31 1187 " "))
1188
1189(defun tex-show-print-queue ()
1190 "Show the print queue that \\[tex-print] put your job on.
1433a222 1191Runs the shell command defined by `tex-show-queue-command'."
869bff31 1192 (interactive)
1193 (if (tex-shell-running)
1194 (tex-kill-job)
1195 (tex-start-shell))
51b2c841
RS
1196 (tex-send-command tex-show-queue-command)
1197 (tex-display-shell))
869bff31 1198
1199(defun tex-bibtex-file ()
1200 "Run BibTeX on the current buffer's file."
1201 (interactive)
1202 (if (tex-shell-running)
1203 (tex-kill-job)
1204 (tex-start-shell))
1205 (let ((tex-out-file
1206 (tex-append (file-name-nondirectory (buffer-file-name)) ""))
1207 (file-dir (file-name-directory (buffer-file-name))))
528415e7 1208 (tex-send-command tex-shell-cd-command file-dir)
51b2c841
RS
1209 (tex-send-command tex-bibtex-command tex-out-file))
1210 (tex-display-shell))
528415e7
RS
1211
1212(run-hooks 'tex-mode-load-hook)
869bff31 1213
49116ac0
JB
1214(provide 'tex-mode)
1215
d501f516 1216;;; tex-mode.el ends here
99621a14 1217