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