diff options
Diffstat (limited to 'elpa/auctex-13.1.3/tex.el')
-rw-r--r-- | elpa/auctex-13.1.3/tex.el | 10227 |
1 files changed, 0 insertions, 10227 deletions
diff --git a/elpa/auctex-13.1.3/tex.el b/elpa/auctex-13.1.3/tex.el deleted file mode 100644 index 747753b..0000000 --- a/elpa/auctex-13.1.3/tex.el +++ /dev/null @@ -1,10227 +0,0 @@ -;;; tex.el --- Support for TeX documents. -*- lexical-binding: t; -*- - -;; Copyright (C) 1985-2022 Free Software Foundation, Inc. - -;; Maintainer: auctex-devel@gnu.org -;; Keywords: tex - -;; This file is part of AUCTeX. - -;; AUCTeX is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. - -;; AUCTeX is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with AUCTeX; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -;; 02110-1301, USA. - -;;; Commentary: - -;; This file provides basic functions used by the AUCTeX modes. - -;;; Code: - -(when (< emacs-major-version 25) - (error "AUCTeX requires Emacs 25.1 or later")) - -(require 'custom) -(require 'tex-site) -(eval-when-compile - (require 'cl-lib)) -(require 'texmathp) -;; Require dbus at compile time to get macro definition of -;; `dbus-ignore-errors'. -(eval-when-compile (require 'dbus)) - -;; Silence the compiler for functions: -(declare-function dbus-get-unique-name "ext:dbusbind.c" - (bus)) -(declare-function dbus-ping "ext:dbus" - (bus service &optional timeout)) -(declare-function dbus-introspect-get-method "ext:dbus" - (bus service path interface method)) -(declare-function dbus-call-method "ext:dbus" - (bus service path interface method &rest args)) -(declare-function dbus-register-signal "ext:dbus" - (bus service path interface signal handler &rest args)) -(declare-function LaTeX-environment-list "latex" - nil) -(declare-function LaTeX-bibliography-list "latex" - nil) -(declare-function comint-exec - (buffer name command startfile switches)) -(declare-function comint-mode - nil) -(declare-function tex--prettify-symbols-compose-p "ext:tex-mode" - (start end match)) -(declare-function gnuserv-start "ext:gnuserv" - (&optional leave-dead) t) - -;; Silence the compiler for variables: -;; tex.el: Variables defined somewhere in this file: -(defvar TeX-PDF-from-DVI) -(defvar TeX-PDF-mode) -(defvar TeX-PDF-mode-parsed) -(defvar TeX-all-extensions) -(defvar TeX-command-default) -(defvar TeX-default-extension) -(defvar TeX-esc) -(defvar TeX-interactive-mode) -(defvar TeX-macro-global) -(defvar TeX-mode-map) -(defvar TeX-mode-p) -(defvar TeX-output-extension) -(defvar TeX-source-correlate-mode) -(defvar TeX-source-specials-places) -(defvar TeX-source-specials-tex-flags) -(defvar TeX-synctex-tex-flags) -(defvar TeX-current-process-region-p) -(defvar TeX-region) -(defvar TeX-region-orig-buffer) -;; Variables defined in other AUCTeX libraries: -;; latex.el: -(defvar LaTeX-default-verb-delimiter) -(defvar LaTeX-optcl) -(defvar LaTeX-optop) -(defvar LaTeX-largest-level) -(defvar LaTeX-section-list) -(defvar TeX-output-dir) -;; tex-ispell.el -(defvar TeX-ispell-verb-delimiters) -;; Others: -(defvar tex--prettify-symbols-alist) ; tex-mode.el -(defvar Info-file-list-for-emacs) ; info.el -(defvar ispell-parser) ; ispell.el -(defvar compilation-error-regexp-alist) ; compile.el - -(defgroup TeX-file nil - "Files used by AUCTeX." - :group 'AUCTeX) - -(defgroup TeX-command nil - "Calling external commands from AUCTeX." - :group 'AUCTeX) - -(defgroup LaTeX nil - "LaTeX support in AUCTeX." - :tag "LaTeX" - :group 'AUCTeX - :prefix "LaTeX-") - -(defgroup TeX-misc nil - "Various AUCTeX settings." - :group 'AUCTeX) - -;;; Site Customization -;; -;; The following variables are likely to need to be changed for your -;; site. You should do this with customize. - -(defcustom TeX-command "tex" - "Command to run plain TeX." - :group 'TeX-command - :type 'string) - -(defcustom TeX-Omega-command "omega" - "Command to run plain TeX on Omega." - :group 'TeX-command - :type '(choice (const :tag "Aleph" "aleph") - (const :tag "Omega" "omega") - (string :tag "Other command"))) - -(defcustom LaTeX-command "latex" - "Command to run LaTeX." - :group 'TeX-command - :type 'string) - -(defcustom LaTeX-Omega-command "lambda" - "Command to run LaTeX on Omega." - :group 'TeX-command - :type '(choice (const :tag "Lamed" "lamed") - (const :tag "Lambda" "lambda") - (string :tag "Other command"))) - -(defcustom TeX-file-line-error t - "Whether to have TeX produce file:line:error style error messages." - :group 'TeX-command - :type 'boolean) - -(defcustom ConTeXt-engine nil - "Engine to use for --engine in the texexec command. -If nil, none is specified." - :group 'TeX-command - :type '(choice (const :tag "Unspecified" nil) - string)) - -(defcustom ConTeXt-Omega-engine TeX-Omega-command - "Engine to use for --engine in the texexec command in Omega mode. -If nil, none is specified." - :group 'TeX-command - :type '(choice (const :tag "Unspecified" nil) - string)) -;; At least in TeXLive 2009 ConTeXt does not support an omega option anymore. -(make-obsolete-variable 'ConTeXt-Omega-engine 'TeX-engine-alist "11.86") - -(defcustom TeX-mode-hook nil - "A hook run in TeX mode buffers." - :type 'hook - :group 'TeX-misc) - -;; This is the major configuration variable. Most sites will only need to -;; change the second string in each entry, which is the name of a command to -;; send to the shell. If you use other formatters like AMSLaTeX or AMSTeX, you -;; can add those to the list. See `TeX-expand-list' and -;; `TeX-expand-list-builtin' for a description of the % escapes - -(defcustom TeX-command-list - '(("TeX" "%(PDF)%(tex) %(file-line-error) %`%(extraopts) %S%(PDFout)%(mode)%' %(output-dir) %t" - TeX-run-TeX nil - (plain-tex-mode ams-tex-mode texinfo-mode) :help "Run plain TeX") - ("LaTeX" "%`%l%(mode)%' %T" - TeX-run-TeX nil - (latex-mode doctex-mode) :help "Run LaTeX") - ;; Not part of standard TeX. - ("Makeinfo" "makeinfo %(extraopts) %(o-dir) %t" TeX-run-compile nil - (texinfo-mode) :help "Run Makeinfo with Info output") - ("Makeinfo HTML" "makeinfo %(extraopts) %(o-dir) --html %t" TeX-run-compile nil - (texinfo-mode) :help "Run Makeinfo with HTML output") - ("AmSTeX" "amstex %(PDFout) %`%(extraopts) %S%(mode)%' %(output-dir) %t" - TeX-run-TeX nil (ams-tex-mode) :help "Run AMSTeX") - ;; support for ConTeXt --pg - ;; first version of ConTeXt to support nonstopmode: 2003.2.10 - ("ConTeXt" "%(cntxcom) --once --texutil %(extraopts) %(execopts)%t" - TeX-run-TeX nil (context-mode) :help "Run ConTeXt once") - ("ConTeXt Full" "%(cntxcom) %(extraopts) %(execopts)%t" - TeX-run-TeX nil - (context-mode) :help "Run ConTeXt until completion") - ("BibTeX" "bibtex %(O?aux)" TeX-run-BibTeX nil - (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode - context-mode) - :help "Run BibTeX") - ("Biber" "biber %(output-dir) %s" TeX-run-Biber nil - (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) - :help "Run Biber") - ;; Not part of standard TeX. - ;; It seems that texindex doesn't support "--output-dir" option. - ("Texindex" "texindex %s.??" TeX-run-command nil - (texinfo-mode) :help "Run Texindex") - ;; TODO: - ;; 1. Supply "--dvipdf" option if `TeX-PDF-mode' and - ;; `TeX-PDF-from-DVI' are non-nil. - ;; 2. Supply "--build-dir=DIR" option when `TeX-output-dir' is - ;; non-nil. - ("Texi2dvi" "%(PDF)texi2dvi %t" TeX-run-command nil - (texinfo-mode) :help "Run Texi2dvi or Texi2pdf") - ("View" "%V" TeX-run-discard-or-function t t :help "Run Viewer") - ("Print" "%p" TeX-run-command t t :help "Print the file") - ("Queue" "%q" TeX-run-background nil t :help "View the printer queue" - :visible TeX-queue-command) - ("File" "%(o?)dvips %d -o %f " TeX-run-dvips t - (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) - :help "Generate PostScript file") - ("Dvips" "%(o?)dvips %d -o %f " TeX-run-dvips nil - (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) - :help "Convert DVI file to PostScript") - ("Dvipdfmx" "dvipdfmx -o %(O?pdf) %d" TeX-run-dvipdfmx nil - (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) - :help "Convert DVI file to PDF with dvipdfmx") - ("Ps2pdf" "ps2pdf %f %(O?pdf)" TeX-run-ps2pdf nil - (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) - :help "Convert PostScript file to PDF") - ("Glossaries" "makeglossaries %(d-dir) %s" TeX-run-command nil - (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) - :help "Run makeglossaries to create glossary file") - ("Index" "makeindex %(O?idx)" TeX-run-index nil - (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) - :help "Run makeindex to create index file") - ("upMendex" "upmendex %(O?idx)" TeX-run-index t - (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) - :help "Run upmendex to create index file") - ("Xindy" "texindy %s" TeX-run-command nil - (plain-tex-mode latex-mode doctex-mode ams-tex-mode texinfo-mode) - :help "Run xindy to create index file") - ("Check" "lacheck %s" TeX-run-compile nil (latex-mode) - :help "Check LaTeX file for correctness") - ("ChkTeX" "chktex -v6 %s" TeX-run-compile nil (latex-mode) - :help "Check LaTeX file for common mistakes") - ("Spell" "(TeX-ispell-document \"\")" TeX-run-function nil t - :help "Spell-check the document") - ("Clean" "TeX-clean" TeX-run-function nil t - :help "Delete generated intermediate files") - ("Clean All" "(TeX-clean t)" TeX-run-function nil t - :help "Delete generated intermediate and output files") - ("Other" "" TeX-run-command t t :help "Run an arbitrary command")) - "List of commands to execute on the current document. - -Each element is a list, whose first element is the name of the command -as it will be presented to the user. - -The second element is the string handed to the shell after being -expanded. The expansion is done using the information found in -`TeX-expand-list'. - -The third element is the function which actually start the process. -Several such hooks have been defined: - -TeX-run-command: Start up the process and show the output in a -separate buffer. Check that there is not two commands running for the -same file. Return the process object. - -TeX-run-format: As `TeX-run-command', but assume the output is created -by a TeX macro package. Return the process object. - -TeX-run-TeX: For TeX output. - -TeX-run-interactive: Run TeX or LaTeX interactively. - -TeX-run-BibTeX: For BibTeX output. - -TeX-run-Biber: For Biber output. - -TeX-run-compile: Use `compile' to run the process. - -TeX-run-shell: Use `shell-command' to run the process. - -TeX-run-discard: Start the process in the background, discarding its -output. - -TeX-run-background: Start the process in the background, show output -in other window. - -TeX-run-silent: Start the process in the background. - -TeX-run-discard-foreground: Start the process in the foreground, -discarding its output. - -TeX-run-function: Execute the Lisp function or function call -specified by the string in the second element. Consequently, -this hook does not start a process. - -TeX-run-discard-or-function: If the command is a Lisp function, -execute it as such, otherwise start the command as a process, -discarding its output. - -To create your own hook, define a function taking three arguments: The -name of the command, the command string, and the name of the file to -process. It might be useful to use `TeX-run-command' in order to -create an asynchronous process. - -If the fourth element is non-nil, the user will get a chance to -modify the expanded string. - -The fifth element indicates in which mode(s) the command should be -present in the Command menu. Use t if it should be active in any -mode. If it should only be present in some modes, specify a list with -the respective mode names. - -Any additional elements get just transferred to the respective menu entries." - :group 'TeX-command - :type '(repeat (group :value ("" "" TeX-run-command nil t) - (string :tag "Name") - (string :tag "Command") - (choice :tag "How" - :value TeX-run-command - (function-item TeX-run-command) - (function-item TeX-run-format) - (function-item TeX-run-TeX) - (function-item TeX-run-interactive) - (function-item TeX-run-BibTeX) - (function-item TeX-run-Biber) - (function-item TeX-run-compile) - (function-item TeX-run-shell) - (function-item TeX-run-discard) - (function-item TeX-run-background) - (function-item TeX-run-silent) - (function-item TeX-run-discard-foreground) - (function-item TeX-run-function) - (function-item TeX-run-discard-or-function) - (function :tag "Other")) - (boolean :tag "Prompt") - (choice :tag "Modes" - (const :tag "All" t) - (set (const :tag "Plain TeX" plain-tex-mode) - (const :tag "LaTeX" latex-mode) - (const :tag "DocTeX" doctex-mode) - (const :tag "ConTeXt" context-mode) - (const :tag "Texinfo" texinfo-mode) - (const :tag "AmSTeX" ams-tex-mode))) - (repeat :tag "Menu elements" :inline t sexp)))) - -(defcustom TeX-command-output-list - '( - ; Add the following line if you want to use htlatex (tex4ht) - ; ("\\`htlatex" ("html")) - ) - "List of regexps and file extensions. - -Each element is a list, whose first element is a regular expression to -match against the name of the command that will be used to process the TeX -file. - -The second element is either a string or a list with a string as element. -If it is a string this is the default file extension that will be expected -for output files that are produced by commands that match the first -element. The real file extension will be obtained from the logging output -if possible, defaulting to the given string. -If it is a list, the element of the list will be the fixed extension used -without looking at the logging output. - -If this list does not yield an extension, the default is either \"dvi\" -or \"pdf\", depending on the setting of `TeX-PDF-mode'. -Extensions must be given without the \".\"." - - :group 'TeX-command - :type '(repeat (group (regexp :tag "Command Regexp") - (choice (string :tag "Default Extension") - (group (string :tag "Fixed Extension")))))) - -;; You may want to change the default LaTeX version for your site. -(defcustom LaTeX-version "2e" - "Default LaTeX version. Currently recognized is \"2\" and \"2e\"." - :group 'LaTeX - :type '(radio (const :format "%v\n%h" - :doc "\ -The executable `latex' is LaTeX version 2." - "2") - (const :format "%v\n%h" - :doc "\ -The executable `latex' is LaTeX version 2e." - "2e") - (string :tag "Other"))) - - -;; Use different compilation commands depending on style. -;; Only works if parsing is enabled. - -(defcustom LaTeX-command-style - ;; They have all been combined in LaTeX 2e. - '(("" "%(PDF)%(latex) %(file-line-error) %(extraopts) %(output-dir) %S%(PDFout)")) -"List of style options and LaTeX commands. - -If the first element (a regular expression) matches the name of one of -the style files, any occurrence of the string `%l' in a command in -`TeX-command-list' will be replaced with the second element. The first -match is used, if no match is found the `%l' is replaced with the empty -string." - :group 'TeX-command - :type '(repeat (group :value ("" "") - regexp (string :tag "Style")))) - -;; Printing: If you want to print, TeX-print-command must be non-nil -;; (if it is nil, you'll get a complaint when using the print menu). -;; If you want to view the queue, TeX-queue-command needs to be -;; non-nil (if it is nil, it won't get mentioned in the menu). If -;; TeX-printer-list is nil, nothing else gets asked: the menu entries -;; lead directly to the respective commands. If those commands -;; contain %p, the value of TeX-printer-default gets inserted there, -;; no questions asked. Now if TeX-printer-list is non-nil, you'll -;; always get asked which printer you want to use. You can enter a -;; configured printer from TeX-printer-list, or an unknown one. The -;; respective menus will show all configured printers. Since you can -;; enter unknown printers, the printer name _must_ be set with %p in -;; TeX-print-command. - -(defcustom TeX-print-command - "{ test -e %d && %(o?)dvips -P%p %r %s; } || lpr -P%p %o" - "Command used to print a file. - -First `%p' is expanded to the printer name, then ordinary expansion is -performed as specified in `TeX-expand-list'. If it is nil, -then customization is requested." - :group 'TeX-command - :type '(choice (string :tag "Print command") - (const :tag "No print command customized" nil))) - -(defcustom TeX-queue-command "lpq -P%p" - "Command used to show the status of a printer queue. - -First `%p' is expanded to the printer name, then ordinary expansion is -performed as specified in `TeX-expand-list'. If this is nil, -the printer has no corresponding command." - :group 'TeX-command - :type '(choice (string :tag "Queue check command") - (const :tag "No such command" nil))) - -;; Enter the names of the printers available at your site, or nil if -;; you only have one printer. - -(defcustom TeX-printer-list - '(("Default" - ;; Print to the (unnamed) default printer. If there is a DVI - ;; file print via Dvips. If not, pass the output file (which - ;; should then be a Postscript or PDF file) directly to lpr. - "{ test -e %d && %(o?)dvips -f %r %s | lpr; } || lpr %o" - ;; Show the queue for the (unnamed) default printer. - "lpq")) - "List of available printers. - -The first element of each entry is the printer name. - -The second element is the command used to print to this -printer. It defaults to the value of `TeX-print-command' when nil. - -The third element is the command used to examine the print queue for -this printer. It defaults to the value of `TeX-queue-command' similarly. - -Any occurrence of `%p' in the second or third element is expanded to -the printer name given in the first element, then ordinary expansion -is performed as specified in `TeX-expand-list'. - -If this list is empty, only `TeX-print-command' and `TeX-queue-command' -get consulted." - :group 'TeX-command - :type '(repeat (group (string :tag "Name") - (option (group :inline t - :extra-offset -4 - (choice :tag "Print" - (const :tag "default") - (string :format "%v")) - (option (choice :tag "Queue" - (const :tag "default") - (string - :format "%v")))))))) - -;; The name of the most used printer. - -(defcustom TeX-printer-default (or (getenv "PRINTER") - (and TeX-printer-list - (car (car TeX-printer-list))) - "lp") - "Default printer to use with `TeX-command'." - :group 'TeX-command - :type 'string) - -(defcustom TeX-print-style '(("^landscape$" "-t landscape")) - "List of style options and print options. - -If the first element (a regular expression) matches the name of one of -the style files, any occurrence of the string `%r' in a command in -`TeX-command-list' will be replaced with the second element. The first -match is used, if no match is found the `%r' is replaced with the empty -string." - :group 'TeX-command - :type '(repeat (group regexp (string :tag "Command")))) - -(defcustom TeX-command-extra-options "" - "String with the extra options to be given to the TeX processor." - :type 'string) -(make-variable-buffer-local 'TeX-command-extra-options) - -(defvar TeX-command-text nil - "Dynamically bound by `TeX-command-expand'.") -(defvar TeX-command-pos nil - "Dynamically bound by `TeX-command-expand'.") -(defvar TeX-expand-pos nil - "Dynamically bound by `TeX-command-expand'.") -(defvar TeX-expand-command nil - "Dynamically bound by `TeX-command-expand'.") - -;; This is the list of expansion for the commands in -;; TeX-command-list. Not likely to be changed, but you may e.g. want -;; to handle .ps files. - -(defvar TeX-expand-list-builtin - '(("%q" (lambda () - (TeX-printer-query t))) - ("%V" (lambda () - (TeX-source-correlate-start-server-maybe) - (TeX-view-command-raw))) - ("%r" (lambda () - (TeX-style-check TeX-print-style))) - ("%l" (lambda () - (TeX-style-check LaTeX-command-style))) - ("%(PDF)" (lambda () - (if (and (eq TeX-engine 'default) - (if TeX-PDF-mode - (not (TeX-PDF-from-DVI)) - TeX-DVI-via-PDFTeX)) - "pdf" - ""))) - ("%(PDFout)" (lambda () - (cond ((eq major-mode 'ams-tex-mode) - (if TeX-PDF-mode - " -output-format=pdf" - " -output-format=dvi")) - ((and (eq TeX-engine 'xetex) - (not TeX-PDF-mode)) - " -no-pdf") - ((and (eq TeX-engine 'luatex) - (not TeX-PDF-mode)) - " --output-format=dvi") - ((and (eq TeX-engine 'default) - (not TeX-PDF-mode) - TeX-DVI-via-PDFTeX) - " \"\\pdfoutput=0 \"") - (t "")))) - ("%(mode)" (lambda () - (if TeX-interactive-mode - "" - " -interaction=nonstopmode"))) - ("%(file-line-error)" - (lambda () (if TeX-file-line-error " -file-line-error" ""))) - ("%(o?)" (lambda () (if (eq TeX-engine 'omega) "o" ""))) - ("%(tex)" (lambda () (eval (nth 2 (TeX-engine-in-engine-alist TeX-engine))))) - ("%(latex)" (lambda () (eval (nth 3 (TeX-engine-in-engine-alist TeX-engine))))) - ("%(cntxcom)" ConTeXt-expand-command) - ("%(execopts)" ConTeXt-expand-options) - ("%(extraopts)" (lambda () TeX-command-extra-options)) - ("%(output-dir)" TeX--output-dir-arg "--output-directory=") - ("%(o-dir)" TeX--output-dir-arg "-o ") - ("%(d-dir)" TeX--output-dir-arg "-d ") - ("%S" TeX-source-correlate-expand-options) - ("%dS" TeX-source-specials-view-expand-options) - ("%cS" TeX-source-specials-view-expand-client) - ("%(outpage)" (lambda () - ;; When `TeX-source-correlate-output-page-function' is nil - ;; and we are using synctex, fallback on - ;; `TeX-synctex-output-page'. - (and TeX-source-correlate-mode - (null TeX-source-correlate-output-page-function) - (eq (TeX-source-correlate-method-active) 'synctex) - (setq TeX-source-correlate-output-page-function - #'TeX-synctex-output-page)) - (or (if TeX-source-correlate-output-page-function - (funcall TeX-source-correlate-output-page-function)) - "1"))) - ;; `TeX-active-master-with-quotes' calls either `TeX-master-file' - ;; or `TeX-region-file' returning the master or region file, and - ;; adds suitable quotes for use in shell command line. - ("%s" TeX-active-master-with-quotes nil t) - ("%t" TeX-active-master-with-quotes t t) - ("%(t-filename-only)" TeX-active-master-with-quotes t t nil nil file-name-nondirectory) - ;; If any TeX codes appear in the interval between %` and %', move - ;; all of them after the interval and supplement " \input". The - ;; appearance is marked by leaving the bind to `TeX-command-text' - ;; with the TeX codes. - ;; Rule: - ;; 1. %` and %' must appear in pair. - ;; 2. %` and %' must not appear more than once in one command - ;; line string (including the results of %-expansion). - ;; 3. Each TeX codes between %` and %' must be enclosed in - ;; double quotes and preceded by a space. - ("%`" (lambda nil - (setq TeX-command-pos t TeX-command-text nil) - "")) - (" \"\\" (lambda nil - (if (eq TeX-command-pos t) - (setq TeX-command-pos TeX-expand-pos - TeX-expand-pos (+ 3 TeX-expand-pos)) - (setq TeX-expand-pos (1+ TeX-expand-pos))))) - ("\"" (lambda nil (if (numberp TeX-command-pos) - (setq TeX-command-text - (concat - TeX-command-text - (substring TeX-expand-command - TeX-command-pos - (1+ TeX-expand-pos))) - TeX-expand-command - (concat - (substring TeX-expand-command - 0 - TeX-command-pos) - (substring TeX-expand-command - (1+ TeX-expand-pos))) - TeX-expand-pos TeX-command-pos - TeX-command-pos t) - (setq TeX-expand-pos (1+ TeX-expand-pos))))) - ("%'" (lambda nil - (setq TeX-command-pos nil) - (if (stringp TeX-command-text) - (progn - (setq TeX-expand-pos (+ TeX-expand-pos (length TeX-command-text) 9)) - (concat TeX-command-text " \"\\input\"")) - ""))) - ;; The fourth argument of t directs to supply "\detokenize{}" when - ;; necessary. See doc string and comment of - ;; `TeX-active-master-with-quotes'. - ("%T" TeX-active-master-with-quotes t t nil t) - ("%n" TeX-current-line) - ("%d" TeX-active-master-with-quotes "dvi" t) - ("%f" TeX-active-master-with-quotes "ps" t) - ("%(O?aux)" TeX-active-master-with-quotes "aux" t) - ("%(O?idx)" TeX-active-master-with-quotes "idx" t) - ("%(O?pdf)" TeX-active-master-with-quotes "pdf" t) - ("%o" (lambda nil (TeX-active-master-with-quotes (TeX-output-extension) t))) - ;; for source specials the file name generated for the xdvi - ;; command needs to be relative to the master file, just in - ;; case the file is in a different subdirectory - ("%b" TeX-current-file-name-master-relative) - ;; Okular forward PDF search requires absolute path. - ("%a" (lambda nil (prin1-to-string (expand-file-name (buffer-file-name))))) - ;; the following is for preview-latex. - ("%m" preview-create-subdirectory)) - "List of built-in expansion strings for TeX command names. - -This should not be changed by the user who can use -`TeX-expand-list' variable. The latter variable also contains a -description of the data format. - -Programs should not use these variables directly but the function -`TeX-expand-list'.") - -(defcustom TeX-expand-list nil - "List of expansion strings for TeX command names defined by the user. - -Each entry is a list with two or more elements. The first -element is the string to be expanded. The second element is the -name of a function returning the expanded string when called with -the remaining elements as arguments. -The second element can also be a variable name whose value is -such function. - -Built-in expansions provided in `TeX-expand-list-builtin' can be -overwritten by defining expansions strings with the same -expander. Only \"%p\" expander cannot be overwritten. - -Programs should not use these variables directly but the function -`TeX-expand-list'." - :group 'TeX-command - :type '(repeat (group (string :tag "Key") - (sexp :tag "Expander") - (repeat :inline t - :tag "Arguments" - (sexp :format "%v"))))) - -(defun TeX-expand-list () - "Complete list of expansion strings for TeX command names. - -Concatenate `TeX-expand-list' and `TeX-expand-list-builtin' making -sure \"%p\" is the first entry." - (append - ;; %p must be the first entry, see `TeX-print-command'. - '(("%p" TeX-printer-query)) - TeX-expand-list - TeX-expand-list-builtin)) - -;; This variable used to be defined in tex-buf.el. It is used in -;; `TeX-mode-specific-command-menu-entries' in this file. It is now -;; (June 2021) moved into this file to avoid `void-variable' errors -;; with the "Command" menu if tex-buf.el is not loaded yet for reasons -;; mentioned above. -(defcustom TeX-parse-all-errors t - "Whether to automatically collect all warning and errors after running TeX. - -If t, it makes it possible to use `TeX-previous-error' with TeX -commands." - :group 'TeX-command - :type 'boolean) - -;;; Portability. - -(defmacro TeX--if-macro-fboundp (name then &rest else) - "Execute THEN if macro NAME is bound and ELSE otherwise. -Essentially, - - (TeX--if-macro-fboundp name then else...) - -is equivalent to - - (if (fboundp \\='name) then else...) - -but takes care of byte-compilation issues where the byte-code for -the latter could signal an error if it has been compiled with -emacs 24.1 and is then later run by emacs 24.5." - (declare (indent 2) (debug (symbolp form &rest form))) - (if (fboundp name) ;If macro exists at compile-time, just use it. - then - `(if (fboundp ',name) ;Else, check if it exists at run-time. - (eval ',then) ;If it does, then run the then code. - ,@else))) ;Otherwise, run the else code. - -(require 'easymenu) - -;;; Documentation for Info-goto-emacs-command-node and similar - -(eval-after-load 'info '(dolist (elt '("TeX" "LaTeX" "ConTeXt" "Texinfo" - "docTeX")) - (add-to-list 'Info-file-list-for-emacs - (cons elt "AUCTeX")))) - -(advice-add 'hack-one-local-variable :after #'TeX--call-minor-mode) -(defun TeX--call-minor-mode (var val &rest _) - "Call minor mode function if minor mode variable is found." - ;; Instead of checking for each mode explicitly `minor-mode-list' - ;; could be used. But this may make the byte compiler pop up. - (when (memq var '(TeX-PDF-mode - TeX-source-correlate-mode TeX-interactive-mode - TeX-fold-mode LaTeX-math-mode)) - (funcall var (if (symbol-value val) 1 0)))) - -(defvar TeX-overlay-priority-step 16 - "Numerical difference of priorities between nested overlays. -The step should be big enough to allow setting a priority for new -overlays between two existing ones.") - -;; require crm here, because we often do -;; -;; (let ((crm-separator ",")) -;; (TeX-completing-read-multiple ...)) -;; -;; which results in a void-variable error if crm hasn't been loaded before. -(require 'crm) - -(if (or (and (= emacs-major-version 24) (>= emacs-minor-version 4)) - (>= emacs-major-version 25)) - ;; For GNU Emacs 24.4 or later, based on `completing-read-multiple' of - ;; git commit b14abca9476cba2f500b5eda89441d593dd0f12b - ;; 2013-01-10 * lisp/emacs-lisp/crm.el: Allow any regexp for separators. - (defun TeX-completing-read-multiple - (prompt table &optional predicate require-match initial-input - hist def inherit-input-method) - "Like `completing-read-multiple' which see. -Retain zero-length substrings but ensure that empty input results -in nil across different emacs versions." - (unwind-protect - (progn - (add-hook 'choose-completion-string-functions - #'crm--choose-completion-string) - (let* ((minibuffer-completion-table #'crm--collection-fn) - (minibuffer-completion-predicate predicate) - ;; see completing_read in src/minibuf.c - (minibuffer-completion-confirm - (unless (eq require-match t) require-match)) - (crm-completion-table table) - (map (if require-match - crm-local-must-match-map - crm-local-completion-map)) - ;; If the user enters empty input, `read-from-minibuffer' - ;; returns the empty string, not DEF. - (input (read-from-minibuffer - prompt initial-input map - nil hist def inherit-input-method)) - result) - (and def (string-equal input "") (setq input def)) - (if (equal (setq result (split-string input crm-separator)) - '("")) - nil - result))) - (remove-hook 'choose-completion-string-functions - #'crm--choose-completion-string))) - ;; For GNU Emacs <= 24.3. - (defun TeX-completing-read-multiple - (prompt table &optional predicate require-match initial-input - hist def inherit-input-method) - "Like `completing-read-multiple' which see. -Ensures that empty input results in nil across different emacs versions." - (let ((result (completing-read-multiple prompt table predicate - require-match initial-input - hist def inherit-input-method))) - (if (equal result '("")) nil result)))) - -(defun TeX-read-string (prompt &optional initial-input history default-value) - (read-string prompt initial-input history default-value t)) - -(defun TeX-active-mark () - (and transient-mark-mode mark-active)) - -(defun TeX-activate-region () - (setq deactivate-mark nil) - (activate-mark)) - -(defun TeX-overlay-prioritize (start end) - "Calculate a priority for an overlay extending from START to END. -The calculated priority is lower than the minimum of priorities -of surrounding overlays and higher than the maximum of enclosed -overlays." - (let (outer-priority inner-priority ov-priority) - (dolist (ov (overlays-in start end)) - (when (or (eq (overlay-get ov 'category) 'TeX-fold) - (overlay-get ov 'preview-state)) - (setq ov-priority (overlay-get ov 'priority)) - (if (>= (overlay-start ov) start) - (setq inner-priority (max ov-priority (or inner-priority - ov-priority))) - (setq outer-priority (min ov-priority (or outer-priority - ov-priority)))))) - (cond ((and inner-priority (not outer-priority)) - (+ inner-priority TeX-overlay-priority-step)) - ((and (not inner-priority) outer-priority) - (/ outer-priority 2)) - ((and inner-priority outer-priority) - (+ (/ (- outer-priority inner-priority) 2) inner-priority)) - (t TeX-overlay-priority-step)))) - -(defun TeX-delete-dups-by-car (alist &optional keep-list) - "Return a list of all elements in ALIST, but each car only once. -Elements of KEEP-LIST are not removed even if duplicate." - ;; Copy of `reftex-uniquify-by-car' (written by David Kastrup). - (setq keep-list (TeX-sort-strings keep-list)) - (setq alist (sort (copy-sequence alist) - #'TeX-car-string-lessp)) - (let ((new alist) elt) - (while (cdr new) - (setq elt (caar new)) - (while (and keep-list (string< (car keep-list) elt)) - (setq keep-list (cdr keep-list))) - (unless (and keep-list (string= elt (car keep-list))) - (while (string= elt (car (cadr new))) - (setcdr new (cddr new)))) - (setq new (cdr new)))) - alist) - -(defun TeX-delete-duplicate-strings (list) - "Return a list of all strings in LIST, but each only once." - (setq list (TeX-sort-strings list)) - (let ((new list) elt) - (while (cdr new) - (setq elt (car new)) - (while (string= elt (cadr new)) - (setcdr new (cddr new))) - (setq new (cdr new)))) - list) - -(defun TeX-sort-strings (list) - "Return sorted list of all strings in LIST." - (sort (copy-sequence list) #'string<)) - -(defun TeX-car-string-lessp (s1 s2) - "Compare the cars of S1 and S2 in lexicographic order. -Return t if first is less than second in lexicographic order." - (string-lessp (car s1) (car s2))) - -;;; Buffer - -(defgroup TeX-output nil - "Parsing TeX output." - :prefix "TeX-" - :group 'AUCTeX) - -(defcustom TeX-display-help t - "Control type of help display when stepping through errors with \\[TeX-next-error]. -If t display help buffer. If nil display message about error in -echo area. If `expert' display output buffer with raw processor output." - :group 'TeX-output - :type '(choice (const :tag "Help buffer" t) - (const :tag "Echo area" nil) - (const :tag "Output buffer" expert))) - -(defcustom TeX-debug-bad-boxes nil - "Non-nil means also find overfull/underfull box warnings with \\[TeX-next-error]." - :group 'TeX-output - :type 'boolean) - -(defcustom TeX-debug-warnings nil - "Non-nil means also find LaTeX or package warnings with \\[TeX-next-error]." - :group 'TeX-output - :type 'boolean) - -(defcustom TeX-ignore-warnings nil - "Controls which warnings are to be ignored. - -It can be either a regexp matching warnings to be ignored, or a -symbol with the name of a custom function taking as arguments all -the information of the warning listed in `TeX-error-list', except -the last one about whether to ignore the warning. - -If you want to use the custom function, see how it is used in the -code of `TeX-warning'." - :group 'TeX-command - :type '(choice (const :tag "Do not ignore anything" nil) - (string :tag "Regexp") - (symbol :tag "Function name"))) - -(defcustom TeX-suppress-ignored-warnings nil - "Whether to actually show ignored warnings. - -Note that `TeX-debug-warnings' always takes the precedence." - :group 'TeX-command - :type 'boolean) - -(defun TeX-toggle-debug-bad-boxes () - "Toggle if the debugger should display \"bad boxes\" too." - (interactive) - (setq TeX-debug-bad-boxes (not TeX-debug-bad-boxes)) - (message (concat "TeX-debug-bad-boxes: " - (if TeX-debug-bad-boxes "on" "off")))) - -(defun TeX-toggle-debug-warnings () - "Toggle if the debugger should display warnings too." - (interactive) - (setq TeX-debug-warnings (not TeX-debug-warnings)) - (message (concat "TeX-debug-warnings: " - (if TeX-debug-warnings "on" "off")))) - -(defun TeX-toggle-suppress-ignored-warnings () - "Toggle if the debugger should display ignored warnings too. - -See `TeX-suppress-ignored-warnings' and `TeX-ignore-warnings' for -more details." - (interactive) - (setq TeX-suppress-ignored-warnings (not TeX-suppress-ignored-warnings)) - (message (concat "TeX-suppress-ignored-warnings: " - (if TeX-suppress-ignored-warnings "on" "off")))) - -;;; Mode names. - -(defvar TeX-base-mode-name nil - "Base name of mode.") -(make-variable-buffer-local 'TeX-base-mode-name) - -(defun TeX-set-mode-name (&optional changed local reset) - "Build and set the mode name. -The base mode name will be concatenated with indicators for -helper modes where appropriate. - -If CHANGED is non-nil, it indicates which global mode -may have changed so that all corresponding buffers -without a local value might get their name updated. -A value of t will thus update all buffer names. - -If LOCAL is non-nil and CHANGED is buffer-local, only -a local change has been performed and only the local -name is to be updated. - -If RESET is non-nil, `TeX-command-next' is reset to -`TeX-command-default' in updated buffers." - (if (and changed - (not (and local (local-variable-p changed (current-buffer))))) - (dolist (buffer (buffer-list)) - (and (local-variable-p 'TeX-mode-p buffer) - (not (local-variable-p changed buffer)) - (with-current-buffer buffer (TeX-set-mode-name nil nil reset)))) - (if TeX-mode-p - (let ((trailing-flags - (concat - (and (boundp 'TeX-fold-mode) TeX-fold-mode "F") - (and (boundp 'LaTeX-math-mode) LaTeX-math-mode "M") - (and TeX-PDF-mode "P") - (and TeX-interactive-mode "I") - (and TeX-source-correlate-mode "S")))) - (setq mode-name (concat TeX-base-mode-name - (when (> (length trailing-flags) 0) - (concat "/" trailing-flags)))) - (when reset - (TeX-process-set-variable (TeX-master-file) - 'TeX-command-next TeX-command-default) - (TeX-process-set-variable (TeX-region-file) - 'TeX-command-next TeX-command-default)) - (set-buffer-modified-p (buffer-modified-p)))))) - -(defun TeX-mode-prefix (&optional mode) - "Return the prefix for the symbol MODE as string. -If no mode is given the current major mode is used." - (cdr (assoc (or mode major-mode) '((plain-tex-mode . "plain-TeX") - (latex-mode . "LaTeX") - (ams-tex-mode . "AmSTeX") - (doctex-mode . "docTeX") - (texinfo-mode . "Texinfo") - (context-mode . "ConTeXt"))))) - -;;; Viewing - -(defgroup TeX-view nil - "Calling viewers from AUCTeX." - :group 'TeX-command) - -(defvar TeX-view-predicate-list-builtin - '((output-dvi - (string-match "dvi" (TeX-output-extension))) - (output-pdf - (string-match "pdf" (TeX-output-extension))) - (output-html - (string-match "html" (TeX-output-extension))) - (has-no-display-manager - (not (display-graphic-p))) - (style-pstricks - (TeX-match-style "^pstricks$\\|^pst-\\|^psfrag$")) - (engine-omega - (eq TeX-engine 'omega)) - (engine-xetex - (eq TeX-engine 'xetex)) - (mode-io-correlate - TeX-source-correlate-mode) - (paper-landscape - (and (fboundp 'LaTeX-match-class-option) - (LaTeX-match-class-option "\\`landscape\\'"))) - (paper-portrait - (not (and (fboundp 'LaTeX-match-class-option) - (LaTeX-match-class-option "\\`landscape\\'")))) - (paper-a4 - (let ((regex "\\`\\(?:a4paper\\|a4dutch\\|a4wide\\|sem-a4\\)\\'")) - (or (TeX-match-style regex) - (and (fboundp 'LaTeX-match-class-option) - (LaTeX-match-class-option regex))))) - (paper-a5 - (let ((regex "\\`\\(?:a5paper\\|a5comb\\)\\'")) - (or (TeX-match-style regex) - (and (fboundp 'LaTeX-match-class-option) - (LaTeX-match-class-option regex))))) - (paper-b5 - (and (fboundp 'LaTeX-match-class-option) - (LaTeX-match-class-option "\\`b5paper\\'"))) - (paper-letter - (and (fboundp 'LaTeX-match-class-option) - (LaTeX-match-class-option "\\`letterpaper\\'"))) - (paper-legal - (and (fboundp 'LaTeX-match-class-option) - (LaTeX-match-class-option "\\`legalpaper\\'"))) - (paper-executive - (and (fboundp 'LaTeX-match-class-option) - (LaTeX-match-class-option "\\`executivepaper\\'")))) - "Alist of built-in predicates for viewer selection and invocation. -See the doc string of `TeX-view-predicate-list' for a short -description of each predicate.") - -(defcustom TeX-view-predicate-list nil - "Alist of predicates for viewer selection and invocation. -The key of each list item is a symbol and the value a Lisp form -to be evaluated. The form should return nil if the predicate is -not fulfilled. - -Built-in predicates provided in `TeX-view-predicate-list-builtin' -can be overwritten by defining predicates with the same symbol. - -The following built-in predicates are available: - `output-dvi': The output is a DVI file. - `output-pdf': The output is a PDF file. - `output-html': The output is an HTML file. - `style-pstricks': The document loads a PSTricks package. - `engine-omega': The Omega engine is used for typesetting. - `engine-xetex': The XeTeX engine is used for typesetting. - `mode-io-correlate': TeX Source Correlate mode is active. - `paper-landscape': The document is typeset in landscape orientation. - `paper-portrait': The document is not typeset in landscape orientation. - `paper-a4': The paper format is A4. - `paper-a5': The paper format is A5. - `paper-b5': The paper format is B5. - `paper-letter': The paper format is letter. - `paper-legal': The paper format is legal. - `paper-executive': The paper format is executive." - :group 'TeX-view - :type '(alist :key-type symbol :value-type (group sexp))) - -;; XXX: Atril and xreader are forks of Evince and share an almost -;; identical interface with it. Instead of having different functions -;; for each program, we keep the original *-evince-* functions and -;; make them accept arguments to specify the actual name of the -;; program and the desktop environment, that will be used to set up -;; DBUS communication. - -(defun TeX-evince-dbus-p (de app &rest options) - "Return non-nil, if an evince-compatible reader is accessible via DBUS. -Additional OPTIONS may be given to extend the check. If none are -given, only the minimal requirements needed by backward search -are checked. If OPTIONS include `:forward', which is currently -the only option, then additional requirements needed by forward -search are checked, too. - -DE is the name of the desktop environment, APP is the name of viewer." - (let ((dbus-debug nil)) - (and (featurep 'dbusbind) - (require 'dbus nil :no-error) - (dbus-ignore-errors (dbus-get-unique-name :session)) - (dbus-ping :session (format "org.%s.%s.Daemon" de app)) - (or (not (memq :forward options)) - (let ((spec (dbus-introspect-get-method - :session (format "org.%s.%s.Daemon" de app) - (format "/org/%s/%s/Daemon" de app) - (format "org.%s.%s.Daemon" de app) - "FindDocument"))) - ;; FindDocument must exist, and its signature must be (String, - ;; Boolean, String). Evince versions between 2.30 and 2.91.x - ;; didn't have the Boolean spawn argument we need to start evince - ;; initially. - (and spec - (equal '("s" "b" "s") - (delq nil (mapcar (lambda (elem) - (when (and (listp elem) - (eq (car elem) 'arg)) - (cdr (caar (cdr elem))))) - spec))))))))) - -(defun TeX-pdf-tools-sync-view () - "Focus the focused page/paragraph in `pdf-view-mode'. -If `TeX-source-correlate-mode' is disabled, only find and pop to -the output PDF file. Used by default for the PDF Tools viewer -entry in `TeX-view-program-list-builtin'." - ;; Make sure `pdf-tools' is at least in the `load-path', but the user must - ;; take care of properly loading and installing the package. We used to test - ;; "(featurep 'pdf-tools)", but that doesn't play well with deferred loading. - (unless (fboundp 'pdf-tools-install) - (error "PDF Tools are not available")) - (unless TeX-PDF-mode - (error "PDF Tools only work with PDF output")) - (add-hook 'pdf-sync-backward-redirect-functions - #'TeX-source-correlate-handle-TeX-region) - (if (and TeX-source-correlate-mode - (fboundp 'pdf-sync-forward-search)) - (with-current-buffer (or (when TeX-current-process-region-p - (get-file-buffer (TeX-region-file t))) - (current-buffer)) - (pdf-sync-forward-search)) - (let ((pdf (TeX-active-master (TeX-output-extension)))) - (pop-to-buffer (or (find-buffer-visiting pdf) - (find-file-noselect pdf)))))) - -(defcustom TeX-view-evince-keep-focus nil - "Whether Emacs retains the focus when viewing PDF files with Evince. - -When calling `TeX-evince-sync-view', Evince normally captures the -focus. If this option is set to non-nil, Emacs will retain the -focus." - :group 'TeX-view - :type 'boolean) - -(defun TeX-evince-sync-view-1 (de app) - "Focus the focused page/paragraph in Evince with the position -of point in emacs by using Evince's DBUS API. Used by default -for the Evince-compatible entries in -`TeX-view-program-list-builtin' if the requirements are met. - -DE is the name of the desktop environment, APP is the name of -viewer." - (require 'url-util) - (let* ((uri (concat "file://" - ;; bug#45510: ? in filenames must be escaped as - ;; %3F to be a proper URI. - (replace-regexp-in-string - "[?]" "%3F" - (url-encode-url - (expand-file-name - (TeX-active-master (TeX-output-extension))))))) - (owner (dbus-call-method - :session (format "org.%s.%s.Daemon" de app) - (format "/org/%s/%s/Daemon" de app) - (format "org.%s.%s.Daemon" de app) - "FindDocument" - uri - t))) - (if owner - (with-current-buffer (or (when TeX-current-process-region-p - (get-file-buffer (TeX-region-file t))) - (current-buffer)) - (dbus-call-method - :session owner - (format "/org/%s/%s/Window/0" de app) - (format "org.%s.%s.Window" de app) - "SyncView" - (buffer-file-name) - (list :struct :int32 (1+ (TeX-current-offset)) - ;; FIXME: Using `current-column' here is dubious. - ;; Most of CJK letters count as occupying 2 columns, - ;; so the column number is not equal to the number of - ;; the characters counting from the beginning of a - ;; line. What is the right number to specify here? - ;; number of letters? bytes in UTF8? or other? - :int32 (1+ (current-column))) - :uint32 0) - (when TeX-view-evince-keep-focus - (select-frame-set-input-focus (selected-frame)))) - (error "Couldn't find the %s instance for %s" (capitalize app) uri)))) - -(defun TeX-atril-sync-view () - "Run `TeX-evince-sync-view-1', which see, set up for Atril." - (TeX-evince-sync-view-1 "mate" "atril")) - -(defun TeX-evince-sync-view () - "Run `TeX-evince-sync-view-1', which see, set up for Evince." - (TeX-evince-sync-view-1 "gnome" "evince")) - -(defun TeX-reader-sync-view () - "Run `TeX-evince-sync-view-1', which see, set up for Xreader." - (TeX-evince-sync-view-1 "x" "reader")) - -(defun TeX-view-program-select-evince (de app) - "Select how to call the Evince-like viewer. - -DE is the name of the desktop environment, APP is the name of -viewer." - (if (TeX-evince-dbus-p de app :forward) - (intern (format "TeX-%s-sync-view" app)) - `(,app (mode-io-correlate - ;; When tex.el is loaded as response to opening a tex file - ;; in a non-existent directory, we need to make sure - ;; `default-directory' exists, otherwise the shell-command - ;; below will error (bug#50225). - ,(let ((default-directory (file-name-as-directory - (expand-file-name "~")))) - ;; With evince 3, -p N opens the page *labeled* N, - ;; and -i,--page-index the physical page N. - (if (string-match "--page-index" - (shell-command-to-string (concat app " --help"))) - " -i %(outpage)" - " -p %(outpage)"))) " %o"))) - -(defvar TeX-view-program-list-builtin - (cond - ((eq system-type 'windows-nt) - '(("Yap" ("yap -1" (mode-io-correlate " -s %n%b") " %o") "yap") - ("dviout" ("dviout -1 " - ((paper-a4 paper-portrait) "-y=A4 ") - ((paper-a4 paper-landscape) "-y=A4L ") - ((paper-a5 paper-portrait) "-y=A5 ") - ((paper-a5 paper-landscape) "-y=A5L ") - ((paper-b5 paper-portrait) "-y=E5 ") - ((paper-b5 paper-landscape) "-y=E5L ") - ((paper-b4jis paper-portrait) "-y=B4 ") - ((paper-b4jis paper-landscape) "-y=B4L ") - ((paper-b5jis paper-portrait) "-y=B5 ") - ((paper-b5jis paper-landscape) "-y=B5L ") - (paper-legal "-y=Legal ") - (paper-letter "-y=Letter ") - (paper-executive "-y=Executive ") - "%d" (mode-io-correlate " \"# %n '%b'\"")) "dviout") - ("PDF Tools" TeX-pdf-tools-sync-view) - ("SumatraPDF" - ("SumatraPDF -reuse-instance" - (mode-io-correlate " -forward-search \"%b\" %n") " %o") - "SumatraPDF") - ("dvips and start" "dvips %d -o && start \"\" %f" "dvips") - ("start" "start \"\" %o"))) - ((eq system-type 'darwin) - '(("Preview.app" "open -a Preview.app %o" "open") - ("Skim" "open -a Skim.app %o" "open") - ("PDF Tools" TeX-pdf-tools-sync-view) - ("displayline" "displayline %n %o %b" "displayline") - ("open" "open %o" "open"))) - (t - `(("dvi2tty" ("dvi2tty -q -w 132 %o")) - ("xdvi" ("%(o?)xdvi" - (mode-io-correlate " -sourceposition \"%n %b\" -editor \"%cS\"") - ((paper-a4 paper-portrait) " -paper a4") - ((paper-a4 paper-landscape) " -paper a4r") - ((paper-a5 paper-portrait) " -paper a5") - ((paper-a5 paper-landscape) " -paper a5r") - (paper-b5 " -paper b5") - (paper-letter " -paper us") - (paper-legal " -paper legal") - (paper-executive " -paper 7.25x10.5in") - " %d") "%(o?)xdvi") - ("dvips and gv" "%(o?)dvips %d -o && gv %f" ,(list "%(o?)dvips" "gv")) - ("gv" "gv %o" "gv") - ("xpdf" ("xpdf -remote %s -raise %o" (mode-io-correlate " %(outpage)")) "xpdf") - ("Evince" ,(TeX-view-program-select-evince "gnome" "evince") "evince") - ("Atril" ,(TeX-view-program-select-evince "mate" "atril") "atril") - ("Xreader" ,(TeX-view-program-select-evince "x" "reader") "xreader") - ("Okular" ("okular --unique %o" (mode-io-correlate "#src:%n%a")) "okular") - ("xdg-open" "xdg-open %o" "xdg-open") - ("PDF Tools" TeX-pdf-tools-sync-view) - ("Zathura" - ("zathura %o" - (mode-io-correlate - " --synctex-forward %n:0:\"%b\" -x \"emacsclient +%{line} %{input}\"")) - "zathura")))) - "Alist of built-in viewer specifications. -This variable should not be changed by the user who can use -`TeX-view-program-list' to add new viewers or overwrite the -definition of built-in ones. The latter variable also contains a -description of the data format.") - -(defcustom TeX-view-program-list nil - "List of viewer specifications. -This variable can be used to specify how a viewer is to be -invoked and thereby add new viewers on top of the built-in list -of viewers defined in `TeX-view-program-list-builtin' or override -entries in the latter. - -The car of each item is a string with a user-readable name. The -second element can be a command line to be run as a process or a -Lisp function to be executed. The command line can either be -specified as a single string or a list of strings and two-part -lists. The first element of the two-part lists is a symbol or a -list of symbols referring to one or more of the predicates in -`TeX-view-predicate-list' or `TeX-view-predicate-list-builtin'. -The second part of the two-part lists is a command line part. -The command line for the viewer is constructed by concatenating -the command line parts. Parts with a predicate are only -considered if the predicate was evaluated with a positive result. -Note that the command line can contain placeholders as defined in -`TeX-expand-list' which are expanded before the viewer is called. -The third element of the item is optional and is a string, or a -list of strings, with the name of the executable, or executables, -needed to open the output file in the viewer. Placeholders -defined in `TeX-expand-list' can be used here. This element is -used to check whether the viewer is actually available on the -system. - -The use of a function as the second element only works if the -View command in `TeX-command-list' makes use of the hook -`TeX-run-discard-or-function'. - -Note: Predicates defined in the current Emacs session will only -show up in the customization interface for this variable after -restarting Emacs." - :group 'TeX-view - :type - `(repeat - (list - (string :tag "Name") - (choice - (group :tag "Command" (string :tag "Command")) - (group :inline t :tag "Command parts" - (repeat - :tag "Command parts" - (choice - (string :tag "Command part") - (list :tag "Predicate and command part" - ,(let (list) - ;; Build the list of available predicates. - (mapc (lambda (spec) - (cl-pushnew `(const ,(car spec)) list :test #'equal)) - (append TeX-view-predicate-list - TeX-view-predicate-list-builtin)) - ;; Sort the list alphabetically. - (setq list (sort list - (lambda (a b) - (string< - (downcase (symbol-name (cadr a))) - (downcase (symbol-name (cadr b))))))) - `(choice - (choice :tag "Predicate" ,@list) - (repeat :tag "List of predicates" - (choice :tag "Predicate" ,@list)))) - (string :tag "Command part"))))) - (group :tag "Function" function)) - (choice :tag "Viewer executable(s)" - (string :tag "One executable") - (repeat :tag "List of executables" (string :tag "Name")) - (const :tag "No executable" nil))))) - -(defcustom TeX-view-program-selection - (cond - ((eq system-type 'windows-nt) - '(((output-dvi style-pstricks) "dvips and start") - (output-dvi "Yap") - (output-pdf "start") - (output-html "start"))) - ((eq system-type 'darwin) - '((output-dvi "open") - (output-pdf "open") - (output-html "open"))) - (t - '(((output-dvi has-no-display-manager) "dvi2tty") - ((output-dvi style-pstricks) "dvips and gv") - (output-dvi "xdvi") - (output-pdf "Evince") - (output-html "xdg-open")))) - "Alist of predicates and viewers. -Each entry consists of a list with two elements. The first -element is a symbol or list of symbols referring to predicates as -defined in `TeX-view-predicate-list' or -`TeX-view-predicate-list-builtin'. The second element is a -string referring to the name of a viewer as defined in -`TeX-view-program-list' or `TeX-view-program-list-builtin'. -\(Note: Viewers added to `TeX-view-program-list' in the current -Emacs session will not show up in the customization interface of -`TeX-view-program-selection' until you restart Emacs.) - -When a viewer is called for, the entries are evaluated in turn -and the viewer related to the first entry all predicates of which -are evaluated positively is chosen." - :group 'TeX-view - :type `(alist :key-type - ;; Offer list of defined predicates. - ,(let (list) - (mapc (lambda (spec) - (cl-pushnew `(const ,(car spec)) list :test #'equal)) - (append TeX-view-predicate-list - TeX-view-predicate-list-builtin)) - (setq list (sort list - (lambda (a b) - (string< - (downcase (symbol-name (cadr a))) - (downcase (symbol-name (cadr b))))))) - `(choice (choice :tag "Single predicate" ,@list) - (repeat :tag "Multiple predicates" - (choice ,@list)))) - :value-type - ;; Offer list of defined viewers. - (group (choice :tag "Viewer" - ,@(let (list) - (mapc (lambda (spec) - (cl-pushnew `(const ,(car spec)) - list :test #'equal)) - (append TeX-view-program-list - TeX-view-program-list-builtin)) - (sort list - (lambda (a b) - (string< (downcase (cadr a)) - (downcase (cadr b)))))))))) - -(defun TeX-match-style (regexp) - "Check if a style matching REGEXP is active." - (TeX-member regexp (TeX-style-list) #'string-match)) - -(defun TeX-view-match-predicate (predicate) - "Check if PREDICATE is true. -PREDICATE can be a symbol or a list of symbols defined in -`TeX-view-predicate-list-builtin' or `TeX-view-predicate-list'. -In case of a single symbol, return t if the predicate is true, -nil otherwise. In case of a list of symbols, return t if all -predicates are true, nil otherwise." - (let ((pred-symbols (if (listp predicate) predicate (list predicate))) - (pred-defs (append TeX-view-predicate-list - TeX-view-predicate-list-builtin)) - (result t) - elt) - (while (and (setq elt (pop pred-symbols)) result) - (unless (eval (cadr (assq elt pred-defs)) t) - (setq result nil))) - result)) - -(defun TeX-view-command-raw () - "Choose a viewer and return its unexpanded command string." - (let ((selection TeX-view-program-selection) - entry viewer item executable spec command) - ;; Find the appropriate viewer. - (while (and (setq entry (pop selection)) (not viewer)) - (when (TeX-view-match-predicate (car entry)) - (setq viewer (cadr entry)))) - (unless viewer - (error "No matching viewer found")) - (setq item (assoc viewer (append TeX-view-program-list - TeX-view-program-list-builtin)) - ;; Get the command line or function spec. - spec (cadr item) - ;; Get the name of the executable(s) associated to the viewer. - executable (nth 2 item)) - ;; Check the executable exists. - (unless (or (null executable) - (cond - ((stringp executable) - (executable-find (TeX-command-expand executable))) - ((listp executable) - (catch 'notfound - (dolist (exec executable t) - (unless (executable-find (TeX-command-expand exec)) - (throw 'notfound nil))))))) - (error (format "Cannot find %S viewer. \ -Select another one in `TeX-view-program-selection'" viewer))) - (cond ((functionp spec) - ;; Converting the function call to a string is ugly, but - ;; the backend currently only supports strings. - (prin1-to-string spec)) - ((stringp spec) - spec) - ((null spec) - (error - (format "Unknown %S viewer. \ -Check the `TeX-view-program-selection' variable" viewer))) - (t - ;; Build the unexpanded command line. Pieces with predicates are - ;; only added if the predicate is evaluated positively. - (dolist (elt spec) - (cond ((stringp elt) - (setq command (concat command elt))) - ((listp elt) - (when (TeX-view-match-predicate (car elt)) - (setq command (concat command (cadr elt))))))) - (if (stringp command) - command - ;; Signal an error if `command' isn't a string. This prevents an - ;; infinite loop in `TeX-command-expand' if `command' is nil. - (error "Wrong viewer specification in `TeX-view-program-list'")))))) - -;;; Engine - -(defvar TeX-engine-alist-builtin - '((default "Default" TeX-command LaTeX-command ConTeXt-engine) - (xetex "XeTeX" "xetex" "xelatex" "xetex") - ;; Some lualatex versions before 0.71 would use "texput" as file - ;; name if --jobname were not supplied - (luatex "LuaTeX" "luatex" "lualatex --jobname=%s" "luatex") - (omega "Omega" TeX-Omega-command LaTeX-Omega-command ConTeXt-Omega-engine)) - "Alist of built-in TeX engines and associated commands. -For a description of the format see `TeX-engine-alist'.") - -(defcustom TeX-engine-alist nil - "Alist of TeX engines and associated commands. -Each entry is a list with a maximum of five elements. The first -element is a symbol used to identify the engine. The second is a -string describing the engine. The third is the command to be -used for plain TeX. The fourth is the command to be used for -LaTeX. The fifth is the command to be used for the --engine -parameter of ConTeXt's texexec program. Each command can either -be a variable or a string. An empty string or nil means there is -no command available. - -You can override a built-in engine defined in the variable -`TeX-engine-alist-builtin' by adding an entry beginning with the -same symbol as the built-in entry to `TeX-engine-alist'." - :group 'TeX-command - :type '(repeat (group symbol - (string :tag "Name") - (choice :tag "Plain TeX command" string variable) - (choice :tag "LaTeX command" string variable) - (choice :tag "ConTeXt command" string variable)))) - -(defun TeX-engine-alist () - "Return an alist of TeX engines. -The function appends the built-in engine specs from -`TeX-engine-alist-builtin' and the user-defined engines from -`TeX-engine-alist' and deletes any entries from the built-in part -where an entry with the same car exists in the user-defined part." - (TeX-delete-dups-by-car (append TeX-engine-alist TeX-engine-alist-builtin))) - -(defun TeX-engine-in-engine-alist (engine) - "Return the `engine' entry in `TeX-engine-alist'. - -Throw an error if `engine' is not present in the alist." - (or - (assq engine (TeX-engine-alist)) - (error "Unknown engine `%s'. Valid values are: %s" engine - (mapconcat - (lambda (x) (prin1-to-string (car x))) - (TeX-engine-alist) ", ")))) - -(defcustom TeX-engine 'default - (concat "Type of TeX engine to use. -It should be one of the following symbols:\n\n" - (mapconcat (lambda (x) (format "* `%s'" (car x))) - (TeX-engine-alist) "\n")) - :group 'TeX-command - :type `(choice ,@(mapcar (lambda (x) - `(const :tag ,(nth 1 x) ,(car x))) - (TeX-engine-alist)))) -(make-variable-buffer-local 'TeX-engine) -(put 'TeX-engine 'safe-local-variable - (lambda (arg) (memq arg (mapcar #'car TeX-engine-alist-builtin)))) - -(defun TeX-engine-set (type) - "Set TeX engine to TYPE. -For available TYPEs, see variable `TeX-engine'." - (interactive (list (completing-read "Engine: " - (mapcar (lambda (x) - (symbol-name (car x))) - (TeX-engine-alist)) - nil t))) - (when (stringp type) - (setq type (intern type))) - (setq TeX-engine type) - ;; Automatically enable or disable TeX PDF mode as a convenience - (cond ((eq type 'xetex) - (TeX-PDF-mode 1) - (setq TeX-PDF-from-DVI nil)) - ((eq type 'omega) (TeX-PDF-mode 0)))) - -(define-minor-mode TeX-Omega-mode - "Minor mode for using the Omega engine." - :init-value nil :lighter nil :keymap nil - :group 'TeX-command - (TeX-engine-set (if TeX-Omega-mode 'omega 'default))) -(defalias 'tex-omega-mode #'TeX-Omega-mode) -(make-obsolete 'TeX-Omega-mode #'TeX-engine-set "11.86") -(make-obsolete-variable 'TeX-Omega-mode 'TeX-engine "11.86") - -;;; Forward and inverse search - -(defcustom TeX-source-correlate-method - '((dvi . source-specials) (pdf . synctex)) - "Method to use for enabling forward and inverse search. -This can be `source-specials' if source specials should be used, -`synctex' if SyncTeX should be used, or `auto' if AUCTeX should -decide. - -The previous values determine the variable for both DVI and PDF -mode. This variable can also be an alist of the kind - - ((dvi . <source-specials or synctex>) - (pdf . <source-specials or synctex>)) - -in which the CDR of each entry is a symbol specifying the method -to be used in the corresponding mode. - -Programs should not use this variable directly but the function -`TeX-source-correlate-method-active' which returns the method -actually used for forward and inverse search." - :type '(choice (const auto) - (const synctex) - (const source-specials) - (list :tag "Different method for DVI and PDF" - (cons (const dvi) - (choice :tag "Method for DVI mode" - (const synctex) - (const source-specials))) - (cons (const pdf) - (choice :tag "Method for PDF mode" - (const synctex) - (const source-specials))))) - :group 'TeX-view) - -(defvar TeX-source-correlate-output-page-function nil - "Symbol of function returning an output page relating to buffer position. -The function should take no arguments and return the page numer -as a string.") -(make-variable-buffer-local 'TeX-source-correlate-output-page-function) - -(define-obsolete-variable-alias 'TeX-source-specials-view-start-server - 'TeX-source-correlate-start-server "11.86") - -(defcustom TeX-source-correlate-start-server 'ask - "Control if server should be started for inverse search." - :type '(choice (const :tag "Always" t) - (const :tag "Never" nil) - (const :tag "Ask" ask)) - :group 'TeX-view) - -(defvar TeX-source-correlate-start-server-asked nil - "Keep track if question about server start search was asked.") - -(defvar TeX-source-correlate-start-server-flag nil - "If non-nil, `TeX-source-correlate-start-server-maybe' will start a server. -Code related to features requiring a server, for example, for inverse -search, can set the variable.") - -(defun TeX-source-correlate-gnuserv-p () - "Guess whether to use gnuserv when a server is requested." - (cond ((and (boundp 'gnuserv-process) - (processp gnuserv-process))) - ((and (boundp 'server-process) - (processp server-process)) - nil))) - -(defun TeX-source-correlate-server-enabled-p () - "Return non-nil if Emacs server or gnuserv is enabled." - (let* ((gnuserv-p (TeX-source-correlate-gnuserv-p)) - (process (if gnuserv-p 'gnuserv-process 'server-process))) - (and (boundp process) (processp (symbol-value process))))) - -(defun TeX-source-correlate-start-server-maybe () - "Start Emacs server or gnuserv if a feature using it is enabled. -This is the case if `TeX-source-correlate-start-server-flag' is non-nil." - (when (and TeX-source-correlate-start-server-flag - (not (TeX-source-correlate-server-enabled-p))) - (let* ((gnuserv-p (TeX-source-correlate-gnuserv-p)) - (start (if gnuserv-p #'gnuserv-start #'server-start))) - (cond - ;; Server should be started unconditionally - ((eq TeX-source-correlate-start-server t) - (funcall start)) - ;; Ask user if server is to be started - ((and (eq TeX-source-correlate-start-server 'ask) - (not TeX-source-correlate-start-server-asked) - (prog1 - (y-or-n-p (format "Start %s for inverse search in viewer? " - (if gnuserv-p - "gnuserv" - "Emacs server"))) - (setq TeX-source-correlate-start-server-asked t))) - (funcall start)))))) - -(defun TeX-source-correlate-determine-method () - "Determine which method is available for forward and inverse search." - (let ((help (condition-case nil - (with-output-to-string - (call-process LaTeX-command - nil (list standard-output nil) nil "--help")) - (error "")))) - (if (string-match "^[ ]*-?-synctex" help) - 'synctex - 'source-specials))) - -(defun TeX-source-correlate-method-active () - "Return the method actually used for forward and inverse search." - (cond - ((eq TeX-source-correlate-method 'auto) - (TeX-source-correlate-determine-method)) - ((listp TeX-source-correlate-method) - (if TeX-PDF-mode - (cdr (assoc 'pdf TeX-source-correlate-method)) - (cdr (assoc 'dvi TeX-source-correlate-method)))) - (t - TeX-source-correlate-method))) - -(defun TeX-source-correlate-expand-options () - "Return TeX engine command line option for forward search facilities. -The return value depends on the value of `TeX-source-correlate-mode'. -If this is nil, an empty string will be returned." - (if TeX-source-correlate-mode - (if (eq (TeX-source-correlate-method-active) 'source-specials) - (concat TeX-source-specials-tex-flags - (if TeX-source-specials-places - ;; -src-specials=WHERE: insert source specials - ;; in certain places of the DVI file. WHERE is a - ;; comma-separated value list: cr display hbox - ;; math par parend vbox - (concat "=" (mapconcat #'identity - TeX-source-specials-places ",")))) - TeX-synctex-tex-flags) - "")) - -(defvar TeX-source-correlate-map (make-sparse-keymap) - "Keymap for `TeX-source-correlate-mode'. -You could use this for unusual mouse bindings.") - -(defun TeX-source-correlate-handle-TeX-region (file line col) - "Translate backward search info with respect to `TeX-region'. -That is, if FILE is `TeX-region', update FILE to the real tex -file and LINE to (+ LINE offset-of-region), but retain COL as is. -Else, return nil." - (when (string-equal TeX-region (file-name-sans-extension - (file-name-nondirectory file))) - (with-current-buffer (or (find-buffer-visiting file) - (find-file-noselect file)) - (goto-char 0) - ;; Same regexp used in `preview-parse-messages'. XXX: XEmacs doesn't - ;; support regexp classes, so we can't use "[:digit:]" here. - (when (re-search-forward "!offset(\\([---0-9]+\\))" nil t) - (let ((offset (string-to-number (match-string-no-properties 1)))) - (when TeX-region-orig-buffer - (list (expand-file-name (buffer-file-name TeX-region-orig-buffer)) - (+ line offset) col))))))) - -(defcustom TeX-raise-frame-function #'raise-frame - "A function which will be called to raise the Emacs frame. -The function is called after `TeX-source-correlate-sync-source' -has processed an inverse search DBUS request from -Evince-compatible viewers in order to raise the Emacs frame. - -The default value is `raise-frame', however, depending on window -manager and focus stealing policies, it might very well be that -Emacs doesn't pop into the foreground. So you can do whatever it -takes here. - -For some users, `x-focus-frame' does the trick. For some -users (on GNOME 3.20), - - (lambda () - (run-at-time 0.5 nil #\\='x-focus-frame)) - -does the trick. Some other users use the external wmctrl tool to -raise the Emacs frame like so: - - (lambda () - (call-process - \"wmctrl\" nil nil nil \"-i\" \"-R\" - (frame-parameter (selected-frame) \\='outer-window-id)))" - :type 'function - :group 'TeX-view) - -(defun TeX-source-correlate-sync-source (file linecol &rest _ignored) - "Show TeX FILE with point at LINECOL. -This function is called when emacs receives a SyncSource signal -emitted from the Evince document viewer. IGNORED absorbs an -unused id field accompanying the DBUS signal sent by Evince-3.0.0 -or newer. - -If the Emacs frame isn't raised, customize -`TeX-raise-frame-function'." - ;; FILE may be given as relative path to the TeX-master root document or as - ;; absolute file:// URL. In the former case, the tex file has to be already - ;; opened. - (let* ((file (progn - (require 'url-parse) - (require 'url-util) - (url-unhex-string (aref (url-generic-parse-url file) 6)))) - (flc (or (apply #'TeX-source-correlate-handle-TeX-region file linecol) - (apply #'list file linecol))) - (file (car flc)) - (line (cadr flc)) - (col (nth 2 flc))) - (pop-to-buffer (or (find-buffer-visiting file) - (find-file-noselect file))) - (push-mark nil 'nomsg) - (let ((pos - (when (> line 0) - (save-excursion - (save-restriction - (widen) - (goto-char 1) - (forward-line (1- line)) - (when (> col 0) - (forward-char (1- col))) - (point)))))) - (when pos - (when (or (< pos (point-min)) - (> pos (point-max))) - (widen)) - (goto-char pos)) - (when TeX-raise-frame-function - (funcall TeX-raise-frame-function))))) - -(define-minor-mode TeX-source-correlate-mode - "Minor mode for forward and inverse search. - -If enabled, the viewer can be advised to show the output page -corresponding to the point in the source and vice versa. - -The method to be used can be controlled with the variable -`TeX-source-correlate-method'. Currently source specials or -SyncTeX are recognized." - :group 'TeX-view - ;; Since this is a global minor mode and we don't want to require - ;; tex.el when the mode variable is set, the mode function is called - ;; explicitly (if necessary) in `VirTeX-common-initialization'. We - ;; do it there because otherwise `kill-all-local-variables' would - ;; reset `TeX-source-correlate-output-page-function' which is - ;; buffer-local. - :global t - (set-keymap-parent TeX-mode-map (and TeX-source-correlate-mode - TeX-source-correlate-map)) - (TeX-set-mode-name 'TeX-source-correlate-mode t t) - (setq TeX-source-correlate-start-server-flag TeX-source-correlate-mode) - ;; Register Emacs for the SyncSource DBUS signal emitted by - ;; Evince-compatible viewers. - (dolist (de-app '(("gnome" "evince") ("mate" "atril") ("x" "reader"))) - (when (TeX-evince-dbus-p (car de-app) (cadr de-app)) - (dbus-register-signal - :session nil (format "/org/%s/%s/Window/0" (car de-app) (cadr de-app)) - (format "org.%s.%s.Window" (car de-app) (cadr de-app)) - "SyncSource" - #'TeX-source-correlate-sync-source)))) - -(defalias 'TeX-source-specials-mode #'TeX-source-correlate-mode) -(make-obsolete 'TeX-source-specials-mode 'TeX-source-correlate-mode "11.86") -(defalias 'tex-source-correlate-mode #'TeX-source-correlate-mode) -(put 'TeX-source-correlate-mode 'safe-local-variable #'booleanp) -(setq minor-mode-map-alist - (delq (assq 'TeX-source-correlate-mode minor-mode-map-alist) - minor-mode-map-alist)) - - -;;; Source Specials - -(defcustom TeX-source-specials-tex-flags "-src-specials" - "Extra flags to pass to TeX commands to generate source specials." - :group 'TeX-view - :type 'string) - -(defcustom TeX-source-specials-places nil - "List of places where to insert source specials into the DVI file. -If nil, use (La)TeX's defaults." - :group 'TeX-view - :type '(list (set :inline t - ;; :tag "Options known to work" - ;; cr display hbox math par parend vbox - (const "cr") - (const "display") - (const "hbox") - (const "math") - (const "par") - (const "parend") - (const "vbox")) - (repeat :inline t - :tag "Other options" - (string)))) - -(defcustom TeX-source-specials-view-position-flags - "-sourceposition \"%n %b\"" - "Flags to pass to the DVI viewer commands for the position in the source." - :group 'TeX-view - :type 'string) - -(defcustom TeX-source-specials-view-editor-flags - "-editor \"%cS\"" - "Flags to pass to DVI viewer commands for inverse search." - :group 'TeX-view - :type 'string) - -(defcustom TeX-source-specials-view-gnuclient-flags - "-q +%%l %%f" - "Flags to pass to gnuclient for inverse search." - :group 'TeX-view - :type 'string) - -(defcustom TeX-source-specials-view-emacsclient-flags - "--no-wait +%%l %%f" - "Flags to emacsclient for inverse search." - :group 'TeX-view - :type 'string) - -;; FIXME: Make client binaries configurable. -(defun TeX-source-specials-view-expand-client () - "Return gnuclient or emacslient executable with options. -Return the full path to the executable if possible." - (let* ((gnuserv-p (TeX-source-correlate-gnuserv-p)) - (client-base (if gnuserv-p - "gnuclient" - "emacsclient")) - (client-full (and invocation-directory - (expand-file-name client-base - invocation-directory))) - (options (if gnuserv-p - TeX-source-specials-view-gnuclient-flags - TeX-source-specials-view-emacsclient-flags))) - (if (and client-full (file-executable-p client-full)) - (concat client-full " " options) - (concat client-base " " options)))) - -(defun TeX-source-specials-view-expand-options (&optional _viewer) - "Return source specials command line option for viewer command. -The return value depends on the values of -`TeX-source-correlate-mode' and -`TeX-source-correlate-method-active'. If those are nil or not -`source-specials' respectively, an empty string will be -returned." - (if (and TeX-source-correlate-mode - (eq (TeX-source-correlate-method-active) 'source-specials)) - (concat TeX-source-specials-view-position-flags - (when (TeX-source-correlate-server-enabled-p) - (concat " " TeX-source-specials-view-editor-flags))) - "")) - -;;; SyncTeX - -(defvar TeX-synctex-tex-flags "--synctex=1" - "Extra flags to pass to TeX commands to enable SyncTeX.") - -(defun TeX-synctex-output-page-1 (file) - "Return the page corresponding to the current position in FILE. -This method assumes that the document was compiled with SyncTeX -enabled and the `synctex' binary is available." - (let ((synctex-output - (with-output-to-string - (call-process "synctex" nil (list standard-output nil) nil "view" - "-i" (format "%s:%s:%s" (1+ (TeX-current-offset)) - ;; FIXME: Using `current-column' - ;; here is dubious. See comment in - ;; `TeX-evince-sync-view-1'. - (1+ (current-column)) - file) - "-o" (TeX-active-master (TeX-output-extension)))))) - (when (string-match "^Page:\\([0-9]+\\)" synctex-output) - (match-string 1 synctex-output)))) - -(defun TeX-synctex-output-page () - "Return the page corresponding to the position in the current buffer. -This method assumes that the document was compiled with SyncTeX -enabled and the `synctex' binary is available." - (let* ((file (file-relative-name (buffer-file-name) - (file-name-directory - (TeX-active-master)))) - (abs-file (concat (expand-file-name (or (file-name-directory (TeX-active-master)) - (file-name-directory (buffer-file-name)))) - "./" file))) - ;; It's known that depending on synctex version one of - ;; /absolute/path/./foo/bar.tex, foo/bar.tex, or ./foo/bar.tex (relative to - ;; TeX-master, and the "." in the absolute path is important) are needed. - ;; So try all variants before falling back to page 1. - (or (TeX-synctex-output-page-1 abs-file) - (TeX-synctex-output-page-1 file) - (TeX-synctex-output-page-1 (concat "./" file)) - "1"))) - -;;; Miscellaneous minor modes - -(defvar TeX-mode-p nil - "This indicates a TeX mode being active.") -(make-variable-buffer-local 'TeX-mode-p) - -(defun TeX-mode-set (var value) - (set-default var value) - (TeX-set-mode-name var nil t)) - -(defcustom TeX-PDF-mode t nil - :group 'TeX-command - :set #'TeX-mode-set - :type 'boolean) -(put 'TeX-PDF-mode 'safe-local-variable #'booleanp) - -(define-minor-mode TeX-PDF-mode - "Minor mode for using PDFTeX. - -If enabled, PDFTeX will be used as an executable by default. -You can customize an initial value, and you can use the -function `TeX-global-PDF-mode' for toggling this value." - :group 'TeX-command - (when (eq TeX-engine 'omega) - (setq TeX-PDF-mode nil)) - (setq TeX-PDF-mode-parsed nil) - (TeX-set-mode-name nil nil t) - (setq TeX-output-extension - (if TeX-PDF-mode "pdf" "dvi"))) -(add-to-list 'minor-mode-alist '(TeX-PDF-mode "")) - -(defun TeX-global-PDF-mode (&optional arg) - "Toggle default for `TeX-PDF-mode'." - (interactive "P") - (prog1 - (setq-default TeX-PDF-mode - (if arg (> (prefix-numeric-value arg) 0) - (not (default-value 'TeX-PDF-mode)))) - (TeX-set-mode-name 'TeX-PDF-mode nil t))) - -(defalias 'tex-pdf-mode #'TeX-PDF-mode) - -(defvar TeX-PDF-mode-parsed nil - "Set if `TeX-PDF-mode' has come about by parsing.") - -(make-variable-buffer-local 'TeX-PDF-mode-parsed) - -(defun TeX-PDF-mode-parsed (arg) - "Change `TeX-PDF-mode' to ARG based on parsing. -If this conflicts with previous parsed settings, -just use the default. If an explicit setting is -already established, don't do anything." - -;; Basically we have the following situations: -;; TeX-PDF-mode-parsed (local-variable-p 'TeX-PDF-mode): -;; nil nil : virgin state -;; nil t : stably set state (possibly because of conflicting parse info) -;; t t : non-conflicting parsed info - - (if TeX-PDF-mode-parsed - (unless (eq TeX-PDF-mode arg) - (TeX-PDF-mode (if (default-value 'TeX-PDF-mode) 1 0))) - (unless (local-variable-p 'TeX-PDF-mode (current-buffer)) - (TeX-PDF-mode (if arg 1 0)) - (setq TeX-PDF-mode-parsed t)))) - -(defun TeX-PDF-mode-on () - "Use only from parsing routines." - (TeX-PDF-mode-parsed t)) - -(defun TeX-PDF-mode-off () - "Use only from parsing routines." - (TeX-PDF-mode-parsed nil)) - -(defcustom TeX-DVI-via-PDFTeX nil - "Whether to use PDFTeX also for producing DVI files." - :group 'TeX-command - :type 'boolean) - -(defcustom TeX-PDF-from-DVI nil - "Specify if and how to produce PDF output from a DVI file. - -If non-nil, the default compiler produces DVI output. The value -should be the name of the command used to convert the DVI file to -PDF or to an intermediate type. - -Possible values are - -* \"Dvips\": the DVI file is converted to PS with dvips. After - successfully running it, ps2pdf will be the default command to - convert the PS file to PDF -* \"Dvipdfmx\": the PDF is produced with dvipdfmx - -Programs should not use this variable directly but the function -`TeX-PDF-from-DVI' which handles now obsolete variable -`TeX-PDF-via-dvips-ps2pdf'." - :group 'TeX-command - :type '(choice - (const :tag "No DVI to PDF conversion" nil) - (const :tag "dvips - ps2pdf sequence" "Dvips") - (const :tag "dvipdfmx" "Dvipdfmx"))) -;; If you plan to support new values of `TeX-PDF-from-DVI' remember to update -;; `TeX-command-default' accordingly. -(make-variable-buffer-local 'TeX-PDF-from-DVI) -(put 'TeX-PDF-from-DVI 'safe-local-variable - (lambda (x) (or (stringp x) (null x)))) - -(defcustom TeX-PDF-via-dvips-ps2pdf nil - "Whether to produce PDF output through the (La)TeX - dvips - ps2pdf sequence." - :group 'TeX-command - :type 'boolean) -(make-variable-buffer-local 'TeX-PDF-via-dvips-ps2pdf) -(put 'TeX-PDF-via-dvips-ps2pdf 'safe-local-variable #'booleanp) -(make-obsolete-variable 'TeX-PDF-via-dvips-ps2pdf 'TeX-PDF-from-DVI "11.90") - -(defun TeX-PDF-from-DVI () - "Return the value of variable `TeX-PDF-from-DVI'. - -If `TeX-PDF-from-DVI' is not set and obsolete option -`TeX-PDF-via-dvips-ps2pdf' is non-nil, return \"Dvips\" -for backward compatibility." - (cond - (TeX-PDF-from-DVI) - (TeX-PDF-via-dvips-ps2pdf - "Dvips"))) - -(define-minor-mode TeX-interactive-mode - "Minor mode for interactive runs of TeX." - :init-value nil :lighter nil :keymap nil - :group 'TeX-command - (TeX-set-mode-name 'TeX-interactive-mode t t)) -(defalias 'tex-interactive-mode #'TeX-interactive-mode) -(add-to-list 'minor-mode-alist '(TeX-interactive-mode "")) - -;;; Commands - -(defgroup TeX-command-name nil - "Names for external commands in AUCTeX." - :group 'TeX-command) - -(defcustom TeX-command-BibTeX "BibTeX" - "The name of the BibTeX entry in `TeX-command-list'." - :group 'TeX-command-name - :type 'string) - (make-variable-buffer-local 'TeX-command-BibTeX) - -(defcustom TeX-command-Biber "Biber" - "The name of the Biber entry in `TeX-command-list'." - :group 'TeX-command-name - :type 'string) - (make-variable-buffer-local 'TeX-command-Biber) - -(defcustom TeX-command-Show "View" - "The default command to show (view or print) a TeX file. -Must be the car of an entry in `TeX-command-list'." - :group 'TeX-command-name - :type 'string) - (make-variable-buffer-local 'TeX-command-Show) - -(defcustom TeX-command-Print "Print" - "The name of the Print entry in `TeX-command-Print'." - :group 'TeX-command-name - :type 'string) - -(defcustom TeX-command-Queue "Queue" - "The name of the Queue entry in `TeX-command-Queue'." - :group 'TeX-command-name - :type 'string) - -(defvar TeX-trailer-start nil - "Regular expression delimiting start of trailer in a TeX file.") - - (make-variable-buffer-local 'TeX-trailer-start) - -(defvar TeX-header-end nil - "Regular expression delimiting end of header in a TeX file.") - - (make-variable-buffer-local 'TeX-header-end) - -(defvar TeX-command-default nil - "The default command for `TeX-command' in the current major mode.") - - (make-variable-buffer-local 'TeX-command-default) - -(put 'TeX-command-default 'safe-local-variable #'stringp) - -(defvar TeX-clean-default-intermediate-suffixes - '("\\.aux" "\\.bbl" "\\.blg" "\\.brf" "\\.fot" - "\\.glo" "\\.gls" "\\.idx" "\\.ilg" "\\.ind" - "\\.lof" "\\.log" "\\.lot" "\\.nav" "\\.out" - "\\.snm" "\\.toc" "\\.url" "\\.synctex\\.gz" - "\\.bcf" "\\.run\\.xml" "\\.fls" "-blx\\.bib") - "List of regexps matching suffixes of files to be cleaned. -Used as a default in TeX, LaTeX and docTeX mode.") - -(defvar TeX-clean-default-output-suffixes - '("\\.dvi" "\\.pdf" "\\.ps" "\\.xdv") - "List of regexps matching suffixes of files to be cleaned. -Used as a default in TeX, LaTeX and docTeX mode.") - -(defcustom TeX-clean-confirm t - "If non-nil, ask before deleting files." - :type 'boolean - :group 'TeX-command) - -(autoload 'dired-mark-pop-up "dired") - -(defun TeX-clean (&optional arg) - "Delete generated files associated with current master and region files. -If prefix ARG is non-nil, not only remove intermediate but also -output files." - (interactive "P") - (let* (;; Call with output extension then remove it, to make sure we - ;; get the correct directory in cases TeX-output-dir is - ;; non-nil - (master (file-name-sans-extension (TeX-active-master (TeX-output-extension)))) - (master-dir (file-name-directory master)) - (regexp (concat "\\(" - (regexp-quote (file-name-nondirectory master)) "\\|" - (regexp-quote (file-name-nondirectory (TeX-region-file nil t))) - "\\)" - "\\(" - (TeX--clean-extensions-regexp arg) - "\\)\\'" - "\\|" (regexp-quote (file-name-nondirectory (TeX-region-file t t))))) - (files (when (and regexp (or (not master-dir) (file-exists-p master-dir))) - (directory-files (or master-dir ".") nil regexp)))) - (if files - (when (or (not TeX-clean-confirm) - (dired-mark-pop-up " *Deletions*" 'delete - (if (> (length files) 1) - files - (cons t files)) - 'y-or-n-p "Delete files? ")) - (dolist (file files) - (delete-file (concat master-dir file)))) - (message "No files to be deleted")))) - -(defun TeX--clean-extensions-regexp (&optional arg) - "Return a regexp to match extensions that should be cleaned by `TeX-clean'. -If the optional argument ARG is non-nil then output files are -also included in the regexp." - (let* ((mode-prefix (TeX-mode-prefix)) - (suffixes (and mode-prefix - (append (symbol-value - (intern (concat mode-prefix - "-clean-intermediate-suffixes"))) - (when arg - (symbol-value - (intern (concat mode-prefix - "-clean-output-suffixes")))))))) - (when suffixes - (mapconcat #'identity suffixes "\\|")))) - -;;; Master File - -(defcustom TeX-master t - "The master file associated with the current buffer. -If the file being edited is actually included from another file, you -can tell AUCTeX the name of the master file by setting this variable. -If there are multiple levels of nesting, specify the top level file. - -If this variable is nil, AUCTeX will query you for the name. - -If the variable is t, AUCTeX will assume the file is a master file -itself. - -If the variable is `shared', AUCTeX will query for the name, but not -change the file. - -If the variable is `dwim', AUCTeX will try to avoid querying by -attempting to `do what I mean'; and then change the file. - -It is suggested that you use the File Variables (see the info node -`File Variables') to set this variable permanently for each file." - :group 'TeX-command - :group 'TeX-parse - :type '(choice (const :tag "Query" nil) - (const :tag "This file" t) - (const :tag "Shared" shared) - (const :tag "Dwim" dwim) - (string :format "%v"))) -(make-variable-buffer-local 'TeX-master) -(put 'TeX-master 'safe-local-variable - (lambda (x) - (or (stringp x) - (member x (quote (t nil shared dwim)))))) - -(defcustom TeX-one-master "\\.\\(texi?\\|dtx\\)$" - "Regular expression matching ordinary TeX files. - -You should set this variable to match the name of all files, where -automatically adding a file variable with the name of the master file -is a good idea. When AUCTeX adds the name of the master file as a -file variable, it does not need to ask next time you edit the file. - -If you dislike AUCTeX automatically modifying your files, you can set -this variable to \"<none>\"." - :group 'TeX-command - :type 'regexp) - -;; Can be let-bound temporarily in order to inhibit the master file question -;; by using its value instead in case `TeX-master' is nil or 'shared. -(defvar TeX-transient-master nil) - -(defun TeX-dwim-master () - "Find a likely `TeX-master'." - (let ((dir default-directory)) - (cl-loop for buf in (buffer-list) - until - (when (with-current-buffer buf - (and (equal dir default-directory) - (stringp TeX-master))) - (cl-return (with-current-buffer buf TeX-master)))))) - -(defun TeX-master-file-ask () - "Ask for master file, set `TeX-master' and add local variables." - (interactive) - (if (TeX-local-master-p) - (error "Master file already set") - (let* ((default (TeX-dwim-master)) - (name (or (and (eq 'dwim TeX-master) default) - (condition-case nil - (read-file-name (format "Master file (default %s): " - (or default "this file")) - nil default) - (quit "<quit>"))))) - (cond ((string= name "<quit>") - (setq TeX-master t)) - ((string= name default) - (setq TeX-master default) - (TeX-add-local-master)) - ((or - ;; Default `read-file-name' proposes and buffer visits a file. - (string= (expand-file-name name) (buffer-file-name)) - ;; Default of `read-file-name' and buffer does not visit a file. - (string= name default-directory) - ;; User typed <RET> in an empty minibuffer. - (string= name "")) - (setq TeX-master t) - (TeX-add-local-master)) - (t - (setq TeX-master (TeX-strip-extension (file-relative-name name) - (list TeX-default-extension) - 'path)) - (TeX-add-local-master)))))) - -(defun TeX-master-file (&optional extension nondirectory ask) - "Set and return the name of the master file for the current document. - -If optional argument EXTENSION is non-nil, add that file extension to -the name. Special value t means use `TeX-default-extension'. - -If optional second argument NONDIRECTORY is non-nil, do not include -the directory. - -If optional third argument ASK is non-nil, ask the user for the -name of master file if it cannot be determined otherwise." - (interactive) - (if (eq extension t) - (setq extension TeX-default-extension)) - (let ((my-name (if (buffer-file-name) - (TeX-strip-extension nil (list TeX-default-extension) t) - "<none>"))) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (cond - ((and TeX-transient-master - (or (not TeX-master) (eq TeX-master 'shared))) - (setq TeX-master TeX-transient-master)) - ;; Special value 't means it is own master (a free file). - ((equal TeX-master my-name) - (setq TeX-master t)) - - ;; For files shared between many documents. - ((and (eq 'shared TeX-master) ask) - (setq TeX-master - (let* ((default (TeX-dwim-master)) - (name (read-file-name - (format "Master file (default %s): " - (or default "this file")) - nil default))) - (cond ((string= name default) - default) - ((or - ;; Default `read-file-name' proposes and - ;; buffer visits a file. - (string= (expand-file-name name) - (buffer-file-name)) - ;; Default of `read-file-name' and - ;; buffer does not visit a file. - (string= name default-directory) - ;; User typed <RET> in an empty minibuffer. - (string= name "")) - t) - (t - (TeX-strip-extension - name (list TeX-default-extension) 'path)))))) - - ;; We might already know the name. - ((or (eq TeX-master t) (stringp TeX-master)) TeX-master) - - ;; Ask the user (but add it as a local variable). - (ask (TeX-master-file-ask))))) - - (let ((name (if (stringp TeX-master) - TeX-master - my-name))) - - (if (TeX-match-extension name) - ;; If it already has an extension... - (if (equal extension TeX-default-extension) - ;; Use instead of the default extension - (setq extension nil) - ;; Otherwise drop it. - (setq name (TeX-strip-extension name)))) - - (let* ((reg (TeX--clean-extensions-regexp t)) - (is-output-ext (and reg - (or (string-match-p reg (concat "." extension)) - (string= "prv" extension)))) - (output-dir (and is-output-ext - (TeX--master-output-dir - (file-name-directory name) - nondirectory)))) - (if output-dir - (setq name (concat output-dir (file-name-nondirectory name))) - ;; Remove directory if needed. - (if nondirectory - (setq name (file-name-nondirectory name))))) - (if extension - (concat name "." extension) - name)))) - -(defun TeX-master-directory () - "Directory of master file." - (file-name-as-directory - (abbreviate-file-name - (substitute-in-file-name - (expand-file-name - (let ((dir (file-name-directory (TeX-master-file)))) - (if dir (directory-file-name dir) ".")) - (and buffer-file-name - (file-name-directory buffer-file-name))))))) - -(defun TeX-add-local-master () - "Add local variable for `TeX-master'. - -Get `major-mode' from master file and enable it." - (when (and (buffer-file-name) - (string-match TeX-one-master - (file-name-nondirectory (buffer-file-name))) - (not buffer-read-only)) - (goto-char (point-max)) - (if (re-search-backward "^\\([^\n]+\\)Local Variables:" - (- (point-max) 3000) t) - (let ((prefix (TeX-match-buffer 1))) - (re-search-forward (regexp-quote (concat prefix - "End:"))) - (beginning-of-line 1) - (insert prefix "TeX-master: " (prin1-to-string TeX-master) "\n")) - (let* ((mode (if (stringp TeX-master) - (with-current-buffer - (find-file-noselect - (TeX-master-file TeX-default-extension)) - major-mode) - major-mode)) - (comment-prefix (cond ((eq mode 'texinfo-mode) "@c ") - ((eq mode 'doctex-mode) "% ") - (t "%%% "))) - (mode-string (concat (and (boundp 'japanese-TeX-mode) japanese-TeX-mode - "japanese-") - (substring (symbol-name mode) 0 -5)))) - (newline) - (when (eq major-mode 'doctex-mode) - (insert comment-prefix TeX-esc "endinput\n")) - (insert - comment-prefix "Local Variables:\n" - comment-prefix "mode: " mode-string "\n" - comment-prefix "TeX-master: " (prin1-to-string TeX-master) "\n" - comment-prefix "End:\n") - (unless (eq mode major-mode) - (funcall mode) - ;; TeX modes run `VirTeX-common-initialization' which kills all local - ;; variables, thus `TeX-master' will be forgotten after `(funcall - ;; mode)'. Reparse local variables in order to bring it back. - (hack-local-variables)))))) - -(defun TeX-local-master-p () - "Return non-nil if there is a `TeX-master' entry in local variables spec. -Return nil otherwise." - (assq 'TeX-master file-local-variables-alist)) - -;;; Style Paths - -(defcustom TeX-style-global (expand-file-name "style" TeX-data-directory) - "Directory containing hand generated TeX information. - -These correspond to TeX macros shared by all users of a site." - :group 'TeX-file - :type 'directory) - -(defcustom TeX-auto-local "auto" - "Directory containing automatically generated TeX information. - -This correspond to TeX macros found in the current directory, and must -be relative to that." - :group 'TeX-file - :type 'string) - -(defcustom TeX-output-dir nil - "The path of the directory where output files should be placed. - -A relative path is interpreted as being relative to the master -file in `TeX-master'. The path cannot contain a directory that -starts with '.'. If this variable is nil, the output directory -is assumed to be the same as the directory of `TeX-master'." - :group 'TeX-file - :safe #'string-or-null-p - :type '(choice (const :tag "Directory of master file" nil) - (string :tag "Custom" "build"))) -(make-variable-buffer-local 'TeX-output-dir) - -(defun TeX--master-output-dir (master-dir relative-to-master &optional ensure) - "Return the directory path where output files should be placed. -If `TeX-output-dir' is nil, then return nil. - -MASTER-DIR is the directory path where the master file is -located. If RELATIVE-TO-MASTER is non-nil, make the returned -path relative to the directory in MASTER-DIR. If ENSURE is -non-nil, the output directory is created if it does not exist." - (when TeX-output-dir - (let* ((master-dir (expand-file-name (or master-dir ""))) - (out-dir (file-name-as-directory - (abbreviate-file-name - (substitute-in-file-name - (expand-file-name - TeX-output-dir - master-dir)))))) - ;; Make sure the directory exists - (unless (or (not ensure) (file-exists-p out-dir)) - (make-directory (file-name-as-directory out-dir) t)) - (if relative-to-master - (file-relative-name out-dir master-dir) - out-dir)))) - -(defun TeX--output-dir-arg (argname) - "Format the output directory as a command argument. -ARGNAME is prepended to the quoted output directory. If -`TeX-output-dir' is nil then return an empty string." - (let ((out-dir (TeX--master-output-dir (TeX-master-directory) t t))) - (if out-dir - (concat argname "\"" out-dir "\"") - ""))) - -(defcustom TeX-style-local "style" - "Directory containing hand generated TeX information. - -These correspond to TeX macros found in the current directory, and must -be relative to that." - :group 'TeX-file - :type 'string) - -;; Compatibility alias -(defun TeX-split-string (regexp string) - (split-string string regexp)) -(make-obsolete 'TeX-split-string - "use (split-string STRING REGEXP) instead." "AUCTeX 13.0") - -(defun TeX-parse-path (env) - "Return a list if private TeX directories found in environment variable ENV." - (let* ((value (getenv env)) - (entries (and value - (split-string - value - (if (string-match ";" value) ";" ":")))) - (global (append '("/" "\\") - (mapcar #'file-name-as-directory - TeX-macro-global))) - entry - answers) - (while entries - (setq entry (car entries)) - (setq entries (cdr entries)) - (setq entry (file-name-as-directory - (if (string-match "/?/?\\'" entry) - (substring entry 0 (match-beginning 0)) - entry))) - (or (not (file-name-absolute-p entry)) - (member entry global) - (setq answers (cons entry answers)))) - answers)) - -(defun TeX-kpathsea-detect-path-delimiter () - "Auto detect the path delimiter for kpsewhich command. -Usually return \":\" or \";\". If auto detect fails for some reason, -return nil." - (let ((res (ignore-errors - (with-output-to-string - (call-process "kpsewhich" nil - (list standard-output nil) nil - "--expand-path" "{.,..}"))))) - ;; kpsewhich expands "{.,..}" to ".:SOMEDIR" or ".;SOMEDIR" - ;; according to its environment. - ;; Don't use "{.,.}" instead because kpsewhich of MiKTeX 2.9 - ;; simplifies it to just a ".", not ".;.". - (and (stringp res) (> (length res) 0) - ;; Check whether ; is contained. This should work even if - ;; some implementation of kpsewhich considers it sane to - ;; insert drive letters or directory separators or whatever - ;; else to the current directory. - (if (string-match ";" res) ";" ":")))) - -(defcustom TeX-kpathsea-path-delimiter - (TeX-kpathsea-detect-path-delimiter) - "Path delimiter for kpathsea output. -t means autodetect, nil means kpathsea is disabled." - :group 'TeX-file - :type '(choice (const ":") - (const ";") - (const :tag "Autodetect" t) - (const :tag "Off" nil))) - -(defun TeX-tree-expand (vars program &optional subdirs) - "Return directories corresponding to the kpathsea variables VARS. -This is done calling `kpsewhich --expand-path' for the variables. -PROGRAM if non-nil is passed as the parameter for --progname. -Optional argument SUBDIRS are subdirectories which are appended -to the directories of the TeX trees. Only existing directories -are returned." - ;; FIXME: The GNU convention only uses "path" to mean "list of directories" - ;; and uses "filename" for the name of a file even if it contains possibly - ;; several elements separated by "/". - (if (eq TeX-kpathsea-path-delimiter t) - (setq TeX-kpathsea-path-delimiter - (TeX-kpathsea-detect-path-delimiter))) - (when TeX-kpathsea-path-delimiter - (let* ((exit-status 1) - (args `(,@(if program `("--progname" ,program)) - "--expand-path" - ,(mapconcat #'identity vars - TeX-kpathsea-path-delimiter))) - (path-list (ignore-errors - (with-output-to-string - (setq exit-status - (apply #'call-process - "kpsewhich" nil - (list standard-output nil) nil - args)))))) - (if (not (zerop exit-status)) - ;; kpsewhich is not available. Disable subsequent usage. - (setq TeX-kpathsea-path-delimiter nil) - (let ((separators (format "[\n\r%s]" TeX-kpathsea-path-delimiter)) - path input-dir-list) - (dolist (item (split-string path-list separators t)) - (if subdirs - (dolist (subdir subdirs) - (setq path (file-name-as-directory (concat item subdir))) - (when (file-exists-p path) - (cl-pushnew path input-dir-list :test #'equal))) - (setq path (file-name-as-directory item)) - (when (file-exists-p path) - (cl-pushnew path input-dir-list :test #'equal)))) - ;; No duplication in result is assured since `cl-pushnew' is - ;; used above. Should we introduce an option for speed just - ;; to accumulate all the results without care for - ;; duplicates? - (nreverse input-dir-list)))))) - -(defun TeX-macro-global () - "Return directories containing the site's TeX macro and style files." - (or (TeX-tree-expand '("$SYSTEXMF" "$TEXMFLOCAL" "$TEXMFMAIN" "$TEXMFDIST") - "latex" '("/tex/" "/bibtex/bst/")) - '("/usr/share/texmf/tex/" "/usr/share/texmf/bibtex/bst/"))) - -(defun TeX-macro-private () - "Return directories containing the user's TeX macro and style files." - (TeX-tree-expand '("$TEXMFHOME") "latex" '("/tex/" "/bibtex/bst/"))) - -(defcustom TeX-macro-global (TeX-macro-global) - "Directories containing the site's TeX macro and style files." - :group 'TeX-file - :type '(repeat (directory :format "%v"))) - -(defcustom TeX-macro-private (or (append (TeX-parse-path "TEXINPUTS") - (TeX-parse-path "BIBINPUTS")) - (TeX-macro-private)) - "Directories where you store your personal TeX macros." - :group 'TeX-file - :type '(repeat (file :format "%v"))) - -(defcustom TeX-auto-private - (list (expand-file-name TeX-auto-local - (or (concat user-emacs-directory "auctex/") - "~/.emacs.d/auctex/"))) - "List of directories containing automatically generated AUCTeX style files. - -These correspond to the personal TeX macros." - :group 'TeX-file - :type '(repeat (file :format "%v"))) - -(if (stringp TeX-auto-private) ;Backward compatibility - (setq TeX-auto-private (list TeX-auto-private))) - -(defcustom TeX-style-private - (list (expand-file-name TeX-style-local - (or (concat user-emacs-directory "auctex/") - "~/.emacs.d/auctex/"))) - "List of directories containing hand-generated AUCTeX style files. - -These correspond to the personal TeX macros." - :group 'TeX-file - :type '(repeat (file :format "%v"))) - -(if (stringp TeX-style-private) ;Backward compatibility - (setq TeX-style-private (list TeX-style-private))) - -(defcustom TeX-style-path - (let ((path)) - ;; Put directories in an order where the more local files can - ;; override the more global ones. - (mapc (lambda (file) - (when (and file (not (member file path))) - (setq path (cons file path)))) - (append (list TeX-auto-global TeX-style-global) - TeX-auto-private TeX-style-private - (list TeX-auto-local TeX-style-local))) - (nreverse path)) - "List of directories to search for AUCTeX style files. -Per default the list is built from the values of the variables -`TeX-auto-global', `TeX-style-global', `TeX-auto-private', -`TeX-style-private', `TeX-auto-local', and `TeX-style-local'." - :group 'TeX-file - :type '(repeat (file :format "%v"))) - -(defcustom TeX-check-path - (append (list ".") TeX-macro-private TeX-macro-global) - "Directory path to search for dependencies. - -If nil, just check the current file. -Used when checking if any files have changed." - :group 'TeX-file - :type '(repeat (file :format "%v"))) - -;;; Style Files - -(define-obsolete-variable-alias 'LaTeX-dialect 'TeX-dialect "13.0") -(defconst TeX-dialect :latex - "Default dialect for use with function `TeX-add-style-hook' for -argument DIALECT-EXPR when the hook is to be run only on LaTeX -file, or any mode derived thereof. See variable -`TeX-style-hook-dialect'." ) - -(defvar TeX-style-hook-list nil - "List of TeX style hooks currently loaded. - -Each entry is a list: - - (STYLE HOOK1 HOOK2 ...) - -where the first element STYLE is the name of the style, and the -remaining elements HOOKN, if any, are hooks to be run when that -style is active. - -A hook HOOKN may be a hook function HOOK-FUN to be run in -all TeX dialects (LaTeX, Texinfo, etc.), or a vector like: - - [TeX-style-hook HOOK-FUN DIALECT-SET] - -where HOOK-FUN is the hook function to be run, and DIALECT-SET is -a non-empty set of dialects in which the hook function may be -run. - -This set is instantiated by function `TeX-add-style-hook' through -functions manipulating style hook dialect expression named with a -`TeX-shdex-' prefix. - -For supported dialects, see variables `TeX-style-hook-dialect'.") - -(defvar TeX-style-hook-dialect :latex - "Dialect for running hooks locally to the considered file. -Supported values are described below: - -* `:bibtex' for files in BibTeX mode. -* `:context' for files in ConTeXt mode. -* `:latex' for files in LaTeX mode, or any mode derived - thereof. -* `:plain-tex' for files in plain-TeX mode. -* `:texinfo' for Texinfo files. -* `:classopt' for class options of LaTeX document. Just - considered as a pseudo-dialect. - -Purpose is notably to prevent non-Texinfo hooks to be run in -Texinfo files, due to ambiguous style name, as this may cause bad -side effect for example on variable `TeX-font-list'.") - -(defcustom TeX-byte-compile nil - "Not nil means try to byte compile auto files before loading." - :group 'TeX-parse - :type 'boolean) - -(defun TeX-bibtex-set-BibTeX-dialect () - "Set `TeX-style-hook-dialect' to `:bibtex' locally to BibTeX buffers." - (set (make-local-variable 'TeX-style-hook-dialect) :bibtex)) - -(defun TeX-load-style (style) - "Search for and load each definition for STYLE in `TeX-style-path'." - (cond ((assoc style TeX-style-hook-list)) ; We already found it - ((string-match "\\`\\(.+[/\\]\\)\\([^/\\]*\\)\\'" style) ;Complex path - (let* ((dir (substring style (match-beginning 1) (match-end 1))) - (style (substring style (match-beginning 2) (match-end 2))) - (master-dir (if (stringp TeX-master) - (file-name-directory - (file-relative-name TeX-master)) - "./")) - (TeX-style-path (append (list (expand-file-name - TeX-auto-local dir) - (expand-file-name - TeX-auto-local master-dir) - (expand-file-name - TeX-style-local dir) - (expand-file-name - TeX-style-local master-dir)) - TeX-style-path))) - (TeX-load-style style))) - (t ;Relative path - ;; Insert empty list to mark the fact that we have searched. - (setq TeX-style-hook-list (cons (list style) TeX-style-hook-list)) - ;; Now check each element of the path - (dolist (name TeX-style-path) - (TeX-load-style-file (expand-file-name style name)))))) - -(defun TeX-load-style-file (file) - "Load FILE checking for a Lisp extensions." - (let ((el (concat file ".el")) - (elc (concat file ".elc"))) - (cond ((file-newer-than-file-p el elc) - (if (file-readable-p el) - (if (and TeX-byte-compile - (file-writable-p elc) - (save-excursion - ;; `byte-compile-file' switches buffer in Emacs 20.3. - (byte-compile-file el)) - (file-readable-p elc)) - (load-file elc) - (load-file el)))) - ((file-readable-p elc) - (load-file elc)) - ((file-readable-p el) - (load-file el))))) - -(defconst TeX-style-hook-dialect-weight-alist - '((:latex . 1) (:texinfo . 2) (:bibtex . 4) (:plain-tex . 8) (:context . 16) - (:classopt . 32)) - "Association list to map dialects to binary weight, in order to -implement dialect sets as bitmaps." ) - -(defun TeX-shdex-eval (dialect-expr) - "Evaluate a style hook dialect expression DIALECT-EXPR." - (cond - ((symbolp dialect-expr) - (let ((cell (assq dialect-expr TeX-style-hook-dialect-weight-alist))) - (if cell (cdr cell) - (error "Invalid dialect expression : %S" dialect-expr)))) - ((and (consp dialect-expr) - (memq (car dialect-expr) '(or not and nor))) - (apply (intern - (concat "TeX-shdex-" (symbol-name (car dialect-expr)))) - (cdr dialect-expr))) - (t - (error "Invalid dialect expression : %S" dialect-expr)))) - -(defsubst TeX-shdex-or (&rest args) - "OR operator for style hook dialect expressions." - (apply #'logior (mapcar #'TeX-shdex-eval args))) - -(defsubst TeX-shdex-and (&rest args) - "AND operator for style hook dialect expressions." - (apply #'logand (mapcar #'TeX-shdex-eval args))) - -(defsubst TeX-shdex-nor (&rest args) - "NOR operator for style hook dialect expressions." - (lognot (apply #'TeX-shdex-or args))) - -(defsubst TeX-shdex-not (arg) - "NOT operator for style hook dialect expressions." - (lognot (TeX-shdex-eval arg))) - -(defsubst TeX-shdex-in-p (dialect dialect-set) - "Test whether dialect DIALECT is in dialect set DIALECT-SET." - (let ((cell (assq dialect TeX-style-hook-dialect-weight-alist))) - (if cell - (/= 0 (logand (cdr cell) dialect-set)) - (error "Invalid dialect %S" dialect)))) - -(defsubst TeX-shdex-listify (dialect-set) - "Converts a dialect set DIALECT-SET to a list of all dialect -comprised in this set, where dialects are symbols" - (let (ret) - (dolist (c dialect-set) - (when (/= 0 (logand (cdr c) dialect-set)) - (push (car c) ret))) - ret)) - -(defun TeX-add-style-hook (style hook &optional dialect-expr) - "Give STYLE yet another HOOK to run. - -DIALECT-EXPR serves the purpose of marking the hook to be run only in -that dicontext. - -DIALECT-EXPR may be a single symbol defining the dialect, see -variable `TeX-style-hook-dialect' for supported dialects. - -DIALECT-EXPR can also be an expression like one of the following: - -* (or DIALECT1 DIALECT2 ...) -* (nor DIALECT1 DIALECT2 ...) -* (and DIALECT1 DIALECT2 ...) -* (not DIALECT ) - -When omitted DIALECT-EXPR is equivalent to `(nor )', ie all -dialected are allowed." - (let ((entry (assoc-string style TeX-style-hook-list))) - (and dialect-expr (setq hook (vector 'TeX-style-hook hook - (TeX-shdex-eval dialect-expr)))) - (cond ((null entry) - ;; New style, add entry. - (setq TeX-style-hook-list (cons (list style hook) - TeX-style-hook-list))) - ((member hook entry) - ;; Old style, hook already there, do nothing. - nil) - (t - ;; Old style, new hook. - (setcdr entry (cons hook (cdr entry))))))) - -(defun TeX-keep-hooks-in-dialect (hooks dialect-list) - "Scan HOOKS for all hooks the associated dialect of which is -found in DIALECT-LIST and return the list thereof." - (let (ret dialect-list-1) - (dolist (hook hooks) - (setq dialect-list-1 (and (vectorp hook) (eq (aref hook 0) 'TeX-style-hook) - (TeX-shdex-listify (aref hook 2)))) - (while dialect-list-1 - (when (memq (pop dialect-list-1) dialect-list) - (push hook ret) - (setq dialect-list-1 nil))) - ret))) - -(defun TeX-unload-style (style &optional dialect-list) - "Forget that we once loaded STYLE. If DIALECT-LIST is provided -the STYLE is only removed for those dialects in DIALECT-LIST. - -See variable `TeX-style-hook-dialect' for supported dialects." - (let ((style-data (assoc-string style TeX-style-hook-list))) - (if style-data - (let ((hooks (and dialect-list (TeX-keep-hooks-in-dialect (cdr style-data) dialect-list)))) - (if hooks - (setcdr style-data hooks) - (setq TeX-style-hook-list (delq style-data TeX-style-hook-list))))))) - -(defcustom TeX-virgin-style (if (and TeX-auto-global - (file-directory-p TeX-auto-global)) - "virtex" - "NoVirtexSymbols") - "Style all documents use." - :group 'TeX-parse - :type 'string) - -(defvar TeX-active-styles nil - "List of styles currently active in the document.") - (make-variable-buffer-local 'TeX-active-styles) - -(defun TeX-run-style-hooks (&rest styles) - "Run the TeX style hooks STYLES." - (mapcar (lambda (style) - ;; Avoid recursion. - (unless (TeX-member style TeX-active-styles #'string-equal) - (setq TeX-active-styles - (cons style TeX-active-styles)) - (TeX-load-style style) - (let ((default-directory default-directory)) - ;; Complex path. - (when (string-match "\\`\\(.+[/\\]\\)\\([^/\\]*\\)\\'" style) - ;; Set `default-directory' to directory of master - ;; file since style files not stored in the fixed - ;; style directories are usually located there. - (setq default-directory (save-match-data - (TeX-master-directory)) - style (substring style - (match-beginning 2) (match-end 2)))) - (condition-case nil - (mapcar (lambda (hook) - (cond - ((functionp hook) - (funcall hook)) - ((and (vectorp hook) - (eq (aref hook 0) 'TeX-style-hook)) - (and (TeX-shdex-in-p TeX-style-hook-dialect (aref hook 2)) - (funcall (aref hook 1)))) - (t (error "Invalid style hook %S" hook)))) - ;; Reverse the list of style hooks in order to run - ;; styles in the order global, private, local - ;; (assuming TeX-style-path has that ordering, - ;; too). - (reverse (cdr-safe (assoc-string style TeX-style-hook-list)))) - ;; This happens in case some style added a new parser, and - ;; now the style isn't used anymore (user deleted - ;; \usepackage{style}). Then we're left over with, e.g., - ;; (LaTeX-add-siunitx-units "\\parsec"), but the function is - ;; defined in a style siunitx.el that's not loaded anymore. - (void-function nil))))) - styles)) - -(defcustom TeX-parse-self nil - "Parse file after loading it if no style hook is found for it." - :group 'TeX-parse - :type 'boolean) - -(defvar TeX-style-hook-applied-p nil - "Non-nil means the style specific hooks have been applied.") - (make-variable-buffer-local 'TeX-style-hook-applied-p) - -(defvar TeX-update-style-hook nil - "Hook run as soon as style specific hooks were applied.") - -(defun TeX-update-style (&optional force) - "Run style specific hooks for the current document. - -Only do this if it has not been done before, or if optional argument -FORCE is not nil." - (unless (or (eq major-mode 'bibtex-mode) ; Not a real TeX buffer - (and (not force) - TeX-style-hook-applied-p)) - (setq TeX-style-hook-applied-p t) - (message "Applying style hooks...") - (TeX-run-style-hooks (TeX-strip-extension nil nil t)) - ;; Run parent style hooks if it has a single parent that isn't itself. - (if (or (not (memq TeX-master '(nil t))) - (and (buffer-file-name) - (string-match TeX-one-master - (file-name-nondirectory (buffer-file-name))))) - (TeX-run-style-hooks (TeX-master-file))) - (if (and TeX-parse-self - (null (cdr-safe (assoc (TeX-strip-extension nil nil t) - TeX-style-hook-list)))) - (TeX-auto-apply)) - (run-hooks 'TeX-update-style-hook) - (message "Applying style hooks...done"))) - -(defvar TeX-remove-style-hook nil - "List of hooks to call when we remove the style specific information.") - -(defun TeX-remove-style () - "Remove all style specific information." - (setq TeX-style-hook-applied-p nil) - (run-hooks 'TeX-remove-style-hook) - (setq TeX-active-styles (list TeX-virgin-style))) - -(defun TeX-style-list () - "Return a list of all styles (subfiles) used by the current document." - (TeX-update-style) - TeX-active-styles) - -;;; Special Characters - -(defvar TeX-esc "\\" "The TeX escape character.") - (make-variable-buffer-local 'TeX-esc) - -(defvar TeX-grop "{" "The TeX group opening character.") - (make-variable-buffer-local 'TeX-grop) - -(defvar TeX-grcl "}" "The TeX group closing character.") - (make-variable-buffer-local 'TeX-grcl) - -;;; Symbols - -;; Must be before keymaps. - -(defgroup TeX-macro nil - "Support for TeX macros in AUCTeX." - :prefix "TeX-" - :group 'AUCTeX) - -(defcustom TeX-complete-word #'ispell-complete-word - "Function to call for completing non-macros in `tex-mode'." - :type 'function - :group 'TeX-macro) - -(defcustom TeX-complete-expert-commands nil - "Complete macros and environments marked as expert commands. - -Possible values are nil, t, or a list of style names. - - - nil Don't complete expert commands (default). - - t Always complete expert commands. - - (STYLES ...) Only complete expert commands of STYLES." - :group 'TeX-macro - :type '(choice (const :tag "Don't complete expert commands" nil) - (const :tag "Always complete expert commands" t) - (repeat :tag "Complete expert commands of certain styles" string))) - -(defmacro TeX-complete-make-expert-command-functions (thing list-var prefix) - (let* ((plural (concat thing "s")) - (upcase-plural (upcase plural)) - (table-var (intern (format "%s-expert-%s-table" prefix thing)))) - `(progn - (defvar ,table-var - (make-hash-table :test #'equal) - ,(format "A hash-table mapping %s names to the style name providing it. - -A %s occuring in this table is considered an expert %s and -treated specially in the completion." thing thing thing)) - - (defun ,(intern (format "%s-declare-expert-%s" prefix plural)) (style &rest ,(intern plural)) - ,(format "Declare %s as expert %s of STYLE. - -Expert %s are completed depending on `TeX-complete-expert-commands'." - upcase-plural plural plural) - (dolist (x ,(intern plural)) - (if (null style) - (remhash x ,table-var) - (puthash x style ,table-var)))) - - (defun ,(intern (format "%s-filtered" list-var)) () - ,(format "Filter (%s) depending on `TeX-complete-expert-commands'." - list-var) - (delq nil - (mapcar - (lambda (entry) - (if (eq t TeX-complete-expert-commands) - entry - (let* ((cmd (car entry)) - (style (gethash cmd ,table-var))) - (when (or (null style) - (member style TeX-complete-expert-commands)) - entry)))) - (,list-var))))))) - -(TeX-complete-make-expert-command-functions "macro" TeX-symbol-list "TeX") -(TeX-complete-make-expert-command-functions "environment" LaTeX-environment-list "LaTeX") - -(defvar TeX-complete-list nil - "List of ways to complete the preceding text. - -Each entry is a list with the following elements: - -0. Regexp matching the preceding text or a predicate of arity 0 -which returns non-nil and sets `match-data' appropriately if it -is applicable. -1. A number indicating the subgroup in the regexp containing the -text. -2. A function returning an alist of possible completions. -3. Text to append after a succesful completion. - -Or alternatively: - -0. Regexp matching the preceding text. -1. Function to do the actual completion.") - -(defun TeX--complete-find-entry () - "Return the first applicable entry of `TeX-complete-list'." - (let ((list TeX-complete-list) - entry) - (while list - (setq entry (car list) - list (cdr list)) - (when (if (functionp (car entry)) - (funcall (car entry)) - (TeX-looking-at-backward (car entry) 250)) - (setq list nil))) - entry)) - -(defun TeX-complete-symbol () - "Perform completion on TeX/LaTeX symbol preceding point." - (interactive "*") - (let ((entry (TeX--complete-find-entry))) - (when entry - (if (numberp (nth 1 entry)) - (let* ((sub (nth 1 entry)) - (close (if (and (nth 3 entry) - (listp (nth 3 entry)) - (symbolp (car (nth 3 entry)))) - (eval (nth 3 entry) t) - (nth 3 entry))) - (begin (match-beginning sub)) - (end (match-end sub)) - (pattern (TeX-match-buffer 0)) - (symbol (buffer-substring begin end)) - (list (funcall (nth 2 entry))) - (completion (try-completion symbol list)) - (buf-name "*Completions*")) - (cond ((eq completion t) - (and close - (not (looking-at (regexp-quote close))) - (insert close)) - (let ((window (get-buffer-window buf-name))) - (when window (delete-window window)))) - ((null completion) - (error "Can't find completion for \"%s\"" pattern)) - ((not (string-equal symbol completion)) - (delete-region begin end) - (insert completion) - (and close - (eq (try-completion completion list) t) - (not (looking-at (regexp-quote close))) - (insert close)) - (let ((window (get-buffer-window buf-name))) - (when window (delete-window window)))) - (t - (completion-in-region begin end - (all-completions symbol list nil))))) - (funcall (nth 1 entry)))))) - -(defun TeX--completion-annotation-from-tex--prettify-symbols-alist (sym) - (when (boundp 'tex--prettify-symbols-alist) - (let ((ann (cdr (assoc (concat "\\" sym) - tex--prettify-symbols-alist)))) - (when ann - (concat " " (char-to-string ann)))))) - -(declare-function LaTeX--completion-annotation-from-math-menu - "latex" (sym)) - -(defun TeX--completion-annotation-function (sym) - "Annotation function for symbol/macro completion. -Used as `:annotation-function' in `completion-extra-properties'." - (or (TeX--completion-annotation-from-tex--prettify-symbols-alist sym) - (and (fboundp #'LaTeX--completion-annotation-from-math-menu) - (LaTeX--completion-annotation-from-math-menu sym)))) - -(defun TeX--completion-at-point () - "(La)TeX completion at point function. -See `completion-at-point-functions'." - (let ((entry (TeX--complete-find-entry))) - (when entry - (if (numberp (nth 1 entry)) - (let* ((sub (nth 1 entry)) - (begin (match-beginning sub)) - (end (match-end sub)) - (symbol (buffer-substring-no-properties begin end)) - (list (funcall (nth 2 entry)))) - (list begin end (all-completions symbol list) - :annotation-function - #'TeX--completion-annotation-function)) - ;; We intentionally don't call the fallback completion functions because - ;; they do completion on their own and don't work too well with things - ;; like company-mode. And the default function `ispell-complete-word' - ;; isn't so useful anyway. - nil)))) - -(defcustom TeX-default-macro "ref" - "The default macro when creating new ones with `TeX-insert-macro'." - :group 'TeX-macro - :type 'string) - -(make-variable-buffer-local 'TeX-default-macro) - -(defcustom TeX-insert-braces t - "If non-nil, append a empty pair of braces after inserting a macro. - -See also `TeX-insert-braces-alist'." - :group 'TeX-macro - :type 'boolean) - -(defcustom TeX-insert-braces-alist nil - "Alist of macros to which braces should or should not be appended. - -Each element is a cons cell, whose CAR is the macro name, and the -CDR is non-nil or nil, depending on whether a pair of braces -should be, respectively, appended or not to the macro. - -If a macro has an element in this variable, `TeX-parse-macro' -will use its value to decide what to do, whatever the value of -the variable `TeX-insert-braces'." - :group 'TeX-macro - :type '(repeat (cons (string :tag "Macro name") - (boolean :tag "Append braces?")))) -(make-variable-buffer-local 'TeX-insert-braces-alist) - -(defcustom TeX-insert-macro-default-style 'show-optional-args - "Specifies whether `TeX-insert-macro' will ask for all optional arguments. - -If set to the symbol `show-optional-args', `TeX-insert-macro' -asks for optional arguments of TeX marcos, unless the previous -optional argument has been rejected. If set to -`show-all-optional-args', `TeX-insert-macro' asks for all -optional arguments. If set to `mandatory-args-only', -`TeX-insert-macro' asks only for mandatory argument. - -When `TeX-insert-macro' is called with \\[universal-argument], it's the other -way round. - -Note that for some macros, there are special mechanisms, see for example -`LaTeX-includegraphics-options-alist' and `TeX-arg-cite-note-p'." - :group 'TeX-macro - :type '(choice (const mandatory-args-only) - (const show-optional-args) - (const show-all-optional-args))) - -(defvar TeX-arg-opening-brace nil - "String used as an opening brace for argument insertion. -The variable will be temporarily let-bound with the necessary value.") - -(defvar TeX-arg-closing-brace nil - "String used as a closing brace for argument insertion. -The variable will be temporarily let-bound with the necessary value.") - -(defvar TeX-after-insert-macro-hook nil - "A hook run after `TeX-insert-macro'.") - -(defvar TeX-macro-history nil) - -(defun TeX--symbol-completion-table () - (completion-table-dynamic - (lambda (_str) - (TeX-symbol-list-filtered)) - t)) - -(defun TeX-insert-macro (symbol) - "Insert TeX macro SYMBOL with completion. - -AUCTeX knows of some macros and may query for extra arguments, depending on -the value of `TeX-insert-macro-default-style' and whether `TeX-insert-macro' -is called with \\[universal-argument]." - ;; When called with a prefix (C-u), only ask for mandatory arguments, - ;; i.e. all optional arguments are skipped. See `TeX-parse-arguments' for - ;; details. Note that this behavior may be changed in favor of a more - ;; flexible solution in the future, therefore we don't document it at the - ;; moment. - (interactive (list - (let ((completion-extra-properties - (list :annotation-function - #'TeX--completion-annotation-function))) - (completing-read (concat "Macro (default " - TeX-default-macro - "): " - TeX-esc) - (TeX--symbol-completion-table) nil nil nil - 'TeX-macro-history TeX-default-macro)))) - (when (called-interactively-p 'any) - (setq TeX-default-macro symbol)) - (TeX-parse-macro symbol (cdr-safe (assoc symbol (TeX-symbol-list)))) - (run-hooks 'TeX-after-insert-macro-hook)) - -(defvar TeX-electric-macro-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map minibuffer-local-completion-map) - (define-key map " " #'minibuffer-complete-and-exit) - map)) - -(defun TeX-electric-macro () - "Insert TeX macro with completion. - -AUCTeX knows of some macros, and may query for extra arguments. -Space will complete and exit." - (interactive) - (cond ((eq (preceding-char) last-command-event) - (call-interactively #'self-insert-command)) - ((eq (preceding-char) ?.) - (let ((TeX-default-macro " ") - (minibuffer-local-completion-map TeX-electric-macro-map)) - (call-interactively #'TeX-insert-macro))) - (t - (let ((minibuffer-local-completion-map TeX-electric-macro-map)) - (call-interactively #'TeX-insert-macro))))) - -(defvar TeX-exit-mark nil - "Dynamically bound by `TeX-parse-macro' and `LaTeX-env-args'.") - -(defun TeX-parse-macro (symbol args) - "How to parse TeX macros which takes one or more arguments. - -First argument SYMBOL is the name of the macro. - -If ARGS is nil, insert macro with point inside braces. -Otherwise, each element in ARGS should match an argument to the -TeX macro. What is done depend on the type of the element: - - string: Use the string as a prompt to prompt for the argument. - - number: Insert that many braces, leave point inside the first. - - nil: Insert empty braces. - - t: Insert empty braces, leave point between the braces. - - other symbols: Call the symbol as a function. You can define - your own hook, or use one of the predefined argument hooks. If - you add new hooks, you can assume that point is placed directly - after the previous argument, or after the macro name if this is - the first argument. Please leave point located after the - argument you are inserting. If you want point to be located - somewhere else after all hooks have been processed, set the - value of `TeX-exit-mark'. It will point nowhere, until the - argument hook set it. By convention, these hooks all start - with `TeX-arg-'. - - list: If the car is a string, insert it as a prompt and the next - element as initial input. Otherwise, call the car of the list - with the remaining elements as arguments. - - vector: Optional argument. If it has more than one element, - parse it as a list, otherwise parse the only element as above. - Use square brackets instead of curly braces, and is not inserted - on empty user input." - (let ((TeX-grop (if (and (or (atom args) (= (length args) 1)) - (fboundp 'LaTeX-verbatim-macros-with-delims) - (member symbol (LaTeX-verbatim-macros-with-delims))) - LaTeX-default-verb-delimiter - TeX-grop)) - (TeX-grcl (if (and (or (atom args) (= (length args) 1)) - (fboundp 'LaTeX-verbatim-macros-with-delims) - (member symbol (LaTeX-verbatim-macros-with-delims))) - LaTeX-default-verb-delimiter - TeX-grcl))) - (if (and (TeX-active-mark) - (> (point) (mark))) - (exchange-point-and-mark)) - (insert TeX-esc symbol) - (let ((TeX-exit-mark (make-marker)) - (position (point))) - (TeX-parse-arguments args) - (cond ((marker-position TeX-exit-mark) - (goto-char (marker-position TeX-exit-mark)) - (set-marker TeX-exit-mark nil)) - ((let ((element (assoc symbol TeX-insert-braces-alist))) - ;; If in `TeX-insert-braces-alist' there is an element associated - ;; to the current macro, use its value to decide whether inserting - ;; a pair of braces, otherwise use the standard criterion. - (if element - (cdr element) - (and TeX-insert-braces - ;; Do not add braces if the argument is 0 or -1. - (not (and (= (safe-length args) 1) - (numberp (car args)) - (<= (car args) 0))) - (equal position (point)) - (string-match "[a-zA-Z]+" symbol)))) - (if (texmathp) - (when (TeX-active-mark) - (insert TeX-grop) - (exchange-point-and-mark) - (insert TeX-grcl)) - (insert TeX-grop) - (if (TeX-active-mark) - (progn - (exchange-point-and-mark) - (insert TeX-grcl)) - (insert TeX-grcl) - (backward-char)))))))) - -(defun TeX-arg-string (optional &optional prompt initial-input) - "Prompt for a string. - -If OPTIONAL is not nil then the PROMPT will start with ``(Optional) ''. -INITIAL-INPUT is a string to insert before reading input." - (TeX-argument-insert - (if (and (not optional) (TeX-active-mark)) - (let ((TeX-argument (buffer-substring (point) (mark)))) - (delete-region (point) (mark)) - TeX-argument) - (TeX-read-string (TeX-argument-prompt optional prompt "Text") initial-input)) - optional)) - -(defvar TeX-last-optional-rejected nil - "Dynamically bound by `TeX-parse-arguments'.") - -(defun TeX-parse-arguments (args) - "Parse TeX macro arguments ARGS. - -See `TeX-parse-macro' for details." - (let ((TeX-last-optional-rejected nil)) - (while args - (if (vectorp (car args)) - ;; Maybe get rid of all optional arguments. See `TeX-insert-macro' - ;; for more comments. See `TeX-insert-macro-default-style'. - ;; The macro `LaTeX-check-insert-macro-default-style' in - ;; `latex.el' uses the code inside (unless ...) This macro - ;; should be adapted if the code here changs. - (unless (if (eq TeX-insert-macro-default-style 'show-all-optional-args) - (equal current-prefix-arg '(4)) - (or - (and (eq TeX-insert-macro-default-style 'show-optional-args) - (equal current-prefix-arg '(4))) - (and (eq TeX-insert-macro-default-style 'mandatory-args-only) - (null (equal current-prefix-arg '(4)))) - TeX-last-optional-rejected)) - (let ((TeX-arg-opening-brace LaTeX-optop) - (TeX-arg-closing-brace LaTeX-optcl)) - (TeX-parse-argument t (if (equal (length (car args)) 1) - (aref (car args) 0) - (append (car args) nil))))) - (let ((TeX-arg-opening-brace TeX-grop) - (TeX-arg-closing-brace TeX-grcl)) - (setq TeX-last-optional-rejected nil) - (TeX-parse-argument nil (car args)))) - (setq args (cdr args))))) - -(defun TeX-parse-argument (optional arg) - "Depending on OPTIONAL, insert TeX macro argument ARG. -If OPTIONAL is set, only insert if there is anything to insert, and -then use square brackets instead of curly braces. - -See `TeX-parse-macro' for details." - (let (insert-flag) - (cond ((stringp arg) - (TeX-arg-string optional arg) - (setq insert-flag t)) - ((numberp arg) - (cond ((< arg 0) - (when (TeX-active-mark) - ;; Put both the macro and the marked region in a TeX group. - (let ((beg (min (point) (mark))) - (end (set-marker (make-marker) (max (point) (mark))))) - (insert " ") - (goto-char beg) - (skip-chars-backward "^\\\\") - (backward-char) - (insert TeX-arg-opening-brace) - (goto-char (marker-position end)) - (insert TeX-arg-closing-brace) - (setq insert-flag t) - (set-marker end nil)))) - ((= arg 0)) ; nop for clarity - ((> arg 0) - (TeX-parse-argument optional t) - (while (> arg 1) - (TeX-parse-argument optional nil) - (setq arg (- arg 1)))))) - ((null arg) - (insert TeX-arg-opening-brace) - (when (and (not optional) (TeX-active-mark)) - (exchange-point-and-mark)) - (insert TeX-arg-closing-brace) - (setq insert-flag t)) - ((eq arg t) - (insert TeX-arg-opening-brace) - (if (and (not optional) (TeX-active-mark)) - (progn - (exchange-point-and-mark)) - (set-marker TeX-exit-mark (point))) - (insert TeX-arg-closing-brace) - (setq insert-flag t)) - ((symbolp arg) - (funcall arg optional)) - ((listp arg) - (let ((head (car arg)) - (tail (cdr arg))) - (cond ((stringp head) - (apply #'TeX-arg-string optional arg)) - ((symbolp head) - (apply head optional tail)) - (t (error "Unknown list argument type %s" - (prin1-to-string head)))))) - (t (error "Unknown argument type %s" (prin1-to-string arg)))) - (when (and insert-flag (not optional) (TeX-active-mark)) - (deactivate-mark)))) - -(defun TeX-argument-insert (name optional &optional prefix) - "Insert NAME surrounded by curly braces. - -If OPTIONAL, only insert it if not empty, and then use square brackets. -If PREFIX is given, insert it before NAME." - (if (and optional (string-equal name "")) - (setq TeX-last-optional-rejected t) - (insert TeX-arg-opening-brace) - (if prefix - (insert prefix)) - (if (and (string-equal name "") - (null (marker-position TeX-exit-mark))) - (set-marker TeX-exit-mark (point)) - (insert name)) - (insert TeX-arg-closing-brace))) - -(defun TeX-argument-prompt (optional prompt default &optional complete) - "Return a argument prompt. - -If OPTIONAL is not nil then the prompt will start with ``(Optional) ''. - -PROMPT will be used if not nil, otherwise use DEFAULT. - -Unless optional argument COMPLETE is non-nil, ``: '' will be appended." - (concat (if optional "(Optional) " "") - (if prompt prompt default) - (if complete "" ": "))) - -(defun TeX-string-divide-number-unit (string) - "Divide number and unit in STRING and return a list (number unit)." - (if (string-match "[0-9]*\\.?[0-9]+" string) - (list (substring string 0 (string-match "[^.0-9]" string)) - (substring string (if (string-match "[^.0-9]" string) - (string-match "[^.0-9]" string) - (length string)))) - (list "" string))) - -(defcustom TeX-default-unit-for-image "cm" - "Default unit when prompting for an image size." - :group 'TeX-macro - :type '(choice (const "cm") - (const "in") - (const "\\linewidth") - (string :tag "Other"))) - -(defun TeX-arg-maybe (symbol list form) - "Evaluate FORM, if SYMBOL is an element of LIST." - (when (memq symbol list) - (eval form t))) - -(defun TeX-arg-free (optional &rest args) - "Parse its arguments but use no braces when they are inserted." - (let ((TeX-arg-opening-brace "") - (TeX-arg-closing-brace "")) - (if (equal (length args) 1) - (TeX-parse-argument optional (car args)) - (TeX-parse-argument optional args)))) - -(defun TeX-arg-literal (_optional &rest args) - "Insert its arguments ARGS into the buffer. -Used for specifying extra syntax for a macro. The compatibility -argument OPTIONAL is ignored." - (apply #'insert args)) - - -;;; Font Locking - -(defcustom TeX-install-font-lock #'font-latex-setup - "Function to call to install font lock support. -Choose `ignore' if you don't want AUCTeX to install support for font locking." - :group 'TeX-misc - :type '(radio (function-item font-latex-setup) - (function-item tex-font-setup) - (function-item ignore) - (function :tag "Other"))) - -;;; The Mode - -(defvar TeX-format-list - '(("JLATEX" japanese-latex-mode - "\\\\\\(documentstyle\\|documentclass\\)[^%\n]*{u?\\(j[s-]?\\|t\\)\ -\\(article\\|report\\|book\\|slides\\)") - ("JTEX" japanese-plain-tex-mode - "-- string likely in Japanese TeX --") - ("AMSTEX" ams-tex-mode - "\\\\document\\b") - ("CONTEXT" context-mode - "\\\\\\(start\\(text\\|tekst\\|proje[ck]t\\|proiect\\|\ -produ[ck]t\\|produs\\|environment\\|omgeving\\|umgebung\\|prostredi\\|mediu\\|\ -component\\|onderdeel\\|komponent[ea]\\|componenta\\)\ -\\|inizia\\(testo\\|progetto\\|prodotto\\|ambiente\\|componente\\)\ -\\)\\|%.*?interface=") - ("LATEX" latex-mode - "\\\\\\(begin\\|\\(?:sub\\)\\{0,2\\}section\\|chapter\\|documentstyle\\|\ -documentclass\\)\\b") - ("TEX" plain-tex-mode ".")) - "List of format packages to consider when choosing a TeX mode. - -A list with an entry for each format package available at the site. - -Each entry is a list with three elements. - -1. The name of the format package. -2. The name of the major mode. -3. A regexp typically matched in the beginning of the file. - -When entering `tex-mode', each regexp is tried in turn in order to find -the major mode to be used.") - -(defcustom TeX-default-mode #'latex-mode - "Mode to enter for a new file when it can't be determined otherwise." - :group 'TeX-misc - :type '(radio (function-item latex-mode) - (function-item plain-tex-mode) - (function :tag "Other"))) - -(defcustom TeX-force-default-mode nil - "If set to nil, try to infer the mode of the file from its content." - :group 'TeX-misc - :type 'boolean) - -;;;###autoload -(defun TeX-tex-mode () - "Major mode in AUCTeX for editing TeX or LaTeX files. -Tries to guess whether this file is for plain TeX or LaTeX. - -The algorithm is as follows: - - 1) if the file is empty or `TeX-force-default-mode' is not set to nil, - `TeX-default-mode' is chosen - 2) If \\documentstyle or \\begin{, \\section{, \\part{ or \\chapter{ is - found, `latex-mode' is selected. - 3) Otherwise, use `plain-tex-mode'" - (interactive) - - (funcall (if (or (equal (buffer-size) 0) - TeX-force-default-mode) - TeX-default-mode - (save-excursion - (goto-char (point-min)) - (let ((comment-start-skip ;Used by TeX-in-comment - (concat - "\\(\\(^\\|[^\\\n]\\)\\(" - (regexp-quote TeX-esc) - (regexp-quote TeX-esc) - "\\)*\\)\\(%+ *\\)")) - (entry TeX-format-list) - answer case-fold-search) - (while (and entry (not answer)) - (if (re-search-forward (nth 2 (car entry)) - 10000 t) - (if (not (TeX-in-comment)) - (setq answer (nth 1 (car entry)))) - (setq entry (cdr entry)))) - (if answer - answer - TeX-default-mode)))))) - -(defun TeX--prettify-symbols-compose-p (start end match) - (and (tex--prettify-symbols-compose-p start end match) - (not (let ((face (get-text-property end 'face))) - (if (consp face) - (memq 'font-latex-verbatim-face face) - (eq face 'font-latex-verbatim-face)))))) - -(defun VirTeX-common-initialization () - "Perform basic initialization." - (kill-all-local-variables) - (setq TeX-mode-p t) - (setq TeX-output-extension (if TeX-PDF-mode "pdf" "dvi")) - (setq indent-tabs-mode nil) - - ;; Ispell support - (set (make-local-variable 'ispell-parser) 'tex) - - ;; Redefine some standard variables - (make-local-variable 'paragraph-start) - (make-local-variable 'paragraph-separate) - (set (make-local-variable 'comment-start) "%") - (set (make-local-variable 'comment-start-skip) - (concat - "\\(\\(^\\|[^\\\n]\\)\\(" - (regexp-quote TeX-esc) - (regexp-quote TeX-esc) - "\\)*\\)\\(%+[ \t]*\\)")) - (set (make-local-variable 'comment-end-skip) "[ \t]*\\(\\s>\\|\n\\)") - (set (make-local-variable 'comment-use-syntax) t) - (set (make-local-variable 'comment-padding) " ") - ;; Removed as commenting in (La)TeX is done with one `%' not two - ;; (make-local-variable 'comment-add) - ;; (setq comment-add 1) ;default to `%%' in comment-region - (set (make-local-variable 'comment-indent-function) #'TeX-comment-indent) - (set (make-local-variable 'comment-multi-line) nil) - (make-local-variable 'compile-command) - (unless (boundp 'compile-command) - (setq compile-command "make")) - (set (make-local-variable 'words-include-escapes) nil) - - ;; Make TAB stand out - ;; (make-local-variable 'buffer-display-table) - ;; (setq buffer-display-table (if standard-display-table - ;; (copy-sequence standard-display-table) - ;; (make-display-table))) - ;; (aset buffer-display-table ?\t (apply 'vector (append "<TAB>" nil))) - - ;; Symbol completion. - (set (make-local-variable 'TeX-complete-list) - (list (list "\\\\\\([a-zA-Z]*\\)" - 1 'TeX-symbol-list-filtered - (if TeX-insert-braces "{}")) - (list "" TeX-complete-word))) - - (funcall TeX-install-font-lock) - - ;; We want this to be early in the list, so we do not add it before - ;; we enter TeX mode the first time. - (add-hook 'write-contents-functions #'TeX-safe-auto-write nil t) - - ;; Minor modes - (when TeX-source-correlate-mode - (TeX-source-correlate-mode 1)) - - ;; Prettify Symbols mode - (require 'tex-mode) - (setq-local prettify-symbols-alist tex--prettify-symbols-alist) - (add-function :override (local 'prettify-symbols-compose-predicate) - #'TeX--prettify-symbols-compose-p) - - ;; Standard Emacs completion-at-point support - (add-hook 'completion-at-point-functions - #'TeX--completion-at-point nil t) - - ;; Let `TeX-master-file' be called after a new file was opened and - ;; call `TeX-update-style' on any file opened. (The addition to the - ;; hook has to be made here because its local value will be deleted - ;; by `kill-all-local-variables' if it is added e.g. in `tex-mode'.) - ;; - ;; `TeX-update-style' has to be called before - ;; `global-font-lock-mode', which may also be specified in - ;; `find-file-hook', gets called. Otherwise style-based - ;; fontification will break (in XEmacs). That means, `add-hook' - ;; cannot be called with a non-nil value of the APPEND argument. - ;; - ;; `(TeX-master-file nil nil t)' has to be called *before* - ;; `TeX-update-style' as the latter will call `TeX-master-file' - ;; without the `ask' bit set. - (add-hook 'find-file-hook - (lambda () - ;; Check if we are looking at a new or shared file. - (when (or (not (file-exists-p (buffer-file-name))) - (eq TeX-master 'shared)) - (TeX-master-file nil nil t)) - (TeX-update-style t)) nil t)) - - -;;; Hilighting - -;; FIXME: It's likely that `hilit-patterns-alist' is much obsolete. -(if (boundp 'hilit-patterns-alist) - (let ((latex-patterns (cdr-safe (assq 'latex-mode hilit-patterns-alist))) - (plain-tex-patterns (cdr-safe (assq 'plain-tex-mode - hilit-patterns-alist)))) - (if (and latex-patterns plain-tex-patterns) - (setq hilit-patterns-alist - (append (list (cons 'ams-tex-mode plain-tex-patterns)) - hilit-patterns-alist))))) - -;;; Parsing - -(defgroup TeX-parse nil - "Parsing TeX files from AUCTeX." - :group 'AUCTeX) - -(defvar TeX-auto-parser '((styles TeX-auto-file TeX-run-style-hooks))) -;; Alist of parsed information. -;; Each entry is a list with the following elements: -;; -;; 0. Name of information type. -;; 1. Name of temporary variable used when parsing. -;; 2. Name of function to add information to add to #3. -;; 3. Name of variable holding buffer local information. -;; 4. Name of variable indicating that #3 has changed. - - -(defconst TeX-auto-parser-temporary 1) -(defconst TeX-auto-parser-add 2) -(defconst TeX-auto-parser-local 3) -(defconst TeX-auto-parser-change 4) - -(defun TeX-auto-add-information (name entries) - "For NAME in `TeX-auto-parser' add ENTRIES." - (let* ((entry (assoc name TeX-auto-parser)) - (change (nth TeX-auto-parser-change entry)) - (change-value (symbol-value change)) - (local (nth TeX-auto-parser-local entry)) - (local-value (symbol-value local))) - (if change-value - (set local (cons entries local-value)) - (set change t) - (set local (list entries local-value))))) - -(defun TeX-auto-list-information (name) - "Return information in `TeX-auto-parser' about NAME." - (TeX-update-style) - (let* ((entry (assoc name TeX-auto-parser)) - (change (nth TeX-auto-parser-change entry)) - (change-value (symbol-value change)) - (local (nth TeX-auto-parser-local entry))) - (if (not change-value) - () - (set change nil) - ;; Sort it - (message "Sorting %s..." name) - (set local - (sort (mapcar #'TeX-listify (apply #'append (symbol-value local))) - #'TeX-car-string-lessp)) - (message "Sorting %s...done" name) - ;; Make it unique - (message "Removing duplicates...") - (let ((entry (symbol-value local))) - (while (and entry (cdr entry)) - (let ((this (car entry)) - (next (car (cdr entry)))) - (if (not (string-equal (car this) (car next))) - (setq entry (cdr entry)) - ;; We have two equal symbols. Use the one with - ;; most arguments. - (if (> (length next) (length this)) - (setcdr this (cdr next))) - (setcdr entry (cdr (cdr entry))))))) - (message "Removing duplicates...done")) - (symbol-value local))) - -(defmacro TeX-auto-add-type (name prefix &optional plural) - "Add information about NAME to the parser using PREFIX. - -Optional third argument PLURAL is the plural form of NAME. -By default just add an `s'. - -This macro creates a set of variables and functions to maintain a -separate type of information in the parser." - (let* ((names (or plural (concat name "s"))) - (tmp (intern (concat prefix "-auto-" name))) - (add (intern (concat prefix "-add-" names))) - (local (intern (concat prefix "-" name "-list"))) - (change (intern (concat prefix "-" name "-changed"))) - (vardoc (concat "Information about " names - " in the current buffer. -Generated by `TeX-auto-add-type'."))) - `(progn - (defvar ,tmp nil ,vardoc) - (defvar ,local nil ,vardoc) - (make-variable-buffer-local ',local) - (defvar ,change nil ,vardoc) - (make-variable-buffer-local ',change) - (defun ,add (&rest ,(intern names)) - ,(concat "Add information about " (upcase names) - " to the current buffer. -Generated by `TeX-auto-add-type'.") - (TeX-auto-add-information ,name ,(intern names))) - (defun ,local () - ,(concat "List of " names - " active in the current buffer. -Generated by `TeX-auto-add-type'.") - (TeX-auto-list-information ,name)) - ;; Append new type to `TeX-auto-parser' in order to make `style' type - ;; always the first. - (add-to-list 'TeX-auto-parser ',(list name tmp add local change) t) - (add-hook 'TeX-remove-style-hook - (lambda () - (setq ,local nil)))))) - -(TeX-auto-add-type "symbol" "TeX") - -(defvar TeX-auto-apply-hook nil - "Hook run when a buffer is parsed and the information is applied.") - -(defun TeX-auto-apply () - "Parse and apply TeX information in the current buffer." - (TeX-auto-parse) - (run-hooks 'TeX-auto-apply-hook) - (mapcar #'TeX-auto-apply-entry TeX-auto-parser)) - -(defun TeX-auto-apply-entry (entry) - "Apply the information in ENTRY in `TeX-auto-parser'." - (let ((value (symbol-value (nth TeX-auto-parser-temporary entry))) - (add (nth TeX-auto-parser-add entry))) - (if value (apply add value)))) - -(defun TeX-safe-auto-write () - "Call `TeX-auto-write' safely." - (condition-case _ignored - (TeX-auto-write) - (error nil)) - ;; Continue with the other write file hooks. - nil) - -(defcustom TeX-auto-save nil - "Automatically save style information when saving the buffer." - :group 'TeX-parse - :type 'boolean) - -(defcustom TeX-auto-untabify nil - "Automatically untabify when saving the buffer." - :group 'TeX-parse - :type 'boolean) - -(defun TeX-auto-write () - "Save all relevant TeX information from the current buffer." - (if TeX-auto-untabify - (untabify (point-min) (point-max))) - (if (and TeX-auto-save TeX-auto-local) - (let* ((file (expand-file-name - (concat - (file-name-as-directory TeX-auto-local) - (TeX-strip-extension nil TeX-all-extensions t) - ".el") - (TeX-master-directory))) - (dir (file-name-directory file))) - ;; Create auto directory if possible. - (if (not (file-exists-p dir)) - (condition-case _ignored - (make-directory dir) - (error nil))) - (if (file-writable-p file) - (save-excursion - (TeX-update-style) - (TeX-auto-store file)) - (message "Can't write style information."))))) - -(defcustom TeX-macro-default (car-safe TeX-macro-private) - "Default directory to search for TeX macros." - :group 'TeX-file - :type 'directory) - -(defcustom TeX-auto-default (car-safe TeX-auto-private) - "Default directory to place automatically generated TeX information." - :group 'TeX-file - :type 'directory) - -(defcustom TeX-ignore-file - "\\(^\\|[/\\]\\)\\(\\.\\|\\.\\.\\|RCS\\|SCCS\\|CVS\\|babel\\..*\\)$" - "Regular expression matching file names to ignore. - -These files or directories will not be considered when searching for -TeX files in a directory." - :group 'TeX-parse - :type 'regexp) - -(defcustom TeX-file-recurse t - "Whether to search TeX directories recursively. -nil means do not recurse, a positive integer means go that far deep in the -directory hierarchy, t means recurse indefinitely." - :group 'TeX-parse - :type '(choice (const :tag "On" t) - (const :tag "Off" nil) - (integer :tag "Depth" :value 1))) - -(defvar TeX-file-extensions) -(defvar BibTeX-file-extensions) -(defvar TeX-Biber-file-extensions) - -;;;###autoload -(defun TeX-auto-generate (tex auto) - "Generate style file for TEX and store it in AUTO. -If TEX is a directory, generate style files for all files in the directory." - (interactive (list (setq TeX-macro-default - (expand-file-name (read-file-name - "TeX file or directory: " - TeX-macro-default - TeX-macro-default 'confirm))) - (setq TeX-auto-default - (expand-file-name (read-file-name - "AUTO lisp directory: " - TeX-auto-default - TeX-auto-default 'confirm))))) - (cond ((not (file-readable-p tex))) - ((string-match TeX-ignore-file tex)) - ((file-directory-p tex) - (let ((files (directory-files (expand-file-name tex))) - (default-directory (file-name-as-directory - (expand-file-name tex))) - (TeX-file-recurse (cond ((symbolp TeX-file-recurse) - TeX-file-recurse) - ((zerop TeX-file-recurse) - nil) - ((1- TeX-file-recurse))))) - (mapcar (lambda (file) - (if (or TeX-file-recurse - (not (file-directory-p file))) - (TeX-auto-generate file auto))) - files))) - ((not (file-newer-than-file-p - tex - (concat (file-name-as-directory auto) - (TeX-strip-extension tex TeX-all-extensions t) - ".el")))) - ((TeX-match-extension tex (TeX-delete-duplicate-strings - (append TeX-file-extensions - BibTeX-file-extensions - TeX-Biber-file-extensions))) - (with-current-buffer (let (enable-local-eval) - (find-file-noselect tex)) - (message "Parsing %s..." tex) - (TeX-auto-store (concat (file-name-as-directory auto) - (TeX-strip-extension tex - TeX-all-extensions - t) - ".el")) - (kill-buffer (current-buffer)) - (message "Parsing %s...done" tex))))) - -;;;###autoload -(defun TeX-auto-generate-global () - "Create global auto directory for global TeX macro definitions." - (interactive) - (unless (file-directory-p TeX-auto-global) - (make-directory TeX-auto-global)) - (let ((TeX-file-extensions '("cls" "sty")) - (BibTeX-file-extensions nil) - (TeX-Biber-file-extensions nil)) - (mapc (lambda (macro) (TeX-auto-generate macro TeX-auto-global)) - TeX-macro-global)) - (byte-recompile-directory TeX-auto-global 0)) - -(defun TeX-auto-store (file) - "Extract information for AUCTeX from current buffer and store it in FILE." - (TeX-auto-parse) - - (if (member nil (mapcar #'TeX-auto-entry-clear-p TeX-auto-parser)) - (let ((style (TeX-strip-extension nil TeX-all-extensions t)) - (class-opts (if (boundp 'LaTeX-provided-class-options) - LaTeX-provided-class-options)) - (pkg-opts (if (boundp 'LaTeX-provided-package-options) - LaTeX-provided-package-options)) - (tex-cmd-opts TeX-command-extra-options) - (verb-envs (when (boundp 'LaTeX-verbatim-environments-local) - LaTeX-verbatim-environments-local)) - (verb-macros-delims (when (boundp 'LaTeX-verbatim-macros-with-delims-local) - LaTeX-verbatim-macros-with-delims-local)) - (verb-macros-braces (when (boundp 'LaTeX-verbatim-macros-with-braces-local) - LaTeX-verbatim-macros-with-braces-local)) - (dialect TeX-style-hook-dialect) - (bibtex-p (eq major-mode 'bibtex-mode))) - (TeX-unload-style style) - (with-current-buffer (generate-new-buffer file) - (erase-buffer) - (insert "(TeX-add-style-hook\n \"" - style "\"\n (lambda ()") - (unless (string= tex-cmd-opts "") - (insert "\n (setq TeX-command-extra-options\n" - " " (prin1-to-string tex-cmd-opts) ")")) - (when class-opts - (insert "\n (TeX-add-to-alist 'LaTeX-provided-class-options\n" - " '" (prin1-to-string class-opts) ")")) - (when pkg-opts - (insert "\n (TeX-add-to-alist 'LaTeX-provided-package-options\n" - " '" (prin1-to-string pkg-opts) ")")) - (dolist (env verb-envs) - (insert - (format "\n (add-to-list 'LaTeX-verbatim-environments-local \"%s\")" - env))) - (dolist (env verb-macros-braces) - (insert - (format "\n (add-to-list 'LaTeX-verbatim-macros-with-braces-local \"%s\")" - env))) - (dolist (env verb-macros-delims) - (insert - (format "\n (add-to-list 'LaTeX-verbatim-macros-with-delims-local \"%s\")" - env))) - (mapc (lambda (el) (TeX-auto-insert el style)) - TeX-auto-parser) - (insert ")") - (if dialect (insert (concat - "\n " - (prin1-to-string - (if bibtex-p - ;; Add :latex since functions such - ;; as `LaTeX-add-bibitems' are - ;; only meaningful in LaTeX - ;; document buffer. - ;; FIXME: BibTeX is available to - ;; plain TeX through eplain - ;; (<URL:https://tug.org/eplain/doc/eplain.html#Citations>). - ;; It would be nice if AUCTeX - ;; supports such usage. - `'(or ,dialect :latex) - dialect))))) - (insert ")\n\n") - (write-region (point-min) (point-max) file nil 'silent) - (kill-buffer (current-buffer)))) - (if (file-exists-p (concat file "c")) - (delete-file (concat file "c"))) - (if (file-exists-p file) - (delete-file file)))) - -(defun TeX-auto-entry-clear-p (entry) - "Check if the temporary for `TeX-auto-parser' entry ENTRY is clear." - ;; FIXME: This doc-string isn't clear to me. -- rs - (null (symbol-value (nth TeX-auto-parser-temporary entry)))) - -(defun TeX-auto-insert (entry &optional skip) - "Insert code to initialize ENTRY from `TeX-auto-parser'. - -If SKIP is not-nil, don't insert code for SKIP." - (let ((name (symbol-name (nth TeX-auto-parser-add entry))) - (list (symbol-value (nth TeX-auto-parser-temporary entry)))) - (unless (null list) - (insert "\n (" name) - (dolist (el list) - (cond ((and (stringp el) (not (string= el skip))) - (insert "\n ") - (insert (prin1-to-string el))) - ((not (stringp el)) - (insert "\n ") - (insert "'" (prin1-to-string el))))) - (insert ")")))) - -(defvar TeX-auto-ignore - '("csname" "filedate" "fileversion" "docdate" "next" "labelitemi" - "labelitemii" "labelitemiii" "labelitemiv" "labelitemv" - "labelenumi" "labelenumii" "labelenumiii" "labelenumiv" - "labelenumv" "theenumi" "theenumii" "theenumiii" "theenumiv" - "theenumv" "document" "par" "do" "expandafter") - "List of symbols to ignore when scanning a TeX style file.") - -(defcustom TeX-auto-regexp-list 'TeX-auto-full-regexp-list - "List of regular expressions used for parsing the current file. -It can also be a name of a variable having such value." - :type '(radio (variable-item TeX-auto-empty-regexp-list) - (variable-item TeX-auto-full-regexp-list) - (variable-item plain-TeX-auto-regexp-list) - (variable-item LaTeX-auto-minimal-regexp-list) - (variable-item LaTeX-auto-label-regexp-list) - (variable-item LaTeX-auto-regexp-list) - (variable :tag "Other") - (repeat :tag "Specify" - (group (regexp :tag "Match") - (sexp :tag "Groups") - symbol))) - :group 'TeX-parse) - (make-variable-buffer-local 'TeX-auto-regexp-list) - -(defun TeX-auto-add-regexp (regexp) - "Add REGEXP to `TeX-auto-regexp-list' if not already a member." - (if (symbolp TeX-auto-regexp-list) - (setq TeX-auto-regexp-list (symbol-value TeX-auto-regexp-list))) - (or (member regexp TeX-auto-regexp-list) - (setq TeX-auto-regexp-list (cons regexp TeX-auto-regexp-list)))) - -(defvar TeX-auto-empty-regexp-list - '(("<IMPOSSIBLE>\\(\\'\\`\\)" 1 ignore)) - "List of regular expressions guaranteed to match nothing.") - -(defvar TeX-token-char - "\\(?:[a-zA-Z]\\|\\cj\\)" - "Regexp matching a character in a TeX macro. - -Please use a shy group if you use a grouping construct, because -the functions/variables which use `TeX-token-char' expect not to -alter the numbering of any ordinary, non-shy groups.") - -(defvar plain-TeX-auto-regexp-list - (let ((token TeX-token-char)) - `((,(concat "\\\\def\\\\\\(" token "+\\)[^a-zA-Z@]") - 1 TeX-auto-symbol-check) - (,(concat "\\\\let\\\\\\(" token "+\\)[^a-zA-Z@]") - 1 TeX-auto-symbol-check) - (,(concat "\\\\font\\\\\\(" token "+\\)[^a-zA-Z@]") 1 TeX-auto-symbol) - (,(concat "\\\\chardef\\\\\\(" token "+\\)[^a-zA-Z@]") 1 TeX-auto-symbol) - (,(concat "\\\\new\\(?:count\\|dimen\\|muskip\\|skip\\)\\\\\\(" token - "+\\)[^a-zA-Z@]") - 1 TeX-auto-symbol) - (,(concat "\\\\newfont{?\\\\\\(" token "+\\)}?") 1 TeX-auto-symbol) - (,(concat "\\\\typein\\[\\\\\\(" token "+\\)\\]") 1 TeX-auto-symbol) - ("\\\\input +\\(\\.*[^#%\\\\\\.\n\r]+\\)\\(\\.[^#%\\\\\\.\n\r]+\\)?" - 1 TeX-auto-file) - (,(concat "\\\\mathchardef\\\\\\(" token "+\\)[^a-zA-Z@]") - 1 TeX-auto-symbol))) - "List of regular expression matching common plain TeX macro definitions.") - -(defvar TeX-auto-full-regexp-list plain-TeX-auto-regexp-list - "Full list of regular expression matching TeX macro definitions.") - -(defvar TeX-auto-prepare-hook nil - "List of hooks to be called before parsing a TeX file.") - -(defvar TeX-auto-cleanup-hook nil - "List of hooks to be called after parsing a TeX file.") - -(defcustom TeX-auto-parse-length 999999 - "Maximal length of TeX file (in characters) that will be parsed." - :group 'TeX-parse - :type 'integer) - (make-variable-buffer-local 'TeX-auto-parse-length) - -(defcustom TeX-auto-x-parse-length 0 - "Maximum length of TeX file that will be parsed additionally. -Use `TeX-auto-x-regexp-list' for parsing the region between -`TeX-auto-parse-length' and this value." - :group 'TeX-parse - :type 'integer) - (make-variable-buffer-local 'TeX-auto-x-parse-length) - -(defcustom TeX-auto-x-regexp-list 'LaTeX-auto-label-regexp-list - "List of regular expressions used for additional parsing. -It can also be a name of a variable having such value. -See `TeX-auto-x-parse-length'." - :type '(radio (variable-item TeX-auto-empty-regexp-list) - (variable-item TeX-auto-full-regexp-list) - (variable-item plain-TeX-auto-regexp-list) - (variable-item LaTeX-auto-minimal-regexp-list) - (variable-item LaTeX-auto-label-regexp-list) - (variable-item LaTeX-auto-regexp-list) - (variable :tag "Other") - (repeat :tag "Specify" - (group (regexp :tag "Match") - (sexp :tag "Groups") - symbol))) - :group 'TeX-parse) - (make-variable-buffer-local 'TeX-auto-x-regexp-list) - -(defun TeX-regexp-group-count (regexp) - "Return number of groups in a REGEXP. This is not foolproof: -you should not use something like `[\\(]' for a character range." - (let (start (n 0)) - (while (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\([^?]" - regexp start) - (setq start (- (match-end 0) 2) - n (1+ n))) - n)) - -(defun TeX-auto-parse-region (regexp-list beg end) - "Parse TeX information according to REGEXP-LIST between BEG and END." - (if (symbolp regexp-list) - (setq regexp-list (and (boundp regexp-list) (symbol-value regexp-list)))) - (if regexp-list - ;; Extract the information. - (let* (groups - (count 1) - (regexp (concat "\\(" - (mapconcat - (lambda(x) - (push (cons count x) groups) - (setq count - (+ 1 count - (TeX-regexp-group-count (car x)))) - (car x)) - regexp-list "\\)\\|\\(") - "\\)")) - syms - lst) - ;; TODO: Emacs allows at most 255 groups in a regexp, see the - ;; "#define MAX_REGNUM 255" in regex-emacs.c. If our regex - ;; has more groups, bad things may happen, e.g., - ;; (match-beginning 271) returns nil although the regexp that - ;; matched contains group number 271. Sadly, MAX_REGNUM is - ;; not exposed to Lisp, so we need to hard-code it here (and - ;; sometimes check if it increased in newer Emacs versions). - (when (> count 255) - (error "The TeX auto-parser's regexp has too many groups (%d)" count)) - (setq count 0) - (goto-char (if end (min end (point-max)) (point-max))) - (while (re-search-backward regexp beg t) - (let* ((entry (cdr (TeX-member nil groups - (lambda (_a b) - (match-beginning (car b)))))) - (symbol (nth 2 entry)) - (match (nth 1 entry))) - (unless (TeX-in-comment) - (looking-at (nth 0 entry)) - (if (fboundp symbol) - (funcall symbol match) - (puthash (if (listp match) - (mapcar #'TeX-match-buffer match) - (TeX-match-buffer match)) - (setq count (1- count)) - (cdr (or (assq symbol syms) - (car (push - (cons symbol - (make-hash-table :test #'equal)) - syms))))))))) - (setq count 0) - (dolist (symbol syms) - (setq lst (symbol-value (car symbol))) - (while lst - (puthash (pop lst) - (setq count (1+ count)) - (cdr symbol))) - (maphash (lambda (key value) - (push (cons value key) lst)) - (cdr symbol)) - (clrhash (cdr symbol)) - (set (car symbol) (mapcar #'cdr (sort lst #'car-less-than-car))))))) - -(defun TeX-auto-parse () - "Parse TeX information in current buffer. - -Call the functions in `TeX-auto-prepare-hook' before parsing, and the -functions in `TeX-auto-cleanup-hook' after parsing." - - (let ((case-fold-search nil)) - - (mapc #'TeX-auto-clear-entry TeX-auto-parser) - (run-hooks 'TeX-auto-prepare-hook) - - (save-excursion - (and (> TeX-auto-x-parse-length TeX-auto-parse-length) - (> (point-max) TeX-auto-parse-length) - (TeX-auto-parse-region TeX-auto-x-regexp-list - TeX-auto-parse-length - TeX-auto-x-parse-length)) - (TeX-auto-parse-region TeX-auto-regexp-list - nil TeX-auto-parse-length)) - - ;; Cleanup ignored symbols. - - ;; NOTE: This is O(N M) where it could be O(N log N + M log M) if we - ;; sorted the lists first. - (while (member (car TeX-auto-symbol) TeX-auto-ignore) - (setq TeX-auto-symbol (cdr TeX-auto-symbol))) - (let ((list TeX-auto-symbol)) - (while (and list (cdr list)) - (if (member (car (cdr list)) TeX-auto-ignore) - (setcdr list (cdr (cdr list))) - (setq list (cdr list))))) - - (run-hooks 'TeX-auto-cleanup-hook))) - -(defun TeX-auto-clear-entry (entry) - "Set the temporary variable in ENTRY to nil." - (set (nth TeX-auto-parser-temporary entry) nil)) - -(defvar LaTeX-auto-end-symbol nil) - -(defun TeX-auto-symbol-check (match) - "Add MATCH to TeX-auto-symbols. -Check for potential LaTeX environments." - (let ((symbol (if (listp match) - (mapcar #'TeX-match-buffer match) - (TeX-match-buffer match)))) - (if (and (stringp symbol) - (string-match "^end\\(.+\\)$" symbol)) - (add-to-list 'LaTeX-auto-end-symbol - (substring symbol (match-beginning 1) (match-end 1))) - (if (listp symbol) - (dolist (elt symbol) - (add-to-list 'TeX-auto-symbol elt)) - (add-to-list 'TeX-auto-symbol symbol))))) - - -;;; File Extensions - -(defgroup TeX-file-extension nil - "File extensions recognized by AUCTeX." - :group 'TeX-file) - -(defcustom TeX-file-extensions '("tex" "sty" "cls" "ltx" "texi" "txi" "texinfo" "dtx") - "File extensions used by manually generated TeX files." - :group 'TeX-file-extension - :type '(repeat (regexp :format "%v"))) - -(defcustom TeX-all-extensions '("[^.\n]+") - "All possible file extensions." - :group 'TeX-file-extension - :type '(repeat (regexp :format "%v"))) - -(defcustom TeX-default-extension "tex" - "Default extension for TeX files." - :group 'TeX-file-extension - :type 'string) - - (make-variable-buffer-local 'TeX-default-extension) - -(defvar TeX-doc-extensions - '("dvi" "pdf" "ps" "txt" "html" "dvi\\.gz" "pdf\\.gz" "ps\\.gz" "txt\\.gz" - "html\\.gz" "dvi\\.bz2" "pdf\\.bz2" "ps\\.bz2" "txt\\.bz2" "html\\.bz2") - "File extensions of documentation files.") - -(defcustom docTeX-default-extension "dtx" - "Default extension for docTeX files." - :group 'TeX-file-extension - :type 'string) - -(defvar TeX-output-extension nil - "Extension of TeX output file. -This is either a string or a list with -a string as element. Its value is obtained from `TeX-command-output-list'. -Access to the value should be through the function `TeX-output-extension'.") - - (make-variable-buffer-local 'TeX-output-extension) - -(defcustom TeX-Biber-file-extensions '("bib" "ris" "xml") - "Valid file extensions for Biber files." - :group 'TeX-file-extension - :type '(repeat (regexp :format "%v"))) - -(defcustom BibTeX-file-extensions '("bib") - "Valid file extensions for BibTeX files." - :group 'TeX-file-extension - :type '(repeat (regexp :format "%v"))) - -(defcustom BibLaTeX-style-extensions '("bbx") - "Valid file extensions for BibLaTeX styles." - :group 'TeX-file-extension - :type '(repeat (regexp :format "%v"))) - -(defcustom BibTeX-style-extensions '("bst") - "Valid file extensions for BibTeX styles." - :group 'TeX-file-extension - :type '(repeat (regexp :format "%v"))) - -(defun TeX-match-extension (file &optional extensions) - "Return non-nil if FILE has one of EXTENSIONS. - -If EXTENSIONS is not specified or nil, the value of -`TeX-file-extensions' is used instead." - - (if (null extensions) - (setq extensions TeX-file-extensions)) - - (let ((regexp (concat "\\.\\(" - (mapconcat #'identity extensions "\\|") - "\\)$")) - (case-fold-search t)) - (string-match regexp file))) - -(defun TeX-strip-extension (&optional string extensions nodir nostrip) - "Return STRING without any trailing extension in EXTENSIONS. -If NODIR is t, also remove directory part of STRING. -If NODIR is `path', remove directory part of STRING if it is -equal to the current directory or is a member of -`TeX-macro-private' or `TeX-macro-global'. -If NOSTRIP is set, do not remove extension after all. -STRING defaults to the name of the current buffer. -EXTENSIONS defaults to `TeX-file-extensions'." - - (if (null string) - (setq string (or (buffer-file-name) "<none>"))) - - (if (null extensions) - (setq extensions TeX-file-extensions)) - - (let* ((strip (if (and (not nostrip) - (TeX-match-extension string extensions)) - (substring string 0 (match-beginning 0)) - string)) - (dir (expand-file-name (or (file-name-directory strip) "./")))) - (if (or (eq nodir t) - (string-equal dir (expand-file-name "./")) - (member dir (mapcar #'file-name-as-directory TeX-macro-global)) - (member dir (mapcar #'file-name-as-directory TeX-macro-private))) - (file-name-nondirectory strip) - strip))) - - -;;; File Searching - -(defun TeX-tree-roots () - "Return a list of available TeX tree roots." - (let (list) - (dolist (dir (TeX-tree-expand '("$TEXMFHOME" "$TEXMFMAIN" "$TEXMFLOCAL" - "$TEXMFDIST") - "latex")) - (when (file-readable-p dir) - (cl-pushnew dir list :test #'equal))) - (nreverse list))) - -(defcustom TeX-tree-roots (TeX-tree-roots) - "List of all available TeX tree root directories." - :group 'TeX-file - :type '(repeat directory)) - -;; We keep this function in addition to `TeX-search-files' because it -;; is faster. Since it does not look further into subdirectories, -;; this comes at the price of finding a smaller number of files. -(defun TeX-search-files-kpathsea (var extensions scope nodir strip) - "Return a list of files in directories determined by expanding VAR. -Only files which match EXTENSIONS are returned. SCOPE defines -the scope for the search and can be `local' or `global' besides -nil. If NODIR is non-nil, remove directory part. If STRIP is -non-nil, remove file extension." - (when TeX-kpathsea-path-delimiter - (let ((dirs (if (eq scope 'local) - '("./") - (TeX-tree-expand (list var) nil))) - result) - (if (eq scope 'global) - (setq dirs (delete "./" dirs))) - (setq extensions (concat "\\.\\(?:" - (mapconcat #'identity extensions "\\|") - "\\)\\'") - result (apply #'append (mapcar (lambda (x) - (when (file-readable-p x) - (directory-files - x (not nodir) extensions t))) - dirs))) - (if strip - (mapcar (lambda (x) - (if (string-match extensions x) - (substring x 0 (match-beginning 0)) - x)) - result) - result)))) - -(defun TeX-search-files (&optional directories extensions nodir strip) - "Return a list of all reachable files in DIRECTORIES ending with EXTENSIONS. -If optional argument NODIR is set, remove directory part. -If optional argument STRIP is set, remove file extension. -If optional argument DIRECTORIES is set, search in those directories. -Otherwise, search in all TeX macro directories. -If optional argument EXTENSIONS is not set, use `TeX-file-extensions'" - (when (null extensions) - (setq extensions TeX-file-extensions)) - (when (null directories) - (setq directories (cons "./" (append TeX-macro-private TeX-macro-global)))) - (let (match - (TeX-file-recurse (cond ((symbolp TeX-file-recurse) - TeX-file-recurse) - ((zerop TeX-file-recurse) - nil) - ((1- TeX-file-recurse))))) - (while directories - (let* ((directory (car directories)) - (content (and directory - (file-readable-p directory) - (file-directory-p directory) - (directory-files directory)))) - (setq directories (cdr directories)) - (while content - (let ((file (concat directory (car content)))) - (setq content (cdr content)) - (cond ((string-match TeX-ignore-file file)) - ((not (file-readable-p file))) - ((file-directory-p file) - (if TeX-file-recurse - (setq match - (append match - (TeX-search-files - (list (file-name-as-directory file)) - extensions nodir strip))))) - ((TeX-match-extension file extensions) - (setq match (cons (TeX-strip-extension - file extensions nodir (not strip)) - match)))))))) - match)) - -;; The variables `TeX-macro-private' and `TeX-macro-global' are not -;; used for specifying the directories because the number of -;; directories to be searched should be limited as much as possible -;; and the TeX-macro-* variables are just too broad for this. -(defvar TeX-search-files-type-alist - '((texinputs "${TEXINPUTS}" ("tex/") TeX-file-extensions) - (docs "${TEXDOCS}" ("doc/") TeX-doc-extensions) - (bibinputs "${BIBINPUTS}" ("bibtex/bib/") BibTeX-file-extensions) - (bstinputs "${BSTINPUTS}" ("bibtex/bst/") BibTeX-style-extensions)) - "Alist of filetypes with locations and file extensions. -Each element of the alist consists of a symbol expressing the -filetype, a variable which can be expanded on kpathsea-based -systems into the directories where files of the given type -reside, a list of absolute directories, relative directories -below the root of a TDS-compliant TeX tree or a list of variables -with either type of directories as an alternative for -non-kpathsea-based systems and a list of extensions to be matched -upon a file search. Note that the directories have to end with a -directory separator. - -Each AUCTeX mode should set the variable buffer-locally with a -more specific value. See `LaTeX-search-files-type-alist' for an -example.") - -(defun TeX-search-files-by-type (filetype &optional scope nodir strip) - "Return a list of files in TeX's search path with type FILETYPE. -FILETYPE is a symbol used to choose the search paths and -extensions. See `TeX-search-files-type-alist' for supported -symbols. - -The optional argument SCOPE sets the scope for the search. -Besides nil the symbols `local' and `global' are accepted. -`local' means to search in the current directory only, `global' -in the global directories only and nil in both. - -If optional argument NODIR is non-nil, remove directory part. - -If optional argument STRIP is non-nil, remove file extension." - (let* ((gc-cons-threshold 10000000) - (spec (assq filetype TeX-search-files-type-alist)) - (kpse-var (nth 1 spec)) - (rawdirs (nth 2 spec)) - (exts (nth 3 spec)) - expdirs dirs local-files) - (setq exts (if (symbolp exts) (eval exts t) exts)) - (or (TeX-search-files-kpathsea kpse-var exts scope nodir strip) - (progn - (unless (eq scope 'global) - (setq local-files - (let ((TeX-file-recurse nil)) - (TeX-search-files '("./") exts nodir strip)))) - (if (eq scope 'local) - local-files - (if (null TeX-tree-roots) - (error "No TeX trees available; configure `TeX-tree-roots'") - ;; Expand variables. - (setq expdirs - ;; Don't use `delete-dups' instead of - ;; `TeX-delete-duplicate-strings' here. - ;; Otherwise, when the last element of `rawdirs' - ;; is a variable, its value might be truncated as - ;; side effect. - (TeX-delete-duplicate-strings - (apply #'append - (mapcar (lambda (rawdir) - (if (symbolp rawdir) - (symbol-value rawdir) - (list rawdir))) - rawdirs)))) - ;; Assumption: Either all paths are absolute or all are relative. - (if (file-name-absolute-p (car expdirs)) - (setq dirs expdirs) - ;; Append relative TDS subdirs to all TeX tree roots. - (dolist (root TeX-tree-roots) - (dolist (dir expdirs) - (let ((dir (expand-file-name dir root))) - (unless (member dir dirs) - (setq dirs (append dirs (list dir))))))))) - (append local-files (TeX-search-files dirs exts nodir strip))))))) - -;;; Narrowing - -(defun TeX-narrow-to-group () - "Make text outside current group invisible." - (interactive) - (save-excursion - (widen) - (let ((opoint (point)) - beg end) - (if (null (search-backward "{" nil t)) - (message "Nothing to be narrowed here.") - (setq beg (point)) - (forward-sexp) - (setq end (point)) - (if (< end opoint) - (message "Nothing to be narrowed here.") - (narrow-to-region beg end)))))) -(put 'TeX-narrow-to-group 'disabled t) - -;;; Utilities -;; -;; Some of these functions has little to do with TeX, but nonetheless we -;; should use the "TeX-" prefix to avoid name clashes. - -(defun TeX-listify (elt) - "Return a newly created list with element ELT. -If ELT already is a list, return ELT." - (if (listp elt) elt (list elt))) - -(defun TeX-member (elt list how) - "Return the member ELT in LIST. Comparison done with HOW. -Return nil if ELT is not a member of LIST." - (while (and list (not (funcall how elt (car list)))) - (setq list (cdr list))) - (car-safe list)) - -(defun TeX-elt-of-list-member (elts list) - "Return non-nil if an element of ELTS is a member of LIST." - (catch 'found - (dolist (elt elts) - (when (member elt list) - (throw 'found t))))) - -;; Compatibility alias -(defun TeX-assoc (key list) - (assoc-string key list t)) -(make-obsolete 'TeX-assoc - "use (assoc-string KEY LIST t) instead." "AUCTeX 13.0") - -(defun TeX-match-buffer (n) - "Return the substring corresponding to the N'th match. -See `match-data' for details." - (if (match-beginning n) - (buffer-substring-no-properties (match-beginning n) (match-end n)) - "")) - -(defun TeX-looking-at-backward (regexp &optional limit) - "Return non-nil if the text before point matches REGEXP. -Optional second argument LIMIT gives a max number of characters -to look backward for." - (let ((pos (point))) - (save-excursion - (and (re-search-backward regexp - (if limit (max (point-min) (- (point) limit))) - t) - (eq (match-end 0) pos))))) - -(defun TeX-current-line () - "The current line number." - (format "%d" (1+ (TeX-current-offset)))) - -(defun TeX-current-file-name-master-relative () - "Return current filename, relative to master directory." - (file-relative-name - (buffer-file-name) - (TeX-master-directory))) - -(defun TeX-near-bobp () - "Return t if there's nothing but whitespace between (bob) and (point)." - (save-excursion - (skip-chars-backward " \t\n") - (bobp))) - -(defun TeX-add-to-alist (alist-var new-alist) - "Add NEW-ALIST to the ALIST-VAR. -If an element with the same key as the key of an element of -NEW-ALIST is already present in ALIST-VAR, add the new values to -it; if a matching element is not already present, append the new -element to ALIST-VAR." - ;; Loop over all elements of NEW-ALIST. - (while new-alist - (let* ((new-element (car new-alist)) - ;; Get the element of ALIST-VAR with the same key of the current - ;; element of NEW-ALIST, if any. - (old-element (assoc (car new-element) (symbol-value alist-var)))) - (if old-element - (progn - (set alist-var (delete old-element (symbol-value alist-var))) - ;; Append to `old-element' the values of the current element of - ;; NEW-ALIST. - (mapc (lambda (elt) - (unless (member elt (cdr old-element)) - (setq old-element (append old-element (list elt))))) - (cdr new-element)) - (add-to-list alist-var old-element t)) - (add-to-list alist-var new-element t))) - ;; Next element of NEW-ALIST. - (setq new-alist (cdr new-alist)))) - -;;; Syntax Table - -(defvar TeX-mode-syntax-table (make-syntax-table) - "Syntax table used while in TeX mode.") - - (make-variable-buffer-local 'TeX-mode-syntax-table) - -(progn ; Define TeX-mode-syntax-table. - (modify-syntax-entry (string-to-char TeX-esc) - "\\" TeX-mode-syntax-table) - (modify-syntax-entry ?\f ">" TeX-mode-syntax-table) - (modify-syntax-entry ?\n ">" TeX-mode-syntax-table) - (modify-syntax-entry (string-to-char TeX-grop) - (concat "(" TeX-grcl) - TeX-mode-syntax-table) - (modify-syntax-entry (string-to-char TeX-grcl) - (concat ")" TeX-grop) - TeX-mode-syntax-table) - (modify-syntax-entry ?% "<" TeX-mode-syntax-table) - (modify-syntax-entry ?\" "." TeX-mode-syntax-table) - (modify-syntax-entry ?& "." TeX-mode-syntax-table) - (modify-syntax-entry ?_ "." TeX-mode-syntax-table) - (modify-syntax-entry ?@ "_" TeX-mode-syntax-table) - (modify-syntax-entry ?~ "." TeX-mode-syntax-table) - (modify-syntax-entry ?$ "$" TeX-mode-syntax-table) - (modify-syntax-entry ?' "w" TeX-mode-syntax-table) - (modify-syntax-entry ?« "." TeX-mode-syntax-table) - (modify-syntax-entry ?» "." TeX-mode-syntax-table) - (modify-syntax-entry ?| "." TeX-mode-syntax-table)) - -;;; Menu Support - -(defvar TeX-command-current #'TeX-command-master - "Specify whether to run command on master, buffer or region.") -;; Function used to run external command. - -(defun TeX-command-select-master () - "Determine that the next command will be on the master file." - (interactive) - (message "Next command will be on the master file.") - (setq TeX-command-current #'TeX-command-master)) - -(defun TeX-command-select-buffer () - "Determine that the next command will be on the buffer." - (interactive) - (message "Next command will be on the buffer") - (setq TeX-command-current #'TeX-command-buffer)) - -(defun TeX-command-select-region () - "Determine that the next command will be on the region." - (interactive) - (message "Next command will be on the region") - (setq TeX-command-current #'TeX-command-region)) - -(defvar TeX-command-force nil) -;; If non-nil, TeX-command-query will return the value of this -;; variable instead of quering the user. - -(defun TeX-command-menu (name) - "Execute `TeX-command-list' NAME from a menu." - (let ((TeX-command-force name)) - (funcall TeX-command-current))) - -(defun TeX-command-menu-print (printer command name) - "Print on PRINTER using method COMMAND to run NAME." - (let ((TeX-printer-default (unless (string= printer "Other") printer)) - (TeX-printer-list (and (string= printer "Other") TeX-printer-list)) - (TeX-print-command command) - (TeX-queue-command command)) - (TeX-command-menu name))) - -(defun TeX-command-menu-printer-entry (entry lookup command name) - "Return `TeX-printer-list' ENTRY as a menu item." - (vector (nth 0 entry) - (list 'TeX-command-menu-print - (nth 0 entry) - (or (nth lookup entry) command) - name))) - -(defun TeX-command-menu-entry (entry) - "Return `TeX-command-list' ENTRY as a menu item." - (let ((name (car entry))) - (cond ((and (string-equal name TeX-command-Print) - TeX-printer-list) - (cons TeX-command-Print - (mapcar (lambda (entry) - (TeX-command-menu-printer-entry - entry 1 TeX-print-command name)) - (append TeX-printer-list '(("Other")))))) - ((and (string-equal name TeX-command-Queue) - TeX-printer-list) - (cons TeX-command-Queue - (mapcar (lambda (entry) - (TeX-command-menu-printer-entry - entry 2 TeX-queue-command name)) - (append TeX-printer-list '(("Other")))))) - (t - (vconcat `(,name (TeX-command-menu ,name)) - (nthcdr 5 entry)))))) - -(defconst TeX-command-menu-name "Command" - "Name to be displayed for the command menu in all modes defined by AUCTeX.") - -;;; Keymap - -(defcustom TeX-electric-escape nil - "If non-nil, ``\\'' will offer on-the-fly completion. -In Texinfo-mode, ``@'' will do that job instead and ``\\'' is not -affected. See `TeX-electric-macro' for detail." - :group 'TeX-macro - :type 'boolean) - -(defcustom TeX-electric-sub-and-superscript nil - "If non-nil, insert braces after typing `^' and `_' in math mode." - :group 'TeX-macro - :type 'boolean) - -(defcustom TeX-newline-function #'newline - "Function to be called upon pressing `RET'." - :group 'TeX-indentation - :type '(choice (const newline) - (const newline-and-indent) - (const reindent-then-newline-and-indent) - (sexp :tag "Other"))) - -(defun TeX-insert-backslash (arg) - "Either insert typed key ARG times or call `TeX-electric-macro'. -`TeX-electric-macro' will be called if `TeX-electric-escape' is non-nil." - (interactive "*p") - (if TeX-electric-escape - (TeX-electric-macro) - (self-insert-command arg))) - -(defun TeX-insert-sub-or-superscript (arg) - "Insert typed key ARG times and possibly a pair of braces. -Brace insertion is only done if point is in a math construct and -`TeX-electric-sub-and-superscript' has a non-nil value." - (interactive "*p") - (self-insert-command arg) - (when (and TeX-electric-sub-and-superscript (texmathp)) - (insert (concat TeX-grop TeX-grcl)) - (backward-char))) - -(defun TeX-newline () - "Call the function specified by the variable `TeX-newline-function'." - (interactive) (call-interactively TeX-newline-function)) - -(defvar TeX-mode-map - (let ((map (make-sparse-keymap))) - ;; Standard - ;; (define-key map "\177" #'backward-delete-char-untabify) - (define-key map "\C-c}" #'up-list) - (define-key map "\C-c#" #'TeX-normal-mode) - (define-key map "\C-c\C-n" #'TeX-normal-mode) - (define-key map "\C-c?" #'TeX-documentation-texdoc) - (define-key map "\C-c\C-i" #'TeX-goto-info-page) - (define-key map "\r" #'TeX-newline) - - ;; From tex.el - (define-key map "\"" #'TeX-insert-quote) - (define-key map "$" #'TeX-insert-dollar) - ;; Removed because LaTeX 2e have a better solution to italic correction. - ;; (define-key map "." #'TeX-insert-punctuation) - ;; (define-key map "," #'TeX-insert-punctuation) - (define-key map "\C-c{" #'TeX-insert-braces) - (define-key map "\C-c\C-f" #'TeX-font) - (define-key map "\C-c\C-m" #'TeX-insert-macro) - (define-key map "\\" #'TeX-insert-backslash) - (define-key map "^" #'TeX-insert-sub-or-superscript) - (define-key map "_" #'TeX-insert-sub-or-superscript) - (define-key map "\e\t" #'TeX-complete-symbol) ;*** Emacs 19 way - - (define-key map "\C-c'" #'TeX-comment-or-uncomment-paragraph) ;*** Old way - (define-key map "\C-c:" #'comment-or-uncomment-region) ;*** Old way - (define-key map "\C-c\"" #'TeX-uncomment) ;*** Old way - - (define-key map "\C-c;" #'comment-or-uncomment-region) - (define-key map "\C-c%" #'TeX-comment-or-uncomment-paragraph) - - (define-key map "\C-c\C-t\C-p" #'TeX-PDF-mode) - (define-key map "\C-c\C-t\C-i" #'TeX-interactive-mode) - (define-key map "\C-c\C-t\C-s" #'TeX-source-correlate-mode) - (define-key map "\C-c\C-t\C-r" #'TeX-pin-region) - (define-key map "\C-c\C-w" #'TeX-toggle-debug-bad-boxes); to be removed - (define-key map "\C-c\C-t\C-b" #'TeX-toggle-debug-bad-boxes) - (define-key map "\C-c\C-t\C-w" #'TeX-toggle-debug-warnings) - (define-key map "\C-c\C-t\C-x" #'TeX-toggle-suppress-ignored-warnings) - (define-key map "\C-c\C-v" #'TeX-view) - (define-key map "\C-c\C-d" #'TeX-save-document) - (define-key map "\C-c\C-r" #'TeX-command-region) - (define-key map "\C-c\C-b" #'TeX-command-buffer) - (define-key map "\C-c\C-c" #'TeX-command-master) - (define-key map "\C-c\C-a" #'TeX-command-run-all) - (define-key map "\C-c\C-k" #'TeX-kill-job) - (define-key map "\C-c\C-l" #'TeX-recenter-output-buffer) - (define-key map "\C-c^" #'TeX-home-buffer) - (define-key map "\C-c`" #'TeX-next-error) - ;; Remap bindings of `next-error' - (define-key map [remap next-error] #'TeX-next-error) - ;; Remap bindings of `previous-error' - (define-key map [remap previous-error] #'TeX-previous-error) - ;; From tex-fold.el - (define-key map "\C-c\C-o\C-f" #'TeX-fold-mode) - - ;; Multifile - (define-key map "\C-c_" #'TeX-master-file-ask) ;*** temporary - - (define-key map "\C-xng" #'TeX-narrow-to-group) - map) - "Keymap for common TeX and LaTeX commands.") - -(defun TeX-mode-specific-command-menu (mode) - "Return a Command menu specific to the major MODE." - (list TeX-command-menu-name - :filter (lambda (&rest _ignored) - (TeX-mode-specific-command-menu-entries mode)) - "Bug.")) - -(defun TeX-mode-specific-command-menu-entries (mode) - "Return the entries for a Command menu specific to the major MODE." - (append - `("Command on" - [ "Master File" TeX-command-select-master - :keys "C-c C-c" :style radio - :selected (eq TeX-command-current #'TeX-command-master) - :help "Commands in this menu work on the Master File"] - [ "Buffer" TeX-command-select-buffer - :keys "C-c C-b" :style radio - :selected (eq TeX-command-current #'TeX-command-buffer) - :help "Commands in this menu work on the current buffer"] - [ "Region" TeX-command-select-region - :keys "C-c C-r" :style radio - :selected (eq TeX-command-current #'TeX-command-region) - :help "Commands in this menu work on the region"] - [ "Fix the Region" TeX-pin-region - :active (or (if prefix-arg - (<= (prefix-numeric-value prefix-arg) 0) - (and (boundp 'TeX-command-region-begin) - (markerp TeX-command-region-begin))) - mark-active) - ;;:visible (eq TeX-command-current 'TeX-command-region) - :style toggle - :selected (and (boundp 'TeX-command-region-begin) - (markerp TeX-command-region-begin)) - :help "Fix the region for \"Command on Region\""] - "-" - ["Recenter Output Buffer" TeX-recenter-output-buffer - :help "Show the output of current TeX process"] - ["Kill Job" TeX-kill-job - :help "Kill the current TeX process"] - ["Next Error" TeX-next-error - :help "Jump to the next error of the last TeX run"] - ["Previous Error" TeX-previous-error - :help "Jump to the previous error of the last TeX run" - :visible TeX-parse-all-errors] - ["Error Overview" TeX-error-overview - :help "Open an overview of errors occured in the last TeX run" - :visible TeX-parse-all-errors] - ["Quick View" TeX-view - :help "Start a viewer without prompting"] - "-" - ("TeXing Options" - ,@(mapcar (lambda (x) - (let ((symbol (car x)) (name (nth 1 x))) - `[ ,(format "Use %s engine" name) (TeX-engine-set ',symbol) - :style radio :selected (eq TeX-engine ',symbol) - :help ,(format "Use %s engine for compiling" name) ])) - (TeX-engine-alist)) - "-" - [ "Generate PDF" TeX-PDF-mode - :style toggle :selected TeX-PDF-mode - :active (not (eq TeX-engine 'omega)) - :help "Use PDFTeX to generate PDF instead of DVI"] - ( "PDF from DVI" - :visible TeX-PDF-mode - :help "Compile to DVI with (La)TeX and convert to PDF" - [ "Compile directly to PDF" - (lambda () (interactive) (setq TeX-PDF-from-DVI nil)) - :style radio :selected (null (TeX-PDF-from-DVI)) - :help "Compile directly to PDF without intermediate conversions"] - [ "dvips + ps2pdf" - (lambda () (interactive) (setq TeX-PDF-from-DVI "Dvips")) - :style radio :selected (equal (TeX-PDF-from-DVI) "Dvips") - :help "Convert DVI to PDF with dvips + ps2pdf sequence"] - [ "dvipdfmx" - (lambda () (interactive) (setq TeX-PDF-from-DVI "Dvipdfmx")) - :style radio :selected (equal (TeX-PDF-from-DVI) "Dvipdfmx") - :help "Convert DVI to PDF with dvipdfmx"]) - [ "Run Interactively" TeX-interactive-mode - :style toggle :selected TeX-interactive-mode :keys "C-c C-t C-i" - :help "Stop on errors in a TeX run"] - [ "Correlate I/O" TeX-source-correlate-mode - :style toggle :selected TeX-source-correlate-mode - :help "Enable forward and inverse search in the previewer"] - ["Debug Bad Boxes" TeX-toggle-debug-bad-boxes - :style toggle :selected TeX-debug-bad-boxes :keys "C-c C-t C-b" - :help "Make \"Next Error\" show overfull and underfull boxes"] - ["Debug Warnings" TeX-toggle-debug-warnings - :style toggle :selected TeX-debug-warnings - :help "Make \"Next Error\" show warnings"]) - ["Compile and view" TeX-command-run-all - :help "Compile the document until it is ready and open the viewer"]) - (delq nil - (mapcar #'TeX-command-menu-entry - (TeX-mode-specific-command-list mode))))) - -(defun TeX-mode-specific-command-list (mode) - "Return the list of commands available in the given MODE." - (let ((full-list TeX-command-list) - out-list - entry) - (while (setq entry (pop full-list)) - ;; `(nth 4 entry)' may be either an atom in case of which the - ;; entry should be present in any mode or a list of major modes. - (if (or (atom (nth 4 entry)) - (memq mode (nth 4 entry))) - (push entry out-list))) - (nreverse out-list))) - -(defvar TeX-fold-menu - '("Show/Hide" - ["Fold Mode" TeX-fold-mode - :style toggle - :selected (and (boundp 'TeX-fold-mode) TeX-fold-mode) - :help "Toggle folding mode"] - "-" - ["Hide All in Current Buffer" TeX-fold-buffer - :active (and (boundp 'TeX-fold-mode) TeX-fold-mode) - :help "Hide all configured TeX constructs in the current buffer"] - ["Hide All in Current Region" TeX-fold-region - :active (and (boundp 'TeX-fold-mode) TeX-fold-mode) - :help "Hide all configured TeX constructs in the marked region"] - ["Hide All in Current Paragraph" TeX-fold-paragraph - :active (and (boundp 'TeX-fold-mode) TeX-fold-mode) - :help "Hide all configured TeX constructs in the paragraph containing point"] - ["Hide Current Macro" TeX-fold-macro - :active (and (boundp 'TeX-fold-mode) TeX-fold-mode) - :help "Hide the macro containing point"] - ["Hide Current Environment" TeX-fold-env - :visible (not (eq major-mode 'plain-tex-mode)) - :active (and (boundp 'TeX-fold-mode) TeX-fold-mode) - :help "Hide the environment containing point"] - ["Hide Current Comment" TeX-fold-comment - :active (and (boundp 'TeX-fold-mode) TeX-fold-mode) - :help "Hide the comment containing point"] - "-" - ["Show All in Current Buffer" TeX-fold-clearout-buffer - :active (and (boundp 'TeX-fold-mode) TeX-fold-mode) - :help "Permanently show all folded content again"] - ["Show All in Current Region" TeX-fold-clearout-region - :active (and (boundp 'TeX-fold-mode) TeX-fold-mode) - :help "Permanently show all folded content in marked region"] - ["Show All in Current Paragraph" TeX-fold-clearout-paragraph - :active (and (boundp 'TeX-fold-mode) TeX-fold-mode) - :help "Permanently show all folded content in paragraph containing point"] - ["Show Current Item" TeX-fold-clearout-item - :active (and (boundp 'TeX-fold-mode) TeX-fold-mode) - :help "Permanently show the item containing point"] - "-" - ["Hide or Show Current Item" TeX-fold-dwim - :active (and (boundp 'TeX-fold-mode) TeX-fold-mode) - :help "Hide or show the item containing point"]) - "Menu definition for commands from tex-fold.el.") - -(defvar TeX-customization-menu nil) - -(defvar TeX-common-menu-entries - `(("Multifile/Parsing" - ["Switch to Master File" TeX-home-buffer - :help "Switch to buffer of Master File, or buffer of last TeX command"] - ["Save Document" TeX-save-document - :help "Save all buffers associated with the current Master File"] - ["Set Master File" TeX-master-file-ask - :active (not (TeX-local-master-p)) - :help "Set the main file to run TeX commands on"] - ["Reset Buffer" TeX-normal-mode - :help "Save and reparse the current buffer for style information"] - ["Reset AUCTeX" (TeX-normal-mode t) :keys "C-u C-c C-n" - :help "Reset buffer and reload AUCTeX style files"]) - ["Find Documentation..." TeX-documentation-texdoc - :help "Get help on commands, packages, or TeX-related topics in general"] - ["Read the AUCTeX Manual" TeX-goto-info-page - :help "Everything worth reading"] - ("Customize AUCTeX" - ["Browse Options" - (customize-group 'AUCTeX) - :help "Open the customization buffer for AUCTeX"] - ["Extend this Menu" - (progn - (easy-menu-add-item - nil - ;; Ugly hack because docTeX mode uses the LaTeX menu. - (list (if (eq major-mode 'doctex-mode) "LaTeX" TeX-base-mode-name)) - (or TeX-customization-menu - (setq TeX-customization-menu - (customize-menu-create 'AUCTeX "Customize AUCTeX"))))) - :help "Make this menu a full-blown customization menu"]) - ["Report AUCTeX Bug" TeX-submit-bug-report - :help ,(format "Problems with AUCTeX %s? Mail us!" - AUCTeX-version)])) - - -;;; Verbatim constructs - -(defvar TeX-verbatim-p-function nil - "Mode-specific function to be called by `TeX-verbatim-p'. -It must accept optional argument POS for position.") -(make-variable-buffer-local 'TeX-verbatim-p-function) - -;; XXX: We only have an implementation for LaTeX mode at the moment (Oct 2009). -(defun TeX-verbatim-p (&optional pos) - "Return non-nil if position POS is in a verbatim-like construct. -A mode-specific implementation is required. If it is not -available, the function always returns nil." - (when TeX-verbatim-p-function - (funcall TeX-verbatim-p-function pos))) - - -;;; Comments - -(defvar TeX-comment-start-regexp "%" - "Regular expression matching a comment starter. -Unlike the variable `comment-start-skip' it should not match any -whitespace after the comment starter or any character before it.") -(make-variable-buffer-local 'TeX-comment-start-regexp) - -(defun TeX-uncomment () - "Delete comment characters from the beginning of each line in a comment." - (interactive) - (save-excursion - ;; Find first comment line - (beginning-of-line) - (while (and (looking-at (concat "^[ \t]*" TeX-comment-start-regexp)) - (not (bobp))) - (forward-line -1)) - (let ((beg (point))) - (forward-line 1) - ;; Find last comment line - (while (and (looking-at (concat "^[ \t]*" TeX-comment-start-regexp)) - (not (eobp))) - (forward-line 1)) - ;; Uncomment region - (uncomment-region beg (point))))) - -(defun TeX-comment-or-uncomment-paragraph () - "Comment or uncomment current paragraph." - (interactive) - (if (TeX-in-commented-line) - (TeX-uncomment) - (save-excursion - (beginning-of-line) - ;; Don't do anything if we are in an empty line. If this line - ;; is followed by a lot of commented lines, this shall prevent - ;; that mark-paragraph skips over these lines and marks a - ;; paragraph outside the visible window which might get - ;; commented without the user noticing. - (unless (looking-at "^[ \t]*$") - (mark-paragraph) - (comment-region (point) (mark)))))) - -(defun TeX-in-comment () - "Return non-nil if point is in a comment." - (if (or (bolp) - (null comment-start-skip) - (eq (preceding-char) ?\r)) - nil - (save-excursion - (save-match-data - (let ((pos (point))) - (beginning-of-line) - (and (or (looking-at comment-start-skip) - (re-search-forward comment-start-skip pos t)) - (not (TeX-verbatim-p)))))))) - -(defun TeX-in-commented-line () - "Return non-nil if point is in a line consisting only of a comment. -The comment can be preceded by whitespace. This means that -`TeX-in-commented-line' is more general than `TeX-in-line-comment' -which will not match commented lines with leading whitespace. But -`TeX-in-commented-line' will match commented lines without leading -whitespace as well." - (save-excursion - (forward-line 0) - (skip-chars-forward " \t") - (string= (buffer-substring-no-properties - (point) (min (point-max) (+ (point) (length comment-start)))) - comment-start))) - -(defun TeX-in-line-comment () - "Return non-nil if point is in a line comment. -A line comment is a comment starting in column one, that is, there is -no whitespace before the comment sign." - (save-excursion - (forward-line 0) - (string= (buffer-substring-no-properties - (point) (min (point-max) (+ (point) (length comment-start)))) - comment-start))) - -(defun TeX-comment-prefix () - "Return the comment prefix of the current line. -If there are no comment starters after potential whitespace at -the beginning of the line, return nil." - (save-excursion - (beginning-of-line) - (save-match-data - (when (looking-at (concat "\\([ \t]*" TeX-comment-start-regexp "+\\)+")) - (match-string 0))))) - -(defun TeX-forward-comment-skip (&optional count limit) - "Move forward to the next comment skip. -This may be a switch between commented and not commented adjacent -lines or between lines with different comment prefixes. With -argument COUNT do it COUNT times. If argument LIMIT is given, do -not move point further than this value." - (unless count (setq count 1)) - ;; A value of 0 is nonsense. - (when (= count 0) (setq count 1)) - (unless limit (setq limit (point-max))) - (dotimes (_ (abs count)) - (if (< count 0) - (forward-line -1) - (beginning-of-line)) - (let ((prefix (when (looking-at (concat "\\([ \t]*" - TeX-comment-start-regexp "+\\)+")) - (buffer-substring (+ (line-beginning-position) - (current-indentation)) - (match-end 0))))) - (while (save-excursion - (and (if (> count 0) - (<= (point) limit) - (>= (point) limit)) - (zerop (if (> count 0) - (forward-line 1) - (forward-line -1))) - (if prefix - (if (looking-at (concat "\\([ \t]*" - TeX-comment-start-regexp - "+\\)+")) - ;; If the preceding line is a commented line - ;; as well, check if the prefixes are - ;; identical. - (string= prefix - (buffer-substring - (+ (line-beginning-position) - (current-indentation)) - (match-end 0))) - nil) - (not (looking-at (concat "[ \t]*" - TeX-comment-start-regexp)))))) - (if (> count 0) - (forward-line 1) - (forward-line -1))) - (if (> count 0) - (forward-line 1))))) - -(defun TeX-backward-comment-skip (&optional count limit) - "Move backward to the next comment skip. -This may be a switch between commented and not commented adjacent -lines or between lines with different comment prefixes. With -argument COUNT do it COUNT times. If argument LIMIT is given, do -not move point to a position less than this value." - (unless count (setq count 1)) - (when (= count 0) (setq count 1)) - (unless limit (setq limit (point-min))) - (TeX-forward-comment-skip (- count) limit)) - -(defun TeX-comment-forward (&optional n) - "Skip forward over N comments. -Just like `forward-comment' but only for positive N -and can use regexps instead of syntax." - (comment-normalize-vars) - (comment-forward n)) - -(defun TeX-comment-padding-string () - "Return comment padding as a string. -The variable `comment-padding' can hold an integer or a string. -This function will return the appropriate string representation -regardless of its data type." - (if (integerp comment-padding) - (make-string comment-padding ? ) - comment-padding)) - - -;;; Indentation - -(defgroup TeX-indentation nil - "Indentation of TeX buffers in AUCTeX." - :group 'AUCTeX) - -(defcustom TeX-brace-indent-level 2 - "The level of indentation produced by an open brace." - :group 'TeX-indentation - :type 'integer) - -(defcustom TeX-indent-open-delimiters "" - "Additional open delimiters to increase indentation. -Include \"[\" to indent inside square brackets. -See `TeX-brace-count-line' and `TeX-indent-close-delimiters'." - :group 'TeX-indentation - :type '(string :tag "Open delimiters")) - -(defcustom TeX-indent-close-delimiters "" - "Additional close delimiters to increase indentation. -Include \"]\" to indent inside square brackets. -See `TeX-brace-count-line' and `TeX-indent-open-delimiters'." - :group 'TeX-indentation - :type '(string :tag "Close delimiters")) - -(defun TeX-comment-indent () - "Determine the indentation of a comment." - (if (looking-at "%%%") - (current-column) - (skip-chars-backward " \t") - (max (if (bolp) 0 (1+ (current-column))) - comment-column))) - -(defun TeX-brace-count-line () - "Count indent caused by open/closed braces. -In addition to \"{\" and \"}\", characters in -`TeX-indent-open-delimiters' and `TeX-indent-close-delimiters' -are also taken into account. Ignore them when they are escaped -by \"\\\". In comments, ignore \"{\" and \"}\" but don't ignore -additional characters." - (save-excursion - (let ((count 0) (limit (line-end-position)) char) - (while (progn - (skip-chars-forward - (concat "^{}\\\\" - TeX-indent-open-delimiters - TeX-indent-close-delimiters) - limit) - (when (and (< (point) limit) - (not (and (memq (setq char (char-after)) - '(?\{ ?\} ?\\)) - (TeX-in-comment)))) - (forward-char) - (cond ((memq char (append - TeX-indent-open-delimiters - '(?\{))) - (setq count (+ count TeX-brace-indent-level))) - ((memq char (append - TeX-indent-close-delimiters - '(?\}))) - (setq count (- count TeX-brace-indent-level))) - ((eq char ?\\) - (when (< (point) limit) - (forward-char) - t)))))) - count))) - -;;; Navigation - -(defvar TeX-search-syntax-table - (let ((table (make-syntax-table (make-char-table 'syntax-table)))) - ;; Preset mode-independent syntax entries. (Mode-dependent - ;; entries are set in the function `TeX-search-syntax-table'.) - ;; ?\", ?\( and ?\) explicitly get whitespace syntax because - ;; Emacs 21.3 and XEmacs don't generate a completely empty syntax - ;; table. - (dolist (elt '((?\f . ">") (?\n . ">") (?\" . " ") (?\( . " ") (?\) . " "))) - (modify-syntax-entry (car elt) (cdr elt) table)) - table) - "Syntax table used for searching purposes. -It should be accessed through the function `TeX-search-syntax-table'.") - -(defun TeX-search-syntax-table (&rest args) - "Return a syntax table for searching purposes. -ARGS may be a list of characters. For each of them the -respective predefined syntax is set. Currently the parenthetical -characters ?{, ?}, ?[, ?], ?\(, ?\), ?<, and ?> are supported. -The syntax of each of these characters not specified will be -reset to \" \"." - (let ((char-syntax-alist '((?\{ . "(}") (?\} . "){") - (?\[ . "(]") (?\] . ")[") - (?\( . "()") (?\) . ")(") - (?\< . "(>") (?\> . ")<")))) - ;; Clean entries possibly set before. - (modify-syntax-entry ?\\ " " TeX-search-syntax-table) - (modify-syntax-entry ?@ " " TeX-search-syntax-table) - (modify-syntax-entry ?\% " " TeX-search-syntax-table) - ;; Preset mode-dependent syntax entries. (Mode-independent entries - ;; are set when the variable `TeX-search-syntax-table' is created.) - (modify-syntax-entry (string-to-char TeX-esc) "\\" TeX-search-syntax-table) - (unless (eq major-mode 'texinfo-mode) - (modify-syntax-entry ?\% "<" TeX-search-syntax-table)) - ;; Clean up the entries which can be specified as arguments. - (dolist (elt char-syntax-alist) - (modify-syntax-entry (car elt) " " TeX-search-syntax-table)) - ;; Now set what we got. - (dolist (elt args) - (unless (assoc elt char-syntax-alist) (error "Char not supported")) - (modify-syntax-entry elt (cdr (assoc elt char-syntax-alist)) - TeX-search-syntax-table)) - ;; Return the syntax table. - TeX-search-syntax-table)) - -(defun TeX-find-balanced-brace (&optional count depth limit) - "Return the position of a balanced brace in a TeX group. -The function scans forward COUNT parenthetical groupings. -Default is 1. If COUNT is negative, it searches backwards. With -optional DEPTH>=1, find that outer level. If LIMIT is non-nil, -do not search further than this position in the buffer." - (let ((count (if count - (if (= count 0) (error "COUNT has to be <> 0") count) - 1)) - (depth (if depth - (if (< depth 1) (error "DEPTH has to be > 0") depth) - 1))) - (save-restriction - (when limit - (if (> count 0) - (narrow-to-region (point-min) limit) - (narrow-to-region limit (point-max)))) - (with-syntax-table (TeX-search-syntax-table ?\{ ?\}) - (condition-case nil - (scan-lists (point) count depth) - (error nil)))))) - -(defun TeX-find-closing-brace (&optional depth limit) - "Return the position of the closing brace in a TeX group. -The function assumes that point is inside the group, that is, after -an opening brace. With optional DEPTH>=1, find that outer level. -If LIMIT is non-nil, do not search further down than this -position in the buffer." - (TeX-find-balanced-brace 1 depth limit)) - -(defun TeX-find-opening-brace (&optional depth limit) - "Return the position of the opening brace in a TeX group. -The function assumes that point is inside the group, that is, before -a closing brace. With optional DEPTH>=1, find that outer level. -If LIMIT is non-nil, do not search further up than this position -in the buffer." - (TeX-find-balanced-brace -1 depth limit)) - -(defun TeX-find-macro-boundaries (&optional lower-bound) - "Return a list containing the start and end of a macro. -If LOWER-BOUND is given, do not search backward further than this -point in buffer. Arguments enclosed in brackets or braces are -considered part of the macro." - (save-restriction - (when lower-bound - (narrow-to-region lower-bound (point-max))) - (let ((orig-point (point)) - start-point) - ;; Point is located directly at the start of a macro. (-!-\foo{bar}) - (when (and (eq (char-after) (aref TeX-esc 0)) - (not (TeX-escaped-p))) - (setq start-point (point))) - ;; Point is located on a macro. (\fo-!-o{bar}) - (unless start-point - (save-excursion - (skip-chars-backward "A-Za-z@*") - (when (and (eq (char-before) (aref TeX-esc 0)) - (not (TeX-escaped-p (1- (point))))) - (setq start-point (1- (point)))))) - ;; Point is located in the argument of a macro. (\foo{ba-!-r}) - (unless start-point - (save-excursion - (catch 'abort - (let ((parse-sexp-ignore-comments t)) - (when (condition-case nil (progn (up-list) t) (error nil)) - (while (progn - (condition-case nil (backward-sexp) - (error (throw 'abort nil))) - (forward-comment -1) - (and (memq (char-before) '(?\] ?\})) - (not (TeX-escaped-p (1- (point))))))) - (skip-chars-backward "A-Za-z@*") - (when (and (eq (char-before) (aref TeX-esc 0)) - (not (TeX-escaped-p (1- (point))))) - (setq start-point (1- (point))))))))) - ;; Search forward for the end of the macro. - (when start-point - (save-excursion - (goto-char (TeX-find-macro-end-helper start-point)) - (if (< orig-point (point)) - (cons start-point (point)) - nil)))))) - -(defun TeX-find-macro-end-helper (start) - "Find the end of a macro given its START. -START is the position just before the starting token of the macro. -If the macro is followed by square brackets or curly braces, -those will be considered part of it." - (save-excursion - (save-match-data - (catch 'found - (goto-char (1+ start)) - (if (zerop (skip-chars-forward "A-Za-z@")) - (forward-char) - (skip-chars-forward "*")) - (while (not (eobp)) - (cond - ;; Skip over pairs of square brackets - ((or (looking-at "[ \t]*\n?\\(\\[\\)") ; Be conservative: Consider - ; only consecutive lines. - (and (looking-at (concat "[ \t]*" TeX-comment-start-regexp)) - (save-excursion - (forward-line 1) - (looking-at "[ \t]*\\(\\[\\)")))) - (goto-char (match-beginning 1)) - (condition-case nil - (forward-sexp) - (scan-error (throw 'found (point))))) - ;; Skip over pairs of curly braces - ((or (looking-at "[ \t]*\n?{") ; Be conservative: Consider - ; only consecutive lines. - (and (looking-at (concat "[ \t]*" TeX-comment-start-regexp)) - (save-excursion - (forward-line 1) - (looking-at "[ \t]*{")))) - (goto-char (match-end 0)) - (goto-char (or (TeX-find-closing-brace) - ;; If we cannot find a regular end, use the - ;; next whitespace. - (save-excursion (skip-chars-forward "^ \t\n") - (point))))) - (t - (throw 'found (point))))) - ;; Make sure that this function does not return nil, even - ;; when the above `while' loop is totally skipped. (bug#35638) - (throw 'found (point)))))) - -(defun TeX-find-macro-start (&optional limit) - "Return the start of a macro. -If LIMIT is given, do not search backward further than this point -in buffer. Arguments enclosed in brackets or braces are -considered part of the macro." - (car (TeX-find-macro-boundaries limit))) - -(defun TeX-find-macro-end () - "Return the end of a macro. -Arguments enclosed in brackets or braces are considered part of -the macro." - (cdr (TeX-find-macro-boundaries))) - -(defun TeX-search-forward-unescaped (string &optional bound noerror) - "Search forward from point for unescaped STRING. -The optional argument BOUND limits the search to the respective -buffer position. -If NOERROR is non-nil, return nil if the search failed instead of -throwing an error. -A pattern is escaped, if it is preceded by an odd number of escape -characters." - (TeX-search-unescaped string 'forward nil bound noerror)) - -(defun TeX-search-backward-unescaped (string &optional bound noerror) - "Search backward from point for unescaped STRING. -The optional argument BOUND limits the search to the respective -buffer position. -If NOERROR is non-nil, return nil if the search failed instead of -throwing an error. -A pattern is escaped, if it is preceded by an odd number of escape -characters." - (TeX-search-unescaped string 'backward nil bound noerror)) - -(defun TeX-re-search-forward-unescaped (regexp &optional bound noerror) - "Search forward from point for unescaped regular expression REGEXP. -The optional argument BOUND limits the search to the respective -buffer position. -If NOERROR is non-nil, return nil if the search failed instead of -throwing an error. -A pattern is escaped, if it is preceded by an odd number of escape -characters." - (TeX-search-unescaped regexp 'forward t bound noerror)) - -(defun TeX-search-unescaped (pattern - &optional direction regexp-flag bound noerror) - "Search for unescaped PATTERN in a certain DIRECTION. -DIRECTION can be indicated by the symbols 'forward and 'backward. -If DIRECTION is omitted, a forward search is carried out. -If REGEXP-FLAG is non-nil, PATTERN may be a regular expression, -otherwise a string. -The optional argument BOUND limits the search to the respective -buffer position. -If NOERROR is non-nil, return nil if the search failed instead of -throwing an error. -A pattern is escaped, if it is preceded by an odd number of escape -characters." - (let ((search-fun (if (eq direction 'backward) - (if regexp-flag 're-search-backward 'search-backward) - (if regexp-flag 're-search-forward 'search-forward)))) - (catch 'found - (while (funcall search-fun pattern bound noerror) - (when (not (TeX-escaped-p (match-beginning 0))) - (throw 'found (point))))))) - -(defun TeX-escaped-p (&optional pos) - "Return t if the character at position POS is escaped. -If POS is omitted, examine the character at point. -A character is escaped if it is preceded by an odd number of -escape characters, such as \"\\\" in LaTeX." - (save-excursion - (when pos (goto-char pos)) - (not (zerop (mod (skip-chars-backward (regexp-quote TeX-esc)) 2))))) - -(defun TeX-current-macro () - "Return the name of the macro containing point, nil if there is none." - (let ((macro-start (TeX-find-macro-start))) - (when macro-start - (save-excursion - (goto-char macro-start) - (forward-char (length TeX-esc)) - (buffer-substring-no-properties - (point) (progn (skip-chars-forward "@A-Za-z*") (point))))))) - -(defvar TeX-search-forward-comment-start-function nil - "Function to find the start of a comment. -The function should accept an optional argument for specifying -the limit of the search. It should return the position just -before the comment if one is found and nil otherwise. Point -should not be moved.") -(make-variable-buffer-local 'TeX-search-forward-comment-start-function) - -(defun TeX-search-forward-comment-start (&optional limit) - "Search forward for a comment start from current position till LIMIT. -If LIMIT is omitted, search till the end of the buffer. - -The search relies on `TeX-comment-start-regexp' being set -correctly for the current mode. - -Set `TeX-search-forward-comment-start-function' in order to -override the default implementation." - (if TeX-search-forward-comment-start-function - (funcall TeX-search-forward-comment-start-function limit) - (setq limit (or limit (point-max))) - (when (TeX-re-search-forward-unescaped TeX-comment-start-regexp limit t) - (match-beginning 0)))) - -;;; Fonts - -(defcustom TeX-font-list '((?\C-b "{\\bf " "}") - (?\C-c "{\\sc " "}") - (?\C-e "{\\em " "\\/}") - (?\C-i "{\\it " "\\/}") - (?\C-r "{\\rm " "}") - (?\C-s "{\\sl " "\\/}") - (?\C-t "{\\tt " "}") - (?\C-d "" "" t)) - "List of fonts used by `TeX-font'. - -Each entry is a list. -The first element is the key to activate the font. -The second element is the string to insert before point, and the third -element is the string to insert after point. -If the fourth and fifth element are strings, they specify the prefix and -suffix to be used in math mode. -An optional fourth (or sixth) element means always replace if t." - :group 'TeX-macro - :type '(repeat - (group - :value (?\C-a "" "") - (character :tag "Key") - (string :tag "Prefix") - (string :tag "Suffix") - (option (group - :inline t - (string :tag "Math Prefix") - (string :tag "Math Suffix"))) - (option (sexp :format "Replace\n" :value t))))) - -(defvar TeX-font-replace-function #'TeX-font-replace - "Determines the function which is called when a font should be replaced.") - -(defun TeX-describe-font-entry (entry) - "A textual description of an ENTRY in `TeX-font-list'." - (concat (format "%16s " (key-description (char-to-string (nth 0 entry)))) - (if (or (eq t (nth 3 entry)) (eq t (nth 5 entry))) - "-- delete font" - (format "%14s %-3s %14s %-3s" - (nth 1 entry) (nth 2 entry) - (if (stringp (nth 3 entry)) (nth 3 entry) "") - (if (stringp (nth 4 entry)) (nth 4 entry) ""))))) - -(defun TeX-font (replace what) - "Insert template for font change command. -If REPLACE is not nil, replace current font. WHAT determines the font -to use, as specified by `TeX-font-list'." - (interactive "*P\nc") - (TeX-update-style) - (let* ((entry (assoc what TeX-font-list)) - (in-math (texmathp)) - (before (nth 1 entry)) - (after (nth 2 entry))) - (setq replace (or replace (eq t (nth 3 entry)) (eq t (nth 5 entry)))) - (if (and in-math (stringp (nth 3 entry))) - (setq before (nth 3 entry) - after (nth 4 entry))) - (cond ((null entry) - (let ((help (concat - "Font list: " - "KEY TEXTFONT MATHFONT\n\n" - (mapconcat #'TeX-describe-font-entry - TeX-font-list "\n")))) - (with-output-to-temp-buffer "*Help*" - (set-buffer "*Help*") - (insert help)))) - (replace - (funcall TeX-font-replace-function before after)) - ((TeX-active-mark) - (save-excursion - (cond ((> (mark) (point)) - (insert before) - (goto-char (mark)) - (insert after)) - (t - (insert after) - (goto-char (mark)) - (insert before))))) - (t - (insert before) - (save-excursion - (insert after)))))) - -(defun TeX-font-replace (start end) - "Replace font specification around point with START and END. -For modes with font specifications like `{\\font text}'. -See also `TeX-font-replace-macro' and `TeX-font-replace-function'." - (save-excursion - (while (not (looking-at "{\\\\[a-zA-Z]+ ")) - (up-list -1)) - (forward-sexp) - (save-excursion - (replace-match start t t)) - (if (save-excursion - (backward-char 3) - (if (looking-at (regexp-quote "\\/}")) - (progn - (delete-char 3) - nil) - t)) - (delete-char -1)) - (insert end))) - -(defun TeX-font-replace-macro (start end) - "Replace font specification around point with START and END. -For modes with font specifications like `\\font{text}'. -See also `TeX-font-replace' and `TeX-font-replace-function'." - (let ((font-list TeX-font-list) - cmds strings regexp) - (while font-list - (setq strings (cdr (car font-list)) - font-list (cdr font-list)) - (and (stringp (car strings)) (null (string= (car strings) "")) - (setq cmds (cons (car strings) cmds))) - (setq strings (cdr (cdr strings))) - (and (stringp (car strings)) (null (string= (car strings) "")) - (setq cmds (cons (car strings) cmds)))) - (setq regexp (mapconcat #'regexp-quote cmds "\\|")) - (save-excursion - (catch 'done - (while t - (if (/= ?\\ (following-char)) - (skip-chars-backward "a-zA-Z ")) - (skip-chars-backward (regexp-quote TeX-esc)) - (if (looking-at regexp) - (throw 'done t) - (up-list -1)))) - ;; Use stripped syntax table in order to get stuff like "\emph{(}" right. - (with-syntax-table (TeX-search-syntax-table ?\{ ?\}) - (forward-sexp 2)) - (save-excursion - (replace-match start t t)) - (delete-char -1) - (insert end)))) - -;;; Dollars -;; -;; Rewritten from scratch with use of `texmathp' by -;; Carsten Dominik <dominik@strw.leidenuniv.nl> - -(defvar TeX-symbol-marker nil) - -(defvar TeX-symbol-marker-pos 0) - -;; The following constants are no longer used, but kept in case some -;; foreign code uses any of them. -(defvar TeX-dollar-sign ?$ - "Character used to enter and leave math mode in TeX.") -(defconst TeX-dollar-string (char-to-string TeX-dollar-sign)) -(defconst TeX-dollar-regexp - (concat "^" (regexp-quote TeX-dollar-string) "\\|[^" TeX-esc "]" - (regexp-quote TeX-dollar-string))) - -(defcustom TeX-math-toggle-off-input-method t - "If non-nil, auto turn off some input methods when entering math mode. -See `TeX-math-input-method-off-regexp'." - :group 'TeX-macro - :type 'boolean) - -(defcustom TeX-electric-math nil - "If non-nil, when outside math mode `TeX-insert-dollar' will -insert symbols for opening and closing inline equation and put -the point between them. If there is an active region, -`TeX-insert-dollar' will put around it symbols for opening and -closing inline equation and keep the region active, with point -after closing symbol. If you press `$' again, you can toggle -between inline equation, display equation, and no equation. - -If non-nil and point is inside math mode right between a couple -of single dollars, pressing `$' will insert another pair of -dollar signs and leave the point between them. - -If nil, `TeX-insert-dollar' will simply insert \"$\" at point, -this is the default. - -If non-nil, this variable is a cons cell whose CAR is the string -to insert before point, the CDR is the string to insert after -point. You can choose between \"$...$\" and \"\\(...\\)\"." - :group 'TeX-macro - :type '(choice (const :tag "No electricity" nil) - (const :tag "$...$" ("$" . "$")) - (const :tag "\\(...\\)" ("\\(" . "\\)")) - (cons :tag "Other" - (string :tag "Insert before point") - (string :tag "Insert after point")))) - -(defun TeX-insert-dollar (&optional arg) - "Insert dollar sign. - -If current math mode was not entered with a dollar, refuse to -insert one. Show matching dollar sign if this dollar sign ends -the TeX math mode and `blink-matching-paren' is non-nil. - -When outside math mode, the behavior is controlled by the variable -`TeX-electric-math'. - -With raw \\[universal-argument] prefix, insert exactly one dollar -sign. With optional ARG, insert that many dollar signs." - (interactive "P") - (cond - ((and arg (listp arg)) - ;; C-u always inserts one - (insert "$")) - (arg - ;; Numerical arg inserts that many - (insert (make-string (prefix-numeric-value arg) ?\$))) - ((or (TeX-escaped-p) (TeX-verbatim-p)) - ;; Point is escaped with `\' or is in a verbatim-like construct, so just - ;; insert one $. - (insert "$")) - ((texmathp) - ;; We are inside math mode - (cond - ((and TeX-electric-math - (eq (preceding-char) ?\$) - (eq (following-char) ?\$)) - ;; Point is between "$$" and `TeX-electric-math' is non-nil - insert - ;; another pair of dollar signs and leave point between them. - (insert "$$") - (backward-char)) - ((and (stringp (car texmathp-why)) - (string-equal (substring (car texmathp-why) 0 1) "\$")) - ;; Math mode was turned on with $ or $$ - insert a single $. - (insert "$") - ;; Compatibility, `TeX-math-close-double-dollar' has been removed - ;; after AUCTeX 11.87. - (if (boundp 'TeX-math-close-double-dollar) - (message - (concat "`TeX-math-close-double-dollar' has been removed," - "\nplease use `TeX-electric-math' instead."))) - (when (and blink-matching-paren - (or (string= (car texmathp-why) "$") - (zerop (mod (save-excursion - (skip-chars-backward "$")) 2)))) - (save-excursion - (goto-char (cdr texmathp-why)) - (if (pos-visible-in-window-p) - (sit-for blink-matching-delay) - (message "Matches %s" - (buffer-substring - (point) (progn (end-of-line) (point)))))))) - (t - ;; Math mode was not entered with dollar - we cannot finish it with one. - (message "Math mode started with `%s' cannot be closed with dollar" - (car texmathp-why))))) - (t - ;; Just somewhere in the text. - (cond - ((and TeX-electric-math (TeX-active-mark)) - (if (> (point) (mark)) - (exchange-point-and-mark)) - (cond - ;; $...$ to $$...$$ - ((and (eq last-command #'TeX-insert-dollar) - (re-search-forward "\\=\\$\\([^$][^z-a]*[^$]\\)\\$" (mark) t)) - (replace-match "$$\\1$$") - (set-mark (match-beginning 0))) - ;; \(...\) to \[...\] - ((and (eq last-command #'TeX-insert-dollar) - (re-search-forward "\\=\\\\(\\([^z-a]*\\)\\\\)" (mark) t)) - (replace-match "\\\\[\\1\\\\]") - (set-mark (match-beginning 0))) - ;; Strip \[...\] or $$...$$ - ((and (eq last-command #'TeX-insert-dollar) - (or (re-search-forward "\\=\\\\\\[\\([^z-a]*\\)\\\\\\]" (mark) t) - (re-search-forward "\\=\\$\\$\\([^z-a]*\\)\\$\\$" (mark) t))) - (replace-match "\\1") - (set-mark (match-beginning 0))) - (t - ;; We use `save-excursion' because point must be situated before opening - ;; symbol. - (save-excursion (insert (car TeX-electric-math))) - (exchange-point-and-mark) - (insert (cdr TeX-electric-math)))) - ;; Keep the region active. - (TeX-activate-region)) - (TeX-electric-math - (insert (car TeX-electric-math)) - (save-excursion (insert (cdr TeX-electric-math))) - (if blink-matching-paren - (progn - (backward-char) - (sit-for blink-matching-delay) - (forward-char)))) - ;; In any other case just insert a single $. - ((insert "$"))))) - (TeX-math-input-method-off)) - -(defcustom TeX-math-input-method-off-regexp - (concat "^" (regexp-opt '("chinese" "japanese" "korean" "bulgarian" "russian") t)) - "Regexp matching input methods to be deactivated when entering math mode." - :group 'TeX-misc - :type 'regexp) - -(defun TeX-math-input-method-off () - "Toggle off input method when entering math mode." - (and TeX-math-toggle-off-input-method - (texmathp) - current-input-method - (string-match TeX-math-input-method-off-regexp current-input-method) - (deactivate-input-method))) - -;;; Simple Commands - -(defvar TeX-normal-mode-reset-list '(TeX-style-hook-list) - "List of variables to reset with `\\[universal-argument] \\[TeX-normal-mode]'. -AUCTeX libraries and styles should add variables for reset to -this list.") - -(defun TeX-normal-mode (&optional arg) - "Remove all information about this buffer, and apply the style hooks again. -Save buffer first including style information. -With optional argument ARG, also reload the style hooks." - (interactive "*P") - (if arg - (dolist (var TeX-normal-mode-reset-list) - (set var nil))) - (let ((TeX-auto-save t)) - (if (buffer-modified-p) - (save-buffer) - (TeX-auto-write))) - (normal-mode) - ;; See also addition to `find-file-hook' in `VirTeX-common-initialization'. - (when (eq TeX-master 'shared) (TeX-master-file nil nil t)) - (TeX-update-style t)) - -(defgroup TeX-quote nil - "Quoting in AUCTeX." - :group 'AUCTeX) - -(defcustom TeX-open-quote "``" - "String inserted by typing \\[TeX-insert-quote] to open a quotation." - :group 'TeX-quote - :type 'string) - -(defcustom TeX-close-quote "''" - "String inserted by typing \\[TeX-insert-quote] to close a quotation." - :group 'TeX-quote - :type 'string) - -(defcustom TeX-quote-after-quote nil - "Behaviour of \\[TeX-insert-quote]. -Nil means standard behaviour; when non-nil, opening and closing -quotes are inserted only after \"." - :group 'TeX-quote - :type 'boolean) - -(defcustom TeX-quote-language-alist nil - "Alist for overriding the default language-specific quote insertion. -First element in each item is the name of the language as set by -the language style file as a string. Second element is the -opening quotation mark. Third element is the closing quotation -mark. Opening and closing quotation marks can be specified -directly as strings or as functions returning a string. Fourth -element is a boolean specifying insertion behavior, overriding -`TeX-quote-after-quote'. See Info node `(auctex)European' for -valid languages." - :group 'TeX-quote - :link '(custom-manual "(auctex)European") - :type '(repeat (group (choice - (const "czech") - (const "danish") - (const "dutch") - (const "german") - (const "ngerman") - (const "french") ;; not frenchb or francais - (const "italian") - (const "polish") - (const "portuguese") - (const "slovak") - (const "swedish") - (string :tag "Other Language")) - (choice :tag "Opening quotation mark" string function) - (choice :tag "Closing quotation mark" string function) - (boolean :tag "Insert plain quote first" :value t)))) - -(defvar TeX-quote-language nil - "If non-nil determines behavior of quote insertion. -It is usually set by language-related style files. Its value has -the same structure as the elements of `TeX-quote-language-alist'. -The symbol `override' can be used as its car in order to override -the settings of style files. Style files should therefore check -if this symbol is present and not alter `TeX-quote-language' if -it is.") -(make-variable-buffer-local 'TeX-quote-language) - -(defun TeX-insert-quote (force) - "Insert the appropriate quotation marks for TeX. -Inserts the value of `TeX-open-quote' (normally \\=`\\=`) or `TeX-close-quote' -\(normally \\='\\=') depending on the context. If `TeX-quote-after-quote' -is non-nil, this insertion works only after \". -With prefix argument FORCE, always inserts \" characters." - (interactive "*P") - (if (or force - ;; Do not insert TeX quotes in verbatim, math or comment constructs. - (and (fboundp 'font-latex-faces-present-p) - (font-latex-faces-present-p '(font-latex-verbatim-face - font-latex-math-face - font-lock-comment-face)) - (font-latex-faces-present-p '(font-latex-verbatim-face - font-latex-math-face - font-lock-comment-face) - (1- (point)))) - (texmathp) - (and (TeX-in-comment) (not (eq major-mode 'doctex-mode)))) - (self-insert-command (prefix-numeric-value force)) - (TeX-update-style) - (let* ((lang-override (if (eq (car TeX-quote-language) 'override) - TeX-quote-language - (assoc (car TeX-quote-language) - TeX-quote-language-alist))) - (lang (or lang-override TeX-quote-language)) - (open-quote (if lang (nth 1 lang) TeX-open-quote)) - (close-quote (if lang (nth 2 lang) TeX-close-quote)) - (q-after-q (if lang (nth 3 lang) TeX-quote-after-quote))) - (when (functionp open-quote) - (setq open-quote (funcall open-quote))) - (when (functionp close-quote) - (setq close-quote (funcall close-quote))) - (if q-after-q - (insert (cond ((bobp) - ?\") - ((save-excursion - (TeX-looking-at-backward - (concat (regexp-quote open-quote) "\\|" - (regexp-quote close-quote)) - (max (length open-quote) (length close-quote)))) - (delete-char (- (length (match-string 0)))) - "\"\"") - ((< (save-excursion (skip-chars-backward "\"")) -1) - ?\") - ((not (= (preceding-char) ?\")) - ?\") - ((save-excursion - (forward-char -1) - (bobp)) - (delete-char -1) - open-quote) - ((save-excursion - (forward-char -2) ;;; at -1 there is double quote - (looking-at "[ \t\n]\\|\\s(")) - (delete-char -1) - open-quote) - (t - (delete-char -1) - close-quote))) - (insert (cond ((bobp) - open-quote) - ((= (preceding-char) (string-to-char TeX-esc)) - ?\") - ((= (preceding-char) ?\") - ?\") - ((and (<= (length open-quote) (- (point) (point-min))) - (save-excursion - (forward-char (- (length open-quote))) - (looking-at (regexp-quote open-quote)))) - (delete-char (- (length open-quote))) - ?\") - ((and (<= (length open-quote) (- (point) (point-min))) - (save-excursion - (forward-char (- (length close-quote))) - (looking-at (regexp-quote close-quote)))) - (delete-char (- (length close-quote))) - ?\") - ((save-excursion - (forward-char -1) - (looking-at "[ \t\n]\\|\\s(")) - open-quote) - (t - close-quote))))))) - -(defun TeX-insert-punctuation () - "Insert point or comma, cleaning up preceding space." - (interactive) - (expand-abbrev) - (if (TeX-looking-at-backward "\\\\/\\(}+\\)" 50) - (replace-match "\\1" t)) - (call-interactively #'self-insert-command)) - -(defun TeX-insert-braces (arg) - "Make a pair of braces around next ARG sexps and leave point inside. -No argument is equivalent to zero: just insert braces and leave point -between. - -If there is an active region, ARG will be ignored, braces will be -inserted around the region, and point will be left after the -closing brace." - (interactive "P") - (if (TeX-active-mark) - (progn - (if (< (point) (mark)) - (exchange-point-and-mark)) - (insert TeX-grcl) - (save-excursion - (goto-char (mark)) - (insert TeX-grop))) - (insert TeX-grop) - (save-excursion - (if arg (forward-sexp (prefix-numeric-value arg))) - (insert TeX-grcl)))) - -;;;###autoload -(defun TeX-submit-bug-report () - "Submit a bug report on AUCTeX via mail. - -Don't hesitate to report any problems or inaccurate documentation. - -If you don't have setup sending mail from Emacs, please copy the -output buffer into your mail program, as it gives us important -information about your AUCTeX version and AUCTeX configuration." - (interactive) - (require 'reporter) - (defvar reporter-prompt-for-summary-p) - (let ((reporter-prompt-for-summary-p "Bug report subject: ")) - (reporter-submit-bug-report - "bug-auctex@gnu.org" - AUCTeX-version - (list 'AUCTeX-date - 'window-system - 'LaTeX-version - 'TeX-style-path - 'TeX-auto-save - 'TeX-parse-self - 'TeX-master - 'TeX-command-list) - nil - ;; reporter adds too many new lines around salutation text, that we don't - ;; want, since it's itself a new line. - (lambda () - (save-excursion - (goto-char (point-min)) - (re-search-forward mail-header-separator) - (forward-char) - (delete-char 1) - (forward-char) - (delete-char 2))) - (propertize - "\n" 'display - (with-temp-buffer - (insert - "Remember to cover the basics, that is, what you expected to happen and -what in fact did happen. - -Be sure to consult the FAQ section in the manual before submitting -a bug report. In addition check if the bug is reproducable with an -up-to-date version of AUCTeX. So please upgrade to the version -available from ") - (insert-text-button - "https://www.gnu.org/software/auctex/" - 'face 'link - 'help-echo (concat "mouse-2, RET: Follow this link") - 'action (lambda (_button) - (browse-url "https://www.gnu.org/software/auctex/")) - 'follow-link t) - (insert " if your -installation is older than the one available from the web site. - -If the bug is triggered by a specific \(La\)TeX file, you should try -to produce a minimal sample file showing the problem and include it -in your report. - -Your report will be posted for the auctex package at the GNU bug -tracker. Visit ") - (insert-text-button - "https://debbugs.gnu.org/cgi/pkgreport.cgi?pkg=auctex" - 'face 'link - 'help-echo (concat "mouse-2, RET: Follow this link") - 'action (lambda (_button) - (browse-url "https://debbugs.gnu.org/cgi/pkgreport.cgi?pkg=auctex")) - 'follow-link t) - (insert "\nto browse existing AUCTeX bugs. -------------------------------------------------------------------------\n\n") - (buffer-string)))))) - - -;;; Documentation - -(defun TeX-documentation-texdoc (&optional arg) - "Run texdoc to read documentation. - -Prompt for selection of the package of which to show the documentation. - -If called with a prefix argument ARG, after selecting the -package, prompt for selection of the manual of that package to -show." - (interactive "P") - (let ((pkg (thing-at-point 'symbol)) - buffer list doc) - ;; Strip off properties. XXX: XEmacs doesn't have - ;; `substring-no-properties'. - (set-text-properties 0 (length pkg) nil pkg) - (setq pkg (TeX-read-string "View documentation for: " pkg)) - (unless (zerop (length pkg)) - (if arg - ;; Called with prefix argument: run "texdoc --list --nointeract <pkg>" - (progn - ;; Create the buffer, insert the result of the command, and - ;; accumulate the list of manuals. - (with-current-buffer (get-buffer-create - (setq buffer (format "*texdoc: %s*" pkg))) - (erase-buffer) - (insert (shell-command-to-string - (concat "texdoc --list --nointeract " pkg))) - (goto-char 1) ; No need to use `point-min' here. - (save-excursion - (while (re-search-forward - ;; XXX: XEmacs doesn't support character classes in - ;; regexps, like "[:alnum:]". - "^ *\\([0-9]+\\) +\\([-~/a-zA-Z0-9_.${}#%,:\\ ()]+\\)" nil t) - (push (cons (match-string 1) (match-string 2)) list)))) - (unwind-protect - (cond - ((null (executable-find "texdoc")) - ;; Note: `shell-command-to-string' uses shell, only - ;; `call-process' looks at `exec-path', thus only here makes - ;; sense to use `executable-find' to test whether texdoc is - ;; available. - (message "texdoc not found")) - (list - ;; Go on if there are manuals listed: show the buffer, prompt - ;; for the number of the manual, then run - ;; texdoc --just-view <doc> - (TeX-pop-to-buffer (get-buffer buffer)) - (condition-case nil - (when (setq doc - (cdr (assoc (TeX-read-string "Please enter \ -the number of the file to view, anything else to skip: ") list))) - (call-process "texdoc" nil 0 nil "--just-view" doc)) - ;; Exit gently if a `quit' signal is thrown. - (quit nil))) - (t (message "No documentation found for %s" pkg))) - ;; In any case quit-and-kill the window. - (when (get-buffer-window buffer) - (quit-window t (get-buffer-window buffer))))) - ;; Called without prefix argument: just run "texdoc --view <pkg>" and - ;; show the output, so that the user is warned in case it doesn't find - ;; the documentation or "texdoc" is not available. - (message "%s" - ;; The folowing code to the end of `defun' used to be - ;; just - ;; (shell-command-to-string (concat "texdoc --view " pkg)) - ;; , but in some cases it blocks emacs until the user - ;; quits the viewer (bug#28905). - (with-output-to-string - (let* (;; Use pipe rather than pty because the - ;; latter causes atril (evince variant - ;; viewer) to exit before showing anything. - (process-connection-type nil) - (process (start-process-shell-command - "Doc view" standard-output - (concat "texdoc --view " pkg)))) - ;; Suppress the message "Process Doc view - ;; finished". - (set-process-sentinel process #'ignore) - ;; Kill temp buffer without query. This is - ;; necessary, at least for some environment, if - ;; the underlying shell can't find the texdoc - ;; executable. - (set-process-query-on-exit-flag process nil) - ;; Don't discard shell output. - (accept-process-output process)))))))) - -(defun TeX-goto-info-page () - "Read documentation for AUCTeX in the info system." - (interactive) - (info "auctex")) - -(autoload 'info-lookup->completions "info-look") - -(defvar TeX-doc-backend-alist - '((texdoc (plain-tex-mode latex-mode doctex-mode ams-tex-mode context-mode) - (lambda () - (when (executable-find "texdoc") - (TeX-search-files-by-type 'docs 'global t t))) - (lambda (doc) - ;; texdoc in MiKTeX requires --view in order to start - ;; the viewer instead of an intermediate web page. - (call-process "texdoc" nil 0 nil "--view" doc))) - (latex-info (latex-mode) - (lambda () - (mapcar (lambda (x) - (let ((x (car x))) - (if (string-match "\\`\\\\" x) - (substring x 1) x))) - (info-lookup->completions 'symbol 'latex-mode))) - (lambda (doc) - (info-lookup-symbol (concat "\\" doc) 'latex-mode))) - (texinfo-info (texinfo-mode) - (lambda () - (mapcar (lambda (x) - (let ((x (car x))) - (if (string-match "\\`@" x) - (substring x 1) x))) - (info-lookup->completions 'symbol - 'texinfo-mode))) - (lambda (doc) - (info-lookup-symbol (concat "@" doc) 'texinfo-mode)))) - "Alist of backends used for looking up documentation. -Each item consists of four elements. - -The first is a symbol describing the backend's name. - -The second is a list of modes the backend should be activated in. - -The third is a function returning a list of documents available -to the backend. It should return nil if the backend is not -available, for example if a required executable is not present on the -system in question. - -The fourth is a function for displaying the documentation. The -function should accept a single argument, the chosen package, -command, or document name.") - -(defun TeX-doc (&optional name) - "Display documentation for string NAME. -NAME may be a package, a command, or a document." - (interactive) - (let (docs) - ;; Build the lists of available documentation used for completion. - (dolist (elt TeX-doc-backend-alist) - (when (memq major-mode (nth 1 elt)) - (let ((completions (funcall (nth 2 elt)))) - (unless (null completions) - (cl-pushnew (cons completions (nth 0 elt)) docs :test #'equal))))) - (if (null docs) - (progn - (if (executable-find "texdoc") - ;; Fallback if we did not find anything via the backend list. - (let ((doc (read-from-minibuffer "Input for `texdoc': "))) - (when doc (call-process "texdoc" nil 0 nil "--view" doc))) - ;; Give up. - (message "No documentation found"))) - ;; Ask the user about the package, command, or document. - (when (and (called-interactively-p 'any) - (or (not name) (string= name ""))) - (let ((symbol (thing-at-point 'symbol)) - contained completions) - ;; Is the symbol at point contained in the lists of available - ;; documentation? - (setq contained (catch 'found - (dolist (elt docs) - (when (member symbol (car elt)) - (throw 'found t))))) - ;; Setup completion list in a format suitable for `completing-read'. - (dolist (elt docs) - ;; FIXME: Probably not needed! - (setq completions (nconc (mapcar #'list (car elt)) completions))) - ;; Query user. - (setq name (completing-read - (if contained - (format "Package, command, or document (default %s): " - symbol) - "Package, command, or document: ") - completions nil nil nil nil symbol)))) - (if (not name) - (message "No documentation specified") - ;; XXX: Provide way to choose in case a symbol can be found in - ;; more than one backend. - (let* ((backend (catch 'found - (dolist (elt docs) - (when (member name (car elt)) - (throw 'found (cdr elt))))))) - (if backend - (funcall (nth 3 (assoc backend TeX-doc-backend-alist)) name) - (message "Documentation not found"))))))) - - -;;; Ispell Support - -(defun TeX-run-ispell (_command _string file) - "Run ispell on current TeX buffer." - (cond ((string-equal file (TeX-region-file)) - (call-interactively #'ispell-region)) - (t - (ispell-buffer)))) - -(defun TeX-ispell-document (name) - "Run ispell on all open files belonging to the current document." - (interactive (list (TeX-master-file))) - (if (string-equal name "") - (setq name (TeX-master-file))) - - (let ((regexp (concat "\\`\\(" - (mapconcat (lambda (dir) - (regexp-quote - (expand-file-name - (file-name-as-directory dir)))) - (append (when (file-name-directory name) - (list (file-name-directory name))) - TeX-check-path) - "\\|") - "\\).*\\(" - (mapconcat #'regexp-quote - (cons (file-name-nondirectory name) - (TeX-style-list)) - "\\|") - "\\)\\.\\(" - (mapconcat #'identity TeX-file-extensions "\\|") - "\\)\\'")) - (buffers (buffer-list))) - (while buffers - (let* ((buffer (car buffers)) - (name (buffer-file-name buffer))) - (setq buffers (cdr buffers)) - (when (and name (string-match regexp name)) - (save-excursion (switch-to-buffer buffer) (ispell-buffer)) - t))))) - -(defcustom TeX-ispell-extend-skip-list t - "Whether to extend regions selected for skipping during spell checking." - :group 'TeX-misc - :type 'boolean) - -;; These functions are used to add new items to -;; `ispell-tex-skip-alists' -- see tex-ispell.el: -(defun TeX-ispell-skip-setcar (skip) - "Add SKIP to car of `ispell-tex-skip-alists'. -SKIP is an alist with the format described in -`ispell-tex-skip-alists'. Each element in SKIP is added on top -of the car of `ispell-tex-skip-alists'. This only happens if -`TeX-ispell-extend-skip-list' is non-nil." - (when TeX-ispell-extend-skip-list - (let ((raws (car ispell-tex-skip-alists)) - (envs (cadr ispell-tex-skip-alists))) - (dolist (x skip) - (cl-pushnew x raws :test #'equal)) - (setq ispell-tex-skip-alists (list raws envs))))) - -(defun TeX-ispell-skip-setcdr (skip) - "Add SKIP to cdr of `ispell-tex-skip-alists'. -SKIP is an alist with the format described in -`ispell-tex-skip-alists'. Each element in SKIP is added on top -of the cdr of `ispell-tex-skip-alists'. This only happens if -`TeX-ispell-extend-skip-list' is non-nil." - (when TeX-ispell-extend-skip-list - (let ((raws (car ispell-tex-skip-alists)) - (envs (cadr ispell-tex-skip-alists))) - (dolist (x skip) - (cl-pushnew x envs :test #'equal)) - (setq ispell-tex-skip-alists (list raws envs))))) - -(defun TeX-ispell-tex-arg-end (&optional arg1 arg2 arg3) - "Skip across ARG1, ARG2 and ARG3 number of braces and brackets. -This function is a variation of `ispell-tex-arg-end'. It should -be used when adding skip regions to `ispell-tex-skip-alists' for -constructs like: - - \\begin{tabularx}{300pt}[t]{lrc} ... - or - \\fontspec{font name}[font features] - -where optional and/or mandatory argument(s) follow(s) a mandatory -one. ARG1 is the number of mandatory arguments before the -optional one, ARG2 the max. number of following optional -arguments, ARG3 is the max. number of mandatory arguments -following. Omitting argument means 1. - -Here some examples for additions to `ispell-tex-skip-alists': - - \\begin{tabularx}{300pt}[t]{lrc} ... - ARG 1 2 3 - (\"tabularx\" TeX-ispell-tex-arg-end) or equivalent - (\"tabularx\" TeX-ispell-tex-arg-end 1 1 1) - - \\fontspec{font name}[font features] - ARG1 ARG2 ARG3=0 - (\"\\\\\\\\fontspec\" TeX-ispell-tex-arg-end 1 1 0) - - \\raisebox{lift}[height][depth]{contents} - ARG1 ARG2 ARG3=0 (checked by Ispell) - (\"\\\\\\\\raisebox\" TeX-ispell-tex-arg-end 1 2 0) - -Optional arguments before the first mandatory one are all -skipped." - (condition-case nil - (progn - (while (looking-at "[ \t\n]*\\[") (forward-sexp)) - (forward-sexp (or arg1 1)) - (let ((num 0)) - (while (and (looking-at "[ \t\n]*\\[") - (< num (or arg2 1))) - (setq num (1+ num)) - (forward-sexp))) - (forward-sexp (or arg3 1))) - (error - (message "Error skipping s-expressions at point %d" (point)) - (sit-for 2)))) - -(defun TeX-ispell-tex-arg-verb-end (&optional arg) - "Skip an optional argument, ARG number of mandatory ones and verbatim content. -This function always checks if one optional argument in brackets -is given and skips over it. If ARG is a number, it skips over -that many mandatory arguments in braces. Then it checks for -verbatim content to skip which is enclosed by a character given -in `TeX-ispell-verb-delimiters' or in braces, otherwise raises an -error." - (condition-case nil - (progn - (when (looking-at "[ \t\n]*\\[") (forward-sexp)) - (when (and arg (looking-at "{")) - (forward-sexp arg)) - (cond ((looking-at (concat "[" TeX-ispell-verb-delimiters "]")) - (forward-char) - (skip-chars-forward (concat "^" (string (char-before)))) - (forward-char)) - ((looking-at "{") - (forward-sexp)) - (t (error nil)))) - (error - (message "Verbatim delimiter is not one of %s" - (split-string TeX-ispell-verb-delimiters "" t)) - (sit-for 2)))) - -;;; Abbrev mode - -(defmacro TeX-abbrev-mode-setup (mode) - "Set up the abbrev table and variable for MODE." - (let ((symbol (intern (concat (symbol-name mode) "-abbrev-table"))) - (name (TeX-mode-prefix mode))) - `(progn - (defvar ,symbol nil - ,(format "Abbrev table for %s mode." name)) - (define-abbrev-table ',symbol nil) - (abbrev-table-put ,symbol :parents (list text-mode-abbrev-table))))) - - -;;; Special provisions for other modes and libraries - -;; desktop-locals-to-save is broken by design. Don't have -;; buffer-local values of it. -(eval-after-load "desktop" - '(progn - (dolist (elt '(TeX-master)) - (unless (member elt (default-value 'desktop-locals-to-save)) - (setq-default desktop-locals-to-save - (cons elt (default-value 'desktop-locals-to-save))))) - (add-hook 'desktop-after-read-hook (lambda () - (TeX-set-mode-name t))))) - -;; delsel.el, `delete-selection-mode' -(put 'TeX-newline 'delete-selection t) -(put 'TeX-insert-quote 'delete-selection t) -(put 'TeX-insert-backslash 'delete-selection t) -;; When `TeX-electric-math' is non-nil, `TeX-insert-dollar' interferes with -;; `delete-selection-mode', but when it's nil users may want to be able to -;; delete active region if `delete-selection-mode' is active, see bug#23177. We -;; can dynamically determine the behavior of `delete-selection' with -;; `TeX-insert-dollar' based on the value of `TeX-electric-math'. -(put 'TeX-insert-dollar 'delete-selection - (lambda () (null TeX-electric-math))) - -(defun TeX--list-of-string-p (lst) - "Return non-nil if LST is a list of strings. -Used as function for validating a variable's `safe-local-variable' property." - (and (listp lst) - (let ((all-strings t)) - (while (and all-strings lst) - (setq all-strings (stringp (car lst))) - (setq lst (cdr lst))) - all-strings))) - -;; add-log.el: This function is a variation of -;; `tex-current-defun-name' defined in `tex-mode.el'. In `latex.el', -;; the variable `add-log-current-defun-function' is set to this -;; function. -(defun TeX-current-defun-name () - "Return the name of the TeX section/paragraph/chapter at point, or nil." - (save-excursion - (let (s1 e1 s2 e2) - ;; If we are now precisely at the beginning of a sectioning - ;; command, move forward and make sure `re-search-backward' - ;; finds this one rather than the previous one: - (or (eobp) (progn - (when (looking-at-p "\\\\") - (forward-char)) - (unless (eolp) - (forward-sexp)))) - ;; Search backward for sectioning command. If - ;; `LaTeX-section-label' is buffer-local, assume that a style - ;; has changed the value and recalculate the string. Otherwise - ;; take the standard one: - (when (re-search-backward - (if (local-variable-p 'LaTeX-section-label) - (concat "\\\\" - (regexp-opt - (remove "part" (mapcar #'car LaTeX-section-label))) - "\\*?") - "\\\\\\(sub\\)*\\(section\\|paragraph\\|chapter\\)\\*?") - nil t) - ;; Skip over the backslash: - (setq s1 (1+ (point))) - ;; Skip over the sectioning command, incl. the *: - (setq e1 (goto-char (match-end 0))) - ;; Skip over the optional argument, if any: - (when (looking-at-p "[ \t]*\\[") - (forward-sexp)) - ;; Skip over any chars until the mandatory argument: - (skip-chars-forward "^{") - ;; Remember the points for the mandatory argument: - (setq s2 (point)) - (setq e2 (progn (forward-sexp) - (point))) - ;; Now pick the content: For one-line title, return it - ;; incl. the closing brace. For multi-line, return the first - ;; line of the mandatory argument incl. ellipsis and a brace; - (concat - (buffer-substring-no-properties s1 e1) - (buffer-substring-no-properties - (goto-char s2) - (min (line-end-position) e2)) - (when (> e2 (line-end-position)) - (concat "..." TeX-grcl))))))) - -;;; Customization: - -(defcustom TeX-process-asynchronous (not (eq system-type 'ms-dos)) - "Use asynchronous processes." - :group 'TeX-command - :type 'boolean) - -(defcustom TeX-shell - (if (memq system-type '(ms-dos emx windows-nt)) - shell-file-name - "/bin/sh") - "Name of shell used to parse TeX commands." - :group 'TeX-command - :type 'file) - -(defcustom TeX-shell-command-option - (cond ((memq system-type '(ms-dos emx windows-nt)) - shell-command-switch) - (t ;Unix & EMX (Emacs 19 port to OS/2) - "-c")) - "Shell argument indicating that next argument is the command." - :group 'TeX-command - :type 'string) - -;;; Interactive Commands -;; -;; The general idea is, that there is one process and process buffer -;; associated with each master file, and one process and process -;; buffer for running TeX on a region. -;; -;; Some user commands operates on ``the'' process, which is the last -;; process still running or already finished. Note that you cannot -;; run more than one process simultaneously, including preview by -;; preview-latex, because process filters and sentinels refer to -;; certain set of global variables which each invokation of the -;; process overwrites. If you dare to do, the result is thus -;; unpredictable. - -(defun TeX-save-document (name-or-file-fn) - "Save all files belonging to the current document. -Return non-nil if document needs to be re-TeX'ed. -In Lisp program, NAME-OR-FILE-FN specifies the current document. -It is either the master name without extension or the function -`TeX-master-file'." - (interactive (list #'TeX-master-file)) - (TeX-check-files (TeX--concat-ext name-or-file-fn (TeX-output-extension)) - (cons (TeX--concat-ext name-or-file-fn) (TeX-style-list)) - TeX-file-extensions)) - -(defun TeX--concat-ext (name-or-file-fn &optional extension) - "Append EXTENSION to a filename specified by NAME-OR-FILE-FN. - -If NAME-OR-FILE-FN is a string, interpret it as the filename. -Otherwise, assume it is a callable function and call it with -EXTENSION as an argument and return the result without -modification. EXTENSION is a string which should not start with -'.'." - (if (stringp name-or-file-fn) - (if extension - (concat name-or-file-fn "." extension) - name-or-file-fn) - (funcall name-or-file-fn extension))) - -(defun TeX-command-master (&optional override-confirm) - "Run command on the current document. - -If a prefix argument OVERRIDE-CONFIRM is given, confirmation will -depend on it being positive instead of the entry in `TeX-command-list'." - (interactive "P") - (TeX-master-file nil nil t) ;; call to ask if necessary - (TeX-command (TeX-command-query #'TeX-master-file) - #'TeX-master-file override-confirm)) - -(defcustom TeX-region-extra "" - "String to insert in the region file between the header and the text." - :group 'TeX-command - :type 'string) - -;; This was "{\\makeatletter\\gdef\\AucTeX@cite#1[#2]#3{[#3#1#2]}\ -;; \\gdef\\cite{\\@ifnextchar[{\\AucTeX@cite{, }}\ -;; {\\AucTeX@cite{}[]}}}\n" -;; However, that string is inappropriate for plain TeX and ConTeXt. -;; This needs reconsideration. - -(defvar TeX-command-region-begin nil) -(defvar TeX-command-region-end nil) -;; Used for marking the last region. - -(make-variable-buffer-local 'TeX-command-region-begin) -(make-variable-buffer-local 'TeX-command-region-end) - -(defun TeX-current-offset (&optional pos) - "Calculate line offset of POS, or of point if POS is nil." - (save-restriction - (widen) - (save-excursion - (let ((inhibit-point-motion-hooks t) - (inhibit-field-text-motion t)) - (if pos (goto-char pos)) - (+ (count-lines (point-min) (point)) - (if (bolp) 0 -1)))))) - -(defun TeX-pin-region (begin end) - "Pin the TeX region specified by BEGIN and END. -If BEGIN is nil, the region is unpinned. - -In interactive use, a positive prefix arg will pin the region, -a non-positive one will unpin it. Without a prefix arg, if -a region is actively marked, it will get pinned. If not, a -pinned region will get unpinned and vice versa." - (interactive - (if - (if current-prefix-arg - (> (prefix-numeric-value current-prefix-arg) 0) - (or (TeX-active-mark) - (null TeX-command-region-begin))) - (list (region-beginning) (region-end)) - '(nil nil))) - (if begin - (progn - (unless (markerp TeX-command-region-begin) - (setq TeX-command-region-begin (make-marker)) - (setq TeX-command-region-end (make-marker))) - (set-marker TeX-command-region-begin begin) - (set-marker TeX-command-region-end end) - (message "TeX region pinned.")) - (when (markerp TeX-command-region-begin) - (set-marker TeX-command-region-begin nil) - (set-marker TeX-command-region-end nil)) - (setq TeX-command-region-begin nil) - (setq TeX-command-region-end nil) - (message "TeX region unpinned."))) - -(defun TeX-region-update () - "Update the TeX-region file." - ;; Note that TeX-command-region-begin is not a marker when called - ;; from TeX-command-buffer. - (and (or (null TeX-command-region-begin) - (markerp TeX-command-region-begin)) - (TeX-active-mark) - (TeX-pin-region (region-beginning) (region-end))) - (let* ((begin (or TeX-command-region-begin (region-beginning))) - (end (or TeX-command-region-end (region-end))) - (TeX-region-extra - ;; Write out counter information to region. - (concat (and (fboundp 'preview--counter-information) - (preview--counter-information begin)) - TeX-region-extra))) - (TeX-region-create (TeX-region-file TeX-default-extension) - (buffer-substring-no-properties begin end) - (file-name-nondirectory (buffer-file-name)) - (TeX-current-offset begin)))) - -(defun TeX-command-region (&optional override-confirm) - "Run TeX on the current region. - -Query the user for a command to run on the temporary file specified by -the variable `TeX-region'. If there is an explicitly active region, -it is stored for later commands. If not, a previously stored region -\(can be also be set with `TeX-pin-region') overrides the current region, -if present. - -If a prefix argument OVERRIDE-CONFIRM is given, prompting will -ignore the prompting flag from `TeX-command-list' and instead -will prompt only if the prefix is positive. - -If the master file for the document has a header, it is written to the -temporary file before the region itself. The document's header is all -text before `TeX-header-end'. - -If the master file for the document has a trailer, it is written to -the temporary file after the region itself. The document's trailer is -all text after `TeX-trailer-start'." - (interactive "P") - (TeX-region-update) - ;; In the next line, `TeX-region-file' should be called with nil - ;; `nondirectory' argument, otherwise `TeX-command-default' called - ;; within `TeX-command-query' won't work in included files not - ;; placed in `TeX-master-directory'. - (TeX-command (TeX-command-query #'TeX-region-file) #'TeX-region-file - override-confirm)) - -(defun TeX-command-buffer (&optional override-confirm) - "Run TeX on the current buffer. - -Query the user for a command to run on the temporary file specified by -the variable `TeX-region'. The region file will be recreated from the -visible part of the buffer. - -If a prefix argument OVERRIDE-CONFIRM is given, confirmation will -depend on it being positive instead of the entry in `TeX-command-list'." - (interactive "P") - (let ((TeX-command-region-begin (point-min)) - (TeX-command-region-end (point-max))) - (TeX-command-region override-confirm))) - -(defcustom TeX-record-buffer nil - "Whether to record buffer names of generated TeX buffers. -When non-nil, these buffers are put at the front of the list of -recently selected ones." - :group 'TeX-command - :type 'boolean) - -(defun TeX-pop-to-buffer (buffer &optional other-window norecord) - "Compatibility wrapper for `pop-to-buffer'. - -Select buffer BUFFER in some window, preferably a different one. -BUFFER may be a buffer, a string (a buffer name), or nil. -If BUFFER is a string which is not the name of an existing buffer, -then this function creates a buffer with that name. -If BUFFER is nil, then it chooses some other buffer. -If `pop-up-windows' is non-nil, windows can be split to do this. -If optional second arg OTHER-WINDOW is non-nil, insist on finding another -window even if BUFFER is already visible in the selected window, -and ignore `same-window-regexps' and `same-window-buffer-names'. -This function returns the buffer it switched to. -This uses the function `display-buffer' as a subroutine; see the documentation -of `display-buffer' for additional customization information. - -Optional third arg NORECORD non-nil means do not put this buffer -at the front of the list of recently selected ones." - (pop-to-buffer buffer other-window (and norecord (not TeX-record-buffer)))) - -(defun TeX-recenter-output-buffer (line) - "Redisplay buffer of TeX job output so that most recent output can be seen. -The last line of the buffer is displayed on line LINE of the window, or -at bottom if LINE is nil." - (interactive "P") - (let ((buffer (TeX-active-buffer))) - (if buffer - (let ((old-buffer (current-buffer))) - (TeX-pop-to-buffer buffer t t) - (bury-buffer buffer) - (goto-char (point-max)) - (recenter (if line - (prefix-numeric-value line) - (/ (window-height) 2))) - (TeX-pop-to-buffer old-buffer nil t)) - (message "No process for this document.")))) - -(defun TeX-kill-job () - "Kill the currently running TeX job." - (interactive) - (let ((process (TeX-active-process))) - (if process - (kill-process process) - ;; Should test for TeX background process here. - (error "No TeX process to kill")))) - -;; FIXME: The vars below are defined in this file, but they're defined too -;; far down (i.e. further down than their first use), so we have to pre-declare -;; them here to explain it to the compiler. -;; We should move those vars's definitions earlier instead! -(defvar TeX-current-process-region-p) -(defvar TeX-save-query) -(defvar TeX-parse-function) -(defvar TeX-sentinel-function) -(defvar TeX-sentinel-default-function) -(defvar compilation-in-progress) -(defvar TeX-current-page) -(defvar TeX-error-overview-open-after-TeX-run) -(defvar TeX-error-list) -(defvar TeX-command-buffer) -(defvar TeX-region) - -(defun TeX-home-buffer () - "Go to the buffer where you last issued a TeX command. -If there is no such buffer, or you already are in that buffer, find -the master file." - (interactive) - (if (or (null TeX-command-buffer) - (null (buffer-name TeX-command-buffer)) - (eq TeX-command-buffer (current-buffer))) - (find-file (TeX-master-file TeX-default-extension)) - (switch-to-buffer TeX-command-buffer))) - -(defvar TeX-error-last-visited -1 - "Index of the last visited error listed in `TeX-error-list'. - -This variable is intended to be set only in output buffer so it -will be shared among all files of the same document.") -(make-variable-buffer-local 'TeX-error-last-visited) - -(defun TeX-get-parse-function () - "Get the parse function for the current buffer." - (with-current-buffer TeX-command-buffer - (TeX-process-get-variable (TeX-active-master) 'TeX-parse-function))) - -(defun TeX-next-error (&optional arg reparse) - "Find the next error in the TeX output buffer. - -A prefix ARG specifies how many error messages to move; -negative means move back to previous error messages, if possible. - -If REPARSE is non-nil, reparse the error message buffer. - -\\[universal-argument] as a prefix means reparse the error -message buffer and start at the first error." - (interactive "P") - (if (or (null (TeX-active-buffer)) - (eq 'compilation-mode (with-current-buffer TeX-command-buffer - major-mode))) - (next-error arg reparse) - - ;; Force reparsing when the function is called with a universal-argument. - (if (consp arg) (setq reparse t arg nil)) - - (funcall (TeX-get-parse-function) arg reparse))) - -(defun TeX-previous-error (arg) - "Find the previous error in the TeX output buffer. - -Prefix ARG says how many error messages to move backward (or -forward, if negative). - -This works only with TeX commands and if the -`TeX-parse-all-errors' variable is non-nil." - (interactive "p") - (if (or (null (TeX-active-buffer)) - (eq 'compilation-mode (with-current-buffer TeX-command-buffer - major-mode))) - (previous-error arg) - - (let ((parse-function (TeX-get-parse-function))) - (if (and TeX-parse-all-errors (equal parse-function #'TeX-parse-TeX)) - ;; When `TeX-parse-all-errors' is non-nil and the parsing function is - ;; `TeX-parse-TeX' we can move backward in the errors. - (TeX-parse-TeX (- arg) nil) - ;; XXX: moving backward in the errors hasn't yet been implemented for - ;; other parsing functions. - (error "Jumping to previous error not supported"))))) - -;;; Command Query - -(defvar TeX-error-overview-frame nil - "The frame of the error overview.") - -(defconst TeX-error-overview-buffer-name "*TeX errors*" - "Name of the buffer in which to show error list.") - -(defvar LaTeX-idx-md5-alist nil - "Alist of MD5 hashes of idx file. - -Car is the idx file, cdr is its md5 hash.") - -(defvar LaTeX-idx-changed-alist nil - "Whether the idx files changed. - -Car is the idx file, cdr is whether idx changed after LaTeX -run.") - -(defcustom TeX-check-engine t - "Check the correct engine has been set before running TeX commands." - :group 'TeX-command - :type 'boolean) - -(defvar TeX-check-engine-list '(default luatex omega xetex) - "List of engines required by the loaded TeX packages. - -Do not set this variable directly, use -`TeX-check-engine-add-engines' to specify required engines.") -(make-variable-buffer-local 'TeX-check-engine-list) - -(defun TeX-check-engine-add-engines (&rest engines) - "Add ENGINES to list of required engines. - -Set `TeX-check-engine-list' to the intersection between the list -itself and the list of provided engines. - -See for example style/fontspec.el" - (let ((list TeX-check-engine-list) - (res nil)) - (setq TeX-check-engine-list - ;; The following is based on the definition of `cl-intersection' of - ;; GNU Emacs. - (and list engines - (if (equal list engines) list - (or (>= (length list) (length engines)) - (setq list (prog1 engines (setq engines list)))) - (while engines - (if (memq (car engines) list) - (push (car engines) res)) - (pop engines)) - res))))) - -(defun TeX-check-engine (name) - "Check the correct engine has been set. - -Look into `TeX-check-engine-list' for the required engines. - -NAME is the command to be run. Actually do the check only if the -variable `TeX-check-engine' is non-nil and LaTeX is the command -to be run." - (and - (string= name "LaTeX") - TeX-check-engine - TeX-check-engine-list - (null (memq TeX-engine TeX-check-engine-list)) - (memq TeX-engine '(default luatex omega xetex)) - ;; The set engine is not listed in `TeX-check-engine-list'. We check only - ;; builtin engines because we can't take care of custom ones. Do nothing if - ;; there is no allowed engine, we don't know what to do in that case. - (let ((length (length TeX-check-engine-list)) - (name-alist '((default . "TeX") - (luatex . "LuaTeX") - (omega . "Omega") - (xetex . "XeTeX"))) - (completion-ignore-case t) - (engine nil)) - (when - (cond - ;; There is exactly one allowed engine. - ((= length 1) - (setq engine (car TeX-check-engine-list)) - (y-or-n-p (format "%s is required to build this document. -Do you want to use this engine? " (cdr (assoc engine name-alist))))) - ;; More than one engine is allowed. - ((> length 1) - (if (y-or-n-p (format "It appears %s are required to build this document. -Do you want to select one of these engines? " - (mapconcat - (lambda (elt) (cdr (assoc elt name-alist))) - TeX-check-engine-list ", "))) - (setq engine - (car (rassoc - (completing-read - (format - "Choose between %s: " - (mapconcat - (lambda (elt) (cdr (assoc elt name-alist))) - TeX-check-engine-list ", ")) - (mapcar - (lambda (elt) (cdr (assoc elt name-alist))) - TeX-check-engine-list)) - name-alist))) - ;; Don't keep asking. If user doesn't want to change engine, - ;; probably has a good reason. In order to do so, without adding - ;; yet another variable we just hack `TeX-check-engine-list' and - ;; make it nil. - (setq TeX-check-engine-list nil)))) - (TeX-engine-set engine) - (when (y-or-n-p "Do you want to remember the choice? ") - (add-file-local-variable 'TeX-engine engine) - (save-buffer)))))) - -(defcustom TeX-check-TeX t - "Whether AUCTeX should check if a working TeX distribution is present." - :group 'TeX-command - :type 'boolean) - -(defcustom TeX-check-TeX-command-not-found 127 - "Numerical code returned by shell for a command not found error." - :group 'TeX-command - :type 'integer) - -(defun TeX-command (name file-fn &optional override-confirm) - "Run command NAME on the file returned by calling FILE-FN. - -FILE-FN is the symbol of a function returning a file name. The -function has one optional argument, the extension to use on the -file. Valid choices are `TeX-master-file' and `TeX-region-file'. - -Use the information in `TeX-command-list' to determine how to run -the command. - -If OVERRIDE-CONFIRM is a prefix argument, confirmation will be -asked if it is positive, and suppressed if it is not. - -Run function `TeX-check-engine' to check the correct engine has -been set." - (TeX-check-engine name) - - ;; Make sure that `TeX-command-buffer' is set always. - ;; It isn't safe to remove similar lines in `TeX-run-command' etc. - ;; because preview-latex calls `TeX-run-command' directly. - (setq-default TeX-command-buffer (current-buffer)) - - (cond ((eq file-fn #'TeX-region-file) - (setq TeX-current-process-region-p t)) - ((eq file-fn #'TeX-master-file) - (setq TeX-current-process-region-p nil))) - - ;; When we're operating on a region, we need to update the position - ;; of point in the region file so that forward search works. - (if (string= name "View") (TeX-region-update-point)) - - (let ((command (TeX-command-expand (nth 1 (assoc name TeX-command-list)))) - (hook (nth 2 (assoc name TeX-command-list))) - (confirm (if override-confirm - (> (prefix-numeric-value override-confirm) 0) - (nth 3 (assoc name TeX-command-list))))) - - ;; Verify the expanded command - (if confirm - (setq command - (read-from-minibuffer (concat name " command: ") command - nil nil))) - - ;; Kill the frame and buffer associated to the error overview before running - ;; the command, but keep them if the command to be run is View. - (unless (string= name "View") - (if (frame-live-p TeX-error-overview-frame) - (delete-frame TeX-error-overview-frame)) - (if (get-buffer TeX-error-overview-buffer-name) - (kill-buffer TeX-error-overview-buffer-name))) - - ;; Before running some commands, check that AUCTeX is able to find "tex" - ;; program. - (and TeX-check-TeX - (member name '("TeX" "LaTeX" "AmSTeX" "ConTeXt" "ConTeXt Full")) - (= TeX-check-TeX-command-not-found - (call-process TeX-shell nil nil nil - TeX-shell-command-option TeX-command)) - (error (format "ERROR: AUCTeX cannot find a working TeX distribution. -Make sure you have one and that TeX binaries are in PATH environment variable%s" - (if (eq system-type 'darwin) - ". -If you are using OS X El Capitan or later -remember to add /Library/TeX/texbin/ to your PATH" - "")))) - - ;; Now start the process - (let ((file (funcall file-fn))) - (TeX-process-set-variable file 'TeX-command-next TeX-command-Show) - (funcall hook name command file)))) - -(defun TeX-command-expand (command &optional list) - "Expand COMMAND for `TeX-active-master' as described in LIST. -LIST default to `TeX-expand-list'. As a special exception, -`%%' can be used to produce a single `%' sign in the output -without further expansion." - (let ((TeX-expand-command command) - TeX-expand-pos - TeX-command-text - TeX-command-pos - pat entry case-fold-search string expansion arguments) - (setq list (cons - (list "%%" (lambda nil - (setq TeX-expand-pos (1+ TeX-expand-pos)) - "%")) - (or list (TeX-expand-list))) - pat (regexp-opt (mapcar #'car list))) - (while (setq TeX-expand-pos (string-match pat TeX-expand-command TeX-expand-pos)) - (setq string (match-string 0 TeX-expand-command) - entry (assoc string list) - expansion (car (cdr entry)) ;Second element - arguments (cdr (cdr entry)) ;Remaining elements - string (save-match-data - (cond - ((functionp expansion) - (apply expansion arguments)) - ((boundp expansion) - (apply (symbol-value expansion) arguments)) - (t - (error "Nonexpansion %s" expansion))))) - (if (stringp string) - (setq TeX-expand-command - (replace-match string t t TeX-expand-command)))) - TeX-expand-command)) - -(defun TeX-active-master-with-quotes - (&optional extension nondirectory ask extra preprocess-fn) - "Return the current master or region file name with quote for shell. -Pass arguments EXTENSION NONDIRECTORY ASK to `TeX-active-master'. -If the returned file name contains space, enclose it within -quotes `\"' when \" \\input\" is supplemented (indicated by -dynamically bound variable `TeX-command-text' having string -value.) Also enclose the file name within \\detokenize{} when -the following three conditions are met: - 1. compiling with standard (pdf)LaTeX or upLaTeX - 2. \" \\input\" is supplemented - 3. EXTRA is non-nil (default when expanding \"%T\") -Adjust dynamically bound variable `TeX-expand-pos' to avoid possible -infinite loop in `TeX-command-expand'. -If PREPROCESS-FN is non-nil then it is called with the filename -as an argument and the result is enclosed instead of the -filename. - -Helper function of `TeX-command-expand'. Use only within entries in -`TeX-expand-list-builtin' and `TeX-expand-list'." - (let* ((raw (TeX-active-master extension nondirectory ask)) - ;; String `TeX-command-text' means that the file name is - ;; given through \input command. - (quote-for-space (if (and (stringp TeX-command-text) - (string-match " " raw)) - "\"" "")) - (res - (shell-quote-argument - (format - (if (and extra - (stringp TeX-command-text) - (memq major-mode '(latex-mode doctex-mode)) - (memq TeX-engine '(default uptex))) - ;; Since TeXLive 2018, the default encoding for LaTeX - ;; files has been changed to UTF-8 if used with - ;; classic TeX or pdfTeX. I.e., - ;; \usepackage[utf8]{inputenc} is enabled by default - ;; in (pdf)latex. - ;; c.f. LaTeX News issue 28 - ;; Due to this change, \detokenize is required to - ;; recognize non-ascii characters in the file name - ;; when \input precedes. - "\\detokenize{ %s }" "%s") - (concat quote-for-space - (if preprocess-fn - (funcall preprocess-fn raw) - raw) - quote-for-space))))) - ;; Advance past the file name in order to - ;; prevent expanding any substring of it. - (setq TeX-expand-pos - (+ TeX-expand-pos (length res))) - res)) - -(defun TeX-check-files (derived originals extensions) - "Check if DERIVED is newer than any of the ORIGINALS. -Try each original with each member of EXTENSIONS, in all directories -in `TeX-check-path'. Returns true if any of the ORIGINALS with any of the -EXTENSIONS are newer than DERIVED. Will prompt to save the buffer of any -ORIGINALS which are modified but not saved yet." - (let (existingoriginals - found - (extensions (TeX-delete-duplicate-strings extensions)) - (buffers (buffer-list))) - (dolist (path (TeX-delete-duplicate-strings - (mapcar (lambda (dir) - (expand-file-name (file-name-as-directory dir))) - (append - TeX-check-path - ;; In `TeX-command-default', this function is used to - ;; check whether bibliography databases are newer - ;; than generated *.bbl files, but bibliography - ;; database are relative to `TeX-master-directory' - ;; and the test can be run also from included files - ;; that are in directories different from - ;; `TeX-master-directory'. - (list (TeX-master-directory)))))) - (dolist (orig originals) - (dolist (ext extensions) - (let ((filepath (concat path orig "." ext))) - (if (or (file-exists-p filepath) - (get-file-buffer filepath)) - (setq existingoriginals (cons filepath existingoriginals))))))) - (while buffers - (let* ((buffer (car buffers)) - (name (buffer-file-name buffer))) - (setq buffers (cdr buffers)) - (if (and name (member name existingoriginals)) - (progn - (and (buffer-modified-p buffer) - (or (not TeX-save-query) - (y-or-n-p (concat "Save file " - (buffer-file-name buffer) - "? "))) - (with-current-buffer buffer (save-buffer))))))) - (dolist (eo existingoriginals) - (if (file-newer-than-file-p eo derived) - (setq found t))) - found)) - -(defcustom TeX-command-sequence-max-runs-same-command 4 - "Maximum number of runs of the same command." - :type 'integer - :group 'TeX-command) - -(defcustom TeX-command-sequence-max-runs 12 - "Maximum number of total runs." - :type 'integer - :group 'TeX-command) - -(defvar TeX-command-sequence-count-same-command 1 - "Counter for the runs of the same command in `TeX-command-sequence'.") - -(defvar TeX-command-sequence-count 1 - "Counter for the total runs of `TeX-command-sequence'.") - -(defvar TeX-command-sequence-last-command nil - "Last command run in `TeX-command-sequence'.") - -(defvar TeX-command-sequence-sentinel nil - "Sentinel for `TeX-command-sequence'.") - -(defvar TeX-command-sequence-file-function nil - "File function for `TeX-command-sequence'.") - -(defvar TeX-command-sequence-command nil - "Command argument for `TeX-command-sequence'. - -It is set in `TeX-command-sequence' and used in -`TeX-command-sequence-sentinel' to call again -`TeX-command-sequence' with the appropriate command argument.") - -(defun TeX-command-sequence (command &optional reset file-fn) - "Run a sequence of TeX commands defined by COMMAND. - -The COMMAND argument may be - - * nil: no command will be run in this case - - * a string with a command from `TeX-command-list' - - * a non-nil list of strings, which are commands from - `TeX-command-list'; the car of the list is used as command to - be executed in the first run of `TeX-command-sequence', the - cdr of the list will be passed to the function in the next - run, etc. - - * a function name, returning a string which is command from - `TeX-command-list'; it will be funcall'd (without arguments!) - and used again in the next run of `TeX-command-sequence'. - - * with any other value the function `TeX-command-default' is - used to determine the command to run, until a stopping - condition is met. - -This function runs at most -`TeX-command-sequence-max-runs-same-command' times the same -command in a row, and `TeX-command-sequence-max-runs' times in -total in any case. It ends when `TeX-command-Show' is the -command to be run. - -A non-nil value for the optional argument RESET means this is the -first run of the function and some variables need to be reset. - -FILE-FN is a function of zero arguments returning the current -filename. Valid choices are `TeX-master-file' (default if -omitted) and `TeX-region-file'." - (setq TeX-command-sequence-file-function (or file-fn #'TeX-master-file)) - (if (null command) - (message "No command to run.") - (let (cmd process) - (cond - ((stringp command) - (setq cmd command - TeX-command-sequence-command nil)) - ((listp command) - (setq cmd (pop command) - TeX-command-sequence-command command)) - ((functionp command) - (setq cmd (funcall command) - TeX-command-sequence-command command)) - (t - ;; We first call `TeX-master-file' with the third argument - ;; (`ask') set to t, so that the master file is properly set. - ;; This is also what `TeX-command-master' does. - (funcall TeX-command-sequence-file-function nil nil t) - (setq cmd (TeX-command-default TeX-command-sequence-file-function) - TeX-command-sequence-command t))) - (TeX-command cmd TeX-command-sequence-file-function 0) - (when reset - (setq TeX-command-sequence-count-same-command 1 - TeX-command-sequence-count 1 - TeX-command-sequence-last-command nil)) - (cond - ;; Stop when the same command has been run - ;; `TeX-command-sequence-max-runs-same-command' times in a row. - ((>= TeX-command-sequence-count-same-command - TeX-command-sequence-max-runs-same-command) - (message "Stopping after running %S %d times in a row." - TeX-command-sequence-last-command - TeX-command-sequence-count-same-command)) - ;; Stop when there have been `TeX-command-sequence-max-runs' total - ;; compilations. - ((>= TeX-command-sequence-count TeX-command-sequence-max-runs) - (message "Stopping after %d compilations." TeX-command-sequence-count)) - ;; The command just run is `TeX-command-Show'. - ((equal command TeX-command-Show)) - ;; In any other case continue: increase counters (when needed), update - ;; `TeX-command-sequence-last-command' and run the sentinel. - (t - (if (equal cmd TeX-command-sequence-last-command) - (setq TeX-command-sequence-count-same-command - (1+ TeX-command-sequence-count-same-command)) - (setq TeX-command-sequence-count-same-command 1)) - (setq TeX-command-sequence-count (1+ TeX-command-sequence-count) - TeX-command-sequence-last-command cmd) - (and (setq process (get-buffer-process (current-buffer))) - (setq TeX-command-sequence-sentinel (process-sentinel process)) - (set-process-sentinel process - #'TeX-command-sequence-sentinel))))))) - -(defcustom TeX-save-query t - "If non-nil, ask user for permission to save files before starting TeX." - :group 'TeX-command - :type 'boolean) - -(defvar TeX-command-history nil) - -(defun TeX-command-default (name-or-file-fn) - "Guess the next command to be run on NAME-OR-FILE-FN." - (let ((command-next nil) - (name (TeX--concat-ext name-or-file-fn))) - (cond ((if (eq name-or-file-fn #'TeX-region-file) - (TeX-check-files (TeX-region-file (TeX-output-extension)) - ;; Each original will be checked for all dirs - ;; in `TeX-check-path' so this needs to be just - ;; a filename without directory. - (list (file-relative-name name)) - TeX-file-extensions) - (TeX-save-document name-or-file-fn)) - TeX-command-default) - ((and (memq major-mode '(doctex-mode latex-mode)) - ;; Want to know if bib file is newer than .bbl - ;; We don't care whether the bib files are open in emacs - (TeX-check-files (TeX--concat-ext name-or-file-fn "bbl") - (mapcar #'car - (LaTeX-bibliography-list)) - (append BibTeX-file-extensions - TeX-Biber-file-extensions))) - ;; We should check for bst files here as well. - (if (bound-and-true-p LaTeX-using-Biber) - TeX-command-Biber TeX-command-BibTeX)) - ((and - ;; Rationale: makeindex should be run when final document is almost - ;; complete (see - ;; https://tex-talk.net/2012/09/dont-forget-to-run-makeindex/), - ;; otherwise, after following latex runs, index pages may change due - ;; to changes in final document, resulting in extra makeindex and - ;; latex runs. - (member - (setq command-next - (TeX-process-get-variable - name - 'TeX-command-next - (or (and TeX-PDF-mode (TeX-PDF-from-DVI)) - TeX-command-Show))) - (list "Dvips" "Dvipdfmx" TeX-command-Show)) - (cdr (assoc (expand-file-name (TeX--concat-ext name-or-file-fn "idx")) - LaTeX-idx-changed-alist))) - "Index") - (command-next) - (TeX-command-Show)))) - -(defun TeX-command-query (name-or-file-fn) - "Query the user for what TeX command to use." - (let* ((default (TeX-command-default name-or-file-fn)) - (completion-ignore-case t) - (answer (or TeX-command-force - (completing-read - (concat "Command (default " default "): ") - (TeX-mode-specific-command-list major-mode) nil t - nil 'TeX-command-history default)))) - ;; If the answer is "latex" it will not be expanded to "LaTeX" - (setq answer (car-safe (assoc-string answer TeX-command-list t))) - (if (and answer - (not (string-equal answer ""))) - answer - default))) - -(defvar TeX-command-next nil - "The default command next time `TeX-command' is invoked.") - - (make-variable-buffer-local 'TeX-command-next) - -(defun TeX-printer-query (&optional queue) - "Query the user for a printer name. -QUEUE is non-nil when we are checking for the printer queue." - (let (command element printer) - (if queue - (unless (setq element 2 command TeX-queue-command) - (error "Need to customize `TeX-queue-command'")) - (unless (setq element 1 command TeX-print-command) - (error "Need to customize `TeX-print-command'"))) - (while (progn - (setq printer (if TeX-printer-list - (let ((completion-ignore-case t)) - (completing-read - (format "Printer%s: " - (if TeX-printer-default - (format " (default %s)" TeX-printer-default) "")) - TeX-printer-list)) - "")) - (setq printer (or (car-safe (assoc-string printer TeX-printer-list t)) - printer)) - (not (if (or (null printer) (string-equal "" printer)) - (setq printer TeX-printer-default) - (setq TeX-printer-default printer))))) - - (let ((expansion (let ((entry (assoc printer TeX-printer-list))) - (or (nth element entry) - command)))) - (if (string-match "%p" printer) - (error "Don't use %s in printer names" "%p")) - (while (string-match "%p" expansion) - (setq expansion (replace-match printer t t expansion 0))) - expansion))) - -(defun TeX-style-check (styles) - "Check STYLES compared to the current style options." - (let ((files (TeX-style-list))) - (while (and styles - (not (TeX-member (car (car styles)) files #'string-match))) - (setq styles (cdr styles)))) - (if styles - (nth 1 (car styles)) - "")) - -(defun TeX-output-extension () - "Get the extension of the current TeX output file." - (if (listp TeX-output-extension) - (car TeX-output-extension) - (or (TeX-process-get-variable (TeX-active-master) - 'TeX-output-extension - TeX-output-extension) - TeX-output-extension))) - -(defun TeX-view-mouse (event) - "Start `TeX-view' at mouse position." - (interactive "e") - (with-current-buffer (window-buffer (posn-window (event-start event))) - (goto-char (posn-point (event-start event))) - (TeX-view))) - -(defun TeX-region-update-point () - "Syncs the location of point in the region file with the current file. - -Thereafter, point in the region file is on the same text as in -the current buffer. - -Do nothing in case the last command hasn't operated on the region -or `TeX-source-correlate-mode' is disabled." - (when (and TeX-current-process-region-p TeX-source-correlate-mode) - (let ((region-buf (get-file-buffer (TeX-region-file t))) - (orig-line (TeX-current-offset)) - (pos-in-line (- (point) (max (line-beginning-position) - (or TeX-command-region-begin - (region-beginning)))))) - (when region-buf - (with-current-buffer region-buf - (goto-char (point-min)) - (when (re-search-forward "!offset(\\(-?[0-9]+\\)" nil t) - (let ((offset (string-to-number (match-string 1)))) - (goto-char (point-min)) - (forward-line (- orig-line offset)) - (forward-char pos-in-line)))))))) - -(defun TeX-view () - "Start a viewer without confirmation. -The viewer is started either on region or master file, -depending on the last command issued." - (interactive) - (let ((output-file (TeX-active-master (TeX-output-extension)))) - (if (file-exists-p output-file) - (TeX-command "View" #'TeX-active-master 0) - (message "Output file %S does not exist." output-file)))) - -;;; Command Hooks - -(defvar TeX-after-compilation-finished-functions nil - "Hook being run after TeX/LaTeX/ConTeXt finished successfully. -The functions in this hook are run with the DVI/PDF output file -given as argument. Using this hook can be useful for updating -the viewer automatically after re-compilation of the document. - -If you use an emacs-internal viewer such as `doc-view-mode' or -`pdf-view-mode', add `TeX-revert-document-buffer' to this hook.") - -(make-obsolete-variable 'TeX-after-TeX-LaTeX-command-finished-hook - 'TeX-after-compilation-finished-functions - "11.89") - -(defun TeX-revert-document-buffer (file) - "Revert the buffer visiting FILE. -This function is intended to be used in -`TeX-after-compilation-finished-functions' for users that view -their compiled document with an emacs viewer such as -`doc-view-mode' or `pdf-view-mode'. (Note that this function -just calls `revert-buffer' in the respective buffer and thus -requires that the corresponding mode defines a sensible -`revert-buffer-function'.)" - (let ((buf (find-buffer-visiting file))) - (when buf - (with-current-buffer buf - (revert-buffer nil t t))))) - -(defvar TeX-after-start-process-function - #'TeX-adjust-process-coding-system - "Function to adjust coding system of an asynchronous process. -Called with one argument PROCESS.") - -(defun TeX-adjust-process-coding-system (process) - "Adjust coding system of PROCESS to suitable value. -Usually coding system is the same as the TeX file with eol format -adjusted to OS default value. Take care of Japanese TeX, which -requires special treatment." - (if (and (boundp 'japanese-TeX-mode) - (fboundp 'japanese-TeX-set-process-coding-system) - (with-current-buffer TeX-command-buffer - japanese-TeX-mode)) - (japanese-TeX-set-process-coding-system process) - (let ((cs (coding-system-base (with-current-buffer TeX-command-buffer - buffer-file-coding-system)))) - ;; The value of `buffer-file-coding-system' is sometimes - ;; undecided-{unix,dos,mac}. That happens when the file - ;; contains no multibyte chars and only end of line format is - ;; determined. Emacs lisp reference recommends not to use - ;; undecided-* for process coding system, so it might seem - ;; reasonable to change `undecided' into some fixed coding - ;; system like this: - ;; (if (eq 'undecided cs) - ;; (setq cs 'utf-8)) - ;; However, that can lose when the following conditions are met: - ;; (1) The document is divided into multiple files. - ;; (2) The command buffer contains no multibyte chars. - ;; (3) The other files contain mutlibyte chars and saved in a - ;; coding system other than the one chosen above. - ;; So we leave `undecided' unchanged here. Although `undecided' - ;; is not quite safe for the coding system for encoding, i.e., - ;; keyboard input to the TeX process, we expect that this does - ;; not raise serious problems because it is pretty rare that TeX - ;; process needs keyboard input of multibyte chars. - - ;; `utf-8-with-signature' (UTF-8 with BOM) doesn't suit at all - ;; for the coding system for encoding because it always injects - ;; 3-byte BOM in front of its return value (even when the string - ;; to be sent has only ascii characters!) Thus we change it - ;; into `utf-8'. On decoding, `utf-8' can decode UTF-8 with - ;; BOM. So it is safe for both decoding and encoding. - (if (eq cs 'utf-8-with-signature) - (setq cs 'utf-8)) - - ;; Eol format of TeX files can differ from OS default. TeX - ;; binaries accept all type of eol format in the given files - ;; and output messages according to OS default. So we set eol - ;; format to OS default value. - (setq cs (coding-system-change-eol-conversion - cs - ;; The eol of macosX is LF, not CR. So we choose - ;; other than `unix' only for w32 system. - ;; FIXME: what should we do for cygwin? - (if (eq system-type 'windows-nt) 'dos 'unix))) - (set-process-coding-system process cs cs)))) - -(defcustom TeX-show-compilation nil - "If non-nil, show output of TeX compilation in other window." - :group 'TeX-command - :type 'boolean) - -(defun TeX-run-command (name command file) - "Create a process for NAME using COMMAND to process FILE. -Return the new process." - (let ((default TeX-command-default) - (buffer (TeX-process-buffer-name file)) - (dir (TeX-master-directory)) - (command-buff (current-buffer))) - (TeX-process-check file) ; Check that no process is running - (setq-default TeX-command-buffer command-buff) - (get-buffer-create buffer) - (set-buffer buffer) - (buffer-disable-undo) - (erase-buffer) - (set (make-local-variable 'line-number-display-limit) 0) - (setq TeX-output-extension nil) - (set (make-local-variable 'TeX-command-buffer) command-buff) - (if dir (cd dir)) - (insert "Running `" name "' on `" file "' with ``" command "''\n") - (TeX-output-mode) - (if TeX-show-compilation - (display-buffer buffer) - (message "Type `%s' to display results of compilation." - (substitute-command-keys - "\\<TeX-mode-map>\\[TeX-recenter-output-buffer]"))) - (setq TeX-parse-function #'TeX-parse-command) - (setq TeX-command-default default) - (setq TeX-sentinel-function - (lambda (_process name) - (message (concat name ": done.")))) - (if TeX-process-asynchronous - (let ((process (start-process name buffer TeX-shell - TeX-shell-command-option command))) - (if TeX-after-start-process-function - (funcall TeX-after-start-process-function process)) - (TeX-command-mode-line process) - (set-process-filter process #'TeX-command-filter) - (set-process-sentinel process #'TeX-command-sentinel) - (set-marker (process-mark process) (point-max)) - (setq compilation-in-progress (cons process compilation-in-progress)) - process) - (setq mode-line-process ": run") - (force-mode-line-update) - (call-process TeX-shell nil buffer nil - TeX-shell-command-option command)))) - -(defun TeX-run-set-command (name command) - "Remember TeX command to use to NAME and set corresponding output extension." - (setq TeX-command-default name - TeX-output-extension - (if (and (null (TeX-PDF-from-DVI)) TeX-PDF-mode) "pdf" "dvi")) - (let ((case-fold-search t) - (lst TeX-command-output-list)) - (while lst - (if (string-match (car (car lst)) command) - (setq TeX-output-extension (car (cdr (car lst))) - lst nil) - (setq lst (cdr lst)))))) - -(defvar TeX-error-report-switches nil - "Reports presence of errors after `TeX-run-TeX'. -Actually, `TeX-run-format' sets it. -To test whether the current buffer has a compile error from last -run of `TeX-run-format', use - (TeX-error-report-has-errors-p)") - -(defun TeX-error-report-has-errors-p () - "Return non-nil if current buffer has compile errors from last TeX run." - (plist-get TeX-error-report-switches (intern (TeX-master-file)))) - -(defun TeX-run-format (name command file) - "Create a process for NAME using COMMAND to format FILE with TeX." - (TeX-run-set-command name command) - (let ((current-master (TeX-master-file)) - (buffer (TeX-process-buffer-name file)) - (process (TeX-run-command name command file))) - - ;; Save information in TeX-error-report-switches - ;; Initialize error to nil (no error) for current master. - ;; Presence of error is reported inside `TeX-TeX-sentinel-check' - - ;; the current master file is saved because error routines are - ;; parsed in other buffers; - (setq TeX-error-report-switches - (plist-put TeX-error-report-switches - 'TeX-current-master current-master)) - ;; reset error to nil (no error) - (setq TeX-error-report-switches - (plist-put TeX-error-report-switches - (intern current-master) nil)) - - ;; Hook to TeX debugger. - (with-current-buffer buffer - (TeX-parse-reset) - (setq TeX-parse-function #'TeX-parse-TeX) - (setq TeX-sentinel-function #'TeX-TeX-sentinel) - (if TeX-process-asynchronous - (progn - ;; Updating the mode line. - (setq TeX-current-page "[0]") - (TeX-format-mode-line process) - (set-process-filter process #'TeX-format-filter))) - process))) - -(defun TeX-run-TeX (name command file) - "Create a process for NAME using COMMAND to format FILE with TeX." - - (let ((idx-file nil) (element nil)) - ;; Store md5 hash of the index file before running LaTeX. - (and (memq major-mode '(doctex-mode latex-mode)) - (prog1 (file-exists-p - (setq idx-file (expand-file-name (TeX-active-master "idx")))) - ;; In order to avoid confusion and pollution of - ;; `LaTeX-idx-md5-alist', remove from this alist all md5 hashes of - ;; the current index file. Note `assq-delete-all' doesn't work with - ;; string keys and has problems with non-list elements in Emacs 21 - ;; (see file tex-site.el). - (while (setq element (assoc idx-file LaTeX-idx-md5-alist)) - (setq LaTeX-idx-md5-alist (delq element LaTeX-idx-md5-alist)))) - (with-temp-buffer - (insert-file-contents-literally idx-file) - (push (cons idx-file (md5 (current-buffer))) LaTeX-idx-md5-alist)))) - - ;; can we assume that TeX-sentinel-function will not be changed - ;; during (TeX-run-format ..)? --pg - ;; rather use let* ? --pg - - (if TeX-interactive-mode - (TeX-run-interactive name command file) - (let* ((sentinel-function TeX-sentinel-default-function) - (process (TeX-run-format name command file))) - (setq TeX-sentinel-function sentinel-function) - (if TeX-process-asynchronous - process - (TeX-synchronous-sentinel name file process))))) - -;; backward compatibilty - -(defalias 'TeX-run-LaTeX #'TeX-run-TeX) - - -(defun TeX-run-BibTeX (name command file) - "Create a process for NAME using COMMAND to format FILE with BibTeX." - (let ((process (TeX-run-command name command file))) - (setq TeX-sentinel-function #'TeX-BibTeX-sentinel) - (if TeX-process-asynchronous - process - (TeX-synchronous-sentinel name file process)))) - -(defun TeX-run-Biber (name command file) - "Create a process for NAME using COMMAND to format FILE with Biber." - (let ((process (TeX-run-command name command file))) - (setq TeX-sentinel-function #'TeX-Biber-sentinel) - (if TeX-process-asynchronous - process - (TeX-synchronous-sentinel name file process)))) - -(defun TeX-run-dvips (name command file) - "Create a process for NAME using COMMAND to convert FILE with dvips." - (let ((process (TeX-run-command name command file))) - (setq TeX-sentinel-function #'TeX-dvips-sentinel) - (if TeX-process-asynchronous - process - (TeX-synchronous-sentinel name file process)))) - -(defun TeX-run-dvipdfmx (name command file) - "Create a process for NAME using COMMAND to convert FILE with dvipdfmx." - (let ((process (TeX-run-command name command file))) - (setq TeX-sentinel-function #'TeX-dvipdfmx-sentinel) - (if TeX-process-asynchronous - process - (TeX-synchronous-sentinel name file process)))) - -(defun TeX-run-ps2pdf (name command file) - "Create a process for NAME using COMMAND to convert FILE with ps2pdf." - (let ((process (TeX-run-command name command file))) - (setq TeX-sentinel-function #'TeX-ps2pdf-sentinel) - (if TeX-process-asynchronous - process - (TeX-synchronous-sentinel name file process)))) - -(defun TeX-run-index (name command file) - "Create a process for NAME using COMMAND to compile the index file." - (let ((process (TeX-run-command name command file)) - (element nil)) - (setq TeX-sentinel-function #'TeX-index-sentinel) - ;; Same cleaning as that for `LaTeX-idx-md5-alist' in `TeX-run-TeX'. - (while (setq element - ;; `file' has been determined in `TeX-command-buffer', while - ;; this function has `TeX-master-directory' as - ;; `default-directory', then we have to expand `file' file-name - ;; in the same directory of `TeX-command-buffer'. - (assoc (with-current-buffer TeX-command-buffer - (expand-file-name (TeX-active-master "idx"))) - LaTeX-idx-changed-alist)) - (setq LaTeX-idx-changed-alist (delq element LaTeX-idx-changed-alist))) - (if TeX-process-asynchronous - process - (TeX-synchronous-sentinel name file process)))) - -(defun TeX-run-compile (_name command _file) - "Ignore first and third argument, start compile with second argument." - (let ((default-directory (TeX-master-directory))) - (setq TeX-command-buffer (compile command))) - ;; Make `compilation-mode' recognize file names with spaces. - ;; (bug#36483) - ;; FIXME: This is just an ad-hoc workaround and it's better to fix - ;; the regular expression in compile.el properly, if possible. But - ;; there was no response to such request in emacs-devel@gnu.org. - (with-current-buffer TeX-command-buffer - (make-local-variable 'compilation-error-regexp-alist) - ;; Add slightly modified entry of the one associated with `comma' - ;; in `compilation-error-regexp-alist-alist' to pick up file names - ;; with spaces. - (add-to-list 'compilation-error-regexp-alist - '("^\"\\([^,\"\n\t]+\\)\", line \\([0-9]+\\)\ -\\(?:[(. pos]+\\([0-9]+\\))?\\)?[:.,; (-]\\( warning:\\|[-0-9 ]*(W)\\)?" 1 2 3 (4)) - t))) - -(defun TeX-run-shell (_name command _file) - "Ignore first and third argument, start shell-command with second argument." - (let ((default-directory (TeX-master-directory))) - (shell-command command) - (if (eq system-type 'ms-dos) - (redraw-display)))) - -(defun TeX-run-discard (_name command _file) - "Start COMMAND as process, discarding its output. -NAME and FILE are ignored." - (let ((default-directory (TeX-master-directory))) - (call-process TeX-shell - nil 0 nil - TeX-shell-command-option - command))) - -(defun TeX-run-discard-foreground (_name command _file) - "Call process with second argument in the foreground, discarding its output. -With support for MS-DOS, especially when dviout is used with PC-9801 series." - (if (and (boundp 'dos-machine-type) (eq dos-machine-type 'pc98)) ;if PC-9801 - (send-string-to-terminal "\e[2J")) ; clear screen - (call-process TeX-shell (if (eq system-type 'ms-dos) "con") nil nil - TeX-shell-command-option command) - (if (eq system-type 'ms-dos) - (redraw-display))) -(defalias 'TeX-run-dviout #'TeX-run-discard-foreground) - -(defun TeX-run-background (name command _file) - "Start process with second argument, show output when and if it arrives." - (let ((dir (TeX-master-directory))) - (set-buffer (get-buffer-create "*TeX background*")) - (if dir (cd dir)) - (erase-buffer) - (let ((process (start-process (concat name " background") - nil TeX-shell - TeX-shell-command-option command))) - (if TeX-after-start-process-function - (funcall TeX-after-start-process-function process)) - (set-process-filter process #'TeX-background-filter) - (set-process-query-on-exit-flag process nil)))) - -(defun TeX-run-silent (name command _file) - "Start process with second argument." - (let ((dir (TeX-master-directory))) - (set-buffer (get-buffer-create "*TeX silent*")) - (if dir (cd dir)) - (erase-buffer) - (let ((process (start-process (concat name " silent") - (current-buffer) TeX-shell - TeX-shell-command-option command))) - (if TeX-after-start-process-function - (funcall TeX-after-start-process-function process)) - (set-process-query-on-exit-flag process nil)))) - -(defun TeX-run-interactive (name command file) - "Run TeX interactively. -Run command in a buffer (in comint-shell-mode) so that it accepts user -interaction. If you return to the file buffer after the TeX run, -Error parsing on \\[next-error] should work with a bit of luck." - (TeX-run-set-command name command) - (require 'comint) - (let ((default TeX-command-default) - (buffer (TeX-process-buffer-name file)) - (process nil) - (dir (TeX-master-directory)) - (command-buff (current-buffer)) - (sentinel-function TeX-sentinel-default-function)) ; inherit from major mode - (TeX-process-check file) ; Check that no process is running - (setq-default TeX-command-buffer command-buff) - (with-output-to-temp-buffer buffer) - (set-buffer buffer) - (set (make-local-variable 'TeX-command-buffer) command-buff) - (setq buffer-read-only nil) - (if dir (cd dir)) - (insert "Running `" name "' on `" file "' with ``" command "''\n") - (comint-exec buffer name TeX-shell nil - (list TeX-shell-command-option command)) - (comint-mode) - (add-hook 'comint-output-filter-functions #'TeX-interactive-goto-prompt) - (setq mode-name name) - (setq TeX-command-default default) - (setq process (get-buffer-process buffer)) - (if TeX-after-start-process-function - (funcall TeX-after-start-process-function process)) - (TeX-command-mode-line process) - (set-process-sentinel process #'TeX-command-sentinel) - (set-marker (process-mark process) (point-max)) - (setq compilation-in-progress (cons process compilation-in-progress)) - (TeX-parse-reset) - (setq TeX-parse-function #'TeX-parse-TeX) - ;; use the sentinel-function that the major mode sets, not the LaTeX one - (setq TeX-sentinel-function sentinel-function))) - -(defun TeX-run-function (_name command _file) - "Execute Lisp function or function call given as the string COMMAND. -Parameters NAME and FILE are ignored." - (let ((fun (car (read-from-string command)))) - (if (functionp fun) (funcall fun) (eval fun t)))) - -(defun TeX-run-discard-or-function (name command file) - "Start COMMAND as process or execute it as a Lisp function. -If run as a process, the output is discarded. COMMAND is -expected to be a string. NAME and FILE are ignored." - (if (functionp (car (read-from-string command))) - (TeX-run-function name command file) - (TeX-run-discard name command file))) - -(defun TeX-run-ispell-on-document (_command _ignored _name) - "Run Ispell on all open files belonging to the current document. -This function is *obsolete* and only here for compatibility -reasons. Use `TeX-run-function' instead." - (interactive) - (TeX-ispell-document "")) - - -;;; Command Sentinels - -(defun TeX-synchronous-sentinel (name file result) - "Process TeX command output buffer after the process dies." - (let ((buffer (TeX-process-buffer (file-name-nondirectory file)))) - (with-current-buffer buffer - - ;; Append post-mortem information to the buffer - (goto-char (point-max)) - (insert "\n" mode-name (if (and result (zerop result)) - " finished" " exited") " at " - (substring (current-time-string) 0 -5)) - (setq mode-line-process ": exit") - - ;; Do command specific actions. - (setq TeX-command-next TeX-command-Show) - (goto-char (point-min)) - (apply TeX-sentinel-function nil name nil) - - ;; Force mode line redisplay soon - (force-mode-line-update)))) - -(defun TeX-command-sentinel (process msg) - "Process TeX command output buffer after the PROCESS dies. -Insert MSG with some additional information." - ;; Set `TeX-transient-master' here because `preview-parse-messages' - ;; may open files and thereby trigger master file questions which we - ;; don't want and need because we already know the master. Use - ;; `TeX-master-file' instead of `TeX-active-master' to determine the - ;; master because the region file should never be the master. - (let* ((TeX-transient-master (TeX-master-file)) - (buffer (process-buffer process)) - (name (process-name process))) - (cond ((null (buffer-name buffer)) ; buffer killed - (set-process-buffer process nil) - (set-process-sentinel process nil)) - ((memq (process-status process) '(signal exit)) - (with-current-buffer buffer - - ;; Append post-mortem information to the buffer - (goto-char (point-max)) - (insert-before-markers "\n" mode-name " " msg) - (forward-char -1) - (insert " at " - (substring (current-time-string) 0 -5)) - (forward-char 1) - - ;; Do command specific actions. - (TeX-command-mode-line process) - (setq TeX-command-next TeX-command-Show) - (goto-char (point-min)) - (apply TeX-sentinel-function process name nil) - - - ;; If buffer and mode line will show that the process - ;; is dead, we can delete it now. Otherwise it - ;; will stay around until M-x list-processes. - (delete-process process)) - - ;; Force mode line redisplay soon - ;; Do this in all buffers (bug#38058 and bug#40965) - (force-mode-line-update t)))) - - (setq compilation-in-progress (delq process compilation-in-progress))) - - -(defvar TeX-sentinel-function (lambda (_process _name) nil) - "Hook to cleanup TeX command buffer after termination of PROCESS. -NAME is the name of the process.") - -(make-variable-buffer-local 'TeX-sentinel-function) - - -(defvar TeX-sentinel-default-function (lambda (_process _name) nil) - "Default for `TeX-sentinel-function'. To be set in major mode. -Hook to cleanup TeX command buffer after termination of PROCESS. -NAME is the name of the process.") - -(make-variable-buffer-local 'TeX-sentinel-default-function) - -(defun TeX-TeX-sentinel (process name) - "Cleanup TeX output buffer after running TeX. - -Parse the output buffer to collect errors and warnings if the -variable `TeX-parse-all-errors' is non-nil. - -Open the error overview if -`TeX-error-overview-open-after-TeX-run' is non-nil and there are -errors or warnings to show." - (if (TeX-TeX-sentinel-check process name) - (progn - (if TeX-parse-all-errors - (TeX-parse-all-errors)) - (if (and TeX-error-overview-open-after-TeX-run - (TeX-error-overview-make-entries - (TeX-master-directory) (TeX-active-buffer))) - (TeX-error-overview))) - (message (concat name ": formatted " (TeX-current-pages))) - (let (dvi2pdf) - (if (with-current-buffer TeX-command-buffer - (and TeX-PDF-mode (setq dvi2pdf (TeX-PDF-from-DVI)))) - (setq TeX-command-next dvi2pdf) - (setq TeX-command-next TeX-command-Show))))) - -(defun TeX-current-pages () - "Return string indicating the number of pages formatted." - (cond ((null TeX-current-page) - "some pages") - ((string-match "[^0-9]1[^0-9]" TeX-current-page) - (concat TeX-current-page " page")) - (t - (concat TeX-current-page " pages")))) - -(defun TeX-TeX-sentinel-check (process name) - "Cleanup TeX output buffer after running TeX. -Return nil only if no errors were found." - (save-excursion - (goto-char (point-max)) - (cond - ((and (string-match "ConTeXt" name) (boundp 'ConTeXt-Mark-version) - (with-current-buffer TeX-command-buffer - (string= ConTeXt-Mark-version "IV"))) - (when (re-search-backward " > result saved in file: \\(.*?\\), " nil t) - (let ((output-file (TeX-match-buffer 1))) - ;; Shave off quotation marks if present. - (when (string-match "\\`\"\\(.*\\)\"\\'" output-file) - (setq output-file (match-string 1 output-file))) - (setq TeX-output-extension - (if (string-match "\\.\\([^.]*\\)$" output-file) - (match-string 1 output-file) - "dvi"))) - (if (re-search-forward ", \\([0-9]+\\) shipped pages, " nil t) - (setq TeX-current-page (concat "{" (TeX-match-buffer 1) "}"))))) - (t - (if (re-search-backward "^Output written on \\(.*?\\) (\\([0-9]+\\) page" - nil t) - (let ((output-file (TeX-match-buffer 1))) - (setq TeX-current-page (concat "{" (TeX-match-buffer 2) "}")) - ;; Shave off quotation marks if present. - (when (string-match "\\`\"\\(.*\\)\"\\'" output-file) - (setq output-file (match-string 1 output-file))) - (setq TeX-output-extension - (if (string-match "\\.\\([^.]*\\)$" output-file) - (match-string 1 output-file) - "dvi"))))))) - (if process (TeX-format-mode-line process)) - (if (re-search-forward "^\\(!\\|.*:[0-9]+:\\) " nil t) - (progn - (message "%s errors in `%s'. Use %s to display." name (buffer-name) - (substitute-command-keys - "\\<TeX-mode-map>\\[TeX-next-error]")) - (setq TeX-command-next TeX-command-default) - ;; error reported to TeX-error-report-switches - (setq TeX-error-report-switches - (plist-put TeX-error-report-switches - (intern (plist-get TeX-error-report-switches - 'TeX-current-master)) - t)) - t) - (let (dvi2pdf) - (if (with-current-buffer TeX-command-buffer - (and TeX-PDF-mode (setq dvi2pdf (TeX-PDF-from-DVI)))) - (setq TeX-command-next dvi2pdf) - (setq TeX-command-next TeX-command-Show))) - nil)) - -;; This regexp should catch warnings of the type -;; LaTeX Warning: ... -;; LaTeX Font Warning: ... -;; Package xyz123 Warning: ... -;; Class xyz123 Warning: ... -(defvar LaTeX-warnings-regexp - "\\(?:LaTeX\\|Class\\|Package\\|\\*\\) [-A-Za-z0-9]* ?[Ww]arning:" - "Regexp matching LaTeX warnings.") - -(defun TeX-LaTeX-sentinel-has-warnings () - "Return non-nil, if the output buffer contains warnings. -Warnings can be indicated by LaTeX or packages." - (save-excursion - (goto-char (point-min)) - (re-search-forward (concat "^" LaTeX-warnings-regexp) nil t))) - -(defun TeX-LaTeX-sentinel-has-bad-boxes () - "Return non-nil, if LaTeX output indicates overfull or underfull boxes." - (save-excursion - (goto-char (point-min)) - (re-search-forward "^\\(Ov\\|Und\\)erfull \\\\" nil t))) - -;; should go into latex.el? --pg -(defun TeX-LaTeX-sentinel (process name) - "Cleanup TeX output buffer after running LaTeX. - -Parse the output buffer to collect errors and warnings if the -variable `TeX-parse-all-errors' is non-nil. - -Open the error overview if -`TeX-error-overview-open-after-TeX-run' is non-nil and there are -errors or warnings to show." - (if TeX-parse-all-errors - (TeX-parse-all-errors)) - (if (and TeX-error-overview-open-after-TeX-run - (TeX-error-overview-make-entries - (TeX-master-directory) (TeX-active-buffer))) - (TeX-error-overview)) - (cond ((TeX-TeX-sentinel-check process name)) - ((and (save-excursion - (re-search-forward - "^Package biblatex Warning: Please (re)run Biber on the file" - nil t)) - (with-current-buffer TeX-command-buffer - (and (LaTeX-bibliography-list) - (TeX-check-files (TeX-master-file "bbl") - (TeX-style-list) - (append TeX-file-extensions - BibTeX-file-extensions - TeX-Biber-file-extensions))))) - (message "%s%s" "You should run Biber to get citations right, " - (TeX-current-pages)) - (setq TeX-command-next (with-current-buffer TeX-command-buffer - TeX-command-Biber))) - ((and (save-excursion - (re-search-forward - "^\\(?:LaTeX\\|Package natbib\\) Warning: Citation" nil t)) - (with-current-buffer TeX-command-buffer - (and (LaTeX-bibliography-list) - (TeX-check-files (TeX-master-file "bbl") - (TeX-style-list) - (append TeX-file-extensions - BibTeX-file-extensions - TeX-Biber-file-extensions))))) - (message "%s%s" "You should run BibTeX to get citations right, " - (TeX-current-pages)) - (setq TeX-command-next (with-current-buffer TeX-command-buffer - TeX-command-BibTeX))) - ((re-search-forward "Package biblatex Warning: Please rerun LaTeX" nil t) - (message "%s%s" "You should run LaTeX again, " (TeX-current-pages)) - (setq TeX-command-next TeX-command-default)) - ((re-search-forward "^(biblatex)\\W+Page breaks have changed" nil t) - (message "%s%s" "You should run LaTeX again - page breaks have changed, " - (TeX-current-pages)) - (setq TeX-command-next TeX-command-default)) - ((re-search-forward "^\\(?:LaTeX Warning: Label(s)\\|\ -Package natbib Warning: Citation(s)\\)" nil t) - (message "%s%s" "You should run LaTeX again to get references right, " - (TeX-current-pages)) - (setq TeX-command-next TeX-command-default)) - ((re-search-forward - "^\\(?:(rerunfilecheck)\\|Package hyperref Warning:\\)\\W+\ -Rerun to get outlines right" nil t) - (message "%s%s" "You should run LaTeX again to get outlines right, " - (TeX-current-pages)) - (setq TeX-command-next TeX-command-default)) - ((re-search-forward "^LaTeX Warning: Reference" nil t) - (message "%s%s%s" name ": there were unresolved references, " - (TeX-current-pages)) - (let (dvi2pdf) - (if (with-current-buffer TeX-command-buffer - (and TeX-PDF-mode (setq dvi2pdf (TeX-PDF-from-DVI)))) - (setq TeX-command-next dvi2pdf) - (setq TeX-command-next TeX-command-Show)))) - ((re-search-forward "^\\(?:LaTeX Warning: Citation\\|\ -Package natbib Warning:.*undefined citations\\)" nil t) - (message "%s%s%s" name ": there were unresolved citations, " - (TeX-current-pages)) - (let (dvi2pdf) - (if (with-current-buffer TeX-command-buffer - (and TeX-PDF-mode (setq dvi2pdf (TeX-PDF-from-DVI)))) - (setq TeX-command-next dvi2pdf) - (setq TeX-command-next TeX-command-Show)))) - ((re-search-forward "^No file .*\\.\\(toc\\|lof\\|lot\\)\\.$" nil t) - (message "%s" (concat "You should run LaTeX again to get " - (upcase (match-string-no-properties 1)) - " right")) - (setq TeX-command-next TeX-command-default)) - ((re-search-forward "Package longtable Warning: Table widths have \ -changed\\. Rerun LaTeX\\." nil t) - (message - "%s" "You should run LaTeX again to get table formatting right") - (setq TeX-command-next TeX-command-default)) - ((re-search-forward "^hf-TikZ Warning: Mark '.*' changed\\. \ -Rerun to get mark in right position\\." nil t) - (message - "%s" "You should run LaTeX again to get TikZ marks in right position") - (setq TeX-command-next TeX-command-default)) - ((re-search-forward "^\\* xsim warning: \"rerun\"" nil t) - (message - "%s" "You should run LaTeX again to synchronize exercise properties") - (setq TeX-command-next TeX-command-default)) - ((re-search-forward - "^\\(\\*\\* \\)?J?I?p?\\(La\\|Sli\\)TeX\\(2e\\)? \ -\\(Version\\|ver\\.\\|<[0-9/-]*\\(?:u[^>]*\\)?>\\)" nil t) - (let* ((warnings (and TeX-debug-warnings - (TeX-LaTeX-sentinel-has-warnings))) - (bad-boxes (and TeX-debug-bad-boxes - (TeX-LaTeX-sentinel-has-bad-boxes))) - (add-info (when (or warnings bad-boxes) - (concat " (with " - (when warnings "warnings") - (when (and warnings bad-boxes) " and ") - (when bad-boxes "bad boxes") - ")")))) - (message "%s" (concat name ": successfully formatted " - (TeX-current-pages) add-info))) - (let (dvi2pdf) - (if (with-current-buffer TeX-command-buffer - (and TeX-PDF-mode (setq dvi2pdf (TeX-PDF-from-DVI)))) - (setq TeX-command-next dvi2pdf) - (setq TeX-command-next TeX-command-Show)))) - (t - (message "%s%s%s" name ": problems after " (TeX-current-pages)) - (setq TeX-command-next TeX-command-default))) - - ;; Check whether the idx file changed. - (let (idx-file) - (and (file-exists-p - (setq idx-file - (with-current-buffer TeX-command-buffer - (expand-file-name (TeX-active-master "idx"))))) - ;; imakeidx package automatically runs makeindex, thus, we need to be - ;; sure .ind file isn't newer than .idx. - (TeX-check-files (with-current-buffer TeX-command-buffer - (expand-file-name (TeX-active-master "ind"))) - (with-current-buffer TeX-command-buffer - (list (file-name-nondirectory (TeX-active-master)))) - '("idx")) - (with-temp-buffer - (insert-file-contents-literally idx-file) - (not (equal - ;; Compare old md5 hash of the idx file with the new one. - (cdr (assoc idx-file LaTeX-idx-md5-alist)) - (md5 (current-buffer))))) - (push (cons idx-file t) LaTeX-idx-changed-alist))) - - (unless (TeX-error-report-has-errors-p) - (run-hook-with-args 'TeX-after-compilation-finished-functions - (with-current-buffer TeX-command-buffer - (expand-file-name - (TeX-active-master (TeX-output-extension))))))) - -;; should go into latex.el? --pg -(defun TeX-BibTeX-sentinel (_process _name) - "Cleanup TeX output buffer after running BibTeX." - (goto-char (point-max)) - (cond - ;; Check whether BibTeX reports any warnings or errors. - ((re-search-backward (concat - "^(There \\(?:was\\|were\\) \\([0-9]+\\) " - "\\(warnings?\\|error messages?\\))") - nil t) - ;; Tell the user their number so that she sees whether the - ;; situation is getting better or worse. - (message (concat "BibTeX finished with %s %s. " - "Type `%s' to display output.") - (match-string 1) (match-string 2) - (substitute-command-keys - "\\<TeX-mode-map>\\[TeX-recenter-output-buffer]"))) - (t - (message (concat "BibTeX finished successfully. " - "Run LaTeX again to get citations right.")))) - ;; In any case, run the default next command. - (setq TeX-command-next TeX-command-default)) - -(defun TeX-Biber-sentinel (_process _name) - "Cleanup TeX output buffer after running Biber." - (goto-char (point-max)) - (cond - ((re-search-backward "^INFO - \\(WARNINGS\\|ERRORS\\): \\([0-9]+\\)" nil t) - (message (concat "Biber finished with %s %s. " - "Type `%s' to display output.") - (match-string 2) (downcase (match-string 1)) - (substitute-command-keys - "\\<TeX-mode-map>\\[TeX-recenter-output-buffer]")) - (setq TeX-command-next TeX-command-default)) - ((re-search-backward "^FATAL" nil t) - (message (concat "Biber had a fatal error and did not finish! " - "Type `%s' to display output.") - (substitute-command-keys - "\\<TeX-mode-map>\\[TeX-recenter-output-buffer]")) - (setq TeX-command-next TeX-command-Biber)) - (t - (message (concat "Biber finished successfully. " - "Run LaTeX again to get citations right.")) - (setq TeX-command-next TeX-command-default)))) - -(defun TeX-dvips-sentinel (_process _name) - "Cleanup TeX output buffer after running dvips." - (goto-char (point-max)) - (cond - ((search-backward "TeX Output exited abnormally" nil t) - (message "Dvips failed. Type `%s' to display output." - (substitute-command-keys - "\\<TeX-mode-map>\\[TeX-recenter-output-buffer]"))) - (t - (if (with-current-buffer TeX-command-buffer - (and (equal (TeX-PDF-from-DVI) "Dvips") TeX-PDF-mode)) - (setq TeX-output-extension "ps" - TeX-command-next "Ps2pdf")) - (message "Dvips finished successfully. ")))) - -(defun TeX-dvipdfmx-sentinel (_process _name) - "Cleanup TeX output buffer after running dvipdfmx." - (goto-char (point-max)) - (cond - ((search-backward "TeX Output exited abnormally" nil t) - (message "Dvipdfmx failed. Type `%s' to display output." - (substitute-command-keys - "\\<TeX-mode-map>\\[TeX-recenter-output-buffer]"))) - (t - (if (with-current-buffer TeX-command-buffer - (and (equal (TeX-PDF-from-DVI) "Dvipdfmx") TeX-PDF-mode)) - (setq TeX-output-extension "pdf" - TeX-command-next TeX-command-Show)) - (message "Dvipdfmx finished successfully. ")))) - -(defun TeX-ps2pdf-sentinel (_process _name) - "Cleanup TeX output buffer after running ps2pdf." - (goto-char (point-max)) - (cond - ((search-backward "TeX Output exited abnormally" nil t) - (message "ps2pdf failed. Type `%s' to display output." - (substitute-command-keys - "\\<TeX-mode-map>\\[TeX-recenter-output-buffer]"))) - (t - (if (with-current-buffer TeX-command-buffer - (and (equal (TeX-PDF-from-DVI) "Dvips") TeX-PDF-mode)) - (setq TeX-command-next TeX-command-Show - TeX-output-extension "pdf")) - (message "ps2pdf finished successfully. ")))) - -(defun TeX-index-sentinel (_process _name) - "Cleanup TeX output buffer after compiling index." - (goto-char (point-max)) - (cond - ((search-backward "TeX Output exited abnormally" nil t) - (message "Index failed. Type `%s' to display output." - (substitute-command-keys - "\\<TeX-mode-map>\\[TeX-recenter-output-buffer]"))) - (t - (setq TeX-command-next TeX-command-default) - (message (concat "Index finished successfully. " - "Run LaTeX again to get index right."))))) - -(defun TeX-command-sequence-sentinel (process string) - "Call the appropriate sentinel for the current PROCESS. -Pass two arguments PROCESS and STRING to the sentinel. - -If there are no errors, call back `TeX-command-sequence' using -`TeX-command-sequence-command' as command argument, unless this -variable is nil." - (with-current-buffer (process-buffer process) - (funcall TeX-command-sequence-sentinel process string) - (if (string-match "\\(finished\\|exited\\)" string) - (with-current-buffer TeX-command-buffer - (unless - (or - (TeX-error-report-has-errors-p) - (null TeX-command-sequence-command)) - (TeX-command-sequence TeX-command-sequence-command nil - TeX-command-sequence-file-function)))))) - -;;; Process Control - -;; COMPATIBILITY for emacs < 27 -(if (< emacs-major-version 27) - (or (assq 'compilation-in-progress minor-mode-alist) - (setq minor-mode-alist (cons '(compilation-in-progress " Compiling") - minor-mode-alist)))) - -(defun TeX-process-get-variable (name symbol &optional default) - "Return the value in the process buffer for NAME of SYMBOL. - -Return DEFAULT if the process buffer does not exist or SYMBOL is not -defined." - (let ((buffer (TeX-process-buffer name))) - (if (and buffer - (local-variable-p symbol buffer)) - (with-current-buffer buffer - (symbol-value symbol)) - default))) - -(defun TeX-process-set-variable (name symbol value) - "Set the variable SYMBOL in the process buffer to VALUE. -Return nil only if no process buffer exists." - (let ((buffer (TeX-process-buffer name))) - (if buffer - (with-current-buffer buffer - (set symbol value) - t) - nil))) - -(defun TeX-process-check (name) - "Check if a process for the TeX document NAME already exist. -If so, give the user the choice of aborting the process or the current -command." - (let (process) - (while (and (setq process (TeX-process name)) - (eq (process-status process) 'run)) - (cond - ((yes-or-no-p (concat "Process `" - (process-name process) - "' for document `" - name - "' running, kill it? ")) - (delete-process process)) - ((eq (process-status process) 'run) - (error "Cannot have two processes for the same document")))))) - -(defun TeX-process-buffer-name (name) - "Return name of AUCTeX buffer associated with the document NAME." - (concat "*" (abbreviate-file-name (expand-file-name name)) " output*")) - -(defun TeX-process-buffer (name) - "Return the AUCTeX buffer associated with the document NAME." - (get-buffer (TeX-process-buffer-name name))) - -(defun TeX-process (name) - "Return AUCTeX process associated with the document NAME." - (and TeX-process-asynchronous - (get-buffer-process (TeX-process-buffer name)))) - -;;; Process Filters - -(defun TeX-command-mode-line (process) - "Format the mode line for a buffer containing output from PROCESS." - (setq mode-line-process (concat ": " - (symbol-name (process-status process)))) - (force-mode-line-update)) - -(defun TeX-command-filter (process string) - "Filter to process normal output." - (with-current-buffer (process-buffer process) - (save-excursion - (goto-char (process-mark process)) - (insert-before-markers string) - (set-marker (process-mark process) (point))))) - -(defvar TeX-current-page nil - "The page number currently being formatted, enclosed in brackets.") - - (make-variable-buffer-local 'TeX-current-page) - -(defun TeX-format-mode-line (process) - "Format the mode line for a buffer containing TeX output from PROCESS." - (setq mode-line-process (concat " " TeX-current-page ": " - (symbol-name (process-status process)))) - (force-mode-line-update)) - -(defun TeX-format-filter (process string) - "Filter to process TeX output." - (with-current-buffer (process-buffer process) - (let (str pos end (pt (marker-position (process-mark process)))) - (save-excursion - (goto-char pt) - (insert-before-markers string) - (set-marker (process-mark process) (point)) - ;; Remove line breaks at columns 79 and 80 - (while (> (point) pt) - (end-of-line 0) - (when (and (memq (- (point) (line-beginning-position)) '(79 80)) - ;; Heuristic: Don't delete the linebreak if the next line - ;; is empty or starts with an opening parenthesis, or if - ;; point is located after a period and in the next line no - ;; word char follows. - (not (memq (char-after (1+ (point))) '(?\n ?\())) - (not (and (eq (char-before) ?.) - (char-after (1+ (point))) - (not (eq ?w (char-syntax (char-after (1+ (point))))))))) - (delete-char 1))) - (goto-char (marker-position (process-mark process))) - ;; Determine current page - (while (and pt - (skip-chars-backward "^]" pt) - (> (point) pt)) - (setq end (point)) - (backward-char) - (skip-chars-backward "-0-9\n." (max (point-min) (- pt 128))) - (when (and (eq ?\[ (char-before)) - (not (eq ?\] (char-after))) - (progn - (setq str (buffer-substring (1- (point)) end) - pos nil) - (while (setq pos (string-match "\n" str pos)) - (setq str (replace-match "" t t str))) - (string-match - "\\`\\[-?[0-9]+\\(\\.-?[0-9]+\\)\\{0,9\\}\\]\\'" - str))) - (setq TeX-current-page str - pt nil) - (TeX-format-mode-line process))))))) - -(defvar TeX-parse-function nil - "Function to call to parse content of TeX output buffer.") -(make-variable-buffer-local 'TeX-parse-function) - -(defun TeX-background-filter (_process string) - "Filter to process background output." - (let ((old-window (selected-window)) - (pop-up-windows t)) - (TeX-pop-to-buffer "*TeX background*" nil t) - (goto-char (point-max)) - (insert string) - (select-window old-window))) - -;; Copy and adaption of `comint-postoutput-scroll-to-bottom' from CVS -;; Emacs of 2005-04-24. -(defun TeX-interactive-goto-prompt (string) - "Move point to prompt of an interactive TeX run." - (let* ((selected (selected-window)) - (current (current-buffer)) - (process (get-buffer-process current))) - (unwind-protect - (when process - (walk-windows - (lambda (window) - (when (eq (window-buffer window) current) - (select-window window) - (when (and (< (point) (process-mark process)) - (string-match "^\\? $" string)) - (goto-char (process-mark process))) - (select-window selected))) - nil t)) - (set-buffer current)))) - - -;;; Active Process - -(defvar TeX-current-process-region-p nil - "Non-nil means that the last TeX command is on a region.") - -(defun TeX-active-process () - "Return the active process for the current buffer." - (TeX-process (TeX-active-master))) - -(defun TeX-active-buffer () - "Return the buffer of the active process for this buffer." - (and TeX-command-buffer - (with-current-buffer TeX-command-buffer - (TeX-process-buffer (TeX-active-master))))) - -(defun TeX-active-master (&optional extension nondirectory _ignore) - "The master file currently being compiled. - -If optional argument EXTENSION is non-nil, add that file extension to -the name. Special value t means use `TeX-default-extension'. - -If optional second argument NONDIRECTORY is non-nil, do not include -the directory. - -The compatibility argument IGNORE is ignored." - ;; The third argument `_ignore' is kept for symmetry with - ;; `TeX-master-file's third argument `ask'. For example, it's used - ;; in `TeX-active-master-with-quotes' for backward compatibility. - ;; Keep this in mind should you want to use another argument here. - ;; See also the similar comment in `TeX-region-file'. - (if TeX-current-process-region-p - (TeX-region-file extension nondirectory) - (TeX-master-file extension nondirectory))) - -(defvar TeX-command-buffer nil - "The buffer from where the last TeX command was issued.") - -;;; Region File - - -(defvar TeX-region-hook nil - "List of hooks to run before the region file is saved. -The hooks are run in the region buffer, you may use the variable -`TeX-region-master-buffer' to access the buffer of the master -file and `TeX-region-orig-buffer' to access the buffer where -\\[TeX-command-region] or \\[TeX-command-buffer] is invoked -from.") - -(defun TeX-quote-filename (file) - "Convert file name FILE into a form acceptable to TeX." - (let (pos) - (while (setq pos (string-match "\\\\" file pos)) - (setq file (replace-match "/" t t file 0) - pos (1+ pos))) - (while (setq pos (string-match "[~#]" file pos)) - (setq file (replace-match "\\\\string\\&" t nil file 0) - pos (+ pos 8)))) - ;; Use \unexpanded so that \message outputs the raw file name. - ;; When \usepackage[utf8]{inputenc} is used in standard (pdf)latex, - ;; \message does not output non-ascii file name in raw form without - ;; \unexpanded, which makes AUCTeX to fail to recognize the file - ;; names right when analysing the process output buffer. - ;; Note that \usepackage[utf8]{inputenc} is enabled by default in - ;; standard (pdf)latex since TeXLive 2018. - (if (and (memq major-mode '(latex-mode doctex-mode)) - ;; Japanese upLaTeX requires the same treatment with - ;; respect to non-ascii characters other than Japanese, in - ;; file names within \message{}. - ;; However, pLaTeX (non u- version) does not support - ;; non-ascii file name encoded in UTF-8. So considering - ;; `ptex' doesn't make sense here. We cater for only - ;; `default' and `uptex' engines. - (memq TeX-engine '(default uptex))) - ;; It would fail to put entire `file' inside \unexpanded{} when - ;; the above loop injects \string before "#" and "~". So put - ;; only multibyte characters inside \unexpanded{}. - ;; It is safe in upLaTeX to use \unexpanded{} on Japanese - ;; characters though they are handled by upLaTeX in a totally - ;; different way from inputenc. - ;; Thus put all multibyte characters, without considering - ;; whether they are Japanese or not, inside \unexpanded{}. - (replace-regexp-in-string "[[:multibyte:]]+" - "\\\\unexpanded{\\&}" file t) - file)) - -(defvar-local TeX-region-orig-buffer nil - "The original buffer in which the TeX-region was created.") - -(defvar-local TeX-region-master-buffer nil - "The TeX-master buffer of the document for which the TeX-region -was created.") - -(defun TeX-region-create (file region original offset) - "Create a new file named FILE with the string REGION. -The region is taken from ORIGINAL starting at line OFFSET. - -The current buffer and master file is searched, in order to ensure -that the TeX header and trailer information is also included. - -The OFFSET is used to provide the debugger with information about the -original file." - (if (fboundp 'preview--skip-preamble-region) - (let ((temp (preview--skip-preamble-region region offset))) - (if temp - ;; Skip preamble for the sake of predumped formats. - (setq region (car temp) - offset (cdr temp))))) - - (let* (;; We shift buffer a lot, so we must keep track of the buffer - ;; local variables. - (header-end TeX-header-end) - (trailer-start TeX-trailer-start) - - ;; We seach for header and trailer in the master file. - (orig-buffer (current-buffer)) - (master-name (TeX-master-file TeX-default-extension)) - (master-buffer (find-file-noselect master-name)) - - ;; Attempt to disable font lock. - (font-lock-mode-hook nil) - ;; And insert them into the FILE buffer. - (file-buffer (let (;; Don't query for master file - (TeX-transient-master t) - ;; Don't choose a special mode (and call its hooks) - (auto-mode-alist nil) - (magic-mode-alist nil) - (enable-local-variables nil) - ;; Don't run any f-f hooks - (find-file-hook nil)) - (find-file-noselect file t))) - ;; But remember original content. - original-content - - ;; We search for the header from the master file, if it is - ;; not present in the region. - (header (if (string-match header-end region) - "" - (save-excursion - (save-restriction - (set-buffer master-buffer) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - ;; NOTE: We use the local value of - ;; TeX-header-end from the master file. - (if (not (re-search-forward TeX-header-end nil t)) - "" - (re-search-forward "[\r\n]" nil t) - (buffer-substring-no-properties - (point-min) (point))))))))) - (header-offset 0) - first-line - ;; We search for the trailer from the master file, if it is - ;; not present in the region. - (trailer-offset 0) - (trailer (if (string-match trailer-start region) - "" - (save-excursion - (save-restriction - (set-buffer master-buffer) - (save-excursion - (save-restriction - (widen) - (goto-char (point-max)) - ;; NOTE: We use the local value of - ;; TeX-trailer-start from the master file. - (if (not (re-search-backward TeX-trailer-start nil t)) - "" - ;;(beginning-of-line 1) - (re-search-backward "[\r\n]" nil t) - (setq trailer-offset (TeX-current-offset)) - (buffer-substring-no-properties - (point) (point-max)))))))))) - ;; file name should be relative to master - (setq original (TeX-quote-filename (file-relative-name - original (TeX-master-directory))) - master-name (TeX-quote-filename master-name)) - - ;; If the first line begins with "%&", put that line separately on - ;; the very first line of the region file so that the first line - ;; parsing will work. - (setq first-line (if (and (> (length header) 1) - (string= (substring header 0 2) "%&")) - ;; This would work even if header has no newline. - (substring header 0 (string-match "\n" header)) - "")) - (unless (string= first-line "") - ;; Remove first-line from header. - (setq header (substring header (length first-line))) - (setq first-line (concat first-line "\n"))) - - (with-current-buffer file-buffer - (setq buffer-read-only t - buffer-undo-list t) - (setq original-content (buffer-string)) - (let ((inhibit-read-only t)) - (erase-buffer) - (setq buffer-file-coding-system - (with-current-buffer master-buffer buffer-file-coding-system)) - (insert first-line - "\\message{ !name(" master-name ")}" - header - TeX-region-extra - "\n\\message{ !name(" original ") !offset(") - (setq header-offset (- offset - (1+ (TeX-current-offset)))) - (insert (int-to-string header-offset) - ") }\n" - region - "\n\\message{ !name(" master-name ") !offset(") - (insert (int-to-string (- trailer-offset - (1+ (TeX-current-offset)))) - ") }\n" - trailer) - (setq TeX-region-orig-buffer orig-buffer) - (setq TeX-region-master-buffer master-buffer) - (run-hooks 'TeX-region-hook) - (if (string-equal (buffer-string) original-content) - (set-buffer-modified-p nil) - (save-buffer 0)))))) - -(defun TeX-region-file (&optional extension nondirectory _ignore) - "Return TeX-region file name with EXTENSION. -If optional second argument NONDIRECTORY is non-nil, do not include -the directory. - -The compatibility argument IGNORE is ignored." - ;; The third argument `_ignore' is kept for symmetry with `TeX-master-file's - ;; third argument `ask'. For example, it's used in `TeX-command-sequence', - ;; where we don't know which function has to be called. Keep this in mind - ;; should you want to use another argument here. - (let ((master-dir (TeX-master-directory))) - (concat (or (TeX--master-output-dir master-dir nondirectory) - (if nondirectory "" master-dir)) - (cond ((eq extension t) - (concat TeX-region "." TeX-default-extension)) - (extension - (concat TeX-region "." extension)) - (t - TeX-region))))) - -(defcustom TeX-region "_region_" - "Base name of temporary file for `TeX-command-region' and `TeX-command-buffer'." - :group 'TeX-command - :type 'string) - -(defvar LaTeX-command-section-level nil - "The section level used for `LaTeX-command-section'. -Will be initialized to `LaTeX-largest-level' buffer-locally.") -(make-variable-buffer-local 'LaTeX-command-section-level) - -(defun LaTeX-command-section-level () - "Return the value of `LaTeX-command-section-level'. -Initialize it to `LaTeX-largest-level' if needed." - (unless LaTeX-command-section-level - (setq LaTeX-command-section-level LaTeX-largest-level)) - LaTeX-command-section-level) - - -(defun LaTeX-command-section-change-level (arg) - "Change `LaTeX-command-section-level' by ARG. -`LaTeX-command-section-level' is the sectioning level used to -determine the current section by `LaTeX-command-section'. -The levels are defined by `LaTeX-section-list'." - (interactive "p") - (let ((old-level (car (rassoc (list (LaTeX-command-section-level)) - LaTeX-section-list)))) - (setq LaTeX-command-section-level (+ LaTeX-command-section-level arg)) - (cond - ((> LaTeX-command-section-level 6) - (setq LaTeX-command-section-level 6) - (message "Cannot shrink LaTeX-command-section-level below subparagraph.")) - ((< LaTeX-command-section-level 0) - (setq LaTeX-command-section-level 0) - (message "Cannot enlarge LaTeX-command-section-level above part.")) - (t (message "Changed level from %s to %s." - old-level (car (rassoc (list LaTeX-command-section-level) - LaTeX-section-list))))))) - -(defun LaTeX-command-section-boundaries () - "Return the boundaries of the current section as (start . end). -The section is determined by `LaTeX-command-section-level'." - (let* ((case-fold-search nil) - (rx (concat "\\\\" (regexp-opt - (mapcar - (lambda (level) - (car (rassoc (list level) LaTeX-section-list))) - (let (r) - (dotimes (i (1+ (LaTeX-command-section-level))) - (push i r)) - r))) - "{"))) - (cons (save-excursion - (re-search-backward rx nil t) - (point)) - (save-excursion - (re-search-forward (concat rx "\\|\\\\end{document}") nil t) - (forward-line 0) - (point))))) - -(defun LaTeX-command-section (&optional override-confirm) - "Run a command on the current section. - -What makes the current section is defined by -`LaTeX-command-section-level' which can be enlarged or shrunken -with `LaTeX-command-section-change-level'. - -Query the user for a command to run on the temporary file -specified by the variable `TeX-region'. The region file will be -recreated from current section. - -If a prefix argument OVERRIDE-CONFIRM is given, confirmation will -depend on it being positive instead of the entry in -`TeX-command-list'." - (interactive "P") - (if (eq major-mode 'latex-mode) - (let* ((bounds (LaTeX-command-section-boundaries)) - (TeX-command-region-begin (car bounds)) - (TeX-command-region-end (cdr bounds))) - (TeX-command-region override-confirm)) - (error "LaTeX-command-section can only be run on LaTeX documents"))) - -(defun TeX-command-run-all-region () - "Compile the current region until an error occurs or it is finished." - (interactive) - (TeX-region-update) - (TeX-command-sequence t t #'TeX-region-file)) - -(defun LaTeX-command-run-all-section () - "Compile the current section until an error occurs or it is finished." - (interactive) - (if (eq major-mode 'latex-mode) - (let* ((bounds (LaTeX-command-section-boundaries)) - (TeX-command-region-begin (car bounds)) - (TeX-command-region-end (cdr bounds))) - (TeX-region-update) - (TeX-command-sequence t t #'TeX-region-file)) - (error "LaTeX-command-run-all-section can only be run on LaTeX documents"))) - -(defun TeX-command-run-all (arg) - "Compile the current document until an error occurs or it is finished. -With a prefix ARG (`\\[universal-argument] \\[TeX-command-run-all]'), -compile the current region instead, that is, call -`TeX-command-run-all-region'. With multiple prefix -arguments (`\\[universal-argument] \\[universal-argument] \\[TeX-command-run-all]'), -compile the current section instead, that is, call -`LaTeX-command-run-all-section'." - (interactive "P") - (cond - ((null arg) (TeX-command-sequence t t)) - ((= 4 (car arg)) (TeX-command-run-all-region)) - (t (LaTeX-command-run-all-section)))) - -;;; Parsing - -;;; - Global Parser Variables - -(defvar TeX-error-point nil - "How far we have parsed until now.") - -(make-variable-buffer-local 'TeX-error-point) - -(defvar TeX-error-file nil - "Stack of files in which errors have occurred.") - -(make-variable-buffer-local 'TeX-error-file) - -(defvar TeX-error-offset nil - "Add this to any line numbers from TeX. Stack like `TeX-error-file'.") - -(make-variable-buffer-local 'TeX-error-offset) - -(defun TeX-parse-reset (&optional reparse) - "Reset all variables used for parsing TeX output. -If optional argument REPARSE is non-nil, reparse the output log." - (setq TeX-error-point (point-min) - TeX-error-offset nil - TeX-error-file nil - TeX-error-list nil - TeX-error-last-visited -1) - (if reparse - (TeX-parse-all-errors))) - -;;; - Parsers Hooks - -;; All this parsers hooks should have the same arguments even though they will -;; be ignored, because `TeX-next-error' can call any of these functions. -(defun TeX-parse-command (_arg _reparse) - "We can't parse anything but TeX." - (error "I cannot parse %s output, sorry" - (if (TeX-active-process) - (process-name (TeX-active-process)) - "this"))) - -(defun TeX-error-list-skip-warning-p (type ignore) - "Decide if a warning of `TeX-error-list' should be skipped. - -TYPE is one of the types listed in `TeX-error-list', IGNORE -is the flag to choose if the warning should be skipped." - ;; The warning should be skipped if it... - (or - ;; ...is a warning and we want to ignore all warnings, or... - (and (null TeX-debug-warnings) - (equal type 'warning)) - ;; ...is a bad-box and we want to ignore all bad-boxes, or... - (and (null TeX-debug-bad-boxes) - (equal type 'bad-box)) - ;; ...is a warning to be ignored. - (and TeX-suppress-ignored-warnings - ignore))) - -(defun TeX-parse-TeX (arg reparse) - "Find the next error produced by running TeX. - -ARG specifies how many error messages to move, when possible; -negative means move back to previous error messages. - -If REPARSE is non-nil, reparse the output log. - -If the file occurs in an included file, the file is loaded (if not -already in an Emacs buffer) and the cursor is placed at the error." - (let ((old-buffer (current-buffer)) - max-index item) - - ;; Switch to the output buffer. - (with-current-buffer (TeX-active-buffer) - (if reparse - (TeX-parse-reset reparse)) - (if TeX-parse-all-errors - (progn - (setq arg (or arg 1) - max-index (length TeX-error-list)) - ;; This loop is needed to skip ignored warnings, when - ;; `TeX-suppress-ignored-warnings' is non-nil and there are ignore - ;; warnings. - (while (null (zerop arg)) - (setq TeX-error-last-visited - ;; Increase or decrese `TeX-error-last-visited' depending on - ;; the sign of `arg'. Note: `signum' is a function from - ;; `cl' library, do not be tempted to use it. - (if (> arg 0) - (1+ TeX-error-last-visited) - (1- TeX-error-last-visited)) - item (nth TeX-error-last-visited TeX-error-list)) - ;; Increase or decrease `arg' only if the warning isn't to be - ;; skipped. - (unless (TeX-error-list-skip-warning-p (nth 0 item) (nth 10 item)) - ;; Note: `signum' is a function from `cl' library, do not be - ;; tempted to use it. - (setq arg (if (> arg 0) - (1- arg) - (1+ arg))))) - (if (< TeX-error-last-visited -1) - (setq TeX-error-last-visited -1)) - (cond ((or (null item) - (< TeX-error-last-visited 0)) - (if (> TeX-error-last-visited max-index) - (setq TeX-error-last-visited max-index)) - (message "No more errors.") - (beep) - (TeX-pop-to-buffer old-buffer)) - (t - (apply #'TeX-find-display-help item)))) - - (goto-char TeX-error-point) - (TeX-parse-error old-buffer))))) - -;;; - Parsing (La)TeX - -(defvar TeX-translate-location-file nil) -(defvar TeX-translate-location-offset nil) -(defvar TeX-translate-location-line nil) -(defvar TeX-translate-location-string nil) -(defvar TeX-translate-location-error nil) -(defvar TeX-translate-location-context nil) - -(defvar TeX-translate-location-hook nil - "List of functions to be called before showing an error or warning. - -You might want to examine and modify the dynamically bound -variables - `TeX-translate-location-file', - `TeX-translate-location-offset', - `TeX-translate-location-line', - `TeX-translate-location-string', - `TeX-translate-location-error', and - `TeX-translate-location-context' -from this hook.") - -;; `ignore' flag should be the always the last one in the list of information -;; for each error/warning, because it can be set within `TeX-warning' by a -;; custom function taking as argument all information present in -;; `TeX-error-list' but `ignore', see `TeX-ignore-warnings'. -(defvar TeX-error-list nil - "List of warnings and errors. - -Each element of the list is a list of information for a specific -error or warning. This is the structure of each element: - * 0: type (error, warning, bad-box) - * 1: file - * 2: line - * 3: message of the error or warning - * 4: offset - * 5: context, to be displayed in the help window - * 6: string to search in the buffer, in order to find location - of the error or warning - * 7: for warnings referring to multiple lines (for exapmle, bad boxes), - the last line mentioned in the warning message - * 8: t if it is a bad-box, nil otherwise - * 9: value of `TeX-error-point' - * 10: whether the warning should be ignored - -This variable is intended to be set only in output buffer so it -will be shared among all files of the same document.") -(make-variable-buffer-local 'TeX-error-list) - -(defun TeX-parse-all-errors () - "Parse TeX output buffer to collect all warnings and errors." - ;; Reset error list. - (setq TeX-error-list nil) - (save-excursion - (goto-char (point-min)) - (while (TeX-parse-error nil t))) - ;; Reset last visited error. - (setq TeX-error-last-visited -1)) - -(defun TeX-parse-error (old &optional store) - "Goto next error. Pop to OLD buffer if no more errors are found. - -If the optional argument STORE is non-nil, the function will -store the found warning or error in `TeX-error-list' instead of -displaying the issue. - -Return non-nil if an error or warning is found." - (let ((regexp - (concat - ;; TeX error - "^\\(!\\|\\(.*?\\):[0-9]+:\\) \\|" - ;; New file - "(\n?\\([^\n()]+\\)\\|" - ;; End of file. - "\\()\\)\\|" - ;; Hook to change line numbers - " !\\(?:offset(\\([---0-9]+\\))\\|" - ;; Hook to change file name - "name(\\([^)]+\\))\\)\\|" - ;; Start of LaTeX bad box - "^\\(\\(?:Overfull\\|Underfull\\|Tight\\|Loose\\) " - ;; Horizontal bad box - "\\(?:\\\\hbox.* at lines? [0-9]+\\(?:--[0-9]+\\)?$\\|" - ;; Vertical bad box. See also `TeX-warning'. - "\\\\vbox ([ a-z0-9]+) has occurred while \\\\output is active \\[[^]]+\\]\\)\\)\\|" - ;; LaTeX warning - "^\\(" LaTeX-warnings-regexp ".*\\)")) - (error-found nil)) - (while - (cond - ((null - (re-search-forward regexp nil t)) - ;; No more errors. - (unless store - (message "No more errors.") - (beep) - (TeX-pop-to-buffer old)) - nil) - ;; TeX error - ((match-beginning 1) - (when (match-beginning 2) - (unless TeX-error-file - (push nil TeX-error-file) - (push nil TeX-error-offset)) - (unless (car TeX-error-offset) - (rplaca TeX-error-file (TeX-match-buffer 2)))) - (setq error-found t) - (if (looking-at "Preview ") - t - (TeX-error store) - nil)) - ;; LaTeX bad box - ((match-beginning 7) - ;; In `TeX-error-list' we collect all warnings, also if they're going - ;; to be actually skipped. - (if (or store TeX-debug-bad-boxes) - (progn - (setq error-found t) - (TeX-warning (TeX-match-buffer 7) (match-beginning 7) t store) - nil) - (re-search-forward "\r?\n\ -\\(?:.\\{79\\}\r?\n\ -\\)*.*\r?$") - t)) - ;; LaTeX warning - ((match-beginning 8) - ;; In `TeX-error-list' we collect all warnings, also if they're going - ;; to be actually skipped. - (if (or store TeX-debug-warnings) - (progn - (setq error-found t) - (TeX-warning (TeX-match-buffer 8) (match-beginning 8) nil store) - nil) - t)) - - ;; New file -- Push on stack - ((match-beginning 3) - (let ((file (TeX-match-buffer 3)) - (end (match-end 3))) - ;; Strip quotation marks and remove newlines if necessary - (when (or (eq (string-to-char file) ?\") - (string-match "[ \t\n]" file)) - (setq file (mapconcat #'identity (split-string file "[\"\n]+") ""))) - ;; Polish `file' string - (setq file - (let ((string file)) - (setq string - (if (string-match "\\`[ \t\n\r]+" string) - (replace-match "" t t string) - string)) - ;; Sometimes `file' is something like - ;; "./path/to/file.tex [9] [10 <./path/to/file>] " - ;; where "[9]" and "[10 <./path/to/file>]" are pages of the - ;; output file, with path to an included file. Remove these - ;; numbers together with whitespaces at the end of the - ;; string. - (if (string-match "\\( *\\(\\[[^]]+\\]\\)? *\\)*\\'" string) - (replace-match "" t t string) - string))) - (push file TeX-error-file) - (push nil TeX-error-offset) - (goto-char end)) - t) - - ;; End of file -- Pop from stack - ((match-beginning 4) - (when (> (length TeX-error-file) 0) - (pop TeX-error-file) - (pop TeX-error-offset)) - (goto-char (match-end 4)) - t) - - ;; Hook to change line numbers - ((match-beginning 5) - (setq TeX-error-offset - (list (string-to-number (TeX-match-buffer 5)))) - t) - - ;; Hook to change file name - ((match-beginning 6) - (setq TeX-error-file - (list (TeX-match-buffer 6))) - t))) - error-found)) - -(defun TeX-find-display-help (type file line error offset context string - line-end _bad-box error-point _ignore) - "Find the error and display the help. - -For a description of arguments, see `TeX-error-list'. IGNORE -value is not used here." - ;; Go back to TeX-buffer - (let ((runbuf (TeX-active-buffer)) - (master (with-current-buffer TeX-command-buffer - (expand-file-name (TeX-master-file)))) - (command-buffer TeX-command-buffer) - (TeX-translate-location-file file) - (TeX-translate-location-line line) - (TeX-translate-location-error error) - (TeX-translate-location-offset offset) - (TeX-translate-location-context context) - (TeX-translate-location-string string) - error-file-buffer start) - - (run-hooks 'TeX-translate-location-hook) - - (if TeX-translate-location-file - (progn - (setq error-file-buffer - (find-file - (expand-file-name TeX-translate-location-file - (file-name-directory master)))) - ;; Use the major mode of `TeX-command-buffer' when visiting - ;; the error point. - (if (eq major-mode (default-value 'major-mode)) - (funcall (buffer-local-value 'major-mode command-buffer))) - ;; Set the value of `TeX-command-buffer' in the next file - ;; with an error to be displayed to the value it has in the - ;; current buffer. - (setq-local TeX-command-buffer command-buffer) - - ;; Find the location of the error or warning. - (when TeX-translate-location-line - (goto-char (point-min)) - (forward-line (+ TeX-translate-location-offset - TeX-translate-location-line -1)) - (cond - ;; Error. - ((equal type 'error) - (if (not (string= TeX-translate-location-string " ")) - (search-forward TeX-translate-location-string nil t))) - ;; Warning or bad box. - (t - (beginning-of-line 0) - (setq start (point)) - (goto-char (point-min)) - (forward-line (+ TeX-translate-location-offset - line-end -1)) - (end-of-line) - (when TeX-translate-location-string - (search-backward TeX-translate-location-string start t) - (search-forward TeX-translate-location-string nil t)))))) - ;; When the file cannot be determined stay here but issue a - ;; warning. - (message "Could not determine file for %s" - (if (eq type 'error) "error" "warning")) - (beep)) - - ;; Display the help. - (cond ((eq TeX-display-help 'expert) - (TeX-pop-to-buffer runbuf nil t) - (goto-char error-point) - (if error-file-buffer - (TeX-pop-to-buffer error-file-buffer nil t))) - (TeX-display-help - (TeX-help-error - TeX-translate-location-error - (if (equal type 'warning) - (concat "\n" TeX-translate-location-context) - TeX-translate-location-context) - runbuf type)) - (t - (message "! %s" TeX-translate-location-error))))) - -(defun TeX-error (&optional store) - "Display an error. - -If optional argument STORE is non-nil, store the error -information in `TeX-error-list' instead of displaying the error." - - (let* ( ;; We need the error message to show the user. - (error (progn - (re-search-forward "\\(.*\\)") - (TeX-match-buffer 1))) - - ;; And the context for the help window. - (context-start (point)) - context-available - - ;; And the line number to position the cursor. - (line (cond - ;; regular style - ((re-search-forward "l\\.\\([0-9]+\\)" nil t) - (setq context-available t) - (string-to-number (TeX-match-buffer 1))) - ;; file:line:error style - ((save-excursion - (re-search-backward ":\\([0-9]+\\): " - (line-beginning-position) t)) - (string-to-number (TeX-match-buffer 1))) - ;; nothing found - (t 1))) - - ;; And a string of the context to search for. - (string (progn - (beginning-of-line) - (re-search-forward " \\(\\([^ \t]*$\\)\\|\\($\\)\\)") - (TeX-match-buffer 1))) - - ;; And we have now found to the end of the context. - (context (if context-available - (buffer-substring context-start (progn (forward-line 1) - (end-of-line) - (point))) - ;; There is no real context available, so we - ;; simply show the line with the error message. - (buffer-substring (1- (line-beginning-position)) - context-start))) - ;; We may use these in another buffer. - (offset (or (car TeX-error-offset) 0)) - (file (car TeX-error-file)) - info-list) - - ;; Remember where we was. - (setq TeX-error-point (point) - info-list (list 'error file line error offset context string nil nil - TeX-error-point nil)) - (if store - ;; Store the error information. - (add-to-list 'TeX-error-list info-list t) - ;; Find the error point and display the help. - (apply #'TeX-find-display-help info-list)))) - -(defun TeX-warning (warning warning-start bad-box &optional store) - "Display a warning for WARNING. - -WARNING-START is the position where WARNING starts. If BAD-BOX -is non-nil, the warning refers to a bad-box, otherwise it is a -generic warning. - -If optional argument STORE is non-nil, store the warning -information in `TeX-error-list' instead of displaying the -warning." - - (let* ( ;; line-string: match 1 is beginning line, match 2 is end line - (line-string (if bad-box - "at lines? \\([0-9]*\\)\\(?:--\\([0-9]*\\)\\)?" - ;; Traditional messages say "on input line X", - ;; the LaTeX3 \msg_line_context:. just reads - ;; "on line X". - "on \\(?:input \\)?line \\([0-9]*\\)\\.")) - ;; word-string: match 1 is the word - (word-string (if bad-box "[][\\W() ---]\\(\\w+\\)[][\\W() ---]*$" - ;; Match "ref" in both "Reference `ref' on page NN - ;; undefined" and "Citation 'ref' on page NN undefined". - "\\(?:`\\|'\\)\\([-a-zA-Z0-9:]+\\)'")) - - ;; Get error-line (warning). Don't search before `warning-start' to - ;; avoid catching completely unrelated line numbers. - (line (when (save-excursion (re-search-backward line-string - warning-start t)) - (string-to-number (TeX-match-buffer 1)))) - ;; If this is a bad box and the warning ends with "...at lines MM--NN" - ;; we can use "NN" as `line-end', in any other case (including bad - ;; boxes ending with "...at line NN") just use `line'. - (line-end (if (and bad-box (match-beginning 2)) - (string-to-number (TeX-match-buffer 2)) - line)) - - ;; Find the context - (context-start (progn (cond - ((and bad-box (string-match "\\\\hbox" warning)) - ;; Horizontal bad box - (end-of-line)) - (bad-box - ;; Vertical bad box (by exclusion), don't move - ;; point. In the output buffer, unlike in the - ;; actual *.log file, these warnings do not end - ;; with "...is active []", but in the same line - ;; there may be something else, including a new - ;; file opened. Thus, point shouldn't move - ;; from the end of the actual bad box warning. - ;; This is why the corresponding regexp in - ;; `TeX-parse-error' doesn't match everything - ;; until the end of the line. - nil) - (t - ;; Generic warning. - (beginning-of-line))) - (point))) - - (context (cond ((string-match LaTeX-warnings-regexp warning) - ;; The warnings matching `LaTeX-warnings-regexp' are - ;; emitted by \GenericWarning macro, or macros based on - ;; it (\ClassWarning, \PackageWarning, etc). After - ;; such warnings there is an empty line, just look for - ;; it to find the end. - (beginning-of-line) - (while (null (eolp)) - (forward-line 1)) - (buffer-substring context-start (progn (end-of-line) - (point)))) - - ((and bad-box (string-match "\\\\vbox" warning)) - ;; Vertical bad boxes don't provide any additional - ;; information. In this case, reuse the `warning' as - ;; `context' and don't move point, so that we avoid - ;; eating the next line that may contain another - ;; warning. See also comment for `context-start'. - (concat "\n" warning)) - - (t - ;; Horizontal bad boxes. - (forward-line 1) - (end-of-line) - (while (equal (current-column) 79) - (forward-line 1) - (end-of-line)) - (buffer-substring context-start (point))))) - - ;; This is where we want to be. - (error-point (point)) - - ;; Now find the error word. - (string (when (save-excursion - (re-search-backward word-string context-start t)) - (TeX-match-buffer 1))) - - ;; We might use these in another file. - (offset (or (car TeX-error-offset) 0)) - (file (car TeX-error-file)) - info-list ignore) - - ;; Second chance to get line number right. If `line' is nil, check whether - ;; the reference to the line number is in `context'. For example, this is - ;; the case for warnings emitted with \ClassWarning and \PackageWarning. - ;; XXX: maybe it suffices to evaluate `line' after `context' above, but I - ;; don't know if there are cases in which it's important to get `line' - ;; before `context'. - (and (null line) - (string-match line-string context) - (setq line-end - (setq line (and (match-beginning 1) - (string-to-number (match-string 1 context)))))) - - ;; This is where we start next time. - (goto-char error-point) - (setq TeX-error-point (point)) - - ;; Explanation of what follows: we add the warning to `TeX-error-list' even - ;; if it has to be ignored, with a flag specifying whether it is ignored. - ;; We do so in order to be able to change between "ignore" and "dont-ignore" - ;; behavior by just looking to the flag, without the need to reparse the - ;; output log. - - ;; Store the list of information about the warning. - (setq info-list (list (if bad-box 'bad-box 'warning) file line warning - offset context string line-end bad-box - TeX-error-point) - ;; Decide whether it should be ignored. - ignore (and TeX-ignore-warnings - (cond - ((stringp TeX-ignore-warnings) - (string-match TeX-ignore-warnings warning)) - ((fboundp TeX-ignore-warnings) - (apply TeX-ignore-warnings info-list)))) - ;; Update `info-list'. - info-list (append info-list (list ignore))) - - (if store - ;; Store the warning information. - (add-to-list 'TeX-error-list info-list t) - ;; Find the warning point and display the help. - (apply #'TeX-find-display-help info-list)))) - -;;; Error Messages - -(defcustom TeX-error-description-list nil - "User defined help messages for errors in TeX run. -See `TeX-error-description-list-local' for its format. All -entries have higher priority than those in -`TeX-error-description-list-local'. -It must not have a fallback entry that matches any error." - :group 'TeX-output - :type '(repeat (cons :tag "Entry" - (regexp :tag "Match") - (string :format "Description:\n%v")))) - -(defvar TeX-error-description-list-local - '((".*" . "No help available")) - "Buffer local help messages for errors in TeX run. -A list of the form (ERR-REGEXP . CONTEXT) used by function -`TeX-help-error' to display help-text on an error message or warning. -ERR-REGEXP should be a regular expression matching the error message -given from TeX/LaTeX, and CONTEXT should be some lines describing that -error. -Major modes of AUCTeX can set its own catalogue as buffer local -value of this variable, as LaTeX mode does. -Style files of AUCTeX can also add their own entries to buffer local -value of this variable to provide their own help messages. -It must end with a fallback entry that matches any error, for example -\(\".*\" . \"No help available\")") - -;;; - Help - -(defgroup TeX-error-description-faces nil - "Faces used in error descriptions." - :prefix "TeX-error-description-" - :group 'TeX-output) - -(defface TeX-error-description-error - ;; This is the same as `error' face in latest GNU Emacs versions. - '((((class color) (min-colors 88) (background light)) - :foreground "Red1" :weight bold) - (((class color) (min-colors 88) (background dark)) - :foreground "Pink" :weight bold) - (((class color) (min-colors 16) (background light)) - :foreground "Red1" :weight bold) - (((class color) (min-colors 16) (background dark)) - :foreground "Pink" :weight bold) - (((class color) (min-colors 8)) - :foreground "red" :weight bold) - (t (:inverse-video t :weight bold))) - "Face for \"Error\" string in error descriptions.") - -(defface TeX-error-description-warning - ;; This is the same as `warning' face in latest GNU Emacs versions. - '((((class color) (min-colors 16)) :foreground "DarkOrange" :weight bold) - (((class color)) :foreground "yellow" :weight bold)) - "Face for \"Warning\" string in error descriptions.") - -(defface TeX-error-description-tex-said - ;; This is the same as `font-lock-function-name-face' face in latest GNU - ;; Emacs versions. - '((((class color) (min-colors 88) (background light)) - :foreground "Blue1") - (((class color) (min-colors 88) (background dark)) - :foreground "LightSkyBlue") - (((class color) (min-colors 16) (background light)) - :foreground "Blue") - (((class color) (min-colors 16) (background dark)) - :foreground "LightSkyBlue") - (((class color) (min-colors 8)) - :foreground "blue" :weight bold) - (t (:inverse-video t :weight bold))) - "Face for \"TeX said\" string in error descriptions.") - -(defface TeX-error-description-help - '((t (:inherit TeX-error-description-tex-said))) - "Face for \"Help\" string in error descriptions.") - -(defun TeX-help-error (error output runbuffer type) - "Print ERROR in context OUTPUT from RUNBUFFER in another window. -TYPE is a symbol specifing if ERROR is a real error, a warning or -a bad box." - - (let ((old-buffer (current-buffer)) - (log-file (with-current-buffer runbuffer - (with-current-buffer TeX-command-buffer - (expand-file-name (TeX-active-master "log"))))) - (error-description-list - (append TeX-error-description-list - (buffer-local-value 'TeX-error-description-list-local - (buffer-local-value - 'TeX-command-buffer - runbuffer)))) - (TeX-error-pointer 0)) - - ;; Find help text entry. - (while (not (string-match (car (nth TeX-error-pointer - error-description-list)) - error)) - (setq TeX-error-pointer (+ TeX-error-pointer 1))) - - (TeX-pop-to-buffer (get-buffer-create "*TeX Help*") nil t) - (let ((inhibit-read-only t)) - (erase-buffer) - (insert - (cond - ((equal type 'error) - (propertize "ERROR" 'font-lock-face 'TeX-error-description-error)) - ((equal type 'warning) - (propertize "WARNING" 'font-lock-face 'TeX-error-description-warning)) - ((equal type 'bad-box) - (propertize "BAD BOX" 'font-lock-face 'TeX-error-description-warning))) - ": " error - (propertize "\n\n--- TeX said ---" 'font-lock-face - 'TeX-error-description-tex-said) - output - (propertize "\n--- HELP ---\n" 'font-lock-face - 'TeX-error-description-help) - (let ((help (cdr (nth TeX-error-pointer - error-description-list)))) - (save-excursion - (if (and (= (1+ TeX-error-pointer) - (length error-description-list)) - (let* ((log-buffer (find-buffer-visiting log-file))) - (if log-buffer - (progn - (set-buffer log-buffer) - (revert-buffer t t)) - (setq log-buffer - (find-file-noselect log-file)) - (set-buffer log-buffer)) - (auto-save-mode nil) - (setq buffer-read-only t) - (goto-char (point-min)) - (search-forward error nil t 1)) - (re-search-forward "^l\\." nil t) - (re-search-forward "^ [^\n]+$" nil t)) - (let ((start (1+ (point)))) - (forward-char 1) - (re-search-forward "^$") - (concat "From the .log file...\n\n" - (buffer-substring start (point)))) - help))))) - (goto-char (point-min)) - (TeX-special-mode) - (TeX-pop-to-buffer old-buffer nil t))) - -;;; Error Overview - -(defvar TeX-error-overview-active-buffer nil - "The active buffer for the current error overview.") - -(defvar TeX-error-overview-orig-frame nil - "Frame from which the error overview has been launched.") - -(defvar TeX-error-overview-orig-window nil - "Window from which the error overview has been launched.") - -(defcustom TeX-error-overview-setup nil - "The frame setup of the error overview. - -The possible value is: `separate-frame' (error oveview in a -separate frame); with a nil value the current frame is used. - -If the display does not support multi frame, the current frame -will be used regardless of the value of this variable." - :group 'TeX-output - :type '(choice - (const :tag "Error overview in separate frame" separate-frame) - (const :tag "Use current frame" nil))) - -(defun TeX-error-overview-setup () - "Return the frame setup of the error overview for the current display." - (and (display-multi-frame-p) TeX-error-overview-setup)) - -(defun TeX-error-overview-goto-source (&optional button) - "Go to the error point in the source. -If optional argument BUTTON is non-nil, go to source associated -to the selected error." - (interactive) - (let ((index (if button (button-get button 'id) (tabulated-list-get-id))) - item window) - (if index - (progn - ;; Select the source frame/window, if still live. - (if (TeX-error-overview-setup) - (if (frame-live-p TeX-error-overview-orig-frame) - (select-frame TeX-error-overview-orig-frame) - (error "You have deleted a vital frame---\ -please restart TeX error overview")) - (if (window-live-p TeX-error-overview-orig-window) - (select-window TeX-error-overview-orig-window) - (error "You have deleted a vital window---\ -please restart TeX error overview"))) - ;; Get the error details. - (with-current-buffer TeX-error-overview-active-buffer - (setq item (nth index TeX-error-list) - TeX-error-last-visited index)) - ;; Find the error and display the help. - (with-current-buffer TeX-command-buffer - ;; Find the error and display the help. - (apply #'TeX-find-display-help item)) - ;; Return to the error overview. - (if (TeX-error-overview-setup) - (select-frame TeX-error-overview-frame) - (if (setq window - (get-buffer-window TeX-error-overview-buffer-name)) - ;; If error overview window is visible just select it. - (select-window window) - ;; Otherwise, split the help window and display the error overview - ;; near to it. This should be the only reason for the error - ;; overview window not being still visible after the beginning of - ;; the function. - (select-window - (get-buffer-window (cond - ((eq TeX-display-help 'expert) - TeX-error-overview-active-buffer) - (TeX-display-help "*TeX Help*")))) - (if (window-splittable-p (selected-window) t) - (split-window-horizontally) - (split-window-vertically)) - (switch-to-buffer TeX-error-overview-buffer-name)))) - (message "No more errors.") - (beep)))) - -(defun TeX-error-overview-make-entries (&optional master-dir active-buffer) - "Generate the list of errors to be printed using `tabulated-list-entries'. -Write file names relative to MASTER-DIR when they are not absolute. - -ACTIVE-BUFFER is used as buffer from which to extract the list of -errors. If nil, defaults to `TeX-error-overview-active-buffer'." - (with-current-buffer (or active-buffer TeX-error-overview-active-buffer) - (let ((id 0) - type file line msg entries) - (mapc - (lambda (entry) - (setq type (nth 0 entry) - file (nth 1 entry) - line (nth 2 entry) - msg (nth 3 entry)) - ;; Add the entry only if it isn't to be skipped. - (unless (TeX-error-list-skip-warning-p type (nth 10 entry)) - (push - (list - ;; ID. - id - (vector - ;; File. - (if (stringp file) - (if (file-name-absolute-p file) - file - (file-relative-name file master-dir)) - "") - ;; Line. - (if (numberp line) - (number-to-string line) - "") - ;; Type. - (cond - ((equal type 'error) - (propertize "Error" 'font-lock-face 'TeX-error-description-error)) - ((equal type 'warning) - (propertize "Warning" 'font-lock-face - 'TeX-error-description-warning)) - ((equal type 'bad-box) - (propertize "Bad box" 'font-lock-face - 'TeX-error-description-warning)) - (t - "")) - ;; Message. - (list (if (stringp msg) - ;; Sometimes, the message can be longer than one line, - ;; but print here only the first one. - (progn - (string-match "^.*" msg) - (match-string 0 msg)) - "") - 'face 'link - 'follow-link t - 'id id - 'action #'TeX-error-overview-goto-source))) - entries)) - ;; Increase the `id' counter in any case. - (setq id (1+ id))) - TeX-error-list) - (reverse entries)))) - -(defun TeX-error-overview-next-error (&optional arg) - "Move to the next line and find the associated error. - -A prefix ARG specifies how many error messages to move; negative -means move back to previous error messages." - (interactive "p") - (if (= (forward-line arg) 0) - (TeX-error-overview-goto-source) - ;; If there are lines left to move we are at the beginning or at the end of - ;; the buffer and there are no more errors. - (message "No more errors.") - (beep))) - -(defun TeX-error-overview-previous-error (&optional arg) - "Move to the previous line and find the associated error. - -Prefix ARG says how many error messages to move backward (or -forward, if negative)." - (interactive "p") - (TeX-error-overview-next-error (- arg))) - -(defun TeX-error-overview-jump-to-source () - "Display the help and move point to the error source." - (interactive) - (TeX-error-overview-goto-source) - (pop-to-buffer - (save-window-excursion - (select-window TeX-error-overview-orig-window) - (current-buffer)))) - -(defun TeX-error-overview-goto-log () - "Display the current error in log buffer." - (interactive) - (let ((TeX-display-help 'expert)) - (TeX-error-overview-goto-source))) - -(defun TeX-error-overview-toggle-debug-bad-boxes () - "Run `TeX-toggle-debug-bad-boxes' and update entries list." - (interactive) - (TeX-toggle-debug-bad-boxes) - (setq tabulated-list-entries - (TeX-error-overview-make-entries - (with-current-buffer TeX-command-buffer (TeX-master-directory)))) - (tabulated-list-init-header) - (tabulated-list-print)) - -(defun TeX-error-overview-toggle-debug-warnings () - "Run `TeX-toggle-debug-warnings' and update entries list." - (interactive) - (TeX-toggle-debug-warnings) - (setq tabulated-list-entries - (TeX-error-overview-make-entries - (with-current-buffer TeX-command-buffer (TeX-master-directory)))) - (tabulated-list-init-header) - (tabulated-list-print)) - -(defun TeX-error-overview-toggle-suppress-ignored-warnings () - "Toggle visibility of ignored warnings and update entries list." - (interactive) - (TeX-toggle-suppress-ignored-warnings) - (setq tabulated-list-entries - (TeX-error-overview-make-entries - (with-current-buffer TeX-command-buffer (TeX-master-directory)))) - (tabulated-list-init-header) - (tabulated-list-print)) - -(defun TeX-error-overview-quit () - "Delete the window or the frame of the error overview." - (interactive) - (if (TeX-error-overview-setup) - (delete-frame TeX-error-overview-frame) - (delete-window)) - (setq TeX-error-overview-orig-frame nil)) - -(defvar TeX-error-overview-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "b" #'TeX-error-overview-toggle-debug-bad-boxes) - (define-key map "j" #'TeX-error-overview-jump-to-source) - (define-key map "l" #'TeX-error-overview-goto-log) - (define-key map "n" #'TeX-error-overview-next-error) - (define-key map "p" #'TeX-error-overview-previous-error) - (define-key map "q" #'TeX-error-overview-quit) - (define-key map "w" #'TeX-error-overview-toggle-debug-warnings) - (define-key map "x" #'TeX-error-overview-toggle-suppress-ignored-warnings) - (define-key map "\C-m" #'TeX-error-overview-goto-source) - map) - "Local keymap for `TeX-error-overview-mode' buffers.") - -(easy-menu-define TeX-error-overview-menu - TeX-error-overview-mode-map - "Menu used in TeX error overview mode." - '("TeX errors" - ["Next error" TeX-error-overview-next-error - :help "Jump to the next error"] - ["Previous error" TeX-error-overview-previous-error - :help "Jump to the previous error"] - ["Go to source" TeX-error-overview-goto-source - :help "Show the error in the source"] - ["Jump to source" TeX-error-overview-jump-to-source - :help "Move point to the error in the source"] - ["Go to log" TeX-error-overview-goto-log - :help "Show the error in the log buffer"] - "-" - ["Debug Bad Boxes" TeX-error-overview-toggle-debug-bad-boxes - :style toggle :selected TeX-debug-bad-boxes - :help "Show overfull and underfull boxes"] - ["Debug Warnings" TeX-error-overview-toggle-debug-warnings - :style toggle :selected TeX-debug-warnings - :help "Show warnings"] - ["Ignore Unimportant Warnings" - TeX-error-overview-toggle-suppress-ignored-warnings - :style toggle :selected TeX-suppress-ignored-warnings - :help "Hide specified warnings"] - "-" - ["Quit" TeX-error-overview-quit - :help "Quit"])) - -(defvar TeX-error-overview-list-entries nil - "List of errors to be used in the error overview.") - -(define-derived-mode TeX-error-overview-mode tabulated-list-mode - "TeX errors" - "Major mode for listing TeX errors." - (setq tabulated-list-format [("File" 25 nil) - ("Line" 4 nil :right-align t) - ("Type" 7 nil) - ("Message" 0 nil)] - tabulated-list-padding 1 - tabulated-list-entries TeX-error-overview-list-entries) - (tabulated-list-init-header) - (tabulated-list-print)) - -(defcustom TeX-error-overview-frame-parameters - '((name . "TeX errors") - (title . "TeX errors") - (height . 10) - (width . 80) - (top . (- 0)) - (left . (- 0)) - (unsplittable . t) - (minibuffer . nil) - (vertical-scroll-bars . t) - (tool-bar-lines . 0)) - "Parameters of the error overview frame." - :group 'TeX-output - :type 'alist - :options '((name string) (title string) (height integer) (width integer) - (top integer) (left integer) (unsplittable boolean) - (minibuffer boolean) (vertical-scroll-bars boolean) - (tool-bar-lines integer))) - -(defcustom TeX-error-overview-open-after-TeX-run nil - "Whether to open automatically the error overview after running TeX." - :group 'TeX-output - :type 'boolean) - -(defun TeX-error-overview () - "Show an overview of the errors occurred in the last TeX run." - (interactive) - ;; Check requirements before start. - (if (setq TeX-error-overview-active-buffer (TeX-active-buffer)) - ;; `TeX-error-overview-list-entries' is going to be used only as value - ;; of `tabulated-list-entries' in `TeX-error-overview-mode'. In - ;; principle, we don't need `TeX-error-overview-list-entries', but - ;; `tabulated-list-entries' is buffer-local and we need the list of - ;; entries before creating the error overview buffer in order to - ;; decide whether we need to show anything. - (if (setq TeX-error-overview-list-entries - (TeX-error-overview-make-entries - (TeX-master-directory))) - (progn - (setq TeX-error-overview-orig-window (selected-window) - TeX-error-overview-orig-frame - (window-frame TeX-error-overview-orig-window)) - ;; Create the error overview buffer. This is - ;; automatically killed before running TeX commands, so if - ;; exists it is up-to-date and doesn't need to be - ;; re-created. - (unless (get-buffer TeX-error-overview-buffer-name) - (with-current-buffer - (get-buffer-create TeX-error-overview-buffer-name) - (TeX-error-overview-mode))) - ;; Move point to the line associated to the last visited - ;; error. - (with-current-buffer TeX-error-overview-buffer-name - (goto-char (point-min)) - (forward-line (with-current-buffer - TeX-error-overview-active-buffer - TeX-error-last-visited)) - ;; Create a new frame for the error overview or display the - ;; buffer in the same frame, depending on the setup. - (if (TeX-error-overview-setup) - (if (frame-live-p TeX-error-overview-frame) - ;; Do not create a duplicate frame if there is - ;; already one, just select it. - (select-frame-set-input-focus - TeX-error-overview-frame) - ;; Create a new frame and store its name. - (select-frame - (setq TeX-error-overview-frame - (make-frame - TeX-error-overview-frame-parameters))) - (set-window-buffer (selected-window) - TeX-error-overview-buffer-name) - (set-window-dedicated-p (selected-window) t)) - (TeX-pop-to-buffer TeX-error-overview-buffer-name)))) - (error (concat "No error or warning to show" - ;; Suggest to display warnings and bad boxes with the - ;; appropriate key-bindings if there are such - ;; messages in the output buffer. Rationale of the - ;; test: `TeX-error-overview-list-entries' is nil, - ;; but if `TeX-error-list' is not nil it means that - ;; there are hidden warnings/bad boxes. - (when (TeX-process-get-variable (TeX-active-master) - 'TeX-error-list) - (format ". Type `%s' and `%s' to display \ -warnings and bad boxes" - (substitute-command-keys - "\\<TeX-mode-map>\\[TeX-toggle-debug-warnings]") - (substitute-command-keys - "\\<TeX-mode-map>\\[TeX-toggle-debug-bad-boxes]")))))) - (error "No process for this document"))) - -;;; Output mode - -(define-derived-mode TeX-special-mode special-mode "TeX") - -(defvar TeX-output-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map TeX-special-mode-map) - (define-key map "n" #'TeX-next-error) - (define-key map "p" #'TeX-previous-error) - (define-key map "b" #'TeX-toggle-debug-bad-boxes) - (define-key map "w" #'TeX-toggle-debug-warnings) - (define-key map "i" (lambda () - (interactive) - (with-current-buffer TeX-command-buffer - (TeX-interactive-mode (if TeX-interactive-mode -1 1))))) - (define-key map "s" (lambda () - (interactive) - (with-current-buffer TeX-command-buffer - (TeX-source-correlate-mode (if TeX-source-correlate-mode -1 1))))) - map) - "Keymap for `TeX-output-mode'.") - -(define-derived-mode TeX-output-mode TeX-special-mode "TeX Output" - "Major mode for viewing TeX output. -\\{TeX-output-mode-map} " - :syntax-table nil - (set (make-local-variable 'revert-buffer-function) - #'TeX-output-revert-buffer) - ;; special-mode makes it read-only which prevents input from TeX. - (setq buffer-read-only nil)) - -(defun TeX-output-revert-buffer (_ignore-auto _noconfirm) - "Rerun the TeX command which of which this buffer was the output." - (goto-char (point-min)) - (if (looking-at "Running `\\(.*\\)' on `\\(.*\\)' with ``\\(.*\\)''$") - (let ((name (match-string 1)) - (file (match-string 2))) - (with-current-buffer TeX-command-buffer - (TeX-command name (if (string-match TeX-region file) - #'TeX-region-file - #'TeX-master-file)))) - (error "Unable to find what command to run"))) - -(provide 'tex) - -;; Local Variables: -;; coding: utf-8 -;; End: - -;;; tex.el ends here |