Commit | Line | Data |
---|---|---|
55535639 | 1 | ;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands |
d501f516 | 2 | |
c3ce7bf4 | 3 | ;; Copyright (C) 1985, 86, 89, 92, 94, 95, 96, 97, 98, 1999 |
d61140e8 | 4 | ;; Free Software Foundation, Inc. |
eea8d4ef | 5 | |
70f20973 | 6 | ;; Maintainer: FSF |
d7b4d18f | 7 | ;; Keywords: tex |
e5167999 | 8 | |
528415e7 | 9 | ;; Contributions over the years by William F. Schelter, Dick King, |
70f20973 | 10 | ;; Stephen Gildea, Michael Prange, Jacob Gore, and Edward M. Reingold. |
528415e7 | 11 | |
869bff31 | 12 | ;; This file is part of GNU Emacs. |
13 | ||
14 | ;; GNU Emacs is free software; you can redistribute it and/or modify | |
15 | ;; it under the terms of the GNU General Public License as published by | |
e5167999 | 16 | ;; the Free Software Foundation; either version 2, or (at your option) |
869bff31 | 17 | ;; any later version. |
18 | ||
19 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
20 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
21 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
22 | ;; GNU General Public License for more details. | |
23 | ||
24 | ;; You should have received a copy of the GNU General Public License | |
6da9bbd6 RS |
25 | ;; along with GNU Emacs; see the file COPYING. If not, write to the |
26 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
27 | ;; Boston, MA 02111-1307, USA. | |
869bff31 | 28 | |
55535639 PJ |
29 | ;;; Commentary: |
30 | ||
e5167999 ER |
31 | ;;; Code: |
32 | ||
bed1b0c8 RS |
33 | ;; Pacify the byte-compiler |
34 | (eval-when-compile | |
35 | (require 'compare-w) | |
ea590e1c | 36 | (require 'cl) |
bed1b0c8 RS |
37 | (require 'skeleton)) |
38 | ||
a0e9c22a | 39 | (require 'shell) |
2f3067de | 40 | (require 'compile) |
528415e7 | 41 | |
d61140e8 RS |
42 | (defgroup tex-file nil |
43 | "TeX files and directories" | |
44 | :prefix "tex-" | |
45 | :group 'tex) | |
46 | ||
47 | (defgroup tex-run nil | |
48 | "Running external commands from TeX mode" | |
49 | :prefix "tex-" | |
50 | :group 'tex) | |
51 | ||
52 | (defgroup tex-view nil | |
53 | "Viewing and printing TeX files" | |
54 | :prefix "tex-" | |
55 | :group 'tex) | |
56 | ||
7e1dae73 | 57 | ;;;###autoload |
d61140e8 RS |
58 | (defcustom tex-shell-file-name nil |
59 | "*If non-nil, the shell file name to run in the subshell used to run TeX." | |
60 | :type '(choice (const :tag "None" nil) | |
61 | string) | |
62 | :group 'tex-run) | |
528415e7 | 63 | |
7e1dae73 | 64 | ;;;###autoload |
d61140e8 | 65 | (defcustom tex-directory "." |
f73741fc | 66 | "*Directory in which temporary files are written. |
81c735c0 | 67 | You can make this `/tmp' if your TEXINPUTS has no relative directories in it |
528415e7 | 68 | and you don't try to apply \\[tex-region] or \\[tex-buffer] when there are |
d61140e8 RS |
69 | `\\input' commands with relative directories." |
70 | :type 'directory | |
71 | :group 'tex-file) | |
869bff31 | 72 | |
725b7428 | 73 | ;;;###autoload |
d61140e8 | 74 | (defcustom tex-first-line-header-regexp nil |
725b7428 RS |
75 | "Regexp for matching a first line which `tex-region' should include. |
76 | If this is non-nil, it should be a regular expression string; | |
77 | if it matches the first line of the file, | |
d61140e8 RS |
78 | `tex-region' always includes the first line in the TeX run." |
79 | :type '(choice (const :tag "None" nil) | |
80 | regexp) | |
81 | :group 'tex-file) | |
725b7428 | 82 | |
f73741fc | 83 | ;;;###autoload |
d61140e8 | 84 | (defcustom tex-main-file nil |
f73741fc | 85 | "*The main TeX source file which includes this buffer's file. |
be4a962d RS |
86 | The command `tex-file' runs TeX on the file specified by `tex-main-file' |
87 | if the variable is non-nil." | |
d61140e8 RS |
88 | :type '(choice (const :tag "None" nil) |
89 | file) | |
90 | :group 'tex-file) | |
f73741fc | 91 | |
7e1dae73 | 92 | ;;;###autoload |
d61140e8 RS |
93 | (defcustom tex-offer-save t |
94 | "*If non-nil, ask about saving modified buffers before \\[tex-file] is run." | |
95 | :type 'boolean | |
96 | :group 'tex-file) | |
869bff31 | 97 | |
7e1dae73 | 98 | ;;;###autoload |
d61140e8 | 99 | (defcustom tex-run-command "tex" |
869bff31 | 100 | "*Command used to run TeX subjob. |
c3ce7bf4 RS |
101 | TeX Mode sets `tex-command' to this string. |
102 | See the documentation of that variable." | |
d61140e8 RS |
103 | :type 'string |
104 | :group 'tex-run) | |
869bff31 | 105 | |
7e1dae73 | 106 | ;;;###autoload |
d61140e8 | 107 | (defcustom latex-run-command "latex" |
869bff31 | 108 | "*Command used to run LaTeX subjob. |
c3ce7bf4 RS |
109 | LaTeX Mode sets `tex-command' to this string. |
110 | See the documentation of that variable." | |
d61140e8 RS |
111 | :type 'string |
112 | :group 'tex-run) | |
528415e7 | 113 | |
bed1b0c8 RS |
114 | ;;;###autoload |
115 | (defcustom slitex-run-command "slitex" | |
116 | "*Command used to run SliTeX subjob. | |
c3ce7bf4 RS |
117 | SliTeX Mode sets `tex-command' to this string. |
118 | See the documentation of that variable." | |
bed1b0c8 RS |
119 | :type 'string |
120 | :group 'tex-run) | |
121 | ||
c3ce7bf4 RS |
122 | ;;;###autoload |
123 | (defcustom tex-start-options-string "\\nonstopmode\\input" | |
bed1b0c8 | 124 | "*TeX options to use when running TeX. |
c3ce7bf4 RS |
125 | These precede the input file name. If nil, TeX runs without option. |
126 | See the documentation of `tex-command'." | |
127 | :type '(radio (const :tag "Interactive \(nil\)" nil) | |
128 | (const :tag "Nonstop \(\"\\nonstopmode\\input\"\)" | |
129 | "\\nonstopmode\\input") | |
130 | (string :tag "String at your choice")) | |
bed1b0c8 RS |
131 | :group 'tex-run |
132 | :version "20.4") | |
133 | ||
528415e7 | 134 | (defvar standard-latex-block-names |
dd459839 SM |
135 | '("abstract" "array" "center" "description" |
136 | "displaymath" "document" "enumerate" "eqnarray" | |
137 | "eqnarray*" "equation" "figure" "figure*" | |
138 | "flushleft" "flushright" "itemize" "letter" | |
139 | "list" "minipage" "picture" "quotation" | |
140 | "quote" "slide" "sloppypar" "tabbing" | |
141 | "table" "table*" "tabular" "tabular*" | |
142 | "thebibliography" "theindex*" "titlepage" "trivlist" | |
143 | "verbatim" "verbatim*" "verse" "math") | |
528415e7 RS |
144 | "Standard LaTeX block names.") |
145 | ||
7e1dae73 | 146 | ;;;###autoload |
d61140e8 | 147 | (defcustom latex-block-names nil |
528415e7 | 148 | "*User defined LaTeX block names. |
d61140e8 RS |
149 | Combined with `standard-latex-block-names' for minibuffer completion." |
150 | :type '(repeat string) | |
151 | :group 'tex-run) | |
869bff31 | 152 | |
7e1dae73 | 153 | ;;;###autoload |
d61140e8 | 154 | (defcustom tex-bibtex-command "bibtex" |
528415e7 | 155 | "*Command used by `tex-bibtex-file' to gather bibliographic data. |
81c735c0 | 156 | If this string contains an asterisk (`*'), that is replaced by the file name; |
d61140e8 RS |
157 | otherwise, the file name, preceded by blank, is added at the end." |
158 | :type 'string | |
159 | :group 'tex-run) | |
869bff31 | 160 | |
7e1dae73 | 161 | ;;;###autoload |
d61140e8 | 162 | (defcustom tex-dvi-print-command "lpr -d" |
528415e7 | 163 | "*Command used by \\[tex-print] to print a .dvi file. |
81c735c0 | 164 | If this string contains an asterisk (`*'), that is replaced by the file name; |
d61140e8 RS |
165 | otherwise, the file name, preceded by blank, is added at the end." |
166 | :type 'string | |
167 | :group 'tex-view) | |
528415e7 | 168 | |
7e1dae73 | 169 | ;;;###autoload |
d61140e8 | 170 | (defcustom tex-alt-dvi-print-command "lpr -d" |
528415e7 | 171 | "*Command used by \\[tex-print] with a prefix arg to print a .dvi file. |
81c735c0 RS |
172 | If this string contains an asterisk (`*'), that is replaced by the file name; |
173 | otherwise, the file name, preceded by blank, is added at the end. | |
528415e7 | 174 | |
81c735c0 RS |
175 | If two printers are not enough of a choice, you can set the variable |
176 | `tex-alt-dvi-print-command' to an expression that asks what you want; | |
528415e7 RS |
177 | for example, |
178 | ||
179 | (setq tex-alt-dvi-print-command | |
180 | '(format \"lpr -P%s\" (read-string \"Use printer: \"))) | |
181 | ||
182 | would tell \\[tex-print] with a prefix argument to ask you which printer to | |
d61140e8 RS |
183 | use." |
184 | :type '(choice (string :tag "Command") | |
185 | (sexp :tag "Expression")) | |
186 | :group 'tex-view) | |
869bff31 | 187 | |
7e1dae73 | 188 | ;;;###autoload |
d61140e8 | 189 | (defcustom tex-dvi-view-command nil |
81c735c0 RS |
190 | "*Command used by \\[tex-view] to display a `.dvi' file. |
191 | If this string contains an asterisk (`*'), that is replaced by the file name; | |
192 | otherwise, the file name, preceded by blank, is added at the end. | |
528415e7 RS |
193 | |
194 | This can be set conditionally so that the previewer used is suitable for the | |
195 | window system being used. For example, | |
196 | ||
197 | (setq tex-dvi-view-command | |
198 | (if (eq window-system 'x) \"xdvi\" \"dvi2tty * | cat -s\")) | |
199 | ||
81c735c0 | 200 | would tell \\[tex-view] to use xdvi under X windows and to use dvi2tty |
d61140e8 RS |
201 | otherwise." |
202 | :type '(choice (const nil) string) | |
203 | :group 'tex-view) | |
869bff31 | 204 | |
7e1dae73 | 205 | ;;;###autoload |
d61140e8 | 206 | (defcustom tex-show-queue-command "lpq" |
528415e7 | 207 | "*Command used by \\[tex-show-print-queue] to show the print queue. |
d61140e8 RS |
208 | Should show the queue(s) that \\[tex-print] puts jobs on." |
209 | :type 'string | |
210 | :group 'tex-view) | |
869bff31 | 211 | |
7e1dae73 | 212 | ;;;###autoload |
9920303f | 213 | (defcustom tex-default-mode 'latex-mode |
869bff31 | 214 | "*Mode to enter for a new file that might be either TeX or LaTeX. |
215 | This variable is used when it can't be determined whether the file | |
216 | is plain TeX or LaTeX or what because the file contains no commands. | |
d61140e8 RS |
217 | Normally set to either `plain-tex-mode' or `latex-mode'." |
218 | :type 'function | |
219 | :group 'tex) | |
869bff31 | 220 | |
7e1dae73 | 221 | ;;;###autoload |
d61140e8 RS |
222 | (defcustom tex-open-quote "``" |
223 | "*String inserted by typing \\[tex-insert-quote] to open a quotation." | |
224 | :type 'string | |
225 | :group 'tex) | |
869bff31 | 226 | |
7e1dae73 | 227 | ;;;###autoload |
d61140e8 RS |
228 | (defcustom tex-close-quote "''" |
229 | "*String inserted by typing \\[tex-insert-quote] to close a quotation." | |
230 | :type 'string | |
231 | :group 'tex) | |
869bff31 | 232 | |
528415e7 RS |
233 | (defvar tex-last-temp-file nil |
234 | "Latest temporary file generated by \\[tex-region] and \\[tex-buffer]. | |
235 | Deleted when the \\[tex-region] or \\[tex-buffer] is next run, or when the | |
81c735c0 | 236 | tex shell terminates.") |
528415e7 | 237 | |
869bff31 | 238 | (defvar tex-command nil |
c3ce7bf4 RS |
239 | "*Command to run TeX. |
240 | If this string contains an asterisk \(`*'\), that is replaced by the file name\; | |
241 | otherwise the \(shell-quoted\) value of `tex-start-options-string' and | |
242 | the file name are added at the end, with blanks as separators. | |
243 | ||
244 | In TeX, LaTeX, and SliTeX Mode this variable becomes buffer local. | |
245 | In these modes, use \\[set-variable] if you want to change it for the | |
246 | current buffer.") | |
869bff31 | 247 | |
248 | (defvar tex-trailer nil | |
249 | "String appended after the end of a region sent to TeX by \\[tex-region].") | |
250 | ||
251 | (defvar tex-start-of-header nil | |
898b9ac1 | 252 | "Regular expression used by \\[tex-region] to find start of file's header.") |
869bff31 | 253 | |
254 | (defvar tex-end-of-header nil | |
898b9ac1 | 255 | "Regular expression used by \\[tex-region] to find end of file's header.") |
869bff31 | 256 | |
257 | (defvar tex-shell-cd-command "cd" | |
258 | "Command to give to shell running TeX to change directory. | |
81c735c0 | 259 | The value of `tex-directory' is appended to this, separated by a space.") |
869bff31 | 260 | |
261 | (defvar tex-zap-file nil | |
262 | "Temporary file name used for text being sent as input to TeX. | |
263 | Should be a simple file name with no extension or directory specification.") | |
264 | ||
265 | (defvar tex-last-buffer-texed nil | |
266 | "Buffer which was last TeXed.") | |
267 | ||
268 | (defvar tex-print-file nil | |
269 | "File name that \\[tex-print] prints. | |
270 | Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].") | |
271 | ||
ea590e1c SM |
272 | (easy-mmode-defsyntax tex-mode-syntax-table |
273 | '((?% . "<") | |
274 | (?\n . ">") | |
275 | (?\f . ">") | |
276 | (?\C-@ . "w") | |
277 | (?' . "w") | |
278 | (?@ . "_") | |
279 | (?* . "_") | |
280 | (?\t . " ") | |
281 | (?~ . " ") | |
282 | (?$ . "$$") | |
283 | (?\\ . "/") | |
284 | (?\" . ".") | |
285 | (?& . ".") | |
15ca8de7 SM |
286 | (?_ . ".") |
287 | (?^ . ".")) | |
869bff31 | 288 | "Syntax table used while in TeX mode.") |
53c4fe47 SM |
289 | \f |
290 | ;;;; | |
291 | ;;;; Imenu support | |
292 | ;;;; | |
869bff31 | 293 | |
d6709b80 | 294 | (defcustom latex-imenu-indent-string ". " |
a53c647b RS |
295 | "*String to add repeated in front of nested sectional units for Imenu. |
296 | An alternative value is \" . \", if you use a font with a narrow period." | |
297 | :type 'string | |
298 | :group 'tex) | |
299 | ||
d6709b80 SM |
300 | (defvar latex-section-alist |
301 | '(("part" . 0) ("chapter" . 1) | |
302 | ("section" . 2) ("subsection" . 3) | |
303 | ("subsubsection" . 4) | |
304 | ("paragraph" . 5) ("subparagraph" . 6))) | |
305 | ||
53c4fe47 SM |
306 | (defvar latex-metasection-list |
307 | '("documentstyle" "documentclass" | |
308 | "begin{document}" "end{document}" | |
309 | "appendix" "frontmatter" "mainmatter" "backmatter")) | |
310 | ||
a5e2ae01 | 311 | (defun latex-imenu-create-index () |
53c4fe47 SM |
312 | "Generate an alist for imenu from a LaTeX buffer." |
313 | (let ((section-regexp | |
314 | (concat "\\\\" (regexp-opt (mapcar 'car latex-section-alist) t) | |
315 | "\\*?[ \t]*{")) | |
316 | (metasection-regexp | |
317 | (concat "\\\\" (regexp-opt latex-metasection-list t))) | |
318 | i0 menu case-fold-search) | |
a53c647b RS |
319 | (save-excursion |
320 | ;; Find the top-most level in this file but don't allow it to be | |
321 | ;; any deeper than "section" (which is top-level in an article). | |
322 | (goto-char (point-min)) | |
323 | (if (search-forward-regexp "\\\\part\\*?[ \t]*{" nil t) | |
324 | (setq i0 0) | |
325 | (if (search-forward-regexp "\\\\chapter\\*?[ \t]*{" nil t) | |
326 | (setq i0 1) | |
327 | (setq i0 2))) | |
328 | ||
329 | ;; Look for chapters and sections. | |
330 | (goto-char (point-min)) | |
53c4fe47 | 331 | (while (search-forward-regexp section-regexp nil t) |
a53c647b RS |
332 | (let ((start (match-beginning 0)) |
333 | (here (point)) | |
334 | (i (cdr (assoc (buffer-substring-no-properties | |
335 | (match-beginning 1) | |
336 | (match-end 1)) | |
d6709b80 | 337 | latex-section-alist)))) |
a53c647b RS |
338 | (backward-char 1) |
339 | (condition-case err | |
340 | (progn | |
341 | ;; Using sexps allows some use of matching {...} inside | |
342 | ;; titles. | |
343 | (forward-sexp 1) | |
d6709b80 SM |
344 | (push (cons (concat (apply 'concat |
345 | (make-list | |
346 | (max 0 (- i i0)) | |
347 | latex-imenu-indent-string)) | |
348 | (buffer-substring-no-properties | |
349 | here (1- (point)))) | |
350 | start) | |
351 | menu)) | |
a53c647b RS |
352 | (error nil)))) |
353 | ||
354 | ;; Look for included material. | |
355 | (goto-char (point-min)) | |
356 | (while (search-forward-regexp | |
357 | "\\\\\\(include\\|input\\|verbatiminput\\|bibliography\\)\ | |
53c4fe47 | 358 | \[ \t]*{\\([^}\n]+\\)}" |
a53c647b | 359 | nil t) |
53c4fe47 SM |
360 | (push (cons (concat "<<" (buffer-substring-no-properties |
361 | (match-beginning 2) | |
362 | (match-end 2)) | |
363 | (if (= (char-after (match-beginning 1)) ?b) | |
364 | ".bbl" | |
365 | ".tex")) | |
366 | (match-beginning 0)) | |
367 | menu)) | |
a53c647b RS |
368 | |
369 | ;; Look for \frontmatter, \mainmatter, \backmatter, and \appendix. | |
370 | (goto-char (point-min)) | |
53c4fe47 SM |
371 | (while (search-forward-regexp metasection-regexp nil t) |
372 | (push (cons "--" (match-beginning 0)) menu)) | |
a53c647b RS |
373 | |
374 | ;; Sort in increasing buffer position order. | |
375 | (sort menu (function (lambda (a b) (< (cdr a) (cdr b)))))))) | |
53c4fe47 SM |
376 | \f |
377 | ;;;; | |
378 | ;;;; Outline support | |
379 | ;;;; | |
380 | ||
381 | (defvar latex-outline-regexp | |
382 | (concat "\\\\" | |
383 | (regexp-opt (append latex-metasection-list | |
384 | (mapcar 'car latex-section-alist)) t))) | |
385 | ||
386 | (defun latex-outline-level () | |
387 | (if (looking-at latex-outline-regexp) | |
388 | (1+ (or (cdr (assoc (match-string 1) latex-section-alist)) -1)) | |
389 | 1000)) | |
390 | \f | |
391 | ;;;; | |
392 | ;;;; Font-Lock support | |
393 | ;;;; | |
394 | ||
395 | ;(defvar tex-font-lock-keywords | |
396 | ; ;; Regexps updated with help from Ulrik Dickow <dickow@nbi.dk>. | |
397 | ; '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}" | |
398 | ; 2 font-lock-function-name-face) | |
399 | ; ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}" | |
400 | ; 2 font-lock-constant-face) | |
401 | ; ;; It seems a bit dubious to use `bold' and `italic' faces since we might | |
402 | ; ;; not be able to display those fonts. | |
403 | ; ("{\\\\bf\\([^}]+\\)}" 1 'bold keep) | |
404 | ; ("{\\\\\\(em\\|it\\|sl\\)\\([^}]+\\)}" 2 'italic keep) | |
405 | ; ("\\\\\\([a-zA-Z@]+\\|.\\)" . font-lock-keyword-face) | |
406 | ; ("^[ \t\n]*\\\\def[\\\\@]\\(\\w+\\)" 1 font-lock-function-name-face keep)) | |
407 | ; ;; Rewritten and extended for LaTeX2e by Ulrik Dickow <dickow@nbi.dk>. | |
408 | ; '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}" | |
409 | ; 2 font-lock-function-name-face) | |
410 | ; ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}" | |
411 | ; 2 font-lock-constant-face) | |
412 | ; ("^[ \t]*\\\\def\\\\\\(\\(\\w\\|@\\)+\\)" 1 font-lock-function-name-face) | |
413 | ; "\\\\\\([a-zA-Z@]+\\|.\\)" | |
414 | ; ;; It seems a bit dubious to use `bold' and `italic' faces since we might | |
415 | ; ;; not be able to display those fonts. | |
416 | ; ;; LaTeX2e: \emph{This is emphasized}. | |
417 | ; ("\\\\emph{\\([^}]+\\)}" 1 'italic keep) | |
418 | ; ;; LaTeX2e: \textbf{This is bold}, \textit{...}, \textsl{...} | |
419 | ; ("\\\\text\\(\\(bf\\)\\|it\\|sl\\){\\([^}]+\\)}" | |
420 | ; 3 (if (match-beginning 2) 'bold 'italic) keep) | |
421 | ; ;; Old-style bf/em/it/sl. Stop at `\\' and un-escaped `&', for tables. | |
422 | ; ("\\\\\\(\\(bf\\)\\|em\\|it\\|sl\\)\\>\\(\\([^}&\\]\\|\\\\[^\\]\\)+\\)" | |
423 | ; 3 (if (match-beginning 2) 'bold 'italic) keep)) | |
424 | ||
425 | ;; Rewritten with the help of Alexandra Bac <abac@welcome.disi.unige.it>. | |
426 | (defconst tex-font-lock-keywords-1 | |
427 | (eval-when-compile | |
428 | (let* (;; Names of commands whose arg should be fontified as heading, etc. | |
429 | (headings (regexp-opt | |
430 | '("title" "begin" "end" "chapter" "part" | |
431 | "section" "subsection" "subsubsection" | |
432 | "paragraph" "subparagraph" "subsubparagraph" | |
433 | "newcommand" "renewcommand" "newenvironment" | |
434 | "newtheorem") | |
435 | t)) | |
436 | (variables (regexp-opt | |
437 | '("newcounter" "newcounter*" "setcounter" "addtocounter" | |
438 | "setlength" "addtolength" "settowidth") | |
439 | t)) | |
440 | (includes (regexp-opt | |
441 | '("input" "include" "includeonly" "bibliography" | |
442 | "epsfig" "psfig" "epsf" "nofiles" "usepackage" | |
15ca8de7 | 443 | "documentstyle" "documentclass" "verbatiminput" |
53c4fe47 SM |
444 | "includegraphics" "includegraphics*") |
445 | t)) | |
446 | ;; Miscellany. | |
447 | (slash "\\\\") | |
15ca8de7 SM |
448 | (opt " *\\(\\[[^]]*\\] *\\)*") |
449 | ;; This would allow highlighting \newcommand\CMD but requires | |
450 | ;; adapting subgroup numbers below. | |
451 | ;; (arg "\\(?:{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)\\|\\\\[a-z*]+\\)")) | |
1598a961 | 452 | (arg "{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)")) |
53c4fe47 SM |
453 | (list |
454 | ;; Heading args. | |
455 | (list (concat slash headings "\\*?" opt arg) | |
bdbd9606 SM |
456 | ;; If ARG ends up matching too much (if the {} don't match, f.ex) |
457 | ;; jit-lock will do funny things: when updating the buffer | |
458 | ;; the re-highlighting is only done locally so it will just | |
459 | ;; match the local line, but defer-contextually will | |
460 | ;; match more lines at a time, so ARG will end up matching | |
461 | ;; a lot more, which might suddenly include a comment | |
462 | ;; so you get things highlighted bold when you type them | |
463 | ;; but they get turned back to normal a little while later | |
464 | ;; because "there's already a face there". | |
465 | ;; Using `keep' works around this un-intuitive behavior as well | |
15ca8de7 SM |
466 | ;; as improves the behavior in the very rare case where you do |
467 | ;; have a comment in ARG. | |
bdbd9606 | 468 | 3 'font-lock-function-name-face 'keep) |
15ca8de7 SM |
469 | (list (concat slash "\\(re\\)?newcommand\\** *\\(\\\\[A-Za-z@]+\\)") |
470 | 2 'font-lock-function-name-face 'keep) | |
53c4fe47 | 471 | ;; Variable args. |
15ca8de7 | 472 | (list (concat slash variables " *" arg) 2 'font-lock-variable-name-face) |
53c4fe47 SM |
473 | ;; Include args. |
474 | (list (concat slash includes opt arg) 3 'font-lock-builtin-face) | |
475 | ;; Definitions. I think. | |
15ca8de7 | 476 | '("^[ \t]*\\\\def *\\\\\\(\\(\\w\\|@\\)+\\)" |
bdbd9606 | 477 | 1 font-lock-function-name-face)))) |
53c4fe47 SM |
478 | "Subdued expressions to highlight in TeX modes.") |
479 | ||
480 | (defconst tex-font-lock-keywords-2 | |
481 | (append tex-font-lock-keywords-1 | |
482 | (eval-when-compile | |
483 | (let* (;; | |
484 | ;; Names of commands whose arg should be fontified with fonts. | |
1598a961 | 485 | (bold (regexp-opt '("textbf" "textsc" "textup" |
53c4fe47 | 486 | "boldsymbol" "pmb") t)) |
1598a961 | 487 | (italic (regexp-opt '("textit" "textsl" "emph") t)) |
53c4fe47 SM |
488 | (type (regexp-opt '("texttt" "textmd" "textrm" "textsf") t)) |
489 | ;; | |
490 | ;; Names of commands whose arg should be fontified as a citation. | |
491 | (citations (regexp-opt | |
492 | '("label" "ref" "pageref" "vref" "eqref" | |
15ca8de7 | 493 | "cite" "nocite" "index" "glossary" "bibitem" |
1598a961 SM |
494 | ;; These are text, rather than citations. |
495 | ;; "caption" "footnote" "footnotemark" "footnotetext" | |
496 | ) | |
53c4fe47 SM |
497 | t)) |
498 | ;; | |
499 | ;; Names of commands that should be fontified. | |
500 | (specials (regexp-opt | |
15ca8de7 | 501 | '("\\" "\\*" ;; "-" |
53c4fe47 SM |
502 | "linebreak" "nolinebreak" "pagebreak" "nopagebreak" |
503 | "newline" "newpage" "clearpage" "cleardoublepage" | |
504 | "displaybreak" "allowdisplaybreaks" "enlargethispage") | |
505 | t)) | |
506 | (general "\\([a-zA-Z@]+\\**\\|[^ \t\n]\\)") | |
507 | ;; | |
508 | ;; Miscellany. | |
509 | (slash "\\\\") | |
15ca8de7 | 510 | (opt " *\\(\\[[^]]*\\] *\\)*") |
1598a961 | 511 | (arg "{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)")) |
53c4fe47 SM |
512 | (list |
513 | ;; | |
514 | ;; Citation args. | |
515 | (list (concat slash citations opt arg) 3 'font-lock-constant-face) | |
516 | ;; | |
15ca8de7 SM |
517 | ;; Text between `` quotes ''. |
518 |