Index entries.
[bpt/emacs.git] / lisp / textmodes / tex-mode.el
CommitLineData
55535639 1;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands
d501f516 2
1b741d9e 3;; Copyright (C) 1985, 86, 89, 92, 94, 95, 96, 97, 98, 1999, 2002
d61140e8 4;; Free Software Foundation, Inc.
eea8d4ef 5
70f20973 6;; Maintainer: FSF
d7b4d18f 7;; Keywords: tex
e5167999 8
528415e7 9;; Contributions over the years by William F. Schelter, Dick King,
70f20973 10;; Stephen Gildea, Michael Prange, Jacob Gore, and Edward M. Reingold.
528415e7 11
869bff31 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
6da9bbd6
RS
25;; along with GNU Emacs; see the file COPYING. If not, write to the
26;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27;; Boston, MA 02111-1307, USA.
869bff31 28
55535639
PJ
29;;; Commentary:
30
e5167999
ER
31;;; Code:
32
bed1b0c8
RS
33;; Pacify the byte-compiler
34(eval-when-compile
35 (require 'compare-w)
ea590e1c 36 (require 'cl)
bed1b0c8
RS
37 (require 'skeleton))
38
a0e9c22a 39(require 'shell)
2f3067de 40(require 'compile)
528415e7 41
d61140e8
RS
42(defgroup tex-file nil
43 "TeX files and directories"
44 :prefix "tex-"
45 :group 'tex)
46
47(defgroup tex-run nil
48 "Running external commands from TeX mode"
49 :prefix "tex-"
50 :group 'tex)
51
52(defgroup tex-view nil
53 "Viewing and printing TeX files"
54 :prefix "tex-"
55 :group 'tex)
56
7e1dae73 57;;;###autoload
d61140e8
RS
58(defcustom tex-shell-file-name nil
59 "*If non-nil, the shell file name to run in the subshell used to run TeX."
60 :type '(choice (const :tag "None" nil)
61 string)
62 :group 'tex-run)
528415e7 63
7e1dae73 64;;;###autoload
d61140e8 65(defcustom tex-directory "."
f73741fc 66 "*Directory in which temporary files are written.
81c735c0 67You can make this `/tmp' if your TEXINPUTS has no relative directories in it
528415e7 68and you don't try to apply \\[tex-region] or \\[tex-buffer] when there are
d61140e8
RS
69`\\input' commands with relative directories."
70 :type 'directory
71 :group 'tex-file)
869bff31 72
725b7428 73;;;###autoload
d61140e8 74(defcustom tex-first-line-header-regexp nil
725b7428
RS
75 "Regexp for matching a first line which `tex-region' should include.
76If this is non-nil, it should be a regular expression string;
77if it matches the first line of the file,
d61140e8
RS
78`tex-region' always includes the first line in the TeX run."
79 :type '(choice (const :tag "None" nil)
80 regexp)
81 :group 'tex-file)
725b7428 82
f73741fc 83;;;###autoload
d61140e8 84(defcustom tex-main-file nil
f73741fc 85 "*The main TeX source file which includes this buffer's file.
be4a962d
RS
86The command `tex-file' runs TeX on the file specified by `tex-main-file'
87if the variable is non-nil."
d61140e8
RS
88 :type '(choice (const :tag "None" nil)
89 file)
90 :group 'tex-file)
f73741fc 91
7e1dae73 92;;;###autoload
d61140e8
RS
93(defcustom tex-offer-save t
94 "*If non-nil, ask about saving modified buffers before \\[tex-file] is run."
95 :type 'boolean
96 :group 'tex-file)
869bff31 97
7e1dae73 98;;;###autoload
d61140e8 99(defcustom tex-run-command "tex"
869bff31 100 "*Command used to run TeX subjob.
c3ce7bf4
RS
101TeX Mode sets `tex-command' to this string.
102See the documentation of that variable."
d61140e8
RS
103 :type 'string
104 :group 'tex-run)
869bff31 105
7e1dae73 106;;;###autoload
d61140e8 107(defcustom latex-run-command "latex"
869bff31 108 "*Command used to run LaTeX subjob.
c3ce7bf4
RS
109LaTeX Mode sets `tex-command' to this string.
110See the documentation of that variable."
d61140e8
RS
111 :type 'string
112 :group 'tex-run)
528415e7 113
bed1b0c8
RS
114;;;###autoload
115(defcustom slitex-run-command "slitex"
116 "*Command used to run SliTeX subjob.
c3ce7bf4
RS
117SliTeX Mode sets `tex-command' to this string.
118See the documentation of that variable."
bed1b0c8
RS
119 :type 'string
120 :group 'tex-run)
121
c3ce7bf4 122;;;###autoload
9e0ad27a
RS
123(defcustom tex-start-options nil
124 "*TeX options to use when starting TeX.
125These precede the commands in `tex-start-options'
126and the input file name. If nil, TeX runs with no options.
c3ce7bf4
RS
127See the documentation of `tex-command'."
128 :type '(radio (const :tag "Interactive \(nil\)" nil)
129 (const :tag "Nonstop \(\"\\nonstopmode\\input\"\)"
130 "\\nonstopmode\\input")
131 (string :tag "String at your choice"))
bed1b0c8 132 :group 'tex-run
9e0ad27a
RS
133 :version "21.4")
134
135;;;###autoload
136(defcustom tex-start-commands "\\nonstopmode\\input"
137 "*TeX commands to use when starting TeX.
138These precede the input file name. If nil, no commands are used.
139See the documentation of `tex-command'."
140 :type '(radio (const :tag "Interactive \(nil\)" nil)
141 (const :tag "Nonstop \(\"\\nonstopmode\\input\"\)"
142 "\\nonstopmode\\input")
143 (string :tag "String at your choice"))
144 :group 'tex-run
145 :version "21.4")
bed1b0c8 146
528415e7 147(defvar standard-latex-block-names
dd459839
SM
148 '("abstract" "array" "center" "description"
149 "displaymath" "document" "enumerate" "eqnarray"
150 "eqnarray*" "equation" "figure" "figure*"
151 "flushleft" "flushright" "itemize" "letter"
152 "list" "minipage" "picture" "quotation"
153 "quote" "slide" "sloppypar" "tabbing"
154 "table" "table*" "tabular" "tabular*"
155 "thebibliography" "theindex*" "titlepage" "trivlist"
156 "verbatim" "verbatim*" "verse" "math")
528415e7
RS
157 "Standard LaTeX block names.")
158
7e1dae73 159;;;###autoload
d61140e8 160(defcustom latex-block-names nil
528415e7 161 "*User defined LaTeX block names.
d61140e8
RS
162Combined with `standard-latex-block-names' for minibuffer completion."
163 :type '(repeat string)
164 :group 'tex-run)
869bff31 165
7e1dae73 166;;;###autoload
d61140e8 167(defcustom tex-bibtex-command "bibtex"
528415e7 168 "*Command used by `tex-bibtex-file' to gather bibliographic data.
81c735c0 169If this string contains an asterisk (`*'), that is replaced by the file name;
d61140e8
RS
170otherwise, the file name, preceded by blank, is added at the end."
171 :type 'string
172 :group 'tex-run)
869bff31 173
7e1dae73 174;;;###autoload
d61140e8 175(defcustom tex-dvi-print-command "lpr -d"
528415e7 176 "*Command used by \\[tex-print] to print a .dvi file.
81c735c0 177If this string contains an asterisk (`*'), that is replaced by the file name;
d61140e8
RS
178otherwise, the file name, preceded by blank, is added at the end."
179 :type 'string
180 :group 'tex-view)
528415e7 181
7e1dae73 182;;;###autoload
d61140e8 183(defcustom tex-alt-dvi-print-command "lpr -d"
528415e7 184 "*Command used by \\[tex-print] with a prefix arg to print a .dvi file.
81c735c0
RS
185If this string contains an asterisk (`*'), that is replaced by the file name;
186otherwise, the file name, preceded by blank, is added at the end.
528415e7 187
81c735c0
RS
188If two printers are not enough of a choice, you can set the variable
189`tex-alt-dvi-print-command' to an expression that asks what you want;
528415e7
RS
190for example,
191
192 (setq tex-alt-dvi-print-command
193 '(format \"lpr -P%s\" (read-string \"Use printer: \")))
194
195would tell \\[tex-print] with a prefix argument to ask you which printer to
d61140e8
RS
196use."
197 :type '(choice (string :tag "Command")
198 (sexp :tag "Expression"))
199 :group 'tex-view)
869bff31 200
7e1dae73 201;;;###autoload
d61140e8 202(defcustom tex-dvi-view-command nil
81c735c0
RS
203 "*Command used by \\[tex-view] to display a `.dvi' file.
204If this string contains an asterisk (`*'), that is replaced by the file name;
205otherwise, the file name, preceded by blank, is added at the end.
528415e7
RS
206
207This can be set conditionally so that the previewer used is suitable for the
208window system being used. For example,
209
210 (setq tex-dvi-view-command
211 (if (eq window-system 'x) \"xdvi\" \"dvi2tty * | cat -s\"))
212
81c735c0 213would tell \\[tex-view] to use xdvi under X windows and to use dvi2tty
d61140e8
RS
214otherwise."
215 :type '(choice (const nil) string)
216 :group 'tex-view)
869bff31 217
7e1dae73 218;;;###autoload
d61140e8 219(defcustom tex-show-queue-command "lpq"
528415e7 220 "*Command used by \\[tex-show-print-queue] to show the print queue.
d61140e8
RS
221Should show the queue(s) that \\[tex-print] puts jobs on."
222 :type 'string
223 :group 'tex-view)
869bff31 224
7e1dae73 225;;;###autoload
9920303f 226(defcustom tex-default-mode 'latex-mode
869bff31 227 "*Mode to enter for a new file that might be either TeX or LaTeX.
228This variable is used when it can't be determined whether the file
229is plain TeX or LaTeX or what because the file contains no commands.
d61140e8
RS
230Normally set to either `plain-tex-mode' or `latex-mode'."
231 :type 'function
232 :group 'tex)
869bff31 233
7e1dae73 234;;;###autoload
d61140e8
RS
235(defcustom tex-open-quote "``"
236 "*String inserted by typing \\[tex-insert-quote] to open a quotation."
237 :type 'string
238 :group 'tex)
869bff31 239
7e1dae73 240;;;###autoload
d61140e8
RS
241(defcustom tex-close-quote "''"
242 "*String inserted by typing \\[tex-insert-quote] to close a quotation."
243 :type 'string
244 :group 'tex)
869bff31 245
528415e7
RS
246(defvar tex-last-temp-file nil
247 "Latest temporary file generated by \\[tex-region] and \\[tex-buffer].
248Deleted when the \\[tex-region] or \\[tex-buffer] is next run, or when the
81c735c0 249tex shell terminates.")
528415e7 250
869bff31 251(defvar tex-command nil
c3ce7bf4
RS
252 "*Command to run TeX.
253If this string contains an asterisk \(`*'\), that is replaced by the file name\;
9e0ad27a
RS
254otherwise the value of `tex-start-options', the \(shell-quoted\)
255value of `tex-start-commands', and the file name are added at the end
256with blanks as separators.
c3ce7bf4
RS
257
258In TeX, LaTeX, and SliTeX Mode this variable becomes buffer local.
259In these modes, use \\[set-variable] if you want to change it for the
260current buffer.")
869bff31 261
262(defvar tex-trailer nil
263 "String appended after the end of a region sent to TeX by \\[tex-region].")
264
265(defvar tex-start-of-header nil
898b9ac1 266 "Regular expression used by \\[tex-region] to find start of file's header.")
869bff31 267
268(defvar tex-end-of-header nil
898b9ac1 269 "Regular expression used by \\[tex-region] to find end of file's header.")
869bff31 270
271(defvar tex-shell-cd-command "cd"
272 "Command to give to shell running TeX to change directory.
81c735c0 273The value of `tex-directory' is appended to this, separated by a space.")
869bff31 274
275(defvar tex-zap-file nil
276 "Temporary file name used for text being sent as input to TeX.
277Should be a simple file name with no extension or directory specification.")
278
279(defvar tex-last-buffer-texed nil
280 "Buffer which was last TeXed.")
281
282(defvar tex-print-file nil
283 "File name that \\[tex-print] prints.
284Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")
285
ea590e1c
SM
286(easy-mmode-defsyntax tex-mode-syntax-table
287 '((?% . "<")
288 (?\n . ">")
289 (?\f . ">")
290 (?\C-@ . "w")
291 (?' . "w")
292 (?@ . "_")
293 (?* . "_")
294 (?\t . " ")
295 (?~ . " ")
296 (?$ . "$$")
297 (?\\ . "/")
298 (?\" . ".")
299 (?& . ".")
15ca8de7
SM
300 (?_ . ".")
301 (?^ . "."))
869bff31 302 "Syntax table used while in TeX mode.")
53c4fe47
SM
303\f
304;;;;
305;;;; Imenu support
306;;;;
869bff31 307
d6709b80 308(defcustom latex-imenu-indent-string ". "
a53c647b
RS
309 "*String to add repeated in front of nested sectional units for Imenu.
310An alternative value is \" . \", if you use a font with a narrow period."
311 :type 'string
312 :group 'tex)
313
d6709b80
SM
314(defvar latex-section-alist
315 '(("part" . 0) ("chapter" . 1)
316 ("section" . 2) ("subsection" . 3)
317 ("subsubsection" . 4)
318 ("paragraph" . 5) ("subparagraph" . 6)))
319
53c4fe47
SM
320(defvar latex-metasection-list
321 '("documentstyle" "documentclass"
322 "begin{document}" "end{document}"
323 "appendix" "frontmatter" "mainmatter" "backmatter"))
324
a5e2ae01 325(defun latex-imenu-create-index ()
53c4fe47
SM
326 "Generate an alist for imenu from a LaTeX buffer."
327 (let ((section-regexp
328 (concat "\\\\" (regexp-opt (mapcar 'car latex-section-alist) t)
329 "\\*?[ \t]*{"))
330 (metasection-regexp
331 (concat "\\\\" (regexp-opt latex-metasection-list t)))
332 i0 menu case-fold-search)
a53c647b
RS
333 (save-excursion
334 ;; Find the top-most level in this file but don't allow it to be
335 ;; any deeper than "section" (which is top-level in an article).
336 (goto-char (point-min))
337 (if (search-forward-regexp "\\\\part\\*?[ \t]*{" nil t)
338 (setq i0 0)
339 (if (search-forward-regexp "\\\\chapter\\*?[ \t]*{" nil t)
340 (setq i0 1)
341 (setq i0 2)))
342
343 ;; Look for chapters and sections.
344 (goto-char (point-min))
53c4fe47 345 (while (search-forward-regexp section-regexp nil t)
a53c647b
RS
346 (let ((start (match-beginning 0))
347 (here (point))
348 (i (cdr (assoc (buffer-substring-no-properties
349 (match-beginning 1)
350 (match-end 1))
d6709b80 351 latex-section-alist))))
a53c647b
RS
352 (backward-char 1)
353 (condition-case err
354 (progn
355 ;; Using sexps allows some use of matching {...} inside
356 ;; titles.
357 (forward-sexp 1)
d6709b80
SM
358 (push (cons (concat (apply 'concat
359 (make-list
360 (max 0 (- i i0))
361 latex-imenu-indent-string))
362 (buffer-substring-no-properties
363 here (1- (point))))
364 start)
365 menu))
a53c647b
RS
366 (error nil))))
367
368 ;; Look for included material.
369 (goto-char (point-min))
370 (while (search-forward-regexp
371 "\\\\\\(include\\|input\\|verbatiminput\\|bibliography\\)\
53c4fe47 372\[ \t]*{\\([^}\n]+\\)}"
a53c647b 373 nil t)
53c4fe47
SM
374 (push (cons (concat "<<" (buffer-substring-no-properties
375 (match-beginning 2)
376 (match-end 2))
377 (if (= (char-after (match-beginning 1)) ?b)
378 ".bbl"
379 ".tex"))
380 (match-beginning 0))
381 menu))
a53c647b
RS
382
383 ;; Look for \frontmatter, \mainmatter, \backmatter, and \appendix.
384 (goto-char (point-min))
53c4fe47
SM
385 (while (search-forward-regexp metasection-regexp nil t)
386 (push (cons "--" (match-beginning 0)) menu))
a53c647b
RS
387
388 ;; Sort in increasing buffer position order.
389 (sort menu (function (lambda (a b) (< (cdr a) (cdr b))))))))
53c4fe47
SM
390\f
391;;;;
392;;;; Outline support
393;;;;
394
395(defvar latex-outline-regexp
396 (concat "\\\\"
397 (regexp-opt (append latex-metasection-list
398 (mapcar 'car latex-section-alist)) t)))
399
400(defun latex-outline-level ()
401 (if (looking-at latex-outline-regexp)
402 (1+ (or (cdr (assoc (match-string 1) latex-section-alist)) -1))
403 1000))
404\f
405;;;;
406;;;; Font-Lock support
407;;;;
408
409;(defvar tex-font-lock-keywords
410; ;; Regexps updated with help from Ulrik Dickow <dickow@nbi.dk>.
411; '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}"
412; 2 font-lock-function-name-face)
413; ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}"
414; 2 font-lock-constant-face)
415; ;; It seems a bit dubious to use `bold' and `italic' faces since we might
416; ;; not be able to display those fonts.
417; ("{\\\\bf\\([^}]+\\)}" 1 'bold keep)
418; ("{\\\\\\(em\\|it\\|sl\\)\\([^}]+\\)}" 2 'italic keep)
419; ("\\\\\\([a-zA-Z@]+\\|.\\)" . font-lock-keyword-face)
420; ("^[ \t\n]*\\\\def[\\\\@]\\(\\w+\\)" 1 font-lock-function-name-face keep))
421; ;; Rewritten and extended for LaTeX2e by Ulrik Dickow <dickow@nbi.dk>.
422; '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}"
423; 2 font-lock-function-name-face)
424; ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}"
425; 2 font-lock-constant-face)
426; ("^[ \t]*\\\\def\\\\\\(\\(\\w\\|@\\)+\\)" 1 font-lock-function-name-face)
427; "\\\\\\([a-zA-Z@]+\\|.\\)"
428; ;; It seems a bit dubious to use `bold' and `italic' faces since we might
429; ;; not be able to display those fonts.
430; ;; LaTeX2e: \emph{This is emphasized}.
431; ("\\\\emph{\\([^}]+\\)}" 1 'italic keep)
432; ;; LaTeX2e: \textbf{This is bold}, \textit{...}, \textsl{...}
433; ("\\\\text\\(\\(bf\\)\\|it\\|sl\\){\\([^}]+\\)}"
434; 3 (if (match-beginning 2) 'bold 'italic) keep)
435; ;; Old-style bf/em/it/sl. Stop at `\\' and un-escaped `&', for tables.
436; ("\\\\\\(\\(bf\\)\\|em\\|it\\|sl\\)\\>\\(\\([^}&\\]\\|\\\\[^\\]\\)+\\)"
437; 3 (if (match-beginning 2) 'bold 'italic) keep))
438
439;; Rewritten with the help of Alexandra Bac <abac@welcome.disi.unige.it>.
440(defconst tex-font-lock-keywords-1
441 (eval-when-compile
442 (let* (;; Names of commands whose arg should be fontified as heading, etc.
443 (headings (regexp-opt
444 '("title" "begin" "end" "chapter" "part"
445 "section" "subsection" "subsubsection"
446 "paragraph" "subparagraph" "subsubparagraph"
447 "newcommand" "renewcommand" "newenvironment"
448 "newtheorem")
449 t))
450 (variables (regexp-opt
451 '("newcounter" "newcounter*" "setcounter" "addtocounter"
452 "setlength" "addtolength" "settowidth")
453 t))
454 (includes (regexp-opt
455 '("input" "include" "includeonly" "bibliography"
456 "epsfig" "psfig" "epsf" "nofiles" "usepackage"
15ca8de7 457 "documentstyle" "documentclass" "verbatiminput"
53c4fe47
SM
458 "includegraphics" "includegraphics*")
459 t))
460 ;; Miscellany.
461 (slash "\\\\")
15ca8de7
SM
462 (opt " *\\(\\[[^]]*\\] *\\)*")
463 ;; This would allow highlighting \newcommand\CMD but requires
464 ;; adapting subgroup numbers below.
465 ;; (arg "\\(?:{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)\\|\\\\[a-z*]+\\)"))
1598a961 466 (arg "{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)"))
53c4fe47
SM
467 (list
468 ;; Heading args.
469 (list (concat slash headings "\\*?" opt arg)
bdbd9606
SM
470 ;; If ARG ends up matching too much (if the {} don't match, f.ex)
471 ;; jit-lock will do funny things: when updating the buffer
472 ;; the re-highlighting is only done locally so it will just
473 ;; match the local line, but defer-contextually will
474 ;; match more lines at a time, so ARG will end up matching
475 ;; a lot more, which might suddenly include a comment
476 ;; so you get things highlighted bold when you type them
477 ;; but they get turned back to normal a little while later
478 ;; because "there's already a face there".
479 ;; Using `keep' works around this un-intuitive behavior as well
15ca8de7
SM
480 ;; as improves the behavior in the very rare case where you do
481 ;; have a comment in ARG.
bdbd9606 482 3 'font-lock-function-name-face 'keep)
15ca8de7
SM
483 (list (concat slash "\\(re\\)?newcommand\\** *\\(\\\\[A-Za-z@]+\\)")
484 2 'font-lock-function-name-face 'keep)
53c4fe47 485 ;; Variable args.
15ca8de7 486 (list (concat slash variables " *" arg) 2 'font-lock-variable-name-face)
53c4fe47
SM
487 ;; Include args.
488 (list (concat slash includes opt arg) 3 'font-lock-builtin-face)
489 ;; Definitions. I think.
15ca8de7 490 '("^[ \t]*\\\\def *\\\\\\(\\(\\w\\|@\\)+\\)"
bdbd9606 491 1 font-lock-function-name-face))))
53c4fe47
SM
492 "Subdued expressions to highlight in TeX modes.")
493
494(defconst tex-font-lock-keywords-2
495 (append tex-font-lock-keywords-1
496 (eval-when-compile
497 (let* (;;
498 ;; Names of commands whose arg should be fontified with fonts.
1598a961 499 (bold (regexp-opt '("textbf" "textsc" "textup"
53c4fe47 500 "boldsymbol" "pmb") t))
1598a961 501 (italic (regexp-opt '("textit" "textsl" "emph") t))
53c4fe47
SM
502 (type (regexp-opt '("texttt" "textmd" "textrm" "textsf") t))
503 ;;
504 ;; Names of commands whose arg should be fontified as a citation.
505 (citations (regexp-opt
506 '("label" "ref" "pageref" "vref" "eqref"
15ca8de7 507 "cite" "nocite" "index" "glossary" "bibitem"
1598a961
SM
508 ;; These are text, rather than citations.
509 ;; "caption" "footnote" "footnotemark" "footnotetext"
510 )
53c4fe47
SM
511 t))
512 ;;
513 ;; Names of commands that should be fontified.
1b741d9e
AS
514 (specials-1 (regexp-opt '("\\" "\\*") t)) ;; "-"
515 (specials-2 (regexp-opt
516 '("linebreak" "nolinebreak" "pagebreak" "nopagebreak"
517 "newline" "newpage" "clearpage" "cleardoublepage"
518 "displaybreak" "allowdisplaybreaks"
519 "enlargethispage") t))
53c4fe47
SM
520 (general "\\([a-zA-Z@]+\\**\\|[^ \t\n]\\)")
521 ;;
522 ;; Miscellany.
523 (slash "\\\\")
15ca8de7 524 (opt " *\\(\\[[^]]*\\] *\\)*")
1598a961 525 (arg "{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)"))
53c4fe47
SM
526 (list
527 ;;
528 ;; Citation args.
529 (list (concat slash citations opt arg) 3 'font-lock-constant-face)
530 ;;
15ca8de7 531 ;; Text between `` quotes ''.
7abc9add
SS
532 (cons (concat (regexp-opt `("``" "\"<" "\"`" "<<" "k") t)
533 "[^'\">{]+" ;a bit pessimistic
534 (regexp-opt `("''" "\">" "\"'" ">>" "{") t))
15ca8de7
SM
535 'font-lock-string-face)
536 ;;
53c4fe47 537 ;; Command names, special and general.
1b741d9e
AS
538 (cons (concat slash specials-1) 'font-lock-warning-face)
539 (list (concat "\\(" slash specials-2 "\\)\\([^a-zA-Z@]\\|\\'\\)")
540 1 'font-lock-warning-face)
53c4fe47
SM
541 (concat slash general)
542 ;;
543 ;; Font environments. It seems a bit dubious to use `bold' etc. faces
544 ;; since we might not be able to display those fonts.
15ca8de7
SM
545 (list (concat slash bold " *" arg) 2 '(quote bold) 'append)
546 (list (concat slash italic " *" arg) 2 '(quote italic) 'append)
1598a961 547 ;; (list (concat slash type arg) 2 '(quote bold-italic) 'append)
53c4fe47
SM
548 ;;
549 ;; Old-style bf/em/it/sl. Stop at `\\' and un-escaped `&', for tables.
550 (list (concat "\\\\\\(\\(bf\\)\\|em\\|it\\|sl\\)\\>"
551 "\\(\\([^}&\\]\\|\\\\[^\\]\\)+\\)")
bdbd9606 552 3 '(if (match-beginning 2) 'bold 'italic) 'append)))))
53c4fe47
SM
553 "Gaudy expressions to highlight in TeX modes.")
554
555(defvar tex-font-lock-keywords tex-font-lock-keywords-1
556 "Default expressions to highlight in TeX modes.")
0fb4f245 557
bdbd9606
SM
558
559(defface tex-math-face
560 '((t :inherit font-lock-string-face))
561 "Face used to highlight TeX math expressions.")
562(defvar tex-math-face 'tex-math-face)
563
564;; Use string syntax but math face for $...$.
565(defun tex-font-lock-syntactic-face-function (state)
566 (if (nth 3 state) tex-math-face font-lock-comment-face))
567
53c4fe47 568\f
869bff31 569(defun tex-define-common-keys (keymap)
81c735c0 570 "Define the keys that we want defined both in TeX mode and in the TeX shell."
869bff31 571 (define-key keymap "\C-c\C-k" 'tex-kill-job)
572 (define-key keymap "\C-c\C-l" 'tex-recenter-output-buffer)
573 (define-key keymap "\C-c\C-q" 'tex-show-print-queue)
574 (define-key keymap "\C-c\C-p" 'tex-print)
575 (define-key keymap "\C-c\C-v" 'tex-view)
62a24cb5
RS
576
577 (define-key keymap [menu-bar tex] (cons "TeX" (make-sparse-keymap "TeX")))
578
bdbd9606
SM
579 (define-key keymap [menu-bar tex tex-kill-job]
580 '(menu-item "Tex Kill" tex-kill-job :enable (tex-shell-running)))
cf6d6e8a 581 (define-key keymap [menu-bar tex tex-recenter-output-buffer]
bdbd9606
SM
582 '(menu-item "Tex Recenter" tex-recenter-output-buffer
583 :enable (get-buffer "*tex-shell*")))
62a24cb5
RS
584 (define-key keymap [menu-bar tex tex-show-print-queue]
585 '("Show Print Queue" . tex-show-print-queue))
cf6d6e8a 586 (define-key keymap [menu-bar tex tex-alt-print]
bdbd9606
SM
587 '(menu-item "Tex Print (alt printer)" tex-alt-print
588 :enable (stringp tex-print-file)))
589 (define-key keymap [menu-bar tex tex-print]
590 '(menu-item "Tex Print" tex-print :enable (stringp tex-print-file)))
591 (define-key keymap [menu-bar tex tex-view]
592 '(menu-item "Tex View" tex-view :enable (stringp tex-print-file))))
593
594(defvar tex-mode-map
595 (let ((map (make-sparse-keymap)))
15ca8de7 596 (set-keymap-parent map text-mode-map)
bdbd9606
SM
597 (tex-define-common-keys map)
598 (define-key map "\"" 'tex-insert-quote)
599 (define-key map "(" 'skeleton-pair-insert-maybe)
600 (define-key map "{" 'skeleton-pair-insert-maybe)
601 (define-key map "[" 'skeleton-pair-insert-maybe)
602 (define-key map "$" 'skeleton-pair-insert-maybe)
603 (define-key map "\n" 'tex-terminate-paragraph)
15ca8de7 604 (define-key map "\t" 'indent-for-tab-command)
bdbd9606
SM
605 (define-key map "\M-\r" 'latex-insert-item)
606 (define-key map "\C-c}" 'up-list)
607 (define-key map "\C-c{" 'tex-insert-braces)
608 (define-key map "\C-c\C-r" 'tex-region)
609 (define-key map "\C-c\C-b" 'tex-buffer)
610 (define-key map "\C-c\C-f" 'tex-file)
bdbd9606
SM
611 (define-key map "\C-c\C-i" 'tex-bibtex-file)
612 (define-key map "\C-c\C-o" 'tex-latex-block)
613 (define-key map "\C-c\C-e" 'tex-close-latex-block)
614 (define-key map "\C-c\C-u" 'tex-goto-last-unclosed-latex-block)
615 (define-key map "\C-c\C-m" 'tex-feed-input)
616 (define-key map [(control return)] 'tex-feed-input)
617 (define-key map [menu-bar tex tex-bibtex-file]
618 '("BibTeX File" . tex-bibtex-file))
619 (define-key map [menu-bar tex tex-validate-region]
620 '(menu-item "Validate Region" tex-validate-region :enable mark-active))
621 (define-key map [menu-bar tex tex-validate-buffer]
622 '("Validate Buffer" . tex-validate-buffer))
623 (define-key map [menu-bar tex tex-region]
624 '(menu-item "TeX Region" tex-region :enable mark-active))
625 (define-key map [menu-bar tex tex-buffer]
626 '("TeX Buffer" . tex-buffer))
627 (define-key map [menu-bar tex tex-file] '("TeX File" . tex-file))
628 map)
15ca8de7
SM
629 "Keymap shared by TeX modes.")
630
631(defvar latex-mode-map
632 (let ((map (make-sparse-keymap)))
633 (set-keymap-parent map tex-mode-map)
634 map)
635 "Keymap for `latex-mode'. See also `tex-mode-map'.")
636
637(defvar plain-tex-mode-map
638 (let ((map (make-sparse-keymap)))
639 (set-keymap-parent map tex-mode-map)
640 map)
641 "Keymap for `plain-tex-mode'. See also `tex-mode-map'.")
cf6d6e8a 642
d6709b80
SM
643(defvar tex-shell-map
644 (let ((m (make-sparse-keymap)))
645 (set-keymap-parent m shell-mode-map)
646 (tex-define-common-keys m)
647 m)
81c735c0 648 "Keymap for the TeX shell.
dca5ea48 649Inherits `shell-mode-map' with a few additions.")
869bff31 650
6da9bbd6
RS
651(defvar tex-face-alist
652 '((bold . "{\\bf ")
653 (italic . "{\\it ")
654 (bold-italic . "{\\bi ") ; hypothetical
655 (underline . "\\underline{")
656 (default . "{\\rm "))
657 "Alist of face and TeX font name for facemenu.")
658
659(defvar tex-latex-face-alist
660 `((italic . "{\\em ")
661 ,@tex-face-alist)
662 "Alist of face and LaTeX font name for facemenu.")
663
15ca8de7
SM
664;; This would be a lot simpler if we just used a regexp search,
665;; but then it would be too slow.
7229064d 666;;;###autoload
869bff31 667(defun tex-mode ()
668 "Major mode for editing files of input for TeX, LaTeX, or SliTeX.
669Tries to determine (by looking at the beginning of the file) whether
81c735c0
RS
670this file is for plain TeX, LaTeX, or SliTeX and calls `plain-tex-mode',
671`latex-mode', or `slitex-mode', respectively. If it cannot be determined,
672such as if there are no commands in the file, the value of `tex-default-mode'
673says which mode to use."
869bff31 674 (interactive)
d6709b80 675 (let ((mode tex-default-mode) slash comment)
869bff31 676 (save-excursion
677 (goto-char (point-min))
678 (while (and (setq slash (search-forward "\\" nil t))
679 (setq comment (let ((search-end (point)))
680 (save-excursion
681 (beginning-of-line)
682 (search-forward "%" search-end t))))))
bdbd9606
SM
683 (when (and slash (not comment))
684 (setq mode
685 (if (looking-at
686 (eval-when-compile
687 (concat
688 (regexp-opt '("documentstyle" "documentclass"
689 "begin" "section" "part" "chapter") 'words)
690 "\\|NeedsTeXFormat{LaTeX")))
691 (if (looking-at
692 "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")
693 'slitex-mode
694 'latex-mode)
695 'plain-tex-mode))))
d6709b80 696 (funcall mode)))
e4c8c838 697
6503cec3 698;;;###autoload
31e1d920 699(defalias 'TeX-mode 'tex-mode)
6503cec3 700;;;###autoload
c3ce7bf4
RS
701(defalias 'plain-TeX-mode 'plain-tex-mode)
702;;;###autoload
31e1d920 703(defalias 'LaTeX-mode 'latex-mode)
869bff31 704
7229064d 705;;;###autoload
d6709b80 706(define-derived-mode plain-tex-mode text-mode "TeX"
869bff31 707 "Major mode for editing files of input for plain TeX.
708Makes $ and } display the characters they match.
709Makes \" insert `` when it seems to be the beginning of a quotation,
710and '' when it appears to be the end; it inserts \" only after a \\.
711
712Use \\[tex-region] to run TeX on the current region, plus a \"header\"
713copied from the top of the file (containing macro definitions, etc.),
714running TeX under a special subshell. \\[tex-buffer] does the whole buffer.
715\\[tex-file] saves the buffer and then processes the file.
716\\[tex-print] prints the .dvi file made by any of these.
717\\[tex-view] previews the .dvi file made by any of these.
718\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
719
e6b0b773 720Use \\[tex-validate-buffer] to check buffer for paragraphs containing
869bff31 721mismatched $'s or braces.
722
723Special commands:
15ca8de7 724\\{plain-tex-mode-map}
869bff31 725
726Mode variables:
727tex-run-command
728 Command string used by \\[tex-region] or \\[tex-buffer].
729tex-directory
730 Directory in which to create temporary files for TeX jobs
731 run by \\[tex-region] or \\[tex-buffer].
732tex-dvi-print-command
733 Command string used by \\[tex-print] to print a .dvi file.
528415e7
RS
734tex-alt-dvi-print-command
735 Alternative command string used by \\[tex-print] (when given a prefix
736 argument) to print a .dvi file.
869bff31 737tex-dvi-view-command
738 Command string used by \\[tex-view] to preview a .dvi file.
739tex-show-queue-command
740 Command string used by \\[tex-show-print-queue] to show the print
741 queue that \\[tex-print] put your job on.
742
81c735c0
RS
743Entering Plain-tex mode runs the hook `text-mode-hook', then the hook
744`tex-mode-hook', and finally the hook `plain-tex-mode-hook'. When the
745special subshell is initiated, the hook `tex-shell-hook' is run."
869bff31 746 (tex-common-initialization)
869bff31 747 (setq tex-command tex-run-command)
898b9ac1
RS
748 (setq tex-start-of-header "%\\*\\*start of header")
749 (setq tex-end-of-header "%\\*\\*end of header")
869bff31 750 (setq tex-trailer "\\bye\n")
d6709b80 751 (run-hooks 'tex-mode-hook))
869bff31 752
7229064d 753;;;###autoload
d6709b80 754(define-derived-mode latex-mode text-mode "LaTeX"
869bff31 755 "Major mode for editing files of input for LaTeX.
756Makes $ and } display the characters they match.
757Makes \" insert `` when it seems to be the beginning of a quotation,
758and '' when it appears to be the end; it inserts \" only after a \\.
759
760Use \\[tex-region] to run LaTeX on the current region, plus the preamble
761copied from the top of the file (containing \\documentstyle, etc.),
762running LaTeX under a special subshell. \\[tex-buffer] does the whole buffer.
763\\[tex-file] saves the buffer and then processes the file.
764\\[tex-print] prints the .dvi file made by any of these.
765\\[tex-view] previews the .dvi file made by any of these.
766\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
767
e6b0b773 768Use \\[tex-validate-buffer] to check buffer for paragraphs containing
869bff31 769mismatched $'s or braces.
770
771Special commands:
15ca8de7 772\\{latex-mode-map}
869bff31 773
774Mode variables:
775latex-run-command
776 Command string used by \\[tex-region] or \\[tex-buffer].
777tex-directory
778 Directory in which to create temporary files for LaTeX jobs
779 run by \\[tex-region] or \\[tex-buffer].
780tex-dvi-print-command
781 Command string used by \\[tex-print] to print a .dvi file.
528415e7
RS
782tex-alt-dvi-print-command
783 Alternative command string used by \\[tex-print] (when given a prefix
784 argument) to print a .dvi file.
869bff31 785tex-dvi-view-command
786 Command string used by \\[tex-view] to preview a .dvi file.
787tex-show-queue-command
788 Command string used by \\[tex-show-print-queue] to show the print
789 queue that \\[tex-print] put your job on.
790
bed1b0c8 791Entering Latex mode runs the hook `text-mode-hook', then
81c735c0
RS
792`tex-mode-hook', and finally `latex-mode-hook'. When the special
793subshell is initiated, `tex-shell-hook' is run."
869bff31 794 (tex-common-initialization)
869bff31 795 (setq tex-command latex-run-command)
dd459839
SM
796 (setq tex-start-of-header "\\\\document\\(style\\|class\\)")
797 (setq tex-end-of-header "\\\\begin\\s-*{document}")
798 (setq tex-trailer "\\end\\s-*{document}\n")
ab2c9f54
RS
799 ;; A line containing just $$ is treated as a paragraph separator.
800 ;; A line starting with $$ starts a paragraph,
801 ;; but does not separate paragraphs if it has more stuff on it.
d6709b80 802 (setq paragraph-start
dd459839 803 (concat "[\f%]\\|[ \t]*\\($\\|\\$\\$\\|"
d6709b80
SM
804 "\\\\[][]\\|"
805 "\\\\" (regexp-opt (append
806 (mapcar 'car latex-section-alist)
807 '("begin" "label" "end"
808 "item" "bibitem" "newline" "noindent"
809 "newpage" "footnote" "marginpar"
810 "parbox" "caption")) t)
811 "\\>\\|\\\\[a-z]*" (regexp-opt '("space" "skip" "page") t)
dd459839 812 "\\>\\)"))
d6709b80 813 (setq paragraph-separate
dd459839 814 (concat "[\f%]\\|[ \t]*\\($\\|"
d6709b80
SM
815 "\\\\[][]\\|"
816 "\\\\" (regexp-opt (append
817 (mapcar 'car latex-section-alist)
818 '("begin" "label" "end" )) t)
819 "\\>\\|\\\\\\(" (regexp-opt '("item" "bibitem" "newline"
820 "noindent" "newpage" "footnote"
821 "marginpar" "parbox" "caption"))
dd459839
SM
822 "\\|\\$\\$\\|[a-z]*\\(space\\|skip\\|page[a-z]*\\)"
823 "\\>\\)[ \t]*\\($\\|%\\)\\)"))
d6709b80
SM
824 (set (make-local-variable 'imenu-create-index-function)
825 'latex-imenu-create-index)
826 (set (make-local-variable 'tex-face-alist) tex-latex-face-alist)
827 (set (make-local-variable 'fill-nobreak-predicate)
828 'latex-fill-nobreak-predicate)
ea590e1c 829 (set (make-local-variable 'indent-line-function) 'latex-indent)
dd459839 830 (set (make-local-variable 'fill-indent-according-to-mode) t)
d6709b80
SM
831 (set (make-local-variable 'outline-regexp) latex-outline-regexp)
832 (set (make-local-variable 'outline-level) 'latex-outline-level)
53c4fe47 833 (set (make-local-variable 'forward-sexp-function) 'latex-forward-sexp)
15ca8de7 834 (set (make-local-variable 'skeleton-end-hook) nil)
d6709b80 835 (run-hooks 'tex-mode-hook))
869bff31 836
bd2f2323 837;;;###autoload
d6709b80 838(define-derived-mode slitex-mode latex-mode "SliTeX"
869bff31 839 "Major mode for editing files of input for SliTeX.
840Makes $ and } display the characters they match.
841Makes \" insert `` when it seems to be the beginning of a quotation,
842and '' when it appears to be the end; it inserts \" only after a \\.
843
844Use \\[tex-region] to run SliTeX on the current region, plus the preamble
845copied from the top of the file (containing \\documentstyle, etc.),
846running SliTeX under a special subshell. \\[tex-buffer] does the whole buffer.
847\\[tex-file] saves the buffer and then processes the file.
848\\[tex-print] prints the .dvi file made by any of these.
849\\[tex-view] previews the .dvi file made by any of these.
850\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
851
e6b0b773 852Use \\[tex-validate-buffer] to check buffer for paragraphs containing
869bff31 853mismatched $'s or braces.
854
855Special commands:
15ca8de7 856\\{slitex-mode-map}
869bff31 857
858Mode variables:
859slitex-run-command
860 Command string used by \\[tex-region] or \\[tex-buffer].
861tex-directory
862 Directory in which to create temporary files for SliTeX jobs
863 run by \\[tex-region] or \\[tex-buffer].
864tex-dvi-print-command
865 Command string used by \\[tex-print] to print a .dvi file.
528415e7
RS
866tex-alt-dvi-print-command
867 Alternative command string used by \\[tex-print] (when given a prefix
868 argument) to print a .dvi file.
869bff31 869tex-dvi-view-command
870 Command string used by \\[tex-view] to preview a .dvi file.
871tex-show-queue-command
872 Command string used by \\[tex-show-print-queue] to show the print
873 queue that \\[tex-print] put your job on.
874
81c735c0
RS
875Entering SliTeX mode runs the hook `text-mode-hook', then the hook
876`tex-mode-hook', then the hook `latex-mode-hook', and finally the hook
877`slitex-mode-hook'. When the special subshell is initiated, the hook
878`tex-shell-hook' is run."
869bff31 879 (setq tex-command slitex-run-command)
d6709b80 880 (setq tex-start-of-header "\\\\documentstyle{slides}\\|\\\\documentclass{slides}"))
869bff31 881
882(defun tex-common-initialization ()
ea590e1c 883 (set-syntax-table tex-mode-syntax-table)
822eddf4 884 ;; Regexp isearch should accept newline and formfeed as whitespace.
d6709b80 885 (set (make-local-variable 'search-whitespace-regexp) "[ \t\r\n\f]+")
64db2461 886 ;; A line containing just $$ is treated as a paragraph separator.
d6709b80
SM
887 (set (make-local-variable 'paragraph-start)
888 "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$")
ab2c9f54
RS
889 ;; A line starting with $$ starts a paragraph,
890 ;; but does not separate paragraphs if it has more stuff on it.
d6709b80
SM
891 (set (make-local-variable 'paragraph-separate)
892 "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$[ \t]*$")
893 (set (make-local-variable 'comment-start) "%")
894 (set (make-local-variable 'comment-add) 1)
895 (set (make-local-variable 'comment-start-skip)
896 "\\(\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
d6709b80
SM
897 (set (make-local-variable 'parse-sexp-ignore-comments) t)
898 (set (make-local-variable 'compare-windows-whitespace)
899 'tex-categorize-whitespace)
900 (set (make-local-variable 'facemenu-add-face-function)
901 (lambda (face end)
902 (let ((face-text (cdr (assq face tex-face-alist))))
903 (if face-text
904 face-text
905 (error "Face %s not configured for %s mode" face mode-name)))))
906 (set (make-local-variable 'facemenu-end-add-face) "}")
907 (set (make-local-variable 'facemenu-remove-face-function) t)
908 (set (make-local-variable 'font-lock-defaults)
909 '((tex-font-lock-keywords
910 tex-font-lock-keywords-1 tex-font-lock-keywords-2)
911 nil nil ((?$ . "\"")) nil
912 ;; Who ever uses that anyway ???
bdbd9606
SM
913 (font-lock-mark-block-function . mark-paragraph)
914 (font-lock-syntactic-face-function
915 . tex-font-lock-syntactic-face-function)))
869bff31 916 (make-local-variable 'tex-command)
917 (make-local-variable 'tex-start-of-header)
918 (make-local-variable 'tex-end-of-header)
919 (make-local-variable 'tex-trailer))
920
869bff31 921(defun tex-categorize-whitespace (backward-limit)
922 ;; compare-windows-whitespace is set to this.
923 ;; This is basically a finite-state machine.
924 ;; Returns a symbol telling how TeX would treat
925 ;; the whitespace we are looking at: null, space, or par.
926 (let ((category 'null)
927 (not-finished t))
928 (skip-chars-backward " \t\n\f" backward-limit)
929 (while not-finished
930 (cond ((looking-at "[ \t]+")
931 (goto-char (match-end 0))
2be5fefb 932 (if (eq category 'null)
869bff31 933 (setq category 'space)))
934 ((looking-at "\n")
2be5fefb 935 (cond ((eq category 'newline)
869bff31 936 (setq category 'par)
937 (setq not-finished nil))
938 (t
939 (setq category 'newline) ;a strictly internal state
940 (goto-char (match-end 0)))))
941 ((looking-at "\f+")
942 (setq category 'par)
943 (setq not-finished nil))
944 (t
945 (setq not-finished nil))))
946 (skip-chars-forward " \t\n\f")
2be5fefb 947 (if (eq category 'newline)
869bff31 948 'space ;TeX doesn't distinguish
949 category)))
950
951(defun tex-insert-quote (arg)
952 "Insert the appropriate quote marks for TeX.
08348502
RS
953Inserts the value of `tex-open-quote' (normally ``) or `tex-close-quote'
954\(normally '') depending on the context. With prefix argument, always
869bff31 955inserts \" characters."
528415e7 956 (interactive "*P")
869bff31 957 (if arg
958 (self-insert-command (prefix-numeric-value arg))
959 (insert
bdbd9606
SM
960 (cond ((= (preceding-char) ?\\) ?\")
961 ((memq (char-syntax (preceding-char)) '(?\( ?> ?\ )) tex-open-quote)
962 (t tex-close-quote)))))
869bff31 963
e6b0b773
MR
964(defun tex-validate-buffer ()
965 "Check current buffer for paragraphs containing mismatched braces or $s.
bbd93e41 966Their positions are recorded in the buffer `*Occur*'.
e6b0b773
MR
967To find a particular invalidity from `*Occur*', switch to that buffer
968and type C-c C-c or click with mouse-2
969on the line for the invalidity you want to see."
869bff31 970 (interactive)
bbd93e41
RS
971 (let ((buffer (current-buffer))
972 (prevpos (point-min))
e6b0b773
MR
973 (linenum nil)
974 (num-matches 0))
bbd93e41
RS
975 (with-output-to-temp-buffer "*Occur*"
976 (princ "Mismatches:\n")
977 (save-excursion
978 (set-buffer standard-output)
979 (occur-mode)
52ab062c
CW
980 ;; This won't actually work...Really, this whole thing should
981 ;; be rewritten instead of being a hack on top of occur.
982 (setq occur-revert-arguments (list nil 0 (list buffer))))
bbd93e41
RS
983 (save-excursion
984 (goto-char (point-max))
52ab062c 985 (while (and (not (bobp)))
710a0f53
KH
986 (let ((end (point))
987 prev-end)
bbd93e41 988 ;; Scan the previous paragraph for invalidities.
710a0f53
KH
989 (if (search-backward "\n\n" nil t)
990 (progn
991 (setq prev-end (point))
992 (forward-char 2))
993 (goto-char (setq prev-end (point-min))))
869bff31 994 (or (tex-validate-region (point) end)
710a0f53
KH
995 (let* ((oend end)
996 (end (save-excursion (forward-line 1) (point)))
bbd93e41
RS
997 start tem)
998 (beginning-of-line)
999 (setq start (point))
1000 ;; Keep track of line number as we scan,
1001 ;; in a cumulative fashion.
1002 (if linenum
1003 (setq linenum (- linenum (count-lines prevpos (point))))
1004 (setq linenum (1+ (count-lines 1 start))))
1005 (setq prevpos (point))
bed1b0c8 1006 ;; Mention this mismatch in *Occur*.
bbd93e41 1007 ;; Since we scan from end of buffer to beginning,
e6b0b773 1008 ;; add each mismatch at the beginning of *Occur*.
bbd93e41
RS
1009 (save-excursion
1010 (setq tem (point-marker))
1011 (set-buffer standard-output)
1012 (goto-char (point-min))
1013 ;; Skip "Mismatches:" header line.
1014 (forward-line 1)
e6b0b773 1015 (setq num-matches (1+ num-matches))
bbd93e41 1016 (insert-buffer-substring buffer start end)
e6b0b773
MR
1017 (let (text-beg (text-end (point-marker)))
1018 (forward-char (- start end))
1019 (setq text-beg (point-marker))
1020 (insert (format "%3d: " linenum))
a865de85
EZ
1021 (add-text-properties
1022 text-beg (- text-end 1)
1023 '(mouse-face highlight
1024 help-echo "mouse-2: go to this invalidity"))
1598a961 1025 (put-text-property text-beg (- text-end 1)
52ab062c 1026 'occur-target tem)))))
710a0f53 1027 (goto-char prev-end))))
bdbd9606 1028 (with-current-buffer standard-output
e6b0b773 1029 (if (eq num-matches 0)
bbd93e41
RS
1030 (insert "None!\n"))
1031 (if (interactive-p)
e6b0b773 1032 (message "%d mismatches found" num-matches))))))
869bff31 1033
1034(defun tex-validate-region (start end)
1035 "Check for mismatched braces or $'s in region.
1036Returns t if no mismatches. Returns nil and moves point to suspect
1037area if a mismatch is found."
1038 (interactive "r")
1039 (let ((failure-point nil) (max-possible-sexps (- end start)))
1040 (save-excursion
1041 (condition-case ()
1042 (save-restriction
1043 (narrow-to-region start end)
2ed2806c 1044 ;; First check that the open and close parens balance in numbers.
869bff31 1045 (goto-char start)
e6b0b773 1046 (while (<= 0 (setq max-possible-sexps (1- max-possible-sexps)))
2ed2806c
KH
1047 (forward-sexp 1))
1048 ;; Now check that like matches like.
1049 (goto-char start)
1050 (while (progn (skip-syntax-forward "^(")
1051 (not (eobp)))
1052 (let ((match (matching-paren (following-char))))
1053 (save-excursion
1054 (forward-sexp 1)
1055 (or (= (preceding-char) match)
1056 (error "Mismatched parentheses"))))
1057 (forward-char 1)))
869bff31 1058 (error
bed1b0c8
RS
1059 (skip-syntax-forward " .>")
1060 (setq failure-point (point)))))
bdbd9606
SM
1061 (if failure-point (goto-char failure-point))
1062 (not failure-point)))
869bff31 1063
1064(defun tex-terminate-paragraph (inhibit-validation)
1065 "Insert two newlines, breaking a paragraph for TeX.
81c735c0 1066Check for mismatched braces or $s in paragraph being terminated.
869bff31 1067A prefix arg inhibits the checking."
528415e7 1068 (interactive "*P")
869bff31 1069 (or inhibit-validation
1070 (save-excursion
1071 (tex-validate-region
bed1b0c8
RS
1072 (save-excursion
1073 (search-backward "\n\n" nil 'move)
1074 (point))
1075 (point)))
869bff31 1076 (message "Paragraph being closed appears to contain a mismatch"))
1077 (insert "\n\n"))
1078
1079(defun tex-insert-braces ()
1080 "Make a pair of braces and be poised to type inside of them."
528415e7 1081 (interactive "*")
869bff31 1082 (insert ?\{)
1083 (save-excursion
1084 (insert ?})))
1085
9bd4f69c
RS
1086;; This function is used as the value of fill-nobreak-predicate
1087;; in LaTeX mode. Its job is to prevent line-breaking inside
1088;; of a \verb construct.
1089(defun latex-fill-nobreak-predicate ()
1090 (let ((opoint (point))
1091 inside)
bed1b0c8 1092 (save-excursion
9bd4f69c
RS
1093 (save-restriction
1094 (beginning-of-line)
1095 (narrow-to-region (point) opoint)
1096 (while (re-search-forward "\\\\verb\\(.\\)" nil t)
1097 (unless (re-search-forward (regexp-quote (match-string 1)) nil t)
1098 (setq inside t)))))
1099 inside))
1100
53c4fe47
SM
1101(defvar latex-block-default "enumerate")
1102
15ca8de7 1103;; Like tex-insert-braces, but for LaTeX.
cf149bdf
RS
1104(define-skeleton tex-latex-block
1105 "Create a matching pair of lines \\begin[OPT]{NAME} and \\end{NAME} at point.
869bff31 1106Puts point on a blank line between them."
53c4fe47
SM
1107 (let ((choice (completing-read (format "LaTeX block name [%s]: "
1108 latex-block-default)
1109 (mapcar 'list
1110 (append standard-latex-block-names
1111 latex-block-names))
1112 nil nil nil nil latex-block-default)))
1113 (setq latex-block-default choice)
1114 (unless (or (member choice standard-latex-block-names)
1115 (member choice latex-block-names))
1116 ;; Remember new block names for later completion.
1117 (push choice latex-block-names))
1118 choice)
15ca8de7 1119 \n "\\begin{" str ?\}
53c4fe47 1120 ?\[ (skeleton-read "[options]: ") & ?\] | -1
dd459839 1121 > \n _ \n
15ca8de7 1122 "\\end{" str ?\} > \n)
53c4fe47 1123
ea590e1c
SM
1124(define-skeleton latex-insert-item
1125 "Insert a \item macro."
1126 nil
15ca8de7 1127 \n "\\item " >)
ea590e1c 1128
53c4fe47
SM
1129\f
1130;;;;
1131;;;; LaTeX syntax navigation
1132;;;;
869bff31 1133
1134(defun tex-last-unended-begin ()
81c735c0 1135 "Leave point at the beginning of the last `\\begin{...}' that is unended."
53c4fe47
SM
1136 (while (and (re-search-backward "\\\\\\(begin\\|end\\)\\s *{")
1137 (looking-at "\\\\end"))
869bff31 1138 (tex-last-unended-begin)))
1139
53c4fe47
SM
1140(defun tex-next-unmatched-end ()
1141 "Leave point at the end of the next `\\end' that is unended."
1142 (while (and (re-search-forward "\\\\\\(begin\\|end\\)\\s *{[^}]+}")
ea590e1c
SM
1143 (save-excursion (goto-char (match-beginning 0))
1144 (looking-at "\\\\begin")))
53c4fe47
SM
1145 (tex-next-unmatched-end)))
1146
6a900cf1
ER
1147(defun tex-goto-last-unclosed-latex-block ()
1148 "Move point to the last unclosed \\begin{...}.
1149Mark is left at original location."
1150 (interactive)
1151 (let ((spot))
1152 (save-excursion
1153 (condition-case nil
1154 (tex-last-unended-begin)
1155 (error (error "Couldn't find unended \\begin")))
1156 (setq spot (point)))
1157 (push-mark)
1158 (goto-char spot)))
1159
53c4fe47
SM
1160(defun latex-backward-sexp-1 ()
1161 "Like (backward-sexp 1) but aware of multi-char elements."
1162 (let ((pos (point))
1163 (forward-sexp-function))
1164 (backward-sexp 1)
1165 (if (looking-at "\\\\begin\\>")
1166 (signal 'scan-error
1167 (list "Containing expression ends prematurely"
1168 (point) (prog1 (point) (goto-char pos))))
1169 (when (eq (char-after) ?{)
1170 (let ((newpos (point)))
1171 (when (ignore-errors (backward-sexp 1) t)
1172 (if (looking-at "\\\\end\\>")
1173 (tex-last-unended-begin)
1174 (goto-char newpos))))))))
1175
1176(defun latex-forward-sexp-1 ()
1177 "Like (forward-sexp 1) but aware of multi-char elements."
1178 (let ((pos (point))
1179 (forward-sexp-function))
1180 (forward-sexp 1)
1181 (let ((newpos (point)))
1182 (skip-syntax-backward "/w")
1183 (cond
1184 ((looking-at "\\\\end\\>")
1185 (signal 'scan-error
1186 (list "Containing expression ends prematurely"
1187 (point)
1188 (prog1
1189 (progn (ignore-errors (forward-sexp 2)) (point))
1190 (goto-char pos)))))
1191 ((looking-at "\\\\begin\\>")
1192 (goto-char (match-end 0))
1193 (tex-next-unmatched-end))
1194 (t (goto-char newpos))))))
1195
1196(defun latex-forward-sexp (&optional arg)
1197 "Like `forward-sexp' but aware of multi-char elements."
1198 (interactive "P")
1199 (unless arg (setq arg 1))
1200 (let ((pos (point)))
1201 (condition-case err
1202 (while (/= arg 0)
1203 (setq arg
1204 (if (> arg 0)
1205 (progn (latex-forward-sexp-1) (1- arg))
1206 (progn (latex-backward-sexp-1) (1+ arg)))))
1207 (scan-error
1208 (goto-char pos)
1209 (signal (car err) (cdr err))))))
1210
ea590e1c
SM
1211(defun latex-syntax-after ()
1212 "Like (char-syntax (char-after)) but aware of multi-char elements."
15ca8de7 1213 (if (looking-at "\\\\end\\>") ?\) (char-syntax (following-char))))
ea590e1c
SM
1214
1215(defun latex-skip-close-parens ()
1216 "Like (skip-syntax-forward \" )\") but aware of multi-char elements."
1217 (let ((forward-sexp-function nil))
1218 (while (progn (skip-syntax-forward " )")
1219 (looking-at "\\\\end\\>"))
1220 (forward-sexp 2))))
1221
1222(defun latex-down-list ()
1223 "Like (down-list 1) but aware of multi-char elements."
1224 (forward-comment (point-max))
1225 (let ((forward-sexp-function nil))
1226 (if (not (looking-at "\\\\begin\\>"))
1227 (down-list 1)
1228 (forward-sexp 1)
1229 ;; Skip arguments.
1230 (while (looking-at "[ \t]*\\s(") (forward-sexp)))))
1231
869bff31 1232(defun tex-close-latex-block ()
1233 "Creates an \\end{...} to match the last unclosed \\begin{...}."
1234 (interactive "*")
1235 (let ((new-line-needed (bolp))
1236 text indentation)
1237 (save-excursion
528415e7 1238 (condition-case nil
869bff31 1239 (tex-last-unended-begin)
1240 (error (error "Couldn't find unended \\begin")))
1241 (setq indentation (current-column))
1242 (re-search-forward "\\\\begin\\(\\s *{[^}\n]*}\\)")
1243 (setq text (buffer-substring (match-beginning 1) (match-end 1))))
1244 (indent-to indentation)
1245 (insert "\\end" text)
1246 (if new-line-needed (insert ?\n))))
15ca8de7
SM
1247
1248(defconst tex-discount-args-cmds
1249 '("begin" "end" "input" "special" "cite" "ref" "include" "includeonly"
1250 "documentclass" "usepackage" "label")
1251 "TeX commands whose arguments should not be counted as text.")
1252
1253(defun tex-count-words (begin end)
1254 "Count the number of words in the buffer."
1255 (interactive
1256 (if (and transient-mark-mode mark-active)
1257 (list (region-beginning) (region-end))
1258 (list (point-min) (point-max))))
1259 ;; TODO: skip comments and math and maybe some environments.
1260 (save-excursion
1261 (goto-char begin)
1262 (let ((count 0))
1263 (while (and (< (point) end) (re-search-forward "\\<" end t))
1264 (if (not (eq (char-syntax (preceding-char)) ?/))
1265 (progn
1266 ;; Don't count single-char words.
1267 (unless (looking-at ".\\>") (incf count))
1268 (forward-char 1))
1269 (let ((cmd
1270 (buffer-substring-no-properties
1271 (point) (progn (when (zerop (skip-chars-forward "a-zA-Z@"))
1272 (forward-char 1))
1273 (point)))))
1274 (when (member cmd tex-discount-args-cmds)
1275 (skip-chars-forward "*")
1276 (forward-comment (point-max))
1277 (when (looking-at "\\[")
1278 (forward-sexp 1)
1279 (forward-comment (point-max)))
1280 (if (not (looking-at "{"))
1281 (forward-char 1)
1282 (forward-sexp 1))))))
1283 (message "%s words" count))))
b781e739
SS
1284
1285
869bff31 1286\f
1287;;; Invoking TeX in an inferior shell.
1288
15ca8de7
SM
1289;; Why use a shell instead of running TeX directly? Because if TeX
1290;; gets stuck, the user can switch to the shell window and type at it.
869bff31 1291
15ca8de7 1292;; The utility functions:
869bff31 1293
bdbd9606
SM
1294(define-derived-mode tex-shell shell-mode "TeX-Shell"
1295 (compilation-shell-minor-mode t))
1296
d974af30 1297;;;###autoload
869bff31 1298(defun tex-start-shell ()
d6709b80
SM
1299 (with-current-buffer
1300 (make-comint
1301 "tex-shell"
07c16ec4 1302 (or tex-shell-file-name (getenv "ESHELL") shell-file-name)
d6709b80 1303 nil)
528415e7
RS
1304 (let ((proc (get-process "tex-shell")))
1305 (set-process-sentinel proc 'tex-shell-sentinel)
1306 (process-kill-without-query proc)
bdbd9606 1307 (tex-shell)
528415e7 1308 (while (zerop (buffer-size))
51b2c841
RS
1309 (sleep-for 1)))))
1310
033306e3
RS
1311(defun tex-feed-input ()
1312 "Send input to the tex shell process.
1313In the tex buffer this can be used to continue an interactive tex run.
bed1b0c8 1314In the tex shell buffer this command behaves like `comint-send-input'."
033306e3 1315 (interactive)
b781e739 1316 (set-buffer (tex-shell-buf))
033306e3
RS
1317 (comint-send-input)
1318 (tex-recenter-output-buffer nil))
1319
51b2c841
RS
1320(defun tex-display-shell ()
1321 "Make the TeX shell buffer visible in a window."
b781e739 1322 (display-buffer (tex-shell-buf))
51b2c841 1323 (tex-recenter-output-buffer nil))
528415e7
RS
1324
1325(defun tex-shell-sentinel (proc msg)
1326 (cond ((null (buffer-name (process-buffer proc)))
1327 ;; buffer killed
1328 (set-process-buffer proc nil)
1329 (tex-delete-last-temp-files))
1330 ((memq (process-status proc) '(signal exit))
1331 (tex-delete-last-temp-files))))
1332
1333(defun tex-set-buffer-directory (buffer directory)
869bff31 1334 "Set BUFFER's default directory to be DIRECTORY."
1335 (setq directory (file-name-as-directory (expand-file-name directory)))
1336 (if (not (file-directory-p directory))
1337 (error "%s is not a directory" directory)
1338 (save-excursion
1339 (set-buffer buffer)
1340 (setq default-directory directory))))
1341
30803a05
RS
1342(defvar tex-send-command-modified-tick 0)
1343(make-variable-buffer-local 'tex-send-command-modified-tick)
1344
bdbd9606 1345(defun tex-shell-proc ()
b781e739 1346 (or (tex-shell-running) (error "No TeX subprocess")))
bdbd9606
SM
1347(defun tex-shell-buf ()
1348 (process-buffer (tex-shell-proc)))
b781e739
SS
1349(defun tex-shell-buf-no-error ()
1350 (let ((proc (tex-shell-running)))
1351 (and proc (process-buffer proc))))
bdbd9606 1352
528415e7 1353(defun tex-send-command (command &optional file background)
4cdc1d4b 1354 "Send COMMAND to TeX shell process, substituting optional FILE for *.
8241d7b9
ER
1355Do this in background if optional BACKGROUND is t. If COMMAND has no *,
1356FILE will be appended, preceded by a blank, to COMMAND. If FILE is nil, no
1357substitution will be made in COMMAND. COMMAND can be any expression that
460e1b7d
RS
1358evaluates to a command string.
1359
1360Return the process in which TeX is running."
528415e7
RS
1361 (save-excursion
1362 (let* ((cmd (eval command))
bdbd9606 1363 (proc (tex-shell-proc))
64db2461 1364 (buf (process-buffer proc))
4f45adda 1365 (star (string-match "\\*" cmd))
4cdc1d4b
RS
1366 (string
1367 (concat
1368 (if file
1369 (if star (concat (substring cmd 0 star)
1370 file (substring cmd (1+ star)))
1371 (concat cmd " " file))
1372 cmd)
1373 (if background "&" ""))))
64db2461
RS
1374 ;; Switch to buffer before checking for subproc output in it.
1375 (set-buffer buf)
30803a05
RS
1376 ;; If text is unchanged since previous tex-send-command,
1377 ;; we haven't got any output. So wait for output now.
64db2461 1378 (if (= (buffer-modified-tick buf) tex-send-command-modified-tick)
30803a05 1379 (accept-process-output proc))
4cdc1d4b
RS
1380 (goto-char (process-mark proc))
1381 (insert string)
30803a05 1382 (comint-send-input)
460e1b7d
RS
1383 (setq tex-send-command-modified-tick (buffer-modified-tick buf))
1384 proc)))
528415e7 1385
a15849cb
RS
1386(defun tex-delete-last-temp-files (&optional not-all)
1387 "Delete any junk files from last temp file.
1388If NOT-ALL is non-nil, save the `.dvi' file."
528415e7
RS
1389 (if tex-last-temp-file
1390 (let* ((dir (file-name-directory tex-last-temp-file))
adf6b7f9
KH
1391 (list (and (file-directory-p dir)
1392 (file-name-all-completions
02fd229c
RS
1393 (file-name-sans-extension
1394 (file-name-nondirectory tex-last-temp-file))
1395 dir))))
adf6b7f9 1396 (while list
a15849cb
RS
1397 (if not-all
1398 (and
1399 ;; If arg is non-nil, don't delete the .dvi file.
1400 (not (string-match "\\.dvi$" (car list)))
1401 (delete-file (concat dir (car list))))
1402 (delete-file (concat dir (car list))))
528415e7
RS
1403 (setq list (cdr list))))))
1404
99621a14 1405(add-hook 'kill-emacs-hook 'tex-delete-last-temp-files)
869bff31 1406
dd459839
SM
1407(defun tex-guess-main-file (&optional all)
1408 "Find a likely `tex-main-file'.
1409Looks for hints in other buffers in the same directory or in
1410ALL other buffers."
1411 (let ((dir default-directory)
1412 (header-re tex-start-of-header))
1413 (catch 'found
1414 ;; Look for a buffer with `tex-main-file' set.
1415 (dolist (buf (if (consp all) all (buffer-list)))
1416 (with-current-buffer buf
1417 (when (and (or all (equal dir default-directory))
1418 (stringp tex-main-file))
1419 (throw 'found (expand-file-name tex-main-file)))))
1420 ;; Look for a buffer containing the magic `tex-start-of-header'.
1421 (dolist (buf (if (consp all) all (buffer-list)))
1422 (with-current-buffer buf
1423 (when (and (or all (equal dir default-directory))
1424 buffer-file-name
1425 ;; (or (easy-mmode-derived-mode-p 'latex-mode)
1426 ;; (easy-mmode-derived-mode-p 'plain-tex-mode))
1427 (save-excursion
cb30255a
SM
1428 (save-restriction
1429 (widen)
1430 (goto-char (point-min))
1431 (re-search-forward header-re 10000 t))))
dd459839
SM
1432 (throw 'found (expand-file-name buffer-file-name))))))))
1433
07c16ec4
SM
1434(defun tex-main-file ()
1435 "Return the relative name of the main file."
bdbd9606
SM
1436 (let* ((file (or tex-main-file
1437 ;; Compatibility with AUCTeX.
1438 (and (boundp 'TeX-master) (stringp TeX-master)
1439 (set (make-local-variable 'tex-main-file) TeX-master))
1440 ;; Try to guess the main file.
1441 (if (not buffer-file-name)
1442 (error "Buffer is not associated with any file")
1443 (file-relative-name
1444 (if (save-excursion
1445 (goto-char (point-min))
1446 (re-search-forward tex-start-of-header 10000 t))
1447 ;; This is the main file.
1448 buffer-file-name
1449 ;; This isn't the main file, let's try to find better,
1450 (or (tex-guess-main-file)
1451 ;; (tex-guess-main-file t)
07c16ec4
SM
1452 buffer-file-name)))))))
1453 (if (file-exists-p file) file (concat file ".tex"))))
dd459839 1454
d6709b80
SM
1455
1456(defun tex-start-tex (command file &optional dir)
460e1b7d 1457 "Start a TeX run, using COMMAND on FILE."
6633b891 1458 (let* ((star (string-match "\\*" command))
460e1b7d 1459 (compile-command
6633b891
KH
1460 (if star
1461 (concat (substring command 0 star)
1462 (comint-quote-filename file)
1463 (substring command (1+ star)))
1464 (concat command " "
9e0ad27a 1465 (if (< 0 (length tex-start-commands))
c3ce7bf4 1466 (concat
9e0ad27a
RS
1467 (shell-quote-argument tex-start-commands) " "))
1468 tex-start-options
6633b891 1469 (comint-quote-filename file)))))
bdbd9606
SM
1470 (tex-send-tex-command compile-command dir)))
1471
1472(defun tex-send-tex-command (cmd &optional dir)
b781e739
SS
1473 (unless (or (equal dir (let ((buf (tex-shell-buf-no-error)))
1474 (and buf (with-current-buffer buf
1475 default-directory))))
bdbd9606
SM
1476 (not dir))
1477 (let (shell-dirtrack-verbose)
1478 (tex-send-command tex-shell-cd-command dir)))
1479 (with-current-buffer (process-buffer (tex-send-command cmd))
bdbd9606
SM
1480 (make-local-variable 'compilation-parse-errors-function)
1481 (setq compilation-parse-errors-function 'tex-compilation-parse-errors)
1482 (setq compilation-last-buffer (current-buffer))
1483 (compilation-forget-errors)
1598a961 1484 ;; Don't parse previous compilations.
bdbd9606
SM
1485 (set-marker compilation-parsing-end (1- (point-max))))
1486 (tex-display-shell)
1487 (setq tex-last-buffer-texed (current-buffer)))
460e1b7d 1488\f
1598a961
SM
1489(defvar tex-error-parse-syntax-table
1490 (let ((st (make-syntax-table)))
1491 (modify-syntax-entry ?\( "()" st)
1492 (modify-syntax-entry ?\) ")(" st)
1493 (modify-syntax-entry ?\\ "\\" st)
1494 (modify-syntax-entry ?\{ "_" st)
1495 (modify-syntax-entry ?\} "_" st)
1496 (modify-syntax-entry ?\[ "_" st)
1497 (modify-syntax-entry ?\] "_" st)
1498 ;; Single quotations may appear in errors
1499 (modify-syntax-entry ?\" "_" st)
1500 st)
1501 "Syntax-table used while parsing TeX error messages.")
1502
460e1b7d 1503(defun tex-compilation-parse-errors (limit-search find-at-least)
f05bd645
RS
1504 "Parse the current buffer as TeX error messages.
1505See the variable `compilation-parse-errors-function' for the interface it uses.
1506
1507This function parses only the last TeX compilation.
1508It works on TeX compilations only. It is necessary for that purpose,
1509since TeX does not put file names and line numbers on the same line as
1510for the error messages."
460e1b7d
RS
1511 (require 'thingatpt)
1512 (setq compilation-error-list nil)
1513 (message "Parsing error messages...")
f05bd645
RS
1514 (let ((default-directory ; Perhaps dir has changed meanwhile.
1515 (file-name-directory (buffer-file-name tex-last-buffer-texed)))
f05bd645
RS
1516 found-desired (num-errors-found 0)
1517 last-filename last-linenum last-position
1518 begin-of-error end-of-error)
f05bd645
RS
1519 ;; Don't reparse messages already seen at last parse.
1520 (goto-char compilation-parsing-end)
1521 ;; Parse messages.
1522 (while (and (not (or found-desired (eobp)))
1523 (prog1 (re-search-forward "^! " nil 'move)
1524 (setq begin-of-error (match-beginning 0)
1525 end-of-error (match-end 0)))
1526 (re-search-forward
1527 "^l\\.\\([0-9]+\\) \\(\\.\\.\\.\\)?\\(.*\\)$" nil 'move))
1528 (let* ((this-error (set-marker (make-marker) begin-of-error))
1529 (linenum (string-to-int (match-string 1)))
1530 (error-text (regexp-quote (match-string 3)))
1531 (filename
1532 (save-excursion
ea590e1c
SM
1533 (with-syntax-table tex-error-parse-syntax-table
1534 (backward-up-list 1)
1535 (skip-syntax-forward "(_")
1536 (while (not (file-readable-p (thing-at-point 'filename)))
1537 (skip-syntax-backward "(_")
1538 (backward-up-list 1)
1539 (skip-syntax-forward "(_"))
1540 (thing-at-point 'filename))))
f05bd645
RS
1541 (new-file
1542 (or (null last-filename)
1543 (not (string-equal last-filename filename))))
1544 (error-location
1545 (save-excursion
1546 (if (equal filename (concat tex-zap-file ".tex"))
1547 (set-buffer tex-last-buffer-texed)
1548 (set-buffer (find-file-noselect filename)))
1549 (if new-file
1598a961 1550 (progn (goto-line linenum) (setq last-position nil))
f05bd645
RS
1551 (goto-char last-position)
1552 (forward-line (- linenum last-linenum)))
1553 ;; first try a forward search for the error text,
1554 ;; then a backward search limited by the last error.
1555 (let ((starting-point (point)))
1556 (or (re-search-forward error-text nil t)
1598a961 1557 (re-search-backward error-text last-position t)
f05bd645
RS
1558 (goto-char starting-point)))
1559 (point-marker))))
1560 (goto-char this-error)
1561 (if (and compilation-error-list
1562 (or (and find-at-least
1563 (>= num-errors-found
1564 find-at-least))
1565 (and limit-search
1566 (>= end-of-error limit-search)))
1567 new-file)
1568 (setq found-desired t)
1569 (setq num-errors-found (1+ num-errors-found)
1570 last-filename filename
1571 last-linenum linenum
1572 last-position error-location
1573 compilation-error-list ; Add the new error
1574 (cons (cons this-error error-location)
1575 compilation-error-list))
1576 (goto-char end-of-error)))))
ee13a145 1577 (set-marker compilation-parsing-end (point))
f05bd645 1578 (setq compilation-error-list (nreverse compilation-error-list))
460e1b7d
RS
1579 (message "Parsing error messages...done"))
1580\f
528415e7 1581;;; The commands:
869bff31 1582
1583(defun tex-region (beg end)
1584 "Run TeX on the current region, via a temporary file.
1585The file's name comes from the variable `tex-zap-file' and the
1586variable `tex-directory' says where to put it.
1587
1588If the buffer has a header, the header is given to TeX before the
1589region itself. The buffer's header is all lines between the strings
1590defined by `tex-start-of-header' and `tex-end-of-header' inclusive.
1591The header must start in the first 100 lines of the buffer.
1592
1593The value of `tex-trailer' is given to TeX as input after the region.
1594
1595The value of `tex-command' specifies the command to use to run TeX."
1596 (interactive "r")
1597 (if (tex-shell-running)
1598 (tex-kill-job)
1599 (tex-start-shell))
1600 (or tex-zap-file
1601 (setq tex-zap-file (tex-generate-zap-file-name)))
6d34c59f
RS
1602 ;; Temp file will be written and TeX will be run in zap-directory.
1603 ;; If the TEXINPUTS file has relative directories or if the region has
1604 ;; \input of files, this must be the same directory as the file for
1605 ;; TeX to access the correct inputs. That's why it's safest if
1606 ;; tex-directory is ".".
1607 (let* ((zap-directory
528415e7 1608 (file-name-as-directory (expand-file-name tex-directory)))
d6709b80
SM
1609 (tex-out-file (expand-file-name (concat tex-zap-file ".tex")
1610 zap-directory)))
0d548e5d
RS
1611 ;; Don't delete temp files if we do the same buffer twice in a row.
1612 (or (eq (current-buffer) tex-last-buffer-texed)
1613 (tex-delete-last-temp-files t))
869bff31 1614 ;; Write the new temp file.
1615 (save-excursion
1616 (save-restriction
1617 (widen)
1618 (goto-char (point-min))
1619 (forward-line 100)
1620 (let ((search-end (point))
6d34c59f
RS
1621 (default-directory zap-directory)
1622 (already-output 0))
869bff31 1623 (goto-char (point-min))
6d34c59f 1624
725b7428
RS
1625 ;; Maybe copy first line, such as `\input texinfo', to temp file.
1626 (and tex-first-line-header-regexp
1627 (looking-at tex-first-line-header-regexp)
bed1b0c8 1628 (write-region (point)
6d34c59f
RS
1629 (progn (forward-line 1)
1630 (setq already-output (point)))
725b7428
RS
1631 tex-out-file nil nil))
1632
6d34c59f
RS
1633 ;; Write out the header, if there is one,
1634 ;; and any of the specified region which extends before it.
1635 ;; But don't repeat anything already written.
898b9ac1 1636 (if (re-search-forward tex-start-of-header search-end t)
6d34c59f 1637 (let (hbeg)
869bff31 1638 (beginning-of-line)
1639 (setq hbeg (point)) ;mark beginning of header
898b9ac1 1640 (if (re-search-forward tex-end-of-header nil t)
6d34c59f
RS
1641 (let (hend)
1642 (forward-line 1)
bed1b0c8 1643 (setq hend (point)) ;mark end of header
6d34c59f
RS
1644 (write-region (max (min hbeg beg) already-output)
1645 hend
1646 tex-out-file
1647 (not (zerop already-output)) nil)
1648 (setq already-output hend)))))
1649
1650 ;; Write out the specified region
1651 ;; (but don't repeat anything already written).
1652 (write-region (max beg already-output) end
1653 tex-out-file
1654 (not (zerop already-output)) nil))
1655 ;; Write the trailer, if any.
1656 ;; Precede it with a newline to make sure it
1657 ;; is not hidden in a comment.
1658 (if tex-trailer
1659 (write-region (concat "\n" tex-trailer) nil
1660 tex-out-file t nil))))
528415e7
RS
1661 ;; Record the file name to be deleted afterward.
1662 (setq tex-last-temp-file tex-out-file)
f05bd645
RS
1663 ;; Use a relative file name here because (1) the proper dir
1664 ;; is already current, and (2) the abs file name is sometimes
1665 ;; too long and can make tex crash.
d6709b80
SM
1666 (tex-start-tex tex-command (concat tex-zap-file ".tex") zap-directory)
1667 (setq tex-print-file tex-out-file)))
869bff31 1668
1669(defun tex-buffer ()
1670 "Run TeX on current buffer. See \\[tex-region] for more information.
528415e7
RS
1671Does not save the buffer, so it's useful for trying experimental versions.
1672See \\[tex-file] for an alternative."
869bff31 1673 (interactive)
1674 (tex-region (point-min) (point-max)))
1675
1676(defun tex-file ()
1677 "Prompt to save all buffers and run TeX (or LaTeX) on current buffer's file.
1678This function is more useful than \\[tex-buffer] when you need the
1679`.aux' file of LaTeX to have the correct name."
1680 (interactive)
7abc9add
SS
1681 (when tex-offer-save
1682 (save-some-buffers))
d6709b80 1683 (let* ((source-file (tex-main-file))
07c16ec4 1684 (file-dir (file-name-directory (expand-file-name source-file))))
869bff31 1685 (if (tex-shell-running)
1686 (tex-kill-job)
1687 (tex-start-shell))
d6709b80 1688 (tex-start-tex tex-command source-file file-dir)
f05bd645 1689 (setq tex-print-file (expand-file-name source-file))))
869bff31 1690
1691(defun tex-generate-zap-file-name ()
1692 "Generate a unique name suitable for use as a file name."
1693 ;; Include the shell process number and host name
1694 ;; in case there are multiple shells (for same or different user).
f5cdb851
KH
1695 ;; Dec 1998: There is a report that some versions of xdvi
1696 ;; don't work with file names that start with #.
5616ee46 1697 (format "_TZ_%d-%s"
869bff31 1698 (process-id (get-buffer-process "*tex-shell*"))
07c16ec4 1699 (subst-char-in-string ?. ?- (system-name))))
869bff31 1700
1701;; This will perhaps be useful for modifying TEXINPUTS.
1702;; Expand each file name, separated by colons, in the string S.
1703(defun tex-expand-files (s)
1704 (let (elts (start 0))
1705 (while (string-match ":" s start)
1706 (setq elts (cons (substring s start (match-beginning 0)) elts))
1707 (setq start (match-end 0)))
1708 (or (= start 0)
1709 (setq elts (cons (substring s start) elts)))
c0df1972
SM
1710 (mapconcat (lambda (elt)
1711 (if (= (length elt) 0) elt (expand-file-name elt)))
5616ee46 1712 (nreverse elts) ":")))
869bff31 1713
1714(defun tex-shell-running ()
713f7b15 1715 (let ((proc (get-process "tex-shell")))
b781e739
SS
1716 (when proc
1717 (if (and (eq (process-status proc) 'run)
1718 (buffer-live-p (process-buffer proc)))
1719 ;; return the TeX process on success
1720 proc
1721 ;; get rid of the process permanently
1722 ;; this should get rid of the annoying w32 problem with
1723 ;; dead tex-shell buffer and live process
1724 (delete-process proc)))))
869bff31 1725
1726(defun tex-kill-job ()
1727 "Kill the currently running TeX job."
1728 (interactive)
b781e739 1729 ;; `quit-process' leads to core dumps of the tex process (except if
bed1b0c8
RS
1730 ;; coredumpsize has limit 0kb as on many environments). One would
1731 ;; like to use (kill-process proc 'lambda), however that construct
1732 ;; does not work on some systems and kills the shell itself.
b781e739
SS
1733 (let ((proc (get-process "tex-shell")))
1734 (when proc (quit-process proc t))))
869bff31 1735
1736(defun tex-recenter-output-buffer (linenum)
1737 "Redisplay buffer of TeX job output so that most recent output can be seen.
1738The last line of the buffer is displayed on
1739line LINE of the window, or centered if LINE is nil."
1740 (interactive "P")
1741 (let ((tex-shell (get-buffer "*tex-shell*"))
23b64225
RS
1742 (old-buffer (current-buffer))
1743 (window))
869bff31 1744 (if (null tex-shell)
1745 (message "No TeX output buffer")
23b64225
RS
1746 (setq window (display-buffer tex-shell))
1747 (save-selected-window
1748 (select-window window)
1749 (bury-buffer tex-shell)
1750 (goto-char (point-max))
1751 (recenter (if linenum
1752 (prefix-numeric-value linenum)
1753 (/ (window-height) 2)))))))
869bff31 1754
528415e7 1755(defun tex-print (&optional alt)
869bff31 1756 "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file].
1433a222
CZ
1757Runs the shell command defined by `tex-dvi-print-command'. If prefix argument
1758is provided, use the alternative command, `tex-alt-dvi-print-command'."
528415e7 1759 (interactive "P")
869bff31 1760 (let ((print-file-name-dvi (tex-append tex-print-file ".dvi"))
1761 test-name)
1762 (if (and (not (equal (current-buffer) tex-last-buffer-texed))
45c3304d
RS
1763 (buffer-file-name)
1764 ;; Check that this buffer's printed file is up to date.
869bff31 1765 (file-newer-than-file-p
1766 (setq test-name (tex-append (buffer-file-name) ".dvi"))
45c3304d 1767 (buffer-file-name)))
869bff31 1768 (setq print-file-name-dvi test-name))
528415e7
RS
1769 (if (not (file-exists-p print-file-name-dvi))
1770 (error "No appropriate `.dvi' file could be found")
460e1b7d
RS
1771 (if (tex-shell-running)
1772 (tex-kill-job)
1773 (tex-start-shell))
528415e7 1774 (tex-send-command
bed1b0c8
RS
1775 (if alt tex-alt-dvi-print-command tex-dvi-print-command)
1776 print-file-name-dvi t))))
869bff31 1777
cf6d6e8a
RS
1778(defun tex-alt-print ()
1779 "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file].
002b0d00 1780Runs the shell command defined by `tex-alt-dvi-print-command'."
cf6d6e8a
RS
1781 (interactive)
1782 (tex-print t))
1783
869bff31 1784(defun tex-view ()
1785 "Preview the last `.dvi' file made by running TeX under Emacs.
1786This means, made using \\[tex-region], \\[tex-buffer] or \\[tex-file].
2b7971c9
RS
1787The variable `tex-dvi-view-command' specifies the shell command for preview.
1788You must set that variable yourself before using this command,
1789because there is no standard value that would generally work."
869bff31 1790 (interactive)
2b7971c9
RS
1791 (or tex-dvi-view-command
1792 (error "You must set `tex-dvi-view-command'"))
869bff31 1793 (let ((tex-dvi-print-command tex-dvi-view-command))
1794 (tex-print)))
1795
1796(defun tex-append (file-name suffix)
1797 "Append to FILENAME the suffix SUFFIX, using same algorithm TeX uses.
cf6d6e8a 1798Pascal-based TeX scans for the first period, C TeX uses the last.
869bff31 1799No period is retained immediately before SUFFIX,
1800so normally SUFFIX starts with one."
1801 (if (stringp file-name)
cf6d6e8a
RS
1802 (let ((file (file-name-nondirectory file-name))
1803 trial-name)
6da9bbd6 1804 ;; Try splitting on last period.
7d0ca249
RS
1805 ;; The first-period split can get fooled when two files
1806 ;; named a.tex and a.b.tex are both tex'd;
1807 ;; the last-period split must be right if it matches at all.
cf6d6e8a
RS
1808 (setq trial-name
1809 (concat (file-name-directory file-name)
1810 (substring file 0
7d0ca249 1811 (string-match "\\.[^.]*$" file))
cf6d6e8a
RS
1812 suffix))
1813 (if (or (file-exists-p trial-name)
1814 (file-exists-p (concat trial-name ".aux"))) ;for BibTeX files
1815 trial-name
7d0ca249 1816 ;; Not found, so split on first period.
cf6d6e8a
RS
1817 (concat (file-name-directory file-name)
1818 (substring file 0
7d0ca249 1819 (string-match "\\." file))
cf6d6e8a 1820 suffix)))
869bff31 1821 " "))
1822
1823(defun tex-show-print-queue ()
1824 "Show the print queue that \\[tex-print] put your job on.
1433a222 1825Runs the shell command defined by `tex-show-queue-command'."
869bff31 1826 (interactive)
1827 (if (tex-shell-running)
1828 (tex-kill-job)
1829 (tex-start-shell))
51b2c841
RS
1830 (tex-send-command tex-show-queue-command)
1831 (tex-display-shell))
869bff31 1832
1833(defun tex-bibtex-file ()
1834 "Run BibTeX on the current buffer's file."
1835 (interactive)
1836 (if (tex-shell-running)
1837 (tex-kill-job)
1838 (tex-start-shell))
e6b0b773
MR
1839 (let (shell-dirtrack-verbose
1840 (tex-out-file
869bff31 1841 (tex-append (file-name-nondirectory (buffer-file-name)) ""))
1842 (file-dir (file-name-directory (buffer-file-name))))
528415e7 1843 (tex-send-command tex-shell-cd-command file-dir)
51b2c841
RS
1844 (tex-send-command tex-bibtex-command tex-out-file))
1845 (tex-display-shell))
ea590e1c
SM
1846\f
1847;;;;
1848;;;; LaTeX indentation
1849;;;;
1850
1851(defvar tex-indent-allhanging t)
1852(defvar tex-indent-arg 4)
1853(defvar tex-indent-basic 2)
1854(defvar tex-indent-item tex-indent-basic)
1855(defvar tex-indent-item-re "\\\\\\(bib\\)?item\\>")
1856
1857(easy-mmode-defsyntax tex-latex-indent-syntax-table
dd459839
SM
1858 '((?$ . ".")
1859 (?\( . ".")
1860 (?\) . "."))
ea590e1c
SM
1861 "Syntax table used while computing indentation."
1862 :copy tex-mode-syntax-table)
1863
1864(defun latex-indent (&optional arg)
1865 (with-syntax-table tex-latex-indent-syntax-table
1866 ;; TODO: Rather than ignore $, we should try to be more clever about it.
1867 (let ((indent
1868 (save-excursion
1869 (beginning-of-line)
1870 (latex-find-indent))))
1871 (if (< indent 0) (setq indent 0))
1872 (if (<= (current-column) (current-indentation))
1873 (indent-line-to indent)
1874 (save-excursion (indent-line-to indent))))))
1875
1876(defun latex-find-indent (&optional virtual)
1877 "Find the proper indentation of text after point.
1878VIRTUAL if non-nil indicates that we're only trying to find the indentation
1879 in order to determine the indentation of something else.
1880There might be text before point."
1881 (save-excursion
1882 (skip-chars-forward " \t")
1883 (or
1884 ;; Trust the current indentation, if such info is applicable.
1885 (and virtual (>= (current-indentation) (current-column))
1886 (current-indentation))
1887 ;; Put leading close-paren where the matching open brace would be.
1888 (and (eq (latex-syntax-after) ?\))
1889 (ignore-errors
1890 (save-excursion
1891 (latex-skip-close-parens)
1892 (latex-backward-sexp-1)
1893 (latex-find-indent 'virtual))))
1894 ;; Default (maybe an argument)
1895 (let ((pos (point))
1896 (char (char-after))
1897 ;; Outdent \item if necessary.
1898 (indent (if (looking-at tex-indent-item-re) (- tex-indent-item) 0))
1899 up-list-pos)
1900 ;; Find the previous point which determines our current indentation.
1901 (condition-case err
1902 (progn
1903 (latex-backward-sexp-1)
1904 (while (> (current-column) (current-indentation))
1905 (latex-backward-sexp-1)))
1906 (scan-error
1907 (setq up-list-pos (nth 2 err))))
8908cf40
SM
1908 (cond
1909 ((= (point-min) pos) 0) ; We're really just indenting the first line.
1910 ((integerp up-list-pos)
1911 ;; Have to indent relative to the open-paren.
1912 (goto-char up-list-pos)
1913 (if (and (not tex-indent-allhanging)
1914 (> pos (progn (latex-down-list)
1915 (forward-comment (point-max))
1916 (point))))
1917 ;; Align with the first element after the open-paren.
1918 (current-column)
1919 ;; We're the first element after a hanging brace.
1920 (goto-char up-list-pos)
1921 (+ indent tex-indent-basic (latex-find-indent 'virtual))))
1922 ;; We're now at the "beginning" of a line.
1923 ((not (and (not virtual) (eq (char-after) ?\\)))
1924 ;; Nothing particular here: just keep the same indentation.
1925 (+ indent (current-column)))
1926 ;; We're now looking at a macro call.
1927 ((looking-at tex-indent-item-re)
1928 ;; Indenting relative to an item, have to re-add the outdenting.
1929 (+ indent (current-column) tex-indent-item))
1930 (t
1931 (let ((col (current-column)))
1932 (if (not (eq (char-syntax char) ?\())
1933 ;; If the first char was not an open-paren, there's
1934 ;; a risk that this is really not an argument to the
1935 ;; macro at all.
1936 (+ indent col)
1937 (forward-sexp 1)
1938 (if (< (line-end-position)
1939 (save-excursion (forward-comment (point-max))
1940 (point)))
1941 ;; we're indenting the first argument.
1942 (min (current-column) (+ tex-indent-arg col))
1943 (skip-syntax-forward " ")
1944 (current-column))))))))))
528415e7
RS
1945
1946(run-hooks 'tex-mode-load-hook)
869bff31 1947
49116ac0
JB
1948(provide 'tex-mode)
1949
d501f516 1950;;; tex-mode.el ends here