6341 lines
226 KiB
EmacsLisp
6341 lines
226 KiB
EmacsLisp
;;; tex.el --- Support for TeX documents.
|
||
|
||
;; Copyright (C) 1985-1987, 1991, 1993-2015 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 21)
|
||
(error "AUCTeX requires Emacs 21 or later"))
|
||
|
||
(require 'custom)
|
||
(require 'tex-site)
|
||
(eval-when-compile
|
||
(require 'cl))
|
||
|
||
(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)
|
||
|
||
(defcustom AmS-TeX-mode-hook nil
|
||
"A hook run in AmS-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)%' %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) %t" TeX-run-compile nil
|
||
(texinfo-mode) :help "Run Makeinfo with Info output")
|
||
("Makeinfo HTML" "makeinfo %(extraopts) --html %t" TeX-run-compile nil
|
||
(texinfo-mode) :help "Run Makeinfo with HTML output")
|
||
("AmSTeX" "amstex %(PDFout) %(extraopts) %`%S%(mode)%' %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 %s" TeX-run-BibTeX nil t :help "Run BibTeX")
|
||
("Biber" "biber %s" TeX-run-Biber nil t :help "Run Biber")
|
||
("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 t
|
||
:help "Generate PostScript file")
|
||
("Dvips" "%(o?)dvips %d -o %f " TeX-run-dvips nil t
|
||
:help "Convert DVI file to PostScript")
|
||
("Ps2pdf" "ps2pdf %f" TeX-run-ps2pdf nil t
|
||
:help "Convert PostScript file to PDF")
|
||
("Index" "makeindex %s" TeX-run-index nil t
|
||
:help "Run makeindex to create index file")
|
||
("Xindy" "texindy %s" TeX-run-command nil t
|
||
: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 has 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) %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 %s.dvi && %(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 %s.dvi && %(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)
|
||
|
||
;; 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)))
|
||
("%vv" (lambda ()
|
||
(TeX-source-correlate-start-server-maybe)
|
||
(TeX-output-style-check TeX-output-view-style)))
|
||
("%v" (lambda ()
|
||
(TeX-source-correlate-start-server-maybe)
|
||
(TeX-style-check TeX-view-style)))
|
||
("%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-via-dvips-ps2pdf)
|
||
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 (assq TeX-engine (TeX-engine-alist))))))
|
||
("%(latex)" (lambda () (eval (nth 3 (assq TeX-engine (TeX-engine-alist))))))
|
||
("%(cntxcom)" ConTeXt-expand-command)
|
||
("%(execopts)" ConTeXt-expand-options)
|
||
("%(extraopts)" (lambda () TeX-command-extra-options))
|
||
("%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")))
|
||
;; `file' means to call `TeX-master-file' or `TeX-region-file'
|
||
("%s" file nil t)
|
||
("%t" file t t)
|
||
("%`" (lambda nil
|
||
(setq TeX-command-pos t TeX-command-text "")))
|
||
(" \"\\" (lambda nil
|
||
(if (eq TeX-command-pos t)
|
||
(setq TeX-command-pos pos
|
||
pos (+ 3 pos))
|
||
(setq pos (1+ pos)))))
|
||
("\"" (lambda nil (if (numberp TeX-command-pos)
|
||
(setq TeX-command-text
|
||
(concat
|
||
TeX-command-text
|
||
(substring command
|
||
TeX-command-pos
|
||
(1+ pos)))
|
||
command
|
||
(concat
|
||
(substring command
|
||
0
|
||
TeX-command-pos)
|
||
(substring command
|
||
(1+ pos)))
|
||
pos TeX-command-pos
|
||
TeX-command-pos t)
|
||
(setq pos (1+ pos)))))
|
||
("%'" (lambda nil
|
||
(prog1
|
||
(if (stringp TeX-command-text)
|
||
(progn
|
||
(setq pos (+ pos (length TeX-command-text) 9)
|
||
TeX-command-pos
|
||
(and (string-match " "
|
||
(funcall file t t))
|
||
"\""))
|
||
(concat TeX-command-text " \"\\input\""))
|
||
(setq TeX-command-pos nil)
|
||
"")
|
||
(setq TeX-command-text nil))))
|
||
("%n" TeX-current-line)
|
||
("%d" file "dvi" t)
|
||
("%f" file "ps" t)
|
||
("%o" (lambda nil (funcall file (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 special value `file'
|
||
will be expanded to the name of the file being processed, with an
|
||
optional extension.
|
||
|
||
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-bultin' 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))
|
||
|
||
;; The following dependencies are not done with autoload cookies since
|
||
;; they are only useful when tex.el is loaded, anyway. tex-buf.el
|
||
;; should remain unloaded as long as one is only editing files, so
|
||
;; requiring it here would be wrong.
|
||
|
||
(autoload 'TeX-region-create "tex-buf" nil nil)
|
||
(autoload 'TeX-save-document "tex-buf" nil t)
|
||
(autoload 'TeX-home-buffer "tex-buf" nil t)
|
||
(autoload 'TeX-pin-region "tex-buf" nil t)
|
||
(autoload 'TeX-command-region "tex-buf" nil t)
|
||
(autoload 'TeX-command-buffer "tex-buf" nil t)
|
||
(autoload 'TeX-command-master "tex-buf" nil t)
|
||
(autoload 'LaTeX-command-section "tex-buf" nil t)
|
||
(autoload 'TeX-command-run-all "tex-buf" nil t)
|
||
(autoload 'TeX-command-run-all-region "tex-buf" nil t)
|
||
(autoload 'LaTeX-command-run-all-section "tex-buf" nil t)
|
||
(autoload 'TeX-command "tex-buf" nil nil)
|
||
(autoload 'TeX-kill-job "tex-buf" nil t)
|
||
(autoload 'TeX-recenter-output-buffer "tex-buf" nil t)
|
||
(autoload 'TeX-next-error "tex-buf" nil t)
|
||
(autoload 'TeX-error-overview "tex-buf" nil t)
|
||
(autoload 'TeX-region-file "tex-buf" nil nil)
|
||
(autoload 'TeX-current-offset "tex-buf" nil nil)
|
||
(autoload 'TeX-process-set-variable "tex-buf" nil nil)
|
||
(autoload 'TeX-view "tex-buf" nil t)
|
||
|
||
;;; 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)))
|
||
(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)
|
||
|
||
(eval-and-compile
|
||
(if (featurep 'xemacs)
|
||
(defun TeX-maybe-remove-help (menu)
|
||
"Removes :help entries from menus, since XEmacs does not like them.
|
||
Also does other stuff."
|
||
(cond ((consp menu)
|
||
(cond ((eq (car menu) :help)
|
||
(TeX-maybe-remove-help (cddr menu)))
|
||
((eq (car menu) :visible)
|
||
(cons :included
|
||
(cons (cadr menu)
|
||
(TeX-maybe-remove-help (cddr menu)))))
|
||
(t (cons (TeX-maybe-remove-help (car menu))
|
||
(TeX-maybe-remove-help (cdr menu))))))
|
||
((vectorp menu)
|
||
(vconcat (TeX-maybe-remove-help (append menu nil))))
|
||
(t menu)))
|
||
(defun TeX-maybe-remove-help (menu)
|
||
"Compatibility function that would remove :help entries if on XEmacs,
|
||
but does nothing in Emacs."
|
||
menu))
|
||
(defmacro TeX-menu-with-help (menu)
|
||
"Compatibility macro that removes :help entries if on XEmacs.
|
||
Also does other stuff."
|
||
(TeX-maybe-remove-help menu)))
|
||
|
||
;;;###autoload
|
||
(defalias 'TeX-assoc-string
|
||
(symbol-function (if (featurep 'xemacs) 'assoc 'assoc-string)))
|
||
|
||
;;; 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"))))
|
||
|
||
(defadvice hack-one-local-variable (after TeX-hack-one-local-variable-after
|
||
activate)
|
||
"Call minor mode function if minor mode variable is found."
|
||
(let ((var (ad-get-arg 0))
|
||
(val (ad-get-arg 1)))
|
||
;; Instead of checking for each mode explicitely `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))
|
||
(if (symbol-value val) (funcall var 1) (funcall var 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.")
|
||
|
||
|
||
;;; Special support for XEmacs
|
||
|
||
(when (featurep 'xemacs)
|
||
|
||
(defun TeX-read-string
|
||
(prompt &optional initial-input history default-value)
|
||
(condition-case nil
|
||
(read-string prompt initial-input history default-value t)
|
||
(wrong-number-of-arguments
|
||
(read-string prompt initial-input history default-value))))
|
||
|
||
(defun TeX-mark-active ()
|
||
;; In Lucid (mark) returns nil when not active.
|
||
(if zmacs-regions
|
||
(mark)
|
||
(mark t)))
|
||
|
||
(defun TeX-active-mark ()
|
||
(and zmacs-regions (mark)))
|
||
|
||
(fset 'TeX-activate-region (symbol-function 'zmacs-activate-region))
|
||
|
||
;; I am aware that this counteracts coding conventions but I am sick
|
||
;; of it.
|
||
(unless (fboundp 'line-beginning-position)
|
||
(defalias 'line-beginning-position 'point-at-bol))
|
||
(unless (fboundp 'line-end-position)
|
||
(defalias 'line-end-position 'point-at-eol))
|
||
|
||
(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 (inner-priority outer-priority
|
||
(prios (cons nil nil)))
|
||
(map-extents
|
||
#'(lambda (ov prios)
|
||
(and
|
||
(or (eq (extent-property ov 'category) 'TeX-fold)
|
||
(extent-property ov 'preview-state))
|
||
(setcar prios
|
||
(max (or (car prios) 0)
|
||
(extent-property ov 'priority))))
|
||
nil)
|
||
nil start end prios 'start-and-end-in-region 'priority)
|
||
(map-extents
|
||
#'(lambda (ov prios)
|
||
(and
|
||
(or (eq (extent-property ov 'category) 'TeX-fold)
|
||
(extent-property ov 'preview-state))
|
||
(setcdr prios
|
||
(min (or (cdr prios) most-positive-fixnum)
|
||
(extent-property ov 'priority))))
|
||
nil)
|
||
nil start end prios
|
||
'(start-and-end-in-region negate-in-region) 'priority)
|
||
(setq inner-priority (car prios) outer-priority (cdr prios))
|
||
(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)))) )
|
||
|
||
;; 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.
|
||
;; XEmacs 21.4 `require' doesn't have the third NOERROR argument, thus we handle
|
||
;; the file-error signal with a `condition-case' also in GNU Emacs.
|
||
(condition-case nil
|
||
(require 'crm)
|
||
(file-error
|
||
(error "AUCTeX requires crm.el which is included in Emacs and
|
||
edit-utils >= 2.32 for XEmacs.")))
|
||
|
||
(if (fboundp 'completing-read-multiple)
|
||
(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))))
|
||
;; For XEmacs.
|
||
(defun TeX-completing-read-multiple
|
||
(prompt table &optional predicate require-match initial-input
|
||
hist def inherit-input-method)
|
||
"Poor mans implementation of Emacs' `completing-read-multiple' for XEmacs.
|
||
The XEmacs package edit-utils-2.32 includes `crm.el'."
|
||
(multi-prompt (if (boundp 'crm-separator) crm-separator ",") nil prompt
|
||
table predicate require-match initial-input hist)))
|
||
|
||
(if (fboundp 'line-number-at-pos)
|
||
(defalias 'TeX-line-number-at-pos 'line-number-at-pos)
|
||
;; `line-number-at-pos' from `simple.el' in Emacs CVS (2006-06-07)
|
||
(defun TeX-line-number-at-pos (&optional pos)
|
||
"Return (narrowed) buffer line number at position POS.
|
||
If POS is nil, use current buffer location."
|
||
(let ((opoint (or pos (point))) start)
|
||
(save-excursion
|
||
(goto-char (point-min))
|
||
(setq start (point))
|
||
(goto-char opoint)
|
||
(forward-line 0)
|
||
(1+ (count-lines start (point)))))))
|
||
|
||
;;; Special support for GNU Emacs
|
||
|
||
(unless (featurep 'xemacs)
|
||
|
||
(defun TeX-read-string (prompt &optional initial-input history default-value)
|
||
(read-string prompt initial-input history default-value t))
|
||
|
||
(defun TeX-mark-active ()
|
||
;; In FSF 19 mark-active indicates if mark is active.
|
||
mark-active)
|
||
|
||
(defun TeX-active-mark ()
|
||
(and transient-mark-mode mark-active))
|
||
|
||
(defun TeX-activate-region ()
|
||
(setq deactivate-mark nil)
|
||
(if (fboundp 'activate-mark)
|
||
(activate-mark)
|
||
;; COMPATIBILITY for Emacs <= 22
|
||
;; This part is adopted from `activate-mark' of Emacs 24.5.
|
||
(when (mark t)
|
||
(unless (and transient-mark-mode mark-active
|
||
(mark))
|
||
(force-mode-line-update) ;Refresh toolbar (bug#16382).
|
||
(setq mark-active t)
|
||
(unless transient-mark-mode
|
||
(setq transient-mark-mode 'lambda))
|
||
(if (boundp 'activate-mark-hook)
|
||
(run-hooks 'activate-mark-hook))))))
|
||
|
||
(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 (sort (copy-sequence keep-list) #'string<))
|
||
(setq alist (sort (copy-sequence alist)
|
||
(lambda (a b)
|
||
(string< (car a) (car b)))))
|
||
(let ((new alist) elt)
|
||
(while 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 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<))
|
||
|
||
;;; 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)
|
||
|
||
(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"))))
|
||
|
||
;;; 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")
|
||
(doctex-mode . "docTeX")
|
||
(texinfo-mode . "Texinfo")
|
||
(context-mode . "ConTeXt")))))
|
||
|
||
;;; Viewing
|
||
|
||
(defgroup TeX-view nil
|
||
"Calling viewers from AUCTeX."
|
||
:group 'TeX-command)
|
||
|
||
(defcustom TeX-view-style
|
||
`((,(concat
|
||
"^" (regexp-opt '("a4paper" "a4dutch" "a4wide" "sem-a4")) "$")
|
||
"%(o?)xdvi %dS -paper a4 %d")
|
||
(,(concat "^" (regexp-opt '("a5paper" "a5comb")) "$")
|
||
"%(o?)xdvi %dS -paper a5 %d")
|
||
("^b5paper$" "%(o?)xdvi %dS -paper b5 %d")
|
||
("^letterpaper$" "%(o?)xdvi %dS -paper us %d")
|
||
("^legalpaper$" "%(o?)xdvi %dS -paper legal %d")
|
||
("^executivepaper$" "%(o?)xdvi %dS -paper 7.25x10.5in %d")
|
||
("^landscape$" "%(o?)xdvi %dS -paper a4r -s 0 %d")
|
||
;; The latest xdvi can show embedded postscript. If you don't
|
||
;; have that, uncomment next line.
|
||
;; ("^epsf$" "ghostview %f")
|
||
("." "%(o?)xdvi %dS %d"))
|
||
"List of style options and view options.
|
||
|
||
If the first element (a regular expression) matches the name of
|
||
one of the style files, any occurrence of the string `%v' 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 `%v'
|
||
is replaced with the empty string.
|
||
|
||
As a default, the \"View\" command in `TeX-command-list' is set
|
||
to `%V'. This means that `TeX-output-view-style' will be
|
||
consulted before `TeX-view-style'. Only if no match is found in
|
||
`TeX-output-view-style' the settings in `TeX-view-style' will be
|
||
considered. If you want to bypass `TeX-output-view-style', which
|
||
is not recommended because it is more powerful than
|
||
`TeX-view-style', use `%v' in the \"View\" command."
|
||
:group 'TeX-view
|
||
:type '(repeat (group regexp (string :tag "Command"))))
|
||
|
||
(defcustom TeX-output-view-style
|
||
`(("^dvi$" ("^landscape$" "^pstricks$\\|^pst-\\|^psfrag$")
|
||
"%(o?)dvips -t landscape %d -o && gv %f")
|
||
("^dvi$" "^pstricks$\\|^pst-\\|^psfrag$" "%(o?)dvips %d -o && gv %f")
|
||
("^dvi$" (,(concat
|
||
"^" (regexp-opt '("a4paper" "a4dutch" "a4wide" "sem-a4")) "$")
|
||
"^landscape$")
|
||
"%(o?)xdvi %dS -paper a4r -s 0 %d")
|
||
("^dvi$" ,(concat
|
||
"^" (regexp-opt '("a4paper" "a4dutch" "a4wide" "sem-a4")) "$")
|
||
"%(o?)xdvi %dS -paper a4 %d")
|
||
("^dvi$" (,(concat "^" (regexp-opt '("a5paper" "a5comb")) "$")
|
||
"^landscape$")
|
||
"%(o?)xdvi %dS -paper a5r -s 0 %d")
|
||
("^dvi$" ,(concat "^" (regexp-opt '("a5paper" "a5comb")) "$")
|
||
"%(o?)xdvi %dS -paper a5 %d")
|
||
("^dvi$" "^b5paper$" "%(o?)xdvi %dS -paper b5 %d")
|
||
("^dvi$" "^letterpaper$" "%(o?)xdvi %dS -paper us %d")
|
||
("^dvi$" "^legalpaper$" "%(o?)xdvi %dS -paper legal %d")
|
||
("^dvi$" "^executivepaper$" "%(o?)xdvi %dS -paper 7.25x10.5in %d")
|
||
("^dvi$" "." "%(o?)xdvi %dS %d")
|
||
("^pdf$" "." "xpdf -remote %s -raise %o %(outpage)")
|
||
("^html?$" "." "netscape %o"))
|
||
"List of output file extensions and view options.
|
||
|
||
If the first element (a regular expression) matches the output
|
||
file extension, and the second element (a regular expression)
|
||
matches the name of one of the style options, any occurrence of
|
||
the string `%V' in a command in `TeX-command-list' will be
|
||
replaced with the third element. The first match is used; if no
|
||
match is found the `%V' is replaced with `%v'. The outcome of `%v'
|
||
is determined by the settings in `TeX-view-style' which therefore
|
||
serves as a fallback for `TeX-output-view-style'. The second
|
||
element may also be a list of regular expressions, in which case
|
||
all the regular expressions must match for the element to apply."
|
||
:group 'TeX-view
|
||
:type '(repeat (group
|
||
(regexp :tag "Extension")
|
||
(choice regexp (repeat :tag "List" regexp))
|
||
(string :tag "Command"))))
|
||
|
||
;;; Viewing (new implementation)
|
||
|
||
(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
|
||
;; Compatibility for Emacs <= 22: older Emacsen don't have FRAME argument
|
||
;; to `getenv', later versions have the `display-graphic-p' function.
|
||
(not (if (< emacs-major-version 23)
|
||
(or window-system (getenv "DISPLAY"))
|
||
(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
|
||
(TeX-match-style "\\`landscape\\'"))
|
||
(paper-portrait
|
||
(not (TeX-match-style "\\`landscape\\'")))
|
||
(paper-a4
|
||
(TeX-match-style "\\`a4paper\\|a4dutch\\|a4wide\\|sem-a4\\'"))
|
||
(paper-a5
|
||
(TeX-match-style "\\`a5paper\\|a5comb\\'"))
|
||
(paper-b5
|
||
(TeX-match-style "\\`b5paper\\'"))
|
||
(paper-letter
|
||
(TeX-match-style "\\`letterpaper\\'"))
|
||
(paper-legal
|
||
(TeX-match-style "\\`legalpaper\\'"))
|
||
(paper-executive
|
||
(TeX-match-style "\\`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)))
|
||
|
||
;; Require dbus at compile time to prevent errors due to `dbus-ignore-errors'
|
||
;; not being defined.
|
||
(eval-when-compile (and (featurep 'dbusbind)
|
||
(require 'dbus nil :no-error)))
|
||
(defun TeX-evince-dbus-p (&rest options)
|
||
"Return non-nil, if evince is installed and 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."
|
||
(let ((dbus-debug nil))
|
||
(and (featurep 'dbusbind)
|
||
(require 'dbus nil :no-error)
|
||
(dbus-ignore-errors (dbus-get-unique-name :session))
|
||
(dbus-ping :session "org.gnome.evince.Daemon")
|
||
(executable-find "evince")
|
||
(or (not (memq :forward options))
|
||
(let ((spec (dbus-introspect-get-method
|
||
:session "org.gnome.evince.Daemon"
|
||
"/org/gnome/evince/Daemon"
|
||
"org.gnome.evince.Daemon"
|
||
"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'."
|
||
(unless (featurep 'pdf-tools)
|
||
(error "PDF Tools are not installed"))
|
||
(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 (find-buffer-visiting
|
||
(concat file "." TeX-default-extension))
|
||
(current-buffer))
|
||
(pdf-sync-forward-search))
|
||
(let ((pdf (concat file "." (TeX-output-extension))))
|
||
(pop-to-buffer (or (find-buffer-visiting pdf)
|
||
(find-file-noselect pdf))))))
|
||
|
||
(defvar url-unreserved-chars)
|
||
|
||
(defun TeX-evince-sync-view ()
|
||
"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 viewer entry in `TeX-view-program-list-builtin' if
|
||
the requirements are met."
|
||
(require 'url-util)
|
||
(let* ((uri (concat "file://" (url-encode-url
|
||
(expand-file-name
|
||
(concat file "." (TeX-output-extension))))))
|
||
(owner (dbus-call-method
|
||
:session "org.gnome.evince.Daemon"
|
||
"/org/gnome/evince/Daemon"
|
||
"org.gnome.evince.Daemon"
|
||
"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
|
||
"/org/gnome/evince/Window/0"
|
||
"org.gnome.evince.Window"
|
||
"SyncView"
|
||
(buffer-file-name)
|
||
(list :struct :int32 (line-number-at-pos) :int32 (1+ (current-column)))
|
||
:uint32 0))
|
||
(error "Couldn't find the Evince instance for %s" uri))))
|
||
|
||
(defvar TeX-view-program-list-builtin
|
||
(cond
|
||
((eq system-type 'windows-nt)
|
||
'(("Yap" ("yap -1" (mode-io-correlate " -s %n%b") " %o") "yap")
|
||
("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")
|
||
("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" ,(if (TeX-evince-dbus-p :forward)
|
||
'TeX-evince-sync-view
|
||
`("evince" (mode-io-correlate
|
||
;; 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 "evince --help"))
|
||
" -i %(outpage)"
|
||
" -p %(outpage)")) " %o")) "evince")
|
||
("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))))
|
||
"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)
|
||
(add-to-list 'list `(const ,(car spec))))
|
||
(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)
|
||
(add-to-list 'list `(const ,(car spec))))
|
||
(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)
|
||
(add-to-list 'list
|
||
`(const ,(car spec))))
|
||
(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)))
|
||
(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 nil)))
|
||
((listp executable)
|
||
(catch 'notfound
|
||
(dolist (exec executable t)
|
||
(unless (executable-find (TeX-command-expand exec nil))
|
||
(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)))))))
|
||
command))))
|
||
|
||
;;; 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)))
|
||
|
||
(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))
|
||
((eq type 'omega) (TeX-PDF-mode 0))))
|
||
|
||
(define-minor-mode TeX-Omega-mode
|
||
"Minor mode for using the Omega engine."
|
||
nil nil 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)
|
||
|
||
(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)
|
||
(when (fboundp 'defvaralias)
|
||
(defvaralias 'TeX-source-specials-view-start-server
|
||
'TeX-source-correlate-start-server))
|
||
|
||
(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, e.g. 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)
|
||
((featurep 'xemacs))))
|
||
|
||
(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
|
||
(let ((map (make-sparse-keymap)))
|
||
;; (if (featurep 'xemacs)
|
||
;; (define-key map [(control button1)] #'TeX-view-mouse)
|
||
;; (define-key map [C-down-mouse-1] #'TeX-view-mouse))
|
||
map)
|
||
"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). 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)
|
||
(when (re-search-forward "!offset(\\([[:digit:]]+\\))" nil t)
|
||
(let ((offset (string-to-int (match-string-no-properties 1))))
|
||
(when TeX-region-orig-buffer
|
||
(list (expand-file-name (buffer-file-name TeX-region-orig-buffer))
|
||
(+ line offset) col)))))))
|
||
|
||
(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."
|
||
;; 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 (condition-case nil
|
||
(progn
|
||
(require 'url-parse)
|
||
(require 'url-util)
|
||
(url-unhex-string (aref (url-generic-parse-url file) 6)))
|
||
;; For Emacs 21 compatibility, which doesn't have the
|
||
;; url package.
|
||
(file-error (replace-regexp-in-string "^file://" "" file))))
|
||
(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)))))
|
||
|
||
(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
|
||
;; explicitely (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.
|
||
(when (TeX-evince-dbus-p)
|
||
(dbus-register-signal
|
||
:session nil "/org/gnome/evince/Window/0"
|
||
"org.gnome.evince.Window" "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 'TeX-booleanp)
|
||
;; We do not want the custom variable to require tex.el. This is only
|
||
;; necessary if AUCTeX was compiled with Emacs 21.
|
||
(put 'TeX-source-correlate-mode 'custom-requests nil)
|
||
(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" (line-number-at-pos)
|
||
(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 'TeX-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-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)
|
||
|
||
(defun TeX-toggle-PDF-via-dvips-ps2pdf ()
|
||
"Toggle `TeX-PDF-via-dvips-ps2pdf'."
|
||
(interactive)
|
||
(setq TeX-PDF-via-dvips-ps2pdf (not TeX-PDF-via-dvips-ps2pdf))
|
||
(message (concat "TeX-PDF-via-dvips-ps2pdf: "
|
||
(if TeX-PDF-via-dvips-ps2pdf "on" "off"))))
|
||
|
||
(define-minor-mode TeX-interactive-mode
|
||
"Minor mode for interactive runs of TeX."
|
||
nil nil 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* ((mode-prefix (TeX-mode-prefix))
|
||
(suffixes (append (symbol-value
|
||
(intern (concat mode-prefix
|
||
"-clean-intermediate-suffixes")))
|
||
(when arg
|
||
(symbol-value
|
||
(intern (concat mode-prefix
|
||
"-clean-output-suffixes"))))))
|
||
(master (TeX-active-master))
|
||
(master-dir (file-name-directory master))
|
||
(regexp (concat "\\("
|
||
(regexp-quote (file-name-nondirectory master)) "\\|"
|
||
(regexp-quote (TeX-region-file nil t))
|
||
"\\)"
|
||
"\\("
|
||
(mapconcat 'identity suffixes "\\|")
|
||
"\\)\\'"
|
||
"\\|" (regexp-quote (TeX-region-file t t))))
|
||
(files (when regexp
|
||
(directory-files (or master-dir ".") nil regexp))))
|
||
(if files
|
||
(when (or (not TeX-clean-confirm)
|
||
(condition-case nil
|
||
(dired-mark-pop-up " *Deletions*" 'delete
|
||
(if (> (length files) 1)
|
||
files
|
||
(cons t files))
|
||
'y-or-n-p "Delete files? ")
|
||
(wrong-type-argument ; e.g. with Emacs 21
|
||
(y-or-n-p (format "Delete %S? " (car files))))))
|
||
(dolist (file files)
|
||
(delete-file (concat master-dir file))))
|
||
(message "No files to be deleted"))))
|
||
|
||
;;; 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 in
|
||
the Emacs manual) 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))
|
||
(dolist (buf (buffer-list))
|
||
(when (with-current-buffer buf
|
||
(and (equal dir default-directory)
|
||
(stringp TeX-master)))
|
||
(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))))
|
||
|
||
;; 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'."
|
||
(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 ((comment-prefix (cond ((eq major-mode 'texinfo-mode) "@c ")
|
||
((eq major-mode 'doctex-mode) "% ")
|
||
(t "%%% ")))
|
||
(mode (concat (and (boundp 'japanese-TeX-mode) japanese-TeX-mode
|
||
"japanese-")
|
||
(substring (symbol-name major-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 "\n"
|
||
comment-prefix "TeX-master: " (prin1-to-string TeX-master) "\n"
|
||
comment-prefix "End:\n")))))
|
||
|
||
(defun TeX-local-master-p ()
|
||
"Return non-nil if there is a `TeX-master' entry in local variables spec.
|
||
Return nil otherwise."
|
||
(save-excursion
|
||
;; XXX: Checking -*- line necessary as well?
|
||
(goto-char (point-max))
|
||
(search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move)
|
||
(re-search-forward "^%+ *TeX-master:" nil t)))
|
||
|
||
;;; 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-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)
|
||
|
||
(defun TeX-split-string (regexp string)
|
||
"Return a list of strings.
|
||
Given REGEXP the STRING is split into sections which in string was
|
||
seperated by REGEXP.
|
||
|
||
Examples:
|
||
|
||
(TeX-split-string \"\:\" \"abc:def:ghi\")
|
||
-> (\"abc\" \"def\" \"ghi\")
|
||
|
||
(TeX-split-string \" +\" \"dvips -Plw -p3 -c4 testfile.dvi\")
|
||
|
||
-> (\"dvips\" \"-Plw\" \"-p3\" \"-c4\" \"testfile.dvi\")
|
||
|
||
If REGEXP is nil, or \"\", an error will occur."
|
||
|
||
(let ((start 0) result match)
|
||
(while (setq match (string-match regexp string start))
|
||
(push (substring string start match) result)
|
||
(setq start (match-end 0)))
|
||
(push (substring string start) result)
|
||
(nreverse result)))
|
||
|
||
(defun TeX-parse-path (env)
|
||
"Return a list if private TeX directories found in environment variable ENV."
|
||
(let* ((value (getenv env))
|
||
(entries (and value
|
||
(TeX-split-string
|
||
(if (string-match ";" value) ";" ":")
|
||
value)))
|
||
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 (append '("/" "\\") TeX-macro-global))
|
||
(setq answers (cons entry answers))))
|
||
answers))
|
||
|
||
(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 is passed as the parameter for --progname. 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 "/".
|
||
(let* ((exit-status 1)
|
||
(path-list (ignore-errors
|
||
(with-output-to-string
|
||
(setq exit-status
|
||
(call-process
|
||
"kpsewhich" nil
|
||
(list standard-output nil) nil
|
||
"--progname" program
|
||
"--expand-path"
|
||
(mapconcat #'identity vars
|
||
(if (eq system-type 'windows-nt)
|
||
";" ":"))))))))
|
||
(when (zerop exit-status)
|
||
(let ((separators (if (string-match "^[A-Za-z]:" path-list)
|
||
"[\n\r;]"
|
||
"[\n\r:]"))
|
||
path input-dir-list)
|
||
(dolist (item (condition-case nil
|
||
(split-string path-list separators t)
|
||
;; COMPATIBILITY for XEmacs <= 21.4.15
|
||
(error (delete "" (split-string path-list separators)))))
|
||
(if subdirs
|
||
(dolist (subdir subdirs)
|
||
(setq path (file-name-as-directory (concat item subdir)))
|
||
(when (file-exists-p path)
|
||
(pushnew path input-dir-list :test #'equal)))
|
||
(setq path (file-name-as-directory item))
|
||
(when (file-exists-p path)
|
||
(pushnew path input-dir-list :test #'equal))))
|
||
(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 (and (boundp 'user-emacs-directory)
|
||
(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 (and (boundp 'user-emacs-directory)
|
||
(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
|
||
|
||
(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.
|
||
|
||
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 e.g. 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))
|
||
"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 (TeX-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 (TeX-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 (TeX-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
|
||
"Nil, unless 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 (and (boundp 'TeX-auto-update)
|
||
(eq TeX-auto-update 'BibTeX)) ; 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.")
|
||
(make-variable-buffer-local 'TeX-remove-style-hook)
|
||
|
||
(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'."
|
||
: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 (upcase thing))
|
||
(upcase-plural (upcase plural)))
|
||
`(progn
|
||
(defvar ,(intern (format "%s-expert-%s-table" prefix thing))
|
||
(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 TeX-expert-macro-table)
|
||
(puthash x style TeX-expert-macro-table))))
|
||
|
||
(defun ,(intern (format "%s-filtered" list-var)) ()
|
||
,(format "Return (%s) filtered 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 TeX-expert-macro-table)))
|
||
(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.
|
||
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-symbol ()
|
||
"Perform completion on TeX/LaTeX symbol preceding point."
|
||
(interactive "*")
|
||
(let ((list TeX-complete-list)
|
||
entry)
|
||
(while list
|
||
(setq entry (car list)
|
||
list (cdr list))
|
||
(if (TeX-looking-at-backward (car entry) 250)
|
||
(setq list nil)))
|
||
(if (numberp (nth 1 entry))
|
||
(let* ((sub (nth 1 entry))
|
||
(close (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
|
||
(if (fboundp 'completion-in-region)
|
||
(completion-in-region begin end
|
||
(all-completions symbol list nil))
|
||
(message "Making completion list...")
|
||
(let ((list (all-completions symbol list nil)))
|
||
(with-output-to-temp-buffer buf-name
|
||
(display-completion-list list)))
|
||
(set-window-dedicated-p (get-buffer-window buf-name) 'soft)
|
||
(message "Making completion list...done")))))
|
||
(funcall (nth 1 entry)))))
|
||
|
||
(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 decided 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 e.g.
|
||
`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-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 (completing-read (concat "Macro (default "
|
||
TeX-default-macro
|
||
"): "
|
||
TeX-esc)
|
||
(TeX-symbol-list-filtered) nil nil nil
|
||
'TeX-macro-history TeX-default-macro)))
|
||
(when (interactive-p)
|
||
(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) ?\\)
|
||
(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)))))
|
||
|
||
(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 `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 ((exit-mark (make-marker))
|
||
(position (point)))
|
||
(TeX-parse-arguments args)
|
||
(cond ((marker-position exit-mark)
|
||
(goto-char (marker-position exit-mark))
|
||
(set-marker 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))
|
||
|
||
(defun TeX-parse-arguments (args)
|
||
"Parse TeX macro arguments ARGS.
|
||
|
||
See `TeX-parse-macro' for details."
|
||
(let ((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'.
|
||
(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))))
|
||
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 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))))
|
||
((= 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 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))
|
||
(TeX-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 last-optional-rejected t)
|
||
(insert TeX-arg-opening-brace)
|
||
(if prefix
|
||
(insert prefix))
|
||
(if (and (string-equal name "")
|
||
(null (marker-position exit-mark)))
|
||
(set-marker 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)
|
||
"Evaluates FORM, if SYMBOL is an element of LIST."
|
||
(when (memq symbol list)
|
||
(eval form)))
|
||
|
||
(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 OPTION 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]*{\\(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))))))
|
||
|
||
(when (and (boundp 'tex--prettify-symbols-alist)
|
||
(boundp 'prettify-symbols-compose-predicate))
|
||
(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)
|
||
(set (make-local-variable 'ispell-tex-p) t)
|
||
|
||
;; 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)
|
||
;; `comment-padding' is defined here as an integer for compatibility
|
||
;; reasons because older Emacsen could not cope with a string.
|
||
(set (make-local-variable 'comment-padding) 1)
|
||
;; 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.
|
||
(if (boundp 'local-write-file-hooks)
|
||
(add-hook 'local-write-file-hooks 'TeX-safe-auto-write)
|
||
(add-hook 'write-file-hooks 'TeX-safe-auto-write))
|
||
(set (make-local-variable 'TeX-auto-update) t)
|
||
|
||
(define-key TeX-mode-map "\C-xng" 'TeX-narrow-to-group)
|
||
|
||
;; Minor modes
|
||
(when TeX-source-correlate-mode
|
||
(TeX-source-correlate-mode 1))
|
||
|
||
;; Prettify Symbols mode
|
||
(when (fboundp 'TeX--prettify-symbols-compose-p)
|
||
(set (make-local-variable 'prettify-symbols-alist) tex--prettify-symbols-alist)
|
||
(TeX--if-macro-fboundp add-function
|
||
(add-function :override (local 'prettify-symbols-compose-predicate)
|
||
#'TeX--prettify-symbols-compose-p)
|
||
(set (make-local-variable 'prettify-symbols-compose-predicate)
|
||
#'TeX--prettify-symbols-compose-p)))
|
||
|
||
;; 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.
|
||
(when (featurep 'xemacs)
|
||
(unless (boundp 'find-file-hook)
|
||
(defvaralias 'find-file-hook 'find-file-hooks))
|
||
(when (not (emacs-version>= 21 5))
|
||
(make-local-hook 'find-file-hook)))
|
||
(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
|
||
|
||
(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))
|
||
;; 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 TYPE.
|
||
By default just add an `s'.
|
||
|
||
This function create 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 name
|
||
(and (boundp 'TeX-auto-update)
|
||
TeX-auto-update
|
||
(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 name
|
||
(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))
|
||
(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))
|
||
(TeX-unload-style style)
|
||
(with-current-buffer (generate-new-buffer file)
|
||
(erase-buffer)
|
||
(insert "(TeX-add-style-hook\n \""
|
||
style "\"\n (lambda ()")
|
||
(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 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."
|
||
: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)
|
||
(symbol :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 (memq 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
|
||
(if (featurep 'mule)
|
||
"\\(?:[a-zA-Z]\\|\\cj\\)"
|
||
"[a-zA-Z]")
|
||
"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 LaTeX 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.
|
||
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)
|
||
(symbol :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)
|
||
(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 (string :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 (string :format "%v")))
|
||
|
||
(defcustom BibTeX-file-extensions '("bib")
|
||
"Valid file extensions for BibTeX files."
|
||
:group 'TeX-file-extension
|
||
:type '(repeat (string :format "%v")))
|
||
|
||
(defcustom BibLaTeX-style-extensions '("bbx")
|
||
"Valid file extensions for BibLaTeX styles."
|
||
:group 'TeX-file-extension
|
||
:type '(repeat (string :format "%v")))
|
||
|
||
(defcustom BibTeX-style-extensions '("bst")
|
||
"Valid file extensions for BibTeX styles."
|
||
:group 'TeX-file-extension
|
||
:type '(repeat (string :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, `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 TeX-macro-global)
|
||
(member dir 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)
|
||
(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))
|
||
|
||
(defcustom TeX-kpathsea-path-delimiter t
|
||
"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)))
|
||
|
||
;; 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."
|
||
(and TeX-kpathsea-path-delimiter
|
||
(catch 'no-kpathsea
|
||
(let* ((dirs (if (eq scope 'local)
|
||
"."
|
||
(with-output-to-string
|
||
(unless (zerop (call-process
|
||
"kpsewhich" nil
|
||
(list standard-output nil) nil
|
||
(concat "-expand-path=" var)))
|
||
(if (eq TeX-kpathsea-path-delimiter t)
|
||
(throw 'no-kpathsea
|
||
(setq TeX-kpathsea-path-delimiter nil))
|
||
(error "kpsewhich error"))))))
|
||
result)
|
||
(when (eq TeX-kpathsea-path-delimiter t)
|
||
(setq TeX-kpathsea-path-delimiter
|
||
(if (string-match ";" dirs) ";" ":")))
|
||
(unless TeX-kpathsea-path-delimiter
|
||
(throw 'no-kpathsea nil))
|
||
(setq dirs (TeX-delete-duplicate-strings
|
||
(delete "" (split-string
|
||
dirs (concat "[\n\r"
|
||
TeX-kpathsea-path-delimiter
|
||
"]+")))))
|
||
(if (eq scope 'global)
|
||
(delete "." dirs))
|
||
(setq extensions (concat "\\." (regexp-opt extensions t) "\\'")
|
||
result (apply #'append (mapcar (lambda (x)
|
||
(when (file-readable-p x)
|
||
(directory-files
|
||
x (not nodir) extensions)))
|
||
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)
|
||
(graphics "${TEXINPUTS}" ("tex/") LaTeX-includegraphics-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* ((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) 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
|
||
(delete-dups
|
||
(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-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)))
|
||
|
||
(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)))))
|
||
|
||
(defun TeX-assoc (key list)
|
||
"Return non-nil if KEY is `equal' to the car of an element of LIST.
|
||
Like assoc, except case insensitive."
|
||
(let ((case-fold-search t))
|
||
(TeX-member key list
|
||
(lambda (a b)
|
||
(string-match (concat "^" (regexp-quote a) "$")
|
||
(car b))))))
|
||
|
||
(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-function-p (arg)
|
||
"Return non-nil if ARG is callable as a function."
|
||
(or (and (fboundp 'byte-code-function-p)
|
||
(byte-code-function-p arg))
|
||
(and (listp arg)
|
||
(eq (car arg) 'lambda))
|
||
(and (symbolp arg)
|
||
(fboundp arg))))
|
||
|
||
(defun TeX-booleanp (arg)
|
||
"Return non-nil if ARG is t or nil."
|
||
(memq arg '(t nil)))
|
||
|
||
(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 iff there's nothing but whitespace between (bob) and (point)."
|
||
(save-excursion
|
||
(skip-chars-backward " \t\n")
|
||
(bobp)))
|
||
|
||
(defun TeX-deactivate-mark ()
|
||
"Deactivate the mark.
|
||
This is a compatibility function which works both in Emacs and
|
||
XEmacs. In XEmacs the region is deactivated instead of the
|
||
mark which is sort of equivalent."
|
||
(if (featurep 'xemacs)
|
||
(zmacs-deactivate-region)
|
||
(deactivate-mark)))
|
||
|
||
(defalias 'TeX-run-mode-hooks
|
||
(if (fboundp 'run-mode-hooks) 'run-mode-hooks 'run-hooks))
|
||
|
||
(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) (add-to-list 'old-element elt t))
|
||
(cdr new-element))
|
||
(set alist-var (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 ?<3F> "." TeX-mode-syntax-table)
|
||
(modify-syntax-entry ?<3F> "." 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 be bound to `TeX-electric-macro'."
|
||
: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) (funcall 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-doc)
|
||
(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:" 'TeX-comment-or-uncomment-region) ;*** Old way
|
||
(define-key map "\C-c\"" 'TeX-uncomment) ;*** Old way
|
||
|
||
(define-key map "\C-c;" 'TeX-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-v" 'TeX-view)
|
||
;; From tex-buf.el
|
||
(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'
|
||
(if (featurep 'xemacs)
|
||
(substitute-key-definition 'next-error 'TeX-next-error map global-map)
|
||
(define-key map [remap next-error] 'TeX-next-error))
|
||
;; Remap bindings of `previous-error'
|
||
(if (featurep 'xemacs)
|
||
(substitute-key-definition 'previous-error 'TeX-previous-error
|
||
map global-map)
|
||
(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
|
||
map)
|
||
"Keymap for common TeX and LaTeX commands.")
|
||
|
||
(defun TeX-mode-specific-command-menu (mode)
|
||
"Return a Command menu specific to the major MODE."
|
||
;; COMPATIBILITY for Emacs < 21
|
||
(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
|
||
(TeX-menu-with-help
|
||
`("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)))
|
||
(TeX-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 (and TeX-parse-all-errors (fboundp 'tabulated-list-mode))]
|
||
["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 via dvips + ps2pdf" TeX-toggle-PDF-via-dvips-ps2pdf
|
||
:style toggle :selected TeX-PDF-via-dvips-ps2pdf
|
||
:visible TeX-PDF-mode
|
||
:help "Compile with (La)TeX and convert to PDF with dvips + ps2pdf"]
|
||
[ "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"]))
|
||
(let ((file 'TeX-command-on-current)) ;; is this actually needed?
|
||
(TeX-maybe-remove-help
|
||
(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
|
||
(TeX-menu-with-help
|
||
'("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
|
||
(TeX-menu-with-help
|
||
`(("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-doc
|
||
: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'.")
|
||
(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)))
|
||
|
||
|
||
;;; 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-comment-region (beg end &optional arg)
|
||
"Comment each line in the region from BEG to END.
|
||
Numeric prefix arg ARG means use ARG comment characters.
|
||
If ARG is negative, delete that many comment characters instead."
|
||
(interactive "*r\nP")
|
||
;; `comment-padding' will not be recognized in XEmacs' (21.4)
|
||
;; `comment-region', so we temporarily modify `comment-start' to get
|
||
;; proper spacing. Unfortunately we have to check for the XEmacs
|
||
;; version and cannot test if `comment-padding' is bound as this
|
||
;; gets initialized in `VirTeX-common-initialization'.
|
||
(let ((comment-start (if (and (featurep 'xemacs)
|
||
(= emacs-major-version 21)
|
||
(<= emacs-minor-version 4))
|
||
(concat comment-start (TeX-comment-padding-string))
|
||
comment-start)))
|
||
(comment-region beg end arg)))
|
||
|
||
(eval-and-compile
|
||
;; COMPATIBILITY for Emacs <= 21.3
|
||
(if (fboundp 'comment-or-uncomment-region)
|
||
(defalias 'TeX-comment-or-uncomment-region 'comment-or-uncomment-region)
|
||
;; The following function was copied from `newcomment.el' on
|
||
;; 2004-01-30 and adapted accordingly
|
||
(defun TeX-comment-or-uncomment-region (beg end &optional arg)
|
||
"Comment or uncomment a the region from BEG to END.
|
||
Call `TeX-comment-region', unless the region only consists of
|
||
comments, in which case call `TeX-uncomment-region'. If a prefix
|
||
arg ARG is given, it is passed on to the respective function."
|
||
(interactive "*r\nP")
|
||
(funcall (if (save-excursion ;; check for already commented region
|
||
(goto-char beg)
|
||
(TeX-comment-forward (point-max))
|
||
(<= end (point)))
|
||
'TeX-uncomment-region 'TeX-comment-region)
|
||
beg end arg)))
|
||
|
||
;; COMPATIBILITY for Emacs <= 20. (Introduced in 21.1?)
|
||
(if (fboundp 'uncomment-region)
|
||
(defalias 'TeX-uncomment-region 'uncomment-region)
|
||
(defun TeX-uncomment-region (beg end &optional arg)
|
||
"Remove comment characters from the beginning of each line
|
||
in the region from BEG to END. Numeric prefix arg ARG means use
|
||
ARG comment characters. If ARG is negative, delete that many
|
||
comment characters instead."
|
||
(interactive "*r\nP")
|
||
(or arg
|
||
;; Determine the number of comment characters at the
|
||
;; beginning of the first commented line.
|
||
(setq arg
|
||
(save-excursion
|
||
(goto-char beg)
|
||
(re-search-forward
|
||
(concat "^" TeX-comment-start-regexp "+") end t)
|
||
(length (match-string 0)))))
|
||
(comment-region beg end (- arg)))))
|
||
|
||
(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
|
||
(TeX-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)
|
||
(TeX-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, i.e. 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 (i (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))
|
||
|
||
;; Taken from `comment-forward' in Emacs' CVS on 2006-12-26. Used as
|
||
;; a compatibility function for XEmacs 21.4.
|
||
(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."
|
||
(when (fboundp 'comment-normalize-vars)
|
||
(comment-normalize-vars))
|
||
(if (fboundp 'comment-forward)
|
||
(comment-forward n)
|
||
(setq n (or n 1))
|
||
(if (< n 0) (error "No comment-backward")
|
||
(if comment-use-syntax (forward-comment n)
|
||
(while (> n 0)
|
||
(setq n
|
||
(if (or (forward-comment 1)
|
||
(and (looking-at comment-start-skip)
|
||
(goto-char (match-end 0))
|
||
(re-search-forward comment-end-skip nil 'move)))
|
||
(1- n) -1)))
|
||
(= n 0)))))
|
||
|
||
(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)
|
||
|
||
(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 number of open/closed braces."
|
||
(save-excursion
|
||
(let ((count 0) (limit (line-end-position)) char)
|
||
(while (progn
|
||
(skip-chars-forward "^{}\\\\" limit)
|
||
(when (and (< (point) limit) (not (TeX-in-comment)))
|
||
(setq char (char-after))
|
||
(forward-char)
|
||
(cond ((eq char ?\{)
|
||
(setq count (+ count TeX-brace-indent-level)))
|
||
((eq char ?\})
|
||
(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 (if (featurep 'xemacs)
|
||
'syntax
|
||
'syntax-table)))))
|
||
;; Preset mode-independent syntax entries. (Mode-dependent
|
||
;; entries are set in the function `TeX-search-syntax-table'.)
|
||
;; ?\", ?\( and ?\) explicitely 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, i.e. 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, i.e. 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))))
|
||
(when (eobp) (throw 'found (point))))
|
||
(t
|
||
(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-defun' 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 toggle off CJK input methods when entering math mode."
|
||
: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))
|
||
(insert "$"))))
|
||
(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))
|
||
|
||
(defvar 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.")
|
||
|
||
(defun TeX-math-input-method-off ()
|
||
"Toggle off input method when entering math mode."
|
||
(and TeX-math-toggle-off-input-method
|
||
(texmathp)
|
||
(boundp 'current-input-method) current-input-method
|
||
(string-match TeX-math-input-method-off-regexp current-input-method)
|
||
(inactivate-input-method)))
|
||
|
||
;;; Simple Commands
|
||
|
||
(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
|
||
(setq TeX-style-hook-list nil
|
||
BibTeX-global-style-files nil
|
||
BibTeX-global-files nil
|
||
BibLaTeX-global-style-files nil
|
||
TeX-Biber-global-files nil
|
||
TeX-global-input-files nil
|
||
LaTeX-global-class-files 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 "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) ?\")
|
||
?\")
|
||
((save-excursion
|
||
(forward-char (- (length open-quote)))
|
||
(looking-at (regexp-quote open-quote)))
|
||
(delete-char (- (length open-quote)))
|
||
?\")
|
||
((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 (X)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 nil
|
||
"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 http://www.gnu.org/software/auctex/ 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 http://debbugs.gnu.org/cgi/pkgreport.cgi?pkg=auctex
|
||
to browse existing AUCTeX bugs.
|
||
------------------------------------------------------------------------")))
|
||
|
||
|
||
;;; Documentation
|
||
|
||
(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
|
||
;; Explicitely supply doc directory for
|
||
;; non-kpathsea-based TeX systems.
|
||
(unless (stringp TeX-kpathsea-path-delimiter)
|
||
(or (TeX-tree-expand
|
||
'("$SYSTEXMF" "$TEXMFLOCAL" "$TEXMFMAIN" "$TEXMFDIST")
|
||
"latex" '("/doc/"))
|
||
`(,@TeX-macro-global ,@TeX-macro-private)))
|
||
'("dvi" "pdf" "ps" "txt" "html") 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, e.g. 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)
|
||
(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 (interactive-p)
|
||
(or (not name) (string= name "")))
|
||
(let ((symbol (thing-at-point 'symbol))
|
||
contained completions doc)
|
||
;; 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)
|
||
(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
|
||
|
||
;; FIXME: Document those functions and variables. -- rs
|
||
|
||
;; The FSF ispell.el use this.
|
||
(defun ispell-tex-buffer-p ()
|
||
(and (boundp 'ispell-tex-p) ispell-tex-p))
|
||
|
||
;; The FSF ispell.el might one day use this.
|
||
(setq ispell-enable-tex-parser t)
|
||
|
||
(defun TeX-run-ispell (command string file)
|
||
"Run ispell on current TeX buffer."
|
||
(cond ((and (string-equal file (TeX-region-file))
|
||
(fboundp 'ispell-region))
|
||
(call-interactively 'ispell-region))
|
||
((string-equal file (TeX-region-file))
|
||
(call-interactively 'spell-region))
|
||
((fboundp 'ispell-buffer)
|
||
(ispell-buffer))
|
||
((fboundp 'ispell)
|
||
(ispell))
|
||
(t
|
||
(spell-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 ((found nil)
|
||
(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 'regexp-quote TeX-file-extensions "\\|")
|
||
"\\)\\'"))
|
||
(buffers (buffer-list)))
|
||
(while buffers
|
||
(let* ((buffer (car buffers))
|
||
(name (buffer-file-name buffer)))
|
||
(setq buffers (cdr buffers))
|
||
(if (and name (string-match regexp name))
|
||
(progn
|
||
(save-excursion (switch-to-buffer buffer) (ispell-buffer))
|
||
(setq found t)))))))
|
||
|
||
;; Some versions of ispell 3 use this.
|
||
(defvar ispell-tex-major-modes nil)
|
||
(setq ispell-tex-major-modes
|
||
(append '(plain-tex-mode ams-tex-mode latex-mode doctex-mode)
|
||
ispell-tex-major-modes))
|
||
|
||
|
||
;;; 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)
|
||
(when (fboundp 'abbrev-table-put)
|
||
(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)
|
||
|
||
(defun TeX-how-many (regexp &optional rstart rend)
|
||
"Compatibily function for `how-many'.
|
||
Supports restriction to a region where the XEmacs version doesn't
|
||
and always returns the number of matches, also in XEmacs and GNU
|
||
Emacs 21."
|
||
;; Emacs >= 22 does what we want.
|
||
(if (>= emacs-major-version 22)
|
||
(how-many regexp rstart rend)
|
||
;; XEmacs and GNU Emacs 21 don't return the number of matches but only print
|
||
;; it.
|
||
(let ((string
|
||
(if (featurep 'xemacs)
|
||
;; XEmacs doesn't even support restriction to a region.
|
||
(save-excursion
|
||
(save-restriction
|
||
(when (and (integer-or-marker-p rstart)
|
||
(integer-or-marker-p rend))
|
||
(narrow-to-region rstart rend)
|
||
(goto-char (point-min)))
|
||
(how-many regexp)))
|
||
(how-many regexp rstart rend))))
|
||
;; Hide the message printed by `how-many'.
|
||
(message "")
|
||
;; Select the number of occurrences and convert it to a number.
|
||
(if (string-match "\\([0-9]+\\).*" string)
|
||
(string-to-number (replace-match "\\1" nil nil string))
|
||
0))))
|
||
|
||
(provide 'tex)
|
||
|
||
;; Local Variables:
|
||
;; coding: iso-8859-1
|
||
;; End:
|
||
|
||
;;; tex.el ends here
|