* NEWS: Mention the new libxml2 functions.
[bpt/emacs.git] / lisp / textmodes / tex-mode.el
CommitLineData
95a045bd 1;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- coding: utf-8 -*-
d501f516 2
c6228f14 3;; Copyright (C) 1985, 1986, 1989, 1992, 1994, 1995, 1996, 1997, 1998
114f9c96 4;; 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
c6228f14 5;; Free Software Foundation, Inc.
eea8d4ef 6
70f20973 7;; Maintainer: FSF
d7b4d18f 8;; Keywords: tex
e5167999 9
528415e7 10;; Contributions over the years by William F. Schelter, Dick King,
70f20973 11;; Stephen Gildea, Michael Prange, Jacob Gore, and Edward M. Reingold.
528415e7 12
869bff31 13;; This file is part of GNU Emacs.
14
1fecc8fe 15;; GNU Emacs is free software: you can redistribute it and/or modify
869bff31 16;; it under the terms of the GNU General Public License as published by
1fecc8fe
GM
17;; the Free Software Foundation, either version 3 of the License, or
18;; (at your option) any later version.
869bff31 19
20;; GNU Emacs is distributed in the hope that it will be useful,
21;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23;; GNU General Public License for more details.
24
25;; You should have received a copy of the GNU General Public License
1fecc8fe 26;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
869bff31 27
55535639
PJ
28;;; Commentary:
29
e5167999
ER
30;;; Code:
31
bed1b0c8
RS
32;; Pacify the byte-compiler
33(eval-when-compile
34 (require 'compare-w)
ea590e1c 35 (require 'cl)
bed1b0c8
RS
36 (require 'skeleton))
37
2e261f76
JB
38(defvar font-lock-comment-face)
39(defvar font-lock-doc-face)
40
a0e9c22a 41(require 'shell)
2f3067de 42(require 'compile)
528415e7 43
d61140e8 44(defgroup tex-file nil
d1218e3e 45 "TeX files and directories."
d61140e8
RS
46 :prefix "tex-"
47 :group 'tex)
48
49(defgroup tex-run nil
d1218e3e 50 "Running external commands from TeX mode."
d61140e8
RS
51 :prefix "tex-"
52 :group 'tex)
53
54(defgroup tex-view nil
d1218e3e 55 "Viewing and printing TeX files."
d61140e8
RS
56 :prefix "tex-"
57 :group 'tex)
58
7e1dae73 59;;;###autoload
d61140e8
RS
60(defcustom tex-shell-file-name nil
61 "*If non-nil, the shell file name to run in the subshell used to run TeX."
62 :type '(choice (const :tag "None" nil)
63 string)
64 :group 'tex-run)
528415e7 65
7e1dae73 66;;;###autoload
1e8780b1 67(defcustom tex-directory (purecopy ".")
f73741fc 68 "*Directory in which temporary files are written.
81c735c0 69You can make this `/tmp' if your TEXINPUTS has no relative directories in it
528415e7 70and you don't try to apply \\[tex-region] or \\[tex-buffer] when there are
d61140e8
RS
71`\\input' commands with relative directories."
72 :type 'directory
73 :group 'tex-file)
869bff31 74
725b7428 75;;;###autoload
d61140e8 76(defcustom tex-first-line-header-regexp nil
725b7428
RS
77 "Regexp for matching a first line which `tex-region' should include.
78If this is non-nil, it should be a regular expression string;
79if it matches the first line of the file,
d61140e8
RS
80`tex-region' always includes the first line in the TeX run."
81 :type '(choice (const :tag "None" nil)
82 regexp)
83 :group 'tex-file)
725b7428 84
f73741fc 85;;;###autoload
d61140e8 86(defcustom tex-main-file nil
f73741fc 87 "*The main TeX source file which includes this buffer's file.
be4a962d
RS
88The command `tex-file' runs TeX on the file specified by `tex-main-file'
89if the variable is non-nil."
d61140e8
RS
90 :type '(choice (const :tag "None" nil)
91 file)
92 :group 'tex-file)
f73741fc 93
7e1dae73 94;;;###autoload
d61140e8
RS
95(defcustom tex-offer-save t
96 "*If non-nil, ask about saving modified buffers before \\[tex-file] is run."
97 :type 'boolean
98 :group 'tex-file)
869bff31 99
7e1dae73 100;;;###autoload
1e8780b1 101(defcustom tex-run-command (purecopy "tex")
869bff31 102 "*Command used to run TeX subjob.
c3ce7bf4
RS
103TeX Mode sets `tex-command' to this string.
104See the documentation of that variable."
d61140e8
RS
105 :type 'string
106 :group 'tex-run)
869bff31 107
7e1dae73 108;;;###autoload
1e8780b1 109(defcustom latex-run-command (purecopy "latex")
869bff31 110 "*Command used to run LaTeX subjob.
c3ce7bf4
RS
111LaTeX Mode sets `tex-command' to this string.
112See the documentation of that variable."
d61140e8
RS
113 :type 'string
114 :group 'tex-run)
528415e7 115
bed1b0c8 116;;;###autoload
1e8780b1 117(defcustom slitex-run-command (purecopy "slitex")
bed1b0c8 118 "*Command used to run SliTeX subjob.
c3ce7bf4
RS
119SliTeX Mode sets `tex-command' to this string.
120See the documentation of that variable."
bed1b0c8
RS
121 :type 'string
122 :group 'tex-run)
123
c3ce7bf4 124;;;###autoload
1e8780b1 125(defcustom tex-start-options (purecopy "")
9e0ad27a 126 "*TeX options to use when starting TeX.
95a045bd
SM
127These immediately precede the commands in `tex-start-commands'
128and the input file name, with no separating space and are not shell-quoted.
129If nil, TeX runs with no options. See the documentation of `tex-command'."
130 :type 'string
bed1b0c8 131 :group 'tex-run
bf247b6e 132 :version "22.1")
9e0ad27a
RS
133
134;;;###autoload
1e8780b1 135(defcustom tex-start-commands (purecopy "\\nonstopmode\\input")
9e0ad27a 136 "*TeX commands to use when starting TeX.
95a045bd
SM
137They are shell-quoted and precede the input file name, with a separating space.
138If nil, no commands are used. See the documentation of `tex-command'."
9e0ad27a
RS
139 :type '(radio (const :tag "Interactive \(nil\)" nil)
140 (const :tag "Nonstop \(\"\\nonstopmode\\input\"\)"
141 "\\nonstopmode\\input")
142 (string :tag "String at your choice"))
143 :group 'tex-run
bf247b6e 144 :version "22.1")
bed1b0c8 145
7afecb99 146(defvar latex-standard-block-names
dd459839
SM
147 '("abstract" "array" "center" "description"
148 "displaymath" "document" "enumerate" "eqnarray"
149 "eqnarray*" "equation" "figure" "figure*"
150 "flushleft" "flushright" "itemize" "letter"
151 "list" "minipage" "picture" "quotation"
152 "quote" "slide" "sloppypar" "tabbing"
153 "table" "table*" "tabular" "tabular*"
154 "thebibliography" "theindex*" "titlepage" "trivlist"
155 "verbatim" "verbatim*" "verse" "math")
528415e7
RS
156 "Standard LaTeX block names.")
157
7e1dae73 158;;;###autoload
d61140e8 159(defcustom latex-block-names nil
528415e7 160 "*User defined LaTeX block names.
7afecb99 161Combined with `latex-standard-block-names' for minibuffer completion."
d61140e8
RS
162 :type '(repeat string)
163 :group 'tex-run)
869bff31 164
7e1dae73 165;;;###autoload
1e8780b1 166(defcustom tex-bibtex-command (purecopy "bibtex")
528415e7 167 "*Command used by `tex-bibtex-file' to gather bibliographic data.
81c735c0 168If this string contains an asterisk (`*'), that is replaced by the file name;
d61140e8
RS
169otherwise, the file name, preceded by blank, is added at the end."
170 :type 'string
171 :group 'tex-run)
869bff31 172
7e1dae73 173;;;###autoload
1e8780b1 174(defcustom tex-dvi-print-command (purecopy "lpr -d")
528415e7 175 "*Command used by \\[tex-print] to print a .dvi file.
81c735c0 176If this string contains an asterisk (`*'), that is replaced by the file name;
d61140e8
RS
177otherwise, the file name, preceded by blank, is added at the end."
178 :type 'string
179 :group 'tex-view)
528415e7 180
7e1dae73 181;;;###autoload
1e8780b1 182(defcustom tex-alt-dvi-print-command (purecopy "lpr -d")
528415e7 183 "*Command used by \\[tex-print] with a prefix arg to print a .dvi file.
81c735c0
RS
184If this string contains an asterisk (`*'), that is replaced by the file name;
185otherwise, the file name, preceded by blank, is added at the end.
528415e7 186
81c735c0
RS
187If two printers are not enough of a choice, you can set the variable
188`tex-alt-dvi-print-command' to an expression that asks what you want;
528415e7
RS
189for example,
190
191 (setq tex-alt-dvi-print-command
192 '(format \"lpr -P%s\" (read-string \"Use printer: \")))
193
194would tell \\[tex-print] with a prefix argument to ask you which printer to
d61140e8
RS
195use."
196 :type '(choice (string :tag "Command")
197 (sexp :tag "Expression"))
198 :group 'tex-view)
869bff31 199
7e1dae73 200;;;###autoload
dd166d5f 201(defcustom tex-dvi-view-command
a7610c52
DN
202 `(cond
203 ((eq window-system 'x) ,(purecopy "xdvi"))
204 ((eq window-system 'w32) ,(purecopy "yap"))
205 (t ,(purecopy "dvi2tty * | cat -s")))
81c735c0 206 "*Command used by \\[tex-view] to display a `.dvi' file.
746c30e2 207If it is a string, that specifies the command directly.
81c735c0 208If this string contains an asterisk (`*'), that is replaced by the file name;
746c30e2 209otherwise, the file name, preceded by a space, is added at the end.
528415e7 210
746c30e2
RS
211If the value is a form, it is evaluated to get the command to use."
212 :type '(choice (const nil) string sexp)
d61140e8 213 :group 'tex-view)
869bff31 214
7e1dae73 215;;;###autoload
a7610c52 216(defcustom tex-show-queue-command (purecopy "lpq")
528415e7 217 "*Command used by \\[tex-show-print-queue] to show the print queue.
d61140e8
RS
218Should show the queue(s) that \\[tex-print] puts jobs on."
219 :type 'string
220 :group 'tex-view)
869bff31 221
7e1dae73 222;;;###autoload
9920303f 223(defcustom tex-default-mode 'latex-mode
869bff31 224 "*Mode to enter for a new file that might be either TeX or LaTeX.
225This variable is used when it can't be determined whether the file
226is plain TeX or LaTeX or what because the file contains no commands.
d61140e8
RS
227Normally set to either `plain-tex-mode' or `latex-mode'."
228 :type 'function
229 :group 'tex)
869bff31 230
7e1dae73 231;;;###autoload
a7610c52 232(defcustom tex-open-quote (purecopy "``")
d61140e8
RS
233 "*String inserted by typing \\[tex-insert-quote] to open a quotation."
234 :type 'string
95a045bd 235 :options '("``" "\"<" "\"`" "<<" "«")
d61140e8 236 :group 'tex)
869bff31 237
7e1dae73 238;;;###autoload
a7610c52 239(defcustom tex-close-quote (purecopy "''")
d61140e8
RS
240 "*String inserted by typing \\[tex-insert-quote] to close a quotation."
241 :type 'string
95a045bd 242 :options '("''" "\">" "\"'" ">>" "»")
d61140e8 243 :group 'tex)
869bff31 244
2b1567a5
RS
245(defcustom tex-fontify-script t
246 "If non-nil, fontify subscript and superscript strings."
247 :type 'boolean
0bda3658
GM
248 :group 'tex
249 :version "23.1")
2b1567a5
RS
250(put 'tex-fontify-script 'safe-local-variable 'booleanp)
251
0e1627a7 252(defcustom tex-font-script-display '(-0.2 0.2)
acdc4e59
GM
253 "How much to lower and raise subscript and superscript content.
254This is a list of two floats. The first is negative and
255specifies how much subscript is lowered, the second is positive
256and specifies how much superscript is raised. Heights are
257measured relative to that of the normal text."
2b1567a5 258 :group 'tex
0e1627a7 259 :type '(list (float :tag "Subscript")
0bda3658
GM
260 (float :tag "Superscript"))
261 :version "23.1")
2b1567a5 262
528415e7
RS
263(defvar tex-last-temp-file nil
264 "Latest temporary file generated by \\[tex-region] and \\[tex-buffer].
265Deleted when the \\[tex-region] or \\[tex-buffer] is next run, or when the
81c735c0 266tex shell terminates.")
528415e7 267
95a045bd 268(defvar tex-command "tex"
c3ce7bf4 269 "*Command to run TeX.
95a045bd 270If this string contains an asterisk \(`*'\), that is replaced by the file name;
9e0ad27a
RS
271otherwise the value of `tex-start-options', the \(shell-quoted\)
272value of `tex-start-commands', and the file name are added at the end
273with blanks as separators.
c3ce7bf4
RS
274
275In TeX, LaTeX, and SliTeX Mode this variable becomes buffer local.
276In these modes, use \\[set-variable] if you want to change it for the
277current buffer.")
869bff31 278
279(defvar tex-trailer nil
280 "String appended after the end of a region sent to TeX by \\[tex-region].")
281
282(defvar tex-start-of-header nil
898b9ac1 283 "Regular expression used by \\[tex-region] to find start of file's header.")
869bff31 284
285(defvar tex-end-of-header nil
898b9ac1 286 "Regular expression used by \\[tex-region] to find end of file's header.")
869bff31 287
288(defvar tex-shell-cd-command "cd"
289 "Command to give to shell running TeX to change directory.
81c735c0 290The value of `tex-directory' is appended to this, separated by a space.")
869bff31 291
292(defvar tex-zap-file nil
293 "Temporary file name used for text being sent as input to TeX.
294Should be a simple file name with no extension or directory specification.")
295
296(defvar tex-last-buffer-texed nil
297 "Buffer which was last TeXed.")
298
299(defvar tex-print-file nil
300 "File name that \\[tex-print] prints.
301Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")
302
8a591d52
SM
303(defvar tex-mode-syntax-table
304 (let ((st (make-syntax-table)))
305 (modify-syntax-entry ?% "<" st)
306 (modify-syntax-entry ?\n ">" st)
307 (modify-syntax-entry ?\f ">" st)
308 (modify-syntax-entry ?\C-@ "w" st)
309 (modify-syntax-entry ?' "w" st)
310 (modify-syntax-entry ?@ "_" st)
311 (modify-syntax-entry ?* "_" st)
312 (modify-syntax-entry ?\t " " st)
bca7a08b
SM
313 ;; ~ is printed by TeX as a space, but it's semantics in the syntax
314 ;; of TeX is not `whitespace' (i.e. it's just like \hspace{foo}).
8a591d52
SM
315 (modify-syntax-entry ?~ "." st)
316 (modify-syntax-entry ?$ "$$" st)
317 (modify-syntax-entry ?\\ "/" st)
318 (modify-syntax-entry ?\" "." st)
319 (modify-syntax-entry ?& "." st)
320 (modify-syntax-entry ?_ "." st)
321 (modify-syntax-entry ?^ "." st)
322 st)
869bff31 323 "Syntax table used while in TeX mode.")
53c4fe47
SM
324\f
325;;;;
326;;;; Imenu support
327;;;;
869bff31 328
d6709b80 329(defcustom latex-imenu-indent-string ". "
a53c647b
RS
330 "*String to add repeated in front of nested sectional units for Imenu.
331An alternative value is \" . \", if you use a font with a narrow period."
332 :type 'string
333 :group 'tex)
334
d6709b80
SM
335(defvar latex-section-alist
336 '(("part" . 0) ("chapter" . 1)
337 ("section" . 2) ("subsection" . 3)
338 ("subsubsection" . 4)
339 ("paragraph" . 5) ("subparagraph" . 6)))
340
53c4fe47
SM
341(defvar latex-metasection-list
342 '("documentstyle" "documentclass"
343 "begin{document}" "end{document}"
344 "appendix" "frontmatter" "mainmatter" "backmatter"))
345
a5e2ae01 346(defun latex-imenu-create-index ()
53c4fe47
SM
347 "Generate an alist for imenu from a LaTeX buffer."
348 (let ((section-regexp
349 (concat "\\\\" (regexp-opt (mapcar 'car latex-section-alist) t)
350 "\\*?[ \t]*{"))
351 (metasection-regexp
352 (concat "\\\\" (regexp-opt latex-metasection-list t)))
353 i0 menu case-fold-search)
a53c647b
RS
354 (save-excursion
355 ;; Find the top-most level in this file but don't allow it to be
356 ;; any deeper than "section" (which is top-level in an article).
357 (goto-char (point-min))
358 (if (search-forward-regexp "\\\\part\\*?[ \t]*{" nil t)
359 (setq i0 0)
360 (if (search-forward-regexp "\\\\chapter\\*?[ \t]*{" nil t)
361 (setq i0 1)
362 (setq i0 2)))
363
364 ;; Look for chapters and sections.
365 (goto-char (point-min))
53c4fe47 366 (while (search-forward-regexp section-regexp nil t)
a53c647b
RS
367 (let ((start (match-beginning 0))
368 (here (point))
369 (i (cdr (assoc (buffer-substring-no-properties
370 (match-beginning 1)
371 (match-end 1))
d6709b80 372 latex-section-alist))))
a53c647b
RS
373 (backward-char 1)
374 (condition-case err
375 (progn
376 ;; Using sexps allows some use of matching {...} inside
377 ;; titles.
378 (forward-sexp 1)
d6709b80
SM
379 (push (cons (concat (apply 'concat
380 (make-list
381 (max 0 (- i i0))
382 latex-imenu-indent-string))
383 (buffer-substring-no-properties
384 here (1- (point))))
385 start)
386 menu))
a53c647b
RS
387 (error nil))))
388
389 ;; Look for included material.
390 (goto-char (point-min))
391 (while (search-forward-regexp
392 "\\\\\\(include\\|input\\|verbatiminput\\|bibliography\\)\
53c4fe47 393\[ \t]*{\\([^}\n]+\\)}"
a53c647b 394 nil t)
53c4fe47
SM
395 (push (cons (concat "<<" (buffer-substring-no-properties
396 (match-beginning 2)
397 (match-end 2))
398 (if (= (char-after (match-beginning 1)) ?b)
399 ".bbl"
400 ".tex"))
401 (match-beginning 0))
402 menu))
a53c647b
RS
403
404 ;; Look for \frontmatter, \mainmatter, \backmatter, and \appendix.
405 (goto-char (point-min))
53c4fe47
SM
406 (while (search-forward-regexp metasection-regexp nil t)
407 (push (cons "--" (match-beginning 0)) menu))
a53c647b
RS
408
409 ;; Sort in increasing buffer position order.
410 (sort menu (function (lambda (a b) (< (cdr a) (cdr b))))))))
53c4fe47
SM
411\f
412;;;;
413;;;; Outline support
414;;;;
415
416(defvar latex-outline-regexp
417 (concat "\\\\"
418 (regexp-opt (append latex-metasection-list
419 (mapcar 'car latex-section-alist)) t)))
420
421(defun latex-outline-level ()
422 (if (looking-at latex-outline-regexp)
423 (1+ (or (cdr (assoc (match-string 1) latex-section-alist)) -1))
424 1000))
425\f
426;;;;
427;;;; Font-Lock support
428;;;;
429
430;(defvar tex-font-lock-keywords
431; ;; Regexps updated with help from Ulrik Dickow <dickow@nbi.dk>.
432; '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}"
433; 2 font-lock-function-name-face)
434; ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}"
435; 2 font-lock-constant-face)
436; ;; It seems a bit dubious to use `bold' and `italic' faces since we might
437; ;; not be able to display those fonts.
438; ("{\\\\bf\\([^}]+\\)}" 1 'bold keep)
439; ("{\\\\\\(em\\|it\\|sl\\)\\([^}]+\\)}" 2 'italic keep)
440; ("\\\\\\([a-zA-Z@]+\\|.\\)" . font-lock-keyword-face)
441; ("^[ \t\n]*\\\\def[\\\\@]\\(\\w+\\)" 1 font-lock-function-name-face keep))
442; ;; Rewritten and extended for LaTeX2e by Ulrik Dickow <dickow@nbi.dk>.
443; '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}"
444; 2 font-lock-function-name-face)
445; ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}"
446; 2 font-lock-constant-face)
447; ("^[ \t]*\\\\def\\\\\\(\\(\\w\\|@\\)+\\)" 1 font-lock-function-name-face)
448; "\\\\\\([a-zA-Z@]+\\|.\\)"
449; ;; It seems a bit dubious to use `bold' and `italic' faces since we might
450; ;; not be able to display those fonts.
451; ;; LaTeX2e: \emph{This is emphasized}.
452; ("\\\\emph{\\([^}]+\\)}" 1 'italic keep)
453; ;; LaTeX2e: \textbf{This is bold}, \textit{...}, \textsl{...}
454; ("\\\\text\\(\\(bf\\)\\|it\\|sl\\){\\([^}]+\\)}"
455; 3 (if (match-beginning 2) 'bold 'italic) keep)
456; ;; Old-style bf/em/it/sl. Stop at `\\' and un-escaped `&', for tables.
457; ("\\\\\\(\\(bf\\)\\|em\\|it\\|sl\\)\\>\\(\\([^}&\\]\\|\\\\[^\\]\\)+\\)"
458; 3 (if (match-beginning 2) 'bold 'italic) keep))
459
460;; Rewritten with the help of Alexandra Bac <abac@welcome.disi.unige.it>.
461(defconst tex-font-lock-keywords-1
462 (eval-when-compile
463 (let* (;; Names of commands whose arg should be fontified as heading, etc.
464 (headings (regexp-opt
465 '("title" "begin" "end" "chapter" "part"
466 "section" "subsection" "subsubsection"
467 "paragraph" "subparagraph" "subsubparagraph"
7afecb99
SM
468 "newcommand" "renewcommand" "providecommand"
469 "newenvironment" "renewenvironment"
470 "newtheorem" "renewtheorem")
53c4fe47
SM
471 t))
472 (variables (regexp-opt
473 '("newcounter" "newcounter*" "setcounter" "addtocounter"
474 "setlength" "addtolength" "settowidth")
475 t))
476 (includes (regexp-opt
477 '("input" "include" "includeonly" "bibliography"
478 "epsfig" "psfig" "epsf" "nofiles" "usepackage"
15ca8de7 479 "documentstyle" "documentclass" "verbatiminput"
dd166d5f
SM
480 "includegraphics" "includegraphics*"
481 "url" "nolinkurl")
53c4fe47
SM
482 t))
483 ;; Miscellany.
484 (slash "\\\\")
15ca8de7
SM
485 (opt " *\\(\\[[^]]*\\] *\\)*")
486 ;; This would allow highlighting \newcommand\CMD but requires
487 ;; adapting subgroup numbers below.
488 ;; (arg "\\(?:{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)\\|\\\\[a-z*]+\\)"))
1598a961 489 (arg "{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)"))
53c4fe47 490 (list
b119fdd5 491 ;; font-lock-syntactic-keywords causes the \ of \end{verbatim} to be
621f893a 492 ;; highlighted as tex-verbatim face. Let's undo that.
b119fdd5
SM
493 ;; This is ugly and brittle :-( --Stef
494 '("^\\(\\\\\\)end" (1 (get-text-property (match-end 1) 'face) t))
95a045bd
SM
495 ;; display $$ math $$
496 ;; We only mark the match between $$ and $$ because the $$ delimiters
497 ;; themselves have already been marked (along with $..$) by syntactic
498 ;; fontification. Also this is done at the very beginning so as to
499 ;; interact with the other keywords in the same way as $...$ does.
500 (list "\\$\\$\\([^$]+\\)\\$\\$" 1 'tex-math-face)
53c4fe47
SM
501 ;; Heading args.
502 (list (concat slash headings "\\*?" opt arg)
12f0a4d6 503 ;; If ARG ends up matching too much (if the {} don't match, e.g.)
bdbd9606
SM
504 ;; jit-lock will do funny things: when updating the buffer
505 ;; the re-highlighting is only done locally so it will just
506 ;; match the local line, but defer-contextually will
507 ;; match more lines at a time, so ARG will end up matching
508 ;; a lot more, which might suddenly include a comment
509 ;; so you get things highlighted bold when you type them
510 ;; but they get turned back to normal a little while later
511 ;; because "there's already a face there".
512 ;; Using `keep' works around this un-intuitive behavior as well
15ca8de7
SM
513 ;; as improves the behavior in the very rare case where you do
514 ;; have a comment in ARG.
bdbd9606 515 3 'font-lock-function-name-face 'keep)
7afecb99
SM
516 (list (concat slash "\\(?:provide\\|\\(?:re\\)?new\\)command\\** *\\(\\\\[A-Za-z@]+\\)")
517 1 'font-lock-function-name-face 'keep)
53c4fe47 518 ;; Variable args.
15ca8de7 519 (list (concat slash variables " *" arg) 2 'font-lock-variable-name-face)
53c4fe47
SM
520 ;; Include args.
521 (list (concat slash includes opt arg) 3 'font-lock-builtin-face)
522 ;; Definitions. I think.
15ca8de7 523 '("^[ \t]*\\\\def *\\\\\\(\\(\\w\\|@\\)+\\)"
bdbd9606 524 1 font-lock-function-name-face))))
53c4fe47
SM
525 "Subdued expressions to highlight in TeX modes.")
526
1f4cc034
SM
527(defun tex-font-lock-append-prop (prop)
528 (unless (memq (get-text-property (match-end 1) 'face)
621f893a 529 '(font-lock-comment-face tex-verbatim))
1f4cc034
SM
530 prop))
531
53c4fe47
SM
532(defconst tex-font-lock-keywords-2
533 (append tex-font-lock-keywords-1
534 (eval-when-compile
535 (let* (;;
536 ;; Names of commands whose arg should be fontified with fonts.
1598a961 537 (bold (regexp-opt '("textbf" "textsc" "textup"
53c4fe47 538 "boldsymbol" "pmb") t))
1598a961 539 (italic (regexp-opt '("textit" "textsl" "emph") t))
a3d80d4a
SM
540 ;; FIXME: unimplemented yet.
541 ;; (type (regexp-opt '("texttt" "textmd" "textrm" "textsf") t))
53c4fe47
SM
542 ;;
543 ;; Names of commands whose arg should be fontified as a citation.
544 (citations (regexp-opt
545 '("label" "ref" "pageref" "vref" "eqref"
15ca8de7 546 "cite" "nocite" "index" "glossary" "bibitem"
1d16f33c
SM
547 ;; natbib's two variants of \cite:
548 "citep" "citet"
1598a961
SM
549 ;; These are text, rather than citations.
550 ;; "caption" "footnote" "footnotemark" "footnotetext"
551 )
53c4fe47
SM
552 t))
553 ;;
554 ;; Names of commands that should be fontified.
1b741d9e
AS
555 (specials-1 (regexp-opt '("\\" "\\*") t)) ;; "-"
556 (specials-2 (regexp-opt
557 '("linebreak" "nolinebreak" "pagebreak" "nopagebreak"
558 "newline" "newpage" "clearpage" "cleardoublepage"
559 "displaybreak" "allowdisplaybreaks"
560 "enlargethispage") t))
53c4fe47
SM
561 (general "\\([a-zA-Z@]+\\**\\|[^ \t\n]\\)")
562 ;;
563 ;; Miscellany.
564 (slash "\\\\")
15ca8de7 565 (opt " *\\(\\[[^]]*\\] *\\)*")
7afecb99 566 (args "\\(\\(?:[^{}&\\]+\\|\\\\.\\|{[^}]*}\\)+\\)")
1598a961 567 (arg "{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)"))
53c4fe47
SM
568 (list
569 ;;
570 ;; Citation args.
571 (list (concat slash citations opt arg) 3 'font-lock-constant-face)
572 ;;
15ca8de7 573 ;; Text between `` quotes ''.
95a045bd 574 (cons (concat (regexp-opt `("``" "\"<" "\"`" "<<" "«") t)
7abc9add 575 "[^'\">{]+" ;a bit pessimistic
95a045bd 576 (regexp-opt `("''" "\">" "\"'" ">>" "»") t))
15ca8de7
SM
577 'font-lock-string-face)
578 ;;
53c4fe47 579 ;; Command names, special and general.
1b741d9e
AS
580 (cons (concat slash specials-1) 'font-lock-warning-face)
581 (list (concat "\\(" slash specials-2 "\\)\\([^a-zA-Z@]\\|\\'\\)")
582 1 'font-lock-warning-face)
53c4fe47
SM
583 (concat slash general)
584 ;;
585 ;; Font environments. It seems a bit dubious to use `bold' etc. faces
586 ;; since we might not be able to display those fonts.
1f4cc034
SM
587 (list (concat slash bold " *" arg) 2
588 '(tex-font-lock-append-prop 'bold) 'append)
589 (list (concat slash italic " *" arg) 2
590 '(tex-font-lock-append-prop 'italic) 'append)
1598a961 591 ;; (list (concat slash type arg) 2 '(quote bold-italic) 'append)
53c4fe47
SM
592 ;;
593 ;; Old-style bf/em/it/sl. Stop at `\\' and un-escaped `&', for tables.
7afecb99 594 (list (concat "\\\\\\(em\\|it\\|sl\\)\\>" args)
1f4cc034 595 2 '(tex-font-lock-append-prop 'italic) 'append)
7afecb99
SM
596 ;; This is separate from the previous one because of cases like
597 ;; {\em foo {\bf bar} bla} where both match.
7c357894 598 (list (concat "\\\\\\(bf\\(series\\)?\\)\\>" args)
9bf211ad 599 3 '(tex-font-lock-append-prop 'bold) 'append)))))
53c4fe47
SM
600 "Gaudy expressions to highlight in TeX modes.")
601
7afecb99
SM
602(defun tex-font-lock-suscript (pos)
603 (unless (or (memq (get-text-property pos 'face)
604 '(font-lock-constant-face font-lock-builtin-face
621f893a 605 font-lock-comment-face tex-verbatim))
7afecb99
SM
606 ;; Check for backslash quoting
607 (let ((odd nil)
608 (pos pos))
609 (while (eq (char-before pos) ?\\)
610 (setq pos (1- pos) odd (not odd)))
611 odd))
612 (if (eq (char-after pos) ?_)
2b1567a5 613 `(face subscript display (raise ,(car tex-font-script-display)))
0e1627a7 614 `(face superscript display (raise ,(cadr tex-font-script-display))))))
7afecb99 615
587043f8
SM
616(defun tex-font-lock-match-suscript (limit)
617 "Match subscript and superscript patterns up to LIMIT."
2b1567a5
RS
618 (when (and tex-fontify-script
619 (re-search-forward "[_^] *\\([^\n\\{}]\\|\
620\\\\\\([a-zA-Z@]+\\|[^ \t\n]\\)\\|\\({\\)\\)" limit t))
587043f8
SM
621 (when (match-end 3)
622 (let ((beg (match-beginning 3))
623 (end (save-restriction
624 (narrow-to-region (point-min) limit)
625 (condition-case nil (scan-lists (point) 1 1) (error nil)))))
626 (store-match-data (if end
43c50d22
SM
627 (list (match-beginning 0) end beg end)
628 (list beg beg beg beg)))))
587043f8
SM
629 t))
630
7afecb99
SM
631(defconst tex-font-lock-keywords-3
632 (append tex-font-lock-keywords-2
587043f8
SM
633 '((tex-font-lock-match-suscript
634 (1 (tex-font-lock-suscript (match-beginning 0)) append))))
7afecb99
SM
635 "Experimental expressions to highlight in TeX modes.")
636
53c4fe47
SM
637(defvar tex-font-lock-keywords tex-font-lock-keywords-1
638 "Default expressions to highlight in TeX modes.")
0fb4f245 639
7afecb99
SM
640(defvar tex-verbatim-environments
641 '("verbatim" "verbatim*"))
c25d0edb 642(put 'tex-verbatim-environments 'safe-local-variable
299ea3d3 643 (lambda (x) (null (delq t (mapcar 'stringp x)))))
7afecb99
SM
644
645(defvar tex-font-lock-syntactic-keywords
c25d0edb
SM
646 '((eval . `(,(concat "^\\\\begin *{"
647 (regexp-opt tex-verbatim-environments t)
648 "}.*\\(\n\\)") 2 "|"))
649 ;; Technically, we'd like to put the "|" property on the \n preceding
650 ;; the \end, but this would have 2 disadvantages:
651 ;; 1 - it's wrong if the verbatim env is empty (the same \n is used to
652 ;; start and end the fenced-string).
653 ;; 2 - font-lock considers the preceding \n as being part of the
654 ;; preceding line, so things gets screwed every time the previous
655 ;; line is re-font-locked on its own.
656 ;; There's a hack in tex-font-lock-keywords-1 to remove the verbatim
657 ;; face from the \ but C-M-f still jumps to the wrong spot :-( --Stef
658 (eval . `(,(concat "^\\(\\\\\\)end *{"
659 (regexp-opt tex-verbatim-environments t)
660 "}\\(.?\\)") (1 "|") (3 "<")))
661 ;; ("^\\(\\\\\\)begin *{comment}" 1 "< b")
662 ;; ("^\\\\end *{comment}.*\\(\n\\)" 1 "> b")
663 ("\\\\verb\\**\\([^a-z@*]\\)"
664 ;; Do it last, because it uses syntax-ppss which needs the
665 ;; syntax-table properties of previous entries.
666 1 (tex-font-lock-verb (match-end 1)))))
7afecb99
SM
667
668(defun tex-font-lock-unfontify-region (beg end)
669 (font-lock-default-unfontify-region beg end)
670 (while (< beg end)
671 (let ((next (next-single-property-change beg 'display nil end))
672 (prop (get-text-property beg 'display)))
673 (if (and (eq (car-safe prop) 'raise)
0e1627a7 674 (member (car-safe (cdr prop)) tex-font-script-display)
7afecb99
SM
675 (null (cddr prop)))
676 (put-text-property beg next 'display nil))
677 (setq beg next))))
678
8b6f62fc
GM
679(defcustom tex-suscript-height-ratio 0.8
680 "Ratio of subscript/superscript height to that of the preceding text.
681In nested subscript/superscript, this factor is applied repeatedly,
682subject to the limit set by `tex-suscript-height-minimum'."
683 :type 'float
684 :group 'tex
685 :version "23.1")
686
687(defcustom tex-suscript-height-minimum 0.0
688 "Integer or float limiting the minimum size of subscript/superscript text.
689An integer is an absolute height in units of 1/10 point, a float
690is a height relative to that of the default font. Zero means no minimum."
691 :type '(choice (integer :tag "Integer height in 1/10 point units")
692 (float :tag "Fraction of default font height"))
693 :group 'tex
694 :version "23.1")
695
696(defun tex-suscript-height (height)
697 "Return the integer height of subscript/superscript font in 1/10 points.
698Not smaller than the value set by `tex-suscript-height-minimum'."
699 (ceiling (max (if (integerp tex-suscript-height-minimum)
700 tex-suscript-height-minimum
701 ;; For bootstrapping.
702 (condition-case nil
703 (* tex-suscript-height-minimum
704 (face-attribute 'default :height))
705 (error 0)))
706 ;; NB assumes height is integer.
707 (* height tex-suscript-height-ratio))))
708
7afecb99 709(defface superscript
8b6f62fc 710 '((t :height tex-suscript-height)) ;; :raise 0.2
18a8c773
LK
711 "Face used for superscripts."
712 :group 'tex)
7afecb99 713(defface subscript
8b6f62fc 714 '((t :height tex-suscript-height)) ;; :raise -0.2
18a8c773
LK
715 "Face used for subscripts."
716 :group 'tex)
bdbd9606 717
ad49d9d6 718(defface tex-math
bdbd9606 719 '((t :inherit font-lock-string-face))
18a8c773
LK
720 "Face used to highlight TeX math expressions."
721 :group 'tex)
c4f6e489 722(define-obsolete-face-alias 'tex-math-face 'tex-math "22.1")
ad49d9d6
MB
723(defvar tex-math-face 'tex-math)
724
725(defface tex-verbatim
7afecb99 726 ;; '((t :inherit font-lock-string-face))
f37a389e 727 '((t :family "courier"))
18a8c773
LK
728 "Face used to highlight TeX verbatim environments."
729 :group 'tex)
c4f6e489 730(define-obsolete-face-alias 'tex-verbatim-face 'tex-verbatim "22.1")
ad49d9d6 731(defvar tex-verbatim-face 'tex-verbatim)
bdbd9606 732
3307a4fa
SM
733(defun tex-font-lock-verb (end)
734 "Place syntax-table properties on the \verb construct.
735END is the position of the first delimiter after \verb."
736 (unless (nth 8 (syntax-ppss end))
737 ;; Do nothing if the \verb construct is itself inside a comment or
738 ;; verbatim env.
739 (save-excursion
740 ;; Let's find the end and mark it.
741 ;; We used to do it inside tex-font-lock-syntactic-face-function, but
742 ;; this leads to funny effects when jumping to the end of the buffer,
743 ;; because font-lock applies font-lock-syntactic-keywords to the whole
744 ;; preceding text but font-lock-syntactic-face-function only to the
745 ;; actually displayed text.
746 (goto-char end)
747 (let ((char (char-before)))
748 (skip-chars-forward (string ?^ char)) ;; Use `end' ?
749 (when (eq (char-syntax (preceding-char)) ?/)
750 (put-text-property (1- (point)) (point) 'syntax-table '(1)))
751 (unless (eobp)
752 (put-text-property (point) (1+ (point)) 'syntax-table '(7))
753 ;; Cause the rest of the buffer to be re-fontified.
754 ;; (remove-text-properties (1+ (point)) (point-max) '(fontified))
755 )))
756 "\""))
757
bdbd9606
SM
758;; Use string syntax but math face for $...$.
759(defun tex-font-lock-syntactic-face-function (state)
7afecb99
SM
760 (let ((char (nth 3 state)))
761 (cond
762 ((not char) font-lock-comment-face)
763 ((eq char ?$) tex-math-face)
3307a4fa 764 (t tex-verbatim-face))))
bdbd9606 765
53c4fe47 766\f
869bff31 767(defun tex-define-common-keys (keymap)
81c735c0 768 "Define the keys that we want defined both in TeX mode and in the TeX shell."
869bff31 769 (define-key keymap "\C-c\C-k" 'tex-kill-job)
770 (define-key keymap "\C-c\C-l" 'tex-recenter-output-buffer)
771 (define-key keymap "\C-c\C-q" 'tex-show-print-queue)
772 (define-key keymap "\C-c\C-p" 'tex-print)
773 (define-key keymap "\C-c\C-v" 'tex-view)
62a24cb5
RS
774
775 (define-key keymap [menu-bar tex] (cons "TeX" (make-sparse-keymap "TeX")))
776
bdbd9606
SM
777 (define-key keymap [menu-bar tex tex-kill-job]
778 '(menu-item "Tex Kill" tex-kill-job :enable (tex-shell-running)))
cf6d6e8a 779 (define-key keymap [menu-bar tex tex-recenter-output-buffer]
bdbd9606
SM
780 '(menu-item "Tex Recenter" tex-recenter-output-buffer
781 :enable (get-buffer "*tex-shell*")))
62a24cb5
RS
782 (define-key keymap [menu-bar tex tex-show-print-queue]
783 '("Show Print Queue" . tex-show-print-queue))
cf6d6e8a 784 (define-key keymap [menu-bar tex tex-alt-print]
bdbd9606
SM
785 '(menu-item "Tex Print (alt printer)" tex-alt-print
786 :enable (stringp tex-print-file)))
787 (define-key keymap [menu-bar tex tex-print]
788 '(menu-item "Tex Print" tex-print :enable (stringp tex-print-file)))
789 (define-key keymap [menu-bar tex tex-view]
790 '(menu-item "Tex View" tex-view :enable (stringp tex-print-file))))
791
792(defvar tex-mode-map
793 (let ((map (make-sparse-keymap)))
15ca8de7 794 (set-keymap-parent map text-mode-map)
bdbd9606
SM
795 (tex-define-common-keys map)
796 (define-key map "\"" 'tex-insert-quote)
797 (define-key map "(" 'skeleton-pair-insert-maybe)
798 (define-key map "{" 'skeleton-pair-insert-maybe)
799 (define-key map "[" 'skeleton-pair-insert-maybe)
800 (define-key map "$" 'skeleton-pair-insert-maybe)
801 (define-key map "\n" 'tex-terminate-paragraph)
802 (define-key map "\M-\r" 'latex-insert-item)
803 (define-key map "\C-c}" 'up-list)
804 (define-key map "\C-c{" 'tex-insert-braces)
805 (define-key map "\C-c\C-r" 'tex-region)
806 (define-key map "\C-c\C-b" 'tex-buffer)
807 (define-key map "\C-c\C-f" 'tex-file)
75035a80 808 (define-key map "\C-c\C-c" 'tex-compile)
bdbd9606 809 (define-key map "\C-c\C-i" 'tex-bibtex-file)
7afecb99 810 (define-key map "\C-c\C-o" 'latex-insert-block)
2ef3c144
CY
811
812 ;; Redundant keybindings, for consistency with SGML mode.
813 (define-key map "\C-c\C-t" 'latex-insert-block)
814 (define-key map "\C-c/" 'latex-close-block)
815
7afecb99 816 (define-key map "\C-c\C-e" 'latex-close-block)
bdbd9606
SM
817 (define-key map "\C-c\C-u" 'tex-goto-last-unclosed-latex-block)
818 (define-key map "\C-c\C-m" 'tex-feed-input)
819 (define-key map [(control return)] 'tex-feed-input)
820 (define-key map [menu-bar tex tex-bibtex-file]
821 '("BibTeX File" . tex-bibtex-file))
822 (define-key map [menu-bar tex tex-validate-region]
823 '(menu-item "Validate Region" tex-validate-region :enable mark-active))
824 (define-key map [menu-bar tex tex-validate-buffer]
825 '("Validate Buffer" . tex-validate-buffer))
826 (define-key map [menu-bar tex tex-region]
827 '(menu-item "TeX Region" tex-region :enable mark-active))
828 (define-key map [menu-bar tex tex-buffer]
829 '("TeX Buffer" . tex-buffer))
830 (define-key map [menu-bar tex tex-file] '("TeX File" . tex-file))
831 map)
15ca8de7
SM
832 "Keymap shared by TeX modes.")
833
834(defvar latex-mode-map
835 (let ((map (make-sparse-keymap)))
836 (set-keymap-parent map tex-mode-map)
a3d80d4a 837 (define-key map "\C-c\C-s" 'latex-split-block)
15ca8de7
SM
838 map)
839 "Keymap for `latex-mode'. See also `tex-mode-map'.")
840
841(defvar plain-tex-mode-map
842 (let ((map (make-sparse-keymap)))
843 (set-keymap-parent map tex-mode-map)
844 map)
845 "Keymap for `plain-tex-mode'. See also `tex-mode-map'.")
cf6d6e8a 846
d6709b80
SM
847(defvar tex-shell-map
848 (let ((m (make-sparse-keymap)))
849 (set-keymap-parent m shell-mode-map)
850 (tex-define-common-keys m)
851 m)
81c735c0 852 "Keymap for the TeX shell.
dca5ea48 853Inherits `shell-mode-map' with a few additions.")
869bff31 854
6da9bbd6
RS
855(defvar tex-face-alist
856 '((bold . "{\\bf ")
857 (italic . "{\\it ")
858 (bold-italic . "{\\bi ") ; hypothetical
859 (underline . "\\underline{")
860 (default . "{\\rm "))
861 "Alist of face and TeX font name for facemenu.")
862
863(defvar tex-latex-face-alist
864 `((italic . "{\\em ")
865 ,@tex-face-alist)
866 "Alist of face and LaTeX font name for facemenu.")
867
673c1168
CY
868(defun tex-facemenu-add-face-function (face end)
869 (or (cdr (assq face tex-face-alist))
870 (or (and (consp face)
871 (consp (car face))
872 (null (cdr face))
873 (eq major-mode 'latex-mode)
874 ;; This actually requires the `color' LaTeX package.
875 (cond ((eq (caar face) :foreground)
876 (format "{\\color{%s} " (cadr (car face))))
877 ((eq (caar face) :background)
878 (format "\\colorbox{%s}{" (cadr (car face))))))
879 (error "Face %s not configured for %s mode" face mode-name))))
880
15ca8de7
SM
881;; This would be a lot simpler if we just used a regexp search,
882;; but then it would be too slow.
a3d80d4a 883(defun tex-guess-mode ()
d6709b80 884 (let ((mode tex-default-mode) slash comment)
869bff31 885 (save-excursion
886 (goto-char (point-min))
887 (while (and (setq slash (search-forward "\\" nil t))
888 (setq comment (let ((search-end (point)))
889 (save-excursion
890 (beginning-of-line)
891 (search-forward "%" search-end t))))))
bdbd9606
SM
892 (when (and slash (not comment))
893 (setq mode
894 (if (looking-at
895 (eval-when-compile
896 (concat
897 (regexp-opt '("documentstyle" "documentclass"
95a045bd 898 "begin" "subsection" "section"
bca7a08b 899 "part" "chapter" "newcommand"
29a47b89 900 "renewcommand" "RequirePackage") 'words)
bdbd9606 901 "\\|NeedsTeXFormat{LaTeX")))
dd166d5f
SM
902 (if (and (looking-at
903 "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")
904 ;; SliTeX is almost never used any more nowadays.
905 (tex-executable-exists-p slitex-run-command))
bdbd9606
SM
906 'slitex-mode
907 'latex-mode)
908 'plain-tex-mode))))
d6709b80 909 (funcall mode)))
e4c8c838 910
a3d80d4a
SM
911;; `tex-mode' plays two roles: it's the parent of several sub-modes
912;; but it's also the function that chooses between those submodes.
913;; To tell the difference between those two cases where the function
914;; might be called, we check `delay-mode-hooks'.
a3d80d4a
SM
915(define-derived-mode tex-mode text-mode "generic-TeX"
916 (tex-common-initialization))
bca7a08b
SM
917;; We now move the function and define it again. This gives a warning
918;; in the byte-compiler :-( but it's difficult to avoid because
919;; `define-derived-mode' will necessarily define the function once
920;; and we need to define it a second time for `autoload' to get the
921;; proper docstring.
922(defalias 'tex-mode-internal (symbol-function 'tex-mode))
3405b0df
GM
923
924;; Suppress the byte-compiler warning about multiple definitions.
925;; This is a) ugly, and b) cheating, but this was the last
926;; remaining warning from byte-compiling all of Emacs...
927(eval-when-compile
928 (setq byte-compile-function-environment
88fd78ae
GM
929 (delq (assq 'tex-mode byte-compile-function-environment)
930 byte-compile-function-environment)))
3405b0df 931
bca7a08b
SM
932;;;###autoload
933(defun tex-mode ()
934 "Major mode for editing files of input for TeX, LaTeX, or SliTeX.
a3d80d4a
SM
935Tries to determine (by looking at the beginning of the file) whether
936this file is for plain TeX, LaTeX, or SliTeX and calls `plain-tex-mode',
937`latex-mode', or `slitex-mode', respectively. If it cannot be determined,
938such as if there are no commands in the file, the value of `tex-default-mode'
939says which mode to use."
bca7a08b
SM
940 (interactive)
941 (if delay-mode-hooks
942 ;; We're called from one of the children already.
943 (tex-mode-internal)
944 (tex-guess-mode)))
a3d80d4a 945
1639cc2e
DK
946;; The following three autoloaded aliases appear to conflict with
947;; AUCTeX. However, even though AUCTeX uses the mixed case variants
948;; for all mode relevant variables and hooks, the invocation function
949;; and setting of `major-mode' themselves need to be lowercase for
950;; AUCTeX to provide a fully functional user-level replacement. So
951;; these aliases should remain as they are, in particular since AUCTeX
952;; users are likely to use them.
953
6503cec3 954;;;###autoload
31e1d920 955(defalias 'TeX-mode 'tex-mode)
6503cec3 956;;;###autoload
c3ce7bf4
RS
957(defalias 'plain-TeX-mode 'plain-tex-mode)
958;;;###autoload
31e1d920 959(defalias 'LaTeX-mode 'latex-mode)
869bff31 960
7229064d 961;;;###autoload
a3d80d4a 962(define-derived-mode plain-tex-mode tex-mode "TeX"
869bff31 963 "Major mode for editing files of input for plain TeX.
964Makes $ and } display the characters they match.
965Makes \" insert `` when it seems to be the beginning of a quotation,
966and '' when it appears to be the end; it inserts \" only after a \\.
967
968Use \\[tex-region] to run TeX on the current region, plus a \"header\"
969copied from the top of the file (containing macro definitions, etc.),
970running TeX under a special subshell. \\[tex-buffer] does the whole buffer.
971\\[tex-file] saves the buffer and then processes the file.
972\\[tex-print] prints the .dvi file made by any of these.
973\\[tex-view] previews the .dvi file made by any of these.
974\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
975
e6b0b773 976Use \\[tex-validate-buffer] to check buffer for paragraphs containing
869bff31 977mismatched $'s or braces.
978
979Special commands:
15ca8de7 980\\{plain-tex-mode-map}
869bff31 981
982Mode variables:
983tex-run-command
984 Command string used by \\[tex-region] or \\[tex-buffer].
985tex-directory
986 Directory in which to create temporary files for TeX jobs
987 run by \\[tex-region] or \\[tex-buffer].
988tex-dvi-print-command
989 Command string used by \\[tex-print] to print a .dvi file.
528415e7
RS
990tex-alt-dvi-print-command
991 Alternative command string used by \\[tex-print] (when given a prefix
992 argument) to print a .dvi file.
869bff31 993tex-dvi-view-command
994 Command string used by \\[tex-view] to preview a .dvi file.
995tex-show-queue-command
996 Command string used by \\[tex-show-print-queue] to show the print
997 queue that \\[tex-print] put your job on.
998
81c735c0
RS
999Entering Plain-tex mode runs the hook `text-mode-hook', then the hook
1000`tex-mode-hook', and finally the hook `plain-tex-mode-hook'. When the
1001special subshell is initiated, the hook `tex-shell-hook' is run."
a3d80d4a
SM
1002 (set (make-local-variable 'tex-command) tex-run-command)
1003 (set (make-local-variable 'tex-start-of-header) "%\\*\\*start of header")
1004 (set (make-local-variable 'tex-end-of-header) "%\\*\\*end of header")
1005 (set (make-local-variable 'tex-trailer) "\\bye\n"))
869bff31 1006
7229064d 1007;;;###autoload
a3d80d4a 1008(define-derived-mode latex-mode tex-mode "LaTeX"
869bff31 1009 "Major mode for editing files of input for LaTeX.
1010Makes $ and } display the characters they match.
1011Makes \" insert `` when it seems to be the beginning of a quotation,
1012and '' when it appears to be the end; it inserts \" only after a \\.
1013
1014Use \\[tex-region] to run LaTeX on the current region, plus the preamble
1015copied from the top of the file (containing \\documentstyle, etc.),
1016running LaTeX under a special subshell. \\[tex-buffer] does the whole buffer.
1017\\[tex-file] saves the buffer and then processes the file.
1018\\[tex-print] prints the .dvi file made by any of these.
1019\\[tex-view] previews the .dvi file made by any of these.
1020\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
1021
e6b0b773 1022Use \\[tex-validate-buffer] to check buffer for paragraphs containing
869bff31 1023mismatched $'s or braces.
1024
1025Special commands:
15ca8de7 1026\\{latex-mode-map}
869bff31 1027
1028Mode variables:
1029latex-run-command
1030 Command string used by \\[tex-region] or \\[tex-buffer].
1031tex-directory
1032 Directory in which to create temporary files for LaTeX jobs
1033 run by \\[tex-region] or \\[tex-buffer].
1034tex-dvi-print-command
1035 Command string used by \\[tex-print] to print a .dvi file.
528415e7
RS
1036tex-alt-dvi-print-command
1037 Alternative command string used by \\[tex-print] (when given a prefix
1038 argument) to print a .dvi file.
869bff31 1039tex-dvi-view-command
1040 Command string used by \\[tex-view] to preview a .dvi file.
1041tex-show-queue-command
1042 Command string used by \\[tex-show-print-queue] to show the print
1043 queue that \\[tex-print] put your job on.
1044
bed1b0c8 1045Entering Latex mode runs the hook `text-mode-hook', then
81c735c0
RS
1046`tex-mode-hook', and finally `latex-mode-hook'. When the special
1047subshell is initiated, `tex-shell-hook' is run."
a3d80d4a
SM
1048 (set (make-local-variable 'tex-command) latex-run-command)
1049 (set (make-local-variable 'tex-start-of-header)
1050 "\\\\document\\(style\\|class\\)")
1051 (set (make-local-variable 'tex-end-of-header) "\\\\begin\\s-*{document}")
d9cbee57 1052 (set (make-local-variable 'tex-trailer) "\\end{document}\n")
ab2c9f54
RS
1053 ;; A line containing just $$ is treated as a paragraph separator.
1054 ;; A line starting with $$ starts a paragraph,
1055 ;; but does not separate paragraphs if it has more stuff on it.
d6709b80 1056 (setq paragraph-start
a3d80d4a 1057 (concat "[ \t]*\\(\\$\\$\\|"
d6709b80
SM
1058 "\\\\[][]\\|"
1059 "\\\\" (regexp-opt (append
1060 (mapcar 'car latex-section-alist)
1061 '("begin" "label" "end"
1062 "item" "bibitem" "newline" "noindent"
1063 "newpage" "footnote" "marginpar"
1064 "parbox" "caption")) t)
1065 "\\>\\|\\\\[a-z]*" (regexp-opt '("space" "skip" "page") t)
dd459839 1066 "\\>\\)"))
d6709b80 1067 (setq paragraph-separate
8afe2ec6 1068 (concat "[\f%]\\|[ \t]*\\($\\|"
d6709b80
SM
1069 "\\\\[][]\\|"
1070 "\\\\" (regexp-opt (append
1071 (mapcar 'car latex-section-alist)
1072 '("begin" "label" "end" )) t)
1073 "\\>\\|\\\\\\(" (regexp-opt '("item" "bibitem" "newline"
1074 "noindent" "newpage" "footnote"
1075 "marginpar" "parbox" "caption"))
dd459839
SM
1076 "\\|\\$\\$\\|[a-z]*\\(space\\|skip\\|page[a-z]*\\)"
1077 "\\>\\)[ \t]*\\($\\|%\\)\\)"))
d6709b80
SM
1078 (set (make-local-variable 'imenu-create-index-function)
1079 'latex-imenu-create-index)
1080 (set (make-local-variable 'tex-face-alist) tex-latex-face-alist)
95a045bd 1081 (add-hook 'fill-nobreak-predicate 'latex-fill-nobreak-predicate nil t)
ea590e1c 1082 (set (make-local-variable 'indent-line-function) 'latex-indent)
dd459839 1083 (set (make-local-variable 'fill-indent-according-to-mode) t)
fb10ee4a
SM
1084 (add-hook 'completion-at-point-functions
1085 'latex-complete-data nil 'local)
d6709b80
SM
1086 (set (make-local-variable 'outline-regexp) latex-outline-regexp)
1087 (set (make-local-variable 'outline-level) 'latex-outline-level)
53c4fe47 1088 (set (make-local-variable 'forward-sexp-function) 'latex-forward-sexp)
a3d80d4a 1089 (set (make-local-variable 'skeleton-end-hook) nil))
869bff31 1090
bd2f2323 1091;;;###autoload
d6709b80 1092(define-derived-mode slitex-mode latex-mode "SliTeX"
869bff31 1093 "Major mode for editing files of input for SliTeX.
1094Makes $ and } display the characters they match.
1095Makes \" insert `` when it seems to be the beginning of a quotation,
1096and '' when it appears to be the end; it inserts \" only after a \\.
1097
1098Use \\[tex-region] to run SliTeX on the current region, plus the preamble
1099copied from the top of the file (containing \\documentstyle, etc.),
1100running SliTeX under a special subshell. \\[tex-buffer] does the whole buffer.
1101\\[tex-file] saves the buffer and then processes the file.
1102\\[tex-print] prints the .dvi file made by any of these.
1103\\[tex-view] previews the .dvi file made by any of these.
1104\\[tex-bibtex-file] runs bibtex on the file of the current buffer.
1105
e6b0b773 1106Use \\[tex-validate-buffer] to check buffer for paragraphs containing
869bff31 1107mismatched $'s or braces.
1108
1109Special commands:
15ca8de7 1110\\{slitex-mode-map}
869bff31 1111
1112Mode variables:
1113slitex-run-command
1114 Command string used by \\[tex-region] or \\[tex-buffer].
1115tex-directory
1116 Directory in which to create temporary files for SliTeX jobs
1117 run by \\[tex-region] or \\[tex-buffer].
1118tex-dvi-print-command
1119 Command string used by \\[tex-print] to print a .dvi file.
528415e7
RS
1120tex-alt-dvi-print-command
1121 Alternative command string used by \\[tex-print] (when given a prefix
1122 argument) to print a .dvi file.
869bff31 1123tex-dvi-view-command
1124 Command string used by \\[tex-view] to preview a .dvi file.
1125tex-show-queue-command
1126 Command string used by \\[tex-show-print-queue] to show the print
1127 queue that \\[tex-print] put your job on.
1128
81c735c0
RS
1129Entering SliTeX mode runs the hook `text-mode-hook', then the hook
1130`tex-mode-hook', then the hook `latex-mode-hook', and finally the hook
1131`slitex-mode-hook'. When the special subshell is initiated, the hook
1132`tex-shell-hook' is run."
869bff31 1133 (setq tex-command slitex-run-command)
d6709b80 1134 (setq tex-start-of-header "\\\\documentstyle{slides}\\|\\\\documentclass{slides}"))
869bff31 1135
1136(defun tex-common-initialization ()
822eddf4 1137 ;; Regexp isearch should accept newline and formfeed as whitespace.
d6709b80 1138 (set (make-local-variable 'search-whitespace-regexp) "[ \t\r\n\f]+")
64db2461 1139 ;; A line containing just $$ is treated as a paragraph separator.
d6709b80
SM
1140 (set (make-local-variable 'paragraph-start)
1141 "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$")
ab2c9f54
RS
1142 ;; A line starting with $$ starts a paragraph,
1143 ;; but does not separate paragraphs if it has more stuff on it.
d6709b80
SM
1144 (set (make-local-variable 'paragraph-separate)
1145 "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$[ \t]*$")
1146 (set (make-local-variable 'comment-start) "%")
1147 (set (make-local-variable 'comment-add) 1)
1148 (set (make-local-variable 'comment-start-skip)
5ae0d697 1149 "\\(\\(^\\|[^\\\n]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
d6709b80
SM
1150 (set (make-local-variable 'parse-sexp-ignore-comments) t)
1151 (set (make-local-variable 'compare-windows-whitespace)
1152 'tex-categorize-whitespace)
1153 (set (make-local-variable 'facemenu-add-face-function)
673c1168 1154 'tex-facemenu-add-face-function)
d6709b80
SM
1155 (set (make-local-variable 'facemenu-end-add-face) "}")
1156 (set (make-local-variable 'facemenu-remove-face-function) t)
1157 (set (make-local-variable 'font-lock-defaults)
7afecb99
SM
1158 '((tex-font-lock-keywords tex-font-lock-keywords-1
1159 tex-font-lock-keywords-2 tex-font-lock-keywords-3)
d6709b80
SM
1160 nil nil ((?$ . "\"")) nil
1161 ;; Who ever uses that anyway ???
bdbd9606
SM
1162 (font-lock-mark-block-function . mark-paragraph)
1163 (font-lock-syntactic-face-function
7afecb99
SM
1164 . tex-font-lock-syntactic-face-function)
1165 (font-lock-unfontify-region-function
1166 . tex-font-lock-unfontify-region)
1167 (font-lock-syntactic-keywords
1168 . tex-font-lock-syntactic-keywords)
1169 (parse-sexp-lookup-properties . t)))
95a045bd
SM
1170 ;; TABs in verbatim environments don't do what you think.
1171 (set (make-local-variable 'indent-tabs-mode) nil)
7afecb99 1172 ;; Other vars that should be buffer-local.
869bff31 1173 (make-local-variable 'tex-command)
1174 (make-local-variable 'tex-start-of-header)
1175 (make-local-variable 'tex-end-of-header)
1176 (make-local-variable 'tex-trailer))
1177
869bff31 1178(defun tex-categorize-whitespace (backward-limit)
1179 ;; compare-windows-whitespace is set to this.
1180 ;; This is basically a finite-state machine.
1181 ;; Returns a symbol telling how TeX would treat
1182 ;; the whitespace we are looking at: null, space, or par.
1183 (let ((category 'null)
1184 (not-finished t))
1185 (skip-chars-backward " \t\n\f" backward-limit)
1186 (while not-finished
1187 (cond ((looking-at "[ \t]+")
1188 (goto-char (match-end 0))
2be5fefb 1189 (if (eq category 'null)
869bff31 1190 (setq category 'space)))
1191 ((looking-at "\n")
2be5fefb 1192 (cond ((eq category 'newline)
869bff31 1193 (setq category 'par)
1194 (setq not-finished nil))
1195 (t
1196 (setq category 'newline) ;a strictly internal state
1197 (goto-char (match-end 0)))))
1198 ((looking-at "\f+")
1199 (setq category 'par)
1200 (setq not-finished nil))
1201 (t
1202 (setq not-finished nil))))
1203 (skip-chars-forward " \t\n\f")
2be5fefb 1204 (if (eq category 'newline)
869bff31 1205 'space ;TeX doesn't distinguish
1206 category)))
1207
1208(defun tex-insert-quote (arg)
1209 "Insert the appropriate quote marks for TeX.
08348502
RS
1210Inserts the value of `tex-open-quote' (normally ``) or `tex-close-quote'
1211\(normally '') depending on the context. With prefix argument, always
869bff31 1212inserts \" characters."
528415e7 1213 (interactive "*P")
95a045bd 1214 (if (or arg (memq (char-syntax (preceding-char)) '(?/ ?\\))
014e29b9 1215 (eq (get-text-property (point) 'face) 'tex-verbatim)
95a045bd
SM
1216 (save-excursion
1217 (backward-char (length tex-open-quote))
1218 (when (or (looking-at (regexp-quote tex-open-quote))
1219 (looking-at (regexp-quote tex-close-quote)))
1220 (delete-char (length tex-open-quote))
1221 t)))
869bff31 1222 (self-insert-command (prefix-numeric-value arg))
d1218e3e 1223 (insert (if (memq (char-syntax (preceding-char)) '(?\( ?> ?\s))
95a045bd 1224 tex-open-quote tex-close-quote))))
869bff31 1225
e6b0b773
MR
1226(defun tex-validate-buffer ()
1227 "Check current buffer for paragraphs containing mismatched braces or $s.
bbd93e41 1228Their positions are recorded in the buffer `*Occur*'.
e6b0b773
MR
1229To find a particular invalidity from `*Occur*', switch to that buffer
1230and type C-c C-c or click with mouse-2
1231on the line for the invalidity you want to see."
869bff31 1232 (interactive)
bbd93e41
RS
1233 (let ((buffer (current-buffer))
1234 (prevpos (point-min))
e6b0b773
MR
1235 (linenum nil)
1236 (num-matches 0))
bbd93e41
RS
1237 (with-output-to-temp-buffer "*Occur*"
1238 (princ "Mismatches:\n")
a3d80d4a 1239 (with-current-buffer standard-output
bbd93e41 1240 (occur-mode)
52ab062c
CW
1241 ;; This won't actually work...Really, this whole thing should
1242 ;; be rewritten instead of being a hack on top of occur.
1243 (setq occur-revert-arguments (list nil 0 (list buffer))))
bbd93e41
RS
1244 (save-excursion
1245 (goto-char (point-max))
0a4daff5
GM
1246 ;; Do a little shimmy to place point at the end of the last
1247 ;; "real" paragraph. Need to avoid validating across an \end,
1248 ;; because that blows up latex-forward-sexp.
1249 (backward-paragraph)
1250 (forward-paragraph)
1251 (while (not (bobp))
bbd93e41 1252 ;; Scan the previous paragraph for invalidities.
0a4daff5
GM
1253 (backward-paragraph)
1254 (save-excursion
1255 (or (tex-validate-region (point) (save-excursion
1256 (forward-paragraph)
1257 (point)))
1258 (let ((end (line-beginning-position 2))
bbd93e41
RS
1259 start tem)
1260 (beginning-of-line)
1261 (setq start (point))
1262 ;; Keep track of line number as we scan,
1263 ;; in a cumulative fashion.
1264 (if linenum
0a4daff5
GM
1265 (setq linenum (- linenum
1266 (count-lines prevpos (point))))
bbd93e41
RS
1267 (setq linenum (1+ (count-lines 1 start))))
1268 (setq prevpos (point))
bed1b0c8 1269 ;; Mention this mismatch in *Occur*.
bbd93e41 1270 ;; Since we scan from end of buffer to beginning,
e6b0b773 1271 ;; add each mismatch at the beginning of *Occur*.
bbd93e41
RS
1272 (save-excursion
1273 (setq tem (point-marker))
1274 (set-buffer standard-output)
1275 (goto-char (point-min))
1276 ;; Skip "Mismatches:" header line.
1277 (forward-line 1)
e6b0b773 1278 (setq num-matches (1+ num-matches))
bbd93e41 1279 (insert-buffer-substring buffer start end)
e6b0b773
MR
1280 (let (text-beg (text-end (point-marker)))
1281 (forward-char (- start end))
1282 (setq text-beg (point-marker))
1283 (insert (format "%3d: " linenum))
a865de85
EZ
1284 (add-text-properties
1285 text-beg (- text-end 1)
1286 '(mouse-face highlight
0a4daff5
GM
1287 help-echo
1288 "mouse-2: go to this invalidity"))
1598a961 1289 (put-text-property text-beg (- text-end 1)
0a4daff5 1290 'occur-target tem))))))))
bdbd9606 1291 (with-current-buffer standard-output
003274a0
JPW
1292 (let ((no-matches (zerop num-matches)))
1293 (if no-matches
1294 (insert "None!\n"))
32226619 1295 (if (called-interactively-p 'interactive)
f04232c3
JPW
1296 (message (cond (no-matches "No mismatches found")
1297 ((= num-matches 1) "1 mismatch found")
1298 (t "%d mismatches found"))
1299 num-matches)))))))
869bff31 1300
1301(defun tex-validate-region (start end)
1302 "Check for mismatched braces or $'s in region.
1303Returns t if no mismatches. Returns nil and moves point to suspect
1304area if a mismatch is found."
1305 (interactive "r")
1306 (let ((failure-point nil) (max-possible-sexps (- end start)))
1307 (save-excursion
1308 (condition-case ()
1309 (save-restriction
1310 (narrow-to-region start end)
2ed2806c 1311 ;; First check that the open and close parens balance in numbers.
869bff31 1312 (goto-char start)
0a4daff5
GM
1313 (while (and (not (eobp))
1314 (<= 0 (setq max-possible-sexps
1315 (1- max-possible-sexps))))
2ed2806c
KH
1316 (forward-sexp 1))
1317 ;; Now check that like matches like.
1318 (goto-char start)
35dccc62
SM
1319 (while (re-search-forward "\\s(" nil t)
1320 (save-excursion
1321 (let ((pos (match-beginning 0)))
1322 (goto-char pos)
09b33024 1323 (skip-chars-backward "\\\\") ; escaped parens
2ed2806c 1324 (forward-sexp 1)
35dccc62
SM
1325 (or (eq (preceding-char) (cdr (syntax-after pos)))
1326 (eq (char-after pos) (cdr (syntax-after (1- (point)))))
1327 (error "Mismatched parentheses"))))))
869bff31 1328 (error
bed1b0c8
RS
1329 (skip-syntax-forward " .>")
1330 (setq failure-point (point)))))
bdbd9606
SM
1331 (if failure-point (goto-char failure-point))
1332 (not failure-point)))
869bff31 1333
1334(defun tex-terminate-paragraph (inhibit-validation)
1335 "Insert two newlines, breaking a paragraph for TeX.
81c735c0 1336Check for mismatched braces or $s in paragraph being terminated.
869bff31 1337A prefix arg inhibits the checking."
528415e7 1338 (interactive "*P")
869bff31 1339 (or inhibit-validation
3cfff67b
GM
1340 (save-excursion
1341 ;; For the purposes of this, a "paragraph" is a block of text
1342 ;; wherein all the brackets etc are expected to be balanced. It
1343 ;; may start after a blank line (ie a "proper" paragraph), or
1344 ;; a begin{} or end{} block, etc.
1345 (tex-validate-region
1346 (save-excursion
1347 (backward-paragraph)
1348 (point))
1349 (point)))
1350 (message "Paragraph being closed appears to contain a mismatch"))
1351 (insert "\n\n"))
869bff31 1352
7afecb99 1353(define-skeleton tex-insert-braces
869bff31 1354 "Make a pair of braces and be poised to type inside of them."
7afecb99
SM
1355 nil
1356 ?\{ _ ?})
869bff31 1357
9bd4f69c
RS
1358;; This function is used as the value of fill-nobreak-predicate
1359;; in LaTeX mode. Its job is to prevent line-breaking inside
1360;; of a \verb construct.
1361(defun latex-fill-nobreak-predicate ()
7afecb99
SM
1362 (save-excursion
1363 (skip-chars-backward " ")
1364 ;; Don't break after \ since `\ ' has special meaning.
1365 (or (and (not (bobp)) (memq (char-syntax (char-before)) '(?\\ ?/)))
1366 (let ((opoint (point))
1367 inside)
1368 (beginning-of-line)
1369 (while (re-search-forward "\\\\verb\\(.\\)" opoint t)
1370 (unless (re-search-forward (regexp-quote (match-string 1)) opoint t)
1371 (setq inside t)))
1372 inside))))
9bd4f69c 1373
53c4fe47
SM
1374(defvar latex-block-default "enumerate")
1375
8084f5d8 1376(defvar latex-block-args-alist
dd166d5f
SM
1377 '(("array" nil ?\{ (skeleton-read "Format: ") ?\})
1378 ("tabular" nil ?\{ (skeleton-read "Format: ") ?\})
1379 ("minipage" nil ?\{ (skeleton-read "Size: ") ?\})
1380 ("picture" nil ?\( (skeleton-read "SizeX,SizeY: ") ?\))
1381 ;; FIXME: This is right for Prosper, but not for seminar.
1382 ;; ("slide" nil ?\{ (skeleton-read "Title: ") ?\})
1383 )
8084f5d8
SM
1384 "Skeleton element to use for arguments to particular environments.
1385Every element of the list has the form (NAME . SKEL-ELEM) where NAME is
1386the name of the environment and SKEL-ELEM is an element to use in
1387a skeleton (see `skeleton-insert').")
1388
1389(defvar latex-block-body-alist
1390 '(("enumerate" nil '(latex-insert-item) > _)
1391 ("itemize" nil '(latex-insert-item) > _)
dd166d5f
SM
1392 ("table" nil "\\caption{" > (skeleton-read "Caption: ") "}" > \n
1393 '(if (and (boundp 'reftex-mode) reftex-mode) (reftex-label "table"))
1394 \n _)
1395 ("figure" nil > _ \n "\\caption{" > (skeleton-read "Caption: ") "}" > \n
1396 '(if (and (boundp 'reftex-mode) reftex-mode) (reftex-label "table"))))
8084f5d8
SM
1397 "Skeleton element to use for the body of particular environments.
1398Every element of the list has the form (NAME . SKEL-ELEM) where NAME is
1399the name of the environment and SKEL-ELEM is an element to use in
1400a skeleton (see `skeleton-insert').")
1401
15ca8de7 1402;; Like tex-insert-braces, but for LaTeX.
7afecb99
SM
1403(defalias 'tex-latex-block 'latex-insert-block)
1404(define-skeleton latex-insert-block
8a591d52 1405 "Create a matching pair of lines \\begin{NAME} and \\end{NAME} at point.
869bff31 1406Puts point on a blank line between them."
53c4fe47
SM
1407 (let ((choice (completing-read (format "LaTeX block name [%s]: "
1408 latex-block-default)
95a045bd 1409 (append latex-block-names
7afecb99 1410 latex-standard-block-names)
53c4fe47
SM
1411 nil nil nil nil latex-block-default)))
1412 (setq latex-block-default choice)
7afecb99 1413 (unless (or (member choice latex-standard-block-names)
53c4fe47
SM
1414 (member choice latex-block-names))
1415 ;; Remember new block names for later completion.
1416 (push choice latex-block-names))
1417 choice)
95a045bd 1418 \n "\\begin{" str "}"
8084f5d8 1419 (cdr (assoc str latex-block-args-alist))
dd166d5f
SM
1420 > \n (or (cdr (assoc str latex-block-body-alist)) '(nil > _))
1421 (unless (bolp) '\n)
95a045bd 1422 "\\end{" str "}" > \n)
53c4fe47 1423
ea590e1c
SM
1424(define-skeleton latex-insert-item
1425 "Insert a \item macro."
1426 nil
15ca8de7 1427 \n "\\item " >)
ea590e1c 1428
53c4fe47 1429\f
eff77808
SM
1430;;;; LaTeX completion.
1431
1432(defvar latex-complete-bibtex-cache nil)
1433
1434(defun latex-string-prefix-p (str1 str2)
1435 (eq t (compare-strings str1 nil nil str2 0 (length str1))))
1436
1437(defvar bibtex-reference-key)
1438(declare-function reftex-get-bibfile-list "reftex-cite.el" ())
1439
1440(defun latex-complete-bibtex-keys ()
1441 (when (bound-and-true-p reftex-mode)
1442 (lambda (key pred action)
1443 (let ((re (concat "^[ \t]*@\\([a-zA-Z]+\\)[ \t\n]*\\([{(][ \t\n]*\\)"
1444 (regexp-quote key)))
1445 (files (reftex-get-bibfile-list))
1446 keys)
1447 (if (and (eq (car latex-complete-bibtex-cache)
1448 (reftex-get-bibfile-list))
1449 (latex-string-prefix-p (nth 1 latex-complete-bibtex-cache)
1450 key))
1451 ;; Use the cache.
1452 (setq keys (nth 2 latex-complete-bibtex-cache))
1453 (dolist (file files)
1454 (with-current-buffer (find-file-noselect file)
1455 (goto-char (point-min))
1456 (while (re-search-forward re nil t)
1457 (goto-char (match-end 2))
1458 (when (and (not (member-ignore-case (match-string 1)
1459 '("c" "comment" "string")))
1460 (looking-at bibtex-reference-key))
1461 (push (match-string-no-properties 0) keys)))))
1462 ;; Fill the cache.
1463 (set (make-local-variable 'latex-complete-bibtex-cache)
1464 (list files key keys)))
1465 (complete-with-action action keys key pred)))))
1466
1467(defun latex-complete-envnames ()
1468 (append latex-block-names latex-standard-block-names))
1469
1470(defun latex-complete-refkeys ()
1471 (when (boundp 'reftex-docstruct-symbol)
1472 (symbol-value reftex-docstruct-symbol)))
1473
1474(defvar latex-complete-alist
1475 ;; TODO: Add \begin, \end, \ref, ...
1476 '(("\\`\\\\\\(short\\)?cite\\'" . latex-complete-bibtex-keys)
1477 ("\\`\\\\\\(begin\\|end\\)\\'" . latex-complete-envnames)
1478 ("\\`\\\\[vf]?ref\\'" . latex-complete-refkeys)))
1479
1480(defun latex-complete-data ()
1481 "Get completion-data at point."
1482 (save-excursion
1483 (let ((pt (point)))
1484 (skip-chars-backward "^ {}\n\t\\\\")
1485 (case (char-before)
1486 ((nil ?\s ?\n ?\t ?\}) nil)
1487 (?\\
1488 ;; TODO: Complete commands.
1489 nil)
1490 (?\{
1491 ;; Complete args to commands.
1492 (let* ((cmd
1493 (save-excursion
1494 (forward-char -1)
1495 (skip-chars-backward " \n")
1496 (buffer-substring (point)
1497 (progn
1498 (skip-chars-backward "a-zA-Z@*")
1499 (let ((n (skip-chars-backward "\\\\")))
1500 (forward-char (* 2 (/ n 2))))
1501 (point)))))
1502 (start (point))
1503 (_ (progn (goto-char pt) (skip-chars-backward "^," start)))
1504 (comp-beg (point))
1505 (_ (progn (goto-char pt) (skip-chars-forward "^, {}\n\t\\\\")))
1506 (comp-end (point))
1507 (table
1508 (funcall
1509 (let ((f (lambda () t)))
1510 (dolist (comp latex-complete-alist)
1511 (if (string-match (car comp) cmd)
1512 (setq f (cdr comp))))
1513 f))))
1514 (if (eq table t)
1515 ;; Unknown command.
1516 nil
1517 (list comp-beg comp-end table))))))))
1518
53c4fe47
SM
1519;;;;
1520;;;; LaTeX syntax navigation
1521;;;;
869bff31 1522
5e56fb53
SM
1523(defmacro tex-search-noncomment (&rest body)
1524 "Execute BODY as long as it return non-nil and point is in a comment.
1525Return the value returned by the last execution of BODY."
1526 (declare (debug t))
1527 (let ((res-sym (make-symbol "result")))
1528 `(let (,res-sym)
1529 (while
1530 (and (setq ,res-sym (progn ,@body))
1531 (save-excursion (skip-chars-backward "^\n%") (not (bolp)))))
1532 ,res-sym)))
1533
869bff31 1534(defun tex-last-unended-begin ()
81c735c0 1535 "Leave point at the beginning of the last `\\begin{...}' that is unended."
95a045bd 1536 (condition-case nil
5e56fb53
SM
1537 (while (and (tex-search-noncomment
1538 (re-search-backward "\\\\\\(begin\\|end\\)\\s *{"))
95a045bd
SM
1539 (looking-at "\\\\end"))
1540 (tex-last-unended-begin))
1541 (search-failed (error "Couldn't find unended \\begin"))))
869bff31 1542
53c4fe47 1543(defun tex-next-unmatched-end ()
0a4daff5 1544 "Leave point at the end of the next `\\end' that is unmatched."
5e56fb53
SM
1545 (while (and (tex-search-noncomment
1546 (re-search-forward "\\\\\\(begin\\|end\\)\\s *{[^}]+}"))
ea590e1c
SM
1547 (save-excursion (goto-char (match-beginning 0))
1548 (looking-at "\\\\begin")))
53c4fe47
SM
1549 (tex-next-unmatched-end)))
1550
09b33024
GM
1551(defun tex-next-unmatched-eparen (otype)
1552 "Leave point after the next unmatched escaped closing parenthesis.
2fb34c68 1553The string OTYPE is an opening parenthesis type: `(', `{', or `['."
09b33024
GM
1554 (condition-case nil
1555 (let ((ctype (char-to-string (cdr (aref (syntax-table)
1556 (string-to-char otype))))))
1557 (while (and (tex-search-noncomment
1558 (re-search-forward (format "\\\\[%s%s]" ctype otype)))
1559 (save-excursion
1560 (goto-char (match-beginning 0))
1561 (looking-at (format "\\\\%s" (regexp-quote otype)))))
1562 (tex-next-unmatched-eparen otype)))
1563 (wrong-type-argument (error "Unknown opening parenthesis type: %s" otype))
1564 (search-failed (error "Couldn't find closing escaped paren"))))
1565
2fb34c68
GM
1566(defun tex-last-unended-eparen (ctype)
1567 "Leave point at the start of the last unended escaped opening parenthesis.
1568The string CTYPE is a closing parenthesis type: `)', `}', or `]'."
1569 (condition-case nil
1570 (let ((otype (char-to-string (cdr (aref (syntax-table)
1571 (string-to-char ctype))))))
1572 (while (and (tex-search-noncomment
1573 (re-search-backward (format "\\\\[%s%s]" ctype otype)))
1574 (looking-at (format "\\\\%s" (regexp-quote ctype))))
1575 (tex-last-unended-eparen ctype)))
1576 (wrong-type-argument (error "Unknown opening parenthesis type: %s" ctype))
1577 (search-failed (error "Couldn't find unended escaped paren"))))
1578
6a900cf1
ER
1579(defun tex-goto-last-unclosed-latex-block ()
1580 "Move point to the last unclosed \\begin{...}.
1581Mark is left at original location."
1582 (interactive)
1583 (let ((spot))
1584 (save-excursion
95a045bd 1585 (tex-last-unended-begin)
6a900cf1
ER
1586 (setq spot (point)))
1587 (push-mark)
1588 (goto-char spot)))
1589
fa9a8f78
MR
1590(defvar latex-handle-escaped-parens t)
1591
2fb34c68
GM
1592;; Don't think this one actually _needs_ (for the purposes of
1593;; tex-mode) to handle escaped parens.
fa9a8f78 1594;; Does not handle escaped parens when latex-handle-escaped-parens is nil.
53c4fe47 1595(defun latex-backward-sexp-1 ()
2fb34c68 1596 "Like (backward-sexp 1) but aware of multi-char elements and escaped parens."
53c4fe47
SM
1597 (let ((pos (point))
1598 (forward-sexp-function))
1599 (backward-sexp 1)
fa9a8f78
MR
1600 (cond ((looking-at
1601 (if latex-handle-escaped-parens
1602 "\\\\\\(begin\\>\\|[[({]\\)"
1603 "\\\\begin\\>"))
2fb34c68
GM
1604 (signal 'scan-error
1605 (list "Containing expression ends prematurely"
1606 (point) (prog1 (point) (goto-char pos)))))
fa9a8f78
MR
1607 ((and latex-handle-escaped-parens
1608 (looking-at "\\\\\\([])}]\\)"))
2fb34c68
GM
1609 (tex-last-unended-eparen (match-string 1)))
1610 ((eq (char-after) ?{)
1611 (let ((newpos (point)))
1612 (when (ignore-errors (backward-sexp 1) t)
1613 (if (or (looking-at "\\\\end\\>")
1614 ;; In case the \\ ends a verbatim section.
1615 (and (looking-at "end\\>") (eq (char-before) ?\\)))
1616 (tex-last-unended-begin)
1617 (goto-char newpos))))))))
53c4fe47 1618
09b33024
GM
1619;; Note this does not handle things like mismatched brackets inside
1620;; begin/end blocks.
2fb34c68
GM
1621;; Needs to handle escaped parens for tex-validate-*.
1622;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2007-09/msg00038.html
fa9a8f78 1623;; Does not handle escaped parens when latex-handle-escaped-parens is nil.
53c4fe47 1624(defun latex-forward-sexp-1 ()
09b33024 1625 "Like (forward-sexp 1) but aware of multi-char elements and escaped parens."
53c4fe47
SM
1626 (let ((pos (point))
1627 (forward-sexp-function))
1628 (forward-sexp 1)
1629 (let ((newpos (point)))
1630 (skip-syntax-backward "/w")
1631 (cond
1632 ((looking-at "\\\\end\\>")
1633 (signal 'scan-error
1634 (list "Containing expression ends prematurely"
1635 (point)
1636 (prog1
1637 (progn (ignore-errors (forward-sexp 2)) (point))
1638 (goto-char pos)))))
1639 ((looking-at "\\\\begin\\>")
1640 (goto-char (match-end 0))
1641 (tex-next-unmatched-end))
2fb34c68
GM
1642 ;; A better way to handle this, \( .. \) etc, is probably to
1643 ;; temporarily change the syntax of the \ in \( to punctuation.
fa9a8f78
MR
1644 ((and latex-handle-escaped-parens
1645 (looking-back "\\\\[])}]"))
09b33024
GM
1646 (signal 'scan-error
1647 (list "Containing expression ends prematurely"
1648 (- (point) 2) (prog1 (point)
1649 (goto-char pos)))))
fa9a8f78
MR
1650 ((and latex-handle-escaped-parens
1651 (looking-back "\\\\\\([({[]\\)"))
09b33024 1652 (tex-next-unmatched-eparen (match-string 1)))
53c4fe47
SM
1653 (t (goto-char newpos))))))
1654
1655(defun latex-forward-sexp (&optional arg)
09b33024 1656 "Like `forward-sexp' but aware of multi-char elements and escaped parens."
53c4fe47
SM
1657 (interactive "P")
1658 (unless arg (setq arg 1))
1659 (let ((pos (point)))
1660 (condition-case err
1661 (while (/= arg 0)
1662 (setq arg
1663 (if (> arg 0)
1664 (progn (latex-forward-sexp-1) (1- arg))
1665 (progn (latex-backward-sexp-1) (1+ arg)))))
1666 (scan-error
1667 (goto-char pos)
1668 (signal (car err) (cdr err))))))
1669
ea590e1c
SM
1670(defun latex-syntax-after ()
1671 "Like (char-syntax (char-after)) but aware of multi-char elements."
15ca8de7 1672 (if (looking-at "\\\\end\\>") ?\) (char-syntax (following-char))))
ea590e1c
SM
1673
1674(defun latex-skip-close-parens ()
1675 "Like (skip-syntax-forward \" )\") but aware of multi-char elements."
1676 (let ((forward-sexp-function nil))
1677 (while (progn (skip-syntax-forward " )")
1678 (looking-at "\\\\end\\>"))
1679 (forward-sexp 2))))
1680
1681(defun latex-down-list ()
1682 "Like (down-list 1) but aware of multi-char elements."
1683 (forward-comment (point-max))
1684 (let ((forward-sexp-function nil))
1685 (if (not (looking-at "\\\\begin\\>"))
1686 (down-list 1)
1687 (forward-sexp 1)
1688 ;; Skip arguments.
7afecb99
SM
1689 (while (looking-at "[ \t]*[[{(]")
1690 (with-syntax-table tex-mode-syntax-table
1691 (forward-sexp))))))
ea590e1c 1692
7afecb99
SM
1693(defalias 'tex-close-latex-block 'latex-close-block)
1694(define-skeleton latex-close-block
1695 "Create an \\end{...} to match the last unclosed \\begin{...}."
1696 (save-excursion
1697 (tex-last-unended-begin)
1698 (if (not (looking-at "\\\\begin\\(\\s *{[^}\n]*}\\)")) '("{" _ "}")
1699 (match-string 1)))
1700 \n "\\end" str > \n)
1701
1702(define-skeleton latex-split-block
1703 "Split the enclosing environment by inserting \\end{..}\\begin{..} at point."
1704 (save-excursion
1705 (tex-last-unended-begin)
1706 (if (not (looking-at "\\\\begin\\(\\s *{[^}\n]*}\\)")) '("{" _ "}")
1707 (prog1 (match-string 1)
1708 (goto-char (match-end 1))
1709 (setq v1 (buffer-substring (point)
1710 (progn
1711 (while (looking-at "[ \t]*[[{]")
1712 (forward-sexp 1))
1713 (point)))))))
1714 \n "\\end" str > \n _ \n "\\begin" str v1 > \n)
15ca8de7
SM
1715
1716(defconst tex-discount-args-cmds
1717 '("begin" "end" "input" "special" "cite" "ref" "include" "includeonly"
1718 "documentclass" "usepackage" "label")
1719 "TeX commands whose arguments should not be counted as text.")
1720
1721(defun tex-count-words (begin end)
1722 "Count the number of words in the buffer."
1723 (interactive
1724 (if (and transient-mark-mode mark-active)
1725 (list (region-beginning) (region-end))
1726 (list (point-min) (point-max))))
1727 ;; TODO: skip comments and math and maybe some environments.
1728 (save-excursion
1729 (goto-char begin)
1730 (let ((count 0))
1731 (while (and (< (point) end) (re-search-forward "\\<" end t))
1732 (if (not (eq (char-syntax (preceding-char)) ?/))
1733 (progn
1734 ;; Don't count single-char words.
1735 (unless (looking-at ".\\>") (incf count))
1736 (forward-char 1))
1737 (let ((cmd
1738 (buffer-substring-no-properties
1739 (point) (progn (when (zerop (skip-chars-forward "a-zA-Z@"))
1740 (forward-char 1))
1741 (point)))))
1742 (when (member cmd tex-discount-args-cmds)
1743 (skip-chars-forward "*")
1744 (forward-comment (point-max))
1745 (when (looking-at "\\[")
1746 (forward-sexp 1)
1747 (forward-comment (point-max)))
1748 (if (not (looking-at "{"))
1749 (forward-char 1)
1750 (forward-sexp 1))))))
1751 (message "%s words" count))))
b781e739
SS
1752
1753
869bff31 1754\f
1755;;; Invoking TeX in an inferior shell.
1756
15ca8de7
SM
1757;; Why use a shell instead of running TeX directly? Because if TeX
1758;; gets stuck, the user can switch to the shell window and type at it.
869bff31 1759
15ca8de7 1760;; The utility functions:
869bff31 1761
bdbd9606 1762(define-derived-mode tex-shell shell-mode "TeX-Shell"
3f2c97ea
SM
1763 (set (make-local-variable 'compilation-parse-errors-function)
1764 'tex-compilation-parse-errors)
bdbd9606
SM
1765 (compilation-shell-minor-mode t))
1766
d974af30 1767;;;###autoload
869bff31 1768(defun tex-start-shell ()
d6709b80
SM
1769 (with-current-buffer
1770 (make-comint
1771 "tex-shell"
07c16ec4 1772 (or tex-shell-file-name (getenv "ESHELL") shell-file-name)
4042dc25 1773 nil
053be11a 1774 ;; Specify an interactive shell, to make sure it prompts.
4042dc25 1775 "-i")
528415e7
RS
1776 (let ((proc (get-process "tex-shell")))
1777 (set-process-sentinel proc 'tex-shell-sentinel)
003274a0 1778 (set-process-query-on-exit-flag proc nil)
bdbd9606 1779 (tex-shell)
528415e7 1780 (while (zerop (buffer-size))
51b2c841
RS
1781 (sleep-for 1)))))
1782
033306e3
RS
1783(defun tex-feed-input ()
1784 "Send input to the tex shell process.
1785In the tex buffer this can be used to continue an interactive tex run.
bed1b0c8 1786In the tex shell buffer this command behaves like `comint-send-input'."
033306e3 1787 (interactive)
b781e739 1788 (set-buffer (tex-shell-buf))
033306e3
RS
1789 (comint-send-input)
1790 (tex-recenter-output-buffer nil))
1791
51b2c841
RS
1792(defun tex-display-shell ()
1793 "Make the TeX shell buffer visible in a window."
b781e739 1794 (display-buffer (tex-shell-buf))
51b2c841 1795 (tex-recenter-output-buffer nil))
528415e7
RS
1796
1797(defun tex-shell-sentinel (proc msg)
1798 (cond ((null (buffer-name (process-buffer proc)))
1799 ;; buffer killed
1800 (set-process-buffer proc nil)
1801 (tex-delete-last-temp-files))
1802 ((memq (process-status proc) '(signal exit))
1803 (tex-delete-last-temp-files))))
1804
1805(defun tex-set-buffer-directory (buffer directory)
869bff31 1806 "Set BUFFER's default directory to be DIRECTORY."
1807 (setq directory (file-name-as-directory (expand-file-name directory)))
1808 (if (not (file-directory-p directory))
1809 (error "%s is not a directory" directory)
9a529312 1810 (with-current-buffer buffer
869bff31 1811 (setq default-directory directory))))
1812
30803a05
RS
1813(defvar tex-send-command-modified-tick 0)
1814(make-variable-buffer-local 'tex-send-command-modified-tick)
1815
bdbd9606 1816(defun tex-shell-proc ()
b781e739 1817 (or (tex-shell-running) (error "No TeX subprocess")))
bdbd9606
SM
1818(defun tex-shell-buf ()
1819 (process-buffer (tex-shell-proc)))
b781e739
SS
1820(defun tex-shell-buf-no-error ()
1821 (let ((proc (tex-shell-running)))
1822 (and proc (process-buffer proc))))
bdbd9606 1823
528415e7 1824(defun tex-send-command (command &optional file background)
4cdc1d4b 1825 "Send COMMAND to TeX shell process, substituting optional FILE for *.
8241d7b9
ER
1826Do this in background if optional BACKGROUND is t. If COMMAND has no *,
1827FILE will be appended, preceded by a blank, to COMMAND. If FILE is nil, no
1828substitution will be made in COMMAND. COMMAND can be any expression that
460e1b7d
RS
1829evaluates to a command string.
1830
1831Return the process in which TeX is running."
528415e7
RS
1832 (save-excursion
1833 (let* ((cmd (eval command))
bdbd9606 1834 (proc (tex-shell-proc))
64db2461 1835 (buf (process-buffer proc))
4f45adda 1836 (star (string-match "\\*" cmd))
4cdc1d4b
RS
1837 (string
1838 (concat
8ca66348
SM
1839 (if (null file)
1840 cmd
1841 (if (file-name-absolute-p file)
1842 (setq file (convert-standard-filename file)))
1843 (if star (concat (substring cmd 0 star)
1844 (shell-quote-argument file)
1845 (substring cmd (1+ star)))
1846 (concat cmd " " (shell-quote-argument file))))
4cdc1d4b 1847 (if background "&" ""))))
64db2461
RS
1848 ;; Switch to buffer before checking for subproc output in it.
1849 (set-buffer buf)
30803a05
RS
1850 ;; If text is unchanged since previous tex-send-command,
1851 ;; we haven't got any output. So wait for output now.
64db2461 1852 (if (= (buffer-modified-tick buf) tex-send-command-modified-tick)
30803a05 1853 (accept-process-output proc))
4cdc1d4b
RS
1854 (goto-char (process-mark proc))
1855 (insert string)
30803a05 1856 (comint-send-input)
460e1b7d
RS
1857 (setq tex-send-command-modified-tick (buffer-modified-tick buf))
1858 proc)))
528415e7 1859
a15849cb
RS
1860(defun tex-delete-last-temp-files (&optional not-all)
1861 "Delete any junk files from last temp file.
1862If NOT-ALL is non-nil, save the `.dvi' file."
528415e7
RS
1863 (if tex-last-temp-file
1864 (let* ((dir (file-name-directory tex-last-temp-file))
adf6b7f9
KH
1865 (list (and (file-directory-p dir)
1866 (file-name-all-completions
02fd229c
RS
1867 (file-name-sans-extension
1868 (file-name-nondirectory tex-last-temp-file))
1869 dir))))
adf6b7f9 1870 (while list
a15849cb
RS
1871 (if not-all
1872 (and
1873 ;; If arg is non-nil, don't delete the .dvi file.
1874 (not (string-match "\\.dvi$" (car list)))
1875 (delete-file (concat dir (car list))))
1876 (delete-file (concat dir (car list))))
528415e7
RS
1877 (setq list (cdr list))))))
1878
99621a14 1879(add-hook 'kill-emacs-hook 'tex-delete-last-temp-files)
869bff31 1880
75035a80
SM
1881;;
1882;; Machinery to guess the command that the user wants to execute.
1883;;
1884
1885(defvar tex-compile-history nil)
1886
1887(defvar tex-input-files-re
1888 (eval-when-compile
1889 (concat "\\." (regexp-opt '("tex" "texi" "texinfo"
1890 "bbl" "ind" "sty" "cls") t)
1891 ;; Include files with no dots (for directories).
1892 "\\'\\|\\`[^.]+\\'")))
1893
1894(defcustom tex-use-reftex t
1895 "If non-nil, use RefTeX's list of files to determine what command to use."
18a8c773
LK
1896 :type 'boolean
1897 :group 'tex)
75035a80
SM
1898
1899(defvar tex-compile-commands
1900 '(((concat "pdf" tex-command
bf4ec222 1901 " " (if (< 0 (length tex-start-commands))
d18fc930 1902 (shell-quote-argument tex-start-commands)) " %f")
75035a80
SM
1903 t "%r.pdf")
1904 ((concat tex-command
bf4ec222 1905 " " (if (< 0 (length tex-start-commands))
d18fc930 1906 (shell-quote-argument tex-start-commands)) " %f")
75035a80
SM
1907 t "%r.dvi")
1908 ("xdvi %r &" "%r.dvi")
68a2af7a 1909 ("\\doc-view \"%r.pdf\"" "%r.pdf")
29a47b89
SM
1910 ("xpdf %r.pdf &" "%r.pdf")
1911 ("gv %r.ps &" "%r.ps")
1912 ("yap %r &" "%r.dvi")
75035a80 1913 ("advi %r &" "%r.dvi")
29a47b89 1914 ("gv %r.pdf &" "%r.pdf")
75035a80
SM
1915 ("bibtex %r" "%r.aux" "%r.bbl")
1916 ("makeindex %r" "%r.idx" "%r.ind")
1917 ("texindex %r.??")
1918 ("dvipdfm %r" "%r.dvi" "%r.pdf")
1919 ("dvipdf %r" "%r.dvi" "%r.pdf")
dd166d5f 1920 ("dvips -o %r.ps %r" "%r.dvi" "%r.ps")
e70ff1af 1921 ("ps2pdf %r.ps" "%r.ps" "%r.pdf")
75035a80
SM
1922 ("lpr %r.ps" "%r.ps"))
1923 "List of commands for `tex-compile'.
1924Each element should be of the form (FORMAT IN OUT) where
1925FORMAT is an expression that evaluates to a string that can contain
1926 - `%r' the main file name without extension.
1927 - `%f' the main file name.
1928IN can be either a string (with the same % escapes in it) indicating
1929 the name of the input file, or t to indicate that the input is all
1930 the TeX files of the document, or nil if we don't know.
1931OUT describes the output file and is either a %-escaped string
1932 or nil to indicate that there is no output file.")
1933
8084f5d8
SM
1934;; defsubst* gives better byte-code than defsubst.
1935(defsubst* tex-string-prefix-p (str1 str2)
1936 "Return non-nil if STR1 is a prefix of STR2"
1937 (eq t (compare-strings str2 nil (length str1) str1 nil nil)))
1938
dd459839
SM
1939(defun tex-guess-main-file (&optional all)
1940 "Find a likely `tex-main-file'.
1941Looks for hints in other buffers in the same directory or in
8084f5d8
SM
1942ALL other buffers. If ALL is `sub' only look at buffers in parent directories
1943of the current buffer."
dd459839
SM
1944 (let ((dir default-directory)
1945 (header-re tex-start-of-header))
1946 (catch 'found
1947 ;; Look for a buffer with `tex-main-file' set.
1948 (dolist (buf (if (consp all) all (buffer-list)))
1949 (with-current-buffer buf
8084f5d8
SM
1950 (when (and (cond
1951 ((null all) (equal dir default-directory))
1952 ((eq all 'sub) (tex-string-prefix-p default-directory dir))
1953 (t))
dd459839
SM
1954 (stringp tex-main-file))
1955 (throw 'found (expand-file-name tex-main-file)))))
1956 ;; Look for a buffer containing the magic `tex-start-of-header'.
1957 (dolist (buf (if (consp all) all (buffer-list)))
1958 (with-current-buffer buf
8084f5d8
SM
1959 (when (and (cond
1960 ((null all) (equal dir default-directory))
1961 ((eq all 'sub) (tex-string-prefix-p default-directory dir))
1962 (t))
dd459839
SM
1963 buffer-file-name
1964 ;; (or (easy-mmode-derived-mode-p 'latex-mode)
1965 ;; (easy-mmode-derived-mode-p 'plain-tex-mode))
1966 (save-excursion
cb30255a
SM
1967 (save-restriction
1968 (widen)
1969 (goto-char (point-min))
95a045bd
SM
1970 (re-search-forward
1971 header-re (+ (point) 10000) t))))
dd459839
SM
1972 (throw 'found (expand-file-name buffer-file-name))))))))
1973
07c16ec4
SM
1974(defun tex-main-file ()
1975 "Return the relative name of the main file."
bdbd9606
SM
1976 (let* ((file (or tex-main-file
1977 ;; Compatibility with AUCTeX.
96c0d9e9 1978 (with-no-warnings
034a48f4
MR
1979 (when (boundp 'TeX-master)
1980 (cond ((stringp TeX-master)
1981 (make-local-variable 'tex-main-file)
1982 (setq tex-main-file TeX-master))
1983 ((and (eq TeX-master t) buffer-file-name)
1984 (file-relative-name buffer-file-name)))))
bdbd9606
SM
1985 ;; Try to guess the main file.
1986 (if (not buffer-file-name)
1987 (error "Buffer is not associated with any file")
1988 (file-relative-name
1989 (if (save-excursion
1990 (goto-char (point-min))
95a045bd
SM
1991 (re-search-forward tex-start-of-header
1992 (+ (point) 10000) t))
bdbd9606
SM
1993 ;; This is the main file.
1994 buffer-file-name
1995 ;; This isn't the main file, let's try to find better,
1996 (or (tex-guess-main-file)
8084f5d8 1997 (tex-guess-main-file 'sub)
bdbd9606 1998 ;; (tex-guess-main-file t)
07c16ec4 1999 buffer-file-name)))))))
e70ff1af
SM
2000 (if (or (file-exists-p file) (string-match "\\.tex\\'" file))
2001 file (concat file ".tex"))))
dd459839 2002
75035a80
SM
2003(defun tex-summarize-command (cmd)
2004 (if (not (stringp cmd)) ""
2005 (mapconcat 'identity
2006 (mapcar (lambda (s) (car (split-string s)))
2007 (split-string cmd "\\s-*\\(?:;\\|&&\\)\\s-*"))
2008 "&")))
2009
2010(defun tex-uptodate-p (file)
2011 "Return non-nil if FILE is not uptodate w.r.t the document source files.
2012FILE is typically the output DVI or PDF file."
2013 ;; We should check all the files included !!!
2014 (and
2015 ;; Clearly, the target must exist.
2016 (file-exists-p file)
2017 ;; And the last run must not have asked for a rerun.
2018 ;; FIXME: this should check that the last run was done on the same file.
2019 (let ((buf (condition-case nil (tex-shell-buf) (error nil))))
2020 (when buf
2021 (with-current-buffer buf
2022 (save-excursion
2023 (goto-char (point-max))
2024 (and (re-search-backward
68a2af7a
SM
2025 (concat "(see the transcript file for additional information)"
2026 "\\|^Output written on .*"
2027 (regexp-quote (file-name-nondirectory file))
2028 " (.*)\\.")
2029 nil t)
75035a80 2030 (> (save-excursion
24d2266c
SM
2031 ;; Usually page numbers are output as [N], but
2032 ;; I've already seen things like
2033 ;; [1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}]
2034 (or (re-search-backward "\\[[0-9]+\\({[^}]*}\\)?\\]"
2035 nil t)
75035a80
SM
2036 (point-min)))
2037 (save-excursion
2038 (or (re-search-backward "Rerun" nil t)
2039 (point-min)))))))))
2040 ;; And the input files must not have been changed in the meantime.
2041 (let ((files (if (and tex-use-reftex
2042 (fboundp 'reftex-scanning-info-available-p)
2043 (reftex-scanning-info-available-p))
2044 (reftex-all-document-files)
2045 (list (file-name-directory (expand-file-name file)))))
2046 (ignored-dirs-re
2047 (concat
2048 (regexp-opt
2049 (delq nil (mapcar (lambda (s) (if (eq (aref s (1- (length s))) ?/)
2050 (substring s 0 (1- (length s)))))
2051 completion-ignored-extensions))
2052 t) "\\'"))
2053 (uptodate t))
2054 (while (and files uptodate)
2055 (let ((f (pop files)))
e70ff1af
SM
2056 (if (and (file-directory-p f)
2057 ;; Avoid infinite loops.
2058 (not (file-symlink-p f)))
75035a80
SM
2059 (unless (string-match ignored-dirs-re f)
2060 (setq files (nconc
594bab65
SM
2061 (ignore-errors ;Not readable or something.
2062 (directory-files f t tex-input-files-re))
75035a80
SM
2063 files)))
2064 (when (file-newer-than-file-p f file)
2065 (setq uptodate nil)))))
2066 uptodate)))
bf247b6e 2067
75035a80
SM
2068
2069(autoload 'format-spec "format-spec")
2070
2071(defvar tex-executable-cache nil)
2072(defun tex-executable-exists-p (name)
2073 "Like `executable-find' but with a cache."
68a2af7a
SM
2074 (let ((f (and (string-match "^\\\\\\([^ \t\n]+\\)" name)
2075 (intern-soft (concat "tex-cmd-" (match-string 1 name))))))
2076 (if (fboundp f)
2077 f
2078 (let ((cache (assoc name tex-executable-cache)))
2079 (if cache (cdr cache)
2080 (let ((executable (executable-find name)))
2081 (push (cons name executable) tex-executable-cache)
2082 executable))))))
75035a80
SM
2083
2084(defun tex-command-executable (cmd)
2085 (let ((s (if (stringp cmd) cmd (eval (car cmd)))))
2086 (substring s 0 (string-match "[ \t]\\|\\'" s))))
2087
2088(defun tex-command-active-p (cmd fspec)
2089 "Return non-nil if the CMD spec might need to be run."
2090 (let ((in (nth 1 cmd))
2091 (out (nth 2 cmd)))
2092 (if (stringp in)
2093 (let ((file (format-spec in fspec)))
2094 (when (file-exists-p file)
2095 (or (not out)
2096 (file-newer-than-file-p
2097 file (format-spec out fspec)))))
2098 (when (and (eq in t) (stringp out))
2099 (not (tex-uptodate-p (format-spec out fspec)))))))
2100
68a2af7a
SM
2101(defcustom tex-cmd-bibtex-args "--min-crossref=100"
2102 "Extra args to pass to `bibtex' by default."
56b654bb
GM
2103 :type 'string
2104 :version "23.1"
2105 :group 'tex-run)
68a2af7a
SM
2106
2107(defun tex-format-cmd (format fspec)
2108 "Like `format-spec' but adds user-specified args to the command.
2109Only applies the FSPEC to the args part of FORMAT."
2110 (if (not (string-match "\\([^ /\\]+\\) " format))
2111 (format-spec format fspec)
2112 (let* ((prefix (substring format 0 (match-beginning 0)))
2113 (cmd (match-string 1 format))
2114 (args (substring format (match-end 0)))
2115 (sym (intern-soft (format "tex-cmd-%s-args" cmd)))
2116 (extra-args (and sym (symbol-value sym))))
2117 (concat prefix cmd
2118 (if extra-args (concat " " extra-args))
2119 " " (format-spec args fspec)))))
56b654bb 2120
8084f5d8 2121(defun tex-compile-default (fspec)
dd166d5f 2122 "Guess a default command given the `format-spec' FSPEC."
75035a80
SM
2123 ;; TODO: Learn to do latex+dvips!
2124 (let ((cmds nil)
2125 (unchanged-in nil))
2126 ;; Only consider active commands.
2127 (dolist (cmd tex-compile-commands)
2128 (when (tex-executable-exists-p (tex-command-executable cmd))
2129 (if (tex-command-active-p cmd fspec)
2130 (push cmd cmds)
2131 (push (nth 1 cmd) unchanged-in))))
dd166d5f 2132 ;; If no command seems to be applicable, arbitrarily pick the first one.
29a47b89 2133 (setq cmds (if cmds (nreverse cmds) (list (car tex-compile-commands))))
75035a80
SM
2134 ;; Remove those commands whose input was considered stable for
2135 ;; some other command (typically if (t . "%.pdf") is inactive
2136 ;; then we're using pdflatex and the fact that the dvi file
2137 ;; is inexistent doesn't matter).
2138 (let ((tmp nil))
2139 (dolist (cmd cmds)
2140 (unless (member (nth 1 cmd) unchanged-in)
2141 (push cmd tmp)))
8084f5d8 2142 ;; Only remove if there's something left.
29a47b89 2143 (if tmp (setq cmds (nreverse tmp))))
8084f5d8
SM
2144 ;; Remove commands whose input is not uptodate either.
2145 (let ((outs (delq nil (mapcar (lambda (x) (nth 2 x)) cmds)))
2146 (tmp nil))
2147 (dolist (cmd cmds)
75035a80 2148 (unless (member (nth 1 cmd) outs)
8084f5d8
SM
2149 (push cmd tmp)))
2150 ;; Only remove if there's something left.
29a47b89 2151 (if tmp (setq cmds (nreverse tmp))))
75035a80
SM
2152 ;; Select which file we're going to operate on (the latest).
2153 (let ((latest (nth 1 (car cmds))))
2154 (dolist (cmd (prog1 (cdr cmds) (setq cmds (list (car cmds)))))
2155 (if (equal latest (nth 1 cmd))
2156 (push cmd cmds)
2157 (unless (eq latest t) ;Can't beat that!
2158 (if (or (not (stringp latest))
2159 (eq (nth 1 cmd) t)
2160 (and (stringp (nth 1 cmd))
2161 (file-newer-than-file-p
2162 (format-spec (nth 1 cmd) fspec)
2163 (format-spec latest fspec))))
2164 (setq latest (nth 1 cmd) cmds (list cmd)))))))
2165 ;; Expand the command spec into the actual text.
2166 (dolist (cmd (prog1 cmds (setq cmds nil)))
2167 (push (cons (eval (car cmd)) (cdr cmd)) cmds))
2168 ;; Select the favorite command from the history.
2169 (let ((hist tex-compile-history)
8084f5d8 2170 re hist-cmd)
75035a80 2171 (while hist
8084f5d8 2172 (setq hist-cmd (pop hist))
75035a80 2173 (setq re (concat "\\`"
8084f5d8 2174 (regexp-quote (tex-command-executable hist-cmd))
75035a80
SM
2175 "\\([ \t]\\|\\'\\)"))
2176 (dolist (cmd cmds)
8084f5d8
SM
2177 ;; If the hist entry uses the same command and applies to a file
2178 ;; of the same type (e.g. `gv %r.pdf' vs `gv %r.ps'), select cmd.
2179 (and (string-match re (car cmd))
2180 (or (not (string-match "%[fr]\\([-._[:alnum:]]+\\)" (car cmd)))
2181 (string-match (regexp-quote (match-string 1 (car cmd)))
2182 hist-cmd))
2183 (setq hist nil cmds (list cmd)))))
2184 ;; Substitute and return.
2185 (if (and hist-cmd
2186 (string-match (concat "[' \t\"]" (format-spec "%r" fspec)
2187 "\\([;&' \t\"]\\|\\'\\)") hist-cmd))
2188 ;; The history command was already applied to the same file,
2189 ;; so just reuse it.
2190 hist-cmd
68a2af7a
SM
2191 (if cmds (tex-format-cmd (caar cmds) fspec))))))
2192
2193(defun tex-cmd-doc-view (file)
2194 (pop-to-buffer (find-file-noselect file)))
75035a80
SM
2195
2196(defun tex-compile (dir cmd)
2197 "Run a command CMD on current TeX buffer's file in DIR."
2198 ;; FIXME: Use time-stamps on files to decide the next op.
2199 (interactive
2200 (let* ((file (tex-main-file))
5e56fb53
SM
2201 (default-directory
2202 (prog1 (file-name-directory (expand-file-name file))
2203 (setq file (file-name-nondirectory file))))
75035a80 2204 (root (file-name-sans-extension file))
d18fc930
SM
2205 (fspec (list (cons ?r (shell-quote-argument root))
2206 (cons ?f (shell-quote-argument file))))
8084f5d8 2207 (default (tex-compile-default fspec)))
5e56fb53 2208 (list default-directory
75035a80
SM
2209 (completing-read
2210 (format "Command [%s]: " (tex-summarize-command default))
2211 (mapcar (lambda (x)
68a2af7a 2212 (list (tex-format-cmd (eval (car x)) fspec)))
75035a80
SM
2213 tex-compile-commands)
2214 nil nil nil 'tex-compile-history default))))
2215 (save-some-buffers (not compilation-ask-about-save) nil)
68a2af7a
SM
2216 (let ((f (and (string-match "^\\\\\\([^ \t\n]+\\)" cmd)
2217 (intern-soft (concat "tex-cmd-" (match-string 1 cmd))))))
2218 (if (functionp f)
2219 (condition-case nil
2220 (let ((default-directory dir))
2221 (apply f (split-string-and-unquote
2222 (substring cmd (match-end 0)))))
2223 (wrong-number-of-arguments
2224 (error "Wrong number of arguments to %s"
2225 (substring (symbol-name f) 8))))
2226 (if (tex-shell-running)
2227 (tex-kill-job)
2228 (tex-start-shell))
2229 (tex-send-tex-command cmd dir))))
d6709b80
SM
2230
2231(defun tex-start-tex (command file &optional dir)
460e1b7d 2232 "Start a TeX run, using COMMAND on FILE."
6633b891 2233 (let* ((star (string-match "\\*" command))
460e1b7d 2234 (compile-command
6633b891
KH
2235 (if star
2236 (concat (substring command 0 star)
d18fc930 2237 (shell-quote-argument file)
6633b891
KH
2238 (substring command (1+ star)))
2239 (concat command " "
95a045bd 2240 tex-start-options
9e0ad27a 2241 (if (< 0 (length tex-start-commands))
d18fc930
SM
2242 (concat
2243 (shell-quote-argument tex-start-commands) " "))
2244 (shell-quote-argument file)))))
bdbd9606
SM
2245 (tex-send-tex-command compile-command dir)))
2246
2247(defun tex-send-tex-command (cmd &optional dir)
b781e739
SS
2248 (unless (or (equal dir (let ((buf (tex-shell-buf-no-error)))
2249 (and buf (with-current-buffer buf
2250 default-directory))))
bdbd9606
SM
2251 (not dir))
2252 (let (shell-dirtrack-verbose)
8ca66348 2253 (tex-send-command tex-shell-cd-command dir)))
bdbd9606 2254 (with-current-buffer (process-buffer (tex-send-command cmd))
bdbd9606
SM
2255 (setq compilation-last-buffer (current-buffer))
2256 (compilation-forget-errors)
1598a961 2257 ;; Don't parse previous compilations.
bdbd9606
SM
2258 (set-marker compilation-parsing-end (1- (point-max))))
2259 (tex-display-shell)
2260 (setq tex-last-buffer-texed (current-buffer)))
460e1b7d 2261\f
1598a961
SM
2262(defvar tex-error-parse-syntax-table
2263 (let ((st (make-syntax-table)))
2264 (modify-syntax-entry ?\( "()" st)
2265 (modify-syntax-entry ?\) ")(" st)
2266 (modify-syntax-entry ?\\ "\\" st)
2267 (modify-syntax-entry ?\{ "_" st)
2268 (modify-syntax-entry ?\} "_" st)
2269 (modify-syntax-entry ?\[ "_" st)
2270 (modify-syntax-entry ?\] "_" st)
2271 ;; Single quotations may appear in errors
2272 (modify-syntax-entry ?\" "_" st)
2273 st)
2274 "Syntax-table used while parsing TeX error messages.")
2275
460e1b7d 2276(defun tex-compilation-parse-errors (limit-search find-at-least)
f05bd645
RS
2277 "Parse the current buffer as TeX error messages.
2278See the variable `compilation-parse-errors-function' for the interface it uses.
2279
2280This function parses only the last TeX compilation.
2281It works on TeX compilations only. It is necessary for that purpose,
2282since TeX does not put file names and line numbers on the same line as
2283for the error messages."
460e1b7d
RS
2284 (require 'thingatpt)
2285 (setq compilation-error-list nil)
f05bd645
RS
2286 (let ((default-directory ; Perhaps dir has changed meanwhile.
2287 (file-name-directory (buffer-file-name tex-last-buffer-texed)))
f05bd645
RS
2288 found-desired (num-errors-found 0)
2289 last-filename last-linenum last-position
3d1634c6 2290 begin-of-error end-of-error errfilename)
f05bd645
RS
2291 ;; Don't reparse messages already seen at last parse.
2292 (goto-char compilation-parsing-end)
2293 ;; Parse messages.
2294 (while (and (not (or found-desired (eobp)))
3d1634c6
GM
2295 ;; First alternative handles the newer --file-line-error style:
2296 ;; ./test2.tex:14: Too many }'s.
2297 ;; Second handles the old-style:
2298 ;; ! Too many }'s.
e47a29ad 2299 (prog1 (re-search-forward
3d1634c6 2300 "^\\(?:\\([^:\n]+\\):[[:digit:]]+:\\|!\\) " nil 'move)
f05bd645 2301 (setq begin-of-error (match-beginning 0)
3d1634c6
GM
2302 end-of-error (match-end 0)
2303 errfilename (match-string 1)))
f05bd645
RS
2304 (re-search-forward
2305 "^l\\.\\([0-9]+\\) \\(\\.\\.\\.\\)?\\(.*\\)$" nil 'move))
3f2c97ea 2306 (let* ((this-error (copy-marker begin-of-error))
003274a0 2307 (linenum (string-to-number (match-string 1)))
f05bd645 2308 (error-text (regexp-quote (match-string 3)))
1957b847 2309 try-filename
f05bd645 2310 (filename
3d1634c6
GM
2311 ;; Prefer --file-liner-error filename if we have it.
2312 (or errfilename
2313 (save-excursion
2314 (with-syntax-table tex-error-parse-syntax-table
2315 (backward-up-list 1)
2316 (skip-syntax-forward "(_")
e6ce8c42 2317 (while (not
1957b847
CY
2318 (and (setq try-filename (thing-at-point
2319 'filename))
2320 (not (string= "" try-filename))
2321 (file-readable-p try-filename)))
3d1634c6
GM
2322 (skip-syntax-backward "(_")
2323 (backward-up-list 1)
2324 (skip-syntax-forward "(_"))
2325 (thing-at-point 'filename)))))
f05bd645
RS
2326 (new-file
2327 (or (null last-filename)
2328 (not (string-equal last-filename filename))))
2329 (error-location
cc9f5376
SM
2330 (with-current-buffer
2331 (if (equal filename (concat tex-zap-file ".tex"))
2332 tex-last-buffer-texed
2333 (find-file-noselect filename))
2334 (save-excursion
2335 (if new-file
e6ce8c42
GM
2336 (progn
2337 (goto-char (point-min))
2338 (forward-line (1- linenum))
2339 (setq last-position nil))
cc9f5376
SM
2340 (goto-char last-position)
2341 (forward-line (- linenum last-linenum)))
2342 ;; first try a forward search for the error text,
2343 ;; then a backward search limited by the last error.
2344 (let ((starting-point (point)))
2345 (or (re-search-forward error-text nil t)
2346 (re-search-backward error-text last-position t)
2347 (goto-char starting-point)))
2348 (point-marker)))))
f05bd645
RS
2349 (goto-char this-error)
2350 (if (and compilation-error-list
2351 (or (and find-at-least
2352 (>= num-errors-found
2353 find-at-least))
2354 (and limit-search
2355 (>= end-of-error limit-search)))
2356 new-file)
2357 (setq found-desired t)
2358 (setq num-errors-found (1+ num-errors-found)
2359 last-filename filename
2360 last-linenum linenum
2361 last-position error-location
2362 compilation-error-list ; Add the new error
2363 (cons (cons this-error error-location)
2364 compilation-error-list))
2365 (goto-char end-of-error)))))
ee13a145 2366 (set-marker compilation-parsing-end (point))
13376c78 2367 (setq compilation-error-list (nreverse compilation-error-list)))
460e1b7d 2368\f
528415e7 2369;;; The commands:
869bff31 2370
2371(defun tex-region (beg end)
2372 "Run TeX on the current region, via a temporary file.
2373The file's name comes from the variable `tex-zap-file' and the
2374variable `tex-directory' says where to put it.
2375
2376If the buffer has a header, the header is given to TeX before the
2377region itself. The buffer's header is all lines between the strings
2378defined by `tex-start-of-header' and `tex-end-of-header' inclusive.
2379The header must start in the first 100 lines of the buffer.
2380
2381The value of `tex-trailer' is given to TeX as input after the region.
2382
2383The value of `tex-command' specifies the command to use to run TeX."
2384 (interactive "r")
2385 (if (tex-shell-running)
2386 (tex-kill-job)
2387 (tex-start-shell))
2388 (or tex-zap-file
2389 (setq tex-zap-file (tex-generate-zap-file-name)))
6d34c59f
RS
2390 ;; Temp file will be written and TeX will be run in zap-directory.
2391 ;; If the TEXINPUTS file has relative directories or if the region has
2392 ;; \input of files, this must be the same directory as the file for
2393 ;; TeX to access the correct inputs. That's why it's safest if
2394 ;; tex-directory is ".".
2395 (let* ((zap-directory
528415e7 2396 (file-name-as-directory (expand-file-name tex-directory)))
d6709b80 2397 (tex-out-file (expand-file-name (concat tex-zap-file ".tex")
80c2ab0f
GM
2398 zap-directory))
2399 (main-file (expand-file-name (tex-main-file)))
595a68b4
GM
2400 (ismain (string-equal main-file (buffer-file-name)))
2401 already-output)
0d548e5d
RS
2402 ;; Don't delete temp files if we do the same buffer twice in a row.
2403 (or (eq (current-buffer) tex-last-buffer-texed)
2404 (tex-delete-last-temp-files t))
595a68b4
GM
2405 (let ((default-directory zap-directory)) ; why?
2406 ;; We assume the header is fully contained in tex-main-file.
2407 ;; We use f-f-ns so we get prompted about any changes on disk.
2408 (with-current-buffer (find-file-noselect main-file)
2409 (setq already-output (tex-region-header tex-out-file
2410 (and ismain beg))))
2411 ;; Write out the specified region (but don't repeat anything
2412 ;; already written in the header).
2413 (write-region (if ismain
2414 (max beg already-output)
2415 beg)
2416 end tex-out-file (not (zerop already-output)))
2417 ;; Write the trailer, if any.
2418 ;; Precede it with a newline to make sure it
2419 ;; is not hidden in a comment.
2420 (if tex-trailer
2421 (write-region (concat "\n" tex-trailer) nil
2422 tex-out-file t)))
80c2ab0f
GM
2423 ;; Record the file name to be deleted afterward.
2424 (setq tex-last-temp-file tex-out-file)
2425 ;; Use a relative file name here because (1) the proper dir
2426 ;; is already current, and (2) the abs file name is sometimes
2427 ;; too long and can make tex crash.
2428 (tex-start-tex tex-command (concat tex-zap-file ".tex") zap-directory)
2429 (setq tex-print-file tex-out-file)))
2430
595a68b4
GM
2431(defun tex-region-header (file &optional beg)
2432 "If there is a TeX header in the current buffer, write it to FILE.
2433Return point at the end of the region so written, or zero. If
2434the optional buffer position BEG is specified, then the region
2435written out starts at BEG, if this lies before the start of the header.
2436
2437If the first line matches `tex-first-line-header-regexp', it is
2438also written out. The variables `tex-start-of-header' and
2439`tex-end-of-header' are used to locate the header. Note that the
2440start of the header is required to be within the first 100 lines."
2441 (save-excursion
2442 (save-restriction
2443 (widen)
2444 (goto-char (point-min))
2445 (let ((search-end (save-excursion
2446 (forward-line 100)
2447 (point)))
2448 (already-output 0)
2449 hbeg hend)
2450 ;; Maybe copy first line, such as `\input texinfo', to temp file.
2451 (and tex-first-line-header-regexp
2452 (looking-at tex-first-line-header-regexp)
2453 (write-region (point)
2454 (progn (forward-line 1)
2455 (setq already-output (point)))
2456 file))
2457 ;; Write out the header, if there is one, and any of the
2458 ;; specified region which extends before it. But don't repeat
2459 ;; anything already written.
2460 (and tex-start-of-header
2461 (re-search-forward tex-start-of-header search-end t)
2462 (progn
2463 (beginning-of-line)
2464 (setq hbeg (point)) ; mark beginning of header
2465 (when (re-search-forward tex-end-of-header nil t)
2466 (forward-line 1)
2467 (setq hend (point)) ; mark end of header
2468 (write-region
2469 (max (if beg
2470 (min hbeg beg)
2471 hbeg)
2472 already-output)
2473 hend file (not (zerop already-output)))
2474 (setq already-output hend))))
2475 already-output))))
869bff31 2476
2477(defun tex-buffer ()
2478 "Run TeX on current buffer. See \\[tex-region] for more information.
528415e7
RS
2479Does not save the buffer, so it's useful for trying experimental versions.
2480See \\[tex-file] for an alternative."
869bff31 2481 (interactive)
2482 (tex-region (point-min) (point-max)))
2483
2484(defun tex-file ()
2485 "Prompt to save all buffers and run TeX (or LaTeX) on current buffer's file.
2486This function is more useful than \\[tex-buffer] when you need the
2487`.aux' file of LaTeX to have the correct name."
2488 (interactive)
7abc9add
SS
2489 (when tex-offer-save
2490 (save-some-buffers))
d6709b80 2491 (let* ((source-file (tex-main-file))
07c16ec4 2492 (file-dir (file-name-directory (expand-file-name source-file))))
869bff31 2493 (if (tex-shell-running)
2494 (tex-kill-job)
2495 (tex-start-shell))
d6709b80 2496 (tex-start-tex tex-command source-file file-dir)
f05bd645 2497 (setq tex-print-file (expand-file-name source-file))))
869bff31 2498
2499(defun tex-generate-zap-file-name ()
2500 "Generate a unique name suitable for use as a file name."
2501 ;; Include the shell process number and host name
2502 ;; in case there are multiple shells (for same or different user).
f5cdb851
KH
2503 ;; Dec 1998: There is a report that some versions of xdvi
2504 ;; don't work with file names that start with #.
5616ee46 2505 (format "_TZ_%d-%s"
869bff31 2506 (process-id (get-buffer-process "*tex-shell*"))
07c16ec4 2507 (subst-char-in-string ?. ?- (system-name))))
869bff31 2508
2509;; This will perhaps be useful for modifying TEXINPUTS.
2510;; Expand each file name, separated by colons, in the string S.
2511(defun tex-expand-files (s)
2512 (let (elts (start 0))
2513 (while (string-match ":" s start)
2514 (setq elts (cons (substring s start (match-beginning 0)) elts))
2515 (setq start (match-end 0)))
2516 (or (= start 0)
2517 (setq elts (cons (substring s start) elts)))
c0df1972
SM
2518 (mapconcat (lambda (elt)
2519 (if (= (length elt) 0) elt (expand-file-name elt)))
5616ee46 2520 (nreverse elts) ":")))
869bff31 2521
2522(defun tex-shell-running ()
713f7b15 2523 (let ((proc (get-process "tex-shell")))
b781e739
SS
2524 (when proc
2525 (if (and (eq (process-status proc) 'run)
2526 (buffer-live-p (process-buffer proc)))
2527 ;; return the TeX process on success
2528 proc
2529 ;; get rid of the process permanently
2530 ;; this should get rid of the annoying w32 problem with
2531 ;; dead tex-shell buffer and live process
2532 (delete-process proc)))))
869bff31 2533
2534(defun tex-kill-job ()
2535 "Kill the currently running TeX job."
2536 (interactive)
b781e739 2537 ;; `quit-process' leads to core dumps of the tex process (except if
bed1b0c8
RS
2538 ;; coredumpsize has limit 0kb as on many environments). One would
2539 ;; like to use (kill-process proc 'lambda), however that construct
2540 ;; does not work on some systems and kills the shell itself.
b781e739
SS
2541 (let ((proc (get-process "tex-shell")))
2542 (when proc (quit-process proc t))))
869bff31 2543
2544(defun tex-recenter-output-buffer (linenum)
2545 "Redisplay buffer of TeX job output so that most recent output can be seen.
2546The last line of the buffer is displayed on
2547line LINE of the window, or centered if LINE is nil."
2548 (interactive "P")
2549 (let ((tex-shell (get-buffer "*tex-shell*"))
23b64225 2550 (window))
869bff31 2551 (if (null tex-shell)
2552 (message "No TeX output buffer")
23b64225
RS
2553 (setq window (display-buffer tex-shell))
2554 (save-selected-window
2555 (select-window window)
2556 (bury-buffer tex-shell)
2557 (goto-char (point-max))
2558 (recenter (if linenum
2559 (prefix-numeric-value linenum)
2560 (/ (window-height) 2)))))))
869bff31 2561
528415e7 2562(defun tex-print (&optional alt)
869bff31 2563 "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file].
1433a222
CZ
2564Runs the shell command defined by `tex-dvi-print-command'. If prefix argument
2565is provided, use the alternative command, `tex-alt-dvi-print-command'."
528415e7 2566 (interactive "P")
869bff31 2567 (let ((print-file-name-dvi (tex-append tex-print-file ".dvi"))
2568 test-name)
2569 (if (and (not (equal (current-buffer) tex-last-buffer-texed))
45c3304d
RS
2570 (buffer-file-name)
2571 ;; Check that this buffer's printed file is up to date.
869bff31 2572 (file-newer-than-file-p
2573 (setq test-name (tex-append (buffer-file-name) ".dvi"))
45c3304d 2574 (buffer-file-name)))
869bff31 2575 (setq print-file-name-dvi test-name))
528415e7
RS
2576 (if (not (file-exists-p print-file-name-dvi))
2577 (error "No appropriate `.dvi' file could be found")
460e1b7d
RS
2578 (if (tex-shell-running)
2579 (tex-kill-job)
2580 (tex-start-shell))
528415e7 2581 (tex-send-command
bed1b0c8 2582 (if alt tex-alt-dvi-print-command tex-dvi-print-command)
b5352ff5 2583 print-file-name-dvi
602503c5 2584 t))))
869bff31 2585
cf6d6e8a
RS
2586(defun tex-alt-print ()
2587 "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file].
002b0d00 2588Runs the shell command defined by `tex-alt-dvi-print-command'."
cf6d6e8a
RS
2589 (interactive)
2590 (tex-print t))
2591
869bff31 2592(defun tex-view ()
2593 "Preview the last `.dvi' file made by running TeX under Emacs.
2594This means, made using \\[tex-region], \\[tex-buffer] or \\[tex-file].
2b7971c9
RS
2595The variable `tex-dvi-view-command' specifies the shell command for preview.
2596You must set that variable yourself before using this command,
2597because there is no standard value that would generally work."
869bff31 2598 (interactive)
2b7971c9
RS
2599 (or tex-dvi-view-command
2600 (error "You must set `tex-dvi-view-command'"))
3356ce3b
EZ
2601 ;; Restart the TeX shell if necessary.
2602 (or (tex-shell-running)
2603 (tex-start-shell))
746c30e2 2604 (let ((tex-dvi-print-command (eval tex-dvi-view-command)))
869bff31 2605 (tex-print)))
2606
2607(defun tex-append (file-name suffix)
2608 "Append to FILENAME the suffix SUFFIX, using same algorithm TeX uses.
cf6d6e8a 2609Pascal-based TeX scans for the first period, C TeX uses the last.
869bff31 2610No period is retained immediately before SUFFIX,
2611so normally SUFFIX starts with one."
2612 (if (stringp file-name)
cf6d6e8a
RS
2613 (let ((file (file-name-nondirectory file-name))
2614 trial-name)
6da9bbd6 2615 ;; Try splitting on last period.
7d0ca249
RS
2616 ;; The first-period split can get fooled when two files
2617 ;; named a.tex and a.b.tex are both tex'd;
2618 ;; the last-period split must be right if it matches at all.
cf6d6e8a
RS
2619 (setq trial-name
2620 (concat (file-name-directory file-name)
2621 (substring file 0
7d0ca249 2622 (string-match "\\.[^.]*$" file))
cf6d6e8a
RS
2623 suffix))
2624 (if (or (file-exists-p trial-name)
2625 (file-exists-p (concat trial-name ".aux"))) ;for BibTeX files
2626 trial-name
7d0ca249 2627 ;; Not found, so split on first period.
cf6d6e8a
RS
2628 (concat (file-name-directory file-name)
2629 (substring file 0
7d0ca249 2630 (string-match "\\." file))
cf6d6e8a 2631 suffix)))
869bff31 2632 " "))
2633
2634(defun tex-show-print-queue ()
2635 "Show the print queue that \\[tex-print] put your job on.
1433a222 2636Runs the shell command defined by `tex-show-queue-command'."
869bff31 2637 (interactive)
2638 (if (tex-shell-running)
2639 (tex-kill-job)
2640 (tex-start-shell))
51b2c841
RS
2641 (tex-send-command tex-show-queue-command)
2642 (tex-display-shell))
869bff31 2643
2644(defun tex-bibtex-file ()
2645 "Run BibTeX on the current buffer's file."
2646 (interactive)
2647 (if (tex-shell-running)
2648 (tex-kill-job)
2649 (tex-start-shell))
78796feb 2650 (let* (shell-dirtrack-verbose
88fd78ae 2651 (source-file (expand-file-name (tex-main-file)))
78796feb
SM
2652 (tex-out-file
2653 (tex-append (file-name-nondirectory source-file) ""))
2654 (file-dir (file-name-directory source-file)))
8ca66348 2655 (tex-send-command tex-shell-cd-command file-dir)
51b2c841
RS
2656 (tex-send-command tex-bibtex-command tex-out-file))
2657 (tex-display-shell))
ea590e1c
SM
2658\f
2659;;;;
2660;;;; LaTeX indentation
2661;;;;
2662
2663(defvar tex-indent-allhanging t)
2664(defvar tex-indent-arg 4)
2665(defvar tex-indent-basic 2)
2666(defvar tex-indent-item tex-indent-basic)
2667(defvar tex-indent-item-re "\\\\\\(bib\\)?item\\>")
dd166d5f 2668(defvar latex-noindent-environments '("document"))
ea590e1c 2669
8a591d52
SM
2670(defvar tex-latex-indent-syntax-table
2671 (let ((st (make-syntax-table tex-mode-syntax-table)))
2672 (modify-syntax-entry ?$ "." st)
2673 (modify-syntax-entry ?\( "." st)
2674 (modify-syntax-entry ?\) "." st)
2675 st)
2676 "Syntax table used while computing indentation.")
ea590e1c
SM
2677
2678(defun latex-indent (&optional arg)
7afecb99 2679 (if (and (eq (get-text-property (line-beginning-position) 'face)
014e29b9 2680 'tex-verbatim))
a3d80d4a 2681 'noindent
7afecb99
SM
2682 (with-syntax-table tex-latex-indent-syntax-table
2683 ;; TODO: Rather than ignore $, we should try to be more clever about it.
2684 (let ((indent
2685 (save-excursion
2686 (beginning-of-line)
2687 (latex-find-indent))))
2688 (if (< indent 0) (setq indent 0))
2689 (if (<= (current-column) (current-indentation))
2690 (indent-line-to indent)
2691 (save-excursion (indent-line-to indent)))))))
ea590e1c 2692
fa9a8f78
MR
2693(defcustom latex-indent-within-escaped-parens nil
2694 "Non-nil means add extra indent to text within escaped parens.
2695When this is non-nil, text within matching pairs of escaped
2696parens is indented at the column following the open paren. The
2697default value does not add any extra indent thus providing the
2698behavior of Emacs 22 and earlier."
2699 :type 'boolean
2700 :group 'tex
2701 :version "23.1")
2702
ea590e1c
SM
2703(defun latex-find-indent (&optional virtual)
2704 "Find the proper indentation of text after point.
2705VIRTUAL if non-nil indicates that we're only trying to find the indentation
2706 in order to determine the indentation of something else.
2707There might be text before point."
fa9a8f78
MR
2708 (let ((latex-handle-escaped-parens latex-indent-within-escaped-parens))
2709 (save-excursion
2710 (skip-chars-forward " \t")
2711 (or
2712 ;; Stick the first line at column 0.
2713 (and (= (point-min) (line-beginning-position)) 0)
2714 ;; Trust the current indentation, if such info is applicable.
2715 (and virtual (save-excursion (skip-chars-backward " \t&") (bolp))
2716 (current-column))
2717 ;; Stick verbatim environments to the left margin.
2718 (and (looking-at "\\\\\\(begin\\|end\\) *{\\([^\n}]+\\)")
2719 (member (match-string 2) tex-verbatim-environments)
2720 0)
2721 ;; Put leading close-paren where the matching open paren would be.
2722 (let (escaped)
2723 (and (or (eq (latex-syntax-after) ?\))
2724 ;; Try to handle escaped close parens but keep
2725 ;; original position if it doesn't work out.
2726 (and latex-handle-escaped-parens
2727 (setq escaped (looking-at "\\\\\\([])}]\\)"))))
2728 (ignore-errors
2729 (save-excursion
2730 (when escaped
2731 (goto-char (match-beginning 1)))
2732 (latex-skip-close-parens)
2733 (latex-backward-sexp-1)
2734 (latex-find-indent 'virtual)))))
2735 ;; Default (maybe an argument)
2736 (let ((pos (point))
2737 ;; Outdent \item if necessary.
2738 (indent (if (looking-at tex-indent-item-re) (- tex-indent-item) 0))
2739 up-list-pos)
2740 ;; Find the previous point which determines our current indentation.
2741 (condition-case err
2742 (progn
8ca37e61 2743 (latex-backward-sexp-1)
fa9a8f78
MR
2744 (while (> (current-column) (current-indentation))
2745 (latex-backward-sexp-1)))
2746 (scan-error
2747 (setq up-list-pos (nth 2 err))))
2748 (cond
2749 ((= (point-min) pos) 0) ; We're really just indenting the first line.
2750 ((integerp up-list-pos)
2751 ;; Have to indent relative to the open-paren.
8908cf40 2752 (goto-char up-list-pos)
fa9a8f78
MR
2753 (if (and (not tex-indent-allhanging)
2754 (save-excursion
2755 ;; Make sure we're an argument to a macro and
2756 ;; that the macro is at the beginning of a line.
2757 (condition-case nil
2758 (progn
2759 (while (eq (char-syntax (char-after)) ?\()
2760 (forward-sexp -1))
2761 (and (eq (char-syntax (char-after)) ?/)
2762 (progn (skip-chars-backward " \t&")
2763 (bolp))))
2764 (scan-error nil)))
2765 (> pos (progn (latex-down-list)
2766 (forward-comment (point-max))
2767 (point))))
2768 ;; Align with the first element after the open-paren.
2769 (current-column)
2770 ;; We're the first element after a hanging brace.
2771 (goto-char up-list-pos)
2772 (+ (if (and (looking-at "\\\\begin *{\\([^\n}]+\\)")
2773 (member (match-string 1)
2774 latex-noindent-environments))
2775 0 tex-indent-basic)
2776 indent (latex-find-indent 'virtual))))
2777 ;; We're now at the "beginning" of a line.
2778 ((not (and (not virtual) (eq (char-after) ?\\)))
2779 ;; Nothing particular here: just keep the same indentation.
2780 (+ indent (current-column)))
2781 ;; We're now looking at a macro call.
2782 ((looking-at tex-indent-item-re)
2783 ;; Indenting relative to an item, have to re-add the outdenting.
2784 (+ indent (current-column) tex-indent-item))
2785 (t
2786 (let ((col (current-column)))
2787 (if (or (not (eq (char-syntax (or (char-after pos) ?\s)) ?\())
2788 ;; Can't be an arg if there's an empty line inbetween.
2789 (save-excursion (re-search-forward "^[ \t]*$" pos t)))
2790 ;; If the first char was not an open-paren, there's
2791 ;; a risk that this is really not an argument to the
2792 ;; macro at all.
2793 (+ indent col)
2794 (forward-sexp 1)
2795 (if (< (line-end-position)
2796 (save-excursion (forward-comment (point-max))
2797 (point)))
2798 ;; we're indenting the first argument.
2799 (min (current-column) (+ tex-indent-arg col))
2800 (skip-syntax-forward " ")
2801 (current-column)))))))))))
a3d80d4a
SM
2802;;; DocTeX support
2803
2804(defun doctex-font-lock-^^A ()
2805 (if (eq (char-after (line-beginning-position)) ?\%)
2806 (progn
2807 (put-text-property
2808 (1- (match-beginning 1)) (match-beginning 1)
2809 'syntax-table
2810 (if (= (1+ (line-beginning-position)) (match-beginning 1))
2811 ;; The `%' is a single-char comment, which Emacs
2812 ;; syntax-table can't deal with. We could turn it
2813 ;; into a non-comment, or use `\n%' or `%^' as the comment.
2814 ;; Instead, we include it in the ^^A comment.
2815 (eval-when-compile (string-to-syntax "< b"))
2816 (eval-when-compile (string-to-syntax ">"))))
2817 (let ((end (line-end-position)))
2818 (if (< end (point-max))
2819 (put-text-property
2820 end (1+ end)
2821 'syntax-table
2822 (eval-when-compile (string-to-syntax "> b")))))
2823 (eval-when-compile (string-to-syntax "< b")))))
2824
2825(defun doctex-font-lock-syntactic-face-function (state)
2826 ;; Mark DocTeX documentation, which is parsed as a style A comment
2827 ;; starting in column 0.
2828 (if (or (nth 3 state) (nth 7 state)
2829 (not (memq (char-before (nth 8 state))
2830 '(?\n nil))))
2831 ;; Anything else is just as for LaTeX.
2832 (tex-font-lock-syntactic-face-function state)
2833 font-lock-doc-face))
2834
2835(defvar doctex-font-lock-syntactic-keywords
2836 (append
2837 tex-font-lock-syntactic-keywords
2838 ;; For DocTeX comment-in-doc.
2839 `(("\\(\\^\\)\\^A" (1 (doctex-font-lock-^^A))))))
2840
2841(defvar doctex-font-lock-keywords
2842 (append tex-font-lock-keywords
2843 '(("^%<[^>]*>" (0 font-lock-preprocessor-face t)))))
2844
2845;;;###autoload
2846(define-derived-mode doctex-mode latex-mode "DocTeX"
2847 "Major mode to edit DocTeX files."
2848 (setq font-lock-defaults
2849 (cons (append (car font-lock-defaults) '(doctex-font-lock-keywords))
2850 (mapcar
2851 (lambda (x)
2852 (case (car-safe x)
2853 (font-lock-syntactic-keywords
2854 (cons (car x) 'doctex-font-lock-syntactic-keywords))
2855 (font-lock-syntactic-face-function
2856 (cons (car x) 'doctex-font-lock-syntactic-face-function))
2857 (t x)))
2858 (cdr font-lock-defaults)))))
528415e7
RS
2859
2860(run-hooks 'tex-mode-load-hook)
869bff31 2861
49116ac0
JB
2862(provide 'tex-mode)
2863
dd166d5f 2864;; arch-tag: c0a680b1-63aa-4547-84b9-4193c29c0080
d501f516 2865;;; tex-mode.el ends here