1;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- lexical-binding:t -*- 2 3;; Copyright (C) 1985-1986, 1989, 1992, 1994-1999, 2001-2021 Free 4;; Software Foundation, Inc. 5 6;; Maintainer: emacs-devel@gnu.org 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 3 of the License, or 17;; (at your option) 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. If not, see <https://www.gnu.org/licenses/>. 26 27;;; Commentary: 28 29;;; Code: 30 31;; Pacify the byte-compiler 32(eval-when-compile 33 (require 'compare-w) 34 (require 'cl-lib) 35 (require 'skeleton)) 36 37(defvar font-lock-comment-face) 38(defvar font-lock-doc-face) 39 40(require 'shell) 41(require 'compile) 42 43(defgroup tex-file nil 44 "TeX files and directories." 45 :prefix "tex-" 46 :group 'tex) 47 48(defgroup tex-run nil 49 "Running external commands from TeX mode." 50 :prefix "tex-" 51 :group 'tex) 52 53(defgroup tex-view nil 54 "Viewing and printing TeX files." 55 :prefix "tex-" 56 :group 'tex) 57 58(defgroup tex-flymake nil 59 "Flymake backend for linting TeX files." 60 :prefix "tex-" 61 :group 'tex) 62 63;;;###autoload 64(defcustom tex-shell-file-name nil 65 "If non-nil, the shell file name to run in the subshell used to run TeX." 66 :type '(choice (const :tag "None" nil) 67 string) 68 :group 'tex-run) 69 70;;;###autoload 71(defcustom tex-directory (purecopy ".") 72 "Directory in which temporary files are written. 73You can make this `/tmp' if your TEXINPUTS has no relative directories in it 74and you don't try to apply \\[tex-region] or \\[tex-buffer] when there are 75`\\input' commands with relative directories." 76 :type 'directory 77 :group 'tex-file) 78 79;;;###autoload 80(defcustom tex-first-line-header-regexp nil 81 "Regexp for matching a first line which `tex-region' should include. 82If this is non-nil, it should be a regular expression string; 83if it matches the first line of the file, 84`tex-region' always includes the first line in the TeX run." 85 :type '(choice (const :tag "None" nil) 86 regexp) 87 :group 'tex-file) 88 89;;;###autoload 90(defcustom tex-main-file nil 91 "The main TeX source file which includes this buffer's file. 92The command `tex-file' runs TeX on the file specified by `tex-main-file' 93if the variable is non-nil." 94 :type '(choice (const :tag "None" nil) 95 file) 96 :group 'tex-file) 97 98;;;###autoload 99(defcustom tex-offer-save t 100 "If non-nil, ask about saving modified buffers before \\[tex-file] is run." 101 :type 'boolean 102 :group 'tex-file) 103 104;;;###autoload 105(defcustom tex-run-command (purecopy "tex") 106 "Command used to run TeX subjob. 107TeX Mode sets `tex-command' to this string. 108See the documentation of that variable." 109 :type 'string 110 :group 'tex-run) 111 112;;;###autoload 113(defcustom latex-run-command (purecopy "latex") 114 "Command used to run LaTeX subjob. 115LaTeX Mode sets `tex-command' to this string. 116See the documentation of that variable." 117 :type 'string 118 :group 'tex-run) 119 120;;;###autoload 121(defcustom slitex-run-command (purecopy "slitex") 122 "Command used to run SliTeX subjob. 123SliTeX Mode sets `tex-command' to this string. 124See the documentation of that variable." 125 :type 'string 126 :group 'tex-run) 127 128;;;###autoload 129(defcustom tex-start-options (purecopy "") 130 "TeX options to use when starting TeX. 131These immediately precede the commands in `tex-start-commands' 132and the input file name, with no separating space and are not shell-quoted. 133If nil, TeX runs with no options. See the documentation of `tex-command'." 134 :type 'string 135 :group 'tex-run 136 :version "22.1") 137 138;;;###autoload 139(defcustom tex-start-commands (purecopy "\\nonstopmode\\input") 140 "TeX commands to use when starting TeX. 141They are shell-quoted and precede the input file name, with a separating space. 142If nil, no commands are used. See the documentation of `tex-command'." 143 :type '(radio (const :tag "Interactive (nil)" nil) 144 (const :tag "Nonstop (\"\\nonstopmode\\input\")" 145 "\\nonstopmode\\input") 146 (string :tag "String at your choice")) 147 :group 'tex-run 148 :version "22.1") 149 150(defvar latex-standard-block-names 151 '("abstract" "array" "center" "description" 152 "displaymath" "document" "enumerate" "eqnarray" 153 "eqnarray*" "equation" "figure" "figure*" 154 "flushleft" "flushright" "itemize" "letter" 155 "list" "minipage" "picture" "quotation" 156 "quote" "slide" "sloppypar" "tabbing" 157 "table" "table*" "tabular" "tabular*" 158 "thebibliography" "theindex*" "titlepage" "trivlist" 159 "verbatim" "verbatim*" "verse" "math") 160 "Standard LaTeX block names.") 161 162;;;###autoload 163(defcustom latex-block-names nil 164 "User defined LaTeX block names. 165Combined with `latex-standard-block-names' for minibuffer completion." 166 :type '(repeat string) 167 :group 'tex-run) 168 169;;;###autoload 170(defcustom tex-bibtex-command (purecopy "bibtex") 171 "Command used by `tex-bibtex-file' to gather bibliographic data. 172If this string contains an asterisk (`*'), that is replaced by the file name; 173otherwise, the file name, preceded by blank, is added at the end." 174 :type 'string 175 :group 'tex-run) 176 177;;;###autoload 178(defcustom tex-dvi-print-command (purecopy "lpr -d") 179 "Command used by \\[tex-print] to print a .dvi file. 180If this string contains an asterisk (`*'), that is replaced by the file name; 181otherwise, the file name, preceded by blank, is added at the end." 182 :type 'string 183 :group 'tex-view) 184 185;;;###autoload 186(defcustom tex-alt-dvi-print-command (purecopy "lpr -d") 187 "Command used by \\[tex-print] with a prefix arg to print a .dvi file. 188If this string contains an asterisk (`*'), that is replaced by the file name; 189otherwise, the file name, preceded by blank, is added at the end. 190 191If two printers are not enough of a choice, you can set the variable 192`tex-alt-dvi-print-command' to an expression that asks what you want; 193for example, 194 195 (setq tex-alt-dvi-print-command 196 \\='(format \"lpr -P%s\" (read-string \"Use printer: \"))) 197 198would tell \\[tex-print] with a prefix argument to ask you which printer to 199use." 200 :type '(choice (string :tag "Command") 201 (sexp :tag "Expression")) 202 :group 'tex-view) 203 204;;;###autoload 205(defcustom tex-dvi-view-command 206 `(cond 207 ((eq window-system 'x) ,(purecopy "xdvi")) 208 ((eq window-system 'w32) ,(purecopy "yap")) 209 (t ,(purecopy "dvi2tty * | cat -s"))) 210 "Command used by \\[tex-view] to display a `.dvi' file. 211If it is a string, that specifies the command directly. 212If this string contains an asterisk (`*'), that is replaced by the file name; 213otherwise, the file name, preceded by a space, is added at the end. 214 215If the value is a form, it is evaluated to get the command to use." 216 :type '(choice (const nil) string sexp) 217 :group 'tex-view) 218 219;;;###autoload 220(defcustom tex-show-queue-command (purecopy "lpq") 221 "Command used by \\[tex-show-print-queue] to show the print queue. 222Should show the queue(s) that \\[tex-print] puts jobs on." 223 :type 'string 224 :group 'tex-view) 225 226;;;###autoload 227(defcustom tex-default-mode 'latex-mode 228 "Mode to enter for a new file that might be either TeX or LaTeX. 229This variable is used when it can't be determined whether the file 230is plain TeX or LaTeX or what because the file contains no commands. 231Normally set to either `plain-tex-mode' or `latex-mode'." 232 :type 'function 233 :group 'tex) 234 235;;;###autoload 236(defcustom tex-open-quote (purecopy "``") 237 "String inserted by typing \\[tex-insert-quote] to open a quotation." 238 :type 'string 239 :options '("``" "\"<" "\"`" "<<" "«") 240 :group 'tex) 241 242;;;###autoload 243(defcustom tex-close-quote (purecopy "''") 244 "String inserted by typing \\[tex-insert-quote] to close a quotation." 245 :type 'string 246 :options '("''" "\">" "\"'" ">>" "»") 247 :group 'tex) 248 249(defcustom tex-fontify-script t 250 "If non-nil, fontify subscript and superscript strings." 251 :type 'boolean 252 :group 'tex 253 :version "23.1") 254(put 'tex-fontify-script 'safe-local-variable #'booleanp) 255 256(defcustom tex-font-script-display '(-0.2 0.2) 257 "How much to lower and raise subscript and superscript content. 258This is a list of two floats. The first is negative and 259specifies how much subscript is lowered, the second is positive 260and specifies how much superscript is raised. Heights are 261measured relative to that of the normal text." 262 :group 'tex 263 :type '(list (float :tag "Subscript") 264 (float :tag "Superscript")) 265 :version "23.1") 266 267(defcustom tex-chktex-program "chktex" 268 "ChkTeX executable to use for linting TeX files." 269 :version "26.1" 270 :type 'string 271 :link '(url-link "man:chktex(1)") 272 :group 'tex-flymake) 273 274(defcustom tex-chktex-extra-flags nil 275 "Extra command line flags for `tex-chktex-program'." 276 :version "26.1" 277 :type '(repeat string) 278 :group 'tex-flymake) 279 280(defvar tex-last-temp-file nil 281 "Latest temporary file generated by \\[tex-region] and \\[tex-buffer]. 282Deleted when the \\[tex-region] or \\[tex-buffer] is next run, or when the 283tex shell terminates.") 284 285(defvar tex-command "tex" 286 "Command to run TeX. 287If this string contains an asterisk \(`*'), that is replaced by the file name; 288otherwise the value of `tex-start-options', the \(shell-quoted) 289value of `tex-start-commands', and the file name are added at the end 290with blanks as separators. 291 292In TeX, LaTeX, and SliTeX Mode this variable becomes buffer local.") 293 294(defvar tex-trailer nil 295 "String appended after the end of a region sent to TeX by \\[tex-region].") 296 297(defvar tex-start-of-header nil 298 "Regular expression used by \\[tex-region] to find start of file's header.") 299 300(defvar tex-end-of-header nil 301 "Regular expression used by \\[tex-region] to find end of file's header.") 302 303(defvar tex-shell-cd-command "cd" 304 "Command to give to shell running TeX to change directory. 305The value of `tex-directory' is appended to this, separated by a space.") 306 307(defvar tex-zap-file nil 308 "Temporary file name used for text being sent as input to TeX. 309Should be a simple file name with no extension or directory specification.") 310 311(defvar tex-last-buffer-texed nil 312 "Buffer which was last TeXed.") 313 314(defvar tex-print-file nil 315 "File name that \\[tex-print] prints. 316Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].") 317 318(defvar tex-mode-syntax-table 319 (let ((st (make-syntax-table))) 320 (modify-syntax-entry ?% "<" st) 321 (modify-syntax-entry ?\n ">" st) 322 (modify-syntax-entry ?\f ">" st) 323 (modify-syntax-entry ?\C-@ "w" st) 324 (modify-syntax-entry ?' "w" st) 325 (modify-syntax-entry ?@ "_" st) 326 (modify-syntax-entry ?* "_" st) 327 (modify-syntax-entry ?\t " " st) 328 ;; ~ is printed by TeX as a space, but it's semantics in the syntax 329 ;; of TeX is not `whitespace' (i.e. it's just like \hspace{foo}). 330 (modify-syntax-entry ?~ "." st) 331 (modify-syntax-entry ?$ "$$" st) 332 (modify-syntax-entry ?\\ "/" st) 333 (modify-syntax-entry ?\" "." st) 334 (modify-syntax-entry ?& "." st) 335 (modify-syntax-entry ?_ "." st) 336 (modify-syntax-entry ?^ "." st) 337 st) 338 "Syntax table used while in TeX mode.") 339 340;;;; 341;;;; Imenu support 342;;;; 343 344(defcustom latex-imenu-indent-string ". " 345 "String to add repeated in front of nested sectional units for Imenu. 346An alternative value is \" . \", if you use a font with a narrow period." 347 :type 'string 348 :group 'tex) 349 350(defvar latex-section-alist 351 '(("part" . 0) ("chapter" . 1) 352 ("section" . 2) ("subsection" . 3) 353 ("subsubsection" . 4) 354 ("paragraph" . 5) ("subparagraph" . 6))) 355 356(defvar latex-metasection-list 357 '("documentstyle" "documentclass" 358 "begin{document}" "end{document}" 359 "appendix" "frontmatter" "mainmatter" "backmatter")) 360 361(defun latex-imenu-create-index () 362 "Generate an alist for imenu from a LaTeX buffer." 363 (let ((section-regexp 364 (concat "\\\\" (regexp-opt (mapcar #'car latex-section-alist) t) 365 "\\*?[ \t]*{")) 366 (metasection-regexp 367 (concat "\\\\" (regexp-opt latex-metasection-list t))) 368 i0 menu case-fold-search) 369 (save-excursion 370 ;; Find the top-most level in this file but don't allow it to be 371 ;; any deeper than "section" (which is top-level in an article). 372 (goto-char (point-min)) 373 (if (search-forward-regexp "\\\\part\\*?[ \t]*{" nil t) 374 (setq i0 0) 375 (if (search-forward-regexp "\\\\chapter\\*?[ \t]*{" nil t) 376 (setq i0 1) 377 (setq i0 2))) 378 379 ;; Look for chapters and sections. 380 (goto-char (point-min)) 381 (while (search-forward-regexp section-regexp nil t) 382 (let ((start (match-beginning 0)) 383 (here (point)) 384 (i (cdr (assoc (buffer-substring-no-properties 385 (match-beginning 1) 386 (match-end 1)) 387 latex-section-alist)))) 388 (backward-char 1) 389 (condition-case nil 390 (progn 391 ;; Using sexps allows some use of matching {...} inside 392 ;; titles. 393 (forward-sexp 1) 394 (push (cons (concat (apply #'concat 395 (make-list 396 (max 0 (- i i0)) 397 latex-imenu-indent-string)) 398 (buffer-substring-no-properties 399 here (1- (point)))) 400 start) 401 menu)) 402 (error nil)))) 403 404 ;; Look for included material. 405 (goto-char (point-min)) 406 (while (search-forward-regexp 407 "\\\\\\(include\\|input\\|verbatiminput\\|bibliography\\)\ 408[ \t]*{\\([^}\n]+\\)}" 409 nil t) 410 (push (cons (concat "<<" (buffer-substring-no-properties 411 (match-beginning 2) 412 (match-end 2)) 413 (if (= (char-after (match-beginning 1)) ?b) 414 ".bbl" 415 ".tex")) 416 (match-beginning 0)) 417 menu)) 418 419 ;; Look for \frontmatter, \mainmatter, \backmatter, and \appendix. 420 (goto-char (point-min)) 421 (while (search-forward-regexp metasection-regexp nil t) 422 (push (cons "--" (match-beginning 0)) menu)) 423 424 ;; Sort in increasing buffer position order. 425 (sort menu (function (lambda (a b) (< (cdr a) (cdr b)))))))) 426 427;;;; 428;;;; Outline support 429;;;; 430 431(defvar latex-outline-regexp 432 (concat "\\\\" 433 (regexp-opt (append latex-metasection-list 434 (mapcar #'car latex-section-alist)) 435 t))) 436 437(defun latex-outline-level () 438 (if (looking-at latex-outline-regexp) 439 (1+ (or (cdr (assoc (match-string 1) latex-section-alist)) -1)) 440 1000)) 441 442(defun tex-current-defun-name () 443 "Return the name of the TeX section/paragraph/chapter at point, or nil." 444 (save-excursion 445 (when (re-search-backward 446 "\\\\\\(sub\\)*\\(section\\|paragraph\\|chapter\\)" 447 nil t) 448 (goto-char (match-beginning 0)) 449 (buffer-substring-no-properties 450 (1+ (point)) ; without initial backslash 451 (line-end-position))))) 452 453;;;; 454;;;; Font-Lock support 455;;;; 456 457;(defvar tex-font-lock-keywords 458; ;; Regexps updated with help from Ulrik Dickow <dickow@nbi.dk>. 459; '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}" 460; 2 font-lock-function-name-face) 461; ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}" 462; 2 font-lock-constant-face) 463; ;; It seems a bit dubious to use `bold' and `italic' faces since we might 464; ;; not be able to display those fonts. 465; ("{\\\\bf\\([^}]+\\)}" 1 'bold keep) 466; ("{\\\\\\(em\\|it\\|sl\\)\\([^}]+\\)}" 2 'italic keep) 467; ("\\\\\\([a-zA-Z@]+\\|.\\)" . font-lock-keyword-face) 468; ("^[ \t\n]*\\\\def[\\\\@]\\(\\w+\\)" 1 font-lock-function-name-face keep)) 469; ;; Rewritten and extended for LaTeX2e by Ulrik Dickow <dickow@nbi.dk>. 470; '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}" 471; 2 font-lock-function-name-face) 472; ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}" 473; 2 font-lock-constant-face) 474; ("^[ \t]*\\\\def\\\\\\(\\(\\w\\|@\\)+\\)" 1 font-lock-function-name-face) 475; "\\\\\\([a-zA-Z@]+\\|.\\)" 476; ;; It seems a bit dubious to use `bold' and `italic' faces since we might 477; ;; not be able to display those fonts. 478; ;; LaTeX2e: \emph{This is emphasized}. 479; ("\\\\emph{\\([^}]+\\)}" 1 'italic keep) 480; ;; LaTeX2e: \textbf{This is bold}, \textit{...}, \textsl{...} 481; ("\\\\text\\(\\(bf\\)\\|it\\|sl\\){\\([^}]+\\)}" 482; 3 (if (match-beginning 2) 'bold 'italic) keep) 483; ;; Old-style bf/em/it/sl. Stop at `\\' and un-escaped `&', for tables. 484; ("\\\\\\(\\(bf\\)\\|em\\|it\\|sl\\)\\>\\(\\([^}&\\]\\|\\\\[^\\]\\)+\\)" 485; 3 (if (match-beginning 2) 'bold 'italic) keep)) 486 487;; Rewritten with the help of Alexandra Bac <abac@welcome.disi.unige.it>. 488(defconst tex-font-lock-keywords-1 489 (eval-when-compile 490 (let* (;; Names of commands whose arg should be fontified as heading, etc. 491 (headings (regexp-opt 492 '("title" "begin" "end" "chapter" "part" 493 "section" "subsection" "subsubsection" 494 "paragraph" "subparagraph" "subsubparagraph" 495 "newcommand" "renewcommand" "providecommand" 496 "newenvironment" "renewenvironment" 497 "newtheorem" "renewtheorem") 498 t)) 499 (variables (regexp-opt 500 '("newcounter" "newcounter*" "setcounter" "addtocounter" 501 "setlength" "addtolength" "settowidth") 502 t)) 503 (includes (regexp-opt 504 '("input" "include" "includeonly" "bibliography" 505 "epsfig" "psfig" "epsf" "nofiles" "usepackage" 506 "documentstyle" "documentclass" "verbatiminput" 507 "includegraphics" "includegraphics*") 508 t)) 509 (verbish (regexp-opt '("url" "nolinkurl" "path") t)) 510 ;; Miscellany. 511 (slash "\\\\") 512 (opt " *\\(\\[[^]]*\\] *\\)*") 513 ;; This would allow highlighting \newcommand\CMD but requires 514 ;; adapting subgroup numbers below. 515 ;; (arg "\\(?:{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)\\|\\\\[a-z*]+\\)")) 516 (inbraces-re (lambda (re) 517 (concat "\\(?:[^{}\\]\\|\\\\.\\|" re "\\)"))) 518 (arg (concat "{\\(" (funcall inbraces-re "{[^}]*}") "+\\)"))) 519 `( ;; Highlight $$math$$ and $math$. 520 ;; This is done at the very beginning so as to interact with the other 521 ;; keywords in the same way as comments and strings. 522 (,(concat "\\$\\$?\\(?:[^$\\{}]\\|\\\\.\\|{" 523 (funcall inbraces-re 524 (concat "{" (funcall inbraces-re "{[^}]*}") "*}")) 525 "*}\\)+\\$?\\$") 526 (0 'tex-math)) 527 ;; Heading args. 528 (,(concat slash headings "\\*?" opt arg) 529 ;; If ARG ends up matching too much (if the {} don't match, e.g.) 530 ;; jit-lock will do funny things: when updating the buffer 531 ;; the re-highlighting is only done locally so it will just 532 ;; match the local line, but defer-contextually will 533 ;; match more lines at a time, so ARG will end up matching 534 ;; a lot more, which might suddenly include a comment 535 ;; so you get things highlighted bold when you type them 536 ;; but they get turned back to normal a little while later 537 ;; because "there's already a face there". 538 ;; Using `keep' works around this un-intuitive behavior as well 539 ;; as improves the behavior in the very rare case where you do 540 ;; have a comment in ARG. 541 3 font-lock-function-name-face keep) 542 (,(concat slash "\\(?:provide\\|\\(?:re\\)?new\\)command\\** *\\(\\\\[A-Za-z@]+\\)") 543 1 font-lock-function-name-face keep) 544 ;; Variable args. 545 (,(concat slash variables " *" arg) 2 font-lock-variable-name-face) 546 ;; Include args. 547 (,(concat slash includes opt arg) 3 font-lock-builtin-face) 548 ;; Verbatim-like args. 549 (,(concat slash verbish opt arg) 3 'tex-verbatim t) 550 ;; Definitions. I think. 551 ("^[ \t]*\\\\def *\\\\\\(\\(\\w\\|@\\)+\\)" 552 1 font-lock-function-name-face)))) 553 "Subdued expressions to highlight in TeX modes.") 554 555(defun tex-font-lock-append-prop (prop) 556 (unless (memq (get-text-property (match-end 1) 'face) 557 '(font-lock-comment-face tex-verbatim)) 558 prop)) 559 560(defconst tex-font-lock-keywords-2 561 (append tex-font-lock-keywords-1 562 (eval-when-compile 563 (let* (;; 564 ;; Names of commands whose arg should be fontified with fonts. 565 (bold (regexp-opt '("textbf" "textsc" "textup" 566 "boldsymbol" "pmb") 567 t)) 568 (italic (regexp-opt '("textit" "textsl" "emph") t)) 569 ;; FIXME: unimplemented yet. 570 ;; (type (regexp-opt '("texttt" "textmd" "textrm" "textsf") t)) 571 ;; 572 ;; Names of commands whose arg should be fontified as a citation. 573 (citations (regexp-opt 574 '("label" "ref" "pageref" "vref" "eqref" 575 "cite" "nocite" "index" "glossary" "bibitem" 576 ;; natbib's two variants of \cite: 577 "citep" "citet" 578 ;; These are text, rather than citations. 579 ;; "caption" "footnote" "footnotemark" "footnotetext" 580 ) 581 t)) 582 ;; 583 ;; Names of commands that should be fontified. 584 (specials-1 (regexp-opt '("\\" "\\*") t)) ;; "-" 585 (specials-2 (regexp-opt 586 '("linebreak" "nolinebreak" "pagebreak" "nopagebreak" 587 "newline" "newpage" "clearpage" "cleardoublepage" 588 "displaybreak" "allowdisplaybreaks" 589 "enlargethispage") 590 t)) 591 (general "\\([a-zA-Z@]+\\**\\|[^ \t\n]\\)") 592 ;; 593 ;; Miscellany. 594 (slash "\\\\") 595 (opt " *\\(\\[[^]]*\\] *\\)*") 596 (args "\\(\\(?:[^{}&\\]+\\|\\\\.\\|{[^}]*}\\)+\\)") 597 (arg "{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)")) 598 (list 599 ;; 600 ;; Citation args. 601 (list (concat slash citations opt arg) 3 'font-lock-constant-face) 602 ;; 603 ;; Text between `` quotes ''. 604 (cons (concat (regexp-opt '("``" "\"<" "\"`" "<<" "«") t) 605 "[^'\">{]+" ;a bit pessimistic 606 (regexp-opt '("''" "\">" "\"'" ">>" "»") t)) 607 'font-lock-string-face) 608 ;; 609 ;; Command names, special and general. 610 (cons (concat slash specials-1) 'font-lock-warning-face) 611 (list (concat "\\(" slash specials-2 "\\)\\([^a-zA-Z@]\\|\\'\\)") 612 1 'font-lock-warning-face) 613 (concat slash general) 614 ;; 615 ;; Font environments. It seems a bit dubious to use `bold' etc. faces 616 ;; since we might not be able to display those fonts. 617 (list (concat slash bold " *" arg) 2 618 '(tex-font-lock-append-prop 'bold) 'append) 619 (list (concat slash italic " *" arg) 2 620 '(tex-font-lock-append-prop 'italic) 'append) 621 ;; (list (concat slash type arg) 2 '(quote bold-italic) 'append) 622 ;; 623 ;; Old-style bf/em/it/sl. Stop at `\\' and un-escaped `&', for tables. 624 (list (concat "\\\\\\(em\\|it\\|sl\\)\\>" args) 625 2 '(tex-font-lock-append-prop 'italic) 'append) 626 ;; This is separate from the previous one because of cases like 627 ;; {\em foo {\bf bar} bla} where both match. 628 (list (concat "\\\\\\(bf\\(series\\)?\\)\\>" args) 629 3 '(tex-font-lock-append-prop 'bold) 'append))))) 630 "Gaudy expressions to highlight in TeX modes.") 631 632(defun tex-font-lock-suscript (pos) 633 (unless (or (memq (get-text-property pos 'face) 634 '(font-lock-constant-face font-lock-builtin-face 635 font-lock-comment-face tex-verbatim)) 636 ;; Check for backslash quoting 637 (let ((odd nil) 638 (pos pos)) 639 (while (eq (char-before pos) ?\\) 640 (setq pos (1- pos) odd (not odd))) 641 odd)) 642 (if (eq (char-after pos) ?_) 643 `(face subscript display (raise ,(car tex-font-script-display))) 644 `(face superscript display (raise ,(cadr tex-font-script-display)))))) 645 646(defun tex-font-lock-match-suscript (limit) 647 "Match subscript and superscript patterns up to LIMIT." 648 (when (and tex-fontify-script 649 (re-search-forward "[_^] *\\([^\n\\{}]\\|\ 650\\\\\\([a-zA-Z@]+\\|[^ \t\n]\\)\\|\\({\\)\\)" limit t)) 651 (when (match-end 3) 652 (let ((beg (match-beginning 3)) 653 (end (save-restriction 654 (narrow-to-region (point-min) limit) 655 (condition-case nil (scan-lists (point) 1 1) (error nil))))) 656 (store-match-data (if end 657 (list (match-beginning 0) end beg end) 658 (list beg beg beg beg))))) 659 t)) 660 661(defconst tex-font-lock-keywords-3 662 (append tex-font-lock-keywords-2 663 '((tex-font-lock-match-suscript 664 (1 (tex-font-lock-suscript (match-beginning 0)) append)))) 665 "Experimental expressions to highlight in TeX modes.") 666 667(defconst tex-font-lock-keywords tex-font-lock-keywords-1 668 "Default expressions to highlight in TeX modes.") 669 670(defvar tex-verbatim-environments 671 '("verbatim" "verbatim*")) 672(put 'tex-verbatim-environments 'safe-local-variable 673 (lambda (x) (not (memq nil (mapcar #'stringp x))))) 674 675(eval-when-compile 676 (defconst tex-syntax-propertize-rules 677 (syntax-propertize-precompile-rules 678 ("\\\\verb\\**\\([^a-z@*]\\)" 679 (1 (prog1 "\"" 680 (tex-font-lock-verb 681 (match-beginning 0) (char-after (match-beginning 1)))))))) 682 683 (defconst latex-syntax-propertize-rules 684 (syntax-propertize-precompile-rules 685 tex-syntax-propertize-rules 686 ("\\\\\\(?:end\\|begin\\) *\\({[^\n{}]*}\\)" 687 (1 (ignore 688 (tex-env-mark (match-beginning 0) 689 (match-beginning 1) (match-end 1)))))))) 690 691(defun tex-env-mark (cmd start end) 692 (when (= cmd (line-beginning-position)) 693 (let ((arg (buffer-substring-no-properties (1+ start) (1- end)))) 694 (when (member arg tex-verbatim-environments) 695 (if (eq ?b (char-after (1+ cmd))) 696 ;; \begin 697 (put-text-property (line-end-position) 698 (line-beginning-position 2) 699 'syntax-table (string-to-syntax "< c")) 700 ;; In the case of an empty verbatim env, the \n after the \begin is 701 ;; the same as the \n before the \end. Lucky for us, the "> c" 702 ;; property associated to the \end will be placed afterwards, so it 703 ;; will override the "< c". 704 (put-text-property (1- cmd) cmd 705 'syntax-table (string-to-syntax "> c")) 706 ;; The text between \end{verbatim} and \n is ignored, so we'll treat 707 ;; it as a comment. 708 (put-text-property end (min (1+ end) (line-end-position)) 709 'syntax-table (string-to-syntax "<")))))) 710 ;; Mark env args for possible electric pairing. 711 (unless (get-char-property (1+ start) 'text-clones) ;Already paired-up. 712 (put-text-property start end 'latex-env-pair t))) 713 714(define-minor-mode latex-electric-env-pair-mode 715 "Toggle Latex Electric Env Pair mode. 716 717Latex Electric Env Pair mode is a buffer-local minor mode for use 718with `latex-mode'. When enabled, typing a \\begin or \\end tag 719automatically inserts its partner." 720 :lighter "/e" 721 (if latex-electric-env-pair-mode 722 (add-hook 'before-change-functions 723 #'latex-env-before-change nil 'local) 724 (remove-hook 'before-change-functions 725 #'latex-env-before-change 'local))) 726 727(defun latex-env-before-change (start end) 728 (when (get-text-property start 'latex-env-pair) 729 (condition-case err 730 (with-silent-modifications 731 ;; Remove properties even if don't find a pair. 732 (remove-list-of-text-properties 733 (previous-single-property-change (1+ start) 'latex-env-pair) 734 (next-single-property-change start 'latex-env-pair) 735 '(latex-env-pair)) 736 (unless (or (get-char-property start 'text-clones) 737 (get-char-property (1+ start) 'text-clones) 738 (save-excursion 739 (goto-char start) 740 (not (re-search-backward 741 "\\\\\\(?:end\\|begi\\(n\\)\\) *{" 742 (line-beginning-position) t)))) 743 (let ((cmd-start (match-beginning 0)) 744 (type (match-end 1)) ;nil for \end, else \begin. 745 (arg-start (1- (match-end 0)))) 746 (save-excursion 747 (goto-char (match-end 0)) 748 (when (and (looking-at "[^\n{}]*}") 749 (> (match-end 0) end)) 750 (let ((arg-end (match-end 0))) 751 (if (null type) ;\end 752 (progn (goto-char arg-end) 753 (latex-forward-sexp -1) 754 (forward-word-strictly 1)) 755 (goto-char cmd-start) 756 (latex-forward-sexp 1) 757 (let (forward-sexp-function) (backward-sexp))) 758 (when (looking-at 759 (regexp-quote (buffer-substring arg-start arg-end))) 760 (text-clone-create arg-start arg-end)))))))) 761 (scan-error nil) 762 (error (message "Error in latex-env-before-change: %s" err))))) 763 764(defun tex-font-lock-unfontify-region (beg end) 765 (font-lock-default-unfontify-region beg end) 766 (while (< beg end) 767 (let ((next (next-single-property-change beg 'display nil end)) 768 (prop (get-text-property beg 'display))) 769 (if (and (eq (car-safe prop) 'raise) 770 (member (car-safe (cdr prop)) tex-font-script-display) 771 (null (cddr prop))) 772 (put-text-property beg next 'display nil)) 773 (setq beg next)))) 774 775(defcustom tex-suscript-height-ratio 0.8 776 "Ratio of subscript/superscript height to that of the preceding text. 777In nested subscript/superscript, this factor is applied repeatedly, 778subject to the limit set by `tex-suscript-height-minimum'." 779 :type 'float 780 :group 'tex 781 :version "23.1") 782 783(defcustom tex-suscript-height-minimum 0.0 784 "Integer or float limiting the minimum size of subscript/superscript text. 785An integer is an absolute height in units of 1/10 point, a float 786is a height relative to that of the default font. Zero means no minimum." 787 :type '(choice (integer :tag "Integer height in 1/10 point units") 788 (float :tag "Fraction of default font height")) 789 :group 'tex 790 :version "23.1") 791 792(defun tex-suscript-height (height) 793 "Return the integer height of subscript/superscript font in 1/10 points. 794Not smaller than the value set by `tex-suscript-height-minimum'." 795 (ceiling (max (if (integerp tex-suscript-height-minimum) 796 tex-suscript-height-minimum 797 ;; For bootstrapping. 798 (condition-case nil 799 (* tex-suscript-height-minimum 800 (face-attribute 'default :height)) 801 (error 0))) 802 ;; NB assumes height is integer. 803 (* height tex-suscript-height-ratio)))) 804 805(defface superscript 806 '((t :height tex-suscript-height)) ;; :raise 0.2 807 "Face used for superscripts." 808 :group 'tex) 809(defface subscript 810 '((t :height tex-suscript-height)) ;; :raise -0.2 811 "Face used for subscripts." 812 :group 'tex) 813 814(defface tex-math 815 '((t :inherit font-lock-string-face)) 816 "Face used to highlight TeX math expressions." 817 :group 'tex) 818 819(defface tex-verbatim 820 '((t :inherit fixed-pitch-serif)) 821 "Face used to highlight TeX verbatim environments." 822 :group 'tex) 823 824(defun tex-font-lock-verb (start delim) 825 "Place syntax table properties on the \\verb construct. 826START is the position of the \\ and DELIM is the delimiter char." 827 ;; Do nothing if the \verb construct is itself inside a comment or 828 ;; verbatim env. 829 (unless (nth 8 (save-excursion (syntax-ppss start))) 830 ;; Let's find the end and mark it. 831 (let ((afterdelim (point))) 832 (skip-chars-forward (string ?^ delim) (line-end-position)) 833 (if (eolp) 834 ;; "LaTeX Error: \verb ended by end of line." 835 ;; Remove the syntax-table property we've just put on the 836 ;; start-delimiter, so it doesn't spill over subsequent lines. 837 (put-text-property (1- afterdelim) afterdelim 838 'syntax-table nil) 839 (when (eq (char-syntax (preceding-char)) ?/) 840 (put-text-property (1- (point)) (point) 841 'syntax-table (string-to-syntax "."))) 842 (put-text-property (point) (1+ (point)) 843 'syntax-table (string-to-syntax "\"")))))) 844 845;; Use string syntax but math face for $...$. 846(defun tex-font-lock-syntactic-face-function (state) 847 (let ((char (nth 3 state))) 848 (cond 849 ((not char) 850 (if (eq 2 (nth 7 state)) 'tex-verbatim font-lock-comment-face)) 851 ((eq char ?$) 'tex-math) 852 ;; A \verb element. 853 (t 'tex-verbatim)))) 854 855 856(defun tex-define-common-keys (keymap) 857 "Define the keys that we want defined both in TeX mode and in the TeX shell." 858 (define-key keymap "\C-c\C-k" 'tex-kill-job) 859 (define-key keymap "\C-c\C-l" 'tex-recenter-output-buffer) 860 (define-key keymap "\C-c\C-q" 'tex-show-print-queue) 861 (define-key keymap "\C-c\C-p" 'tex-print) 862 (define-key keymap "\C-c\C-v" 'tex-view) 863 864 (define-key keymap [menu-bar tex] (cons "TeX" (make-sparse-keymap "TeX"))) 865 866 (define-key keymap [menu-bar tex tex-kill-job] 867 '(menu-item "Tex Kill" tex-kill-job :enable (tex-shell-running))) 868 (define-key keymap [menu-bar tex tex-recenter-output-buffer] 869 '(menu-item "Tex Recenter" tex-recenter-output-buffer 870 :enable (get-buffer "*tex-shell*"))) 871 (define-key keymap [menu-bar tex tex-show-print-queue] 872 '("Show Print Queue" . tex-show-print-queue)) 873 (define-key keymap [menu-bar tex tex-alt-print] 874 '(menu-item "Tex Print (alt printer)" tex-alt-print 875 :enable (stringp tex-print-file))) 876 (define-key keymap [menu-bar tex tex-print] 877 '(menu-item "Tex Print" tex-print :enable (stringp tex-print-file))) 878 (define-key keymap [menu-bar tex tex-view] 879 '(menu-item "Tex View" tex-view :enable (stringp tex-print-file)))) 880 881(defvar tex-mode-map 882 (let ((map (make-sparse-keymap))) 883 (set-keymap-parent map text-mode-map) 884 (tex-define-common-keys map) 885 (define-key map "\"" 'tex-insert-quote) 886 (define-key map "\n" 'tex-handle-newline) 887 (define-key map "\M-\r" 'latex-insert-item) 888 (define-key map "\C-c}" 'up-list) 889 (define-key map "\C-c{" 'tex-insert-braces) 890 (define-key map "\C-c\C-r" 'tex-region) 891 (define-key map "\C-c\C-b" 'tex-buffer) 892 (define-key map "\C-c\C-f" 'tex-file) 893 (define-key map "\C-c\C-c" 'tex-compile) 894 (define-key map "\C-c\C-i" 'tex-bibtex-file) 895 (define-key map "\C-c\C-o" 'latex-insert-block) 896 897 ;; Redundant keybindings, for consistency with SGML mode. 898 (define-key map "\C-c\C-t" 'latex-insert-block) 899 (define-key map "\C-c]" 'latex-close-block) 900 (define-key map "\C-c/" 'latex-close-block) 901 902 (define-key map "\C-c\C-e" 'latex-close-block) 903 (define-key map "\C-c\C-u" 'tex-goto-last-unclosed-latex-block) 904 (define-key map "\C-c\C-m" 'tex-feed-input) 905 (define-key map [(control return)] 'tex-feed-input) 906 (define-key map [menu-bar tex tex-bibtex-file] 907 '("BibTeX File" . tex-bibtex-file)) 908 (define-key map [menu-bar tex tex-validate-region] 909 '(menu-item "Validate Region" tex-validate-region :enable mark-active)) 910 (define-key map [menu-bar tex tex-validate-buffer] 911 '("Validate Buffer" . tex-validate-buffer)) 912 (define-key map [menu-bar tex tex-region] 913 '(menu-item "TeX Region" tex-region :enable mark-active)) 914 (define-key map [menu-bar tex tex-buffer] 915 '("TeX Buffer" . tex-buffer)) 916 (define-key map [menu-bar tex tex-file] '("TeX File" . tex-file)) 917 map) 918 "Keymap shared by TeX modes.") 919 920(defvar latex-mode-map 921 (let ((map (make-sparse-keymap))) 922 (set-keymap-parent map tex-mode-map) 923 (define-key map "\C-c\C-s" 'latex-split-block) 924 map) 925 "Keymap for `latex-mode'. See also `tex-mode-map'.") 926 927(defvar plain-tex-mode-map 928 (let ((map (make-sparse-keymap))) 929 (set-keymap-parent map tex-mode-map) 930 map) 931 "Keymap for `plain-tex-mode'. See also `tex-mode-map'.") 932 933(defvar tex-shell-map 934 (let ((m (make-sparse-keymap))) 935 (set-keymap-parent m shell-mode-map) 936 (tex-define-common-keys m) 937 m) 938 "Keymap for the TeX shell. 939Inherits `shell-mode-map' with a few additions.") 940 941(defvar tex-face-alist 942 '((bold . "{\\bf ") 943 (italic . "{\\it ") 944 (bold-italic . "{\\bi ") ; hypothetical 945 (underline . "\\underline{") 946 (default . "{\\rm ")) 947 "Alist of face and TeX font name for facemenu.") 948 949(defvar tex-latex-face-alist 950 `((italic . "{\\em ") 951 ,@tex-face-alist) 952 "Alist of face and LaTeX font name for facemenu.") 953 954(defun tex-facemenu-add-face-function (face _end) 955 (or (cdr (assq face tex-face-alist)) 956 (or (and (consp face) 957 (consp (car face)) 958 (null (cdr face)) 959 (eq major-mode 'latex-mode) 960 ;; This actually requires the `color' LaTeX package. 961 (cond ((eq (caar face) :foreground) 962 (format "{\\color{%s} " (cadr (car face)))) 963 ((eq (caar face) :background) 964 (format "\\colorbox{%s}{" (cadr (car face)))))) 965 (error "Face %s not configured for %s mode" face mode-name)))) 966 967;; This would be a lot simpler if we just used a regexp search, 968;; but then it would be too slow. 969(defun tex-guess-mode () 970 (let ((mode tex-default-mode) slash comment) 971 (save-excursion 972 (goto-char (point-min)) 973 (while (and (setq slash (search-forward "\\" nil t)) 974 (setq comment (let ((search-end (point))) 975 (save-excursion 976 (beginning-of-line) 977 (search-forward "%" search-end t)))))) 978 (when (and slash (not comment)) 979 (setq mode 980 (if (looking-at 981 (eval-when-compile 982 (concat 983 (regexp-opt '("documentstyle" "documentclass" 984 "begin" "subsection" "section" 985 "part" "chapter" "newcommand" 986 "renewcommand" "RequirePackage") 'words) 987 "\\|NeedsTeXFormat{LaTeX"))) 988 (if (and (looking-at 989 "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}") 990 ;; SliTeX is almost never used any more nowadays. 991 (tex-executable-exists-p slitex-run-command)) 992 'slitex-mode 993 'latex-mode) 994 'plain-tex-mode)))) 995 (funcall mode))) 996 997;; `tex-mode' plays two roles: it's the parent of several sub-modes 998;; but it's also the function that chooses between those submodes. 999;; To tell the difference between those two cases where the function 1000;; might be called, we check `delay-mode-hooks'. 1001(define-derived-mode tex-mode text-mode "generic-TeX" 1002 (tex-common-initialization)) 1003;; We now move the function and define it again. This gives a warning 1004;; in the byte-compiler :-( but it's difficult to avoid because 1005;; `define-derived-mode' will necessarily define the function once 1006;; and we need to define it a second time for `autoload' to get the 1007;; proper docstring. 1008(defalias 'tex-mode-internal (symbol-function 'tex-mode)) 1009 1010;; Suppress the byte-compiler warning about multiple definitions. 1011;; This is a) ugly, and b) cheating, but this was the last 1012;; remaining warning from byte-compiling all of Emacs... 1013(eval-when-compile 1014 (if (boundp 'byte-compile-function-environment) 1015 (setq byte-compile-function-environment 1016 (delq (assq 'tex-mode byte-compile-function-environment) 1017 byte-compile-function-environment)))) 1018 1019;;;###autoload 1020(defun tex-mode () 1021 "Major mode for editing files of input for TeX, LaTeX, or SliTeX. 1022Tries to determine (by looking at the beginning of the file) whether 1023this file is for plain TeX, LaTeX, or SliTeX and calls `plain-tex-mode', 1024`latex-mode', or `slitex-mode', respectively. If it cannot be determined, 1025such as if there are no commands in the file, the value of `tex-default-mode' 1026says which mode to use." 1027 (interactive) 1028 (if delay-mode-hooks 1029 ;; We're called from one of the children already. 1030 (tex-mode-internal) 1031 (tex-guess-mode))) 1032 1033;; The following three autoloaded aliases appear to conflict with 1034;; AUCTeX. However, even though AUCTeX uses the mixed case variants 1035;; for all mode relevant variables and hooks, the invocation function 1036;; and setting of `major-mode' themselves need to be lowercase for 1037;; AUCTeX to provide a fully functional user-level replacement. So 1038;; these aliases should remain as they are, in particular since AUCTeX 1039;; users are likely to use them. 1040 1041;;;###autoload 1042(defalias 'TeX-mode 'tex-mode) 1043;;;###autoload 1044(defalias 'plain-TeX-mode 'plain-tex-mode) 1045;;;###autoload 1046(defalias 'LaTeX-mode 'latex-mode) 1047 1048;;;###autoload 1049(define-derived-mode plain-tex-mode tex-mode "TeX" 1050 "Major mode for editing files of input for plain TeX. 1051Makes $ and } display the characters they match. 1052Makes \" insert \\=`\\=` when it seems to be the beginning of a quotation, 1053and \\='\\=' when it appears to be the end; it inserts \" only after a \\. 1054 1055Use \\[tex-region] to run TeX on the current region, plus a \"header\" 1056copied from the top of the file (containing macro definitions, etc.), 1057running TeX under a special subshell. \\[tex-buffer] does the whole buffer. 1058\\[tex-file] saves the buffer and then processes the file. 1059\\[tex-print] prints the .dvi file made by any of these. 1060\\[tex-view] previews the .dvi file made by any of these. 1061\\[tex-bibtex-file] runs bibtex on the file of the current buffer. 1062 1063Use \\[tex-validate-buffer] to check buffer for paragraphs containing 1064mismatched $'s or braces. 1065 1066Special commands: 1067\\{plain-tex-mode-map} 1068 1069Mode variables: 1070tex-run-command 1071 Command string used by \\[tex-region] or \\[tex-buffer]. 1072tex-directory 1073 Directory in which to create temporary files for TeX jobs 1074 run by \\[tex-region] or \\[tex-buffer]. 1075tex-dvi-print-command 1076 Command string used by \\[tex-print] to print a .dvi file. 1077tex-alt-dvi-print-command 1078 Alternative command string used by \\[tex-print] (when given a prefix 1079 argument) to print a .dvi file. 1080tex-dvi-view-command 1081 Command string used by \\[tex-view] to preview a .dvi file. 1082tex-show-queue-command 1083 Command string used by \\[tex-show-print-queue] to show the print 1084 queue that \\[tex-print] put your job on. 1085 1086Entering Plain-tex mode runs the hook `text-mode-hook', then the hook 1087`tex-mode-hook', and finally the hook `plain-tex-mode-hook'. When the 1088special subshell is initiated, the hook `tex-shell-hook' is run." 1089 (setq-local tex-command tex-run-command) 1090 (setq-local tex-start-of-header "%\\*\\*start of header") 1091 (setq-local tex-end-of-header "%\\*\\*end of header") 1092 (setq-local tex-trailer "\\bye\n")) 1093 1094;;;###autoload 1095(define-derived-mode latex-mode tex-mode "LaTeX" 1096 "Major mode for editing files of input for LaTeX. 1097Makes $ and } display the characters they match. 1098Makes \" insert \\=`\\=` when it seems to be the beginning of a quotation, 1099and \\='\\=' when it appears to be the end; it inserts \" only after a \\. 1100 1101Use \\[tex-region] to run LaTeX on the current region, plus the preamble 1102copied from the top of the file (containing \\documentstyle, etc.), 1103running LaTeX under a special subshell. \\[tex-buffer] does the whole buffer. 1104\\[tex-file] saves the buffer and then processes the file. 1105\\[tex-print] prints the .dvi file made by any of these. 1106\\[tex-view] previews the .dvi file made by any of these. 1107\\[tex-bibtex-file] runs bibtex on the file of the current buffer. 1108 1109Use \\[tex-validate-buffer] to check buffer for paragraphs containing 1110mismatched $'s or braces. 1111 1112Special commands: 1113\\{latex-mode-map} 1114 1115Mode variables: 1116latex-run-command 1117 Command string used by \\[tex-region] or \\[tex-buffer]. 1118tex-directory 1119 Directory in which to create temporary files for LaTeX jobs 1120 run by \\[tex-region] or \\[tex-buffer]. 1121tex-dvi-print-command 1122 Command string used by \\[tex-print] to print a .dvi file. 1123tex-alt-dvi-print-command 1124 Alternative command string used by \\[tex-print] (when given a prefix 1125 argument) to print a .dvi file. 1126tex-dvi-view-command 1127 Command string used by \\[tex-view] to preview a .dvi file. 1128tex-show-queue-command 1129 Command string used by \\[tex-show-print-queue] to show the print 1130 queue that \\[tex-print] put your job on. 1131 1132Entering Latex mode runs the hook `text-mode-hook', then 1133`tex-mode-hook', and finally `latex-mode-hook'. When the special 1134subshell is initiated, `tex-shell-hook' is run." 1135 (setq-local tex-command latex-run-command) 1136 (setq-local tex-start-of-header "\\\\document\\(style\\|class\\)") 1137 (setq-local tex-end-of-header "\\\\begin\\s-*{document}") 1138 (setq-local tex-trailer "\\end{document}\n") 1139 ;; A line containing just $$ is treated as a paragraph separator. 1140 ;; A line starting with $$ starts a paragraph, 1141 ;; but does not separate paragraphs if it has more stuff on it. 1142 ;; For \pagebreak allow latex optional arg like \pagebreak[2] 1143 (setq paragraph-start 1144 (concat "[ \t]*\\(\\$\\$\\|" 1145 "\\\\[][]\\|" 1146 "\\\\" (regexp-opt (append 1147 (mapcar #'car latex-section-alist) 1148 '("begin" "label" "end" 1149 "item" "bibitem" "newline" "noindent" 1150 "newpage" "footnote" "marginpar" 1151 "parbox" "caption")) 1152 t) 1153 "\\>\\|\\\\[a-z]*" (regexp-opt '("space" "skip" "page") t) 1154 "\\>\\)")) 1155 (setq paragraph-separate 1156 (concat "\\([ \t]*%\\)\\|[\f]\\|[ \t]*\\($\\|" 1157 "\\\\[][]\\|" 1158 "\\\\" (regexp-opt (append 1159 (mapcar #'car latex-section-alist) 1160 '("begin" "label" "end" )) 1161 t) 1162 "\\>\\|\\\\\\(" (regexp-opt '("item" "bibitem" "newline" 1163 "noindent" "newpage" "footnote" 1164 "marginpar" "parbox" "caption")) 1165 "\\|\\$\\$\\|[a-z]*\\(space\\|skip\\|page[a-z]*\\)" 1166 "\\>\\)[][0-9 \t]*\\($\\|%\\)\\)")) 1167 (setq-local imenu-create-index-function #'latex-imenu-create-index) 1168 (setq-local tex-face-alist tex-latex-face-alist) 1169 (add-hook 'fill-nobreak-predicate #'latex-fill-nobreak-predicate nil t) 1170 (setq-local indent-line-function #'latex-indent) 1171 (setq-local fill-indent-according-to-mode t) 1172 (add-hook 'completion-at-point-functions 1173 #'latex-complete-data nil 'local) 1174 (add-hook 'flymake-diagnostic-functions #'tex-chktex nil t) 1175 (setq-local outline-regexp latex-outline-regexp) 1176 (setq-local outline-level #'latex-outline-level) 1177 (setq-local forward-sexp-function #'latex-forward-sexp) 1178 (setq-local skeleton-end-hook nil)) 1179 1180;;;###autoload 1181(define-derived-mode slitex-mode latex-mode "SliTeX" 1182 "Major mode for editing files of input for SliTeX. 1183Makes $ and } display the characters they match. 1184Makes \" insert \\=`\\=` when it seems to be the beginning of a quotation, 1185and \\='\\=' when it appears to be the end; it inserts \" only after a \\. 1186 1187Use \\[tex-region] to run SliTeX on the current region, plus the preamble 1188copied from the top of the file (containing \\documentstyle, etc.), 1189running SliTeX under a special subshell. \\[tex-buffer] does the whole buffer. 1190\\[tex-file] saves the buffer and then processes the file. 1191\\[tex-print] prints the .dvi file made by any of these. 1192\\[tex-view] previews the .dvi file made by any of these. 1193\\[tex-bibtex-file] runs bibtex on the file of the current buffer. 1194 1195Use \\[tex-validate-buffer] to check buffer for paragraphs containing 1196mismatched $'s or braces. 1197 1198Special commands: 1199\\{slitex-mode-map} 1200 1201Mode variables: 1202slitex-run-command 1203 Command string used by \\[tex-region] or \\[tex-buffer]. 1204tex-directory 1205 Directory in which to create temporary files for SliTeX jobs 1206 run by \\[tex-region] or \\[tex-buffer]. 1207tex-dvi-print-command 1208 Command string used by \\[tex-print] to print a .dvi file. 1209tex-alt-dvi-print-command 1210 Alternative command string used by \\[tex-print] (when given a prefix 1211 argument) to print a .dvi file. 1212tex-dvi-view-command 1213 Command string used by \\[tex-view] to preview a .dvi file. 1214tex-show-queue-command 1215 Command string used by \\[tex-show-print-queue] to show the print 1216 queue that \\[tex-print] put your job on. 1217 1218Entering SliTeX mode runs the hook `text-mode-hook', then the hook 1219`tex-mode-hook', then the hook `latex-mode-hook', and finally the hook 1220`slitex-mode-hook'. When the special subshell is initiated, the hook 1221`tex-shell-hook' is run." 1222 (setq tex-command slitex-run-command) 1223 (setq tex-start-of-header "\\\\documentstyle{slides}\\|\\\\documentclass{slides}")) 1224 1225(defvar tildify-space-string) 1226(defvar tildify-foreach-region-function) 1227(declare-function tildify-foreach-ignore-environments 1228 "tildify" (pairs callback _beg end)) 1229(defvar tex--prettify-symbols-alist) 1230 1231(defun tex-common-initialization () 1232 ;; Regexp isearch should accept newline and formfeed as whitespace. 1233 (setq-local search-whitespace-regexp "[ \t\r\n\f]+") 1234 ;; Use tilde as hard-space character in tildify package. 1235 (setq-local tildify-space-string "~") 1236 ;; FIXME: Use the fact that we're parsing the document already 1237 ;; rather than using regex-based filtering. 1238 (setq-local tildify-foreach-region-function 1239 (apply-partially 1240 #'tildify-foreach-ignore-environments 1241 `(("\\\\\\\\" . "") ; do not remove this 1242 (,(eval-when-compile 1243 (concat "\\\\begin{\\(" 1244 (regexp-opt '("verbatim" "math" "displaymath" 1245 "equation" "eqnarray" "eqnarray*")) 1246 "\\)}")) 1247 . ("\\\\end{" 1 "}")) 1248 ("\\\\verb\\*?\\(.\\)" . (1)) 1249 ("\\$\\$?" . (0)) 1250 ("\\\\(" . "\\\\)") 1251 ("\\\\[[]" . "\\\\[]]") 1252 ("\\\\[a-zA-Z]+\\( +\\|{}\\)[a-zA-Z]*" . "") 1253 ("%" . "$")))) 1254 ;; A line containing just $$ is treated as a paragraph separator. 1255 (setq-local paragraph-start "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$") 1256 ;; A line starting with $$ starts a paragraph, 1257 ;; but does not separate paragraphs if it has more stuff on it. 1258 (setq-local paragraph-separate "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$[ \t]*$") 1259 (setq-local add-log-current-defun-function #'tex-current-defun-name) 1260 (setq-local comment-start "%") 1261 (setq-local comment-add 1) 1262 (setq-local comment-start-skip 1263 "\\(\\(^\\|[^\\\n]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)") 1264 (setq-local parse-sexp-ignore-comments t) 1265 (setq-local compare-windows-whitespace #'tex-categorize-whitespace) 1266 (setq-local facemenu-add-face-function #'tex-facemenu-add-face-function) 1267 (setq-local facemenu-end-add-face "}") 1268 (setq-local facemenu-remove-face-function t) 1269 (setq-local font-lock-defaults 1270 '((tex-font-lock-keywords tex-font-lock-keywords-1 1271 tex-font-lock-keywords-2 tex-font-lock-keywords-3) 1272 nil nil nil nil 1273 ;; Who ever uses that anyway ??? 1274 (font-lock-mark-block-function . mark-paragraph) 1275 (font-lock-syntactic-face-function 1276 . tex-font-lock-syntactic-face-function) 1277 (font-lock-unfontify-region-function 1278 . tex-font-lock-unfontify-region))) 1279 (setq-local prettify-symbols-alist tex--prettify-symbols-alist) 1280 (add-function :override (local 'prettify-symbols-compose-predicate) 1281 #'tex--prettify-symbols-compose-p) 1282 (setq-local syntax-propertize-function 1283 (syntax-propertize-rules latex-syntax-propertize-rules)) 1284 ;; TABs in verbatim environments don't do what you think. 1285 (setq-local indent-tabs-mode nil) 1286 ;; Other vars that should be buffer-local. 1287 (make-local-variable 'tex-command) 1288 (make-local-variable 'tex-start-of-header) 1289 (make-local-variable 'tex-end-of-header) 1290 (make-local-variable 'tex-trailer)) 1291 1292(defun tex-categorize-whitespace (backward-limit) 1293 ;; compare-windows-whitespace is set to this. 1294 ;; This is basically a finite-state machine. 1295 ;; Returns a symbol telling how TeX would treat 1296 ;; the whitespace we are looking at: null, space, or par. 1297 (let ((category 'null) 1298 (not-finished t)) 1299 (skip-chars-backward " \t\n\f" backward-limit) 1300 (while not-finished 1301 (cond ((looking-at "[ \t]+") 1302 (goto-char (match-end 0)) 1303 (if (eq category 'null) 1304 (setq category 'space))) 1305 ((looking-at "\n") 1306 (cond ((eq category 'newline) 1307 (setq category 'par) 1308 (setq not-finished nil)) 1309 (t 1310 (setq category 'newline) ;a strictly internal state 1311 (goto-char (match-end 0))))) 1312 ((looking-at "\f+") 1313 (setq category 'par) 1314 (setq not-finished nil)) 1315 (t 1316 (setq not-finished nil)))) 1317 (skip-chars-forward " \t\n\f") 1318 (if (eq category 'newline) 1319 'space ;TeX doesn't distinguish 1320 category))) 1321 1322(defun tex-insert-quote (arg) 1323 "Insert the appropriate quote marks for TeX. 1324Inserts the value of `tex-open-quote' (normally \\=`\\=`) or `tex-close-quote' 1325\(normally \\='\\=') depending on the context. With prefix argument, always 1326inserts \" characters." 1327 (interactive "*P") 1328 ;; Discover if we'll be inserting normal double quotes. 1329 ;; 1330 (if (or arg (memq (char-syntax (preceding-char)) '(?/ ?\\)) 1331 (eq (get-text-property (point) 'face) 'tex-verbatim) 1332 (nth 4 (syntax-ppss)) ; non-nil if point is in a TeX comment 1333 ;; Discover if a preceding occurrence of `tex-open-quote' 1334 ;; should be morphed to a normal double quote. 1335 ;; 1336 (and (>= (point) (+ (point-min) (length tex-open-quote))) 1337 (save-excursion 1338 (backward-char (length tex-open-quote)) 1339 (when (or (looking-at (regexp-quote tex-open-quote)) 1340 (looking-at (regexp-quote tex-close-quote))) 1341 (delete-char (length tex-open-quote)) 1342 (when (looking-at (regexp-quote tex-close-quote)) 1343 (delete-char (length tex-close-quote))) 1344 t)))) 1345 ;; Insert the normal quote (eventually letting 1346 ;; `electric-pair-mode' do its thing). 1347 ;; 1348 (self-insert-command (prefix-numeric-value arg)) 1349 ;; We'll be inserting fancy TeX quotes, but consider and imitate 1350 ;; `electric-pair-mode''s two behaviors: pair-insertion and 1351 ;; region wrapping. 1352 ;; 1353 (if (and electric-pair-mode (use-region-p)) 1354 (let* ((saved (point-marker))) 1355 (goto-char (mark)) 1356 (insert (if (> saved (mark)) tex-open-quote tex-close-quote)) 1357 (goto-char saved) 1358 (insert (if (> saved (mark)) tex-close-quote tex-open-quote))) 1359 (if (or (memq (char-syntax (preceding-char)) '(?\( ?> ?\s)) 1360 (memq (preceding-char) '(?~ ?'))) 1361 ;; We're in an "opening" context 1362 ;; 1363 (if electric-pair-mode 1364 (if (looking-at (regexp-quote tex-close-quote)) 1365 (forward-char (length tex-close-quote)) 1366 (insert tex-open-quote) 1367 (insert tex-close-quote) 1368 (backward-char (length tex-close-quote))) 1369 (insert tex-open-quote)) 1370 ;; We're in a "closing" context. 1371 ;; 1372 (if (looking-at (regexp-quote tex-close-quote)) 1373 (forward-char (length tex-close-quote)) 1374 (insert tex-close-quote)))))) 1375 1376(defun tex-validate-buffer () 1377 "Check current buffer for paragraphs containing mismatched braces or $s. 1378Their positions are recorded in the buffer `*Occur*'. 1379To find a particular invalidity from `*Occur*', switch to that buffer 1380and type C-c C-c or click with mouse-2 1381on the line for the invalidity you want to see." 1382 (interactive) 1383 (let ((buffer (current-buffer)) 1384 (prevpos (point-min)) 1385 (linenum nil) 1386 (num-matches 0)) 1387 (with-output-to-temp-buffer "*Occur*" 1388 (princ "Mismatches:\n") 1389 (with-current-buffer standard-output 1390 (occur-mode) 1391 ;; This won't actually work...Really, this whole thing should 1392 ;; be rewritten instead of being a hack on top of occur. 1393 (setq occur-revert-arguments (list nil 0 (list buffer)))) 1394 (save-excursion 1395 (goto-char (point-max)) 1396 ;; Do a little shimmy to place point at the end of the last 1397 ;; "real" paragraph. Need to avoid validating across an \end, 1398 ;; because that blows up latex-forward-sexp. 1399 (backward-paragraph) 1400 (forward-paragraph) 1401 (while (not (bobp)) 1402 ;; Scan the previous paragraph for invalidities. 1403 (backward-paragraph) 1404 (save-excursion 1405 (or (tex-validate-region (point) (save-excursion 1406 (forward-paragraph) 1407 (point))) 1408 (let ((end (line-beginning-position 2)) 1409 start tem) 1410 (beginning-of-line) 1411 (setq start (point)) 1412 ;; Keep track of line number as we scan, 1413 ;; in a cumulative fashion. 1414 (if linenum 1415 (setq linenum (- linenum 1416 (count-lines prevpos (point)))) 1417 (setq linenum (1+ (count-lines 1 start)))) 1418 (setq prevpos (point)) 1419 ;; Mention this mismatch in *Occur*. 1420 ;; Since we scan from end of buffer to beginning, 1421 ;; add each mismatch at the beginning of *Occur*. 1422 (save-excursion 1423 (setq tem (point-marker)) 1424 (set-buffer standard-output) 1425 (goto-char (point-min)) 1426 ;; Skip "Mismatches:" header line. 1427 (forward-line 1) 1428 (setq num-matches (1+ num-matches)) 1429 (insert-buffer-substring buffer start end) 1430 (let (text-beg (text-end (point-marker))) 1431 (forward-char (- start end)) 1432 (setq text-beg (point-marker)) 1433 (insert (format "%3d: " linenum)) 1434 (add-text-properties 1435 text-beg (- text-end 1) 1436 '(mouse-face highlight 1437 help-echo 1438 "mouse-2: go to this invalidity")) 1439 (put-text-property text-beg (- text-end 1) 1440 'occur-target tem)))))))) 1441 (with-current-buffer standard-output 1442 (let ((no-matches (zerop num-matches))) 1443 (if no-matches 1444 (insert "None!\n")) 1445 (if (called-interactively-p 'interactive) 1446 (message (cond (no-matches "No mismatches found") 1447 ((= num-matches 1) "1 mismatch found") 1448 (t "%d mismatches found")) 1449 num-matches))))))) 1450 1451(defun tex-validate-region (start end) 1452 "Check for mismatched braces or $'s in region. 1453Returns t if no mismatches. Returns nil and moves point to suspect 1454area if a mismatch is found." 1455 (interactive "r") 1456 (let ((failure-point nil) (max-possible-sexps (- end start))) 1457 (save-excursion 1458 (condition-case () 1459 (save-restriction 1460 (narrow-to-region start end) 1461 ;; First check that the open and close parens balance in numbers. 1462 (goto-char start) 1463 (while (and (not (eobp)) 1464 (<= 0 (setq max-possible-sexps 1465 (1- max-possible-sexps)))) 1466 (forward-sexp 1)) 1467 ;; Now check that like matches like. 1468 (goto-char start) 1469 (while (re-search-forward "\\s(" nil t) 1470 (save-excursion 1471 (let ((pos (match-beginning 0))) 1472 (goto-char pos) 1473 (skip-chars-backward "\\\\") ; escaped parens 1474 (forward-sexp 1) 1475 (or (eq (preceding-char) (cdr (syntax-after pos))) 1476 (eq (char-after pos) (cdr (syntax-after (1- (point))))) 1477 (error "Mismatched parentheses")))))) 1478 (error 1479 (skip-syntax-forward " .>") 1480 (setq failure-point (point))))) 1481 (if failure-point (goto-char failure-point)) 1482 (not failure-point))) 1483 1484(defun tex-handle-newline (inhibit-validation) 1485 "Break a TeX paragraph with two newlines, or continue a comment. 1486If not in a comment, insert two newlines, breaking a paragraph for TeX, 1487and check for mismatched braces or $s in the paragraph being terminated 1488unless prefix arg INHIBIT-VALIDATION is non-nil to inhibit the checking. 1489Otherwise (in a comment), just insert a single continued comment line." 1490 (interactive "*P") 1491 (if (nth 4 (syntax-ppss)) ; non-nil if point is in a TeX comment 1492 (comment-indent-new-line) 1493 (tex-terminate-paragraph inhibit-validation))) 1494 1495(defun tex-terminate-paragraph (inhibit-validation) 1496 "Insert two newlines, breaking a paragraph for TeX. 1497Check for mismatched braces or $s in paragraph being terminated. 1498A prefix arg inhibits the checking." 1499 (interactive "*P") 1500 (or inhibit-validation 1501 (save-excursion 1502 ;; For the purposes of this, a "paragraph" is a block of text 1503 ;; wherein all the brackets etc are expected to be balanced. It 1504 ;; may start after a blank line (ie a "proper" paragraph), or 1505 ;; a begin{} or end{} block, etc. 1506 (tex-validate-region 1507 (save-excursion 1508 (backward-paragraph) 1509 (point)) 1510 (point))) 1511 (message "Paragraph being closed appears to contain a mismatch")) 1512 (insert "\n\n")) 1513 1514(define-skeleton tex-insert-braces 1515 "Make a pair of braces and be poised to type inside of them." 1516 nil 1517 ?\{ _ ?}) 1518 1519;; This function is used as the value of fill-nobreak-predicate 1520;; in LaTeX mode. Its job is to prevent line-breaking inside 1521;; of a \verb construct. 1522(defun latex-fill-nobreak-predicate () 1523 (save-excursion 1524 (skip-chars-backward " ") 1525 ;; Don't break after \ since `\ ' has special meaning. 1526 (or (and (not (bobp)) (memq (char-syntax (char-before)) '(?\\ ?/))) 1527 (let ((opoint (point)) 1528 inside) 1529 (beginning-of-line) 1530 (while (re-search-forward "\\\\verb\\(.\\)" opoint t) 1531 (unless (re-search-forward (regexp-quote (match-string 1)) opoint t) 1532 (setq inside t))) 1533 inside)))) 1534 1535(defvar latex-block-default "enumerate") 1536 1537(defvar latex-block-args-alist 1538 '(("array" nil ?\{ (skeleton-read "Format: ") ?\}) 1539 ("tabular" nil ?\{ (skeleton-read "Format: ") ?\}) 1540 ("minipage" nil ?\{ (skeleton-read "Size: ") ?\}) 1541 ("picture" nil ?\( (skeleton-read "SizeX,SizeY: ") ?\)) 1542 ;; FIXME: This is right for Prosper, but not for seminar. 1543 ;; ("slide" nil ?\{ (skeleton-read "Title: ") ?\}) 1544 ) 1545 "Skeleton element to use for arguments to particular environments. 1546Every element of the list has the form (NAME . SKEL-ELEM) where NAME is 1547the name of the environment and SKEL-ELEM is an element to use in 1548a skeleton (see `skeleton-insert').") 1549 1550(defvar latex-block-body-alist 1551 '(("enumerate" nil '(latex-insert-item) > _) 1552 ("itemize" nil '(latex-insert-item) > _) 1553 ("table" nil "\\caption{" > (skeleton-read "Caption: ") "}" > \n 1554 '(if (and (boundp 'reftex-mode) reftex-mode) (reftex-label "table")) 1555 \n _) 1556 ("figure" nil > _ \n "\\caption{" > (skeleton-read "Caption: ") "}" > \n 1557 '(if (and (boundp 'reftex-mode) reftex-mode) (reftex-label "table")))) 1558 "Skeleton element to use for the body of particular environments. 1559Every element of the list has the form (NAME . SKEL-ELEM) where NAME is 1560the name of the environment and SKEL-ELEM is an element to use in 1561a skeleton (see `skeleton-insert').") 1562 1563;; Like tex-insert-braces, but for LaTeX. 1564(defalias 'tex-latex-block 'latex-insert-block) 1565(define-skeleton latex-insert-block 1566 "Create a matching pair of lines \\begin{NAME} and \\end{NAME} at point. 1567Puts point on a blank line between them." 1568 (let ((choice (completing-read (format "LaTeX block name [%s]: " 1569 latex-block-default) 1570 (latex-complete-envnames) 1571 nil nil nil nil latex-block-default))) 1572 (setq latex-block-default choice) 1573 (unless (or (member choice latex-standard-block-names) 1574 (member choice latex-block-names)) 1575 ;; Remember new block names for later completion. 1576 (push choice latex-block-names)) 1577 choice) 1578 \n "\\begin{" str "}" 1579 (cdr (assoc str latex-block-args-alist)) 1580 > \n (or (cdr (assoc str latex-block-body-alist)) '(nil > _)) 1581 (unless (bolp) '\n) 1582 "\\end{" str "}" > \n) 1583 1584(define-skeleton latex-insert-item 1585 "Insert an \\item macro." 1586 nil 1587 \n "\\item " >) 1588 1589 1590;;;; LaTeX completion. 1591 1592(defvar latex-complete-bibtex-cache nil) 1593 1594(define-obsolete-function-alias 'latex-string-prefix-p 1595 #'string-prefix-p "24.3") 1596 1597(defvar bibtex-reference-key) 1598(declare-function reftex-get-bibfile-list "reftex-cite.el" ()) 1599 1600(defun latex-complete-bibtex-keys () 1601 (when (bound-and-true-p reftex-mode) 1602 (lambda (key pred action) 1603 (let ((re (concat "^[ \t]*@\\([a-zA-Z]+\\)[ \t\n]*\\([{(][ \t\n]*\\)" 1604 (regexp-quote key))) 1605 (files (reftex-get-bibfile-list)) 1606 keys) 1607 (if (and (eq (car latex-complete-bibtex-cache) 1608 (reftex-get-bibfile-list)) 1609 (string-prefix-p (nth 1 latex-complete-bibtex-cache) 1610 key)) 1611 ;; Use the cache. 1612 (setq keys (nth 2 latex-complete-bibtex-cache)) 1613 (dolist (file files) 1614 (with-current-buffer (find-file-noselect file) 1615 (goto-char (point-min)) 1616 (while (re-search-forward re nil t) 1617 (goto-char (match-end 2)) 1618 (when (and (not (member-ignore-case (match-string 1) 1619 '("c" "comment" "string"))) 1620 (looking-at bibtex-reference-key)) 1621 (push (match-string-no-properties 0) keys))))) 1622 ;; Fill the cache. 1623 (setq-local latex-complete-bibtex-cache (list files key keys))) 1624 (complete-with-action action keys key pred))))) 1625 1626(defun latex-complete-envnames () 1627 (completion-table-in-turn 1628 (append latex-block-names latex-standard-block-names) 1629 (completion-table-dynamic 1630 (lambda (str) 1631 (with-current-buffer (if (and (minibufferp) (minibuffer-selected-window)) 1632 (window-buffer (minibuffer-selected-window)) 1633 (current-buffer)) 1634 (save-excursion 1635 (let ((comps '()) 1636 (pos (point))) 1637 (goto-char (point-min)) 1638 (while (re-search-forward (concat "\\\\begin{\\(" str "[^}\n ]*\\)") 1639 nil t) 1640 (unless (and (<= (match-beginning 0) pos) 1641 (>= (match-end 0) pos)) 1642 (push (match-string 1) comps))) 1643 comps))))))) 1644 1645(defun latex-complete-refkeys () 1646 (when (boundp 'reftex-docstruct-symbol) 1647 (symbol-value reftex-docstruct-symbol))) 1648 1649(defvar latex-complete-alist 1650 `(("\\`\\\\\\(short\\)?cite\\'" . ,#'latex-complete-bibtex-keys) 1651 ("\\`\\\\\\(begin\\|end\\)\\'" . ,#'latex-complete-envnames) 1652 ("\\`\\\\[vf]?ref\\'" . ,#'latex-complete-refkeys))) 1653 1654(defun latex-complete-data () 1655 "Get completion-data at point." 1656 (save-excursion 1657 (let ((pt (point))) 1658 (skip-chars-backward "^ {}\n\t\\\\") 1659 (pcase (char-before) 1660 ((or 'nil ?\s ?\n ?\t ?\}) nil) 1661 (?\\ 1662 ;; TODO: Complete commands. 1663 nil) 1664 (?\{ 1665 ;; Complete args to commands. 1666 (let* ((cmd 1667 (save-excursion 1668 (forward-char -1) 1669 (skip-chars-backward " \n") 1670 (buffer-substring (point) 1671 (progn 1672 (skip-chars-backward "a-zA-Z@*") 1673 (let ((n (skip-chars-backward "\\\\"))) 1674 (forward-char (* 2 (/ n 2)))) 1675 (point))))) 1676 (start (point)) 1677 (_ (progn (goto-char pt) (skip-chars-backward "^," start))) 1678 (comp-beg (point)) 1679 (_ (progn (goto-char pt) (skip-chars-forward "^, {}\n\t\\\\"))) 1680 (comp-end (point)) 1681 (table 1682 (funcall 1683 (let ((f (lambda () t))) 1684 (dolist (comp latex-complete-alist) 1685 (if (string-match (car comp) cmd) 1686 (setq f (cdr comp)))) 1687 f)))) 1688 (if (eq table t) 1689 ;; Unknown command. 1690 nil 1691 (list comp-beg comp-end table)))))))) 1692 1693;;;; 1694;;;; LaTeX syntax navigation 1695;;;; 1696 1697(defmacro tex-search-noncomment (&rest body) 1698 "Execute BODY as long as it return non-nil and point is in a comment. 1699Return the value returned by the last execution of BODY." 1700 (declare (debug t)) 1701 (let ((res-sym (make-symbol "result"))) 1702 `(let (,res-sym) 1703 (while 1704 (and (setq ,res-sym (progn ,@body)) 1705 (save-excursion (skip-chars-backward "^\n%") (not (bolp))))) 1706 ,res-sym))) 1707 1708(defun tex-last-unended-begin () 1709 "Leave point at the beginning of the last `\\begin{...}' that is unended." 1710 (condition-case nil 1711 (while (and (tex-search-noncomment 1712 (re-search-backward "\\\\\\(begin\\|end\\)\\s *{")) 1713 (looking-at "\\\\end")) 1714 (tex-last-unended-begin)) 1715 (search-failed (error "Couldn't find unended \\begin")))) 1716 1717(defun tex-next-unmatched-end () 1718 "Leave point at the end of the next `\\end' that is unmatched." 1719 (while (and (tex-search-noncomment 1720 (re-search-forward "\\\\\\(begin\\|end\\)\\s *{[^}]+}")) 1721 (save-excursion (goto-char (match-beginning 0)) 1722 (looking-at "\\\\begin"))) 1723 (tex-next-unmatched-end))) 1724 1725(defun tex-next-unmatched-eparen (otype) 1726 "Leave point after the next unmatched escaped closing parenthesis. 1727The string OTYPE is an opening parenthesis type: `(', `{', or `['." 1728 (condition-case nil 1729 (let ((ctype (char-to-string (cdr (aref (syntax-table) 1730 (string-to-char otype)))))) 1731 (while (and (tex-search-noncomment 1732 (re-search-forward (format "\\\\[%s%s]" ctype otype))) 1733 (save-excursion 1734 (goto-char (match-beginning 0)) 1735 (looking-at (format "\\\\%s" (regexp-quote otype))))) 1736 (tex-next-unmatched-eparen otype))) 1737 (wrong-type-argument (error "Unknown opening parenthesis type: %s" otype)) 1738 (search-failed (error "Couldn't find closing escaped paren")))) 1739 1740(defun tex-last-unended-eparen (ctype) 1741 "Leave point at the start of the last unended escaped opening parenthesis. 1742The string CTYPE is a closing parenthesis type: `)', `}', or `]'." 1743 (condition-case nil 1744 (let ((otype (char-to-string (cdr (aref (syntax-table) 1745 (string-to-char ctype)))))) 1746 (while (and (tex-search-noncomment 1747 (re-search-backward (format "\\\\[%s%s]" ctype otype))) 1748 (looking-at (format "\\\\%s" (regexp-quote ctype)))) 1749 (tex-last-unended-eparen ctype))) 1750 (wrong-type-argument (error "Unknown opening parenthesis type: %s" ctype)) 1751 (search-failed (error "Couldn't find unended escaped paren")))) 1752 1753(defun tex-goto-last-unclosed-latex-block () 1754 "Move point to the last unclosed \\begin{...}. 1755Mark is left at original location." 1756 (interactive) 1757 (let ((spot)) 1758 (save-excursion 1759 (tex-last-unended-begin) 1760 (setq spot (point))) 1761 (push-mark) 1762 (goto-char spot))) 1763 1764(defvar latex-handle-escaped-parens t) 1765 1766;; Don't think this one actually _needs_ (for the purposes of 1767;; tex-mode) to handle escaped parens. 1768;; Does not handle escaped parens when latex-handle-escaped-parens is nil. 1769(defun latex-backward-sexp-1 () 1770 "Like (backward-sexp 1) but aware of multi-char elements and escaped parens." 1771 (let ((pos (point)) 1772 (forward-sexp-function)) 1773 (backward-sexp 1) 1774 (cond ((looking-at 1775 (if latex-handle-escaped-parens 1776 "\\\\\\(begin\\>\\|[[({]\\)" 1777 "\\\\begin\\>")) 1778 (signal 'scan-error 1779 (list "Containing expression ends prematurely" 1780 (point) (prog1 (point) (goto-char pos))))) 1781 ((and latex-handle-escaped-parens 1782 (looking-at "\\\\\\([])}]\\)")) 1783 (tex-last-unended-eparen (match-string 1))) 1784 ((eq (char-after) ?{) 1785 (let ((newpos (point))) 1786 (when (ignore-errors (backward-sexp 1) t) 1787 (if (or (looking-at "\\\\end\\>") 1788 ;; In case the \\ ends a verbatim section. 1789 (and (looking-at "end\\>") (eq (char-before) ?\\))) 1790 (tex-last-unended-begin) 1791 (goto-char newpos)))))))) 1792 1793;; Note this does not handle things like mismatched brackets inside 1794;; begin/end blocks. 1795;; Needs to handle escaped parens for tex-validate-*. 1796;; https://lists.gnu.org/r/bug-gnu-emacs/2007-09/msg00038.html 1797;; Does not handle escaped parens when latex-handle-escaped-parens is nil. 1798(defun latex-forward-sexp-1 () 1799 "Like (forward-sexp 1) but aware of multi-char elements and escaped parens." 1800 (let ((pos (point)) 1801 (forward-sexp-function)) 1802 (forward-sexp 1) 1803 (let ((newpos (point))) 1804 (skip-syntax-backward "/w") 1805 (cond 1806 ((looking-at "\\\\end\\>") 1807 (signal 'scan-error 1808 (list "Containing expression ends prematurely" 1809 (point) 1810 (prog1 1811 (progn (ignore-errors (forward-sexp 2)) (point)) 1812 (goto-char pos))))) 1813 ((looking-at "\\\\begin\\>") 1814 (goto-char (match-end 0)) 1815 (tex-next-unmatched-end)) 1816 ;; A better way to handle this, \( .. \) etc, is probably to 1817 ;; temporarily change the syntax of the \ in \( to punctuation. 1818 ((and latex-handle-escaped-parens 1819 (looking-back "\\\\[])}]" (- (point) 2))) 1820 (signal 'scan-error 1821 (list "Containing expression ends prematurely" 1822 (- (point) 2) (prog1 (point) 1823 (goto-char pos))))) 1824 ((and latex-handle-escaped-parens 1825 (looking-back "\\\\\\([({[]\\)" (- (point) 2))) 1826 (tex-next-unmatched-eparen (match-string 1))) 1827 (t (goto-char newpos)))))) 1828 1829(defun latex-forward-sexp (&optional arg) 1830 "Like `forward-sexp' but aware of multi-char elements and escaped parens." 1831 (interactive "P") 1832 (unless arg (setq arg 1)) 1833 (let ((pos (point)) 1834 (opoint 0)) 1835 (condition-case err 1836 (while (and (/= (point) opoint) 1837 (/= arg 0)) 1838 (setq opoint (point)) 1839 (setq arg 1840 (if (> arg 0) 1841 (progn (latex-forward-sexp-1) (1- arg)) 1842 (progn (latex-backward-sexp-1) (1+ arg))))) 1843 (scan-error 1844 (goto-char pos) 1845 (signal (car err) (cdr err)))))) 1846 1847(defun latex-syntax-after () 1848 "Like (char-syntax (char-after)) but aware of multi-char elements." 1849 (if (looking-at "\\\\end\\>") ?\) (char-syntax (following-char)))) 1850 1851(defun latex-skip-close-parens () 1852 "Like (skip-syntax-forward \" )\") but aware of multi-char elements." 1853 (let ((forward-sexp-function nil)) 1854 (while (progn (skip-syntax-forward " )") 1855 (looking-at "\\\\end\\>")) 1856 (forward-sexp 2)))) 1857 1858(defun latex-down-list () 1859 "Like (down-list 1) but aware of multi-char elements." 1860 (forward-comment (point-max)) 1861 (let ((forward-sexp-function nil)) 1862 (if (not (looking-at "\\\\begin\\>")) 1863 (down-list 1) 1864 (forward-sexp 1) 1865 ;; Skip arguments. 1866 (while (looking-at "[ \t]*[[{(]") 1867 (with-syntax-table tex-mode-syntax-table 1868 (forward-sexp)))))) 1869 1870(defalias 'tex-close-latex-block 'latex-close-block) 1871(define-skeleton latex-close-block 1872 "Create an \\end{...} to match the last unclosed \\begin{...}." 1873 (save-excursion 1874 (tex-last-unended-begin) 1875 (if (not (looking-at "\\\\begin\\(\\s *{[^}\n]*}\\)")) '("{" _ "}") 1876 (match-string 1))) 1877 \n "\\end" str > \n) 1878 1879(define-skeleton latex-split-block 1880 "Split the enclosing environment by inserting \\end{..}\\begin{..} at point." 1881 (save-excursion 1882 (tex-last-unended-begin) 1883 (if (not (looking-at "\\\\begin\\(\\s *{[^}\n]*}\\)")) '("{" _ "}") 1884 (prog1 (match-string 1) 1885 (goto-char (match-end 1)) 1886 (setq v1 (buffer-substring (point) 1887 (progn 1888 (while (looking-at "[ \t]*[[{]") 1889 (forward-sexp 1)) 1890 (point))))))) 1891 \n "\\end" str > \n _ \n "\\begin" str v1 > \n) 1892 1893(defconst tex-discount-args-cmds 1894 '("begin" "end" "input" "special" "cite" "ref" "include" "includeonly" 1895 "documentclass" "usepackage" "label") 1896 "TeX commands whose arguments should not be counted as text.") 1897 1898(defun tex-count-words (begin end) 1899 "Count the number of words in the buffer." 1900 (interactive 1901 (if (and transient-mark-mode mark-active) 1902 (list (region-beginning) (region-end)) 1903 (list (point-min) (point-max)))) 1904 ;; TODO: skip comments and math and maybe some environments. 1905 (save-excursion 1906 (goto-char begin) 1907 (let ((count 0)) 1908 (while (and (< (point) end) (re-search-forward "\\<" end t)) 1909 (if (not (eq (char-syntax (preceding-char)) ?/)) 1910 (progn 1911 ;; Don't count single-char words. 1912 (unless (looking-at ".\\>") (cl-incf count)) 1913 (forward-char 1)) 1914 (let ((cmd 1915 (buffer-substring-no-properties 1916 (point) (progn (when (zerop (skip-chars-forward "a-zA-Z@")) 1917 (forward-char 1)) 1918 (point))))) 1919 (when (member cmd tex-discount-args-cmds) 1920 (skip-chars-forward "*") 1921 (forward-comment (point-max)) 1922 (when (looking-at "\\[") 1923 (forward-sexp 1) 1924 (forward-comment (point-max))) 1925 (if (not (looking-at "{")) 1926 (forward-char 1) 1927 (forward-sexp 1)))))) 1928 (message "%s words" count)))) 1929 1930 1931 1932;;; Invoking TeX in an inferior shell. 1933 1934;; Why use a shell instead of running TeX directly? Because if TeX 1935;; gets stuck, the user can switch to the shell window and type at it. 1936 1937(defvar tex-error-parse-syntax-table 1938 (let ((st (make-syntax-table))) 1939 (modify-syntax-entry ?\( "()" st) 1940 (modify-syntax-entry ?\) ")(" st) 1941 (modify-syntax-entry ?\\ "\\" st) 1942 (modify-syntax-entry ?\{ "_" st) 1943 (modify-syntax-entry ?\} "_" st) 1944 (modify-syntax-entry ?\[ "_" st) 1945 (modify-syntax-entry ?\] "_" st) 1946 ;; Single quotations may appear in errors 1947 (modify-syntax-entry ?\" "_" st) 1948 st) 1949 "Syntax-table used while parsing TeX error messages.") 1950 1951(defun tex-old-error-file-name () 1952 ;; This is unreliable, partly because we don't try very hard, and 1953 ;; partly because TeX's output format is eminently ambiguous and unfriendly 1954 ;; to automation. 1955 (save-excursion 1956 (save-match-data 1957 (with-syntax-table tex-error-parse-syntax-table 1958 (beginning-of-line) 1959 (backward-up-list 1) 1960 (skip-syntax-forward "(_") 1961 (while (not (let ((try-filename (thing-at-point 'filename))) 1962 (and try-filename 1963 (not (string= "" try-filename)) 1964 (file-readable-p try-filename)))) 1965 (skip-syntax-backward "(_") 1966 (backward-up-list 1) 1967 (skip-syntax-forward "(_")) 1968 (thing-at-point 'filename))))) 1969 1970(defconst tex-error-regexp-alist 1971 ;; First alternative handles the newer --file-line-error style: 1972 ;; ./test2.tex:14: Too many }'s. 1973 '(gnu 1974 ;; Second handles the old-style, which spans two lines but doesn't include 1975 ;; any file info: 1976 ;; ! Too many }'s. 1977 ;; l.396 toto} 1978 ("^l\\.\\([1-9][0-9]*\\) \\(?:\\.\\.\\.\\)?\\(.*\\)$" 1979 tex-old-error-file-name 1 nil nil nil 1980 ;; Since there's no filename to highlight, let's highlight the message. 1981 (2 compilation-error-face)) 1982 ;; A few common warning messages. 1983 ("^\\(?:Und\\|Ov\\)erfull \\\\[hv]box .* at lines? \\(\\([1-9][0-9]*\\)\\(?:--\\([1-9][0-9]*\\)\\)?\\)$" 1984 tex-old-error-file-name (2 . 3) nil 1 nil 1985 (1 compilation-warning-face)) 1986 ("^(Font) *\\([^ \n].* on input line \\([1-9][0-9]*\\)\\)\\.$" 1987 tex-old-error-file-name 2 nil 1 1 1988 (2 compilation-warning-face)) 1989 ;; Included files get output as (<file> ...). 1990 ;; FIXME: there tend to be a boatload of them at the beginning of the 1991 ;; output which aren't that interesting. Maybe we should filter out 1992 ;; all the file name that start with /usr/share? 1993 ;; ("(\\.?/\\([^() \n]+\\)" 1 nil nil 0) 1994 )) 1995 1996;; The utility functions: 1997 1998(define-derived-mode tex-shell shell-mode "TeX-Shell" 1999 (setq-local compilation-error-regexp-alist tex-error-regexp-alist) 2000 (compilation-shell-minor-mode t)) 2001 2002;;;###autoload 2003(defun tex-start-shell () 2004 (with-current-buffer 2005 (make-comint 2006 "tex-shell" 2007 (or tex-shell-file-name (getenv "ESHELL") shell-file-name) 2008 nil 2009 ;; Specify an interactive shell, to make sure it prompts. 2010 "-i") 2011 (let ((proc (get-process "tex-shell"))) 2012 (set-process-sentinel proc 'tex-shell-sentinel) 2013 (set-process-query-on-exit-flag proc nil) 2014 (tex-shell) 2015 (while (zerop (buffer-size)) 2016 (sleep-for 1))))) 2017 2018(defun tex-feed-input () 2019 "Send input to the tex shell process. 2020In the tex buffer this can be used to continue an interactive tex run. 2021In the tex shell buffer this command behaves like `comint-send-input'." 2022 (interactive) 2023 (set-buffer (tex-shell-buf)) 2024 (comint-send-input) 2025 (tex-recenter-output-buffer nil)) 2026 2027(defun tex-display-shell () 2028 "Make the TeX shell buffer visible in a window." 2029 (display-buffer (tex-shell-buf)) 2030 (tex-recenter-output-buffer nil)) 2031 2032(defun tex-shell-sentinel (proc _msg) 2033 (cond ((null (buffer-name (process-buffer proc))) 2034 ;; buffer killed 2035 (set-process-buffer proc nil) 2036 (tex-delete-last-temp-files)) 2037 ((memq (process-status proc) '(signal exit)) 2038 (tex-delete-last-temp-files)))) 2039 2040(defun tex-set-buffer-directory (buffer directory) 2041 "Set BUFFER's default directory to be DIRECTORY." 2042 (setq directory (file-name-as-directory (expand-file-name directory))) 2043 (if (not (file-directory-p directory)) 2044 (error "%s is not a directory" directory) 2045 (with-current-buffer buffer 2046 (setq default-directory directory)))) 2047 2048(defvar tex-send-command-modified-tick 0) 2049(make-variable-buffer-local 'tex-send-command-modified-tick) 2050 2051(defun tex-shell-proc () 2052 (or (tex-shell-running) (error "No TeX subprocess"))) 2053(defun tex-shell-buf () 2054 (process-buffer (tex-shell-proc))) 2055(defun tex-shell-buf-no-error () 2056 (let ((proc (tex-shell-running))) 2057 (and proc (process-buffer proc)))) 2058 2059(defun tex-send-command (command &optional file background) 2060 "Send COMMAND to TeX shell process, substituting optional FILE for *. 2061Do this in background if optional BACKGROUND is t. If COMMAND has no *, 2062FILE will be appended, preceded by a blank, to COMMAND. If FILE is nil, no 2063substitution will be made in COMMAND. COMMAND can be any expression that 2064evaluates to a command string. 2065 2066Return the process in which TeX is running." 2067 (save-excursion 2068 (let* ((cmd (eval command)) 2069 (proc (tex-shell-proc)) 2070 (buf (process-buffer proc)) 2071 (star (string-match "\\*" cmd)) 2072 (string 2073 (concat 2074 (if (null file) 2075 cmd 2076 (if (file-name-absolute-p file) 2077 (setq file (convert-standard-filename file))) 2078 (if star (concat (substring cmd 0 star) 2079 (shell-quote-argument file) 2080 (substring cmd (1+ star))) 2081 (concat cmd " " (shell-quote-argument file)))) 2082 (if background "&" "")))) 2083 ;; Switch to buffer before checking for subproc output in it. 2084 (set-buffer buf) 2085 ;; If text is unchanged since previous tex-send-command, 2086 ;; we haven't got any output. So wait for output now. 2087 (if (= (buffer-modified-tick buf) tex-send-command-modified-tick) 2088 (accept-process-output proc)) 2089 (goto-char (process-mark proc)) 2090 (insert string) 2091 (comint-send-input) 2092 (setq tex-send-command-modified-tick (buffer-modified-tick buf)) 2093 proc))) 2094 2095(defun tex-delete-last-temp-files (&optional not-all) 2096 "Delete any junk files from last temp file. 2097If NOT-ALL is non-nil, save the `.dvi' file." 2098 (if tex-last-temp-file 2099 (let* ((dir (file-name-directory tex-last-temp-file)) 2100 (list (and (file-directory-p dir) 2101 (file-name-all-completions 2102 (file-name-base tex-last-temp-file) 2103 dir)))) 2104 (while list 2105 (if not-all 2106 (and 2107 ;; If arg is non-nil, don't delete the .dvi file. 2108 (not (string-match "\\.dvi$" (car list))) 2109 (delete-file (concat dir (car list)))) 2110 (delete-file (concat dir (car list)))) 2111 (setq list (cdr list)))))) 2112 2113(add-hook 'kill-emacs-hook #'tex-delete-last-temp-files) 2114 2115;; 2116;; Machinery to guess the command that the user wants to execute. 2117;; 2118 2119(defvar tex-compile-history nil) 2120 2121(defvar tex-input-files-re 2122 (eval-when-compile 2123 (concat "\\." (regexp-opt '("tex" "texi" "texinfo" 2124 "bbl" "ind" "sty" "cls") t) 2125 ;; Include files with no dots (for directories). 2126 "\\'\\|\\`[^.]+\\'"))) 2127 2128(defcustom tex-use-reftex t 2129 "If non-nil, use RefTeX's list of files to determine what command to use." 2130 :type 'boolean 2131 :group 'tex) 2132 2133(defvar tex-compile-commands 2134 `(,@(mapcar (lambda (prefix) 2135 `((concat ,prefix tex-command 2136 " " (if (< 0 (length tex-start-commands)) 2137 (shell-quote-argument tex-start-commands)) 2138 " %f") 2139 t "%r.pdf")) 2140 '("pdf" "xe" "lua")) 2141 ((concat tex-command 2142 " " (if (< 0 (length tex-start-commands)) 2143 (shell-quote-argument tex-start-commands)) 2144 " %f") 2145 t "%r.dvi") 2146 ("xdvi %r &" "%r.dvi") 2147 ("\\doc-view \"%r.pdf\"" "%r.pdf") 2148 ("xpdf %r.pdf &" "%r.pdf") 2149 ("gv %r.ps &" "%r.ps") 2150 ("yap %r &" "%r.dvi") 2151 ("advi %r &" "%r.dvi") 2152 ("gv %r.pdf &" "%r.pdf") 2153 ("bibtex %r" "%r.aux" "%r.bbl") 2154 ("makeindex %r" "%r.idx" "%r.ind") 2155 ("texindex %r.??") 2156 ("dvipdfm %r" "%r.dvi" "%r.pdf") 2157 ("dvipdf %r" "%r.dvi" "%r.pdf") 2158 ("dvips -o %r.ps %r" "%r.dvi" "%r.ps") 2159 ("ps2pdf %r.ps" "%r.ps" "%r.pdf") 2160 ("lpr %r.ps" "%r.ps")) 2161 "List of commands for `tex-compile'. 2162Each element should be of the form (FORMAT IN OUT) where 2163FORMAT is an expression that evaluates to a string that can contain 2164 - `%r' the main file name without extension. 2165 - `%f' the main file name. 2166IN can be either a string (with the same % escapes in it) indicating 2167 the name of the input file, or t to indicate that the input is all 2168 the TeX files of the document, or nil if we don't know. 2169OUT describes the output file and is either a %-escaped string 2170 or nil to indicate that there is no output file.") 2171 2172(define-obsolete-function-alias 'tex-string-prefix-p #'string-prefix-p "24.3") 2173 2174(defun tex-guess-main-file (&optional all) 2175 "Find a likely `tex-main-file'. 2176Looks for hints in other buffers in the same directory or in 2177ALL other buffers. If ALL is `sub' only look at buffers in parent directories 2178of the current buffer." 2179 (let ((dir default-directory) 2180 (header-re tex-start-of-header)) 2181 (catch 'found 2182 ;; Look for a buffer with `tex-main-file' set. 2183 (dolist (buf (if (consp all) all (buffer-list))) 2184 (with-current-buffer buf 2185 (when (and (cond 2186 ((null all) (equal dir default-directory)) 2187 ((eq all 'sub) (string-prefix-p default-directory dir)) 2188 (t)) 2189 (stringp tex-main-file)) 2190 (throw 'found (expand-file-name tex-main-file))))) 2191 ;; Look for a buffer containing the magic `tex-start-of-header'. 2192 (dolist (buf (if (consp all) all (buffer-list))) 2193 (with-current-buffer buf 2194 (when (and (cond 2195 ((null all) (equal dir default-directory)) 2196 ((eq all 'sub) (string-prefix-p default-directory dir)) 2197 (t)) 2198 buffer-file-name 2199 ;; (or (easy-mmode-derived-mode-p 'latex-mode) 2200 ;; (easy-mmode-derived-mode-p 'plain-tex-mode)) 2201 (save-excursion 2202 (save-restriction 2203 (widen) 2204 (goto-char (point-min)) 2205 (re-search-forward 2206 header-re (+ (point) 10000) t)))) 2207 (throw 'found (expand-file-name buffer-file-name)))))))) 2208 2209(defun tex-main-file () 2210 "Return the relative name of the main file." 2211 (let* ((file (or tex-main-file 2212 ;; Compatibility with AUCTeX. 2213 (with-no-warnings 2214 (when (boundp 'TeX-master) 2215 (cond ((stringp TeX-master) 2216 (setq-local tex-main-file TeX-master)) 2217 ((and (eq TeX-master t) buffer-file-name) 2218 (file-relative-name buffer-file-name))))) 2219 ;; Try to guess the main file. 2220 (if (not buffer-file-name) 2221 (error "Buffer is not associated with any file") 2222 (file-relative-name 2223 (if (save-excursion 2224 (goto-char (point-min)) 2225 (re-search-forward tex-start-of-header 2226 (+ (point) 10000) t)) 2227 ;; This is the main file. 2228 buffer-file-name 2229 ;; This isn't the main file, let's try to find better, 2230 (or (tex-guess-main-file) 2231 (tex-guess-main-file 'sub) 2232 ;; (tex-guess-main-file t) 2233 buffer-file-name))))))) 2234 (if (or (file-exists-p file) (string-match "\\.tex\\'" file)) 2235 file (concat file ".tex")))) 2236 2237(defun tex-summarize-command (cmd) 2238 (if (not (stringp cmd)) "" 2239 (mapconcat #'identity 2240 (mapcar (lambda (s) (car (split-string s))) 2241 (split-string cmd "\\s-*\\(?:;\\|&&\\)\\s-*")) 2242 "&"))) 2243 2244(defun tex-uptodate-p (file) 2245 "Return non-nil if FILE is not uptodate w.r.t the document source files. 2246FILE is typically the output DVI or PDF file." 2247 ;; We should check all the files included !!! 2248 (and 2249 ;; Clearly, the target must exist. 2250 (file-exists-p file) 2251 ;; And the last run must not have asked for a rerun. 2252 ;; FIXME: this should check that the last run was done on the same file. 2253 (let ((buf (condition-case nil (tex-shell-buf) (error nil)))) 2254 (when buf 2255 (with-current-buffer buf 2256 (save-excursion 2257 (goto-char (point-max)) 2258 (and (re-search-backward 2259 (concat "(see the transcript file for additional information)" 2260 "\\|^Output written on .*" 2261 (regexp-quote (file-name-nondirectory file)) 2262 " (.*)\\.") 2263 nil t) 2264 (> (save-excursion 2265 ;; Usually page numbers are output as [N], but 2266 ;; I've already seen things like 2267 ;; [N{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] 2268 ;; as well as [N.N] (e.g. with 'acmart' style). 2269 (or (re-search-backward 2270 "\\[[0-9]+\\({[^}]*}\\|\\.[0-9]+\\)?\\]" 2271 nil t) 2272 (point-min))) 2273 (save-excursion 2274 (or (re-search-backward "Rerun" nil t) 2275 (point-min))))))))) 2276 ;; And the input files must not have been changed in the meantime. 2277 (let ((files (if (and tex-use-reftex 2278 (fboundp 'reftex-scanning-info-available-p) 2279 (reftex-scanning-info-available-p)) 2280 (reftex-all-document-files) 2281 (list (file-name-directory (expand-file-name file))))) 2282 (ignored-dirs-re 2283 (concat 2284 (regexp-opt 2285 (delq nil (mapcar (lambda (s) (if (eq (aref s (1- (length s))) ?/) 2286 (substring s 0 (1- (length s))))) 2287 completion-ignored-extensions)) 2288 t) "\\'")) 2289 (uptodate t)) 2290 (while (and files uptodate) 2291 (let ((f (pop files))) 2292 (if (and (file-directory-p f) 2293 ;; Avoid infinite loops. 2294 (not (file-symlink-p f))) 2295 (unless (string-match ignored-dirs-re f) 2296 (setq files (nconc 2297 (ignore-errors ;Not readable or something. 2298 (directory-files f t tex-input-files-re)) 2299 files))) 2300 (when (file-newer-than-file-p f file) 2301 (setq uptodate nil))))) 2302 uptodate))) 2303 2304 2305(autoload 'format-spec "format-spec") 2306 2307(defvar tex-executable-cache nil) 2308(defun tex-executable-exists-p (name) 2309 "Like `executable-find' but with a cache." 2310 (let ((f (and (string-match "^\\\\\\([^ \t\n]+\\)" name) 2311 (intern-soft (concat "tex-cmd-" (match-string 1 name)))))) 2312 (if (fboundp f) 2313 f 2314 (let ((cache (assoc name tex-executable-cache))) 2315 (if cache (cdr cache) 2316 (let ((executable (executable-find name))) 2317 (push (cons name executable) tex-executable-cache) 2318 executable)))))) 2319 2320(defun tex-command-executable (cmd) 2321 (let ((s (if (stringp cmd) cmd (eval (car cmd))))) 2322 (substring s 0 (string-match "[ \t]\\|\\'" s)))) 2323 2324(defun tex-command-active-p (cmd fspec) 2325 "Return non-nil if the CMD spec might need to be run." 2326 (let ((in (nth 1 cmd)) 2327 (out (nth 2 cmd))) 2328 (if (stringp in) 2329 (let ((file (format-spec in fspec))) 2330 (when (file-exists-p file) 2331 (or (not out) 2332 (file-newer-than-file-p 2333 file (format-spec out fspec))))) 2334 (when (and (eq in t) (stringp out)) 2335 (not (tex-uptodate-p (format-spec out fspec))))))) 2336 2337(defcustom tex-cmd-bibtex-args "--min-crossref=100" 2338 "Extra args to pass to `bibtex' by default." 2339 :type 'string 2340 :version "23.1" 2341 :group 'tex-run) 2342 2343(defun tex-format-cmd (format fspec) 2344 "Like `format-spec' but adds user-specified args to the command. 2345Only applies the FSPEC to the args part of FORMAT." 2346 (if (not (string-match "\\([^ /\\]+\\) " format)) 2347 (format-spec format fspec) 2348 (let* ((prefix (substring format 0 (match-beginning 0))) 2349 (cmd (match-string 1 format)) 2350 (args (substring format (match-end 0))) 2351 (sym (intern-soft (format "tex-cmd-%s-args" cmd))) 2352 (extra-args (and sym (symbol-value sym)))) 2353 (concat prefix cmd 2354 (if extra-args (concat " " extra-args)) 2355 " " (format-spec args fspec))))) 2356 2357(defun tex-compile-default (fspec) 2358 "Guess a default command given the `format-spec' FSPEC." 2359 ;; TODO: Learn to do latex+dvips! 2360 (let ((cmds nil) 2361 (unchanged-in nil)) 2362 ;; Only consider active commands. 2363 (dolist (cmd tex-compile-commands) 2364 (when (tex-executable-exists-p (tex-command-executable cmd)) 2365 (if (tex-command-active-p cmd fspec) 2366 (push cmd cmds) 2367 (push (nth 1 cmd) unchanged-in)))) 2368 ;; If no command seems to be applicable, arbitrarily pick the first one. 2369 (setq cmds (if cmds (nreverse cmds) (list (car tex-compile-commands)))) 2370 ;; Remove those commands whose input was considered stable for 2371 ;; some other command (typically if (t . "%.pdf") is inactive 2372 ;; then we're using pdflatex and the fact that the dvi file 2373 ;; is nonexistent doesn't matter). 2374 (let ((tmp nil)) 2375 (dolist (cmd cmds) 2376 (unless (member (nth 1 cmd) unchanged-in) 2377 (push cmd tmp))) 2378 ;; Only remove if there's something left. 2379 (if tmp (setq cmds (nreverse tmp)))) 2380 ;; Remove commands whose input is not uptodate either. 2381 (let ((outs (delq nil (mapcar (lambda (x) (nth 2 x)) cmds))) 2382 (tmp nil)) 2383 (dolist (cmd cmds) 2384 (unless (member (nth 1 cmd) outs) 2385 (push cmd tmp))) 2386 ;; Only remove if there's something left. 2387 (if tmp (setq cmds (nreverse tmp)))) 2388 ;; Select which file we're going to operate on (the latest). 2389 (let ((latest (nth 1 (car cmds)))) 2390 (dolist (cmd (prog1 (cdr cmds) (setq cmds (list (car cmds))))) 2391 (if (equal latest (nth 1 cmd)) 2392 (push cmd cmds) 2393 (unless (eq latest t) ;Can't beat that! 2394 (if (or (not (stringp latest)) 2395 (eq (nth 1 cmd) t) 2396 (and (stringp (nth 1 cmd)) 2397 (file-newer-than-file-p 2398 (format-spec (nth 1 cmd) fspec) 2399 (format-spec latest fspec)))) 2400 (setq latest (nth 1 cmd) cmds (list cmd))))))) 2401 ;; Expand the command spec into the actual text. 2402 (dolist (cmd (prog1 cmds (setq cmds nil))) 2403 (push (cons (eval (car cmd)) (cdr cmd)) cmds)) 2404 ;; Select the favorite command from the history. 2405 (let ((hist tex-compile-history) 2406 re hist-cmd) 2407 (while hist 2408 (setq hist-cmd (pop hist)) 2409 (setq re (concat "\\`" 2410 (regexp-quote (tex-command-executable hist-cmd)) 2411 "\\([ \t]\\|\\'\\)")) 2412 (dolist (cmd cmds) 2413 ;; If the hist entry uses the same command and applies to a file 2414 ;; of the same type (e.g. `gv %r.pdf' vs `gv %r.ps'), select cmd. 2415 (and (string-match re (car cmd)) 2416 (or (not (string-match "%[fr]\\([-._[:alnum:]]+\\)" (car cmd))) 2417 (string-match (regexp-quote (match-string 1 (car cmd))) 2418 hist-cmd)) 2419 (setq hist nil cmds (list cmd))))) 2420 ;; Substitute and return. 2421 (if (and hist-cmd 2422 (string-match (concat "[' \t\"]" (format-spec "%r" fspec) 2423 "\\([;&' \t\"]\\|\\'\\)") 2424 hist-cmd)) 2425 ;; The history command was already applied to the same file, 2426 ;; so just reuse it. 2427 hist-cmd 2428 (if cmds (tex-format-cmd (caar cmds) fspec)))))) 2429 2430(defun tex-cmd-doc-view (file) 2431 (pop-to-buffer (find-file-noselect file))) 2432 2433(defun tex-compile (dir cmd) 2434 "Run a command CMD on current TeX buffer's file in DIR." 2435 ;; FIXME: Use time-stamps on files to decide the next op. 2436 (interactive 2437 (let* ((file (tex-main-file)) 2438 (default-directory 2439 (prog1 (file-name-directory (expand-file-name file)) 2440 (setq file (file-name-nondirectory file)))) 2441 (root (file-name-sans-extension file)) 2442 (fspec (list (cons ?r (shell-quote-argument root)) 2443 (cons ?f (shell-quote-argument file)))) 2444 (default (tex-compile-default fspec))) 2445 (list default-directory 2446 (completing-read 2447 (format "Command [%s]: " (tex-summarize-command default)) 2448 (mapcar (lambda (x) 2449 (list (tex-format-cmd (eval (car x)) fspec))) 2450 tex-compile-commands) 2451 nil nil nil 'tex-compile-history default)))) 2452 (save-some-buffers (not compilation-ask-about-save) nil) 2453 (let ((f (and (string-match "^\\\\\\([^ \t\n]+\\)" cmd) 2454 (intern-soft (concat "tex-cmd-" (match-string 1 cmd)))))) 2455 (if (functionp f) 2456 (condition-case nil 2457 (let ((default-directory dir)) 2458 (apply f (split-string-and-unquote 2459 (substring cmd (match-end 0))))) 2460 (wrong-number-of-arguments 2461 (error "Wrong number of arguments to %s" 2462 (substring (symbol-name f) 8)))) 2463 (if (tex-shell-running) 2464 (tex-kill-job) 2465 (tex-start-shell)) 2466 (tex-send-tex-command cmd dir)))) 2467 2468(defun tex-start-tex (command file &optional dir) 2469 "Start a TeX run, using COMMAND on FILE." 2470 (let* ((star (string-match "\\*" command)) 2471 (compile-command 2472 (if star 2473 (concat (substring command 0 star) 2474 (shell-quote-argument file) 2475 (substring command (1+ star))) 2476 (concat command " " 2477 tex-start-options 2478 (if (< 0 (length tex-start-commands)) 2479 (concat 2480 (shell-quote-argument tex-start-commands) " ")) 2481 (shell-quote-argument file))))) 2482 (tex-send-tex-command compile-command dir))) 2483 2484(defun tex-send-tex-command (cmd &optional dir) 2485 (unless (or (equal dir (let ((buf (tex-shell-buf-no-error))) 2486 (and buf (with-current-buffer buf 2487 default-directory)))) 2488 (not dir)) 2489 (let (shell-dirtrack-verbose) 2490 (tex-send-command tex-shell-cd-command dir))) 2491 (with-current-buffer (process-buffer (tex-send-command cmd)) 2492 (setq compilation-last-buffer (current-buffer)) 2493 (compilation-forget-errors) 2494 ;; Don't parse previous compilations. 2495 (set-marker compilation-parsing-end (1- (point-max)))) 2496 (tex-display-shell) 2497 (setq tex-last-buffer-texed (current-buffer))) 2498 2499;;; The commands: 2500 2501(defun tex-region (beg end) 2502 "Run TeX on the current region, via a temporary file. 2503The file's name comes from the variable `tex-zap-file' and the 2504variable `tex-directory' says where to put it. 2505 2506If the buffer has a header, the header is given to TeX before the 2507region itself. The buffer's header is all lines between the strings 2508defined by `tex-start-of-header' and `tex-end-of-header' inclusive. 2509The header must start in the first 100 lines of the buffer. 2510 2511The value of `tex-trailer' is given to TeX as input after the region. 2512 2513The value of `tex-command' specifies the command to use to run TeX." 2514 (interactive "r") 2515 (if (tex-shell-running) 2516 (tex-kill-job) 2517 (tex-start-shell)) 2518 (or tex-zap-file 2519 (setq tex-zap-file (tex-generate-zap-file-name))) 2520 ;; Temp file will be written and TeX will be run in zap-directory. 2521 ;; If the TEXINPUTS file has relative directories or if the region has 2522 ;; \input of files, this must be the same directory as the file for 2523 ;; TeX to access the correct inputs. That's why it's safest if 2524 ;; tex-directory is ".". 2525 (let* ((zap-directory 2526 (file-name-as-directory (expand-file-name tex-directory))) 2527 (tex-out-file (expand-file-name (concat tex-zap-file ".tex") 2528 zap-directory)) 2529 (main-file (expand-file-name (tex-main-file))) 2530 (ismain (string-equal main-file (buffer-file-name))) 2531 already-output) 2532 ;; Don't delete temp files if we do the same buffer twice in a row. 2533 (or (eq (current-buffer) tex-last-buffer-texed) 2534 (tex-delete-last-temp-files t)) 2535 (let ((default-directory zap-directory)) ; why? 2536 ;; We assume the header is fully contained in tex-main-file. 2537 ;; We use f-f-ns so we get prompted about any changes on disk. 2538 (with-current-buffer (find-file-noselect main-file) 2539 (setq already-output (tex-region-header tex-out-file 2540 (and ismain beg)))) 2541 ;; Write out the specified region (but don't repeat anything 2542 ;; already written in the header). 2543 (write-region (if ismain 2544 (max beg already-output) 2545 beg) 2546 end tex-out-file (not (zerop already-output))) 2547 ;; Write the trailer, if any. 2548 ;; Precede it with a newline to make sure it 2549 ;; is not hidden in a comment. 2550 (if tex-trailer 2551 (write-region (concat "\n" tex-trailer) nil 2552 tex-out-file t))) 2553 ;; Record the file name to be deleted afterward. 2554 (setq tex-last-temp-file tex-out-file) 2555 ;; Use a relative file name here because (1) the proper dir 2556 ;; is already current, and (2) the abs file name is sometimes 2557 ;; too long and can make tex crash. 2558 (tex-start-tex tex-command (concat tex-zap-file ".tex") zap-directory) 2559 (setq tex-print-file tex-out-file))) 2560 2561(defun tex-region-header (file &optional beg) 2562 "If there is a TeX header in the current buffer, write it to FILE. 2563Return point at the end of the region so written, or zero. If 2564the optional buffer position BEG is specified, then the region 2565written out starts at BEG, if this lies before the start of the header. 2566 2567If the first line matches `tex-first-line-header-regexp', it is 2568also written out. The variables `tex-start-of-header' and 2569`tex-end-of-header' are used to locate the header. Note that the 2570start of the header is required to be within the first 100 lines." 2571 (save-excursion 2572 (save-restriction 2573 (widen) 2574 (goto-char (point-min)) 2575 (let ((search-end (save-excursion 2576 (forward-line 100) 2577 (point))) 2578 (already-output 0) 2579 hbeg hend) 2580 ;; Maybe copy first line, such as `\input texinfo', to temp file. 2581 (and tex-first-line-header-regexp 2582 (looking-at tex-first-line-header-regexp) 2583 (write-region (point) 2584 (progn (forward-line 1) 2585 (setq already-output (point))) 2586 file)) 2587 ;; Write out the header, if there is one, and any of the 2588 ;; specified region which extends before it. But don't repeat 2589 ;; anything already written. 2590 (and tex-start-of-header 2591 (re-search-forward tex-start-of-header search-end t) 2592 (progn 2593 (beginning-of-line) 2594 (setq hbeg (point)) ; mark beginning of header 2595 (when (re-search-forward tex-end-of-header nil t) 2596 (forward-line 1) 2597 (setq hend (point)) ; mark end of header 2598 (write-region 2599 (max (if beg 2600 (min hbeg beg) 2601 hbeg) 2602 already-output) 2603 hend file (not (zerop already-output))) 2604 (setq already-output hend)))) 2605 already-output)))) 2606 2607(defun tex-buffer () 2608 "Run TeX on current buffer. See \\[tex-region] for more information. 2609Does not save the buffer, so it's useful for trying experimental versions. 2610See \\[tex-file] for an alternative." 2611 (interactive) 2612 (tex-region (point-min) (point-max))) 2613 2614(defun tex-file () 2615 "Prompt to save all buffers and run TeX (or LaTeX) on current buffer's file. 2616This function is more useful than \\[tex-buffer] when you need the 2617`.aux' file of LaTeX to have the correct name." 2618 (interactive) 2619 (when tex-offer-save 2620 (save-some-buffers)) 2621 (let* ((source-file (tex-main-file)) 2622 (file-dir (file-name-directory (expand-file-name source-file)))) 2623 (if (tex-shell-running) 2624 (tex-kill-job) 2625 (tex-start-shell)) 2626 (tex-start-tex tex-command source-file file-dir) 2627 (setq tex-print-file (expand-file-name source-file)))) 2628 2629(defun tex-generate-zap-file-name () 2630 "Generate a unique name suitable for use as a file name." 2631 ;; Include the shell process number and host name 2632 ;; in case there are multiple shells (for same or different user). 2633 ;; Dec 1998: There is a report that some versions of xdvi 2634 ;; don't work with file names that start with #. 2635 (format "_TZ_%d-%s" 2636 (process-id (get-buffer-process "*tex-shell*")) 2637 (subst-char-in-string ?. ?- (system-name)))) 2638 2639;; This will perhaps be useful for modifying TEXINPUTS. 2640;; Expand each file name, separated by colons, in the string S. 2641(defun tex-expand-files (s) 2642 (let (elts (start 0)) 2643 (while (string-match ":" s start) 2644 (setq elts (cons (substring s start (match-beginning 0)) elts)) 2645 (setq start (match-end 0))) 2646 (or (= start 0) 2647 (setq elts (cons (substring s start) elts))) 2648 (mapconcat (lambda (elt) 2649 (if (= (length elt) 0) elt (expand-file-name elt))) 2650 (nreverse elts) ":"))) 2651 2652(defun tex-shell-running () 2653 (let ((proc (get-process "tex-shell"))) 2654 (when proc 2655 (if (and (eq (process-status proc) 'run) 2656 (buffer-live-p (process-buffer proc))) 2657 ;; return the TeX process on success 2658 proc 2659 ;; get rid of the process permanently 2660 ;; this should get rid of the annoying w32 problem with 2661 ;; dead tex-shell buffer and live process 2662 (delete-process proc))))) 2663 2664(defun tex-kill-job () 2665 "Kill the currently running TeX job." 2666 (interactive) 2667 ;; `quit-process' leads to core dumps of the tex process (except if 2668 ;; coredumpsize has limit 0kb as on many environments). One would 2669 ;; like to use (kill-process proc 'lambda), however that construct 2670 ;; does not work on some systems and kills the shell itself. 2671 (let ((proc (get-process "tex-shell"))) 2672 (when proc (quit-process proc t)))) 2673 2674(defun tex-recenter-output-buffer (linenum) 2675 "Redisplay buffer of TeX job output so that most recent output can be seen. 2676The last line of the buffer is displayed on 2677line LINE of the window, or centered if LINE is nil." 2678 (interactive "P") 2679 (let ((tex-shell (get-buffer "*tex-shell*")) 2680 (window)) 2681 (if (null tex-shell) 2682 (message "No TeX output buffer") 2683 (setq window (display-buffer tex-shell)) 2684 (with-selected-window window 2685 (bury-buffer tex-shell) 2686 (goto-char (point-max)) 2687 (recenter (if linenum 2688 (prefix-numeric-value linenum) 2689 (/ (window-height) 2))))))) 2690 2691(defcustom tex-print-file-extension ".dvi" 2692 "The TeX-compiled file extension for viewing and printing. 2693If you use pdflatex instead of latex, set this to \".pdf\" and modify 2694 `tex-dvi-view-command' and `tex-dvi-print-command' appropriately." 2695 :type 'string 2696 :group 'tex-view 2697 :version "25.1") 2698 2699(defun tex-print (&optional alt) 2700 "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file]. 2701Runs the shell command defined by `tex-dvi-print-command'. If prefix argument 2702is provided, use the alternative command, `tex-alt-dvi-print-command'." 2703 (interactive "P") 2704 (let ((print-file-name-dvi (tex-append tex-print-file 2705 tex-print-file-extension)) 2706 test-name) 2707 (if (and (not (equal (current-buffer) tex-last-buffer-texed)) 2708 (buffer-file-name) 2709 ;; Check that this buffer's printed file is up to date. 2710 (file-newer-than-file-p 2711 (setq test-name (tex-append (buffer-file-name) 2712 tex-print-file-extension)) 2713 (buffer-file-name))) 2714 (setq print-file-name-dvi test-name)) 2715 (if (not (file-exists-p print-file-name-dvi)) 2716 (error "No appropriate `.dvi' file could be found") 2717 (if (tex-shell-running) 2718 (tex-kill-job) 2719 (tex-start-shell)) 2720 (tex-send-command 2721 (if alt tex-alt-dvi-print-command tex-dvi-print-command) 2722 print-file-name-dvi 2723 t)))) 2724 2725(defun tex-alt-print () 2726 "Print the .dvi file made by \\[tex-region], \\[tex-buffer] or \\[tex-file]. 2727Runs the shell command defined by `tex-alt-dvi-print-command'." 2728 (interactive) 2729 (tex-print t)) 2730 2731(defun tex-view () 2732 "Preview the last `.dvi' file made by running TeX under Emacs. 2733This means, made using \\[tex-region], \\[tex-buffer] or \\[tex-file]. 2734The variable `tex-dvi-view-command' specifies the shell command for preview. 2735You must set that variable yourself before using this command, 2736because there is no standard value that would generally work." 2737 (interactive) 2738 (or tex-dvi-view-command 2739 (error "You must set `tex-dvi-view-command'")) 2740 ;; Restart the TeX shell if necessary. 2741 (or (tex-shell-running) 2742 (tex-start-shell)) 2743 (let ((tex-dvi-print-command (eval tex-dvi-view-command))) 2744 (tex-print))) 2745 2746(defun tex-append (file-name suffix) 2747 "Append to FILENAME the suffix SUFFIX, using same algorithm TeX uses. 2748Pascal-based TeX scans for the first period, C TeX uses the last. 2749No period is retained immediately before SUFFIX, 2750so normally SUFFIX starts with one." 2751 (if (stringp file-name) 2752 (let ((file (file-name-nondirectory file-name)) 2753 trial-name) 2754 ;; Try splitting on last period. 2755 ;; The first-period split can get fooled when two files 2756 ;; named a.tex and a.b.tex are both tex'd; 2757 ;; the last-period split must be right if it matches at all. 2758 (setq trial-name 2759 (concat (file-name-directory file-name) 2760 (substring file 0 2761 (string-match "\\.[^.]*$" file)) 2762 suffix)) 2763 (if (or (file-exists-p trial-name) 2764 (file-exists-p (concat trial-name ".aux"))) ;for BibTeX files 2765 trial-name 2766 ;; Not found, so split on first period. 2767 (concat (file-name-directory file-name) 2768 (substring file 0 2769 (string-match "\\." file)) 2770 suffix))) 2771 " ")) 2772 2773(defun tex-show-print-queue () 2774 "Show the print queue that \\[tex-print] put your job on. 2775Runs the shell command defined by `tex-show-queue-command'." 2776 (interactive) 2777 (if (tex-shell-running) 2778 (tex-kill-job) 2779 (tex-start-shell)) 2780 (tex-send-command tex-show-queue-command) 2781 (tex-display-shell)) 2782 2783(defun tex-bibtex-file () 2784 "Run BibTeX on the current buffer's file." 2785 (interactive) 2786 (if (tex-shell-running) 2787 (tex-kill-job) 2788 (tex-start-shell)) 2789 (let* (shell-dirtrack-verbose 2790 (source-file (expand-file-name (tex-main-file))) 2791 (tex-out-file 2792 (tex-append (file-name-nondirectory source-file) "")) 2793 (file-dir (file-name-directory source-file))) 2794 (tex-send-command tex-shell-cd-command file-dir) 2795 (tex-send-command tex-bibtex-command tex-out-file)) 2796 (tex-display-shell)) 2797 2798;;;; 2799;;;; LaTeX indentation 2800;;;; 2801 2802(defvar tex-indent-allhanging t) 2803(defvar tex-indent-arg 4) 2804(defvar tex-indent-basic 2) 2805(defvar tex-indent-item tex-indent-basic) 2806(defvar tex-indent-item-re "\\\\\\(bib\\)?item\\>") 2807(defcustom latex-noindent-environments '("document") 2808 "Environments whose content is not indented by `tex-indent-basic'." 2809 :type '(repeat string) 2810 :safe (lambda (x) (not (memq nil (mapcar #'stringp x)))) 2811 :group 'tex-file 2812 :version "27.1") 2813 2814(defcustom latex-noindent-commands '("emph" "footnote") 2815 "Commands for which `tex-indent-basic' should not be used." 2816 :type '(repeat string) 2817 :safe (lambda (x) (not (memq nil (mapcar #'stringp x)))) 2818 :group 'tex-file 2819 :version "27.1") 2820 2821(defvar tex-latex-indent-syntax-table 2822 (let ((st (make-syntax-table tex-mode-syntax-table))) 2823 (modify-syntax-entry ?$ "." st) 2824 (modify-syntax-entry ?\( "." st) 2825 (modify-syntax-entry ?\) "." st) 2826 st) 2827 "Syntax table used while computing indentation.") 2828 2829(defun latex-indent (&optional _arg) 2830 (if (and (eq (get-text-property (if (and (eobp) (bolp)) 2831 (max (point-min) (1- (point))) 2832 (line-beginning-position)) 2833 'face) 2834 'tex-verbatim)) 2835 'noindent 2836 (with-syntax-table tex-latex-indent-syntax-table 2837 ;; TODO: Rather than ignore $, we should try to be more clever about it. 2838 (let ((indent 2839 (save-excursion 2840 (beginning-of-line) 2841 (latex-find-indent)))) 2842 (if (< indent 0) (setq indent 0)) 2843 (if (<= (current-column) (current-indentation)) 2844 (indent-line-to indent) 2845 (save-excursion (indent-line-to indent))))))) 2846 2847(defcustom latex-indent-within-escaped-parens nil 2848 "Non-nil means add extra indent to text within escaped parens. 2849When this is non-nil, text within matching pairs of escaped 2850parens is indented at the column following the open paren. The 2851default value does not add any extra indent thus providing the 2852behavior of Emacs 22 and earlier." 2853 :type 'boolean 2854 :group 'tex 2855 :version "23.1") 2856 2857(defun latex-find-indent (&optional virtual) 2858 "Find the proper indentation of text after point. 2859VIRTUAL if non-nil indicates that we're only trying to find the indentation 2860 in order to determine the indentation of something else. 2861There might be text before point." 2862 (let ((latex-handle-escaped-parens latex-indent-within-escaped-parens)) 2863 (save-excursion 2864 (skip-chars-forward " \t") 2865 (or 2866 ;; Stick the first line at column 0. 2867 (and (= (point-min) (line-beginning-position)) 0) 2868 ;; Trust the current indentation, if such info is applicable. 2869 (and virtual (save-excursion (skip-chars-backward " \t&") (bolp)) 2870 (current-column)) 2871 ;; Stick verbatim environments to the left margin. 2872 (and (looking-at "\\\\\\(begin\\|end\\) *{\\([^\n}]+\\)") 2873 (member (match-string 2) tex-verbatim-environments) 2874 0) 2875 ;; Put leading close-paren where the matching open paren would be. 2876 (let (escaped) 2877 (and (or (eq (latex-syntax-after) ?\)) 2878 ;; Try to handle escaped close parens but keep 2879 ;; original position if it doesn't work out. 2880 (and latex-handle-escaped-parens 2881 (setq escaped (looking-at "\\\\\\([])}]\\)")))) 2882 (ignore-errors 2883 (save-excursion 2884 (when escaped 2885 (goto-char (match-beginning 1))) 2886 (latex-skip-close-parens) 2887 (latex-backward-sexp-1) 2888 (latex-find-indent 'virtual))))) 2889 ;; Default (maybe an argument) 2890 (let ((pos (point)) 2891 ;; Outdent \item if necessary. 2892 (indent (if (looking-at tex-indent-item-re) (- tex-indent-item) 0)) 2893 up-list-pos) 2894 ;; Find the previous point which determines our current indentation. 2895 (condition-case err 2896 (progn 2897 (latex-backward-sexp-1) 2898 (while (> (current-column) (current-indentation)) 2899 (latex-backward-sexp-1))) 2900 (scan-error 2901 (setq up-list-pos (nth 2 err)))) 2902 (cond 2903 ((= (point-min) pos) 0) ; We're really just indenting the first line. 2904 ((integerp up-list-pos) 2905 ;; Have to indent relative to the open-paren. 2906 (goto-char up-list-pos) 2907 (if (and (not tex-indent-allhanging) 2908 (save-excursion 2909 ;; Make sure we're an argument to a macro and 2910 ;; that the macro is at the beginning of a line. 2911 (condition-case nil 2912 (progn 2913 (while (eq (char-syntax (char-after)) ?\() 2914 (forward-sexp -1)) 2915 (and (eq (char-syntax (char-after)) ?/) 2916 (progn (skip-chars-backward " \t&") 2917 (bolp)))) 2918 (scan-error nil))) 2919 (> pos (progn (latex-down-list) 2920 (forward-comment (point-max)) 2921 (point)))) 2922 ;; Align with the first element after the open-paren. 2923 (current-column) 2924 ;; We're the first element after a hanging brace. 2925 (goto-char up-list-pos) 2926 (+ (if (if (eq (char-after) ?\{) 2927 (save-excursion 2928 (skip-chars-backward " \t") 2929 (let ((end (point))) 2930 (skip-chars-backward "a-zA-Z") 2931 (and (eq (char-before) ?\\) 2932 (member (buffer-substring (point) end) 2933 latex-noindent-commands)))) 2934 (and (looking-at "\\\\begin *{\\([^\n}]+\\)") 2935 (member (match-string 1) 2936 latex-noindent-environments))) 2937 0 tex-indent-basic) 2938 indent (latex-find-indent 'virtual)))) 2939 ;; We're now at the "beginning" of a line. 2940 ((not (and (not virtual) (eq (char-after) ?\\))) 2941 ;; Nothing particular here: just keep the same indentation. 2942 (+ indent (current-column))) 2943 ;; We're now looking at a macro call. 2944 ((looking-at tex-indent-item-re) 2945 ;; Indenting relative to an item, have to re-add the outdenting. 2946 (+ indent (current-column) tex-indent-item)) 2947 (t 2948 (let ((col (current-column))) 2949 (if (or (not (eq (char-syntax (or (char-after pos) ?\s)) ?\()) 2950 ;; Can't be an arg if there's an empty line in between. 2951 (save-excursion (re-search-forward "^[ \t]*$" pos t))) 2952 ;; If the first char was not an open-paren, there's 2953 ;; a risk that this is really not an argument to the 2954 ;; macro at all. 2955 (+ indent col) 2956 (forward-sexp 1) 2957 (if (< (line-end-position) 2958 (save-excursion (forward-comment (point-max)) 2959 (point))) 2960 ;; we're indenting the first argument. 2961 (min (current-column) (+ tex-indent-arg col)) 2962 (skip-syntax-forward " ") 2963 (current-column))))))))))) 2964;;; DocTeX support 2965 2966(defun doctex-font-lock-^^A () 2967 (if (eq (char-after (line-beginning-position)) ?\%) 2968 (progn 2969 (put-text-property 2970 (1- (match-beginning 1)) (match-beginning 1) 2971 'syntax-table 2972 (if (= (1+ (line-beginning-position)) (match-beginning 1)) 2973 ;; The `%' is a single-char comment, which Emacs 2974 ;; syntax-table can't deal with. We could turn it 2975 ;; into a non-comment, or use `\n%' or `%^' as the comment. 2976 ;; Instead, we include it in the ^^A comment. 2977 (string-to-syntax "< b") 2978 (string-to-syntax ">"))) 2979 (let ((end (line-end-position))) 2980 (if (< end (point-max)) 2981 (put-text-property 2982 end (1+ end) 2983 'syntax-table 2984 (string-to-syntax "> b")))) 2985 (string-to-syntax "< b")))) 2986 2987(defun doctex-font-lock-syntactic-face-function (state) 2988 ;; Mark DocTeX documentation, which is parsed as a style A comment 2989 ;; starting in column 0. 2990 (if (or (nth 3 state) (nth 7 state) 2991 (not (memq (char-before (nth 8 state)) 2992 '(?\n nil)))) 2993 ;; Anything else is just as for LaTeX. 2994 (tex-font-lock-syntactic-face-function state) 2995 font-lock-doc-face)) 2996 2997(eval-when-compile 2998 (defconst doctex-syntax-propertize-rules 2999 (syntax-propertize-precompile-rules 3000 latex-syntax-propertize-rules 3001 ;; For DocTeX comment-in-doc. 3002 ("\\(\\^\\)\\^A" (1 (doctex-font-lock-^^A)))))) 3003 3004(defvar doctex-font-lock-keywords 3005 (append tex-font-lock-keywords 3006 '(("^%<[^>]*>" (0 font-lock-preprocessor-face t))))) 3007 3008;;;###autoload 3009(define-derived-mode doctex-mode latex-mode "DocTeX" 3010 "Major mode to edit DocTeX files." 3011 (setq font-lock-defaults 3012 (cons (append (car font-lock-defaults) '(doctex-font-lock-keywords)) 3013 (mapcar 3014 (lambda (x) 3015 (pcase (car-safe x) 3016 ('font-lock-syntactic-face-function 3017 (cons (car x) #'doctex-font-lock-syntactic-face-function)) 3018 (_ x))) 3019 (cdr font-lock-defaults)))) 3020 (setq-local syntax-propertize-function 3021 (syntax-propertize-rules doctex-syntax-propertize-rules))) 3022 3023;;; Prettify Symbols Support 3024 3025(defvar tex--prettify-symbols-alist 3026 '( ;; Lowercase Greek letters. 3027 ("\\alpha" . ?α) 3028 ("\\beta" . ?β) 3029 ("\\gamma" . ?γ) 3030 ("\\delta" . ?δ) 3031 ("\\epsilon" . ?ϵ) 3032 ("\\zeta" . ?ζ) 3033 ("\\eta" . ?η) 3034 ("\\theta" . ?θ) 3035 ("\\iota" . ?ι) 3036 ("\\kappa" . ?κ) 3037 ("\\lambda" . ?λ) 3038 ("\\mu" . ?μ) 3039 ("\\nu" . ?ν) 3040 ("\\xi" . ?ξ) 3041 ;; There is no \omicron because it looks like a latin o. 3042 ("\\pi" . ?π) 3043 ("\\rho" . ?ρ) 3044 ("\\sigma" . ?σ) 3045 ("\\tau" . ?τ) 3046 ("\\upsilon" . ?υ) 3047 ("\\phi" . ?ϕ) 3048 ("\\chi" . ?χ) 3049 ("\\psi" . ?ψ) 3050 ("\\omega" . ?ω) 3051 ;; Uppercase Greek letters. 3052 ("\\Gamma" . ?Γ) 3053 ("\\Delta" . ?Δ) 3054 ("\\Lambda" . ?Λ) 3055 ("\\Phi" . ?Φ) 3056 ("\\Pi" . ?Π) 3057 ("\\Psi" . ?Ψ) 3058 ("\\Sigma" . ?Σ) 3059 ("\\Theta" . ?Θ) 3060 ("\\Upsilon" . ?Υ) 3061 ("\\Xi" . ?Ξ) 3062 ("\\Omega" . ?Ω) 3063 3064 ;; Other math symbols (taken from leim/quail/latin-ltx.el). 3065 ("\\Box" . ?□) 3066 ("\\Bumpeq" . ?≎) 3067 ("\\Cap" . ?⋒) 3068 ("\\Cup" . ?⋓) 3069 ("\\Diamond" . ?◇) 3070 ("\\Downarrow" . ?⇓) 3071 ("\\H{o}" . ?ő) 3072 ("\\Im" . ?ℑ) 3073 ("\\Join" . ?⋈) 3074 ("\\Leftarrow" . ?⇐) 3075 ("\\Leftrightarrow" . ?⇔) 3076 ("\\Ll" . ?⋘) 3077 ("\\Lleftarrow" . ?⇚) 3078 ("\\Longleftarrow" . ?⇐) 3079 ("\\Longleftrightarrow" . ?⇔) 3080 ("\\Longrightarrow" . ?⇒) 3081 ("\\Lsh" . ?↰) 3082 ("\\Re" . ?ℜ) 3083 ("\\Rightarrow" . ?⇒) 3084 ("\\Rrightarrow" . ?⇛) 3085 ("\\Rsh" . ?↱) 3086 ("\\Subset" . ?⋐) 3087 ("\\Supset" . ?⋑) 3088 ("\\Uparrow" . ?⇑) 3089 ("\\Updownarrow" . ?⇕) 3090 ("\\Vdash" . ?⊩) 3091 ("\\Vert" . ?‖) 3092 ("\\Vvdash" . ?⊪) 3093 ("\\aleph" . ?ℵ) 3094 ("\\amalg" . ?∐) 3095 ("\\angle" . ?∠) 3096 ("\\approx" . ?≈) 3097 ("\\approxeq" . ?≊) 3098 ("\\ast" . ?∗) 3099 ("\\asymp" . ?≍) 3100 ("\\backcong" . ?≌) 3101 ("\\backepsilon" . ?∍) 3102 ("\\backprime" . ?‵) 3103 ("\\backsim" . ?∽) 3104 ("\\backsimeq" . ?⋍) 3105 ("\\backslash" . ?\\) 3106 ("\\barwedge" . ?⊼) 3107 ("\\because" . ?∵) 3108 ("\\beth" . ?ℶ) 3109 ("\\between" . ?≬) 3110 ("\\bigcap" . ?⋂) 3111 ("\\bigcirc" . ?◯) 3112 ("\\bigcup" . ?⋃) 3113 ("\\bigstar" . ?★) 3114 ("\\bigtriangledown" . ?▽) 3115 ("\\bigtriangleup" . ?△) 3116 ("\\bigvee" . ?⋁) 3117 ("\\bigwedge" . ?⋀) 3118 ("\\blacklozenge" . ?✦) 3119 ("\\blacksquare" . ?▪) 3120 ("\\blacktriangle" . ?▴) 3121 ("\\blacktriangledown" . ?▾) 3122 ("\\blacktriangleleft" . ?◂) 3123 ("\\blacktriangleright" . ?▸) 3124 ("\\bot" . ?⊥) 3125 ("\\bowtie" . ?⋈) 3126 ("\\boxminus" . ?⊟) 3127 ("\\boxplus" . ?⊞) 3128 ("\\boxtimes" . ?⊠) 3129 ("\\bullet" . ?•) 3130 ("\\bumpeq" . ?≏) 3131 ("\\cap" . ?∩) 3132 ("\\cdots" . ?⋯) 3133 ("\\centerdot" . ?·) 3134 ("\\checkmark" . ?✓) 3135 ("\\chi" . ?χ) 3136 ("\\cdot" . ?⋅) 3137 ("\\cdots" . ?⋯) 3138 ("\\circ" . ?∘) 3139 ("\\circeq" . ?≗) 3140 ("\\circlearrowleft" . ?↺) 3141 ("\\circlearrowright" . ?↻) 3142 ("\\circledR" . ?®) 3143 ("\\circledS" . ?Ⓢ) 3144 ("\\circledast" . ?⊛) 3145 ("\\circledcirc" . ?⊚) 3146 ("\\circleddash" . ?⊝) 3147 ("\\clubsuit" . ?♣) 3148 ("\\coloneq" . ?≔) 3149 ("\\complement" . ?∁) 3150 ("\\cong" . ?≅) 3151 ("\\coprod" . ?∐) 3152 ("\\cup" . ?∪) 3153 ("\\curlyeqprec" . ?⋞) 3154 ("\\curlyeqsucc" . ?⋟) 3155 ("\\curlypreceq" . ?≼) 3156 ("\\curlyvee" . ?⋎) 3157 ("\\curlywedge" . ?⋏) 3158 ("\\curvearrowleft" . ?↶) 3159 ("\\curvearrowright" . ?↷) 3160 ("\\dag" . ?†) 3161 ("\\dagger" . ?†) 3162 ("\\daleth" . ?ℸ) 3163 ("\\dashv" . ?⊣) 3164 ("\\ddag" . ?‡) 3165 ("\\ddagger" . ?‡) 3166 ("\\ddots" . ?⋱) 3167 ("\\diamond" . ?⋄) 3168 ("\\diamondsuit" . ?♢) 3169 ("\\divideontimes" . ?⋇) 3170 ("\\doteq" . ?≐) 3171 ("\\doteqdot" . ?≑) 3172 ("\\dotplus" . ?∔) 3173 ("\\dotsquare" . ?⊡) 3174 ("\\downarrow" . ?↓) 3175 ("\\downdownarrows" . ?⇊) 3176 ("\\downleftharpoon" . ?⇃) 3177 ("\\downrightharpoon" . ?⇂) 3178 ("\\ell" . ?ℓ) 3179 ("\\emptyset" . ?∅) 3180 ("\\eqcirc" . ?≖) 3181 ("\\eqcolon" . ?≕) 3182 ("\\eqslantgtr" . ?⋝) 3183 ("\\eqslantless" . ?⋜) 3184 ("\\equiv" . ?≡) 3185 ("\\exists" . ?∃) 3186 ("\\fallingdotseq" . ?≒) 3187 ("\\flat" . ?♭) 3188 ("\\forall" . ?∀) 3189 ("\\frown" . ?⌢) 3190 ("\\ge" . ?≥) 3191 ("\\geq" . ?≥) 3192 ("\\geqq" . ?≧) 3193 ("\\geqslant" . ?≥) 3194 ("\\gets" . ?←) 3195 ("\\gg" . ?≫) 3196 ("\\ggg" . ?⋙) 3197 ("\\gimel" . ?ℷ) 3198 ("\\gnapprox" . ?⋧) 3199 ("\\gneq" . ?≩) 3200 ("\\gneqq" . ?≩) 3201 ("\\gnsim" . ?⋧) 3202 ("\\gtrapprox" . ?≳) 3203 ("\\gtrdot" . ?⋗) 3204 ("\\gtreqless" . ?⋛) 3205 ("\\gtreqqless" . ?⋛) 3206 ("\\gtrless" . ?≷) 3207 ("\\gtrsim" . ?≳) 3208 ("\\gvertneqq" . ?≩) 3209 ("\\hbar" . ?ℏ) 3210 ("\\heartsuit" . ?♥) 3211 ("\\hookleftarrow" . ?↩) 3212 ("\\hookrightarrow" . ?↪) 3213 ("\\iff" . ?⇔) 3214 ("\\imath" . ?ı) 3215 ("\\in" . ?∈) 3216 ("\\infty" . ?∞) 3217 ("\\int" . ?∫) 3218 ("\\intercal" . ?⊺) 3219 ("\\langle" . 10216) ; Literal ?⟨ breaks indentation. 3220 ("\\lbrace" . ?{) 3221 ("\\lbrack" . ?\[) 3222 ("\\lceil" . ?⌈) 3223 ("\\ldots" . ?…) 3224 ("\\le" . ?≤) 3225 ("\\leadsto" . ?↝) 3226 ("\\leftarrow" . ?←) 3227 ("\\leftarrowtail" . ?↢) 3228 ("\\leftharpoondown" . ?↽) 3229 ("\\leftharpoonup" . ?↼) 3230 ("\\leftleftarrows" . ?⇇) 3231 ;; ("\\leftparengtr" ?〈), see bug#12948. 3232 ("\\leftrightarrow" . ?↔) 3233 ("\\leftrightarrows" . ?⇆) 3234 ("\\leftrightharpoons" . ?⇋) 3235 ("\\leftrightsquigarrow" . ?↭) 3236 ("\\leftthreetimes" . ?⋋) 3237 ("\\leq" . ?≤) 3238 ("\\leqq" . ?≦) 3239 ("\\leqslant" . ?≤) 3240 ("\\lessapprox" . ?≲) 3241 ("\\lessdot" . ?⋖) 3242 ("\\lesseqgtr" . ?⋚) 3243 ("\\lesseqqgtr" . ?⋚) 3244 ("\\lessgtr" . ?≶) 3245 ("\\lesssim" . ?≲) 3246 ("\\lfloor" . ?⌊) 3247 ("\\lhd" . ?◁) 3248 ("\\rhd" . ?▷) 3249 ("\\ll" . ?≪) 3250 ("\\llcorner" . ?⌞) 3251 ("\\lnapprox" . ?⋦) 3252 ("\\lneq" . ?≨) 3253 ("\\lneqq" . ?≨) 3254 ("\\lnsim" . ?⋦) 3255 ("\\longleftarrow" . ?←) 3256 ("\\longleftrightarrow" . ?↔) 3257 ("\\longmapsto" . ?↦) 3258 ("\\longrightarrow" . ?→) 3259 ("\\looparrowleft" . ?↫) 3260 ("\\looparrowright" . ?↬) 3261 ("\\lozenge" . ?✧) 3262 ("\\lq" . ?‘) 3263 ("\\lrcorner" . ?⌟) 3264 ("\\ltimes" . ?⋉) 3265 ("\\lvertneqq" . ?≨) 3266 ("\\maltese" . ?✠) 3267 ("\\mapsto" . ?↦) 3268 ("\\measuredangle" . ?∡) 3269 ("\\mho" . ?℧) 3270 ("\\mid" . ?∣) 3271 ("\\models" . ?⊧) 3272 ("\\mp" . ?∓) 3273 ("\\multimap" . ?⊸) 3274 ("\\nLeftarrow" . ?⇍) 3275 ("\\nLeftrightarrow" . ?⇎) 3276 ("\\nRightarrow" . ?⇏) 3277 ("\\nVDash" . ?⊯) 3278 ("\\nVdash" . ?⊮) 3279 ("\\nabla" . ?∇) 3280 ("\\napprox" . ?≉) 3281 ("\\natural" . ?♮) 3282 ("\\ncong" . ?≇) 3283 ("\\ne" . ?≠) 3284 ("\\nearrow" . ?↗) 3285 ("\\neg" . ?¬) 3286 ("\\neq" . ?≠) 3287 ("\\nequiv" . ?≢) 3288 ("\\newline" . ? ) 3289 ("\\nexists" . ?∄) 3290 ("\\ngeq" . ?≱) 3291 ("\\ngeqq" . ?≱) 3292 ("\\ngeqslant" . ?≱) 3293 ("\\ngtr" . ?≯) 3294 ("\\ni" . ?∋) 3295 ("\\nleftarrow" . ?↚) 3296 ("\\nleftrightarrow" . ?↮) 3297 ("\\nleq" . ?≰) 3298 ("\\nleqq" . ?≰) 3299 ("\\nleqslant" . ?≰) 3300 ("\\nless" . ?≮) 3301 ("\\nmid" . ?∤) 3302 ;; ("\\not" ?̸) ;FIXME: conflict with "NOT SIGN" ¬. 3303 ("\\notin" . ?∉) 3304 ("\\nparallel" . ?∦) 3305 ("\\nprec" . ?⊀) 3306 ("\\npreceq" . ?⋠) 3307 ("\\nrightarrow" . ?↛) 3308 ("\\nshortmid" . ?∤) 3309 ("\\nshortparallel" . ?∦) 3310 ("\\nsim" . ?≁) 3311 ("\\nsimeq" . ?≄) 3312 ("\\nsubset" . ?⊄) 3313 ("\\nsubseteq" . ?⊈) 3314 ("\\nsubseteqq" . ?⊈) 3315 ("\\nsucc" . ?⊁) 3316 ("\\nsucceq" . ?⋡) 3317 ("\\nsupset" . ?⊅) 3318 ("\\nsupseteq" . ?⊉) 3319 ("\\nsupseteqq" . ?⊉) 3320 ("\\ntriangleleft" . ?⋪) 3321 ("\\ntrianglelefteq" . ?⋬) 3322 ("\\ntriangleright" . ?⋫) 3323 ("\\ntrianglerighteq" . ?⋭) 3324 ("\\nvDash" . ?⊭) 3325 ("\\nvdash" . ?⊬) 3326 ("\\nwarrow" . ?↖) 3327 ("\\odot" . ?⊙) 3328 ("\\oint" . ?∮) 3329 ("\\ominus" . ?⊖) 3330 ("\\oplus" . ?⊕) 3331 ("\\oslash" . ?⊘) 3332 ("\\otimes" . ?⊗) 3333 ("\\par" . ? ) 3334 ("\\parallel" . ?∥) 3335 ("\\partial" . ?∂) 3336 ("\\perp" . ?⊥) 3337 ("\\pitchfork" . ?⋔) 3338 ("\\prec" . ?≺) 3339 ("\\precapprox" . ?≾) 3340 ("\\preceq" . ?≼) 3341 ("\\precnapprox" . ?⋨) 3342 ("\\precnsim" . ?⋨) 3343 ("\\precsim" . ?≾) 3344 ("\\prime" . ?′) 3345 ("\\prod" . ?∏) 3346 ("\\propto" . ?∝) 3347 ("\\qed" . ?∎) 3348 ("\\qquad" . ?⧢) 3349 ("\\quad" . ?␣) 3350 ("\\rangle" . 10217) ; Literal ?⟩ breaks indentation. 3351 ("\\rbrace" . ?}) 3352 ("\\rbrack" . ?\]) 3353 ("\\rceil" . ?⌉) 3354 ("\\rfloor" . ?⌋) 3355 ("\\rightarrow" . ?→) 3356 ("\\rightarrowtail" . ?↣) 3357 ("\\rightharpoondown" . ?⇁) 3358 ("\\rightharpoonup" . ?⇀) 3359 ("\\rightleftarrows" . ?⇄) 3360 ("\\rightleftharpoons" . ?⇌) 3361 ;; ("\\rightparengtr" ?⦔) ;; Was ?〉, see bug#12948. 3362 ("\\rightrightarrows" . ?⇉) 3363 ("\\rightthreetimes" . ?⋌) 3364 ("\\risingdotseq" . ?≓) 3365 ("\\rtimes" . ?⋊) 3366 ("\\times" . ?×) 3367 ("\\sbs" . ?﹨) 3368 ("\\searrow" . ?↘) 3369 ("\\setminus" . ?∖) 3370 ("\\sharp" . ?♯) 3371 ("\\shortmid" . ?∣) 3372 ("\\shortparallel" . ?∥) 3373 ("\\sim" . ?∼) 3374 ("\\simeq" . ?≃) 3375 ("\\smallamalg" . ?∐) 3376 ("\\smallsetminus" . ?∖) 3377 ("\\smallsmile" . ?⌣) 3378 ("\\smile" . ?⌣) 3379 ("\\spadesuit" . ?♠) 3380 ("\\sphericalangle" . ?∢) 3381 ("\\sqcap" . ?⊓) 3382 ("\\sqcup" . ?⊔) 3383 ("\\sqsubset" . ?⊏) 3384 ("\\sqsubseteq" . ?⊑) 3385 ("\\sqsupset" . ?⊐) 3386 ("\\sqsupseteq" . ?⊒) 3387 ("\\square" . ?□) 3388 ("\\squigarrowright" . ?⇝) 3389 ("\\star" . ?⋆) 3390 ("\\straightphi" . ?φ) 3391 ("\\subset" . ?⊂) 3392 ("\\subseteq" . ?⊆) 3393 ("\\subseteqq" . ?⊆) 3394 ("\\subsetneq" . ?⊊) 3395 ("\\subsetneqq" . ?⊊) 3396 ("\\succ" . ?≻) 3397 ("\\succapprox" . ?≿) 3398 ("\\succcurlyeq" . ?≽) 3399 ("\\succeq" . ?≽) 3400 ("\\succnapprox" . ?⋩) 3401 ("\\succnsim" . ?⋩) 3402 ("\\succsim" . ?≿) 3403 ("\\sum" . ?∑) 3404 ("\\supset" . ?⊃) 3405 ("\\supseteq" . ?⊇) 3406 ("\\supseteqq" . ?⊇) 3407 ("\\supsetneq" . ?⊋) 3408 ("\\supsetneqq" . ?⊋) 3409 ("\\surd" . ?√) 3410 ("\\swarrow" . ?↙) 3411 ("\\therefore" . ?∴) 3412 ("\\thickapprox" . ?≈) 3413 ("\\thicksim" . ?∼) 3414 ("\\to" . ?→) 3415 ("\\top" . ?⊤) 3416 ("\\triangle" . ?▵) 3417 ("\\triangledown" . ?▿) 3418 ("\\triangleleft" . ?◃) 3419 ("\\trianglelefteq" . ?⊴) 3420 ("\\triangleq" . ?≜) 3421 ("\\triangleright" . ?▹) 3422 ("\\trianglerighteq" . ?⊵) 3423 ("\\twoheadleftarrow" . ?↞) 3424 ("\\twoheadrightarrow" . ?↠) 3425 ("\\ulcorner" . ?⌜) 3426 ("\\uparrow" . ?↑) 3427 ("\\updownarrow" . ?↕) 3428 ("\\upleftharpoon" . ?↿) 3429 ("\\uplus" . ?⊎) 3430 ("\\uprightharpoon" . ?↾) 3431 ("\\upuparrows" . ?⇈) 3432 ("\\urcorner" . ?⌝) 3433 ("\\u{i}" . ?ĭ) 3434 ("\\vDash" . ?⊨) 3435 ("\\varepsilon" . ?ε) 3436 ("\\varphi" . ?φ) 3437 ("\\varprime" . ?′) 3438 ("\\varpropto" . ?∝) 3439 ("\\varrho" . ?ϱ) 3440 ("\\varsigma" ?ς) 3441 ("\\vartriangleleft" . ?⊲) 3442 ("\\vartriangleright" . ?⊳) 3443 ("\\vdash" . ?⊢) 3444 ("\\vdots" . ?⋮) 3445 ("\\vee" . ?∨) 3446 ("\\veebar" . ?⊻) 3447 ("\\vert" . ?|) 3448 ("\\wedge" . ?∧) 3449 ("\\wp" . ?℘) 3450 ("\\wr" . ?≀) 3451 ("\\Bbb{N}" . ?ℕ) ; AMS commands for blackboard bold 3452 ("\\Bbb{P}" . ?ℙ) ; Also sometimes \mathbb. 3453 ("\\Bbb{Q}" . ?ℚ) 3454 ("\\Bbb{R}" . ?ℝ) 3455 ("\\Bbb{Z}" . ?ℤ) 3456 ("--" . ?–) 3457 ("---" . ?—) 3458 ("\\ordfeminine" . ?ª) 3459 ("\\ordmasculine" . ?º) 3460 ("\\lambdabar" . ?ƛ) 3461 ("\\celsius" . ?℃) 3462 ("\\textmu" . ?µ) 3463 ("\\textfractionsolidus" . ?⁄) 3464 ("\\textbigcircle" . ?⃝) 3465 ("\\textmusicalnote" . ?♪) 3466 ("\\textdied" . ?✝) 3467 ("\\textcolonmonetary" . ?₡) 3468 ("\\textwon" . ?₩) 3469 ("\\textnaira" . ?₦) 3470 ("\\textpeso" . ?₱) 3471 ("\\textlira" . ?₤) 3472 ("\\textrecipe" . ?℞) 3473 ("\\textinterrobang" . ?‽) 3474 ("\\textpertenthousand" . ?‱) 3475 ("\\textbaht" . ?฿) 3476 ("\\textnumero" . ?№) 3477 ("\\textdiscount" . ?⁒) 3478 ("\\textestimated" . ?℮) 3479 ("\\textopenbullet" . ?◦) 3480 ("\\textlquill" . 8261) ; Literal ?⁅ breaks indentation. 3481 ("\\textrquill" . 8262) ; Literal ?⁆ breaks indentation. 3482 ("\\textcircledP" . ?℗) 3483 ("\\textreferencemark" . ?※)) 3484 "A `prettify-symbols-alist' usable for (La)TeX modes.") 3485 3486(defun tex--prettify-symbols-compose-p (_start end _match) 3487 (or 3488 ;; If the matched symbol doesn't end in a word character, then we 3489 ;; simply allow composition. The symbol is probably something like 3490 ;; \|, \(, etc. 3491 (not (eq ?w (char-syntax (char-before end)))) 3492 ;; Else we look at what follows the match in order to decide. 3493 (let* ((after-char (char-after end)) 3494 (after-syntax (char-syntax after-char))) 3495 (not (or 3496 ;; Don't compose \alpha@foo. 3497 (eq after-char ?@) 3498 ;; The \alpha in \alpha2 or \alpha-\beta may be composed but 3499 ;; of course \alphax may not. 3500 (and (eq after-syntax ?w) 3501 (not (memq after-char 3502 '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?+ ?- ?' ?\")))) 3503 ;; Don't compose inside verbatim blocks. 3504 (eq 2 (nth 7 (syntax-ppss)))))))) 3505 3506 3507;;; Flymake support 3508 3509(defvar-local tex-chktex--process nil) 3510 3511(defun tex-chktex-command () 3512 "Return a list of command arguments for invoking ChkTeX." 3513 `(,tex-chktex-program ,@tex-chktex-extra-flags 3514 "--quiet" "--verbosity=0" "--inputfiles")) 3515 3516(defun tex-chktex (report-fn &rest _args) 3517 "Flymake backend for linting TeX buffers with ChkTeX." 3518 (unless (executable-find tex-chktex-program) 3519 (error "Cannot find a suitable TeX checker")) 3520 (when (process-live-p tex-chktex--process) 3521 (kill-process tex-chktex--process)) 3522 (let ((source (current-buffer)) 3523 (re "^stdin:\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\):\\(.*\\)$")) 3524 (save-restriction 3525 (widen) 3526 (setq tex-chktex--process 3527 (make-process 3528 :name "tex-chktex" 3529 :buffer (generate-new-buffer "*tex-chktex*") 3530 :command (tex-chktex-command) 3531 :noquery t :connection-type 'pipe 3532 :sentinel 3533 (lambda (process _event) 3534 (when (eq (process-status process) 'exit) 3535 (unwind-protect 3536 (when (eq process 3537 (with-current-buffer source tex-chktex--process)) 3538 (with-current-buffer (process-buffer process) 3539 (goto-char (point-min)) 3540 (cl-loop 3541 while (search-forward-regexp re nil t) 3542 for msg = (match-string 4) 3543 for line = (string-to-number (match-string 1)) 3544 for col = (string-to-number (match-string 2)) 3545 for (beg . end) = (flymake-diag-region source line col) 3546 collect (flymake-make-diagnostic source beg end :warning msg) 3547 into diags 3548 finally (funcall report-fn diags)))) 3549 (kill-buffer (process-buffer process))))))) 3550 (process-send-region tex-chktex--process (point-min) (point-max)) 3551 (process-send-eof tex-chktex--process)))) 3552 3553(run-hooks 'tex-mode-load-hook) 3554 3555(provide 'tex-mode) 3556 3557;;; tex-mode.el ends here 3558