From becff06c71d277647eda4378203d03ab36e141eb Mon Sep 17 00:00:00 2001 From: mattkae Date: Tue, 17 May 2022 07:07:37 -0400 Subject: Evil mode and latex support --- elpa/auctex-13.1.3/latex.el | 8146 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 8146 insertions(+) create mode 100644 elpa/auctex-13.1.3/latex.el (limited to 'elpa/auctex-13.1.3/latex.el') diff --git a/elpa/auctex-13.1.3/latex.el b/elpa/auctex-13.1.3/latex.el new file mode 100644 index 0000000..5747449 --- /dev/null +++ b/elpa/auctex-13.1.3/latex.el @@ -0,0 +1,8146 @@ +;;; latex.el --- Support for LaTeX documents. -*- lexical-binding: t; -*- + +;; Copyright (C) 1991, 1993-2022 Free Software Foundation, Inc. + +;; Maintainer: auctex-devel@gnu.org +;; Keywords: tex + +;; This file is part of AUCTeX. + +;; AUCTeX is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; AUCTeX is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with AUCTeX; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +;; 02110-1301, USA. + +;;; Commentary: + +;; This file provides AUCTeX support for LaTeX. + +;;; Code: + +(require 'tex) +(require 'tex-style) +(require 'tex-ispell) +(when (<= 26 emacs-major-version) + ;; latex-flymake requires Emacs 26. + (require 'latex-flymake)) +(eval-when-compile + (require 'cl-lib)) + +;; Silence the compiler for functions: +(declare-function outline-level "ext:outline" + nil) +(declare-function outline-mark-subtree "ext:outline" + nil) +(declare-function turn-off-filladapt-mode "ext:filladapt" + nil) + +;; This function is reported to be unknown when built +;; `with-native-compilation': +(declare-function LaTeX-flymake "latex-flymake" + (report-fn &rest _args)) + +;; Silence the compiler for variables: +(defvar outline-heading-alist) +(defvar TeX-auto-file) +(defvar LaTeX-section-list-changed) + +;;; Syntax + +(defvar LaTeX-optop "[" + "The LaTeX optional argument opening character.") + +(defvar LaTeX-optcl "]" + "The LaTeX optional argument closeing character.") + +;;; Style + +(defcustom LaTeX-default-style "article" + "Default when creating new documents." + :group 'LaTeX-environment + :type 'string) + +(defcustom LaTeX-default-options nil + "Default options to documentclass. +A comma-seperated list of strings." + :group 'LaTeX-environment + :type '(repeat (string :format "%v"))) + +(make-variable-buffer-local 'LaTeX-default-options) + +(defcustom LaTeX-insert-into-comments t + "Whether insertion commands stay in comments. +This allows using the insertion commands even when +the lines are outcommented, like in dtx files." + :group 'LaTeX-environment + :type 'boolean) + +(defun LaTeX-newline () + "Start a new line potentially staying within comments. +This depends on `LaTeX-insert-into-comments'." + (interactive) + (if LaTeX-insert-into-comments + (cond ((and (save-excursion (skip-chars-backward " \t") (bolp)) + (save-excursion + (skip-chars-forward " \t") + (looking-at (concat TeX-comment-start-regexp "+")))) + (beginning-of-line) + (insert (buffer-substring-no-properties + (line-beginning-position) (match-end 0))) + (newline)) + ((and (not (bolp)) + (save-excursion + (skip-chars-forward " \t") (not (TeX-escaped-p))) + (looking-at + (concat "[ \t]*" TeX-comment-start-regexp "+[ \t]*"))) + (delete-region (match-beginning 0) (match-end 0)) + (indent-new-comment-line)) + ;; `indent-new-comment-line' does nothing when + ;; `comment-auto-fill-only-comments' is non-nil, so we + ;; must be sure to be in a comment before calling it. In + ;; any other case `newline' is used. + ((TeX-in-comment) + (indent-new-comment-line)) + (t + (newline))) + (newline))) + + +;;; Syntax Table + +(defvar LaTeX-mode-syntax-table (copy-syntax-table TeX-mode-syntax-table) + "Syntax table used in LaTeX mode.") + +(progn ; set [] to match for LaTeX. + (modify-syntax-entry (string-to-char LaTeX-optop) + (concat "(" LaTeX-optcl) + LaTeX-mode-syntax-table) + (modify-syntax-entry (string-to-char LaTeX-optcl) + (concat ")" LaTeX-optop) + LaTeX-mode-syntax-table)) + +;;; Sections + +;; Declare dynamically scoped vars. +(defvar LaTeX-title nil "Dynamically bound by `LaTeX-section'.") +(defvar LaTeX-name nil "Dynamically bound by `LaTeX-section'.") +(defvar LaTeX-level nil "Dynamically bound by `LaTeX-section'.") +(defvar LaTeX-done-mark nil "Dynamically bound by `LaTeX-section'.") +(defvar LaTeX-toc nil "Dynamically bound by `LaTeX-section'.") + +(defun LaTeX-section (arg) + "Insert a template for a LaTeX section. +Determine the type of section to be inserted, by the argument ARG. + +If ARG is nil or missing, use the current level. +If ARG is a list (selected by \\[universal-argument]), go downward one level. +If ARG is negative, go up that many levels. +If ARG is positive or zero, use absolute level: + + 0 : part + 1 : chapter + 2 : section + 3 : subsection + 4 : subsubsection + 5 : paragraph + 6 : subparagraph + +The following variables can be set to customize: + +`LaTeX-section-hook' Hooks to run when inserting a section. +`LaTeX-section-label' Prefix to all section labels." + + (interactive "*P") + (let* ((val (prefix-numeric-value arg)) + (LaTeX-level (cond ((null arg) + (LaTeX-current-section)) + ((listp arg) + (LaTeX-down-section)) + ((< val 0) + (LaTeX-up-section (- val))) + (t val))) + (LaTeX-name (LaTeX-section-name LaTeX-level)) + (LaTeX-toc nil) + (LaTeX-title (if (TeX-active-mark) + (buffer-substring (region-beginning) + (region-end)) + "")) + (LaTeX-done-mark (make-marker))) + (run-hooks 'LaTeX-section-hook) + (LaTeX-newline) + (if (marker-position LaTeX-done-mark) + (goto-char (marker-position LaTeX-done-mark))) + (set-marker LaTeX-done-mark nil))) + +(defun LaTeX-current-section () + "Return the level of the section that contain point. +See also `LaTeX-section' for description of levels." + (save-excursion + (max (LaTeX-largest-level) + (if (re-search-backward (LaTeX-outline-regexp) nil t) + (- (LaTeX-outline-level) (LaTeX-outline-offset)) + (LaTeX-largest-level))))) + +(defun LaTeX-down-section () + "Return the value of a section one level under the current. +Tries to find what kind of section that have been used earlier in the +text, if this fail, it will just return one less than the current +section." + (save-excursion + (let ((current (LaTeX-current-section)) + (next nil) + (regexp (LaTeX-outline-regexp))) + (if (not (re-search-backward regexp nil t)) + (1+ current) + (while (not next) + (cond + ((eq (LaTeX-current-section) current) + (if (re-search-forward regexp nil t) + (if (<= (setq next (LaTeX-current-section)) current) ;Wow! + (setq next (1+ current))) + (setq next (1+ current)))) + ((not (re-search-backward regexp nil t)) + (setq next (1+ current))))) + next)))) + +(defun LaTeX-up-section (arg) + "Return the value of the section ARG levels above this one." + (save-excursion + (if (zerop arg) + (LaTeX-current-section) + (let ((current (LaTeX-current-section))) + (while (and (>= (LaTeX-current-section) current) + (re-search-backward (LaTeX-outline-regexp) + nil t))) + (LaTeX-up-section (1- arg)))))) + +(defvar LaTeX-section-list '(("part" 0) + ("chapter" 1) + ("section" 2) + ("subsection" 3) + ("subsubsection" 4) + ("paragraph" 5) + ("subparagraph" 6)) + "List which elements is the names of the sections used by LaTeX.") + +(defvar LaTeX-section-menu nil) +(make-variable-buffer-local 'LaTeX-section-menu) + +(defun LaTeX-section-list-add-locally (sections &optional clean) + "Add SECTIONS to `LaTeX-section-list'. +SECTIONS can be a single list containing the section macro name +as a string and the level as an integer or a list of such lists. + +If optional argument CLEAN is non-nil, remove any existing +entries from `LaTeX-section-list' before adding the new ones. + +The function will make `LaTeX-section-list' buffer-local and +invalidate the section submenu in order to let the menu filter +regenerate it. It is mainly a convenience function which can be +used in style files." + (when (stringp (car sections)) + (setq sections (list sections))) + (make-local-variable 'LaTeX-section-list) + (when clean (setq LaTeX-section-list nil)) + (dolist (elt sections) (add-to-list 'LaTeX-section-list elt t)) + (setq LaTeX-section-list + (sort (copy-sequence LaTeX-section-list) + (lambda (a b) (< (nth 1 a) (nth 1 b))))) + (setq LaTeX-section-menu nil)) + +(defun LaTeX-section-name (level) + "Return the name of the section corresponding to LEVEL." + (let ((entry (TeX-member level LaTeX-section-list + (lambda (a b) (equal a (nth 1 b)))))) + (if entry + (nth 0 entry) + nil))) + +(defun LaTeX-section-level (name) + "Return the level of the section NAME." + (let ((entry (TeX-member name LaTeX-section-list + (lambda (a b) (equal a (nth 0 b)))))) + + (if entry + (nth 1 entry) + nil))) + +(defcustom TeX-outline-extra nil + "List of extra TeX outline levels. + +Each element is a list with two entries. The first entry is the +regular expression matching a header, and the second is the level of +the header. See `LaTeX-section-list' for existing header levels." + :group 'LaTeX + :type '(repeat (group (regexp :tag "Match") + (integer :tag "Level")))) + +(defun LaTeX-outline-regexp (&optional anywhere) + "Return regexp for LaTeX sections. + +If optional argument ANYWHERE is not nil, do not require that the +header is at the start of a line." + (concat (if anywhere "" "^") + "[ \t]*" + (regexp-quote TeX-esc) + "\\(appendix\\|documentstyle\\|documentclass\\|" + (mapconcat #'car LaTeX-section-list "\\|") + "\\)\\b" + (if TeX-outline-extra + "\\|" + "") + (mapconcat #'car TeX-outline-extra "\\|") + "\\|" TeX-header-end + "\\|" TeX-trailer-start)) + +(defvar LaTeX-largest-level nil + "Largest sectioning level with current document class.") + +(make-variable-buffer-local 'LaTeX-largest-level) + +(defun LaTeX-largest-level () + "Return largest sectioning level with current document class. +Run style hooks before it has not been done." + (TeX-update-style) + LaTeX-largest-level) + +(defun LaTeX-largest-level-set (section) + "Set `LaTeX-largest-level' to the level of SECTION. +SECTION has to be a string contained in `LaTeX-section-list'. +Additionally the function will invalidate the section submenu in +order to let the menu filter regenerate it." + (setq LaTeX-largest-level (LaTeX-section-level section)) + (let ((offset (LaTeX-outline-offset))) + (when (> offset 0) + (let (lst) + (dolist (tup outline-heading-alist) + (setq lst (cons (cons (car tup) + (+ offset (cdr tup))) + lst))) + (setq outline-heading-alist (nreverse lst))))) + (setq LaTeX-section-menu nil)) + +(defun LaTeX-outline-offset () + "Offset to add to `LaTeX-section-list' levels to get outline level." + (- 2 (LaTeX-largest-level))) + +(defun TeX-look-at (list) + "Check if we are looking at the first element of a member of LIST. +If so, return the second element, otherwise return nil." + (while (and list + (not (looking-at (nth 0 (car list))))) + (setq list (cdr list))) + (if list + (nth 1 (car list)) + nil)) + +(defvar LaTeX-header-end + (concat "^[^%\n]*" (regexp-quote TeX-esc) "begin *" + TeX-grop "document" TeX-grcl) + "Default end of header marker for LaTeX documents.") + +(defvar LaTeX-trailer-start + (concat "^[^%\n]*" (regexp-quote TeX-esc) "end *" + TeX-grop "document" TeX-grcl) + "Default start of trailer marker for LaTeX documents.") + +(defun LaTeX-outline-level () + "Find the level of current outline heading in an LaTeX document." + (cond ((looking-at LaTeX-header-end) 1) + ((looking-at LaTeX-trailer-start) 1) + ((TeX-look-at TeX-outline-extra) + (max 1 (+ (TeX-look-at TeX-outline-extra) + (LaTeX-outline-offset)))) + (t + (save-excursion + (skip-chars-forward " \t") + (forward-char 1) + (cond ((looking-at "appendix") 1) + ((looking-at "documentstyle") 1) + ((looking-at "documentclass") 1) + ((TeX-look-at LaTeX-section-list) + (max 1 (+ (TeX-look-at LaTeX-section-list) + (LaTeX-outline-offset)))) + (t (outline-level))))))) + +(defun LaTeX-outline-name () + "Guess a name for the current header line." + (save-excursion + (if (re-search-forward "{\\([^\}]*\\)}" (+ (point) fill-column 10) t) + (match-string 1) + (buffer-substring (point) (min (point-max) (+ 20 (point))))))) + +(add-hook 'TeX-remove-style-hook + (lambda () (setq LaTeX-largest-level nil))) + +(defcustom LaTeX-section-hook + '(LaTeX-section-heading + LaTeX-section-title + ;; LaTeX-section-toc ; Most people won't want this + LaTeX-section-section + LaTeX-section-label) + "List of hooks to run when a new section is inserted. + +The following variables are set before the hooks are run + +LaTeX-level - numeric section level, see the documentation of `LaTeX-section'. +LaTeX-name - name of the sectioning command, derived from `LaTeX-level'. +LaTeX-title - The title of the section, default to an empty string. +LaTeX-toc - Entry for the table of contents list, default nil. +LaTeX-done-mark - Position of point afterwards, default nil (meaning end). + +The following standard hooks exist - + +LaTeX-section-heading: Query the user about the name of the +sectioning command. Modifies `LaTeX-level' and `LaTeX-name'. + +LaTeX-section-title: Query the user about the title of the +section. Modifies `LaTeX-title'. + +LaTeX-section-toc: Query the user for the toc entry. Modifies +`LaTeX-toc'. + +LaTeX-section-section: Insert LaTeX section command according to +`LaTeX-name', `LaTeX-title', and `LaTeX-toc'. If `LaTeX-toc' is +nil, no toc entry is inserted. If `LaTeX-toc' or `LaTeX-title' +are empty strings, `LaTeX-done-mark' will be placed at the point +they should be inserted. + +LaTeX-section-label: Insert a label after the section command. +Controled by the variable `LaTeX-section-label'. + +To get a full featured `LaTeX-section' command, insert + + (setq LaTeX-section-hook + \\='(LaTeX-section-heading + LaTeX-section-title + LaTeX-section-toc + LaTeX-section-section + LaTeX-section-label)) + +in your init file such as .emacs.d/init.el or .emacs." + :group 'LaTeX-macro + :type 'hook + :options '(LaTeX-section-heading + LaTeX-section-title + LaTeX-section-toc + LaTeX-section-section + LaTeX-section-label)) + + +(defcustom LaTeX-section-label + '(("part" . "part:") + ("chapter" . "chap:") + ("section" . "sec:") + ("subsection" . "sec:") + ("subsubsection" . "sec:")) + "Default prefix when asking for a label. + +Some LaTeX packages \(such as `fancyref'\) look at the prefix to generate some +text around cross-references automatically. When using those packages, you +should not change this variable. + +If it is a string, it it used unchanged for all kinds of sections. +If it is nil, no label is inserted. +If it is a list, the list is searched for a member whose car is equal +to the name of the sectioning command being inserted. The cdr is then +used as the prefix. If the name is not found, or if the cdr is nil, +no label is inserted." + :group 'LaTeX-label + :type '(choice (const :tag "none" nil) + (string :format "%v" :tag "Common") + (repeat :menu-tag "Level specific" + :format "\n%v%i" + (cons :format "%v" + (string :tag "Type") + (choice :tag "Prefix" + (const :tag "none" nil) + (string :format "%v")))))) + +;;; Section Hooks. + +(defun LaTeX-section-heading () + "Hook to prompt for LaTeX section name. +Insert this hook into `LaTeX-section-hook' to allow the user to change +the name of the sectioning command inserted with \\[LaTeX-section]." + (let ((string (completing-read + (concat "Level (default " LaTeX-name "): ") + LaTeX-section-list + nil nil nil nil LaTeX-name))) + ;; Update LaTeX-name + (if (not (zerop (length string))) + (setq LaTeX-name string)) + ;; Update level + (setq LaTeX-level (LaTeX-section-level LaTeX-name)))) + +(defun LaTeX-section-title () + "Hook to prompt for LaTeX section title. +Insert this hook into `LaTeX-section-hook' to allow the user to change +the title of the section inserted with \\[LaTeX-section]." + (setq LaTeX-title (TeX-read-string "Title: " LaTeX-title)) + (let ((region (and (TeX-active-mark) + (cons (region-beginning) (region-end))))) + (when region (delete-region (car region) (cdr region))))) + +(defun LaTeX-section-toc () + "Hook to prompt for the LaTeX section entry in the table of contents. +Insert this hook into `LaTeX-section-hook' to allow the user to insert +a different entry for the section in the table of contents." + (setq LaTeX-toc (TeX-read-string "Toc Entry: ")) + (if (zerop (length LaTeX-toc)) + (setq LaTeX-toc nil))) + +(defun LaTeX-section-section () + "Hook to insert LaTeX section command into the file. +Insert this hook into `LaTeX-section-hook' after those hooks that +set the `LaTeX-name', `LaTeX-title', and `LaTeX-toc' variables, +but before those hooks that assume that the section is already +inserted." + ;; insert a new line if the current line and the previous line are + ;; not empty (except for whitespace), with one exception: do not + ;; insert a new line if the previous (or current, sigh) line starts + ;; an environment (i.e., starts with `[optional whitespace]\begin') + (unless (save-excursion + (re-search-backward + (concat "^\\s-*\n\\s-*\\=\\|^\\s-*" (regexp-quote TeX-esc) + "begin") + (line-beginning-position 0) t)) + (LaTeX-newline)) + (insert TeX-esc LaTeX-name) + (cond ((null LaTeX-toc)) + ((zerop (length LaTeX-toc)) + (insert LaTeX-optop) + (set-marker LaTeX-done-mark (point)) + (insert LaTeX-optcl)) + (t + (insert LaTeX-optop LaTeX-toc LaTeX-optcl))) + (insert TeX-grop) + (if (zerop (length LaTeX-title)) + (set-marker LaTeX-done-mark (point))) + (insert LaTeX-title TeX-grcl) + (LaTeX-newline) + ;; If RefTeX is available, tell it that we've just made a new section + (and (fboundp 'reftex-notice-new-section) + (reftex-notice-new-section))) + +(defun LaTeX-section-label () + "Hook to insert a label after the sectioning command. +Insert this hook into `LaTeX-section-hook' to prompt for a label to be +inserted after the sectioning command. + +The behaviour of this hook is controlled by variable `LaTeX-section-label'." + (and (LaTeX-label LaTeX-name 'section) + (LaTeX-newline))) + +;;; Environments + +(defgroup LaTeX-environment nil + "Environments in AUCTeX." + :group 'LaTeX-macro) + +(defcustom LaTeX-default-environment "itemize" + "The default environment when creating new ones with `LaTeX-environment'. +It is overridden by `LaTeX-default-document-environment' when it +is non-nil and the current environment is \"document\"." + :group 'LaTeX-environment + :type 'string) +(make-variable-buffer-local 'LaTeX-default-environment) + +(defvar LaTeX-default-document-environment nil + "The default environment when creating new ones with +`LaTeX-environment' and the current one is \"document\". This +variable overrides `LaTeX-default-environment'.") +(make-variable-buffer-local 'LaTeX-default-document-environment) + +(defvar LaTeX-default-tabular-environment "tabular" + "The default tabular-like environment used when inserting a table env. +Styles such as tabularx may set it according to their needs.") +(make-variable-buffer-local 'LaTeX-default-tabular-environment) + +(defvar LaTeX-environment-history nil) + +;; Variable used to cache the current environment, e.g. for repeated +;; tasks in an environment, like indenting each line in a paragraph to +;; be filled. It must not have a non-nil value in general. That +;; means it is usually let-bound for such operations. +(defvar LaTeX-current-environment nil) + +(defun LaTeX-environment (arg) + "Make LaTeX environment (\\begin{...}-\\end{...} pair). +With optional ARG, modify current environment. + +It may be customized with the following variables: + +`LaTeX-default-environment' Your favorite environment. +`LaTeX-default-style' Your favorite document class. +`LaTeX-default-options' Your favorite document class options. +`LaTeX-float' Where you want figures and tables to float. +`LaTeX-table-label' Your prefix to labels in tables. +`LaTeX-figure-label' Your prefix to labels in figures. +`LaTeX-default-format' Format for array and tabular. +`LaTeX-default-width' Width for minipage and tabular*. +`LaTeX-default-position' Position for array and tabular." + + (interactive "*P") + (let* ((default (cond + ((TeX-near-bobp) "document") + ((and LaTeX-default-document-environment + (string-equal (LaTeX-current-environment) "document")) + LaTeX-default-document-environment) + (t LaTeX-default-environment))) + (environment (completing-read (concat "Environment type (default " + default "): ") + (LaTeX-environment-list-filtered) nil nil + nil 'LaTeX-environment-history default))) + ;; Use `environment' as default for the next time only if it is different + ;; from the current default. + (unless (equal environment default) + (setq LaTeX-default-environment environment)) + + (let ((entry (assoc environment (LaTeX-environment-list)))) + (if (null entry) + (LaTeX-add-environments (list environment))) + + (if arg + (LaTeX-modify-environment environment) + (LaTeX-environment-menu environment))))) + +(defun LaTeX-environment-menu (environment) + "Insert ENVIRONMENT around point or region." + (let ((entry (assoc environment (LaTeX-environment-list)))) + (cond ((not (and entry (nth 1 entry))) + (LaTeX-insert-environment environment)) + ((numberp (nth 1 entry)) + (let ((count (nth 1 entry)) + (args "")) + (while (> count 0) + (setq args (concat args TeX-grop TeX-grcl)) + (setq count (- count 1))) + (LaTeX-insert-environment environment args))) + ((or (stringp (nth 1 entry)) (vectorp (nth 1 entry))) + (let ((prompts (cdr entry)) + (args "")) + (dolist (elt prompts) + (let* ((optional (vectorp elt)) + (elt (if optional (elt elt 0) elt)) + (arg (TeX-read-string (concat (when optional "(Optional) ") + elt ": ")))) + (setq args (concat args + (cond ((and optional (> (length arg) 0)) + (concat LaTeX-optop arg LaTeX-optcl)) + ((not optional) + (concat TeX-grop arg TeX-grcl))))))) + (LaTeX-insert-environment environment args))) + (t + (apply (nth 1 entry) environment (nthcdr 2 entry)))))) + +(defun LaTeX-close-environment (&optional reopen) + "Create an \\end{...} to match the current environment. +With prefix-argument, reopen environment afterwards." + (interactive "*P") + (if (> (point) + (save-excursion + (beginning-of-line) + (when LaTeX-insert-into-comments + (if (looking-at comment-start-skip) + (goto-char (match-end 0)))) + (skip-chars-forward " \t") + (point))) + (LaTeX-newline)) + (let ((environment (LaTeX-current-environment 1)) marker) + (insert "\\end{" environment "}") + (indent-according-to-mode) + (if (or (not (looking-at "[ \t]*$")) + (and (TeX-in-commented-line) + (save-excursion (beginning-of-line 2) + (not (TeX-in-commented-line))))) + (LaTeX-newline) + (unless (= (forward-line 1) 0) + (insert "\n"))) + (indent-according-to-mode) + (when reopen + (save-excursion + (setq marker (point-marker)) + (set-marker-insertion-type marker t) + (LaTeX-environment-menu environment) + (delete-region (point) + (if (save-excursion (goto-char marker) + (bolp)) + (1- marker) + marker)) + (move-marker marker nil))))) + +(define-obsolete-variable-alias 'LaTeX-after-insert-env-hooks 'LaTeX-after-insert-env-hook "11.89") + +(defvar LaTeX-indent-environment-list) ;; Defined further below. + +(defvar LaTeX-after-insert-env-hook nil + "List of functions to be run at the end of `LaTeX-insert-environment'. +Each function is called with three arguments: the name of the +environment just inserted, the buffer position just before +\\begin and the position just before \\end.") + +(defun LaTeX-insert-environment (environment &optional extra) + "Insert LaTeX ENVIRONMENT with optional argument EXTRA." + (let ((active-mark (and (TeX-active-mark) (not (eq (mark) (point))))) + prefix content-start env-start env-end additional-indent) + (when (and active-mark (< (mark) (point))) (exchange-point-and-mark)) + ;; Compute the prefix. + (when (and LaTeX-insert-into-comments (TeX-in-commented-line)) + (save-excursion + (beginning-of-line) + (looking-at + (concat "^\\([ \t]*" TeX-comment-start-regexp "+\\)+[ \t]*")) + (setq prefix (match-string 0)))) + ;; What to do with the line containing point. + ;; - Open a new empty line for later insertion of "\begin{foo}" and + ;; put the point there. + ;; - If there were at first any non-whitespace texts between the + ;; point and EOL, send them into their new own line with possible + ;; comment prefix. + (cond (;; When the entire line consists of whitespaces except + ;; possible prefix... + (save-excursion (beginning-of-line) + (looking-at (concat prefix "[ \t]*$"))) + ;; ...make the line empty and put the point there. + (delete-region (match-beginning 0) (match-end 0))) + (;; When there are only whitespaces except possible prefix + ;; between the point and BOL (including the case the point + ;; is at BOL)... + (TeX-looking-at-backward (if prefix + (concat "^\\(" prefix "\\)?[ \t]*") + "^[ \t]*") + (line-beginning-position)) + ;; ...in this case, we have non-whitespace texts between + ;; the point and EOL, so send the entire line into a new + ;; next line and put the point on the empty line just + ;; created. + (beginning-of-line) + (newline) + (beginning-of-line 0) + ;; Take note that there are texts to be indented later + ;; unless the region is activated. + (unless active-mark + (setq additional-indent t))) + (;; In all other cases... + t + ;; ...insert a new empty line after deleting all + ;; whitespaces around the point, put the point there... + (delete-horizontal-space) + (if (eolp) + (newline) + ;; ...and if there were at first any non-whitespace texts + ;; between (the original position of) the point and EOL, + ;; send them into a new next line with possible comment + ;; prefix. + (newline 2) + (when prefix (insert prefix)) + (beginning-of-line 0) + ;; Take note that there are texts to be indented later + ;; unless the region is activated. + (unless active-mark + (setq additional-indent t))))) + ;; What to do with the line containing mark. + ;; If there is active region... + (when active-mark + ;; - Open a new empty line for later insertion of "\end{foo}" + ;; and put the mark there. + ;; - If there were at first any non-whitespace texts between the + ;; mark and EOL, pass them over the empty line and put them on + ;; their own line with possible comment prefix. + (save-excursion + (goto-char (mark)) + (cond (;; When the entire line consists of whitespaces except + ;; possible prefix... + (save-excursion (beginning-of-line) + (looking-at + (if prefix + (concat "\\(" prefix "\\)?[ \t]*$") + "[ \t]*$"))) + ;; ...make the line empty and put the mark there. + (delete-region (match-beginning 0) (match-end 0))) + (;; When there are only whitespaces except possible prefix + ;; between the mark and BOL (including the case the mark + ;; is at BOL)... + (TeX-looking-at-backward (if prefix + (concat "^\\(" prefix "\\)?[ \t]*") + "^[ \t]*") + (line-beginning-position)) + ;; ...in this case, we have non-whitespace texts + ;; between the mark and EOL, so send the entire line + ;; into a new next line and put the mark on the empty + ;; line just created. + (beginning-of-line) + (set-mark (point)) + (newline) + ;; Take note that there are texts to be indented later. + (setq additional-indent t)) + (;; In all other cases... + t + ;; ...make a new empty line after deleting all + ;; whitespaces around the mark, put the mark there... + (delete-horizontal-space) + (insert-before-markers "\n") + ;; ...and if there were at first any non-whitespace + ;; texts between (the original position of) the mark + ;; and EOL, send them into a new next line with + ;; possible comment prefix. + (unless (eolp) + (newline) + (when prefix (insert prefix)) + ;; Take note that there are texts to be indented + ;; later. + (setq additional-indent t)))))) + ;; Now insert the environment. + (when prefix (insert prefix)) + (setq env-start (point)) + (insert TeX-esc "begin" TeX-grop environment TeX-grcl) + (indent-according-to-mode) + (when extra (insert extra)) + (setq content-start (line-beginning-position 2)) + (unless active-mark + (newline) + (when prefix (insert prefix)) + (newline)) + (when active-mark (goto-char (mark))) + (when prefix (insert prefix)) + (insert TeX-esc "end" TeX-grop environment TeX-grcl) + (end-of-line 0) + (if active-mark + (progn + (or (assoc environment LaTeX-indent-environment-list) + (if auto-fill-function + ;; Fill the region only when `auto-fill-mode' is active. + (LaTeX-fill-region content-start (line-beginning-position 2)) + ;; Else just indent the region. (bug#48518) + (indent-region content-start (line-beginning-position 2)))) + (set-mark content-start)) + (indent-according-to-mode)) + ;; Indent \end{foo}. + (save-excursion (beginning-of-line 2) (indent-according-to-mode) + (when additional-indent + ;; Indent texts sent after the inserted + ;; environment. + (forward-line 1) (indent-according-to-mode))) + (TeX-math-input-method-off) + (setq env-end (save-excursion + (search-forward + (concat TeX-esc "end" TeX-grop + environment TeX-grcl)) + (match-beginning 0))) + (run-hook-with-args 'LaTeX-after-insert-env-hook + environment env-start env-end))) + +(defun LaTeX-environment-name-regexp () + "Return the regexp matching the name of a LaTeX environment. +This matches everything different from a TeX closing brace but +allowing one level of TeX group braces." + (concat "\\([^" (regexp-quote TeX-grcl) (regexp-quote TeX-grop) "]*\\(" + (regexp-quote TeX-grop) "[^" (regexp-quote TeX-grcl) + (regexp-quote TeX-grop) "]*" (regexp-quote TeX-grcl) "\\)*[^" + (regexp-quote TeX-grcl) (regexp-quote TeX-grop) "]*\\)")) + +(defvar LaTeX-after-modify-env-hook nil + "List of functions to be run at the end of `LaTeX-modify-environment'. +Each function is called with four arguments: the new name of the +environment, the former name of the environment, the buffer +position just before \\begin and the position just before +\\end.") + +(defun LaTeX-modify-environment (environment) + "Modify current ENVIRONMENT." + (let ((goto-end (lambda () + (LaTeX-find-matching-end) + (re-search-backward (concat (regexp-quote TeX-esc) + "end" + (regexp-quote TeX-grop) + "\\(" + (LaTeX-environment-name-regexp) + "\\)" + (regexp-quote TeX-grcl)) + (save-excursion (beginning-of-line 1) (point))))) + (goto-begin (lambda () + (LaTeX-find-matching-begin) + (prog1 (point) + (re-search-forward (concat (regexp-quote TeX-esc) + "begin" + (regexp-quote TeX-grop) + "\\(" + (LaTeX-environment-name-regexp) + "\\)" + (regexp-quote TeX-grcl)) + (save-excursion (end-of-line 1) (point))))))) + (save-excursion + (funcall goto-end) + (let ((old-env (match-string 1))) + (replace-match environment t t nil 1) + (beginning-of-line 1) + (funcall goto-begin) + (replace-match environment t t nil 1) + (end-of-line 1) + (run-hook-with-args 'LaTeX-after-modify-env-hook + environment old-env + (save-excursion (funcall goto-begin)) + (progn (funcall goto-end) (point))))))) + +(defvar LaTeX-syntactic-comments) ;; Defined further below. + +(defun LaTeX-current-environment (&optional arg) + "Return the name (a string) of the enclosing LaTeX environment. +With optional ARG>=1, find that outer level. + +If function is called inside a comment and +`LaTeX-syntactic-comments' is enabled, try to find the +environment in commented regions with the same comment prefix. + +The functions `LaTeX-find-matching-begin' and `LaTeX-find-matching-end' +work analogously." + (setq arg (if arg (if (< arg 1) 1 arg) 1)) + (let* ((in-comment (TeX-in-commented-line)) + (comment-prefix (and in-comment (TeX-comment-prefix))) + (case-fold-search nil)) + (save-excursion + (while (and (/= arg 0) + (re-search-backward + "\\\\\\(begin\\|end\\) *{\\([^}]+\\)}" nil t)) + (when (or (and LaTeX-syntactic-comments + (eq in-comment (TeX-in-commented-line)) + (or (not in-comment) + ;; Consider only matching prefixes in the + ;; commented case. + (string= comment-prefix (TeX-comment-prefix)))) + (and (not LaTeX-syntactic-comments) + (not (TeX-in-commented-line))) + ;; macrocode*? in docTeX-mode is special since we + ;; have also regular code lines not starting with a + ;; comment-prefix. Hence, the next check just looks + ;; if we're inside such a group and returns t to + ;; recognize such a situation. + (and (eq major-mode 'doctex-mode) + (member (match-string-no-properties 2) + '("macrocode" "macrocode*")))) + (setq arg (if (string= (match-string 1) "end") (1+ arg) (1- arg))))) + (if (/= arg 0) + "document" + (match-string-no-properties 2))))) + +(defun docTeX-in-macrocode-p () + "Determine if point is inside a macrocode environment." + (let ((case-fold-search nil)) + (save-excursion + (re-search-backward + (concat "^% " (regexp-quote TeX-esc) + "\\(begin\\|end\\)[ \t]*{macrocode\\*?}") nil 'move) + (not (or (bobp) + (= (char-after (match-beginning 1)) ?e)))))) + + +;;; Environment Hooks + +(defvar LaTeX-document-style-hook nil + "List of hooks to run when inserting a document environment. + +To insert a hook here, you must insert it in the appropriate style file.") + +(defun LaTeX-env-document (&optional _ignore) + "Create new LaTeX document. +Also inserts a \\documentclass macro if there's none already and +prompts for the insertion of \\usepackage macros. + +The compatibility argument IGNORE is ignored." + ;; just assume a single valid \\documentclass, i.e., one not in a + ;; commented line + (let ((found nil)) + (save-excursion + (while (and (not found) + (re-search-backward + "\\\\documentclass\\(\\[[^]\n\r]*\\]\\)?\\({[^}]+}\\)" + nil t)) + (and (not (TeX-in-commented-line)) + (setq found t)))) + (when (not found) + (TeX-insert-macro "documentclass") + (LaTeX-newline) + (LaTeX-newline) + ;; Add a newline only if some `\usepackage' has been inserted. + (if (LaTeX-insert-usepackages) + (LaTeX-newline)) + (LaTeX-newline) + (end-of-line 0))) + (LaTeX-insert-environment "document") + (run-hooks 'LaTeX-document-style-hook) + (setq LaTeX-document-style-hook nil)) + +(defcustom LaTeX-float "" + "Default float position for figures and tables. +If nil, act like the empty string is given, but do not prompt. +\(The standard LaTeX classes use [tbp] as float position if the +optional argument is omitted.)" + :group 'LaTeX-environment + :type '(choice (const :tag "Do not prompt" nil) + (const :tag "Empty" "") + (string :format "%v"))) +(make-variable-buffer-local 'LaTeX-float) + +(defcustom LaTeX-top-caption-list nil + "List of float environments with top caption." + :group 'LaTeX-environment + :type '(repeat (string :format "%v"))) + +(defgroup LaTeX-label nil + "Adding labels for LaTeX commands in AUCTeX." + :group 'LaTeX) + +(defcustom LaTeX-label-function #'LaTeX-label--default + "A function inserting a label at point or returning a label string. +Called with two argument NAME and NO-INSERT where NAME is the environment. +The function has to return the label inserted, or nil if no label was +inserted. If the optional argument NO-INSERT is non-nil, then +the function has to return the label as string without any +insertion or nil if no label was read in." + :group 'LaTeX-label + :type 'function) + +(defcustom LaTeX-figure-label "fig:" + "Default prefix to figure labels." + :group 'LaTeX-label + :group 'LaTeX-environment + :type 'string) + +(defcustom LaTeX-table-label "tab:" + "Default prefix to table labels." + :group 'LaTeX-label + :group 'LaTeX-environment + :type 'string) + +(defcustom LaTeX-listing-label "lst:" + "Default prefix to listing labels. +This prefix should apply to all environments which typeset +code listings and take a caption and label." + :group 'LaTeX-label + :group 'LaTeX-environment + :type 'string) + +(defcustom LaTeX-default-format "" + "Default format for array and tabular environments." + :group 'LaTeX-environment + :type 'string) +(make-variable-buffer-local 'LaTeX-default-format) + +(defcustom LaTeX-default-width "1.0\\linewidth" + "Default width for minipage and tabular* environments." + :group 'LaTeX-environment + :type 'string) +(make-variable-buffer-local 'LaTeX-default-width) + +(defcustom LaTeX-default-position "" + "Default position for array and tabular environments. +If nil, act like the empty string is given, but do not prompt." + :group 'LaTeX-environment + :type '(choice (const :tag "Do not prompt" nil) + (const :tag "Empty" "") + string)) +(make-variable-buffer-local 'LaTeX-default-position) + +(defcustom LaTeX-equation-label "eq:" + "Default prefix to equation labels." + :group 'LaTeX-label + :type 'string) + +(defcustom LaTeX-eqnarray-label LaTeX-equation-label + "Default prefix to eqnarray labels." + :group 'LaTeX-label + :type 'string) + +(defun LaTeX-env-item (environment) + "Insert ENVIRONMENT and the first item." + (LaTeX-insert-environment environment) + (if (TeX-active-mark) + (progn + (LaTeX-find-matching-begin) + (end-of-line 1)) + (end-of-line 0)) + (delete-char 1) + (when (looking-at (concat "^[ \t]+$\\|" + "^[ \t]*" TeX-comment-start-regexp "+[ \t]*$")) + (delete-region (point) (line-end-position))) + (delete-horizontal-space) + ;; Deactivate the mark here in order to prevent `TeX-parse-macro' + ;; from swapping point and mark and the \item ending up right after + ;; \begin{...}. + (deactivate-mark) + (LaTeX-insert-item) + ;; The inserted \item may have outdented the first line to the + ;; right. Fill it, if appropriate and `auto-fill-mode' is active. + (when (and auto-fill-function + (not (looking-at "$")) + (not (assoc environment LaTeX-indent-environment-list)) + (> (- (line-end-position) (line-beginning-position)) + (current-fill-column))) + (LaTeX-fill-paragraph nil))) + +(defcustom LaTeX-label-alist + '(("figure" . LaTeX-figure-label) + ("table" . LaTeX-table-label) + ("figure*" . LaTeX-figure-label) + ("table*" . LaTeX-table-label) + ("equation" . LaTeX-equation-label) + ("eqnarray" . LaTeX-eqnarray-label)) + "Lookup prefixes for labels. +An alist where the CAR is the environment name, and the CDR +either the prefix or a symbol referring to one. + +If the name is not found, or if the CDR is nil, no label is +automatically inserted for that environment. + +If you want to automatically insert a label for a environment but +with an empty prefix, use the empty string \"\" as the CDR of the +corresponding entry." + :group 'LaTeX-label + :type '(repeat (cons (string :tag "Environment") + (choice (string :tag "Label prefix") + (symbol :tag "Label prefix symbol"))))) + +(make-variable-buffer-local 'LaTeX-label-alist) + +(defvar TeX-read-label-prefix nil + "Initial input for the label in `TeX-read-label'.") + +(defun LaTeX-label (name &optional type no-insert) + "Insert a label for NAME at point. +The optional TYPE argument can be either environment or section: +in the former case this function looks up `LaTeX-label-alist' to +choose which prefix to use for the label, in the latter case +`LaTeX-section-label' will be looked up instead. If TYPE is nil, +you will be always prompted for a label, with an empty default +prefix. + +If `LaTeX-label-function' is a valid function, LaTeX label will +transfer the job to this function. + +If the optional NO-INSERT is non-nil, only the label is returned +and no insertion happens. Otherwise the inserted label is +returned, nil if it is empty." + (let ((TeX-read-label-prefix + (cond + ((eq type 'environment) + (cdr (assoc name LaTeX-label-alist))) + ((eq type 'section) + (if (assoc name LaTeX-section-list) + (if (stringp LaTeX-section-label) + LaTeX-section-label + (and (listp LaTeX-section-label) + (cdr (assoc name LaTeX-section-label)))) + "")) + ((null type) + "") + (t + nil))) + ) ;; label + (when (symbolp TeX-read-label-prefix) + (setq TeX-read-label-prefix (symbol-value TeX-read-label-prefix))) + (when TeX-read-label-prefix + (funcall (or LaTeX-label-function #'LaTeX-label--default) + name no-insert)))) + +(defun LaTeX-label--default (_name no-insert) + ;; Use completing-read as we do with `C-c C-m \label RET' + (let ((label (TeX-read-label t "What label" t))) + ;; No label or empty string entered? + (if (or (string= TeX-read-label-prefix label) + (string= "" label)) + (setq label nil) + ;; We have a label; when NO-INSERT is nil, insert + ;; \label{label} in the buffer, add new label to list of + ;; known labels and return it + (unless no-insert + (insert TeX-esc "label" TeX-grop label TeX-grcl)) + (LaTeX-add-labels label) + label))) + +(defcustom LaTeX-short-caption-prompt-length 40 + "The length that the caption of a figure should be before +propting for \\caption's optional short-version." + :group 'LaTeX-environment + :type 'integer) + +(defun LaTeX-compose-caption-macro (caption &optional short-caption) + "Return a \\caption macro for a given CAPTION as a string. +If SHORT-CAPTION is non-nil pass it as an optional argument to +\\caption." + (let ((short-caption-string + (if (and short-caption + (not (string= short-caption ""))) + (concat LaTeX-optop short-caption LaTeX-optcl)))) + (concat TeX-esc "caption" short-caption-string + TeX-grop caption TeX-grcl))) + +(defun LaTeX-env-figure (environment) + "Create ENVIRONMENT with \\caption and \\label commands." + (let* ((float (and LaTeX-float ; LaTeX-float can be nil, i.e. + ; do not prompt + (TeX-read-string "(Optional) Float position: " LaTeX-float))) + (caption (TeX-read-string "Caption: ")) + (short-caption (when (>= (length caption) LaTeX-short-caption-prompt-length) + (TeX-read-string "(Optional) Short caption: "))) + (center (y-or-n-p "Center? ")) + (active-mark (and (TeX-active-mark) + (not (eq (mark) (point))))) + start-marker end-marker) + (when active-mark + (if (< (mark) (point)) + (exchange-point-and-mark)) + (setq start-marker (point-marker)) + (set-marker-insertion-type start-marker t) + (setq end-marker (copy-marker (mark)))) + (setq LaTeX-float float) + (LaTeX-insert-environment environment + (unless (zerop (length float)) + (concat LaTeX-optop float + LaTeX-optcl))) + (when active-mark + (goto-char start-marker) + (set-marker start-marker nil)) + (when center + (insert TeX-esc "centering") + (indent-according-to-mode) + (LaTeX-newline) + (indent-according-to-mode)) + ;; Insert caption and ask for a label, do nothing if user skips caption + (unless (zerop (length caption)) + (if (member environment LaTeX-top-caption-list) + ;; top caption + (progn + (insert (LaTeX-compose-caption-macro caption short-caption)) + ;; If `auto-fill-mode' is active, fill the caption. + (if auto-fill-function (LaTeX-fill-paragraph)) + (LaTeX-newline) + (indent-according-to-mode) + ;; ask for a label and insert a new line only if a label is + ;; actually inserted + (when (LaTeX-label environment 'environment) + (LaTeX-newline) + (indent-according-to-mode))) + ;; bottom caption (default) + (when active-mark (goto-char end-marker)) + (save-excursion + (LaTeX-newline) + (indent-according-to-mode) + ;; If there is an active region point is before the backslash of + ;; "\end" macro, go one line upwards. + (when active-mark (forward-line -1) (indent-according-to-mode)) + (insert (LaTeX-compose-caption-macro caption short-caption)) + ;; If `auto-fill-mode' is active, fill the caption. + (if auto-fill-function (LaTeX-fill-paragraph)) + ;; ask for a label and if necessary insert a new line between caption + ;; and label + (when (save-excursion (LaTeX-label environment 'environment)) + (LaTeX-newline) + (indent-according-to-mode))) + ;; Insert an empty line between caption and marked region, if any. + (when active-mark (LaTeX-newline) (forward-line -1)) + (indent-according-to-mode))) + (when (markerp end-marker) + (set-marker end-marker nil)) + (when (and (member environment '("table" "table*")) + ;; Suppose an existing tabular environment should just + ;; be wrapped into a table if there is an active region. + (not active-mark)) + (LaTeX-environment-menu LaTeX-default-tabular-environment)))) + +(defun LaTeX-env-array (environment) + "Insert ENVIRONMENT with position and column specifications. +Just like array and tabular." + (let ((pos (and LaTeX-default-position ; LaTeX-default-position can + ; be nil, i.e. do not prompt + (TeX-read-string "(Optional) Position: " LaTeX-default-position))) + (fmt (TeX-read-string + (if (string= LaTeX-default-format "") + "Format: " + (format "Format (default %s): " LaTeX-default-format)) + nil nil + (if (string= LaTeX-default-format "") + nil + LaTeX-default-format)))) + (setq LaTeX-default-position pos) + (setq LaTeX-default-format fmt) + (LaTeX-insert-environment environment + (concat + (unless (zerop (length pos)) + (concat LaTeX-optop pos LaTeX-optcl)) + (concat TeX-grop fmt TeX-grcl))) + (LaTeX-item-array t))) + +(defun LaTeX-env-label (environment) + "Insert ENVIRONMENT and prompt for label." + (LaTeX-insert-environment environment) + (when (TeX-active-mark) + ;; Point is at the end of the region. Move it back to the + ;; beginning of the region. + (exchange-point-and-mark) + (indent-according-to-mode)) + (when (LaTeX-label environment 'environment) + (LaTeX-newline) + (indent-according-to-mode)) + (when (TeX-active-mark) + (indent-region (point) (mark)) + ;; Restore the positions of point and mark. + (exchange-point-and-mark))) + +(defun LaTeX-env-list (environment) + "Insert ENVIRONMENT and the first item." + (let ((label (TeX-read-string "Default Label: "))) + (LaTeX-insert-environment environment + (format "{%s}{}" label)) + (end-of-line 0) + (delete-char 1) + (delete-horizontal-space)) + (LaTeX-insert-item)) + +(defun LaTeX-env-minipage (environment) + "Create new LaTeX minipage or minipage-like ENVIRONMENT." + (let* ((pos (and LaTeX-default-position ; LaTeX-default-position can + ; be nil, i.e. do not prompt + (completing-read + (TeX-argument-prompt t nil "Position") + '("t" "b" "c")))) + (height (when (and pos (not (string= pos ""))) + (completing-read (TeX-argument-prompt t nil "Height") + ;; A valid length can be a macro + ;; or a length of the form + ;; . Input + ;; starting with a `\' can be + ;; completed with length macros. + (mapcar (lambda (elt) + (concat TeX-esc (car elt))) + (LaTeX-length-list))))) + (inner-pos (when (and height (not (string= height ""))) + (completing-read + (TeX-argument-prompt t nil "Inner position") + '("t" "b" "c" "s")))) + (width (TeX-read-string + (TeX-argument-prompt nil nil (format "Width (default %s)" + LaTeX-default-width)) + nil nil LaTeX-default-width))) + (setq LaTeX-default-position pos) + (setq LaTeX-default-width width) + (LaTeX-insert-environment environment + (concat + (unless (zerop (length pos)) + (concat LaTeX-optop pos LaTeX-optcl)) + (unless (zerop (length height)) + (concat LaTeX-optop height LaTeX-optcl)) + (unless (zerop (length inner-pos)) + (concat LaTeX-optop inner-pos LaTeX-optcl)) + (concat TeX-grop width TeX-grcl))))) + +(defun LaTeX-env-tabular* (environment) + "Insert ENVIRONMENT with width, position and column specifications." + (let ((width (TeX-read-string + (format "Width (default %s): " LaTeX-default-width) + nil nil LaTeX-default-width)) + (pos (and LaTeX-default-position ; LaTeX-default-position can + ; be nil, i.e. do not prompt + (TeX-read-string "(Optional) Position: " LaTeX-default-position))) + (fmt (TeX-read-string + (if (string= LaTeX-default-format "") + "Format: " + (format "Format (default %s): " LaTeX-default-format)) + nil nil + (if (string= LaTeX-default-format "") + nil + LaTeX-default-format)))) + (setq LaTeX-default-width width) + (setq LaTeX-default-position pos) + (setq LaTeX-default-format fmt) + (LaTeX-insert-environment environment + (concat + (concat TeX-grop width TeX-grcl) ;; not optional! + (unless (zerop (length pos)) + (concat LaTeX-optop pos LaTeX-optcl)) + (concat TeX-grop fmt TeX-grcl))) + (LaTeX-item-tabular* t))) + +(defun LaTeX-env-picture (environment) + "Insert ENVIRONMENT with width, height specifications." + (let ((width (TeX-read-string "Width: ")) + (height (TeX-read-string "Height: ")) + (x-offset (TeX-read-string "X Offset: ")) + (y-offset (TeX-read-string "Y Offset: "))) + (if (zerop (length x-offset)) + (setq x-offset "0")) + (if (zerop (length y-offset)) + (setq y-offset "0")) + (LaTeX-insert-environment environment + (concat + (format "(%s,%s)" width height) + (if (not (and (string= x-offset "0") + (string= y-offset "0"))) + (format "(%s,%s)" x-offset y-offset)))))) + +(defun LaTeX-env-bib (environment) + "Insert ENVIRONMENT with label for bibitem." + (LaTeX-insert-environment environment + (concat TeX-grop + (TeX-read-string + (format "Label for BibItem (default %s): " "99") + nil nil "99") + TeX-grcl)) + (end-of-line 0) + (delete-char 1) + (delete-horizontal-space) + (LaTeX-insert-item)) + +(defun LaTeX-env-contents (environment) + "Insert ENVIRONMENT with optional argument and filename for contents." + (let* ((opt '("overwrite" "force" "nosearch")) + (arg (mapconcat #'identity + (TeX-completing-read-multiple + (TeX-argument-prompt t nil "Options") + (if (string= environment "filecontents*") + opt + (cons "noheader" opt))) + ","))) + (LaTeX-insert-environment environment + (concat + (when (and arg (not (string= arg ""))) + (concat LaTeX-optop arg LaTeX-optcl)) + TeX-grop + (TeX-read-string "File: ") + TeX-grcl))) + (delete-horizontal-space)) + +(defun LaTeX-env-args (environment &rest args) + "Insert ENVIRONMENT and arguments defined by ARGS." + (LaTeX-insert-environment environment) + (save-excursion + (LaTeX-find-matching-begin) + (end-of-line) + (let ((TeX-exit-mark (or TeX-exit-mark + (make-marker)))) + (TeX-parse-arguments args)))) + +(defun LaTeX-env-label-as-keyval (_optional &optional keyword keyvals environment) + "Query for a label and insert it in the optional argument of an environment. +OPTIONAL is ignored. Optional KEYWORD is a string to search for +in the optional argument, label is only included if KEYWORD is +found. KEYVALS is a string with key=val's read in. If nil, this +function searchs for key=val's itself. ENVIRONMENT is a string +with the name of environment, if non-nil, don't bother to find +out." + (let ((env-start (make-marker)) + (body-start (make-marker)) + (opt-start (make-marker)) + (opt-end (make-marker)) + (currenv (or environment (LaTeX-current-environment)))) + ;; Save the starting point as we will come back here + (set-marker body-start (point)) + ;; Go to the start of the current environment and save the position + (LaTeX-find-matching-begin) + (set-marker env-start (point)) + ;; Check if an opt. argument is there; assume that it starts in + ;; the same line and save the points in markers + (when (re-search-forward + (concat "\\\\begin{" currenv "}[ \t]*\\[") body-start t) + (set-marker opt-start (1- (point))) + (goto-char opt-start) + (forward-sexp) + (set-marker opt-end (1- (point)))) + ;; If keyword argument is given and keyvals argument is not given, + ;; parse the optional argument and put it into keyvals + (when (and keyword + (marker-position opt-start) + (not keyvals)) + (setq keyvals (buffer-substring-no-properties + (1+ opt-start) opt-end))) + ;; If keyword is given, only insert a label when keyword is found + ;; inside the keyvals. If keyword is nil, then insert a label + ;; anyways + (if (stringp keyword) + (when (and (stringp keyvals) + (not (string= keyvals "")) + (string-match (concat keyword "[ \t]*=") keyvals)) + (goto-char opt-end) + (let ((opt-label (LaTeX-label currenv 'environment t))) + (when opt-label + (insert (if (equal (preceding-char) ?,) + "label=" + ",label=") + TeX-grop opt-label TeX-grcl)))) + (let ((opt-label (LaTeX-label currenv 'environment t))) + (when opt-label + ;; Check if an opt. argument is found and go to the end if + (if (marker-position opt-end) + (progn + (goto-char opt-end) + (insert (if (equal (preceding-char) ?,) + "label=" + ",label=") + TeX-grop opt-label TeX-grcl)) + ;; Otherwise start at the beginning of environment in + ;; order to not mess with any other mandatory arguments + ;; which can be there + (goto-char env-start) + (re-search-forward (concat "\\\\begin{" currenv "}")) + (insert LaTeX-optop "label=" TeX-grop opt-label TeX-grcl LaTeX-optcl))))) + ;; Go to where we started and clean up the markers + (goto-char body-start) + (set-marker env-start nil) + (set-marker body-start nil) + (set-marker opt-start nil) + (set-marker opt-end nil))) + +;;; Item hooks + +(defvar LaTeX-item-list nil + "A list of environments where items have a special syntax. +The cdr is the name of the function, used to insert this kind of items.") + +(defun LaTeX-insert-item () + "Insert a new item in an environment. +You may use `LaTeX-item-list' to change the routines used to insert the item." + (interactive "*") + (let ((environment (LaTeX-current-environment))) + (when (and (TeX-active-mark) + (> (point) (mark))) + (exchange-point-and-mark)) + (unless (bolp) (LaTeX-newline)) + (if (assoc environment LaTeX-item-list) + (funcall (cdr (assoc environment LaTeX-item-list))) + (TeX-insert-macro "item")) + (indent-according-to-mode))) + +(defvar TeX-arg-item-label-p) ;; Defined further below. + +(defun LaTeX-item-argument () + "Insert a new item with an optional argument." + (let ((TeX-arg-item-label-p t) + (TeX-insert-macro-default-style 'show-optional-args)) + (TeX-insert-macro "item"))) + +(defun LaTeX-item-bib () + "Insert a new bibitem." + (TeX-insert-macro "bibitem")) + +(defvar LaTeX-array-skipping-regexp (regexp-opt '("[t]" "[b]" "")) + "Regexp matching between \\begin{xxx} and column specification. +For array and tabular environments. See `LaTeX-insert-ampersands' for +detail.") + +(defvar LaTeX-tabular*-skipping-regexp + ;; Assume width specification contains neither nested curly brace + ;; pair nor escaped "}". + (concat "{[^}]*}[ \t]*" (regexp-opt '("[t]" "[b]" ""))) + "Regexp matching between \\begin{tabular*} and column specification. +For tabular* environment only. See `LaTeX-insert-ampersands' for detail.") + +(defun LaTeX-item-array (&optional suppress) + "Insert line break macro on the last line and suitable number of &'s. +For array and tabular environments. + +If SUPPRESS is non-nil, do not insert line break macro." + (unless suppress + (save-excursion + (end-of-line 0) + (just-one-space) + (TeX-insert-macro "\\"))) + (LaTeX-insert-ampersands + LaTeX-array-skipping-regexp #'LaTeX-array-count-columns)) + +(defun LaTeX-item-tabular* (&optional suppress) + "Insert line break macro on the last line and suitable number of &'s. +For tabular* environment only. + +If SUPPRESS is non-nil, do not insert line break macro." + (unless suppress + (save-excursion + (end-of-line 0) + (just-one-space) + (TeX-insert-macro "\\"))) + (LaTeX-insert-ampersands + LaTeX-tabular*-skipping-regexp #'LaTeX-array-count-columns)) + +(defun LaTeX-insert-ampersands (regexp func) + "Insert suitable number of ampersands for the current environment. +The number is calculated from REGEXP and FUNC. + +Example 1: +Consider the case that the current environment begins with +\\begin{array}[t]{|lcr|} +. REGEXP must be chosen to match \"[t]\", that is, the text between just +after \"\\begin{array}\" and just before \"{|lcr|}\", which encloses +the column specification. FUNC must return the number of ampersands to +be inserted, which is 2 since this example specifies three columns. +FUNC is called with two arguments START and END, which spans the column +specification (without enclosing braces.) REGEXP is used to determine +these START and END. + +Example 2: +This time the environment begins with +\\begin{tabular*}{1.0\\linewidth}[b]{c@{,}p{5ex}} +. REGEXP must match \"{1.0\\linewidth}[b]\" and FUNC must return 1 from +the text \"c@{,}p{5ex}\" between START and END specified two columns. + +FUNC should return nil if it cannot determine the number of ampersands." + (let* ((cur (point)) + (num + (save-excursion + (ignore-errors + (LaTeX-find-matching-begin) + ;; Skip over "\begin{xxx}" and possible whitespaces. + (forward-list 1) + (skip-chars-forward " \t") + ;; Skip over the text specified by REGEXP and whitespaces. + (when (let ((case-fold-search nil)) + (re-search-forward regexp cur)) + (skip-chars-forward " \t") + (when (eq (following-char) ?{) + ;; We have reached the target "{yyy}" part. + (forward-char 1) + ;; The next line doesn't move point, so point + ;; is left just after the opening brace. + (let ((pos (TeX-find-closing-brace))) + (if pos + ;; Calculate number of ampersands to be inserted. + (funcall func (point) (1- pos)))))))))) + (if (natnump num) + (save-excursion (insert (make-string num ?&)))))) + +(defvar LaTeX-array-column-letters "clrp" + "Column letters for array-like environments. +See `LaTeX-array-count-columns' for detail.") + +(defun LaTeX-array-count-columns (start end) + "Count number of ampersands to be inserted. +The columns are specified by the letters found in the string +`LaTeX-array-column-letters' and the number of those letters within the +text between START and END is basically considered to be the number of +columns. The arguments surrounded between braces such as p{30pt} do not +interfere the count of columns. + +Return one less number than the columns, or nil on failing to count the +right number." + (save-excursion + (let (p (cols 0)) + (goto-char start) + (while (< (setq p (point)) end) + + ;; The below block accounts for one unit of move for + ;; one column. + (setq cols (+ cols + ;; treat *-operator specially. + (if (eq (following-char) ?*) + ;; *-operator is there. + (progn + ;; pick up repetition number and count + ;; how many columns are repeated. + (re-search-forward + "\\*[ \t\r\n%]*{[ \t\r\n%]*\\([0-9]+\\)[ \t\r\n%]*}" end) + (let ((n (string-to-number + (match-string-no-properties 1))) + ;; get start and end of repeated spec. + (s (progn (down-list 1) (point))) + (e (progn (up-list 1) (1- (point))))) + (* n (1+ (LaTeX-array-count-columns s e))))) + ;; not *-operator. + (skip-chars-forward + LaTeX-array-column-letters end)))) + ;; Do not skip over `*' (see above) and `[' (siunitx has `S[key=val]':): + (skip-chars-forward (concat + "^" LaTeX-array-column-letters "*" + TeX-grop LaTeX-optop) end) + (when (or (eq (following-char) ?\{) + (eq (following-char) ?\[)) + (forward-list 1)) + + ;; Not sure whether this is really necessary or not, but + ;; prepare for possible infinite loop anyway. + (when (eq p (point)) + (setq cols nil) + (goto-char end))) + ;; The number of ampersands is one less than column. + (if cols (1- cols))))) + +;;; Parser + +(defvar LaTeX-auto-style nil) +(defvar LaTeX-auto-arguments nil) +(defvar LaTeX-auto-optional nil) +(defvar LaTeX-auto-env-args nil) +(defvar LaTeX-auto-env-args-with-opt nil) + +(TeX-auto-add-type "label" "LaTeX") +(TeX-auto-add-type "bibitem" "LaTeX") +(TeX-auto-add-type "environment" "LaTeX") +(TeX-auto-add-type "bibliography" "LaTeX" "bibliographies") +(TeX-auto-add-type "index-entry" "LaTeX" "index-entries") +(TeX-auto-add-type "pagestyle" "LaTeX") +(TeX-auto-add-type "counter" "LaTeX") +(TeX-auto-add-type "length" "LaTeX") +(TeX-auto-add-type "savebox" "LaTeX" "saveboxes") + +(defvar LaTeX-auto-minimal-regexp-list + '(("\\\\document\\(style\\|class\\)\ +\\(\\[\\(\\([^#\\%]\\|%[^\n\r]*[\n\r]\\)*\\)\\]\\)?\ +{\\([^#\\.\n\r]+?\\)}" + (3 5 1) LaTeX-auto-style) + ("\\\\use\\(package\\)\\(\\[\\([^]]*\\)\\]\\)?\ +{\\(\\([^#}\\.%]\\|%[^\n\r]*[\n\r]\\)+?\\)}" + (3 4 1) LaTeX-auto-style)) + "Minimal list of regular expressions matching LaTeX macro definitions.") + +(defvar LaTeX-auto-label-regexp-list + '(("\\\\label{\\([^\n\r%\\{}]+\\)}" 1 LaTeX-auto-label)) + "List of regular expression matching LaTeX labels only.") + +(defvar LaTeX-auto-index-regexp-list + '(("\\\\\\(index\\|glossary\\){\\([^}{]*\\({[^}{]*\\({[^}{]*\\({[^}{]*}[^}{]*\\)*}[^}{]*\\)*}[^}{]*\\)*\\)}" + 2 LaTeX-auto-index-entry)) + "List of regular expression matching LaTeX index/glossary entries only. +Regexp allows for up to 3 levels of parenthesis inside the index argument. +This is necessary since index entries may contain commands and stuff.") + +(defvar LaTeX-auto-class-regexp-list + '(;; \RequirePackage[]{}[] + ("\\\\Require\\(Package\\)\\(\\[\\([^]]*\\)\\]\\)?\ +{\\([^#\\.\n\r]+?\\)}" + (3 4 1) LaTeX-auto-style) + ;; \RequirePackageWithOptions{}[], + ("\\\\Require\\(Package\\)WithOptions\\(\\){\\([^#\\.\n\r]+?\\)}" + (2 3 1) LaTeX-auto-style) + ;; \LoadClass[]{}[] + ("\\\\Load\\(Class\\)\\(\\[\\([^]]*\\)\\]\\)?{\\([^#\\.\n\r]+?\\)}" + (3 4 1) LaTeX-auto-style) + ;; \LoadClassWithOptions{}[] + ("\\\\Load\\(Class\\)WithOptions\\(\\){\\([^#\\.\n\r]+?\\)}" + (2 3 1) LaTeX-auto-style) + ;; \DeclareRobustCommand{}[][]{}, + ;; \DeclareRobustCommand*{}[][]{} + ("\\\\DeclareRobustCommand\\*?{?\\\\\\([A-Za-z]+\\)}?\ +\\[\\([0-9]+\\)\\]\\[\\([^\n\r]*?\\)\\]" + (1 2 3) LaTeX-auto-optional) + ("\\\\DeclareRobustCommand\\*?{?\\\\\\([A-Za-z]+\\)}?\\[\\([0-9]+\\)\\]" + (1 2) LaTeX-auto-arguments) + ("\\\\DeclareRobustCommand\\*?{?\\\\\\([A-Za-z]+\\)}?" + 1 TeX-auto-symbol) + ;; Patterns for commands described in "LaTeX2e font selection" (fntguide) + ("\\\\DeclareMath\\(?:Symbol\\|Delimiter\\|Accent\\|Radical\\)\ +{?\\\\\\([A-Za-z]+\\)}?" + 1 TeX-auto-symbol) + ("\\\\\\(Declare\\|Provide\\)Text\ +\\(?:Command\\|Symbol\\|Accent\\|Composite\\){?\\\\\\([A-Za-z]+\\)}?" + 1 TeX-auto-symbol) + ("\\\\Declare\\(?:Text\\|Old\\)FontCommand{?\\\\\\([A-Za-z]+\\)}?" + 1 TeX-auto-symbol)) + "List of regular expressions matching macros in LaTeX classes and packages.") + +(defvar LaTeX-auto-pagestyle-regexp-list + '(("\\\\ps@\\([A-Za-z]+\\)" 1 LaTeX-auto-pagestyle)) + "List of regular expressions matching LaTeX pagestyles only.") + +(defvar LaTeX-auto-counter-regexp-list + '(("\\\\newcounter *{\\([A-Za-z]+\\)}" 1 LaTeX-auto-counter) + ("\\\\@definecounter{\\([A-Za-z]+\\)}" 1 LaTeX-auto-counter)) + "List of regular expressions matching LaTeX counters only.") + +(defvar LaTeX-auto-length-regexp-list + '(("\\\\newlength *{?\\\\\\([A-Za-z]+\\)}?" 1 LaTeX-auto-length)) + "List of regular expressions matching LaTeX lengths only.") + +(defvar LaTeX-auto-savebox-regexp-list + '(("\\\\newsavebox *{?\\\\\\([A-Za-z]+\\)}?" 1 LaTeX-auto-savebox)) + "List of regular expressions matching LaTeX saveboxes only.") + +(defvar LaTeX-auto-regexp-list + (append + (let ((token TeX-token-char)) + `((,(concat "\\\\\\(re\\)?\\(?:new\\|provide\\)command\\*?" + "{?\\\\\\(" token "+\\)}?\\[\\([0-9]+\\)\\]\\[\\([^\n\r]*\\)\\]") + (2 3 4 1) LaTeX-auto-optional) + (,(concat "\\\\\\(re\\)?\\(?:new\\|provide\\)command\\*?" + "{?\\\\\\(" token "+\\)}?\\[\\([0-9]+\\)\\]") + (2 3 1) LaTeX-auto-arguments) + (,(concat "\\\\\\(?:new\\|provide\\)command\\*?{?\\\\\\(" token "+\\)}?") + 1 TeX-auto-symbol) + ("\\\\\\(re\\)?newenvironment\\*?{\\([^}]+\\)}\\[\\([0-9]+\\)\\]\\[" + (2 3 1) LaTeX-auto-env-args-with-opt) + ("\\\\\\(re\\)?newenvironment\\*?{\\([^}]+\\)}\\[\\([0-9]+\\)\\]" + (2 3 1) LaTeX-auto-env-args) + ("\\\\newenvironment\\*?{\\([^}]+\\)}" + 1 LaTeX-auto-environment) + (,(concat "\\\\newtheorem{\\(" token "+\\)}") 1 LaTeX-auto-environment) + ("\\\\input{\\(\\.*[^#}%\\\\\\.\n\r]+\\)\\(\\.[^#}%\\\\\\.\n\r]+\\)?}" + 1 TeX-auto-file) + ("\\\\include{\\(\\.*[^#}%\\\\\\.\n\r]+\\)\\(\\.[^#}%\\\\\\.\n\r]+\\)?}" + 1 TeX-auto-file) + (,(concat "\\\\bibitem{\\(" token "[^, \n\r\t%\"#'()={}]*\\)}") + 1 LaTeX-auto-bibitem) + (,(concat "\\\\bibitem\\[[^][\n\r]+\\]{\\(" token "[^, \n\r\t%\"#'()={}]*\\)}") + 1 LaTeX-auto-bibitem) + ("\\\\bibliography{\\([^#}\\\\\n\r]+\\)}" 1 LaTeX-auto-bibliography) + ("\\\\addbibresource\\(?:\\[[^]]+\\]\\)?{\\([^#}\\\\\n\r]+\\)\\..+}" + 1 LaTeX-auto-bibliography) + ("\\\\add\\(?:global\\|section\\)bib\\(?:\\[[^]]+\\]\\)?{\\([^#}\\\\\n\r\.]+\\)\\(?:\\..+\\)?}" 1 LaTeX-auto-bibliography) + ("\\\\newrefsection\\[\\([^]]+\\)\\]" 1 LaTeX-split-bibs) + ("\\\\begin{refsection}\\[\\([^]]+\\)\\]" 1 LaTeX-split-bibs))) + LaTeX-auto-class-regexp-list + LaTeX-auto-label-regexp-list + LaTeX-auto-index-regexp-list + LaTeX-auto-minimal-regexp-list + LaTeX-auto-pagestyle-regexp-list + LaTeX-auto-counter-regexp-list + LaTeX-auto-length-regexp-list + LaTeX-auto-savebox-regexp-list) + "List of regular expression matching common LaTeX macro definitions.") + +(defun LaTeX-split-bibs (match) + "Extract bibliography resources from MATCH. +Split the string at commas and remove Biber file extensions." + (let ((bibs (split-string (TeX-match-buffer match) " *, *"))) + (dolist (bib bibs) + (LaTeX-add-bibliographies (replace-regexp-in-string + (concat "\\(?:\\." + (mapconcat #'identity + TeX-Biber-file-extensions + "\\|\\.") + "\\)") + "" bib))))) + +(defun LaTeX-auto-prepare () + "Prepare for LaTeX parsing." + (setq LaTeX-auto-arguments nil + LaTeX-auto-optional nil + LaTeX-auto-env-args nil + LaTeX-auto-style nil + LaTeX-auto-end-symbol nil)) + +(add-hook 'TeX-auto-prepare-hook #'LaTeX-auto-prepare) + +(defun LaTeX-listify-package-options (options) + "Return a list from a comma-separated string of package OPTIONS. +The input string may include LaTeX comments and newlines." + ;; We jump through all those hoops and don't just use `split-string' + ;; or the like in order to be able to deal with key=value package + ;; options which can look like this: "pdftitle={A Perfect Day}, + ;; colorlinks=false" + (let (opts match start) + (with-temp-buffer + (set-syntax-table LaTeX-mode-syntax-table) + (insert options) + (newline) ; So that the last entry can be found. + (goto-char (point-min)) + (setq start (point)) + (while (re-search-forward "[{ ,%\n\r]" nil t) + (setq match (match-string 0)) + (cond + ;; Step over groups. (Let's hope nobody uses escaped braces.) + ((string= match "{") + (up-list)) + ;; Get rid of whitespace. + ((string= match " ") + (delete-region (1- (point)) + (save-excursion + (skip-chars-forward " ") + (point)))) + ;; Add entry to output. + ((or (string= match ",") (= (point) (point-max))) + (let ((entry (buffer-substring-no-properties + start (1- (point))))) + (unless (member entry opts) + (setq opts (append opts (list entry))))) + (setq start (point))) + ;; Get rid of comments. + ((string= match "%") + (delete-region (1- (point)) + (line-beginning-position 2))) + ;; Get rid of newlines. + ((or (string= match "\n") (string= match "\r")) + (delete-char -1))))) + opts)) + +(defvar LaTeX-provided-class-options nil + "Alist of options provided to LaTeX classes. +For each element, the CAR is the name of the class, the CDR is +the list of options provided to it. + +For example, its value will be + ((\"book\" \"a4paper\" \"11pt\" \"openany\" \"fleqn\") + ...) +See also `LaTeX-provided-package-options'.") +(make-variable-buffer-local 'LaTeX-provided-class-options) + +(defun LaTeX-provided-class-options-member (class option) + "Return non-nil if OPTION has been given to CLASS at load time. +The value is actually the tail of the list of options given to CLASS." + (member option (cdr (assoc class LaTeX-provided-class-options)))) + +(defun LaTeX-match-class-option (regexp) + "Check if a documentclass option matching REGEXP is active. +Return first found class option matching REGEXP, or nil if not found." + (TeX-member regexp (apply #'append + (mapcar #'cdr LaTeX-provided-class-options)) + #'string-match)) + +(defvar LaTeX-provided-package-options nil + "Alist of options provided to LaTeX packages. +For each element, the CAR is the name of the package, the CDR is +the list of options provided to it. + +For example, its value will be + ((\"babel\" \"german\") + (\"geometry\" \"a4paper\" \"top=2cm\" \"bottom=2cm\" \"left=2.5cm\" \"right=2.5cm\") + ...) +See also `LaTeX-provided-class-options'.") +(make-variable-buffer-local 'LaTeX-provided-package-options) + +(defun LaTeX-provided-package-options-member (package option) + "Return non-nil if OPTION has been given to PACKAGE at load time. +The value is actually the tail of the list of options given to PACKAGE." + (member option (cdr (assoc package LaTeX-provided-package-options)))) + +(defun LaTeX-auto-cleanup () + "Cleanup after LaTeX parsing." + + ;; Cleanup BibTeX/Biber files + (setq LaTeX-auto-bibliography + (apply #'append (mapcar (lambda (arg) + (split-string arg ",")) + LaTeX-auto-bibliography))) + + ;; Reset class and packages options for the current buffer + (setq LaTeX-provided-class-options nil) + (setq LaTeX-provided-package-options nil) + + ;; Cleanup document classes and packages + (unless (null LaTeX-auto-style) + (while LaTeX-auto-style + (let* ((entry (car LaTeX-auto-style)) + (options (nth 0 entry)) + (style (nth 1 entry)) + (class (nth 2 entry))) + + ;; Next document style. + (setq LaTeX-auto-style (cdr LaTeX-auto-style)) + + ;; Get the options. + (setq options (LaTeX-listify-package-options options)) + + ;; Treat documentclass/documentstyle specially. + (if (or (string-equal "package" class) + (string-equal "Package" class)) + (dolist (elt (split-string + style "\\([ \t\r\n]\\|%[^\n\r]*[\n\r]\\|,\\)+")) + ;; Append style to the style list. + (add-to-list 'TeX-auto-file elt t) + ;; Append to `LaTeX-provided-package-options' the name of the + ;; package and the options provided to it at load time. + (unless (equal options '("")) + (TeX-add-to-alist 'LaTeX-provided-package-options + (list (cons elt options))))) + ;; And a special "art10" style file combining style and size. + (add-to-list 'TeX-auto-file style t) + (add-to-list 'TeX-auto-file + (concat + (cond ((string-equal "article" style) + "art") + ((string-equal "book" style) + "bk") + ((string-equal "report" style) + "rep") + ((string-equal "jarticle" style) + "jart") + ((string-equal "jbook" style) + "jbk") + ((string-equal "jreport" style) + "jrep") + ((string-equal "j-article" style) + "j-art") + ((string-equal "j-book" style) + "j-bk") + ((string-equal "j-report" style ) + "j-rep") + (t style)) + (cond ((member "11pt" options) + "11") + ((member "12pt" options) + "12") + (t + "10"))) + t) + (unless (equal options '("")) + (TeX-add-to-alist 'LaTeX-provided-class-options + (list (cons style options))))) + + ;; The third argument if "class" indicates LaTeX2e features. + (cond ((or (string-equal class "class") + (string-equal class "Class")) + (add-to-list 'TeX-auto-file "latex2e")) + ((string-equal class "style") + (add-to-list 'TeX-auto-file "latex2")))))) + + ;; Cleanup optional arguments + (mapc (lambda (entry) + ;; If we're renewcommand-ing and there is already an entry + ;; in `TeX-auto-symbol', delete it first: + (when (and (string= (nth 2 entry) "re") + (assoc (car entry) TeX-auto-symbol)) + (setq TeX-auto-symbol + (assq-delete-all (car (assoc (car entry) + TeX-auto-symbol)) + TeX-auto-symbol))) + (add-to-list 'TeX-auto-symbol + (list (nth 0 entry) + (string-to-number (nth 1 entry))))) + LaTeX-auto-arguments) + + ;; Cleanup default optional arguments + (mapc (lambda (entry) + ;; If we're renewcommand-ing and there is already an entry + ;; in `TeX-auto-symbol', delete it first: + (when (and (string= (nth 3 entry) "re") + (assoc (car entry) TeX-auto-symbol)) + (setq TeX-auto-symbol + (assq-delete-all (car (assoc (car entry) + TeX-auto-symbol)) + TeX-auto-symbol))) + (add-to-list 'TeX-auto-symbol + (list (nth 0 entry) + (vector "argument") + (1- (string-to-number (nth 1 entry)))))) + LaTeX-auto-optional) + + ;; Cleanup environments arguments + (mapc (lambda (entry) + ;; If we're renewenvironment-ing and there is already an + ;; entry in `LaTeX-auto-environment', delete it first: + (when (and (string= (nth 2 entry) "re") + (assoc (car entry) LaTeX-auto-environment)) + (setq LaTeX-auto-environment + (assq-delete-all (car (assoc (car entry) + LaTeX-auto-environment)) + LaTeX-auto-environment))) + (add-to-list 'LaTeX-auto-environment + (list (nth 0 entry) + (string-to-number (nth 1 entry))))) + LaTeX-auto-env-args) + + ;; Ditto for environments with an optional arg + (mapc (lambda (entry) + ;; If we're renewenvironment-ing and there is already an + ;; entry in `LaTeX-auto-environment', delete it first: + (when (and (string= (nth 2 entry) "re") + (assoc (car entry) LaTeX-auto-environment)) + (setq LaTeX-auto-environment + (assq-delete-all (car (assoc (car entry) + LaTeX-auto-environment)) + LaTeX-auto-environment))) + (add-to-list 'LaTeX-auto-environment + (list (nth 0 entry) 'LaTeX-env-args (vector "argument") + (1- (string-to-number (nth 1 entry)))))) + LaTeX-auto-env-args-with-opt) + + ;; Cleanup use of def to add environments + ;; NOTE: This uses an O(N^2) algorithm, while an O(N log N) + ;; algorithm is possible. + (mapc (lambda (symbol) + (if (not (TeX-member symbol TeX-auto-symbol #'equal)) + ;; No matching symbol, insert in list + (add-to-list 'TeX-auto-symbol (concat "end" symbol)) + ;; Matching symbol found, remove from list + (if (equal (car TeX-auto-symbol) symbol) + ;; Is it the first symbol? + (setq TeX-auto-symbol (cdr TeX-auto-symbol)) + ;; Nope! Travel the list + (let ((list TeX-auto-symbol)) + (while (consp (cdr list)) + ;; Until we find it. + (if (equal (car (cdr list)) symbol) + ;; Then remove it. + (setcdr list (cdr (cdr list)))) + (setq list (cdr list))))) + ;; and add the symbol as an environment. + (add-to-list 'LaTeX-auto-environment symbol))) + LaTeX-auto-end-symbol)) + +(add-hook 'TeX-auto-cleanup-hook #'LaTeX-auto-cleanup) + +(advice-add 'LaTeX-add-bibliographies :after #'TeX-run-style-hooks) + +;;; Biber support + +(defvar LaTeX-using-Biber nil + "Used to track whether Biber is in use.") +(make-variable-buffer-local 'LaTeX-using-Biber) + +;;; BibTeX + +(defvar BibTeX-auto-regexp-list + '(("@[Ss][Tt][Rr][Ii][Nn][Gg]" 1 ignore) + ("@[a-zA-Z]+[{(][ \t]*\\([^, \n\r\t%\"#'()={}]*\\)" 1 LaTeX-auto-bibitem)) + "List of regexp-list expressions matching BibTeX items.") + +;;;###autoload +(defun BibTeX-auto-store () + "This function should be called from `bibtex-mode-hook'. +It will setup BibTeX to store keys in an auto file." + ;; We want this to be early in the list, so we do not + ;; add it before we enter BibTeX mode the first time. + (add-hook 'write-contents-functions #'TeX-safe-auto-write nil t) + (TeX-bibtex-set-BibTeX-dialect) + (set (make-local-variable 'TeX-auto-untabify) nil) + (set (make-local-variable 'TeX-auto-parse-length) 999999) + (set (make-local-variable 'TeX-auto-regexp-list) BibTeX-auto-regexp-list) + (set (make-local-variable 'TeX-master) t)) + +;;; Macro Argument Hooks + +(defun TeX-arg-conditional (_optional expr then else) + "Implement if EXPR THEN ELSE. + +If EXPR evaluate to true, parse THEN as an argument list, else +parse ELSE as an argument list. The compatibility argument +OPTIONAL is ignored." + (TeX-parse-arguments (if (eval expr t) then else))) + +(defun TeX-arg-eval (optional &rest args) + "Evaluate ARGS and insert value in buffer. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one." + (TeX-argument-insert (eval args t) optional)) + +(defun TeX-read-label (optional &optional prompt definition) + "Prompt for a label completing with known labels and return it. +This function always returns a string depending on user input: +the returned value can be an empty string \"\", the value of +`TeX-read-label-prefix' if present (for example, \"fig:\") or a +complete label input (for example, \"fig:foo\"). If OPTIONAL is +non-nil, indicate optional as part of prompt in minibuffer. Use +PROMPT as the prompt string. If DEFINITION is non-nil, add the +chosen label to the list of defined labels. +`TeX-read-label-prefix' is used as initial input for the label. +Also check if label is already defined and ask user for +confirmation before proceeding." + (let (label valid) + (while (not valid) + (setq label + (completing-read + (TeX-argument-prompt optional prompt "Key") + (LaTeX-label-list) nil nil TeX-read-label-prefix)) + ;; If we're defining a label, check if it's already defined and + ;; ask user for confirmation, otherwise ask again + (cond ((and definition + (assoc label (LaTeX-label-list))) + (ding) + (when (y-or-n-p + ;; Emacs 24 compatibility + (if (fboundp 'format-message) + (format-message "Label `%s' exists. Use anyway? " label) + (format "Label `%s' exists. Use anyway? " label))) + (setq valid t))) + (t + (setq valid t)))) + ;; Only add a newly defined label to list of known one if it is + ;; not empty and not equal to `TeX-read-label-prefix', if given + (when (and definition + (not (string-equal "" label)) + (if TeX-read-label-prefix + (not (string-equal TeX-read-label-prefix label)) + t)) + (LaTeX-add-labels label)) + ;; Return label, can be empty string "", TeX-read-label-prefix + ;; only "fig:" or the real thing like "fig:foo" + label)) + +(defun TeX-arg-label (optional &optional prompt definition) + "Prompt for a label completing with known labels. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string. If DEFINITION is non-nil, add the chosen label to the +list of defined labels. `TeX-read-label-prefix' is used as +initial input for the label." + (TeX-argument-insert + (TeX-read-label optional prompt definition) optional optional)) + +(defvar reftex-ref-macro-prompt) + +(defun TeX-arg-ref (optional &optional prompt definition) + "Let-bind `reftex-ref-macro-prompt' to nil and pass arguments +to `TeX-arg-label'. + +See the documentation of `TeX-arg-label' for details on the +arguments: OPTIONAL, PROMPT, and DEFINITION." + (let ((reftex-ref-macro-prompt nil)) + (TeX-arg-label optional prompt definition))) + +(defun TeX-arg-index-tag (optional &optional prompt &rest _args) + "Prompt for an index tag. +This is the name of an index, not the entry. + +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string. ARGS is unused." + (TeX-argument-insert + (TeX-read-string (TeX-argument-prompt optional prompt "Index tag")) + optional)) + +(defun TeX-arg-index (optional &optional prompt &rest _args) + "Prompt for an index entry completing with known entries. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string. ARGS is unused." + (let ((entry (completing-read (TeX-argument-prompt optional prompt "Key") + (LaTeX-index-entry-list)))) + (if (and (not (string-equal "" entry)) + (not (member (list entry) (LaTeX-index-entry-list)))) + (LaTeX-add-index-entries entry)) + (TeX-argument-insert entry optional optional))) + +(defalias 'TeX-arg-define-index #'TeX-arg-index) + +(defun TeX-arg-macro (optional &optional prompt definition) + "Prompt for a TeX macro with completion. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string. If DEFINITION is non-nil, add the chosen macro to the +list of defined macros." + (let ((macro (completing-read (TeX-argument-prompt optional prompt + (concat "Macro: " + TeX-esc) + t) + (TeX-symbol-list)))) + (if (and definition (not (string-equal "" macro))) + (TeX-add-symbols macro)) + (TeX-argument-insert macro optional TeX-esc))) + +(defun TeX-arg-environment (optional &optional prompt definition) + "Prompt for a LaTeX environment with completion. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string. If DEFINITION is non-nil, add the chosen environment to +the list of defined environments." + (let ((environment (completing-read (TeX-argument-prompt optional prompt + "Environment") + (LaTeX-environment-list)))) + (if (and definition (not (string-equal "" environment))) + (LaTeX-add-environments environment)) + + (TeX-argument-insert environment optional))) + +;; Why is DEFINITION unused? +(defun TeX-arg-cite (optional &optional prompt _definition) + "Prompt for a BibTeX citation with completion. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string. DEFINITION is unused." + (let ((items (multi-prompt "," t (TeX-argument-prompt optional prompt "Key") + (LaTeX-bibitem-list)))) + (apply #'LaTeX-add-bibitems items) + (TeX-argument-insert (mapconcat #'identity items ",") optional optional))) + +(defun TeX-arg-counter (optional &optional prompt definition) + "Prompt for a LaTeX counter. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string. If DEFINITION is non-nil, add the chosen counter to +the list of defined counters." + (let ((counter (completing-read (TeX-argument-prompt optional prompt + "Counter") + (LaTeX-counter-list)))) + (if (and definition (not (string-equal "" counter))) + (LaTeX-add-counters counter)) + (TeX-argument-insert counter optional))) + +(defun TeX-arg-savebox (optional &optional prompt definition) + "Prompt for a LaTeX savebox. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string. If definition is non-nil, the savebox is added to the +list of defined saveboxes." + (let ((savebox (completing-read (TeX-argument-prompt optional prompt + (concat "Savebox: " + TeX-esc) t) + (LaTeX-savebox-list)))) + (if (and definition (not (zerop (length savebox)))) + (LaTeX-add-saveboxes savebox)) + (TeX-argument-insert savebox optional TeX-esc))) + +(defun TeX-arg-length (optional &optional prompt default initial-input + definition) + "Prompt for a LaTeX length. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string. DEFAULT is passed to `completing-read', which see. If +INITIAL-INPUT is non-nil, insert it in the minibuffer initially, +with point positioned at the end. If DEFINITION is non-nil, the +length is added to the list of defined length." + (let ((length + (completing-read + (TeX-argument-prompt optional + ;; Cater for the case when PROMPT and + ;; DEFAULT are both given: + (if (and prompt default) + (concat prompt " (default " default ")") + prompt) + (concat "Length" + (when (and default (not optional)) + (concat " (default " default ")")))) + ;; A valid length can be a macro or a length of the form + ;; . Input starting with a `\' can be + ;; completed with length macros. + (mapcar (lambda (elt) (concat TeX-esc (car elt))) + (LaTeX-length-list)) + ;; Some macros takes as argument only a length macro (e.g., + ;; `\setlength' in its first argument, and `\newlength'), in + ;; this case is convenient to set `\\' as initial input. + nil nil initial-input nil default))) + (if (and definition (not (zerop (length length)))) + ;; Strip leading TeX-esc from macro name + (LaTeX-add-lengths (substring length 1))) + (TeX-argument-insert length optional))) + +(defun TeX-arg-file (optional &optional prompt) + "Prompt for a filename in the current directory. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (TeX-argument-insert (read-file-name (TeX-argument-prompt optional + prompt "File") + "" "" nil) + optional)) + +(defun TeX-arg-file-name (optional &optional prompt) + "Prompt for a file name. +Initial input is the name of the file being visited in the +current buffer, with extension. If OPTIONAL is non-nil, insert +it as an optional argument. Use PROMPT as the prompt string." + (let ((name (file-name-nondirectory buffer-file-name))) + (TeX-argument-insert + (TeX-read-string + (TeX-argument-prompt optional + (when prompt + (if optional + prompt + (format (concat prompt " (default %s)") name))) + (if optional + "Name" + (format "Name (default %s)" name))) + nil nil (if optional nil name)) + optional))) + +(defun TeX-arg-file-name-sans-extension (optional &optional prompt) + "Prompt for a file name. +Initial input is the name of the file being visited in the +current buffer, without extension. If OPTIONAL is non-nil, +insert it as an optional argument. Use PROMPT as the prompt +string." + (let ((name (file-name-sans-extension + (file-name-nondirectory buffer-file-name)))) + (TeX-argument-insert + (TeX-read-string + (TeX-argument-prompt optional + (when prompt + (if optional + prompt + (format (concat prompt " (default %s)") name))) + (if optional + "Name" + (format "Name (default %s)" name))) + nil nil (if optional nil name)) + optional))) + +(defun TeX-arg-define-label (optional &optional prompt) + "Prompt for a label completing with known labels. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string. `TeX-read-label-prefix' is used as initial input for the +label." + (TeX-arg-label optional prompt t)) + +(defun TeX-arg-default-argument-value (optional &optional prompt) + "Prompt for the default value for the first argument of a LaTeX macro. + +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (TeX-argument-insert + (TeX-read-string + (TeX-argument-prompt optional prompt "Default value for first argument")) + optional)) + +(defun TeX-arg-define-macro-arguments (optional &optional prompt) + "Prompt for the number of arguments for a LaTeX macro. If this +is non-zero, also prompt for the default value for the first +argument. + +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (let ((arg-count (TeX-read-string + (TeX-argument-prompt optional prompt + "Number of arguments" + nil)))) + (unless (or (string= arg-count "0") + (string= arg-count "")) + (TeX-argument-insert arg-count optional) + (unless (string-equal LaTeX-version "2") + (TeX-arg-default-argument-value optional))))) + +(defun TeX-arg-define-macro (optional &optional prompt) + "Prompt for a TeX macro with completion. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (TeX-arg-macro optional prompt t)) + +(defun TeX-arg-define-environment (optional &optional prompt) + "Prompt for a LaTeX environment with completion. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (TeX-arg-environment optional prompt t)) + +(defun TeX-arg-define-cite (optional &optional prompt) + "Prompt for a BibTeX citation. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (TeX-arg-cite optional prompt t)) + +(defun TeX-arg-define-counter (optional &optional prompt) + "Prompt for a LaTeX counter. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (TeX-arg-counter optional prompt t)) + +(defun TeX-arg-define-savebox (optional &optional prompt) + "Prompt for a LaTeX savebox. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (TeX-arg-savebox optional prompt t)) + +(defun TeX-arg-define-length (optional &optional prompt) + "Prompt for a LaTeX length. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (TeX-arg-length optional prompt nil "\\" t)) + +(defcustom LaTeX-style-list '(("amsart") + ("amsbook") + ("article") + ("beamer") + ("book") + ("dinbrief") + ("foils") + ("letter") + ("memoir") + ("minimal") + ("prosper") + ("report") + ("scrartcl") + ("scrbook") + ("scrlttr2") + ("scrreprt") + ("slides")) + "List of document classes offered when inserting a document environment. + +If `TeX-arg-input-file-search' is set to t, you will get +completion with all LaTeX classes available in your distribution +and this variable will be ignored." + :group 'LaTeX-environment + :type '(repeat (group (string :format "%v")))) + +(defvar LaTeX-global-class-files nil + "List of the LaTeX class files. +Initialized once at the first time you prompt for a LaTeX class. +May be reset with `\\[universal-argument] \\[TeX-normal-mode]'.") + +;; Add the variable to `TeX-normal-mode-reset-list': +(add-to-list 'TeX-normal-mode-reset-list 'TeX-global-class-files) + +(defcustom TeX-arg-input-file-search t + "If `TeX-arg-input-file' should search for files. +If the value is t, files in TeX's search path are searched for +and provided for completion. The file name is then inserted +without directory and extension. If the value is nil, the file +name can be specified manually and is inserted with a path +relative to the directory of the current buffer's file and with +extension. If the value is `ask', you are asked for the method +to use every time `TeX-arg-input-file' is called." + :group 'LaTeX-macro + :type '(choice (const t) (const nil) (const ask))) + +(defvar TeX-after-document-hook nil + "List of functions to be run at the end of `TeX-arg-document'. + +To insert a hook here, you must insert it in the appropiate style file.") + +(defun TeX-arg-document (_optional &optional _ignore) + "Insert arguments to documentclass. +OPTIONAL and IGNORE are ignored." + (let* ((TeX-file-extensions '("cls")) + (crm-separator ",") + style var options defopt optprmpt) + (unless LaTeX-global-class-files + (setq LaTeX-global-class-files + (if (if (eq TeX-arg-input-file-search 'ask) + (not (y-or-n-p "Find class yourself? ")) + TeX-arg-input-file-search) + (prog2 + (message "Searching for LaTeX classes...") + (TeX-search-files-by-type 'texinputs 'global t t) + (message "Searching for LaTeX classes...done")) + LaTeX-style-list))) + (setq style (completing-read + (concat "Document class (default " LaTeX-default-style "): ") + LaTeX-global-class-files nil nil nil nil LaTeX-default-style)) + ;; Clean up hook before use. + (setq TeX-after-document-hook nil) + (TeX-load-style style) + (setq var (intern (format "LaTeX-%s-class-options" style))) + (setq defopt (if (stringp LaTeX-default-options) + LaTeX-default-options + (mapconcat #'identity LaTeX-default-options ","))) + (setq optprmpt + (if (and defopt (not (string-equal defopt ""))) + (format "Options (default %s): " defopt) "Options: ")) + (if (or (and (boundp var) + (listp (symbol-value var))) + (fboundp var)) + (if (functionp var) + (setq options (funcall var)) + (when (symbol-value var) + (setq options + (mapconcat #'identity + (TeX-completing-read-multiple + optprmpt (mapcar #'list (symbol-value var)) + nil nil nil nil defopt) + ",")))) + (setq options (TeX-read-string optprmpt nil nil defopt))) + (unless (zerop (length options)) + (insert LaTeX-optop options LaTeX-optcl) + (let ((opts (LaTeX-listify-package-options options))) + (TeX-add-to-alist 'LaTeX-provided-class-options + (list (cons style opts))))) + (insert TeX-grop style TeX-grcl)) + + (TeX-update-style t) + (run-hooks 'TeX-after-document-hook)) + +(defvar LaTeX-after-usepackage-hook nil + "List of functions to be run at the end of `LaTeX-arg-usepackage'. + +To insert a hook here, you must insert it in the appropiate style file.") + +(defvar TeX-global-input-files nil + "List of the non-local TeX input files. +Initialized once at the first time you prompt for an input file. +May be reset with `\\[universal-argument] \\[TeX-normal-mode]'.") + +(defvar TeX-global-input-files-with-extension nil + "List of the non-local TeX input files with extension. +Initialized once at the first time you prompt for an input file +inside a file hook command. +May be reset with `\\[universal-argument] \\[TeX-normal-mode]'.") + +(defvar LaTeX-global-package-files nil + "List of the LaTeX package files. +Initialized once at the first time you prompt for a LaTeX package. +May be reset with `\\[universal-argument] \\[TeX-normal-mode]'.") + +;; Add the variables to `TeX-normal-mode-reset-list': +(add-to-list 'TeX-normal-mode-reset-list 'TeX-global-input-files) +(add-to-list 'TeX-normal-mode-reset-list 'TeX-global-input-files-with-extension) +(add-to-list 'TeX-normal-mode-reset-list 'LaTeX-global-package-files) + +(defun LaTeX-arg-usepackage-read-packages-with-options () + "Read the packages and the options for the usepackage macro. + +If at least one package is provided, this function returns a cons +cell, whose CAR is the list of packages and the CDR is the string +of the options, nil otherwise." + (let* ((TeX-file-extensions '("sty")) + (crm-separator ",") + packages var options) + (unless LaTeX-global-package-files + (if (if (eq TeX-arg-input-file-search 'ask) + (not (y-or-n-p "Find packages yourself? ")) + TeX-arg-input-file-search) + (progn + (message "Searching for LaTeX packages...") + (setq LaTeX-global-package-files + (mapcar #'list (TeX-search-files-by-type + 'texinputs 'global t t))) + (message "Searching for LaTeX packages...done")))) + (setq packages (TeX-completing-read-multiple + "Packages: " LaTeX-global-package-files)) + ;; Clean up hook before use in `LaTeX-arg-usepackage-insert'. + (setq LaTeX-after-usepackage-hook nil) + (mapc #'TeX-load-style packages) + ;; Prompt for options only if at least one package has been supplied, return + ;; nil otherwise. + (when packages + (setq var (if (= 1 (length packages)) + (intern (format "LaTeX-%s-package-options" (car packages))) + ;; Something like `\usepackage[options]{pkg1,pkg2,pkg3,...}' is + ;; allowed (provided that pkg1, pkg2, pkg3, ... accept same + ;; options). When there is more than one package, set `var' to + ;; a dummy value so next `if' enters else form. + t)) + (if (or (and (boundp var) + (listp (symbol-value var))) + (fboundp var)) + (if (functionp var) + (setq options (funcall var)) + (when (symbol-value var) + (setq options + (mapconcat #'identity + (TeX-completing-read-multiple + "Options: " (mapcar #'list (symbol-value var))) + ",")))) + (setq options (TeX-read-string "Options: "))) + (cons packages options)))) + +(defun LaTeX-arg-usepackage-insert (packages options) + "Actually insert arguments to usepackage." + (unless (zerop (length options)) + (let ((opts (LaTeX-listify-package-options options))) + (mapc (lambda (elt) + (TeX-add-to-alist 'LaTeX-provided-package-options + (list (cons elt opts)))) + packages)) + (insert LaTeX-optop options LaTeX-optcl)) + (insert TeX-grop (mapconcat #'identity packages ",") TeX-grcl) + (run-hooks 'LaTeX-after-usepackage-hook) + (apply #'TeX-run-style-hooks packages)) + +(defun LaTeX-arg-usepackage (_optional) + "Insert arguments to usepackage. +OPTIONAL is ignored." + (let* ((packages-options (LaTeX-arg-usepackage-read-packages-with-options)) + (packages (car packages-options)) + (options (cdr packages-options))) + (LaTeX-arg-usepackage-insert packages options))) + +(defun LaTeX-insert-usepackages () + "Prompt for the insertion of usepackage macros until empty +input is reached. + +Return t if at least one \\usepackage has been inserted, nil +otherwise." + (let (packages-options packages options (inserted nil)) + (while (setq packages-options + (LaTeX-arg-usepackage-read-packages-with-options)) + (setq packages (car packages-options)) + (setq options (cdr packages-options)) + (insert TeX-esc "usepackage") + (LaTeX-arg-usepackage-insert packages options) + (LaTeX-newline) + (setq inserted t)) + inserted)) + +(defcustom LaTeX-search-files-type-alist + '((texinputs "${TEXINPUTS.latex}" ("tex/generic/" "tex/latex/") + 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) + (bbxinputs "" ("tex/latex/") BibLaTeX-style-extensions) + (biberinputs "${BIBINPUTS}" ("bibtex/bib/") TeX-Biber-file-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. + +Reset the mode for a change of this variable to take effect." + :group 'TeX-file + :type '(alist :key-type symbol + :value-type + (group (string :tag "Kpathsea variable") + (choice :tag "Directories" + (repeat :tag "TDS subdirectories" string) + (repeat :tag "Absolute directories" directory) + (repeat :tag "Variables" variable)) + (choice :tag "Extensions" + variable (repeat string))))) + +(defun TeX-arg-input-file (optional &optional prompt local) + "Prompt for a tex or sty file. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. PROMPT is the prompt, +LOCAL is a flag. If the flag is set, only complete with local +files." + (let ((search (if (eq TeX-arg-input-file-search 'ask) + (not (y-or-n-p "Find file yourself? ")) + TeX-arg-input-file-search)) + file style) + (if search + (progn + (unless (or TeX-global-input-files local) + (message "Searching for files...") + (setq TeX-global-input-files + (mapcar #'list (TeX-search-files-by-type + 'texinputs 'global t t))) + (message "Searching for files...done")) + (setq file (completing-read + (TeX-argument-prompt optional prompt "File") + (TeX-delete-dups-by-car + (append (mapcar #'list (TeX-search-files-by-type + 'texinputs 'local t t)) + (unless local + TeX-global-input-files)))) + style file)) + (setq file (read-file-name + (TeX-argument-prompt optional prompt "File") nil "")) + (unless (string-equal file "") + (setq file (file-relative-name file))) + (setq style (file-name-sans-extension (file-name-nondirectory file)))) + (unless (string-equal "" style) + (TeX-run-style-hooks style)) + (TeX-argument-insert file optional))) + +(defvar BibTeX-global-style-files nil + "Association list of BibTeX style files. + +Initialized once at the first time you prompt for an input file. +May be reset with `\\[universal-argument] \\[TeX-normal-mode]'.") + +(defvar BibLaTeX-global-style-files nil + "Association list of BibLaTeX style files. + +Initialized once at the first time you prompt for a BibLaTeX +style. May be reset with `\\[universal-argument] \\[TeX-normal-mode]'.") + +;; Add both variables to `TeX-normal-mode-reset-list': +(add-to-list 'TeX-normal-mode-reset-list 'BibTeX-global-style-files) +(add-to-list 'TeX-normal-mode-reset-list 'BibLaTeX-global-style-files) + +(defun TeX-arg-bibstyle (optional &optional prompt) + "Prompt for a BibTeX style file. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (message "Searching for BibTeX styles...") + (or BibTeX-global-style-files + (setq BibTeX-global-style-files + (mapcar #'list (TeX-search-files-by-type 'bstinputs 'global t t)))) + (message "Searching for BibTeX styles...done") + (TeX-argument-insert + (completing-read (TeX-argument-prompt optional prompt "BibTeX style") + (append (mapcar #'list (TeX-search-files-by-type + 'bstinputs 'local t t)) + BibTeX-global-style-files)) + optional)) + +(defvar BibTeX-global-files nil + "Association list of BibTeX files. + +Initialized once at the first time you prompt for a BibTeX file. +May be reset with `\\[universal-argument] \\[TeX-normal-mode]'.") + +(defvar TeX-Biber-global-files nil + "Association list of Biber files. + +Initialized once at the first time you prompt for an Biber file. +May be reset with `\\[universal-argument] \\[TeX-normal-mode]'.") + +(add-to-list 'TeX-normal-mode-reset-list 'BibTeX-global-files) +(add-to-list 'TeX-normal-mode-reset-list 'TeX-Biber-global-files) + +(defun TeX-arg-bibliography (optional &optional prompt) + "Prompt for a BibTeX database file. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (message "Searching for BibTeX files...") + (or BibTeX-global-files + (setq BibTeX-global-files + (mapcar #'list (TeX-search-files-by-type 'bibinputs 'global t t)))) + (message "Searching for BibTeX files...done") + (let ((styles (multi-prompt + "," t + (TeX-argument-prompt optional prompt "BibTeX files") + (append (mapcar #'list (TeX-search-files-by-type + 'bibinputs 'local t t)) + BibTeX-global-files)))) + (apply #'LaTeX-add-bibliographies styles) + ;; Run style files associated to the bibliography database files in order to + ;; immediately fill `LaTeX-bibitem-list'. + (mapc #'TeX-run-style-hooks styles) + (TeX-argument-insert (mapconcat #'identity styles ",") optional))) + +(defun TeX-arg-corner (optional &optional prompt) + "Prompt for a LaTeX side or corner position with completion. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (TeX-argument-insert + (completing-read (TeX-argument-prompt optional prompt "Position") + '("l" "r" "t" "b" "tl" "tr" "bl" "br") + nil t) + optional)) + +(defun TeX-arg-lr (optional &optional prompt) + "Prompt for a LaTeX side with completion. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (TeX-argument-insert + (completing-read (TeX-argument-prompt optional prompt "Position") + '("l" "r") + nil t) + optional)) + +(defun TeX-arg-tb (optional &optional prompt poslist) + "Prompt for a LaTeX side with completion. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string. POSLIST contains the positioning characters offered for +completion. It can be the symbols `center', `stretch' or nil +with the following completion list: + center t, b, c + stretch t, b, c, s + nil t, b" + (TeX-argument-insert + (completing-read (TeX-argument-prompt optional prompt "Position") + (cond ((eq poslist 'center) + '("t" "b" "c")) + ((eq poslist 'stretch) + '("t" "b" "c" "s")) + (t + '("t" "b"))) + nil t) + optional)) + +(defcustom TeX-date-format "%Y/%m/%d" + "The default date format prompted by `TeX-arg-date'." + :group 'LaTeX-macro + :type 'string) + +(defun TeX-arg-date (optional &optional prompt) + "Prompt for a date, defaulting to the current date. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (let ((default (format-time-string TeX-date-format (current-time)))) + (TeX-argument-insert + (TeX-read-string + (TeX-argument-prompt optional + (when prompt + (format (concat prompt " (default %s)") default)) + (format "Date (default %s)" default)) + nil nil default) + optional))) + +(defun TeX-arg-version (optional &optional prompt) + "Prompt for the version of a file. +Use as initial input the current date. If OPTIONAL is non-nil, +insert the resulting value as an optional argument, otherwise as +a mandatory one. Use PROMPT as the prompt string." + (let ((version (format-time-string "%Y/%m/%d" (current-time)))) + (TeX-argument-insert + (TeX-read-string + (TeX-argument-prompt optional + (when prompt + (format (concat prompt " (default %s)") version)) + (format "Version (default %s)" version)) + nil nil version) + optional))) + +(defun TeX-arg-pagestyle (optional &optional prompt definition) + "Prompt for a LaTeX pagestyle with completion. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string. If DEFINITION is non-nil, add the chosen pagestyle to +the list of defined pagestyles." + (let ((pagestyle (completing-read (TeX-argument-prompt optional prompt + "Pagestyle") + (LaTeX-pagestyle-list)))) + (if (and definition (not (string-equal "" pagestyle))) + (LaTeX-add-pagestyles pagestyle)) + (TeX-argument-insert pagestyle optional))) + +(defcustom LaTeX-default-verb-delimiter ?| + "Default delimiter for `\\verb' macros." + :group 'LaTeX-macro + :type 'character) + +(defun TeX-arg-verb (_optional &optional _ignore) + "Prompt for delimiter and text. +The compatibility argument OPTIONAL and IGNORE are ignored." + (let ((del (read-quoted-char + (concat "Delimiter (default " + (char-to-string LaTeX-default-verb-delimiter) "): ")))) + (when (<= del ?\ ) (setq del LaTeX-default-verb-delimiter)) + (if (TeX-active-mark) + (progn + (insert del) + (goto-char (mark)) + (insert del)) + (insert del (read-from-minibuffer "Text: ") del)) + (setq LaTeX-default-verb-delimiter del))) + +(defun TeX-arg-verb-delim-or-brace (optional &optional prompt) + "Prompt for delimiter and text. +If OPTIONAL, indicate optional argument in minibuffer. PROMPT is +a string replacing the default one when asking the user for text. +This function is intended for \\verb like macros which take their +argument in delimiters like \"\| \|\" or braces \"\{ \}\"." + (let ((del (read-quoted-char + (concat "Delimiter (default " + (char-to-string LaTeX-default-verb-delimiter) "): ")))) + (when (<= del ?\ ) + (setq del LaTeX-default-verb-delimiter)) + (if (TeX-active-mark) + (progn + (insert del) + (goto-char (mark)) + ;; If the delimiter was an opening brace, close it with a + ;; brace, otherwise use the delimiter again + (insert (if (= del ?\{) + ?\} + del))) + ;; Same thing again + (insert del (read-from-minibuffer + (TeX-argument-prompt optional prompt "Text")) + (if (= del ?\{) + ?\} + del))) + ;; Do not set `LaTeX-default-verb-delimiter' if the user input was + ;; an opening brace. This would give funny results for the next + ;; "C-c C-m \verb RET" + (unless (= del ?\{) + (setq LaTeX-default-verb-delimiter del)))) + +(defun TeX-arg-pair (_optional first second) + "Insert a pair of number, prompted by FIRST and SECOND. + +The numbers are surounded by parenthesizes and separated with a +comma. The compatibility argument OPTIONAL is ignored." + (insert "(" (TeX-read-string (concat first ": ")) "," + (TeX-read-string (concat second ": ")) ")")) + +(defun TeX-arg-size (optional) + "Insert width and height as a pair. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one." + (TeX-arg-pair optional "Width" "Height")) + +(defun TeX-arg-coordinate (optional) + "Insert x and y coordinate as a pair. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one." + (TeX-arg-pair optional "X position" "Y position")) + +(defconst TeX-braces-default-association + '(("[" . "]") + ("\\{" . "\\}") + ("(" . ")") + ("|" . "|") + ("\\|" . "\\|") + ("/" . "/") + ("\\backslash" . "\\backslash") + ("\\lfloor" . "\\rfloor") + ("\\lceil" . "\\rceil") + ("\\langle" . "\\rangle"))) + +(defcustom TeX-braces-user-association nil + "A list of your personal association of brace symbols. +These are used for \\left and \\right. + +The car of each entry is the brace used with \\left, +the cdr is the brace used with \\right." + :group 'LaTeX-macro + :group 'LaTeX-math + :type '(repeat (cons :format "%v" + (string :tag "Left") + (string :tag "Right")))) + +(defvar TeX-braces-association + (append TeX-braces-user-association + TeX-braces-default-association) + "A list of association of brace symbols for \\left and \\right. +The car of each entry is the brace used with \\left, +the cdr is the brace used with \\right.") + +(defcustom LaTeX-electric-left-right-brace nil + "If non-nil, insert right brace with suitable macro after typing left brace." + :group 'LaTeX-macro + :type 'boolean) + +(defvar TeX-left-right-braces + '(("[") ("]") ("\\{") ("\\}") ("(") (")") ("|") ("\\|") + ("/") ("\\backslash") ("\\lfloor") ("\\rfloor") + ("\\lceil") ("\\rceil") ("\\langle") ("\\rangle") + ("\\uparrow") ("\\Uparrow") ("\\downarrow") ("\\Downarrow") + ("\\updownarrow") ("\\Updownarrow") (".")) + "List of symbols which can follow the \\left or \\right command.") + +(defvar LaTeX-left-right-macros-association + '(("left" . "right") + ("bigl" . "bigr") ("Bigl" . "Bigr") + ("biggl" . "biggr") ("Biggl" . "Biggr")) + "Alist of macros for adjusting size of left and right braces. +The car of each entry is for left brace and the cdr is for right brace.") + +(defun TeX-arg-insert-braces (optional &optional prompt) + "Prompt for a brace for \\left and insert the corresponding \\right. +If OPTIONAL is non-nil, insert the resulting value as an optional +argument, otherwise as a mandatory one. Use PROMPT as the prompt +string." + (let (left-macro) + (save-excursion + ;; Obtain macro name such as "left", "bigl" etc. + (setq left-macro (buffer-substring-no-properties + (point) + (progn (backward-word 1) (point)))) + (backward-char) + (LaTeX-newline) + (indent-according-to-mode) + ;; Delete possibly produced blank line. + (beginning-of-line 0) + (if (looking-at "^[ \t]*$") + (progn (delete-horizontal-space) + (delete-char 1)))) + (let ((left-brace (completing-read + (TeX-argument-prompt optional prompt + "Which brace") + TeX-left-right-braces))) + (insert left-brace) + (LaTeX-newline) + (save-excursion + (if (TeX-active-mark) + (goto-char (mark))) + (LaTeX-newline) + (LaTeX-insert-corresponding-right-macro-and-brace + left-macro left-brace optional prompt) + (indent-according-to-mode)) + (indent-according-to-mode)))) + +(defvar TeX-arg-right-insert-p) ;; Defined further below. + +(defun TeX-arg-insert-right-brace-maybe (optional) + "Insert the suitable right brace macro such as \\rangle. +Insertion is done when `TeX-arg-right-insert-p' is non-nil. +If the left brace macro is preceded by \\left, \\bigl etc., +supply the corresponding macro such as \\right before the right brace macro." + ;; Nothing is done when TeX-arg-right-insert-p is nil. + (when TeX-arg-right-insert-p + (let (left-brace left-macro) + (save-excursion + ;; Obtain left brace macro name such as "\langle". + (setq left-brace (buffer-substring-no-properties + (point) + (progn (backward-word) (backward-char) + (point))) + ;; Obtain the name of preceding left macro, if any, + ;; such as "left", "bigl" etc. + left-macro (LaTeX--find-preceding-left-macro-name))) + (save-excursion + (if (TeX-active-mark) + (goto-char (mark))) + (LaTeX-insert-corresponding-right-macro-and-brace + left-macro left-brace optional))))) + +(defun LaTeX-insert-left-brace (arg) + "Insert typed left brace ARG times and possibly a correspondig right brace. +Automatic right brace insertion is done only if no prefix ARG is given and +`LaTeX-electric-left-right-brace' is non-nil. +Normally bound to keys \(, { and [." + (interactive "*P") + ;; If you change the condition for `auto-p', adjust the condition in + ;; the `delete-selection' property, just below this defun, accordingly. + (let ((auto-p (and LaTeX-electric-left-right-brace (not arg)))) + (if (and auto-p + (TeX-active-mark) + (> (point) (mark))) + (exchange-point-and-mark)) + (if auto-p + ;; Should supply corresponding right brace with possible + ;; \right-like macro. + (let ((lbrace (char-to-string last-command-event)) lmacro skip-p) + ;; Use `insert' rather than `self-insert-command' so that + ;; unexcpected side effects, e.g. `electric-pair-mode', + ;; won't mess up the following outcomes. (bug#47936) + (insert last-command-event) + (save-excursion + (backward-char) + ;; The brace "{" is exceptional in two aspects. + ;; 1. "\{" should be considered as a single brace + ;; like "(" and "[". + ;; 2. "\left{" is nonsense while "\left\{" and + ;; "\left(" are not. + (if (string= lbrace TeX-grop) + ;; If "{" follows "\", set lbrace to "\{". + (if (TeX-escaped-p) + (progn + (backward-char) + (setq lbrace (concat TeX-esc TeX-grop))) + ;; Otherwise, don't search for left macros. + (setq skip-p t))) + (unless skip-p + ;; Obtain the name of preceding left macro, if any, + ;; such as "left", "bigl" etc. + (setq lmacro (LaTeX--find-preceding-left-macro-name)))) + (let ((TeX-arg-right-insert-p t) + ;; "{" and "}" are paired temporally so that typing + ;; a single "{" should insert a pair "{}". + (TeX-braces-association + (cons (cons TeX-grop TeX-grcl) TeX-braces-association))) + (save-excursion + (if (TeX-active-mark) + (goto-char (mark))) + (LaTeX-insert-corresponding-right-macro-and-brace + lmacro lbrace)))) + ;; Don't supply right brace and just act as ordinary + ;; `self-insert-command'. + (self-insert-command (prefix-numeric-value arg))))) +;; Cater for `delete-selection-mode' (bug#36385) +;; See the header comment of delsel.el for detail. +(put #'LaTeX-insert-left-brace 'delete-selection + (lambda () + ;; Consult `delete-selection' property when + ;; `LaTeX-insert-left-brace' works just the same as + ;; `self-insert-command'. + (and (or (not LaTeX-electric-left-right-brace) + current-prefix-arg) + (let ((f (get #'self-insert-command 'delete-selection))) + ;; If `delete-selection' property of + ;; `self-insert-command' is one of the predefined + ;; special symbols, just return itself. + (if (memq f '(yank supersede kill t nil)) + ;; FIXME: if this list of special symbols is + ;; extended in future delsel.el, this discrimination + ;; will become wrong. + f + ;; Otherwise, call it as a function and return + ;; its value. + (funcall f)))))) + +(defun LaTeX-insert-corresponding-right-macro-and-brace + (lmacro lbrace &optional optional prompt) + "Insert right macro and brace correspoinding to LMACRO and LBRACE. +Left-right association is determined through +`LaTeX-left-right-macros-association' and `TeX-braces-association'. + +If brace association can't be determined or `TeX-arg-right-insert-p' +is nil, consult user which brace should be used." + ;; This function is called with LMACRO being one of the following + ;; possibilities. + ;; (1) nil, which means LBRACE is isolated. + ;; (2) null string, which means LBRACE follows right after "\" to + ;; form "\(" or "\[". + ;; (3) a string in CARs of `LaTeX-left-right-macros-association'. + (let ((rmacro (cdr (assoc lmacro LaTeX-left-right-macros-association))) + (rbrace (cdr (assoc lbrace TeX-braces-association)))) + ;; Since braces like "\(" and "\)" should be paired, RMACRO + ;; should be considered as null string in the case (2). + (if (string= lmacro "") + (setq rmacro "")) + ;; Insert right macros such as "\right", "\bigr" etc., if necessary. + ;; Even single "\" will be inserted so that "\)" or "\]" is + ;; inserted after "\(", "\[". + (if rmacro + (insert TeX-esc rmacro)) + (cond + ((and TeX-arg-right-insert-p rbrace) + (insert rbrace)) + (rmacro + (insert (completing-read + (TeX-argument-prompt + optional prompt + (format "Which brace (default %s)" + (or rbrace "."))) TeX-left-right-braces + nil nil nil nil (or rbrace "."))))))) + +(defun LaTeX--find-preceding-left-macro-name () + "Return the left macro name just before the point, if any. +If the preceding macro isn't left macros such as \\left, \\bigl etc., +return nil. +If the point is just after unescaped `TeX-esc', return the null string." + ;; \left-!- => "left" + ;; \-!- => "" + ;; \infty-!- => nil + ;; \&-!- => nil + ;; \mathrm{abc}-!- => nil + ;; {blah blah blah}-!- => nil + ;; \\-!- => nil + (let ((name (buffer-substring-no-properties + (point) + ;; This is only a helper function, so we do not + ;; preserve point by save-excursion. + (progn + ;; Assume left macro names consist of only A-Z and a-z. + (skip-chars-backward "A-Za-z") + (point))))) + (if (and (TeX-escaped-p) + (or (string= name "") + (assoc name LaTeX-left-right-macros-association))) + name))) +(define-obsolete-function-alias + 'LaTeX-find-preceeding-left-macro-name + #'LaTeX--find-preceding-left-macro-name "AUCTeX 12.2" + "Compatibility function for typo in its name.") + +(defcustom LaTeX-default-author 'user-full-name + "Initial input to `LaTeX-arg-author' prompt. +If nil, do not prompt at all." + :group 'LaTeX-macro + :type '(choice (const :tag "User name in Emacs" user-full-name) + (const :tag "Do not prompt" nil) + string)) + +(defun LaTeX-arg-author (optional &optional prompt) + "Prompt for author name. +Insert the given value as a TeX macro argument. If OPTIONAL is +non-nil, insert it as an optional argument. Use PROMPT as the +prompt string. `LaTeX-default-author' is the initial input." + (let ((author (if LaTeX-default-author + (TeX-read-string + (TeX-argument-prompt optional prompt "Author(s)") + (if (symbolp LaTeX-default-author) + (symbol-value LaTeX-default-author) + LaTeX-default-author)) + ""))) + (TeX-argument-insert author optional nil))) + +(defun TeX-read-key-val (optional key-val-alist &optional prompt) + "Prompt for keys and values in KEY-VAL-ALIST and return them. +If OPTIONAL is non-nil, indicate in the prompt that we are +reading an optional argument. KEY-VAL-ALIST is an alist. The +car of each element should be a string representing a key and the +optional cdr should be a list with strings to be used as values +for the key. KEY-VAL-ALIST can be a symbol or a function call +returning an alist. Use PROMPT as the prompt string." + (multi-prompt-key-value + (TeX-argument-prompt optional prompt "Options (k=v)") + (cond ((and (symbolp key-val-alist) + (boundp key-val-alist)) + (symbol-value key-val-alist)) + ((and (listp key-val-alist) + (symbolp (car key-val-alist)) + (fboundp (car key-val-alist))) + (let ((head (car key-val-alist)) + (tail (cdr key-val-alist))) + (apply head tail))) + (t + key-val-alist)))) + +(defun TeX-arg-key-val (optional key-val-alist &optional prompt) + "Prompt for keys and values in KEY-VAL-ALIST. +Insert the given value as a TeX macro argument. If OPTIONAL is +non-nil, insert it as an optional argument. KEY-VAL-ALIST is an +alist. The car of each element should be a string representing a +key and the optional cdr should be a list with strings to be used +as values for the key. Use PROMPT as the prompt string." + (let ((options (TeX-read-key-val optional key-val-alist prompt))) + (TeX-argument-insert options optional))) + +(defun TeX-read-hook () + "Read a LaTeX hook and return it as a string." + (let* ((hook (completing-read + (TeX-argument-prompt nil nil "Hook") + '("cmd" + "env" + ;; From ltfilehook-doc.pdf + "file" "include" "class" "package" + ;; From lthooks-doc.pdf + "begindocument" "enddocument" + "rmfamily" "sffamily" + "ttfamily" "normalfont" + "bfseries" "mdseries" + ;; From ltshipout-doc.pdf + "shipout" + ;; From ltpara-doc.pdf + "para"))) + (place (lambda (&optional opt pr) + (completing-read + (TeX-argument-prompt opt pr "Where") + (cond ((member hook '("env" "para")) + '("after" "before" "begin" "end")) + ((string= hook "include") + '("after" "before" "end" "excluded")) + ((string= hook "begindocument") + '("before" "end")) + ((string= hook "enddocument") + '("afterlastpage" "afteraux" "info" "end")) + ((member hook '("bfseries" "mdseries")) + '("defaults")) + ((string= hook "shipout") + '("before" "after" + "foreground" "background" + "firstpage" "lastpage")) + (t + '("after" "before")))))) + (search (lambda () + (if (eq TeX-arg-input-file-search 'ask) + (not (y-or-n-p "Find file yourself? ")) + TeX-arg-input-file-search))) + name where files) + (cond ((string= hook "cmd") + ;; cmd//: is one of (before|after) + (setq name (completing-read + (TeX-argument-prompt nil nil "Command") + (TeX-symbol-list))) + (setq where (funcall place))) + + ;; env//: is one of (before|after|begin|end) + ((string= hook "env") + (setq name (completing-read + (TeX-argument-prompt nil nil "Environment") + (LaTeX-environment-list))) + (setq where (funcall place))) + + ;; file//: is optional and + ;; must be with extension and is one of + ;; (before|after) + ((string= hook "file") + (if (funcall search) + (progn + (unless TeX-global-input-files-with-extension + (setq TeX-global-input-files-with-extension + (prog2 + (message "Searching for files...") + (mapcar #'list + (TeX-search-files-by-type 'texinputs + 'global + t nil)) + (message "Searching for files...done")))) + (setq name + (completing-read + (TeX-argument-prompt t nil "File") + TeX-global-input-files-with-extension))) + (setq name + (file-name-nondirectory + (read-file-name + (TeX-argument-prompt t nil "File") + nil "")))) + (setq where (funcall place))) + + ;; include//: is optional and + ;; is one of (before|after|end|excluded) + ((string= hook "include") + (if (funcall search) + (progn + (setq files + (prog2 + (message "Searching for files...") + ;; \include looks for files with TeX content, + ;; so limit the search: + (let* ((TeX-file-extensions '("tex" "ltx"))) + (TeX-search-files-by-type 'texinputs 'local t t)) + (message "Searching for files...done"))) + (setq name (completing-read + (TeX-argument-prompt t nil "File") + files))) + (setq name + (file-name-base + (read-file-name + (TeX-argument-prompt t nil "File") + nil "")))) + (setq where (funcall place))) + + ;; class//: is optional and + ;; is one of (before|after) + ((string= hook "class") + (if (funcall search) + (progn + (unless LaTeX-global-class-files + (setq LaTeX-global-class-files + (prog2 + (message "Searching for LaTeX classes...") + (let* ((TeX-file-extensions '("cls"))) + (mapcar #'list + (TeX-search-files-by-type 'texinputs + 'global + t t))) + (message "Searching for LaTeX classes...done")))) + (setq name (completing-read + (TeX-argument-prompt t nil "Document class") + LaTeX-global-class-files))) + (setq name + (file-name-base + (read-file-name + (TeX-argument-prompt t nil "Document class") + nil "")))) + (setq where (funcall place))) + + ;; package//: is optional and + ;; is one of (before|after) + ((string= hook "package") + (if (funcall search) + (progn + (unless LaTeX-global-package-files + (setq LaTeX-global-package-files + (prog2 + (message "Searching for LaTeX packages...") + (let* ((TeX-file-extensions '("sty"))) + (mapcar #'list + (TeX-search-files-by-type 'texinputs + 'global + t t))) + (message "Searching for LaTeX packages...done")))) + (setq name (completing-read + (TeX-argument-prompt t nil "Package") + LaTeX-global-package-files))) + (setq name (file-name-base + (read-file-name + (TeX-argument-prompt t nil "Package") + nil "")))) + (setq where (funcall place))) + + ;; begindocument/: is empty or one of + ;; (before|end) + ((string= hook "begindocument") + (setq where (funcall place t))) + + ;; enddocument/: is empty or one of + ;; (afterlastpage|afteraux|info|end) + ((string= hook "enddocument") + (setq where (funcall place t))) + + ;; bfseries|mdseries/: is empty or defaults + ((member hook '("bfseries" "mdseries")) + (setq where (funcall place t))) + + ;; shipout/: is one of + ;; (before|after|foreground|background|firstpage|lastpage) + ((string= hook "shipout") + (setq where (funcall place))) + + ;; Other hooks or user specific input, do nothing: + (t nil)) + + ;; Process the input: Concat the given parts and return it + (concat hook + (when (and name (not (string= name ""))) + (concat "/" name)) + (when (and where (not (string= where ""))) + (concat "/" where))))) + +(defun TeX-arg-hook (optional) + "Prompt for a LaTeX hook. +Insert the given hook as a TeX macro argument. If OPTIONAL is +non-nil, insert it as an optional argument." + (TeX-argument-insert (TeX-read-hook) optional)) + +;;; Verbatim constructs + +(defcustom LaTeX-verbatim-macros-with-delims + '("verb" "verb*") + "Macros for inline verbatim with arguments in delimiters, like \\foo|...|. + +Programs should not use this variable directly but the function +`LaTeX-verbatim-macros-with-delims' which returns a value +including buffer-local keyword additions via +`LaTeX-verbatim-macros-with-delims-local' as well." + :group 'LaTeX-macro + :type '(repeat (string))) + +(defvar LaTeX-verbatim-macros-with-delims-local nil + "Buffer-local variable for inline verbatim with args in delimiters. + +Style files should add constructs to this variable and not to +`LaTeX-verbatim-macros-with-delims'. + +Programs should not use this variable directly but the function +`LaTeX-verbatim-macros-with-delims' which returns a value +including values of the variable +`LaTeX-verbatim-macros-with-delims' as well.") +(make-variable-buffer-local 'LaTeX-verbatim-macros-with-delims-local) +(put 'LaTeX-verbatim-macros-with-delims-local 'safe-local-variable + #'TeX--list-of-string-p) + + +(defcustom LaTeX-verbatim-macros-with-braces nil + "Macros for inline verbatim with arguments in braces, like \\foo{...}. + +Programs should not use this variable directly but the function +`LaTeX-verbatim-macros-with-braces' which returns a value +including buffer-local keyword additions via +`LaTeX-verbatim-macros-with-braces-local' as well." + :group 'LaTeX-macro + :type '(repeat (string))) + +(defvar LaTeX-verbatim-macros-with-braces-local nil + "Buffer-local variable for inline verbatim with args in braces. + +Style files should add constructs to this variable and not to +`LaTeX-verbatim-macros-with-braces'. + +Programs should not use this variable directly but the function +`LaTeX-verbatim-macros-with-braces' which returns a value +including values of the variable +`LaTeX-verbatim-macros-with-braces' as well.") +(make-variable-buffer-local 'LaTeX-verbatim-macros-with-braces-local) +(put 'LaTeX-verbatim-macros-with-braces-local 'safe-local-variable + #'TeX--list-of-string-p) + +(defcustom LaTeX-verbatim-environments + '("verbatim" "verbatim*" "filecontents" "filecontents*") + "Verbatim environments. + +Programs should not use this variable directly but the function +`LaTeX-verbatim-environments' which returns a value including +buffer-local keyword additions via +`LaTeX-verbatim-environments-local' as well." + :group 'LaTeX-environment + :type '(repeat (string))) + +(defvar LaTeX-verbatim-environments-local nil + "Buffer-local variable for verbatim environments. + +Style files should add constructs to this variable and not to +`LaTeX-verbatim-environments'. + +Programs should not use this variable directly but the function +`LaTeX-verbatim-environments' which returns a value including +values of the variable `LaTeX-verbatim-environments' as well.") +(make-variable-buffer-local 'LaTeX-verbatim-environments-local) +(put 'LaTeX-verbatim-environments-local 'safe-local-variable + #'TeX--list-of-string-p) + +(defun LaTeX-verbatim-macros-with-delims () + "Return list of verbatim macros with delimiters." + (append LaTeX-verbatim-macros-with-delims + LaTeX-verbatim-macros-with-delims-local)) + +(defun LaTeX-verbatim-macros-with-braces () + "Return list of verbatim macros with braces." + (append LaTeX-verbatim-macros-with-braces + LaTeX-verbatim-macros-with-braces-local)) + +(defun LaTeX-verbatim-environments () + "Return list of verbatim environments." + (append LaTeX-verbatim-environments + LaTeX-verbatim-environments-local)) + +(defun LaTeX-verbatim-macro-boundaries () + "Return boundaries of verbatim macro. +Boundaries are returned as a cons cell where the car is the macro +start and the cdr the macro end. + +Only macros which enclose their arguments with special +non-parenthetical delimiters, like \\verb+foo+, are recognized." + (save-excursion + (let ((orig (point)) + (verbatim-regexp (regexp-opt (LaTeX-verbatim-macros-with-delims) t))) + ;; Search backwards for the macro start, unless we are facing one + (unless (looking-at (concat (regexp-quote TeX-esc) verbatim-regexp)) + (catch 'found + (while (progn + (skip-chars-backward (concat "^\n" (regexp-quote TeX-esc)) + (line-beginning-position)) + (when (looking-at verbatim-regexp) (throw 'found nil)) + (or (bobp) (forward-char -1)) + (/= (point) (line-beginning-position)))))) + ;; Search forward for the macro end, unless we failed to find a start + (unless (bolp) + (let* ((beg (1- (point))) + (macro-end (match-end 0)) + ;; XXX: Here we assume we are dealing with \verb which + ;; expects the delimiter right behind the command. + ;; However, \lstinline can also cope with whitespace as + ;; well as an optional argument after the command. + (delimiter (buffer-substring-no-properties + macro-end (1+ macro-end)))) + ;; Heuristic: If an opening brace is encountered, search for + ;; both the opening and the closing brace as an end marker. + ;; Like that the function should work for \verb|...| as well + ;; as for \url{...}. + (when (string= delimiter TeX-grop) + (setq delimiter (concat delimiter TeX-grcl))) + (goto-char (1+ macro-end)) + (skip-chars-forward (concat "^" delimiter)) + (when (<= orig (point)) + (cons beg (1+ (point))))))))) + +(defun LaTeX-current-verbatim-macro () + "Return name of verbatim macro containing point, nil if none is present." + (let ((macro-boundaries (LaTeX-verbatim-macro-boundaries))) + (when macro-boundaries + (save-excursion + (goto-char (car macro-boundaries)) + (forward-char (length TeX-esc)) + (buffer-substring-no-properties + (point) (progn (skip-chars-forward "@A-Za-z*") (point))))))) + +(defun LaTeX-verbatim-p (&optional pos) + "Return non-nil if position POS is in a verbatim-like construct." + (when pos (goto-char pos)) + (save-match-data + (or (when (fboundp 'font-latex-faces-present-p) + (font-latex-faces-present-p 'font-latex-verbatim-face)) + (member (LaTeX-current-verbatim-macro) + (LaTeX-verbatim-macros-with-delims)) + (member (TeX-current-macro) (LaTeX-verbatim-macros-with-braces)) + (member (LaTeX-current-environment) (LaTeX-verbatim-environments))))) + + +;;; Formatting + +(defcustom LaTeX-syntactic-comments t + "If non-nil comments will be handled according to LaTeX syntax. +This variable influences, among others, the behavior of +indentation and filling which will take LaTeX syntax into +consideration just as is in the non-commented source code." + :type 'boolean + :group 'LaTeX) + + +;;; Indentation + +;; We are distinguishing two different types of comments: +;; +;; 1) Comments starting in column one (line comments) +;; +;; 2) Comments starting after column one with only whitespace +;; preceding it. +;; +;; (There is actually a third type: Comments preceded not only by +;; whitespace but by some code as well; so-called code comments. But +;; they are not relevant for the following explanations.) +;; +;; Additionally we are distinguishing two different types of +;; indentation: +;; +;; a) Outer indentation: Indentation before the comment character(s). +;; +;; b) Inner indentation: Indentation after the comment character(s) +;; (taking into account possible comment padding). +;; +;; Comments can be filled syntax-aware or not. +;; +;; In `doctex-mode' line comments should always be indented +;; syntax-aware and the comment character has to be anchored at the +;; first column (unless the appear in a macrocode environment). Other +;; comments not in the documentation parts always start after the +;; first column and can be indented syntax-aware or not. If they are +;; indented syntax-aware both the indentation before and after the +;; comment character(s) have to be checked and adjusted. Indentation +;; should not move the comment character(s) to the first column. With +;; `LaTeX-syntactic-comments' disabled, line comments should still be +;; indented syntax-aware. +;; +;; In `latex-mode' comments starting in different columns don't have +;; to be handled differently. They don't have to be anchored in +;; column one. That means that in any case indentation before and +;; after the comment characters has to be checked and adjusted. + +(defgroup LaTeX-indentation nil + "Indentation of LaTeX code in AUCTeX" + :group 'LaTeX + :group 'TeX-indentation) + +(defcustom LaTeX-indent-level 2 + "Indentation of begin-end blocks in LaTeX." + :group 'LaTeX-indentation + :type 'integer) + +(defcustom LaTeX-item-indent (- LaTeX-indent-level) + "Extra indentation for lines beginning with an item." + :group 'LaTeX-indentation + :type 'integer) + +(defcustom LaTeX-item-regexp "\\(bib\\)?item\\b" + "Regular expression matching macros considered items." + :group 'LaTeX-indentation + :type 'regexp) + +(defcustom LaTeX-indent-environment-list + '(("verbatim" current-indentation) + ("verbatim*" current-indentation) + ("filecontents" current-indentation) + ("filecontents*" current-indentation) + ("tabular" LaTeX-indent-tabular) + ("tabular*" LaTeX-indent-tabular) + ("array" LaTeX-indent-tabular) + ("eqnarray" LaTeX-indent-tabular) + ("eqnarray*" LaTeX-indent-tabular) + ;; envs of amsmath.sty + ("align" LaTeX-indent-tabular) + ("align*" LaTeX-indent-tabular) + ("aligned" LaTeX-indent-tabular) + ("alignat" LaTeX-indent-tabular) + ("alignat*" LaTeX-indent-tabular) + ("alignedat" LaTeX-indent-tabular) + ("xalignat" LaTeX-indent-tabular) + ("xalignat*" LaTeX-indent-tabular) + ("xxalignat" LaTeX-indent-tabular) + ("flalign" LaTeX-indent-tabular) + ("flalign*" LaTeX-indent-tabular) + ("split" LaTeX-indent-tabular) + ("matrix" LaTeX-indent-tabular) + ("pmatrix" LaTeX-indent-tabular) + ("bmatrix" LaTeX-indent-tabular) + ("Bmatrix" LaTeX-indent-tabular) + ("vmatrix" LaTeX-indent-tabular) + ("Vmatrix" LaTeX-indent-tabular) + ("smallmatrix" LaTeX-indent-tabular) + ("cases" LaTeX-indent-tabular) + ;; envs of mathtools.sty + ("matrix*" LaTeX-indent-tabular) + ("pmatrix*" LaTeX-indent-tabular) + ("bmatrix*" LaTeX-indent-tabular) + ("Bmatrix*" LaTeX-indent-tabular) + ("vmatrix*" LaTeX-indent-tabular) + ("Vmatrix*" LaTeX-indent-tabular) + ("smallmatrix*" LaTeX-indent-tabular) + ("psmallmatrix" LaTeX-indent-tabular) + ("psmallmatrix*" LaTeX-indent-tabular) + ("bsmallmatrix" LaTeX-indent-tabular) + ("bsmallmatrix*" LaTeX-indent-tabular) + ("vsmallmatrix" LaTeX-indent-tabular) + ("vsmallmatrix*" LaTeX-indent-tabular) + ("Vsmallmatrix" LaTeX-indent-tabular) + ("Vsmallmatrix*" LaTeX-indent-tabular) + ("dcases" LaTeX-indent-tabular) + ("dcases*" LaTeX-indent-tabular) + ("rcases" LaTeX-indent-tabular) + ("rcases*" LaTeX-indent-tabular) + ("drcases" LaTeX-indent-tabular) + ("drcases*" LaTeX-indent-tabular) + ("cases*" LaTeX-indent-tabular) + ;; The following should have their own, smart indentation function. + ;; Some other day. + ("displaymath") + ("equation") + ("picture") + ("tabbing") + ;; envs from amsmath.sty + ("gather") ("gather*") ("gathered") + ("equation*") ("multline") ("multline*") + ;; envs from doc.sty + ("macrocode") ("macrocode*")) + "Alist of environments with special indentation. +The second element in each entry is the function to calculate the +indentation level in columns. + +Environments present in this list are not filled by filling +functions, see `LaTeX-fill-region-as-paragraph'." + :group 'LaTeX-indentation + :type '(repeat (list (string :tag "Environment") + (option function)))) + +(defcustom LaTeX-indent-environment-check t + "If non-nil, check for any special environments." + :group 'LaTeX-indentation + :type 'boolean) + +(defcustom LaTeX-document-regexp "document" + "Regexp matching environments in which the indentation starts at col 0." + :group 'LaTeX-indentation + :type 'regexp) + +(defcustom LaTeX-begin-regexp "begin\\b\\|\\[" + "Regexp matching macros considered begins." + :group 'LaTeX-indentation + :type 'regexp) + +(defcustom LaTeX-end-regexp "end\\b\\|\\]" + "Regexp matching macros considered ends." + :group 'LaTeX-indentation + :type 'regexp) + +(defcustom LaTeX-left-right-indent-level LaTeX-indent-level + "The level of indentation produced by a \\left macro." + :group 'LaTeX-indentation + :type 'integer) + +(defcustom LaTeX-indent-comment-start-regexp "%" + "Regexp matching comments ending the indent level count. +This means, we just count the LaTeX tokens \\left, \\right, \\begin, +and \\end up to the first occurence of text matching this regexp. +Thus, the default \"%\" stops counting the tokens at a comment. A +value of \"%[^>]\" would allow you to alter the indentation with +comments, for example with comment `%> \\begin'. +Lines which start with `%' are not considered at all, regardless of this +value." + :group 'LaTeX-indentation + :type 'regexp) + +(defvar docTeX-indent-inner-fixed + `((,(concat (regexp-quote TeX-esc) + "\\(begin\\|end\\)[ \t]*{macrocode\\*?}") + 4 t) + (,(concat (regexp-quote TeX-esc) + "\\(begin\\|end\\)[ \t]*{\\(macro\\|environment\\)\\*?}") + 0 nil)) + "List of items which should have a fixed inner indentation. +The items consist of three parts. The first is a regular +expression which should match the respective string. The second +is the amount of spaces to be used for indentation. The third +toggles if comment padding is relevant or not. If t padding is +part of the amount given, if nil the amount of spaces will be +inserted after potential padding.") + +(defvar-local LaTeX-indent-begin-list nil + "List of macros increasing indentation. +Each item in this list is a string with the name of the macro +without a backslash. The final regexp will be calculated by the +function `LaTeX-indent-commands-regexp-make'. A regexp for the +\\if contructs is added by the function as well. AUCTeX styles +should add their macros to this variable and then run +`LaTeX-indent-commands-regexp-make'.") + +(defvar-local LaTeX-indent-begin-exceptions-list nil + "List of macros which shouldn't increase the indentation. +Each item in this list is a string without a backslash and will +mostly start with 'if'. These macros should not increase +indentation although they start with 'if', for example the +'ifthenelse' macro provided by the ifthen package. AUCTeX styles +should add their macros to this variable and then run +`LaTeX-indent-commands-regexp-make'.") + +(defvar-local LaTeX-indent-mid-list nil + "List of macros which backindent the line where they appear. +Each item in this list is a string with the name of the macro +without a backslash. The final regexp will be calculated by the +function `LaTeX-indent-commands-regexp-make' which takes care of +\\else and \\or. AUCTeX styles should add their macros to this +variable and then run `LaTeX-indent-commands-regexp-make'.") + +(defvar-local LaTeX-indent-end-list nil + "List of macros decreasing indentation. +Each item in this list is a string with the name of the macro +without a backslash. The final regexp will be calculated by the +function `LaTeX-indent-commands-regexp-make' which takes care of +\\fi. AUCTeX styles should add their macros to this variable and +then run `LaTeX-indent-commands-regexp-make'.") + +(defvar-local LaTeX-indent-begin-regexp-local nil + "Regexp calculated from `LaTeX-indent-begin-list'. +The value is calculated and set by the function +`LaTeX-indent-commands-regexp-make' which already takes care of +\\if constructs.") + +(defvar-local LaTeX-indent-begin-regexp-exceptions-local nil + "Regexp calculated from `LaTeX-indent-begin-exceptions-list'. +The value is calculated and set by the function +`LaTeX-indent-commands-regexp-make' which already takes care of +\\ifthenelse.") + +(defvar-local LaTeX-indent-mid-regexp-local nil + "Regexp calculated from `LaTeX-indent-mid-list'. +The value is calculated and set by the function +`LaTeX-indent-commands-regexp-make' which already takes care of +\\else and \\or.") + +(defvar-local LaTeX-indent-end-regexp-local nil + "Regexp calculated from `LaTeX-indent-end-list'. +The value is calculated and set by the function +`LaTeX-indent-commands-regexp-make' which already takes care of +\\fi.") + +(defun LaTeX-indent-commands-regexp-make () + "Calculate final regexp for adjusting indentation. +This function takes the elements provided in +`LaTeX-indent-begin-list', `LaTeX-indent-begin-exceptions-list', +`LaTeX-indent-mid-list' and `LaTeX-indent-end-list' and generates +the regexp's which are stored in +`LaTeX-indent-begin-regexp-local', +`LaTeX-indent-begin-regexp-exceptions-local', +`LaTeX-indent-mid-regexp-local' and +`LaTeX-indent-end-regexp-local' accordingly. Some standard +macros are added to the regexp's. This function is called in +`LaTeX-common-initialization' to set the regexp's." + (let* (cmds + symbs + (func (lambda (in regexp out) + (setq cmds nil + symbs nil) + (dolist (elt in) + (if (string-match "[^a-zA-Z@]" elt) + (push elt symbs) + (push elt cmds))) + (set out (concat regexp + (when cmds + (concat "\\|" + (regexp-opt cmds) + "\\b")) + (when symbs + (concat "\\|" + (regexp-opt symbs)))))))) + (funcall func + LaTeX-indent-begin-list + "if[a-zA-Z@]*\\b" + 'LaTeX-indent-begin-regexp-local) + (funcall func + LaTeX-indent-mid-list + "else\\b\\|or\\b" + 'LaTeX-indent-mid-regexp-local) + (funcall func + LaTeX-indent-end-list + "fi\\b" + 'LaTeX-indent-end-regexp-local) + (funcall func + LaTeX-indent-begin-exceptions-list + "ifthenelse\\b" + 'LaTeX-indent-begin-regexp-exceptions-local))) + +(defun LaTeX-indent-line () + "Indent the line containing point, as LaTeX source. +Add `LaTeX-indent-level' indentation in each \\begin{ - \\end{ block. +Lines starting with an item is given an extra indentation of +`LaTeX-item-indent'." + (interactive) + (let* ((case-fold-search nil) + ;; Compute a fill prefix. Whitespace after the comment + ;; characters will be disregarded and replaced by + ;; `comment-padding'. + (fill-prefix + (and (TeX-in-commented-line) + (save-excursion + (beginning-of-line) + (looking-at + (concat "\\([ \t]*" TeX-comment-start-regexp "+\\)+")) + (concat (match-string 0) (TeX-comment-padding-string)))))) + (save-excursion + (cond ((and fill-prefix + (TeX-in-line-comment) + (eq major-mode 'doctex-mode)) + ;; If point is in a line comment in `doctex-mode' we only + ;; consider the inner indentation. + (let ((inner-indent (LaTeX-indent-calculate 'inner))) + (when (/= (LaTeX-current-indentation 'inner) inner-indent) + (LaTeX-indent-inner-do inner-indent)))) + ((and fill-prefix + LaTeX-syntactic-comments) + ;; In any other case of a comment we have to consider + ;; outer and inner indentation if we do syntax-aware + ;; indentation. + (let ((inner-indent (LaTeX-indent-calculate 'inner)) + (outer-indent (LaTeX-indent-calculate 'outer))) + (when (/= (LaTeX-current-indentation 'inner) inner-indent) + (LaTeX-indent-inner-do inner-indent)) + (when (/= (LaTeX-current-indentation 'outer) outer-indent) + (LaTeX-indent-outer-do outer-indent)))) + (t + ;; The default is to adapt whitespace before any + ;; non-whitespace character, i.e. to do outer + ;; indentation. + (let ((outer-indent (LaTeX-indent-calculate 'outer))) + (when (/= (LaTeX-current-indentation 'outer) outer-indent) + (LaTeX-indent-outer-do outer-indent)))))) + (when (< (current-column) (save-excursion + (LaTeX-back-to-indentation) (current-column))) + (LaTeX-back-to-indentation)))) + +(defun LaTeX-indent-inner-do (inner-indent) + ;; Small helper function for `LaTeX-indent-line' to perform + ;; indentation after a comment character. It requires that + ;; `LaTeX-indent-line' already set the appropriate variables and + ;; should not be used outside of `LaTeX-indent-line'. + (move-to-left-margin) + (TeX-re-search-forward-unescaped + (concat "\\(" TeX-comment-start-regexp "+[ \t]*\\)+") (line-end-position) t) + (delete-region (line-beginning-position) (point)) + (insert fill-prefix) + (indent-to (+ inner-indent (length fill-prefix)))) + +(defun LaTeX-indent-outer-do (outer-indent) + ;; Small helper function for `LaTeX-indent-line' to perform + ;; indentation of normal lines or before a comment character in a + ;; commented line. It requires that `LaTeX-indent-line' already set + ;; the appropriate variables and should not be used outside of + ;; `LaTeX-indent-line'. + (back-to-indentation) + (delete-region (line-beginning-position) (point)) + (indent-to outer-indent)) + +(defun LaTeX-verbatim-regexp (&optional comment) + "Calculate the verbatim env regex from `LaTeX-verbatim-environments'. +If optional argument COMMENT is non-nil, include comment env from +`LaTeX-comment-env-list'." + (regexp-opt (append (LaTeX-verbatim-environments) + (if comment LaTeX-comment-env-list)))) + +(defun LaTeX-indent-calculate (&optional force-type) + "Return the indentation of a line of LaTeX source. +FORCE-TYPE can be used to force the calculation of an inner or +outer indentation in case of a commented line. The symbols +`inner' and `outer' are recognized." + (save-excursion + (LaTeX-back-to-indentation force-type) + (let ((i 0) + (list-length (safe-length docTeX-indent-inner-fixed)) + (case-fold-search nil) + entry + found) + (cond ((save-excursion (beginning-of-line) (bobp)) 0) + ((and (eq major-mode 'doctex-mode) + fill-prefix + (TeX-in-line-comment) + (progn + (while (and (< i list-length) + (not found)) + (setq entry (nth i docTeX-indent-inner-fixed)) + (when (looking-at (nth 0 entry)) + (setq found t)) + (setq i (1+ i))) + found)) + (if (nth 2 entry) + (- (nth 1 entry) (if (integerp comment-padding) + comment-padding + (length comment-padding))) + (nth 1 entry))) + ((looking-at (concat (regexp-quote TeX-esc) + "\\(begin\\|end\\){" + (LaTeX-verbatim-regexp t) + "}")) + ;; \end{verbatim} must be flush left, otherwise an unwanted + ;; empty line appears in LaTeX's output. + 0) + ((and LaTeX-indent-environment-check + ;; Special environments. + (let ((entry (assoc (or LaTeX-current-environment + (LaTeX-current-environment)) + LaTeX-indent-environment-list))) + (and entry + (nth 1 entry) + (funcall (nth 1 entry)))))) + ((looking-at (concat (regexp-quote TeX-esc) + "\\(" + LaTeX-end-regexp + "\\)")) + ;; Backindent at \end. + (- (LaTeX-indent-calculate-last force-type) LaTeX-indent-level)) + ((looking-at (concat (regexp-quote TeX-esc) "right\\b")) + ;; Backindent at \right. + (- (LaTeX-indent-calculate-last force-type) + LaTeX-left-right-indent-level)) + ((looking-at (concat (regexp-quote TeX-esc) + "\\(" + LaTeX-item-regexp + "\\)")) + ;; Items. + (+ (LaTeX-indent-calculate-last force-type) LaTeX-item-indent)) + ;; Other (La)TeX programming constructs which end + ;; something, \fi for example where we backindent: + ((looking-at (concat (regexp-quote TeX-esc) + "\\(" + LaTeX-indent-end-regexp-local + "\\)")) + (- (LaTeX-indent-calculate-last force-type) LaTeX-indent-level)) + ;; (La)TeX programming contructs which backindent only the + ;; current line, for example \or or \else where we backindent: + ((looking-at (concat (regexp-quote TeX-esc) + "\\(" + LaTeX-indent-mid-regexp-local + "\\)")) + (- (LaTeX-indent-calculate-last force-type) LaTeX-indent-level)) + ((memq (char-after) (append + TeX-indent-close-delimiters '(?\}))) + ;; End brace in the start of the line. + (- (LaTeX-indent-calculate-last force-type) + TeX-brace-indent-level)) + (t (LaTeX-indent-calculate-last force-type)))))) + +(defun LaTeX-indent-level-count () + "Count indentation change caused by macros in the current line. +Macros contain \\left, \\right, \\begin, \\end and \\if-\\fi +constructs. A special case is \\newif where the following +\\if should not change the indentation." + (save-excursion + (save-restriction + (let ((count 0)) + (narrow-to-region (point) + (save-excursion + (re-search-forward + (concat "[^" TeX-esc "]" + "\\(" LaTeX-indent-comment-start-regexp + "\\)\\|\n\\|\\'")) + (backward-char) + (point))) + (while (search-forward TeX-esc nil t) + (cond + ((looking-at "left\\b") + (setq count (+ count LaTeX-left-right-indent-level))) + ((looking-at "right\\b") + (setq count (- count LaTeX-left-right-indent-level))) + ((looking-at LaTeX-begin-regexp) + (setq count (+ count LaTeX-indent-level))) + ((looking-at LaTeX-end-regexp) + (setq count (- count LaTeX-indent-level))) + ((looking-at "newif\\b") + (search-forward TeX-esc (line-end-position) t)) + ((and (not (looking-at LaTeX-indent-begin-regexp-exceptions-local)) + (looking-at LaTeX-indent-begin-regexp-local)) + (setq count (+ count LaTeX-indent-level))) + ((looking-at LaTeX-indent-end-regexp-local) + (setq count (- count LaTeX-indent-level))) + ((looking-at (regexp-quote TeX-esc)) + (forward-char 1)))) + count)))) + +(defun LaTeX-indent-calculate-last (&optional force-type) + "Return the correct indentation of a normal line of text. +The point is supposed to be at the beginning of the current line. +FORCE-TYPE can be used to force the calculation of an inner or +outer indentation in case of a commented line. The symbols +`inner' and `outer' are recognized." + (let (line-comment-current-flag + line-comment-last-flag + comment-current-flag + comment-last-flag) + (beginning-of-line) + (setq line-comment-current-flag (TeX-in-line-comment) + comment-current-flag (TeX-in-commented-line)) + (if comment-current-flag + (skip-chars-backward "%\n\t ") + (skip-chars-backward "\n\t ")) + (beginning-of-line) + ;; If we are called in a non-comment line, skip over comment + ;; lines. The computation of indentation should in this case + ;; rather take the last non-comment line into account. + ;; Otherwise there might arise problems with e.g. multi-line + ;; code comments. This behavior is not enabled in docTeX mode + ;; where large amounts of line comments may have to be skipped + ;; and indentation should not be influenced by unrelated code in + ;; other macrocode environments. + (while (and (not (eq major-mode 'doctex-mode)) + (not comment-current-flag) + (TeX-in-commented-line) + (not (bobp))) + (skip-chars-backward "\n\t ") + (beginning-of-line)) + (setq line-comment-last-flag (TeX-in-line-comment) + comment-last-flag (TeX-in-commented-line)) + (LaTeX-back-to-indentation force-type) + ;; Separate line comments and other stuff (normal text/code and + ;; code comments). Additionally we don't want to compute inner + ;; indentation when a commented and a non-commented line are + ;; compared. + (cond ((or (and (eq major-mode 'doctex-mode) + (or (and line-comment-current-flag + (not line-comment-last-flag)) + (and (not line-comment-current-flag) + line-comment-last-flag))) + (and force-type + (eq force-type 'inner) + (or (and comment-current-flag + (not comment-last-flag)) + (and (not comment-current-flag) + comment-last-flag)))) + 0) + ((looking-at (concat (regexp-quote TeX-esc) + "begin *{\\(" + LaTeX-document-regexp + "\\)}")) + ;; I dislike having all of the document indented... + (+ (LaTeX-current-indentation force-type) + ;; Some people have opening braces at the end of the + ;; line, e.g. in case of `\begin{letter}{%'. + (TeX-brace-count-line))) + ((and (eq major-mode 'doctex-mode) + (looking-at (concat (regexp-quote TeX-esc) + "end[ \t]*{macrocode\\*?}")) + fill-prefix + (TeX-in-line-comment)) + ;; Reset indentation to zero after a macrocode environment + ;; only when we're not still inside a describing + ;; environment like "macro" or "environment" etc. Text + ;; inside these environments after '\end{macrocode}' is + ;; indented with `LaTeX-indent-level': + (let ((outer-env (LaTeX-current-environment 2))) + (cond ((member outer-env '("macro" "environment")) + LaTeX-indent-level) + ((and (fboundp 'LaTeX-doc-NewDocElement-list) + (LaTeX-doc-NewDocElement-list) + (member outer-env + (mapcar #'cadr (LaTeX-doc-NewDocElement-list)))) + LaTeX-indent-level) + (t 0)))) + ((looking-at (concat (regexp-quote TeX-esc) + "begin *{" + ;; Don't give optional argument here + ;; because indent would be disabled + ;; inside comment env otherwise. + (LaTeX-verbatim-regexp) + "}")) + 0) + ((looking-at (concat (regexp-quote TeX-esc) + "end *{" + (LaTeX-verbatim-regexp t) + "}")) + ;; If I see an \end{verbatim} in the previous line I skip + ;; back to the preceding \begin{verbatim}. + (save-excursion + (if (re-search-backward (concat (regexp-quote TeX-esc) + "begin *{" + (LaTeX-verbatim-regexp t) + "}") 0 t) + (LaTeX-indent-calculate-last force-type) + 0))) + (t (+ (LaTeX-current-indentation force-type) + (if (not (and force-type + (eq force-type 'outer) + (TeX-in-commented-line))) + (+ (LaTeX-indent-level-count) + (TeX-brace-count-line)) + 0) + (cond ((looking-at (concat (regexp-quote TeX-esc) + "\\(" + LaTeX-end-regexp + "\\)")) + LaTeX-indent-level) + ((looking-at + (concat (regexp-quote TeX-esc) "right\\b")) + LaTeX-left-right-indent-level) + ((looking-at (concat (regexp-quote TeX-esc) + "\\(" + LaTeX-item-regexp + "\\)")) + (- LaTeX-item-indent)) + ((looking-at (concat (regexp-quote TeX-esc) + "\\(" + LaTeX-indent-end-regexp-local + "\\)")) + LaTeX-indent-level) + ((looking-at (concat (regexp-quote TeX-esc) + "\\(" + LaTeX-indent-mid-regexp-local + "\\)")) + LaTeX-indent-level) + ((memq (char-after) (append + TeX-indent-close-delimiters + '(?\}))) + TeX-brace-indent-level) + (t 0))))))) + +(defun LaTeX-current-indentation (&optional force-type) + "Return the indentation of a line. +FORCE-TYPE can be used to force the calculation of an inner or +outer indentation in case of a commented line. The symbols +`inner' and `outer' are recognized." + (if (and fill-prefix + (or (and force-type + (eq force-type 'inner)) + (and (not force-type) + (or + ;; If `LaTeX-syntactic-comments' is not enabled, + ;; do conventional indentation + LaTeX-syntactic-comments + ;; Line comments in `doctex-mode' are always + ;; indented syntax-aware so we need their inner + ;; indentation. + (and (TeX-in-line-comment) + (eq major-mode 'doctex-mode)))))) + ;; INNER indentation + (save-excursion + (beginning-of-line) + (looking-at (concat "\\(?:[ \t]*" TeX-comment-start-regexp "+\\)+" + "\\([ \t]*\\)")) + (- (length (match-string 1)) (length (TeX-comment-padding-string)))) + ;; OUTER indentation + (current-indentation))) + +(defun LaTeX-back-to-indentation (&optional force-type) + "Move point to the first non-whitespace character on this line. +If it is commented and comments are formatted syntax-aware move +point to the first non-whitespace character after the comment +character(s), but only if `this-command' is not a newline +command, that is, `TeX-newline' or the value of +`TeX-newline-function'. The optional argument FORCE-TYPE can be +used to force point being moved to the inner or outer indentation +in case of a commented line. The symbols `inner' and `outer' are +recognized." + (if (or (and force-type + (eq force-type 'inner)) + (and (not force-type) + (or (and (TeX-in-line-comment) + (eq major-mode 'doctex-mode)) + (and (TeX-in-commented-line) + ;; Only move after the % if we're not + ;; performing a newline command (bug#47757). + (not (memq this-command + `( TeX-newline + ,TeX-newline-function))) + LaTeX-syntactic-comments)))) + (progn + (beginning-of-line) + ;; Should this be anchored at the start of the line? + (TeX-re-search-forward-unescaped + (concat "\\(?:" TeX-comment-start-regexp "+[ \t]*\\)+") + (line-end-position) t)) + (back-to-indentation))) + + +;;; Filling + +;; The default value should try not to break formulae across lines (this is +;; useful for preview-latex) and give a meaningful filling. +(defcustom LaTeX-fill-break-at-separators '(\\\( \\\[) + "List of separators before or after which respectively a line +break will be inserted if they do not fit into one line." + :group 'LaTeX + :type '(set :tag "Contents" + (const :tag "Opening Brace" \{) + (const :tag "Closing Brace" \}) + (const :tag "Opening Bracket" \[) + (const :tag "Opening Inline Math Switches" \\\() + (const :tag "Closing Inline Math Switches" \\\)) + (const :tag "Opening Display Math Switch" \\\[) + (const :tag "Closing Display Math Switch" \\\]))) + +(defcustom LaTeX-fill-break-before-code-comments t + "If non-nil, a line with some code followed by a comment will +be broken before the last non-comment word in case the comment +does not fit into the line." + :group 'LaTeX + :type 'boolean) + +(defcustom LaTeX-fill-excluded-macros nil + "List of macro names (without leading \\) whose arguments must +not be subject to filling." + :group 'LaTeX + :type '(repeat string)) + +(defvar LaTeX-nospace-between-char-regexp "\\c|" + "Regexp matching a character where no interword space is necessary. +Words formed by such characters can be broken across newlines.") + +(defvar LaTeX-fill-newline-hook nil + "Hook run after `LaTeX-fill-newline' inserted and indented a new line.") + +(defun LaTeX-fill-region-as-paragraph (from to &optional justify-flag) + "Fill region as one paragraph. +Break lines to fit `fill-column', but leave all lines ending with +\\\\ \(plus its optional argument) alone. Lines with code +comments and lines ending with `\\par' are included in filling but +act as boundaries. Prefix arg means justify too. From program, +pass args FROM, TO and JUSTIFY-FLAG. + +You can disable filling inside a specific environment by adding +it to `LaTeX-indent-environment-list', only indentation is +performed in that case." + (interactive "*r\nP") + (let ((end-marker (copy-marker to)) has-code-comment has-regexp-match) + (if (or (assoc (LaTeX-current-environment) LaTeX-indent-environment-list) + (member (TeX-current-macro) LaTeX-fill-excluded-macros) + ;; This could be generalized, if there are more cases where + ;; a special string at the start of a region to fill should + ;; inhibit filling. + (progn (save-excursion (goto-char from) + (looking-at (concat TeX-comment-start-regexp + "+[ \t]*" + "Local Variables:"))))) + ;; Filling disabled, only do indentation. + (indent-region from to nil) + ;; XXX: This `save-restriction' is a leftover of older codes and + ;; can now be removed. + (save-restriction + (goto-char from) + (while (< (point) end-marker) + ;; Code comments. + (catch 'found + (while (setq has-code-comment + (TeX-search-forward-comment-start end-marker)) + ;; See if there is at least one non-whitespace + ;; character before the comment starts. + (goto-char has-code-comment) + (skip-chars-backward " \t" (line-beginning-position)) + (if (not (bolp)) + ;; A real code comment. + (throw 'found t) + ;; Not a code comment. Continue the loop. + (forward-line 1) + (if (> (point) end-marker) + (goto-char end-marker))))) + + ;; Go back to the former point for the next regexp search. + (goto-char from) + + (when (setq has-regexp-match + (re-search-forward + (concat + "\\(" + ;; Lines ending with `\par'. + ;; XXX: Why exclude \n? vv + "\\(?:\\=\\|[^" TeX-esc "\n]\\)\\(?:" + (regexp-quote (concat TeX-esc TeX-esc)) + "\\)*" + (regexp-quote TeX-esc) "par[ \t]*" + ;; XXX: What's this "whitespaces in braces" ? + ;; vvvvvvvv + "\\(?:{[ \t]*}\\)?[ \t]*$" + "\\)\\|" + ;; Lines ending with `\\'. + ;; XXX: This matches a line ending with "\\\ ". + ;; Should we avoid such corner case? + (regexp-quote (concat TeX-esc TeX-esc)) + ;; XXX: Why not just "\\s-*\\*?" ? + "\\(?:\\s-*\\*\\)?" + ;; XXX: Why not "\\s-*\\(?:\\[[^]]*\\]\\)?" ? + "\\(?:\\s-*\\[[^]]*\\]\\)?" + "\\s-*$") + (or has-code-comment end-marker) t)) + ;; The regexp matched before the code comment (if any). + (setq has-code-comment nil)) + + ;; Here no need to go back to the former position because + ;; "ELSE" part of the following `if' doesn't rely on the + ;; current point. + ;; (goto-char from) + + (if (or has-code-comment has-regexp-match) + (progn + (goto-char (or has-code-comment has-regexp-match)) + (goto-char (line-end-position)) + (delete-horizontal-space) + ;; I doubt very much if we want justify - + ;; this is a line with \\ + ;; if you think otherwise - uncomment the next line + ;; (and justify-flag (justify-current-line)) + (forward-char) + ;; keep our position in a buffer + (save-excursion + ;; Code comments and lines ending with `\par' are + ;; included in filling. Lines ending with `\\' are + ;; skipped. + (if (or has-code-comment + (match-beginning 1)) + (LaTeX-fill-region-as-para-do from (point) justify-flag) + (LaTeX-fill-region-as-para-do + from (line-beginning-position 0) justify-flag) + ;; At least indent the line ending with `\\'. + (indent-according-to-mode))) + (setq from (point))) + ;; ELSE part follows - loop termination relies on a fact + ;; that (LaTeX-fill-region-as-para-do) moves point past + ;; the filled region + (LaTeX-fill-region-as-para-do from end-marker justify-flag))))) + (set-marker end-marker nil))) + +;; The content of `LaTeX-fill-region-as-para-do' was copied from the +;; function `fill-region-as-paragraph' in `fill.el' (CVS Emacs, +;; January 2004) and adapted to the needs of AUCTeX. + +(defun LaTeX-fill-region-as-para-do (from to &optional justify + nosqueeze squeeze-after) + "Fill the region defined by FROM and TO as one paragraph. +It removes any paragraph breaks in the region and extra newlines at the end, +indents and fills lines between the margins given by the +`current-left-margin' and `current-fill-column' functions. +\(In most cases, the variable `fill-column' controls the width.) +It leaves point at the beginning of the line following the paragraph. + +Normally performs justification according to the `current-justification' +function, but with a prefix arg, does full justification instead. + +From a program, optional third arg JUSTIFY can specify any type of +justification. Fourth arg NOSQUEEZE non-nil means not to make spaces +between words canonical before filling. Fifth arg SQUEEZE-AFTER, if non-nil, +means don't canonicalize spaces before that position. + +Return the `fill-prefix' used for filling. + +If `sentence-end-double-space' is non-nil, then period followed by one +space does not end a sentence, so don't break a line there." + (interactive (progn + (barf-if-buffer-read-only) + (list (region-beginning) (region-end) + (if current-prefix-arg 'full)))) + (unless (memq justify '(t nil none full center left right)) + (setq justify 'full)) + + ;; Make sure "to" is the endpoint. + (goto-char (min from to)) + (setq to (max from to)) + ;; Ignore blank lines at beginning of region. + (skip-chars-forward " \t\n") + + (let ((from-plus-indent (point)) + (oneleft nil)) + + (beginning-of-line) + (setq from (point)) + + ;; Delete all but one soft newline at end of region. + ;; And leave TO before that one. + (goto-char to) + (while (and (> (point) from) (eq ?\n (char-after (1- (point))))) + (if (and oneleft + (not (and use-hard-newlines + (get-text-property (1- (point)) 'hard)))) + (delete-char -1) + (backward-char 1) + (setq oneleft t))) + (setq to (copy-marker (point) t)) + (goto-char from-plus-indent)) + + (if (not (> to (point))) + ;; There is no paragraph, only whitespace: exit now. + (progn + (set-marker to nil) + nil) + + (or justify (setq justify (current-justification))) + + ;; Don't let Adaptive Fill mode alter the fill prefix permanently. + (let ((fill-prefix fill-prefix)) + ;; Figure out how this paragraph is indented, if desired. + (when (and adaptive-fill-mode + (or (null fill-prefix) (string= fill-prefix ""))) + (setq fill-prefix (fill-context-prefix from to)) + ;; Ignore a white-space only fill-prefix + ;; if we indent-according-to-mode. + (when (and fill-prefix fill-indent-according-to-mode + (string-match "\\`[ \t]*\\'" fill-prefix)) + (setq fill-prefix nil))) + + (goto-char from) + (beginning-of-line) + + (if (not justify) ; filling disabled: just check indentation + (progn + (goto-char from) + (while (< (point) to) + (if (and (not (eolp)) + (< (LaTeX-current-indentation) (current-left-margin))) + (fill-indent-to-left-margin)) + (forward-line 1))) + + (when use-hard-newlines + (remove-text-properties from to '(hard nil))) + ;; Make sure first line is indented (at least) to left margin... + (indent-according-to-mode) + ;; Delete the fill-prefix from every line. + (fill-delete-prefix from to fill-prefix) + + (setq from (point)) + + ;; FROM, and point, are now before the text to fill, + ;; but after any fill prefix on the first line. + + (fill-delete-newlines from to justify nosqueeze squeeze-after) + + ;; This is the actual FILLING LOOP. + (goto-char from) + (let* (linebeg + (code-comment-start (save-excursion + (LaTeX-back-to-indentation) + (TeX-search-forward-comment-start + (line-end-position)))) + (end-marker (save-excursion + (goto-char (or code-comment-start to)) + (point-marker))) + (LaTeX-current-environment (LaTeX-current-environment))) + ;; Fill until point is greater than the end point. If there + ;; is a code comment, use the code comment's start as a + ;; limit. + (while (and (< (point) (marker-position end-marker)) + (or (not code-comment-start) + (and code-comment-start + (> (- (marker-position end-marker) + (line-beginning-position)) + fill-column)))) + (setq linebeg (point)) + (move-to-column (current-fill-column)) + (if (when (< (point) (marker-position end-marker)) + ;; Find the position where we'll break the line. + (forward-char 1) ; Use an immediately following + ; space, if any. + (LaTeX-fill-move-to-break-point linebeg) + + ;; Check again to see if we got to the end of + ;; the paragraph. + (skip-chars-forward " \t") + (< (point) (marker-position end-marker))) + ;; Found a place to cut. + (progn + (LaTeX-fill-newline) + (when justify + ;; Justify the line just ended, if desired. + (save-excursion + (forward-line -1) + (justify-current-line justify nil t)))) + + (goto-char end-marker) + ;; Justify this last line, if desired. + (if justify (justify-current-line justify t t)))) + + ;; Fill a code comment if necessary. (Enable this code if + ;; you want the comment part in lines with code comments to + ;; be filled. Originally it was disabled because the + ;; indentation code indented the lines following the line + ;; with the code comment to the column of the comment + ;; starters. That means, it would have looked like this: + ;; | code code code % comment + ;; | % comment + ;; | code code code + ;; This now (2005-07-29) is not the case anymore. But as + ;; filling code comments like this would split a single + ;; paragraph into two separate ones, we still leave it + ;; disabled. I leave the code here in case it is useful for + ;; somebody. + ;; (when (and code-comment-start + ;; (> (- (line-end-position) (line-beginning-position)) + ;; fill-column)) + ;; (LaTeX-fill-code-comment justify)) + + ;; The following is an alternative strategy to minimize the + ;; occurence of overfull lines with code comments. A line + ;; will be broken before the last non-comment word if the + ;; code comment does not fit into the line. + (when (and LaTeX-fill-break-before-code-comments + code-comment-start + (> (- (line-end-position) (line-beginning-position)) + fill-column)) + (beginning-of-line) + (goto-char end-marker) + (while (not (looking-at TeX-comment-start-regexp)) (forward-char)) + (skip-chars-backward " \t") + (skip-chars-backward "^ \t\n") + (unless (or (bolp) + ;; Comment starters and whitespace. + (TeX-looking-at-backward + (concat "^\\([ \t]*" TeX-comment-start-regexp "+\\)*" + "[ \t]*") + (line-beginning-position))) + (LaTeX-fill-newline))) + (set-marker end-marker nil))) + ;; Leave point after final newline. + (goto-char to) + (unless (eobp) (forward-char 1)) + (set-marker to nil) + ;; Return the fill-prefix we used + fill-prefix))) + +(defun LaTeX-fill-move-to-break-point (linebeg) + "Move to the position where the line should be broken." + (fill-move-to-break-point linebeg) + ;; Prevent line break between 2-byte char and 1-byte char. + (when (and (or (and (not (looking-at LaTeX-nospace-between-char-regexp)) + (TeX-looking-at-backward + LaTeX-nospace-between-char-regexp 1)) + (and (not (TeX-looking-at-backward + LaTeX-nospace-between-char-regexp 1)) + (looking-at LaTeX-nospace-between-char-regexp))) + (re-search-backward + (concat LaTeX-nospace-between-char-regexp + LaTeX-nospace-between-char-regexp + LaTeX-nospace-between-char-regexp + "\\|" + ".\\ca\\s +\\ca") linebeg t)) + (if (looking-at "..\\c>") + (forward-char 1) + (forward-char 2))) + ;; Cater for Japanese Macro + (when (and (boundp 'japanese-TeX-mode) japanese-TeX-mode + (aref (char-category-set (char-after)) ?j) + (TeX-looking-at-backward (concat (regexp-quote TeX-esc) TeX-token-char "*") + (1- (- (point) linebeg))) + (not (TeX-escaped-p (match-beginning 0)))) + (goto-char (match-beginning 0))) + ;; Cater for \verb|...| (and similar) contructs which should not be + ;; broken. (FIXME: Make it work with shortvrb.sty (also loaded by + ;; doc.sty) where |...| is allowed. Arbitrary delimiters may be + ;; chosen with \MakeShortVerb{}.) This could probably be + ;; handled with `fill-nobreak-predicate', but this is not available + ;; in XEmacs. + (let ((final-breakpoint (point)) + (verb-macros (regexp-opt (append (LaTeX-verbatim-macros-with-delims) + (LaTeX-verbatim-macros-with-braces))))) + (save-excursion + ;; Look for the start of a verbatim macro in the current line. + (when (re-search-backward (concat (regexp-quote TeX-esc) + "\\(?:" verb-macros "\\)\\([^a-z@*]\\)") + (line-beginning-position) t) + ;; Determine start and end of verbatim macro. + (let ((beg (point)) + (end (if (not (string-match "[ [{]" (match-string 1))) + (cdr (LaTeX-verbatim-macro-boundaries)) + (TeX-find-macro-end)))) + ;; Determine if macro end is behind fill column. + (when (and end + (> (- end (line-beginning-position)) + (current-fill-column)) + (> end final-breakpoint)) + ;; Search backwards for place to break before the macro. + (goto-char beg) + (skip-chars-backward "^ \n") + ;; Determine if point ended up at the beginning of the line. + (when (save-excursion (skip-chars-backward " \t%") (bolp)) + ;; Search forward for a place to break after the macro. + (goto-char end) + (skip-chars-forward "^ \n" (point-max))) + (setq final-breakpoint (point)))))) + (goto-char final-breakpoint)) + (when LaTeX-fill-break-at-separators + (let ((orig-breakpoint (point)) + (final-breakpoint (point)) + start-point) + (save-excursion + (beginning-of-line) + (LaTeX-back-to-indentation 'outer) + (setq start-point (point)) + ;; Find occurences of [, $, {, }, \(, \), \[, \] or $$. + (while (and (= final-breakpoint orig-breakpoint) + (TeX-re-search-forward-unescaped + (concat "[[{}]\\|\\$\\$?\\|" + (regexp-quote TeX-esc) "[][()]") + orig-breakpoint t)) + (let ((match-string (match-string 0))) + (cond + ;; [ (opening bracket) (The closing bracket should + ;; already be handled implicitely by the code for the + ;; opening brace.) + ((save-excursion + (and (memq '\[ LaTeX-fill-break-at-separators) + (string= match-string "[") + (TeX-re-search-forward-unescaped (concat "\\][ \t]*{") + (line-end-position) t) + (> (- (or (TeX-find-closing-brace) + (line-end-position)) + (line-beginning-position)) + fill-column))) + (save-excursion + (skip-chars-backward "^ \n") + (when (> (point) start-point) + (setq final-breakpoint (point))))) + ;; { (opening brace) + ((save-excursion + (and (memq '\{ LaTeX-fill-break-at-separators) + (string= match-string "{") + (> (- (save-excursion + ;; `TeX-find-closing-brace' is not enough + ;; if there is no breakpoint in form of + ;; whitespace after the brace. + (goto-char (or (TeX-find-closing-brace) + (line-end-position))) + (skip-chars-forward "^ \t\n") + (point)) + (line-beginning-position)) + fill-column))) + (save-excursion + (skip-chars-backward "^ \n") + ;; The following is a primitive and error-prone method + ;; to cope with point probably being inside square + ;; brackets. A better way would be to use functions + ;; to determine if point is inside an optional + ;; argument and to jump to the start and end brackets. + (when (save-excursion + (TeX-re-search-forward-unescaped + (concat "\\][ \t]*{") orig-breakpoint t)) + (TeX-search-backward-unescaped "[" + (line-beginning-position) t) + (skip-chars-backward "^ \n")) + (when (> (point) start-point) + (setq final-breakpoint (point))))) + ;; } (closing brace) + ((save-excursion + (and (memq '\} LaTeX-fill-break-at-separators) + (string= match-string "}") + (save-excursion + (backward-char 2) + (not (TeX-find-opening-brace + nil (line-beginning-position)))))) + (save-excursion + (skip-chars-forward "^ \n") + (when (> (point) start-point) + (setq final-breakpoint (point))))) + ;; $ or \( or \[ or $$ (opening math) + ((save-excursion + (and (or (and (memq '\\\( LaTeX-fill-break-at-separators) + (or (and (string= match-string "$") + (texmathp)) + (string= match-string "\\("))) + (and (memq '\\\[ LaTeX-fill-break-at-separators) + (or (string= match-string "\\[") + (and (string= match-string "$$") + (texmathp))))) + (> (- (save-excursion + (TeX-search-forward-unescaped + (cond ((string= match-string "\\(") + (concat TeX-esc ")")) + ((string= match-string "$") "$") + ((string= match-string "$$") "$$") + (t (concat TeX-esc "]"))) + (point-max) t) + (skip-chars-forward "^ \n") + (point)) + (line-beginning-position)) + fill-column))) + (save-excursion + (skip-chars-backward "^ \n") + (when (> (point) start-point) + (setq final-breakpoint (point))))) + ;; $ or \) or \] or $$ (closing math) + ((save-excursion + (and (or (and (memq '\\\) LaTeX-fill-break-at-separators) + (or (and (string= match-string "$") + (not (texmathp))) + (string= match-string "\\)"))) + (and (memq '\\\] LaTeX-fill-break-at-separators) + (or (string= match-string "\\]") + (and (string= match-string "$$") + (not (texmathp)))))) + (if (member match-string '("$" "$$")) + (save-excursion + (skip-chars-backward "$") + (TeX-search-backward-unescaped + match-string (line-beginning-position) t)) + (texmathp-match-switch (line-beginning-position))))) + (save-excursion + (skip-chars-forward "^ \n") + (when (> (point) start-point) + (setq final-breakpoint (point))))))))) + (goto-char final-breakpoint)))) + +;; The content of `LaTeX-fill-newline' was copied from the function +;; `fill-newline' in `fill.el' (CVS Emacs, January 2004) and adapted +;; to the needs of AUCTeX. +(defun LaTeX-fill-newline () + "Replace whitespace here with one newline and indent the line." + (skip-chars-backward " \t") + (newline 1) + ;; Give newline the properties of the space(s) it replaces + (set-text-properties (1- (point)) (point) + (text-properties-at (point))) + (and (looking-at "\\( [ \t]*\\)\\(\\c|\\)?") + (or (aref (char-category-set (or (char-before (1- (point))) ?\000)) ?|) + (match-end 2)) + ;; When refilling later on, this newline would normally not + ;; be replaced by a space, so we need to mark it specially to + ;; re-install the space when we unfill. + (put-text-property (1- (point)) (point) 'fill-space (match-string 1))) + ;; If we don't want breaks in invisible text, don't insert + ;; an invisible newline. + (if fill-nobreak-invisible + (remove-text-properties (1- (point)) (point) + '(invisible t))) + ;; Insert the fill prefix. + (and fill-prefix (not (equal fill-prefix "")) + ;; Markers that were after the whitespace are now at point: insert + ;; before them so they don't get stuck before the prefix. + (insert-before-markers-and-inherit fill-prefix)) + (indent-according-to-mode) + (run-hooks 'LaTeX-fill-newline-hook)) + +(defun LaTeX-fill-paragraph (&optional justify) + "Like `fill-paragraph', but handle LaTeX comments. +If any of the current line is a comment, fill the comment or the +paragraph of it that point is in. Code comments, that is, comments +with uncommented code preceding them in the same line, will not +be filled unless the cursor is placed on the line with the +code comment. + +If LaTeX syntax is taken into consideration during filling +depends on the value of `LaTeX-syntactic-comments'." + (interactive "P") + (if (save-excursion + (beginning-of-line) + (looking-at (concat TeX-comment-start-regexp "*[ \t]*$"))) + ;; Don't do anything if we look at an empty line and let + ;; `fill-paragraph' think we successfully filled the paragraph. + t + (let (;; Non-nil if the current line contains a comment. + has-comment + ;; Non-nil if the current line contains code and a comment. + has-code-and-comment + code-comment-start + ;; If has-comment, the appropriate fill-prefix for the comment. + comment-fill-prefix) + + ;; Figure out what kind of comment we are looking at. + (cond + ;; A line only with potential whitespace followed by a + ;; comment on it? + ((save-excursion + (beginning-of-line) + (looking-at (concat "^[ \t]*" TeX-comment-start-regexp + "\\(" TeX-comment-start-regexp "\\|[ \t]\\)*"))) + (setq has-comment t + comment-fill-prefix (TeX-match-buffer 0))) + ;; A line with some code, followed by a comment? + ((and (setq code-comment-start (save-excursion + (beginning-of-line) + (TeX-search-forward-comment-start + (line-end-position)))) + (> (point) code-comment-start) + (not (TeX-in-commented-line)) + (save-excursion + (goto-char code-comment-start) + ;; See if there is at least one non-whitespace character + ;; before the comment starts. + (re-search-backward "[^ \t\n]" (line-beginning-position) t))) + (setq has-comment t + has-code-and-comment t))) + + (cond + ;; Code comments. + (has-code-and-comment + (save-excursion + (when (>= (- code-comment-start (line-beginning-position)) + fill-column) + ;; If start of code comment is beyond fill column, fill it as a + ;; regular paragraph before it is filled as a code comment. + (let ((end-marker (save-excursion (end-of-line) (point-marker)))) + (LaTeX-fill-region-as-paragraph (line-beginning-position) + (line-beginning-position 2) + justify) + (goto-char end-marker) + (beginning-of-line) + (set-marker end-marker nil))) + (LaTeX-fill-code-comment justify))) + ;; Syntax-aware filling: + ;; * `LaTeX-syntactic-comments' enabled: Everything. + ;; * `LaTeX-syntactic-comments' disabled: Uncommented code and + ;; line comments in `doctex-mode'. + ((or (or LaTeX-syntactic-comments + (and (not LaTeX-syntactic-comments) + (not has-comment))) + (and (eq major-mode 'doctex-mode) + (TeX-in-line-comment))) + (let ((fill-prefix comment-fill-prefix)) + (save-excursion + (let* ((end (progn (LaTeX-forward-paragraph) + (or (bolp) (newline 1)) + (and (eobp) (not (bolp)) (open-line 1)) + (point))) + (start + (progn + (LaTeX-backward-paragraph) + (while (and (looking-at + (concat "$\\|[ \t]+$\\|" + "[ \t]*" TeX-comment-start-regexp + "+[ \t]*$")) + (< (point) end)) + (forward-line)) + (point)))) + (LaTeX-fill-region-as-paragraph start end justify))))) + ;; Non-syntax-aware filling. + (t + (save-excursion + (save-restriction + (beginning-of-line) + (narrow-to-region + ;; Find the first line we should include in the region to fill. + (save-excursion + (while (and (zerop (forward-line -1)) + (looking-at (concat "^[ \t]*" + TeX-comment-start-regexp)))) + ;; We may have gone too far. Go forward again. + (or (looking-at (concat ".*" TeX-comment-start-regexp)) + (forward-line 1)) + (point)) + ;; Find the beginning of the first line past the region to fill. + (save-excursion + (while (progn (forward-line 1) + (looking-at (concat "^[ \t]*" + TeX-comment-start-regexp)))) + (point))) + ;; The definitions of `paragraph-start' and + ;; `paragraph-separate' will still make + ;; `forward-paragraph' and `backward-paragraph' stop at + ;; the respective (La)TeX commands. If these should be + ;; disregarded, the definitions would have to be changed + ;; accordingly. (Lines with only `%' characters on them + ;; can be paragraph boundaries.) + (let* ((paragraph-start + (concat paragraph-start "\\|" + "\\(" TeX-comment-start-regexp "\\|[ \t]\\)*$")) + (paragraph-separate + (concat paragraph-separate "\\|" + "\\(" TeX-comment-start-regexp "\\|[ \t]\\)*$")) + (fill-prefix comment-fill-prefix) + (end (progn (forward-paragraph) + (or (bolp) (newline 1)) + (point))) + (beg (progn (backward-paragraph) + (point)))) + (fill-region-as-paragraph + beg end + justify nil + (save-excursion + (goto-char beg) + (if (looking-at fill-prefix) + nil + (re-search-forward comment-start-skip nil t) + (point))))))))) + t))) + +(defun LaTeX-fill-code-comment (&optional justify-flag) + "Fill a line including code followed by a comment." + (let ((beg (line-beginning-position)) + fill-prefix code-comment-start) + (indent-according-to-mode) + (when (when (setq code-comment-start (save-excursion + (goto-char beg) + (TeX-search-forward-comment-start + (line-end-position)))) + (goto-char code-comment-start) + (while (not (looking-at TeX-comment-start-regexp)) (forward-char)) + ;; See if there is at least one non-whitespace character + ;; before the comment starts. + (save-excursion + (re-search-backward "[^ \t\n]" (line-beginning-position) t))) + (setq fill-prefix + (concat + (if indent-tabs-mode + (concat (make-string (/ (current-column) tab-width) ?\t) + (make-string (% (current-column) tab-width) ?\ )) + (make-string (current-column) ?\ )) + (progn + (looking-at (concat TeX-comment-start-regexp "+[ \t]*")) + (TeX-match-buffer 0)))) + (fill-region-as-paragraph beg (line-beginning-position 2) + justify-flag nil + (save-excursion + (goto-char beg) + (if (looking-at fill-prefix) + nil + (re-search-forward comment-start-skip nil t) + (point))))))) + +(defun LaTeX-fill-region (from to &optional justify what) + "Fill and indent the text in region from FROM to TO as LaTeX text. +Prefix arg (non-nil third arg JUSTIFY, if called from program) +means justify as well. Fourth arg WHAT is a word to be displayed when +formatting." + (interactive "*r\nP") + (save-excursion + (let ((to (set-marker (make-marker) to)) + (next-par (make-marker))) + (goto-char from) + (beginning-of-line) + (setq from (point)) + (catch 'end-of-buffer + (while (and (< (point) to)) + (message "Formatting%s...%d%%" + (or what "") + (/ (* 100 (- (point) from)) (- to from))) + (save-excursion (LaTeX-fill-paragraph justify)) + (if (marker-position next-par) + (goto-char (marker-position next-par)) + (LaTeX-forward-paragraph)) + (when (eobp) (throw 'end-of-buffer t)) + (LaTeX-forward-paragraph) + (set-marker next-par (point)) + (LaTeX-backward-paragraph) + (while (and (not (eobp)) + (looking-at + (concat "^\\($\\|[ \t]+$\\|[ \t]*" + TeX-comment-start-regexp "+[ \t]*$\\)"))) + (forward-line 1)))) + (set-marker next-par nil) + (set-marker to nil))) + (message "Formatting%s...done" (or what ""))) + +(defun LaTeX-find-matching-end () + "Move point to the \\end of the current environment. + +If function is called inside a comment and +`LaTeX-syntactic-comments' is enabled, try to find the +environment in commented regions with the same comment prefix." + (interactive) + (let* ((regexp (concat (regexp-quote TeX-esc) "\\(begin\\|end\\)\\b")) + (level 1) + (in-comment (TeX-in-commented-line)) + (comment-prefix (and in-comment (TeX-comment-prefix))) + (case-fold-search nil)) + (let ((pt (point))) + (skip-chars-backward (concat "a-zA-Z \t" (regexp-quote TeX-grop))) + (unless (bolp) + (backward-char 1) + (if (and (looking-at regexp) + (char-equal (char-after (1+ (match-beginning 0))) ?e)) + (setq level 0) + (goto-char pt)))) + (while (and (> level 0) (re-search-forward regexp nil t)) + (when (or (and LaTeX-syntactic-comments + (eq in-comment (TeX-in-commented-line)) + ;; If we are in a commented line, check if the + ;; prefix matches the one we started out with. + (or (not in-comment) + (string= comment-prefix (TeX-comment-prefix)))) + (and (not LaTeX-syntactic-comments) + (not (TeX-in-commented-line)))) + (if (= (char-after (1+ (match-beginning 0))) ?b) ;;begin + (setq level (1+ level)) + (setq level (1- level))))) + (if (= level 0) + (re-search-forward + (concat TeX-grop (LaTeX-environment-name-regexp) TeX-grcl)) + (error "Can't locate end of current environment")))) + +(defun LaTeX-find-matching-begin () + "Move point to the \\begin of the current environment. + +If function is called inside a comment and +`LaTeX-syntactic-comments' is enabled, try to find the +environment in commented regions with the same comment prefix." + (interactive) + (let* ((regexp (concat (regexp-quote TeX-esc) "\\(begin\\|end\\)\\b")) + (level 1) + (in-comment (TeX-in-commented-line)) + (comment-prefix (and in-comment (TeX-comment-prefix))) + (case-fold-search nil)) + (skip-chars-backward (concat "a-zA-Z \t" (regexp-quote TeX-grop))) + (unless (bolp) + (backward-char 1) + (and (looking-at regexp) + (char-equal (char-after (1+ (match-beginning 0))) ?b) + (setq level 0))) + (while (and (> level 0) (re-search-backward regexp nil t)) + (when (or (and LaTeX-syntactic-comments + (eq in-comment (TeX-in-commented-line)) + ;; If we are in a commented line, check if the + ;; prefix matches the one we started out with. + (or (not in-comment) + (string= comment-prefix (TeX-comment-prefix)))) + (and (not LaTeX-syntactic-comments) + (not (TeX-in-commented-line)))) + (if (= (char-after (1+ (match-beginning 0))) ?e) ;;end + (setq level (1+ level)) + (setq level (1- level))))) + (or (= level 0) + (error "Can't locate beginning of current environment")))) + +(defun LaTeX-mark-environment (&optional count) + "Set mark to end of current environment and point to the matching begin. +If prefix argument COUNT is given, mark the respective number of +enclosing environments. The command will not work properly if +there are unbalanced begin-end pairs in comments and verbatim +environments." + (interactive "p") + (setq count (if count (abs count) 1)) + (let ((cur (point)) beg end) + ;; Only change point and mark after beginning and end were found. + ;; Point should not end up in the middle of nowhere if the search fails. + (save-excursion + (dotimes (_ count) (LaTeX-find-matching-end)) + (setq end (line-beginning-position 2)) + (goto-char cur) + (dotimes (_ count) (LaTeX-find-matching-begin)) + (setq beg (point))) + (push-mark end) + (goto-char beg) + (TeX-activate-region))) + +(defun LaTeX-fill-environment (justify) + "Fill and indent current environment as LaTeX text." + (interactive "*P") + (save-excursion + (LaTeX-mark-environment) + (re-search-forward "{\\([^}]+\\)}") + (LaTeX-fill-region (region-beginning) (region-end) justify + (concat " environment " (TeX-match-buffer 1))))) + +(defun LaTeX-fill-section (justify) + "Fill and indent current logical section as LaTeX text." + (interactive "*P") + (save-excursion + (LaTeX-mark-section) + (re-search-forward "{\\([^}]+\\)}") + (LaTeX-fill-region (region-beginning) (region-end) justify + (concat " section " (TeX-match-buffer 1))))) + +(defun LaTeX-mark-section (&optional no-subsections) + "Set mark at end of current logical section, and point at top. +If optional argument NO-SUBSECTIONS is non-nil, mark only the +region from the current section start to the next sectioning +command. Thereby subsections are not being marked. + +If the function `outline-mark-subtree' is not available, +`LaTeX-mark-section' always behaves like this regardless of the +value of NO-SUBSECTIONS." + (interactive "P") + (if (or no-subsections + (not (fboundp 'outline-mark-subtree))) + (progn + (re-search-forward (concat "\\(" (LaTeX-outline-regexp) + "\\|\\'\\)")) + (beginning-of-line) + (push-mark (point) nil t) + (re-search-backward (concat "\\(" (LaTeX-outline-regexp) + "\\|\\`\\)"))) + (outline-mark-subtree) + (when (and transient-mark-mode + (not mark-active)) + (setq mark-active t) + (run-hooks 'activate-mark-hook))) + (TeX-activate-region)) + +(defun LaTeX-fill-buffer (justify) + "Fill and indent current buffer as LaTeX text." + (interactive "*P") + (save-excursion + (LaTeX-fill-region + (point-min) + (point-max) + justify + (concat " buffer " (buffer-name))))) + + +;;; Navigation + +(defvar LaTeX-paragraph-commands-internal + '("[" "]" ; display math + "appendix" "begin" "caption" "chapter" "end" "include" "includeonly" + "label" "maketitle" "newblock" "noindent" "par" "paragraph" "part" + "section" "subsection" "subsubsection" "tableofcontents" + "newpage" "clearpage") + "Internal list of LaTeX macros that should have their own line.") + +(defvar LaTeX-paragraph-commands) + +(defun LaTeX-paragraph-commands-regexp-make () + "Return a regular expression matching defined paragraph commands. +Regexp part containing TeX control words is postfixed with `\\b' +to avoid ambiguities (for example, \\par vs. \\parencite)." + (let (cmds symbs) + (dolist (mac (append LaTeX-paragraph-commands + LaTeX-paragraph-commands-internal)) + (if (string-match "[^a-zA-Z]" mac) + (push mac symbs) + (push mac cmds))) + (concat (regexp-quote TeX-esc) "\\(?:" + (regexp-opt cmds "\\(?:") + "\\b" + "\\|" + (regexp-opt symbs) + "\\)"))) + +(defvar LaTeX-paragraph-commands-regexp) + +(defcustom LaTeX-paragraph-commands nil + "List of LaTeX macros that should have their own line. +The list should contain macro names without the leading backslash." + :group 'LaTeX-macro + :type '(repeat (string)) + :set (lambda (symbol value) + (set-default symbol value) + (setq LaTeX-paragraph-commands-regexp + (LaTeX-paragraph-commands-regexp-make)))) + +(defvar LaTeX-paragraph-commands-regexp (LaTeX-paragraph-commands-regexp-make) + "Regular expression matching LaTeX macros that should have their own line.") + +(defun LaTeX-set-paragraph-start () + "Set `paragraph-start'." + (setq paragraph-start + (concat + "[ \t]*%*[ \t]*\\(" + LaTeX-paragraph-commands-regexp "\\|" + (regexp-quote TeX-esc) "\\(" LaTeX-item-regexp "\\)\\|" + "\\$\\$\\|" ; Plain TeX display math (Some people actually use this + ; with LaTeX. Yuck.) + "$\\)"))) + +(defun LaTeX-paragraph-commands-add-locally (commands) + "Make COMMANDS be recognized as paragraph commands. +COMMANDS can be a single string or a list of strings which will +be added to `LaTeX-paragraph-commands-internal'. Additionally +`LaTeX-paragraph-commands-regexp' will be updated and both +variables will be made buffer-local. This is mainly a +convenience function which can be used in style files." + (make-local-variable 'LaTeX-paragraph-commands-internal) + (make-local-variable 'LaTeX-paragraph-commands-regexp) + (unless (listp commands) (setq commands (list commands))) + (dolist (elt commands) + (add-to-list 'LaTeX-paragraph-commands-internal elt)) + (setq LaTeX-paragraph-commands-regexp (LaTeX-paragraph-commands-regexp-make)) + (LaTeX-set-paragraph-start)) + +(defun LaTeX-forward-paragraph (&optional count) + "Move forward to end of paragraph. +If COUNT is non-nil, do it COUNT times." + (or count (setq count 1)) + (dotimes (_ count) + (let* ((macro-start (TeX-find-macro-start)) + (paragraph-command-start + (cond + ;; Point is inside of a paragraph command. + ((and macro-start + (save-excursion + (goto-char macro-start) + (looking-at LaTeX-paragraph-commands-regexp))) + (match-beginning 0)) + ;; Point is before a paragraph command in the same line. + ((looking-at + (concat "[ \t]*\\(?:" TeX-comment-start-regexp + "\\(?:" TeX-comment-start-regexp "\\|[ \t]\\)*\\)?" + "\\(" LaTeX-paragraph-commands-regexp "\\)")) + (match-beginning 1)))) + macro-end) + ;; If a paragraph command is encountered there are two cases to be + ;; distinguished: + ;; 1) If the end of the paragraph command coincides (apart from + ;; potential whitespace) with the end of the line, is only + ;; followed by a comment or is directly followed by a macro, + ;; it is assumed that it should be handled separately. + ;; 2) If the end of the paragraph command is followed by other + ;; code, it is assumed that it should be included with the rest + ;; of the paragraph. + (if (and paragraph-command-start + (save-excursion + (goto-char paragraph-command-start) + (setq macro-end (goto-char (TeX-find-macro-end))) + (looking-at (concat (regexp-quote TeX-esc) "[@A-Za-z]+\\|" + "[ \t]*\\($\\|" + TeX-comment-start-regexp "\\)")))) + (progn + (goto-char macro-end) + ;; If the paragraph command is followed directly by + ;; another macro, regard the latter as part of the + ;; paragraph command's paragraph. + (when (looking-at (concat (regexp-quote TeX-esc) "[@A-Za-z]+")) + (goto-char (TeX-find-macro-end))) + (forward-line)) + (let (limit) + (goto-char (min (save-excursion + (forward-paragraph) + (setq limit (point))) + (save-excursion + (TeX-forward-comment-skip 1 limit) + (point))))))))) + +(defun LaTeX-backward-paragraph (&optional count) + "Move backward to beginning of paragraph. +If COUNT is non-nil, do it COUNT times." + (or count (setq count 1)) + (dotimes (_ count) + (let* ((macro-start (TeX-find-macro-start))) + (if (and macro-start + ;; Point really has to be inside of the macro, not before it. + (not (= macro-start (point))) + (save-excursion + (goto-char macro-start) + (looking-at LaTeX-paragraph-commands-regexp))) + ;; Point is inside of a paragraph command. + (progn + (goto-char macro-start) + (beginning-of-line)) + (let (limit + (start (line-beginning-position))) + (goto-char + (max (save-excursion + (backward-paragraph) + (setq limit (point))) + ;; Search for possible transitions from commented to + ;; uncommented regions and vice versa. + (save-excursion + (TeX-backward-comment-skip 1 limit) + (point)) + ;; Search for paragraph commands. + (save-excursion + (let ((end-point 0) macro-bol) + (when (setq macro-bol + (re-search-backward + (format "^[ \t]*%s*[ \t]*\\(%s\\)" + TeX-comment-start-regexp + LaTeX-paragraph-commands-regexp) + limit t)) + (if (and (string= (match-string 1) "\\begin") + (progn + (goto-char (match-end 1)) + (skip-chars-forward "{ \t") + (member (buffer-substring-no-properties + (point) (progn (skip-chars-forward + "A-Za-z*") (point))) + LaTeX-verbatim-environments))) + ;; If inside a verbatim environment, just + ;; use the next line. In such environments + ;; `TeX-find-macro-end' could otherwise + ;; think brackets or braces belong to the + ;; \begin macro. + (setq end-point (line-beginning-position 2)) + ;; Jump to the macro end otherwise. + (goto-char (match-beginning 1)) + (goto-char (TeX-find-macro-end)) + ;; For an explanation of this distinction see + ;; `LaTeX-forward-paragraph'. + (if (looking-at (concat (regexp-quote TeX-esc) + "[@A-Za-z]+\\|[ \t]*\\($\\|" + TeX-comment-start-regexp "\\)")) + (progn + (when (looking-at (regexp-quote TeX-esc)) + (goto-char (TeX-find-macro-end))) + (forward-line 1) + (when (< (point) start) + (setq end-point (point)))) + (setq end-point macro-bol)))) + end-point))))))))) + +(defun LaTeX-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. + +This function makes sure that any comment starters found inside +of verbatim constructs are not considered." + (setq limit (or limit (point-max))) + (save-excursion + (let (start) + (catch 'found + (while (progn + (when (and (TeX-re-search-forward-unescaped + TeX-comment-start-regexp limit 'move) + (not (LaTeX-verbatim-p))) + (setq start (match-beginning 0)) + (throw 'found t)) + (< (point) limit)))) + start))) + + +;;; Math Minor Mode + +(defvar LaTeX-math-mode-map) + +(defgroup LaTeX-math nil + "Mathematics in AUCTeX." + :group 'LaTeX-macro) + +(defvar LaTeX-math-keymap (make-sparse-keymap) + "Keymap used for `LaTeX-math-mode' commands.") + +(defcustom LaTeX-math-abbrev-prefix "`" + "Prefix key for use in `LaTeX-math-mode'. +This has to be a string representing a key sequence in a format +understood by the `kbd' macro. This corresponds to the syntax +usually used in the Emacs and Elisp manuals. + +Setting this variable directly does not take effect; +use \\[customize]." + :group 'LaTeX-math + :initialize #'custom-initialize-default + :set (lambda (symbol value) + (define-key LaTeX-math-mode-map (LaTeX-math-abbrev-prefix) t) + (set-default symbol value) + (define-key LaTeX-math-mode-map + (LaTeX-math-abbrev-prefix) LaTeX-math-keymap)) + :type '(string :tag "Key sequence")) + +(defun LaTeX-math-abbrev-prefix () + "Make a key definition from the variable `LaTeX-math-abbrev-prefix'." + (if (stringp LaTeX-math-abbrev-prefix) + (read-kbd-macro LaTeX-math-abbrev-prefix) + LaTeX-math-abbrev-prefix)) + +(defvar LaTeX-math-menu + '("Math" + ("Greek Uppercase") ("Greek Lowercase") ("Binary Op") ("Relational") + ("Arrows") ("Punctuation") ("Misc Symbol") ("Var Symbol") ("Log-like") + ("Delimiters") ("Constructs") ("Accents") ("AMS")) + "Menu containing LaTeX math commands. +The menu entries will be generated dynamically, but you can specify +the sequence by initializing this variable.") + +(defconst LaTeX-math-default + '((?a "alpha" "Greek Lowercase" 945) ;; #X03B1 + (?b "beta" "Greek Lowercase" 946) ;; #X03B2 + (?g "gamma" "Greek Lowercase" 947) ;; #X03B3 + (?d "delta" "Greek Lowercase" 948) ;; #X03B4 + (?e "epsilon" "Greek Lowercase" 1013) ;; #X03F5 + (?z "zeta" "Greek Lowercase" 950) ;; #X03B6 + (?h "eta" "Greek Lowercase" 951) ;; #X03B7 + (?j "theta" "Greek Lowercase" 952) ;; #X03B8 + (nil "iota" "Greek Lowercase" 953) ;; #X03B9 + (?k "kappa" "Greek Lowercase" 954) ;; #X03BA + (?l "lambda" "Greek Lowercase" 955) ;; #X03BB + (?m "mu" "Greek Lowercase" 956) ;; #X03BC + (?n "nu" "Greek Lowercase" 957) ;; #X03BD + (?x "xi" "Greek Lowercase" 958) ;; #X03BE + (?p "pi" "Greek Lowercase" 960) ;; #X03C0 + (?r "rho" "Greek Lowercase" 961) ;; #X03C1 + (?s "sigma" "Greek Lowercase" 963) ;; #X03C3 + (?t "tau" "Greek Lowercase" 964) ;; #X03C4 + (?u "upsilon" "Greek Lowercase" 965) ;; #X03C5 + (?f "phi" "Greek Lowercase" 981) ;; #X03D5 + (?q "chi" "Greek Lowercase" 967) ;; #X03C7 + (?y "psi" "Greek Lowercase" 968) ;; #X03C8 + (?w "omega" "Greek Lowercase" 969) ;; #X03C9 + ("v e" "varepsilon" "Greek Lowercase" 949) ;; #X03B5 + ("v j" "vartheta" "Greek Lowercase" 977) ;; #X03D1 + ("v p" "varpi" "Greek Lowercase" 982) ;; #X03D6 + ("v r" "varrho" "Greek Lowercase" 1009) ;; #X03F1 + ("v s" "varsigma" "Greek Lowercase" 962) ;; #X03C2 + ("v f" "varphi" "Greek Lowercase" 966) ;; #X03C6 + (?G "Gamma" "Greek Uppercase" 915) ;; #X0393 + (?D "Delta" "Greek Uppercase" 916) ;; #X0394 + (?J "Theta" "Greek Uppercase" 920) ;; #X0398 + (?L "Lambda" "Greek Uppercase" 923) ;; #X039B + (?X "Xi" "Greek Uppercase" 926) ;; #X039E + (?P "Pi" "Greek Uppercase" 928) ;; #X03A0 + (?S "Sigma" "Greek Uppercase" 931) ;; #X03A3 + (?U "Upsilon" "Greek Uppercase" 978) ;; #X03D2 + (?F "Phi" "Greek Uppercase" 934) ;; #X03A6 + (?Y "Psi" "Greek Uppercase" 936) ;; #X03A8 + (?W "Omega" "Greek Uppercase" 937) ;; #X03A9 + (?c LaTeX-math-cal "Cal-whatever") + (nil "pm" "Binary Op" 177) ;; #X00B1 + (nil "mp" "Binary Op" 8723) ;; #X2213 + (?* "times" "Binary Op" 215) ;; #X00D7 + (nil "div" "Binary Op" 247) ;; #X00F7 + (nil "ast" "Binary Op" 8727) ;; #X2217 + (nil "star" "Binary Op" 8902) ;; #X22C6 + (nil "circ" "Binary Op" 8728) ;; #X2218 + (nil "bullet" "Binary Op" 8729) ;; #X2219 + (?. "cdot" "Binary Op" 8901) ;; #X22C5 + (?- "cap" "Binary Op" 8745) ;; #X2229 + (?+ "cup" "Binary Op" 8746) ;; #X222A + (nil "uplus" "Binary Op" 8846) ;; #X228E + (nil "sqcap" "Binary Op" 8851) ;; #X2293 + (?| "vee" "Binary Op" 8744) ;; #X2228 + (?& "wedge" "Binary Op" 8743) ;; #X2227 + (?\\ "setminus" "Binary Op" 8726) ;; #X2216 + (nil "wr" "Binary Op" 8768) ;; #X2240 + (nil "diamond" "Binary Op" 8900) ;; #X22C4 + (nil "bigtriangleup" "Binary Op" 9651) ;; #X25B3 + (nil "bigtriangledown" "Binary Op" 9661) ;; #X25BD + (nil "triangleleft" "Binary Op" 9665) ;; #X25C1 + (nil "triangleright" "Binary Op" 9655) ;; #X25B7 + (nil "lhd" "Binary Op" 8882) ;; #X22B2 + (nil "rhd" "Binary Op" 8883) ;; #X22B3 + (nil "unlhd" "Binary Op" 8884) ;; #X22B4 + (nil "unrhd" "Binary Op" 8885) ;; #X22B5 + (nil "oplus" "Binary Op" 8853) ;; #X2295 + (nil "ominus" "Binary Op" 8854) ;; #X2296 + (nil "otimes" "Binary Op" 8855) ;; #X2297 + (nil "oslash" "Binary Op" 8709) ;; #X2205 + (nil "odot" "Binary Op" 8857) ;; #X2299 + (nil "bigcirc" "Binary Op" 9675) ;; #X25CB + (nil "dagger" "Binary Op" 8224) ;; #X2020 + (nil "ddagger" "Binary Op" 8225) ;; #X2021 + (nil "amalg" "Binary Op" 10815) ;; #X2A3F + (?< "leq" "Relational" 8804) ;; #X2264 + (?> "geq" "Relational" 8805) ;; #X2265 + (nil "qed" "Relational" 8718) ;; #X220E + (nil "equiv" "Relational" 8801) ;; #X2261 + (nil "models" "Relational" 8871) ;; #X22A7 + (nil "prec" "Relational" 8826) ;; #X227A + (nil "succ" "Relational" 8827) ;; #X227B + (nil "sim" "Relational" 8764) ;; #X223C + (nil "perp" "Relational" 10178) ;; #X27C2 + (nil "preceq" "Relational" 10927) ;; #X2AAF + (nil "succeq" "Relational" 10928) ;; #X2AB0 + (nil "simeq" "Relational" 8771) ;; #X2243 + (nil "mid" "Relational" 8739) ;; #X2223 + (nil "ll" "Relational" 8810) ;; #X226A + (nil "gg" "Relational" 8811) ;; #X226B + (nil "asymp" "Relational" 8781) ;; #X224D + (nil "parallel" "Relational" 8741) ;; #X2225 + (?\{ "subset" "Relational" 8834) ;; #X2282 + (?\} "supset" "Relational" 8835) ;; #X2283 + (nil "approx" "Relational" 8776) ;; #X2248 + (nil "bowtie" "Relational" 8904) ;; #X22C8 + (?\[ "subseteq" "Relational" 8838) ;; #X2286 + (?\] "supseteq" "Relational" 8839) ;; #X2287 + (nil "cong" "Relational" 8773) ;; #X2245 + (nil "Join" "Relational" 10781) ;; #X2A1D + (nil "sqsubset" "Relational" 8847) ;; #X228F + (nil "sqsupset" "Relational" 8848) ;; #X2290 + (nil "neq" "Relational" 8800) ;; #X2260 + (nil "smile" "Relational" 8995) ;; #X2323 + (nil "sqsubseteq" "Relational" 8849) ;; #X2291 + (nil "sqsupseteq" "Relational" 8850) ;; #X2292 + (nil "doteq" "Relational" 8784) ;; #X2250 + (nil "frown" "Relational" 8994) ;; #X2322 + (?i "in" "Relational" 8712) ;; #X2208 + (nil "ni" "Relational" 8715) ;; #X220B + (nil "propto" "Relational" 8733) ;; #X221D + (nil "vdash" "Relational" 8866) ;; #X22A2 + (nil "dashv" "Relational" 8867) ;; #X22A3 + (?\C-b "leftarrow" "Arrows" 8592) ;; #X2190 + (nil "Leftarrow" "Arrows" 8656) ;; #X21D0 + (?\C-f "rightarrow" "Arrows" 8594) ;; #X2192 + (nil "Rightarrow" "Arrows" 8658) ;; #X21D2 + (nil "leftrightarrow" "Arrows" 8596) ;; #X2194 + (nil "Leftrightarrow" "Arrows" 8660) ;; #X21D4 + (nil "mapsto" "Arrows" 8614) ;; #X21A6 + (nil "hookleftarrow" "Arrows" 8617) ;; #X21A9 + (nil "leftharpoonup" "Arrows" 8636) ;; #X21BC + (nil "leftharpoondown" "Arrows" 8637) ;; #X21BD + (nil "longleftarrow" "Arrows" 10229) ;; #X27F5 + (nil "Longleftarrow" "Arrows" 10232) ;; #X27F8 + (nil "longrightarrow" "Arrows" 10230) ;; #X27F6 + (nil "Longrightarrow" "Arrows" 10233) ;; #X27F9 + (nil "longleftrightarrow" "Arrows" 10231) ;; #X27F7 + (nil "Longleftrightarrow" "Arrows" 10234) ;; #X27FA + (nil "iff" "Arrows" 10234) ;; #X27FA + (nil "longmapsto" "Arrows" 10236) ;; #X27FC + (nil "hookrightarrow" "Arrows" 8618) ;; #X21AA + (nil "rightharpoonup" "Arrows" 8640) ;; #X21C0 + (nil "rightharpoondown" "Arrows" 8641) ;; #X21C1 + (?\C-p "uparrow" "Arrows" 8593) ;; #X2191 + (nil "Uparrow" "Arrows" 8657) ;; #X21D1 + (?\C-n "downarrow" "Arrows" 8595) ;; #X2193 + (nil "Downarrow" "Arrows" 8659) ;; #X21D3 + (nil "updownarrow" "Arrows" 8597) ;; #X2195 + (nil "Updownarrow" "Arrows" 8661) ;; #X21D5 + (nil "nearrow" "Arrows" 8599) ;; #X2197 + (nil "searrow" "Arrows" 8600) ;; #X2198 + (nil "swarrow" "Arrows" 8601) ;; #X2199 + (nil "nwarrow" "Arrows" 8598) ;; #X2196 + (nil "ldots" "Punctuation" 8230) ;; #X2026 + (nil "cdots" "Punctuation" 8943) ;; #X22EF + (nil "vdots" "Punctuation" 8942) ;; #X22EE + (nil "ddots" "Punctuation" 8945) ;; #X22F1 + (?: "colon" "Punctuation" 58) ;; #X003A + (?N "nabla" "Misc Symbol" 8711) ;; #X2207 + (nil "aleph" "Misc Symbol" 8501) ;; #X2135 + (nil "prime" "Misc Symbol" 8242) ;; #X2032 + (?A "forall" "Misc Symbol" 8704) ;; #X2200 + (?I "infty" "Misc Symbol" 8734) ;; #X221E + (nil "hbar" "Misc Symbol" 8463) ;; #X210F + (?0 "emptyset" "Misc Symbol" 8709) ;; #X2205 + (?E "exists" "Misc Symbol" 8707) ;; #X2203 + (nil "surd" "Misc Symbol" 8730) ;; #X221A + (nil "Box" "Misc Symbol" 9633) ;; #X25A1 + (nil "triangle" "Misc Symbol" 9651) ;; #X25B3 + (nil "Diamond" "Misc Symbol" 9671) ;; #X25C7 + (nil "imath" "Misc Symbol" 120484) ;; #X1D6A4 + (nil "jmath" "Misc Symbol" 120485) ;; #X1D6A5 + (nil "ell" "Misc Symbol" 8467) ;; #X2113 + (nil "neg" "Misc Symbol" 172) ;; #X00AC + (?/ "not" "Misc Symbol" 824) ;; #X0338 + (nil "top" "Misc Symbol" 8868) ;; #X22A4 + (nil "flat" "Misc Symbol" 9837) ;; #X266D + (nil "natural" "Misc Symbol" 9838) ;; #X266E + (nil "sharp" "Misc Symbol" 9839) ;; #X266F + (nil "wp" "Misc Symbol" 8472) ;; #X2118 + (nil "bot" "Misc Symbol" 8869) ;; #X22A5 + (nil "clubsuit" "Misc Symbol" 9827) ;; #X2663 + (nil "diamondsuit" "Misc Symbol" 9826) ;; #X2662 + (nil "heartsuit" "Misc Symbol" 9825) ;; #X2661 + (nil "spadesuit" "Misc Symbol" 9824) ;; #X2660 + (nil "mho" "Misc Symbol" 8487) ;; #X2127 + (nil "Re" "Misc Symbol" 8476) ;; #X211C + (nil "Im" "Misc Symbol" 8465) ;; #X2111 + (nil "angle" "Misc Symbol" 8736) ;; #X2220 + (nil "partial" "Misc Symbol" 8706) ;; #X2202 + (nil "sum" "Var Symbol" 8721) ;; #X2211 + (nil "prod" "Var Symbol" 8719) ;; #X220F + (nil "coprod" "Var Symbol" 8720) ;; #X2210 + (nil "int" "Var Symbol" 8747) ;; #X222B + (nil "oint" "Var Symbol" 8750) ;; #X222E + (nil "bigcap" "Var Symbol" 8898) ;; #X22C2 + (nil "bigcup" "Var Symbol" 8899) ;; #X22C3 + (nil "bigsqcup" "Var Symbol" 10758) ;; #X2A06 + (nil "bigvee" "Var Symbol" 8897) ;; #X22C1 + (nil "bigwedge" "Var Symbol" 8896) ;; #X22C0 + (nil "bigodot" "Var Symbol" 10752) ;; #X2A00 + (nil "bigotimes" "Var Symbol" 10754) ;; #X2A02 + (nil "bigoplus" "Var Symbol" 10753) ;; #X2A01 + (nil "biguplus" "Var Symbol" 10756) ;; #X2A04 + (nil "arccos" "Log-like") + (nil "arcsin" "Log-like") + (nil "arctan" "Log-like") + (nil "arg" "Log-like") + (?\C-c "cos" "Log-like") + (nil "cosh" "Log-like") + (nil "cot" "Log-like") + (nil "coth" "Log-like") + (nil "csc" "Log-like") + (nil "deg" "Log-like") + (?\C-d "det" "Log-like") + (nil "dim" "Log-like") + (?\C-e "exp" "Log-like") + (nil "gcd" "Log-like") + (nil "hom" "Log-like") + (?\C-_ "inf" "Log-like") + (nil "ker" "Log-like") + (nil "lg" "Log-like") + (?\C-l "lim" "Log-like") + (nil "liminf" "Log-like") + (nil "limsup" "Log-like") + (nil "ln" "Log-like") + (nil "log" "Log-like") + (nil "max" "Log-like") + (nil "min" "Log-like") + (nil "Pr" "Log-like") + (nil "sec" "Log-like") + (?\C-s "sin" "Log-like") + (nil "sinh" "Log-like") + (?\C-^ "sup" "Log-like") + (?\C-t "tan" "Log-like") + (nil "tanh" "Log-like") + (nil "{" "Delimiters" ?{) + (nil "}" "Delimiters" ?}) + (nil "lfloor" "Delimiters" 8970) ;; #X230A + (nil "rfloor" "Delimiters" 8971) ;; #X230B + (nil "lceil" "Delimiters" 8968) ;; #X2308 + (nil "rceil" "Delimiters" 8969) ;; #X2309 + (?\( "langle" "Delimiters" 10216) ;; #X27E8 + (?\) "rangle" "Delimiters" 10217) ;; #X27E9 + (nil "rmoustache" "Delimiters" 9137) ;; #X23B1 + (nil "lmoustache" "Delimiters" 9136) ;; #X23B0 + (nil "rgroup" "Delimiters" 9133) ;; #X23AD + (nil "lgroup" "Delimiters" 9129) ;; #X23A9 + (nil "backslash" "Delimiters" 92) ;; #X005C + (nil "|" "Delimiters" 8214) ;; #X2016) + (nil "arrowvert" "Delimiters") + (nil "Arrowvert" "Delimiters") + (nil "bracevert" "Delimiters") + (nil "widetilde" "Constructs" 771) ;; #X0303 + (nil "widehat" "Constructs" 770) ;; #X0302 + (nil "overleftarrow" "Constructs" 8406) ;; #X20D6 + (nil "overrightarrow" "Constructs") + (nil "overline" "Constructs" 773) ;; #X0305 + (nil "underline" "Constructs" 818) ;; #X0332 + (nil "overbrace" "Constructs" 65079) ;; #XFE37 + (nil "underbrace" "Constructs" 65080) ;; #XFE38 + (nil "sqrt" "Constructs" 8730) ;; #X221A + (nil "frac" "Constructs") + (?^ "hat" "Accents" 770) ;; #X0302 + (nil "acute" "Accents" 769) ;; #X0301 + (nil "bar" "Accents" 772) ;; #X0304 + (nil "dot" "Accents" 775) ;; #X0307 + (nil "breve" "Accents" 774) ;; #X0306 + (nil "check" "Accents" 780) ;; #X030C + (nil "grave" "Accents" 768) ;; #X0300 + (nil "vec" "Accents" 8407) ;; #X20D7 + (nil "ddot" "Accents" 776) ;; #X0308 + (?~ "tilde" "Accents" 771) ;; #X0303 + (nil "mathring" "Accents" 778) ;; #X030A + (nil "beth" ("AMS" "Hebrew") 8502) ;; #X2136 + (nil "daleth" ("AMS" "Hebrew") 8504) ;; #X2138 + (nil "gimel" ("AMS" "Hebrew") 8503) ;; #X2137 + (nil "digamma" ("AMS" "Greek Lowercase") 989) ;; #X03DD + ("v k" "varkappa" ("AMS" "Greek Lowercase") 1008) ;; #X03F0 + ("v G" "varGamma" ("AMS" "Greek Uppercase") 120548) ;; #X1D6E4 + ("v D" "varDelta" ("AMS" "Greek Uppercase") 120549) ;; #X1D6E5 + ("v J" "varTheta" ("AMS" "Greek Uppercase") 120553) ;; #X1D6E9 + ("v L" "varLambda" ("AMS" "Greek Uppercase") 120556) ;; #X1D6EC + ("v X" "varXi" ("AMS" "Greek Uppercase") 120559) ;; #X1D6EF + ("v P" "varPi" ("AMS" "Greek Uppercase") 120561) ;; #X1D6F1 + ("v S" "varSigma" ("AMS" "Greek Uppercase") 120564) ;; #X1D6F4 + ("v U" "varUpsilon" ("AMS" "Greek Uppercase") 120566) ;; #X1D6F6 + ("v F" "varPhi" ("AMS" "Greek Uppercase") 120567) ;; #X1D6F7 + ("v Y" "varPsi" ("AMS" "Greek Uppercase") 120569) ;; #X1D6F9 + ("v W" "varOmega" ("AMS" "Greek Uppercase") 120570) ;; #X1D6FA + (nil "dashrightarrow" ("AMS" "Arrows")) + (nil "dashleftarrow" ("AMS" "Arrows")) + (nil "impliedby" ("AMS" "Arrows") 10232) ;; #X27F8 + (nil "implies" ("AMS" "Arrows") 10233) ;; #X27F9 + (nil "leftleftarrows" ("AMS" "Arrows") 8647) ;; #X21C7 + (nil "leftrightarrows" ("AMS" "Arrows") 8646) ;; #X21C6 + (nil "Lleftarrow" ("AMS" "Arrows") 8666) ;; #X21DA + (nil "twoheadleftarrow" ("AMS" "Arrows") 8606) ;; #X219E + (nil "leftarrowtail" ("AMS" "Arrows") 8610) ;; #X21A2 + (nil "looparrowleft" ("AMS" "Arrows") 8619) ;; #X21AB + (nil "leftrightharpoons" ("AMS" "Arrows") 8651) ;; #X21CB + (nil "curvearrowleft" ("AMS" "Arrows") 8630) ;; #X21B6 + (nil "circlearrowleft" ("AMS" "Arrows") 8634) ;; #X21BA + (nil "Lsh" ("AMS" "Arrows") 8624) ;; #X21B0 + (nil "upuparrows" ("AMS" "Arrows") 8648) ;; #X21C8 + (nil "upharpoonleft" ("AMS" "Arrows") 8639) ;; #X21BF + (nil "downharpoonleft" ("AMS" "Arrows") 8643) ;; #X21C3 + (nil "multimap" ("AMS" "Arrows") 8888) ;; #X22B8 + (nil "leftrightsquigarrow" ("AMS" "Arrows") 8621) ;; #X21AD + (nil "looparrowright" ("AMS" "Arrows") 8620) ;; #X21AC + (nil "rightleftharpoons" ("AMS" "Arrows") 8652) ;; #X21CC + (nil "curvearrowright" ("AMS" "Arrows") 8631) ;; #X21B7 + (nil "circlearrowright" ("AMS" "Arrows")) + (nil "Rsh" ("AMS" "Arrows") 8625) ;; #X21B1 + (nil "downdownarrows" ("AMS" "Arrows") 8650) ;; #X21CA + (nil "upharpoonright" ("AMS" "Arrows") 8638) ;; #X21BE + (nil "downharpoonright" ("AMS" "Arrows") 8642) ;; #X21C2 + (nil "rightsquigarrow" ("AMS" "Arrows") 8605) ;; #X219D + (nil "nleftarrow" ("AMS" "Neg Arrows") 8602) ;; #X219A + (nil "nrightarrow" ("AMS" "Neg Arrows") 8603) ;; #X219B + (nil "nLeftarrow" ("AMS" "Neg Arrows") 8653) ;; #X21CD + (nil "nRightarrow" ("AMS" "Neg Arrows") 8655) ;; #X21CF + (nil "nleftrightarrow" ("AMS" "Neg Arrows") 8622) ;; #X21AE + (nil "nLeftrightarrow" ("AMS" "Neg Arrows") 8654) ;; #X21CE + (nil "leqq" ("AMS" "Relational I") 8806) ;; #X2266 + (nil "leqslant" ("AMS" "Relational I") 10877) ;; #X2A7D + (nil "eqslantless" ("AMS" "Relational I") 10901) ;; #X2A95 + (nil "lesssim" ("AMS" "Relational I") 8818) ;; #X2272 + (nil "lessapprox" ("AMS" "Relational I") 10885) ;; #X2A85 + (nil "approxeq" ("AMS" "Relational I") 8778) ;; #X224A + (nil "lessdot" ("AMS" "Relational I") 8918) ;; #X22D6 + (nil "lll" ("AMS" "Relational I") 8920) ;; #X22D8 + (nil "lessgtr" ("AMS" "Relational I") 8822) ;; #X2276 + (nil "lesseqgtr" ("AMS" "Relational I") 8922) ;; #X22DA + (nil "lesseqqgtr" ("AMS" "Relational I") 10891) ;; #X2A8B + (nil "doteqdot" ("AMS" "Relational I") 8785) ;; #X2251 + (nil "risingdotseq" ("AMS" "Relational I") 8787) ;; #X2253 + (nil "fallingdotseq" ("AMS" "Relational I") 8786) ;; #X2252 + (nil "backsim" ("AMS" "Relational I") 8765) ;; #X223D + (nil "backsimeq" ("AMS" "Relational I") 8909) ;; #X22CD + (nil "subseteqq" ("AMS" "Relational I") 10949) ;; #X2AC5 + (nil "Subset" ("AMS" "Relational I") 8912) ;; #X22D0 + (nil "sqsubset" ("AMS" "Relational I") 8847) ;; #X228F + (nil "preccurlyeq" ("AMS" "Relational I") 8828) ;; #X227C + (nil "curlyeqprec" ("AMS" "Relational I") 8926) ;; #X22DE + (nil "precsim" ("AMS" "Relational I") 8830) ;; #X227E + (nil "precapprox" ("AMS" "Relational I") 10935) ;; #X2AB7 + (nil "vartriangleleft" ("AMS" "Relational I") 8882) ;; #X22B2 + (nil "trianglelefteq" ("AMS" "Relational I") 8884) ;; #X22B4 + (nil "vDash" ("AMS" "Relational I") 8872) ;; #X22A8 + (nil "Vvdash" ("AMS" "Relational I") 8874) ;; #X22AA + (nil "smallsmile" ("AMS" "Relational I") 8995) ;; #X2323 + (nil "smallfrown" ("AMS" "Relational I") 8994) ;; #X2322 + (nil "bumpeq" ("AMS" "Relational I") 8783) ;; #X224F + (nil "Bumpeq" ("AMS" "Relational I") 8782) ;; #X224E + (nil "geqq" ("AMS" "Relational II") 8807) ;; #X2267 + (nil "geqslant" ("AMS" "Relational II") 10878) ;; #X2A7E + (nil "eqslantgtr" ("AMS" "Relational II") 10902) ;; #X2A96 + (nil "gtrsim" ("AMS" "Relational II") 8819) ;; #X2273 + (nil "gtrapprox" ("AMS" "Relational II") 10886) ;; #X2A86 + (nil "gtrdot" ("AMS" "Relational II") 8919) ;; #X22D7 + (nil "ggg" ("AMS" "Relational II") 8921) ;; #X22D9 + (nil "gtrless" ("AMS" "Relational II") 8823) ;; #X2277 + (nil "gtreqless" ("AMS" "Relational II") 8923) ;; #X22DB + (nil "gtreqqless" ("AMS" "Relational II") 10892) ;; #X2A8C + (nil "eqcirc" ("AMS" "Relational II") 8790) ;; #X2256 + (nil "circeq" ("AMS" "Relational II") 8791) ;; #X2257 + (nil "triangleq" ("AMS" "Relational II") 8796) ;; #X225C + (nil "thicksim" ("AMS" "Relational II") 8764) ;; #X223C + (nil "thickapprox" ("AMS" "Relational II") 8776) ;; #X2248 + (nil "supseteqq" ("AMS" "Relational II") 10950) ;; #X2AC6 + (nil "Supset" ("AMS" "Relational II") 8913) ;; #X22D1 + (nil "sqsupset" ("AMS" "Relational II") 8848) ;; #X2290 + (nil "succcurlyeq" ("AMS" "Relational II") 8829) ;; #X227D + (nil "curlyeqsucc" ("AMS" "Relational II") 8927) ;; #X22DF + (nil "succsim" ("AMS" "Relational II") 8831) ;; #X227F + (nil "succapprox" ("AMS" "Relational II") 10936) ;; #X2AB8 + (nil "vartriangleright" ("AMS" "Relational II") 8883) ;; #X22B3 + (nil "trianglerighteq" ("AMS" "Relational II") 8885) ;; #X22B5 + (nil "Vdash" ("AMS" "Relational II") 8873) ;; #X22A9 + (nil "shortmid" ("AMS" "Relational II") 8739) ;; #X2223 + (nil "shortparallel" ("AMS" "Relational II") 8741) ;; #X2225 + (nil "between" ("AMS" "Relational II") 8812) ;; #X226C + (nil "pitchfork" ("AMS" "Relational II") 8916) ;; #X22D4 + (nil "varpropto" ("AMS" "Relational II") 8733) ;; #X221D + (nil "blacktriangleleft" ("AMS" "Relational II") 9664) ;; #X25C0 + (nil "therefore" ("AMS" "Relational II") 8756) ;; #X2234 + (nil "backepsilon" ("AMS" "Relational II") 1014) ;; #X03F6 + (nil "blacktriangleright" ("AMS" "Relational II") 9654) ;; #X25B6 + (nil "because" ("AMS" "Relational II") 8757) ;; #X2235 + (nil "nless" ("AMS" "Neg Rel I") 8814) ;; #X226E + (nil "nleq" ("AMS" "Neg Rel I") 8816) ;; #X2270 + (nil "nleqslant" ("AMS" "Neg Rel I")) + (nil "nleqq" ("AMS" "Neg Rel I")) + (nil "lneq" ("AMS" "Neg Rel I") 10887) ;; #X2A87 + (nil "lneqq" ("AMS" "Neg Rel I") 8808) ;; #X2268 + (nil "lvertneqq" ("AMS" "Neg Rel I")) + (nil "lnsim" ("AMS" "Neg Rel I") 8934) ;; #X22E6 + (nil "lnapprox" ("AMS" "Neg Rel I") 10889) ;; #X2A89 + (nil "nprec" ("AMS" "Neg Rel I") 8832) ;; #X2280 + (nil "npreceq" ("AMS" "Neg Rel I")) + (nil "precnsim" ("AMS" "Neg Rel I") 8936) ;; #X22E8 + (nil "precnapprox" ("AMS" "Neg Rel I") 10937) ;; #X2AB9 + (nil "nsim" ("AMS" "Neg Rel I") 8769) ;; #X2241 + (nil "nshortmid" ("AMS" "Neg Rel I") 8740) ;; #X2224 + (nil "nmid" ("AMS" "Neg Rel I") 8740) ;; #X2224 + (nil "nvdash" ("AMS" "Neg Rel I") 8876) ;; #X22AC + (nil "nvDash" ("AMS" "Neg Rel I") 8877) ;; #X22AD + (nil "ntriangleleft" ("AMS" "Neg Rel I") 8938) ;; #X22EA + (nil "ntrianglelefteq" ("AMS" "Neg Rel I") 8940) ;; #X22EC + (nil "nsubseteq" ("AMS" "Neg Rel I") 8840) ;; #X2288 + (nil "subsetneq" ("AMS" "Neg Rel I") 8842) ;; #X228A + (nil "varsubsetneq" ("AMS" "Neg Rel I")) + (nil "subsetneqq" ("AMS" "Neg Rel I") 10955) ;; #X2ACB + (nil "varsubsetneqq" ("AMS" "Neg Rel I")) + (nil "ngtr" ("AMS" "Neg Rel II") 8815) ;; #X226F + (nil "ngeq" ("AMS" "Neg Rel II") 8817) ;; #X2271 + (nil "ngeqslant" ("AMS" "Neg Rel II")) + (nil "ngeqq" ("AMS" "Neg Rel II")) + (nil "gneq" ("AMS" "Neg Rel II") 10888) ;; #X2A88 + (nil "gneqq" ("AMS" "Neg Rel II") 8809) ;; #X2269 + (nil "gvertneqq" ("AMS" "Neg Rel II")) + (nil "gnsim" ("AMS" "Neg Rel II") 8935) ;; #X22E7 + (nil "gnapprox" ("AMS" "Neg Rel II") 10890) ;; #X2A8A + (nil "nsucc" ("AMS" "Neg Rel II") 8833) ;; #X2281 + (nil "nsucceq" ("AMS" "Neg Rel II")) + (nil "succnsim" ("AMS" "Neg Rel II") 8937) ;; #X22E9 + (nil "succnapprox" ("AMS" "Neg Rel II") 10938) ;; #X2ABA + (nil "ncong" ("AMS" "Neg Rel II") 8775) ;; #X2247 + (nil "nshortparallel" ("AMS" "Neg Rel II") 8742) ;; #X2226 + (nil "nparallel" ("AMS" "Neg Rel II") 8742) ;; #X2226 + (nil "nvDash" ("AMS" "Neg Rel II") 8877) ;; #X22AD + (nil "nVDash" ("AMS" "Neg Rel II") 8879) ;; #X22AF + (nil "ntriangleright" ("AMS" "Neg Rel II") 8939) ;; #X22EB + (nil "ntrianglerighteq" ("AMS" "Neg Rel II") 8941) ;; #X22ED + (nil "nsupseteq" ("AMS" "Neg Rel II") 8841) ;; #X2289 + (nil "nsupseteqq" ("AMS" "Neg Rel II")) + (nil "supsetneq" ("AMS" "Neg Rel II") 8843) ;; #X228B + (nil "varsupsetneq" ("AMS" "Neg Rel II")) + (nil "supsetneqq" ("AMS" "Neg Rel II") 10956) ;; #X2ACC + (nil "varsupsetneqq" ("AMS" "Neg Rel II")) + (nil "dotplus" ("AMS" "Binary Op") 8724) ;; #X2214 + (nil "smallsetminus" ("AMS" "Binary Op") 8726) ;; #X2216 + (nil "Cap" ("AMS" "Binary Op") 8914) ;; #X22D2 + (nil "Cup" ("AMS" "Binary Op") 8915) ;; #X22D3 + (nil "barwedge" ("AMS" "Binary Op") 8892) ;; #X22BC + (nil "veebar" ("AMS" "Binary Op") 8891) ;; #X22BB + (nil "doublebarwedge" ("AMS" "Binary Op") 8966) ;; #X2306 + (nil "boxminus" ("AMS" "Binary Op") 8863) ;; #X229F + (nil "boxtimes" ("AMS" "Binary Op") 8864) ;; #X22A0 + (nil "boxdot" ("AMS" "Binary Op") 8865) ;; #X22A1 + (nil "boxplus" ("AMS" "Binary Op") 8862) ;; #X229E + (nil "divideontimes" ("AMS" "Binary Op") 8903) ;; #X22C7 + (nil "ltimes" ("AMS" "Binary Op") 8905) ;; #X22C9 + (nil "rtimes" ("AMS" "Binary Op") 8906) ;; #X22CA + (nil "leftthreetimes" ("AMS" "Binary Op") 8907) ;; #X22CB + (nil "rightthreetimes" ("AMS" "Binary Op") 8908) ;; #X22CC + (nil "curlywedge" ("AMS" "Binary Op") 8911) ;; #X22CF + (nil "curlyvee" ("AMS" "Binary Op") 8910) ;; #X22CE + (nil "circleddash" ("AMS" "Binary Op") 8861) ;; #X229D + (nil "circledast" ("AMS" "Binary Op") 8859) ;; #X229B + (nil "circledcirc" ("AMS" "Binary Op") 8858) ;; #X229A + (nil "centerdot" ("AMS" "Binary Op")) + (nil "intercal" ("AMS" "Binary Op") 8890) ;; #X22BA + (nil "hbar" ("AMS" "Misc") 8463) ;; #X210F + (nil "hslash" ("AMS" "Misc") 8463) ;; #X210F + (nil "vartriangle" ("AMS" "Misc") 9653) ;; #X25B5 + (nil "triangledown" ("AMS" "Misc") 9663) ;; #X25BF + (nil "square" ("AMS" "Misc") 9633) ;; #X25A1 + (nil "lozenge" ("AMS" "Misc") 9674) ;; #X25CA + (nil "circledS" ("AMS" "Misc") 9416) ;; #X24C8 + (nil "angle" ("AMS" "Misc") 8736) ;; #X2220 + (nil "measuredangle" ("AMS" "Misc") 8737) ;; #X2221 + (nil "nexists" ("AMS" "Misc") 8708) ;; #X2204 + (nil "mho" ("AMS" "Misc") 8487) ;; #X2127 + (nil "Finv" ("AMS" "Misc") 8498) ;; #X2132 + (nil "Game" ("AMS" "Misc") 8513) ;; #X2141 + (nil "Bbbk" ("AMS" "Misc") 120156) ;; #X1D55C + (nil "backprime" ("AMS" "Misc") 8245) ;; #X2035 + (nil "varnothing" ("AMS" "Misc") 8709) ;; #X2205 + (nil "blacktriangle" ("AMS" "Misc") 9652) ;; #X25B4 + (nil "blacktriangledown" ("AMS" "Misc") 9662) ;; #X25BE + (nil "blacksquare" ("AMS" "Misc") 9632) ;; #X25A0 + (nil "blacklozenge" ("AMS" "Misc") 10731) ;; #X29EB + (nil "bigstar" ("AMS" "Misc") 9733) ;; #X2605 + (nil "sphericalangle" ("AMS" "Misc") 8738) ;; #X2222 + (nil "complement" ("AMS" "Misc") 8705) ;; #X2201 + (nil "eth" ("AMS" "Misc") 240) ;; #X00F0 + (nil "diagup" ("AMS" "Misc") 9585) ;; #X2571 + (nil "diagdown" ("AMS" "Misc") 9586) ;; #X2572 + (nil "dddot" ("AMS" "Accents") 8411) ;; #X20DB + (nil "ddddot" ("AMS" "Accents") 8412) ;; #X20DC + (nil "bigl" ("AMS" "Delimiters")) + (nil "bigr" ("AMS" "Delimiters")) + (nil "Bigl" ("AMS" "Delimiters")) + (nil "Bigr" ("AMS" "Delimiters")) + (nil "biggl" ("AMS" "Delimiters")) + (nil "biggr" ("AMS" "Delimiters")) + (nil "Biggl" ("AMS" "Delimiters")) + (nil "Biggr" ("AMS" "Delimiters")) + (nil "lvert" ("AMS" "Delimiters")) + (nil "rvert" ("AMS" "Delimiters")) + (nil "lVert" ("AMS" "Delimiters")) + (nil "rVert" ("AMS" "Delimiters")) + (nil "ulcorner" ("AMS" "Delimiters") 8988) ;; #X231C + (nil "urcorner" ("AMS" "Delimiters") 8989) ;; #X231D + (nil "llcorner" ("AMS" "Delimiters") 8990) ;; #X231E + (nil "lrcorner" ("AMS" "Delimiters") 8991) ;; #X231F + (nil "nobreakdash" ("AMS" "Special")) + (nil "leftroot" ("AMS" "Special")) + (nil "uproot" ("AMS" "Special")) + (nil "accentedsymbol" ("AMS" "Special")) + (nil "xleftarrow" ("AMS" "Special")) + (nil "xrightarrow" ("AMS" "Special")) + (nil "overset" ("AMS" "Special")) + (nil "underset" ("AMS" "Special")) + (nil "dfrac" ("AMS" "Special")) + (nil "genfrac" ("AMS" "Special")) + (nil "tfrac" ("AMS" "Special")) + (nil "binom" ("AMS" "Special")) + (nil "dbinom" ("AMS" "Special")) + (nil "tbinom" ("AMS" "Special")) + (nil "smash" ("AMS" "Special")) + (nil "eucal" ("AMS" "Special")) + (nil "boldsymbol" ("AMS" "Special")) + (nil "text" ("AMS" "Special")) + (nil "intertext" ("AMS" "Special")) + (nil "substack" ("AMS" "Special")) + (nil "subarray" ("AMS" "Special")) + (nil "sideset" ("AMS" "Special"))) + "Alist of LaTeX math symbols. + +Each entry should be a list with upto four elements, KEY, VALUE, +MENU and CHARACTER, see `LaTeX-math-list' for details.") + +(defcustom LaTeX-math-menu-unicode + (or (string-match "\\" (emacs-version)) + (eq window-system 'w32)) + "Whether the LaTeX menu should try using Unicode for effect." + :type 'boolean + :group 'LaTeX-math) + +(defvar LaTeX-math-list) ;; Defined further below. + +(defun LaTeX-math-initialize () + (let ((math (reverse (append LaTeX-math-list LaTeX-math-default))) + (map LaTeX-math-keymap) + (unicode LaTeX-math-menu-unicode)) + (while math + (let* ((entry (car math)) + (key (nth 0 entry)) + (prefix + (and unicode + (nth 3 entry))) + value menu name) + (setq math (cdr math)) + (if (and prefix + (setq prefix (nth 3 entry))) + (setq prefix (concat (string prefix) " \\")) + (setq prefix "\\")) + (if (listp (cdr entry)) + (setq value (nth 1 entry) + menu (nth 2 entry)) + (setq value (cdr entry) + menu nil)) + (if (stringp value) + (progn + (setq name (intern (concat "LaTeX-math-" value))) + (fset name (lambda (arg) (interactive "*P") + (LaTeX-math-insert value arg)))) + (setq name value)) + (if key + (progn + (setq key (cond ((numberp key) (char-to-string key)) + ((stringp key) (read-kbd-macro key)) + (t (vector key)))) + (define-key map key name))) + (if menu + (let ((parent LaTeX-math-menu)) + (if (listp menu) + (progn + (while (cdr menu) + (let ((sub (assoc (car menu) LaTeX-math-menu))) + (if sub + (setq parent sub) + (setcdr parent (cons (list (car menu)) (cdr parent)))) + (setq menu (cdr menu)))) + (setq menu (car menu)))) + (let ((sub (assoc menu parent))) + (if sub + (if (stringp value) + (setcdr sub (cons (vector (concat prefix value) + name t) + (cdr sub))) + (error "Cannot have multiple special math menu items")) + (setcdr parent + (cons (if (stringp value) + (list menu (vector (concat prefix value) + name t)) + (vector menu name t)) + (cdr parent))))))))) + ;; Make the math prefix char available if it has not been used as a prefix. + (unless (lookup-key map (LaTeX-math-abbrev-prefix)) + (define-key map (LaTeX-math-abbrev-prefix) #'self-insert-command)))) + +(defcustom LaTeX-math-list nil + "Alist of your personal LaTeX math symbols. + +Each entry should be a list with up to four elements, KEY, VALUE, +MENU and CHARACTER. + +KEY is the key (after `LaTeX-math-abbrev-prefix') to be redefined +in math minor mode. KEY can be a character (for example ?o) for a +single stroke or a string (for example \"o a\") for a multi-stroke +binding. If KEY is nil, the symbol has no associated +keystroke (it is available in the menu, though). Note that +predefined keys in `LaTeX-math-default' cannot be overridden in +this variable. Currently, only the lowercase letter 'o' is free +for user customization, more options are available in uppercase +area. + +VALUE can be a string with the name of the macro to be inserted, +or a function to be called. The macro must be given without the +leading backslash. + +The third element MENU is the name of the submenu where the +command should be added. MENU can be either a string (for +example \"greek\"), a list (for example (\"AMS\" \"Delimiters\")) +or nil. If MENU is nil, no menu item will be created. + +The fourth element CHARACTER is a Unicode character position for +menu display. When nil, no character is shown. + +See also `LaTeX-math-menu'." + :group 'LaTeX-math + :set (lambda (symbol value) + (set-default symbol value) + (LaTeX-math-initialize)) + :type '(repeat (group (choice :tag "Key" + (const :tag "none" nil) + (choice (character) + (string :tag "Key sequence"))) + (choice :tag "Value" + (string :tag "Macro") + (function)) + (choice :tag "Menu" + (string :tag "Top level menu" ) + (repeat :tag "Submenu" + (string :tag "Menu"))) + (choice :tag "Unicode character" + (const :tag "none" nil) + (integer :tag "Number"))))) + +(defun LaTeX--completion-annotation-from-math-menu (sym) + "Return a completion annotation for a SYM. +The annotation is usually a unicode representation of the macro +SYM's compiled representation, e.g., if SYM is alpha, α is +returned." + (catch 'found + (dolist (var (list LaTeX-math-list LaTeX-math-default)) + (dolist (e var) + (let ((val (cadr e))) + (when (and (stringp val) + (string= val sym)) + (let ((char (nth 3 e))) + (when char + (throw 'found + (concat " " (char-to-string char))))))))))) + +(defvar LaTeX-math-mode-menu) +(define-minor-mode LaTeX-math-mode + "A minor mode with easy access to TeX math macros. + +Easy insertion of LaTeX math symbols. If you give a prefix argument, +the symbols will be surrounded by dollar signs. The following +commands are defined: + +\\{LaTeX-math-mode-map}" + :init-value nil + :lighter nil + :keymap (list (cons (LaTeX-math-abbrev-prefix) LaTeX-math-keymap)) + (TeX-set-mode-name)) +(defalias 'latex-math-mode #'LaTeX-math-mode) + +(easy-menu-define LaTeX-math-mode-menu + LaTeX-math-mode-map + "Menu used in math minor mode." + LaTeX-math-menu) + +(defcustom LaTeX-math-insert-function #'TeX-insert-macro + "Function called with argument STRING to insert \\STRING." + :group 'LaTeX-math + :type 'function) + +(defun LaTeX-math-insert (string dollar) + "Insert \\STRING{}. If DOLLAR is non-nil, put $'s around it. +If `TeX-electric-math' is non-nil wrap that symbols around the +string." + (let ((active (TeX-active-mark)) + m closer) + (if (and active (> (point) (mark))) + (exchange-point-and-mark)) + (when dollar + (insert (or (car TeX-electric-math) "$")) + (save-excursion + (if active (goto-char (mark))) + ;; Store closer string for later reference. + (setq closer (or (cdr TeX-electric-math) "$")) + (insert closer) + ;; Set temporal marker to decide whether to put the point + ;; after the math mode closer or not. + (setq m (point-marker)))) + (funcall LaTeX-math-insert-function string) + (when dollar + ;; If the above `LaTeX-math-insert-function' resulted in + ;; inserting, e.g., a pair of "\langle" and "\rangle" by + ;; typing "`(", keep the point between them. Otherwise + ;; move the point after the math mode closer. + (if (= m (+ (point) (length closer))) + (goto-char m)) + ;; Make temporal marker point nowhere not to slow down the + ;; subsequent editing in the buffer. + (set-marker m nil)))) + +(defun LaTeX-math-cal (char dollar) + "Insert a {\\cal CHAR}. If DOLLAR is non-nil, put $'s around it. +If `TeX-electric-math' is non-nil wrap that symbols around the +char." + (interactive "*c\nP") + (if dollar (insert (or (car TeX-electric-math) "$"))) + (if (member "latex2e" (TeX-style-list)) + (insert "\\mathcal{" (char-to-string char) "}") + (insert "{\\cal " (char-to-string char) "}")) + (if dollar (insert (or (cdr TeX-electric-math) "$")))) + + +;;; Folding + +(defcustom LaTeX-fold-macro-spec-list nil + "List of display strings and macros to fold in LaTeX mode." + :type '(repeat (group (choice (string :tag "Display String") + (integer :tag "Number of argument" :value 1)) + (repeat :tag "Macros" (string)))) + :group 'TeX-fold) + +(defcustom LaTeX-fold-env-spec-list nil + "List of display strings and environments to fold in LaTeX mode." + :type '(repeat (group (choice (string :tag "Display String") + (integer :tag "Number of argument" :value 1)) + (repeat :tag "Environments" (string)))) + :group 'TeX-fold) + +(defcustom LaTeX-fold-math-spec-list + (delete nil + (mapcar (lambda (elt) + (let ((tex-token (nth 1 elt)) + (submenu (nth 2 elt)) + (unicode (nth 3 elt)) + uchar noargp) + (when (integerp unicode) + (setq uchar unicode)) + (when (listp submenu) (setq submenu (nth 1 submenu))) + (setq noargp + (not (string-match + (concat "^" (regexp-opt '("Constructs" + "Accents"))) + submenu))) + (when (and (stringp tex-token) (integerp uchar) noargp) + `(,(char-to-string uchar) (,tex-token))))) + `((nil "to" "" 8594) + (nil "gets" "" 8592) + ,@LaTeX-math-default))) + "List of display strings and math macros to fold in LaTeX mode." + :type '(repeat (group (choice (string :tag "Display String") + (integer :tag "Number of argument" :value 1)) + (repeat :tag "Math Macros" (string)))) + :group 'TeX-fold) + +;;; Narrowing + +(defun LaTeX-narrow-to-environment (&optional count) + "Make text outside current environment invisible. +With optional COUNT keep visible that number of enclosing +environments." + (interactive "p") + (setq count (if count (abs count) 1)) + (save-excursion + (widen) + (let ((opoint (point)) + beg end) + (dotimes (_ count) (LaTeX-find-matching-end)) + (setq end (point)) + (goto-char opoint) + (dotimes (_ count) (LaTeX-find-matching-begin)) + (setq beg (point)) + (narrow-to-region beg end)))) +(put 'LaTeX-narrow-to-environment 'disabled t) + +;;; Keymap + +(defvar LaTeX-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map TeX-mode-map) + + ;; Standard + (define-key map "\n" #'reindent-then-newline-and-indent) + + ;; From latex.el + ;; We now set `fill-paragraph-function' instead. + ;; (define-key map "\eq" 'LaTeX-fill-paragraph) ;*** Alias + ;; This key is now used by Emacs for face settings. + ;; (define-key map "\eg" 'LaTeX-fill-region) ;*** Alias + ;; We now set `beginning-of-defun-function' and + ;; `end-of-defun-function' instead. + ;; (define-key map "\e\C-e" #'LaTeX-find-matching-end) + ;; (define-key map "\e\C-a" #'LaTeX-find-matching-begin) + + (define-key map "\C-c\C-q\C-p" #'LaTeX-fill-paragraph) + (define-key map "\C-c\C-q\C-r" #'LaTeX-fill-region) + (define-key map "\C-c\C-q\C-s" #'LaTeX-fill-section) + (define-key map "\C-c\C-q\C-e" #'LaTeX-fill-environment) + + (define-key map "\C-c\C-z" #'LaTeX-command-section) + (define-key map "\C-c\M-z" #'LaTeX-command-section-change-level) + + (define-key map "\C-c." #'LaTeX-mark-environment) ;*** Dubious + (define-key map "\C-c*" #'LaTeX-mark-section) ;*** Dubious + + (define-key map "\C-c\C-e" #'LaTeX-environment) + (define-key map "\C-c\n" #'LaTeX-insert-item) + (or (key-binding "\e\r") + (define-key map "\e\r" #'LaTeX-insert-item)) ;*** Alias + (define-key map "\C-c]" #'LaTeX-close-environment) + (define-key map "\C-c\C-s" #'LaTeX-section) + + (define-key map "\C-c~" #'LaTeX-math-mode) ;*** Dubious + + (define-key map "-" #'LaTeX-babel-insert-hyphen) + (define-key map "(" #'LaTeX-insert-left-brace) + (define-key map "{" #'LaTeX-insert-left-brace) + (define-key map "[" #'LaTeX-insert-left-brace) + + (define-key map "\C-xne" #'LaTeX-narrow-to-environment) + map) + "Keymap used in `LaTeX-mode'.") + +(defvar LaTeX-environment-menu-name "Insert Environment (C-c C-e)") + +(defun LaTeX-environment-menu-entry (entry) + "Create an ENTRY for the environment menu." + (vector (car entry) (list #'LaTeX-environment-menu (car entry)) t)) + +(defvar LaTeX-environment-modify-menu-name "Change Environment (C-u C-c C-e)") + +(defun LaTeX-environment-modify-menu-entry (entry) + "Create an ENTRY for the change environment menu." + (vector (car entry) (list #'LaTeX-modify-environment (car entry)) t)) + +(defun LaTeX-section-enable-symbol (level) + "Symbol used to enable section LEVEL in the menu bar." + (intern (concat "LaTeX-section-" (int-to-string level) "-enable"))) + +(defun LaTeX-section-enable (entry) + "Enable or disable section ENTRY from `LaTeX-section-list'." + (let* ((level (nth 1 entry)) + (symbol (LaTeX-section-enable-symbol level))) + (set symbol (or (= level 0) (>= level LaTeX-largest-level))) + (make-variable-buffer-local symbol))) + +(defun LaTeX-section-menu (level) + "Insert section from menu." + (let ((LaTeX-section-hook (delq 'LaTeX-section-heading + (copy-sequence LaTeX-section-hook)))) + (LaTeX-section level))) + +(defun LaTeX-section-menu-entry (entry) + "Create an ENTRY for the section menu." + (let ((enable (LaTeX-section-enable-symbol (nth 1 entry)))) + (vector (car entry) (list #'LaTeX-section-menu (nth 1 entry)) enable))) + +(defcustom LaTeX-menu-max-items 25 + "Maximum number of items in the menu for LaTeX environments. +If number of entries in a menu is larger than this value, split menu +into submenus of nearly equal length. If nil, never split menu into +submenus." + :group 'LaTeX-environment + :type '(choice (const :tag "no submenus" nil) + (integer))) + +(defcustom LaTeX-submenu-name-format "%-12.12s ... %.12s" + "Format specification of the submenu name. +Used by `LaTeX-split-long-menu' if the number of entries in a menu is +larger than `LaTeX-menu-max-items'. +This string should contain one %s for the name of the first entry and +one %s for the name of the last entry in the submenu. +If the value is a function, it should return the submenu name. The +function is called with two arguments, the names of the first and +the last entry in the menu." + :group 'LaTeX-environment + :type '(choice (string :tag "Format string") + (function))) + +(defun LaTeX-split-long-menu (menu) + "Split MENU according to `LaTeX-menu-max-items'." + (let ((len (length menu))) + (if (or (null LaTeX-menu-max-items) + (null (featurep 'lisp-float-type)) + (<= len LaTeX-menu-max-items)) + menu + ;; Submenu is max 2 entries longer than menu, never shorter, number of + ;; entries in submenus differ by at most one (with longer submenus first) + (let* ((outer (floor (sqrt len))) + (inner (/ len outer)) + (rest (% len outer)) + (result nil)) + (setq menu (reverse menu)) + (while menu + (let ((in inner) + (sub nil) + (to (car menu))) + (while (> in 0) + (setq in (1- in) + sub (cons (car menu) sub) + menu (cdr menu))) + (setq result + (cons (cons (if (stringp LaTeX-submenu-name-format) + (format LaTeX-submenu-name-format + (aref (car sub) 0) (aref to 0)) + (funcall LaTeX-submenu-name-format + (aref (car sub) 0) (aref to 0))) + sub) + result) + rest (1+ rest)) + (if (= rest outer) (setq inner (1+ inner))))) + result)))) + +(defun LaTeX-section-menu-filter (_ignored) + "Filter function for the section submenu in the mode menu. +The argument IGNORED is not used in any way." + (TeX-update-style) + (or LaTeX-section-menu + (progn + (setq LaTeX-section-list-changed nil) + (mapc #'LaTeX-section-enable LaTeX-section-list) + (setq LaTeX-section-menu + (mapcar #'LaTeX-section-menu-entry LaTeX-section-list))))) + +(defvar LaTeX-environment-menu nil) +(make-variable-buffer-local 'LaTeX-environment-menu) +(defvar LaTeX-environment-modify-menu nil) +(make-variable-buffer-local 'LaTeX-environment-modify-menu) +(defun LaTeX-environment-menu-filter (menu) + "Filter function for the environment submenus in the mode menu. +The argument MENU is the name of the submenu in concern and +corresponds to the variables `LaTeX-environment-menu-name' and +`LaTeX-environment-modify-menu-name'." + (TeX-update-style) + (cond + ((string= menu LaTeX-environment-menu-name) + (or LaTeX-environment-menu + (setq LaTeX-environment-menu + (LaTeX-split-long-menu + (mapcar #'LaTeX-environment-menu-entry + (LaTeX-environment-list)))))) + ((string= menu LaTeX-environment-modify-menu-name) + (or LaTeX-environment-modify-menu + (setq LaTeX-environment-modify-menu + (LaTeX-split-long-menu + (mapcar #'LaTeX-environment-modify-menu-entry + (LaTeX-environment-list)))))))) + +(advice-add 'LaTeX-add-environments :after #'LaTeX--invalidate-menus) +(defun LaTeX--invalidate-menus (&rest _) + "Mark the environment menus as being in need of a refresh." + (setq LaTeX-environment-menu nil) + (setq LaTeX-environment-modify-menu nil)) + +(easy-menu-define LaTeX-mode-command-menu + LaTeX-mode-map + "Command menu used in LaTeX mode." + (TeX-mode-specific-command-menu 'latex-mode)) + +(easy-menu-define LaTeX-mode-menu + LaTeX-mode-map + "Menu used in LaTeX mode." + `("LaTeX" + ("Section (C-c C-s)" :filter LaTeX-section-menu-filter) + ["Macro..." TeX-insert-macro + :help "Insert a macro and possibly arguments"] + ["Complete Macro" TeX-complete-symbol + :help "Complete the current macro or environment name"] + ,(list LaTeX-environment-menu-name + :filter (lambda (_ignored) + (LaTeX-environment-menu-filter + LaTeX-environment-menu-name))) + ,(list LaTeX-environment-modify-menu-name + :filter (lambda (_ignored) + (LaTeX-environment-menu-filter + LaTeX-environment-modify-menu-name))) + ["Close Environment" LaTeX-close-environment + :help "Insert the \\end part of the current environment"] + ["Item" LaTeX-insert-item + :help "Insert a new \\item into current environment"] + "-" + ("Insert Font" + ["Emphasize" (TeX-font nil ?\C-e) :keys "C-c C-f C-e"] + "-" + ["Roman" (TeX-font nil ?\C-r) :keys "C-c C-f C-r"] + ["Sans Serif" (TeX-font nil ?\C-f) :keys "C-c C-f C-f"] + ["Typewriter" (TeX-font nil ?\C-t) :keys "C-c C-f C-t"] + "-" + ["Medium" (TeX-font nil ?\C-m) :keys "C-c C-f C-m"] + ["Bold" (TeX-font nil ?\C-b) :keys "C-c C-f C-b"] + "-" + ["Italic" (TeX-font nil ?\C-i) :keys "C-c C-f C-i"] + ["Slanted" (TeX-font nil ?\C-s) :keys "C-c C-f C-s"] + ["Small Caps" (TeX-font nil ?\C-c) :keys "C-c C-f C-c"] + ["Swash" (TeX-font nil ?\C-w) :keys "C-c C-f C-w"] + ["Upper Lower" (TeX-font nil ?\C-l) :keys "C-c C-f C-l"] + "-" + ["Calligraphic" (TeX-font nil ?\C-a) :keys "C-c C-f C-a"] + ["Normal" (TeX-font nil ?\C-n) :keys "C-c C-f C-n"]) + ("Replace Font" + ["Emphasize" (TeX-font t ?\C-e) :keys "C-u C-c C-f C-e"] + "-" + ["Roman" (TeX-font t ?\C-r) :keys "C-u C-c C-f C-r"] + ["Sans Serif" (TeX-font t ?\C-f) :keys "C-u C-c C-f C-f"] + ["Typewriter" (TeX-font t ?\C-t) :keys "C-u C-c C-f C-t"] + "-" + ["Medium" (TeX-font t ?\C-m) :keys "C-u C-c C-f C-m"] + ["Bold" (TeX-font t ?\C-b) :keys "C-u C-c C-f C-b"] + "-" + ["Italic" (TeX-font t ?\C-i) :keys "C-u C-c C-f C-i"] + ["Slanted" (TeX-font t ?\C-s) :keys "C-u C-c C-f C-s"] + ["Small Caps" (TeX-font t ?\C-c) :keys "C-u C-c C-f C-c"] + ["Swash" (TeX-font t ?\C-w) :keys "C-u C-c C-f C-w"] + ["Upper Lower" (TeX-font t ?\C-l) :keys "C-u C-c C-f C-l"] + "-" + ["Calligraphic" (TeX-font t ?\C-a) :keys "C-u C-c C-f C-a"] + ["Normal" (TeX-font t ?\C-n) :keys "C-u C-c C-f C-n"]) + ["Delete Font" (TeX-font t ?\C-d) :keys "C-c C-f C-d"] + "-" + ["Comment or Uncomment Region" + comment-or-uncomment-region + :help "Make the selected region outcommented or active again"] + ["Comment or Uncomment Paragraph" + TeX-comment-or-uncomment-paragraph + :help "Make the current paragraph outcommented or active again"] + ("Formatting and Marking" + ["Format Environment" LaTeX-fill-environment + :help "Fill and indent the current environment"] + ["Format Paragraph" LaTeX-fill-paragraph + :help "Fill and ident the current paragraph"] + ["Format Region" LaTeX-fill-region + :help "Fill and indent the currently selected region"] + ["Format Section" LaTeX-fill-section + :help "Fill and indent the current section"] + "-" + ["Mark Environment" LaTeX-mark-environment + :help "Mark the current environment"] + ["Mark Section" LaTeX-mark-section + :help "Mark the current section"] + "-" + ["Beginning of Environment" LaTeX-find-matching-begin + :help "Move point to the beginning of the current environment"] + ["End of Environment" LaTeX-find-matching-end + :help "Move point to the end of the current environment"]) + ,TeX-fold-menu + ["Math Mode" LaTeX-math-mode + :style toggle :selected LaTeX-math-mode + :help "Toggle math mode"] + "-" + [ "Convert 209 to 2e" LaTeX-209-to-2e + :visible (member "latex2" (TeX-style-list)) ] + . ,TeX-common-menu-entries)) + +(defcustom LaTeX-font-list + '((?\C-a "" "" "\\mathcal{" "}") + (?\C-b "\\textbf{" "}" "\\mathbf{" "}") + (?\C-c "\\textsc{" "}") + (?\C-e "\\emph{" "}") + (?\C-f "\\textsf{" "}" "\\mathsf{" "}") + (?\C-i "\\textit{" "}" "\\mathit{" "}") + (?\C-l "\\textulc{" "}") + (?\C-m "\\textmd{" "}") + (?\C-n "\\textnormal{" "}" "\\mathnormal{" "}") + (?\C-r "\\textrm{" "}" "\\mathrm{" "}") + (?\C-s "\\textsl{" "}" "\\mathbb{" "}") + (?\C-t "\\texttt{" "}" "\\mathtt{" "}") + (?\C-u "\\textup{" "}") + (?\C-w "\\textsw{" "}") + (?\C-d "" "" t)) + "Font commands used with LaTeX2e. See `TeX-font-list'." + :group 'LaTeX-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))))) + + +;;; Simple Commands + +(defcustom LaTeX-babel-hyphen "\"=" + "String to be used when typing `-'. +This usually is a hyphen alternative or hyphenation aid, like +\"=, \"~ or \"-, provided by babel and the related language style +files. + +Set it to an empty string or nil in order to disable this +feature. Alter `LaTeX-babel-hyphen-language-alist' in case you +want to change the behavior for a specific language only." + :group 'LaTeX-macro + :type 'string) + +(defcustom LaTeX-babel-hyphen-after-hyphen t + "Control insertion of hyphen strings. +If non-nil insert normal hyphen on first key press and swap it +with the language-specific hyphen string specified in the +variable `LaTeX-babel-hyphen' on second key press. If nil do it +the other way round." + :group 'LaTeX-macro + :type 'boolean) + +(defcustom LaTeX-babel-hyphen-language-alist nil + "Alist controlling hyphen insertion for specific languages. +It may be used to override the defaults given by `LaTeX-babel-hyphen' +and `LaTeX-babel-hyphen-after-hyphen' respectively. The first item +in each element is a string specifying the language as set by the +language-specific style file. The second item is the string to be +used instead of `LaTeX-babel-hyphen'. The third element is the +value overriding `LaTeX-babel-hyphen-after-hyphen'." + :group 'LaTeX-macro + :type '(alist :key-type (string :tag "Language") + :value-type (group (string :tag "Hyphen string") + (boolean :tag "Insert plain hyphen first" + :value t)))) + +(defvar LaTeX-babel-hyphen-language nil + "String determining language-specific behavior of hyphen insertion. +It serves as an indicator that the babel hyphenation string +should be used and as a means to find a potential customization +in `LaTeX-babel-hyphen-language-alist' related to the active +language. It is usually set by language-related style files.") +(make-variable-buffer-local 'LaTeX-babel-hyphen-language) + +(defun LaTeX-babel-insert-hyphen (force) + "Insert a hyphen string. +The string can be either a normal hyphen or the string specified +in `LaTeX-babel-hyphen'. Wether one or the other is chosen +depends on the value of `LaTeX-babel-hyphen-after-hyphen' and +the buffer context. +If prefix argument FORCE is non-nil, always insert a regular hyphen." + (interactive "*P") + (if (or force + (zerop (length LaTeX-babel-hyphen)) + (not LaTeX-babel-hyphen-language) + ;; FIXME: It would be nice to check for verbatim constructs in the + ;; non-font-locking case, but things like `LaTeX-current-environment' + ;; are rather expensive in large buffers. + (and (fboundp 'font-latex-faces-present-p) + (font-latex-faces-present-p '(font-latex-verbatim-face + font-latex-math-face + font-lock-comment-face))) + (texmathp) + (TeX-in-comment)) + (call-interactively #'self-insert-command) + (let* ((lang (assoc LaTeX-babel-hyphen-language + LaTeX-babel-hyphen-language-alist)) + (hyphen (if lang (nth 1 lang) LaTeX-babel-hyphen)) + (h-after-h (if lang (nth 2 lang) LaTeX-babel-hyphen-after-hyphen)) + (hyphen-length (length hyphen))) + (cond + ;; "= --> -- / - + ((string= (buffer-substring (max (- (point) hyphen-length) (point-min)) + (point)) + hyphen) + (if h-after-h + (progn (delete-char (- hyphen-length)) + (insert "--")) + (delete-char (- hyphen-length)) + (call-interactively #'self-insert-command))) + ;; -- --> [+]- + ((string= (buffer-substring (max (- (point) 2) (point-min)) + (point)) + "--") + (call-interactively #'self-insert-command)) + ;; - --> "= / [+]- + ((eq (char-before) ?-) + (if h-after-h + (progn (delete-char -1) + (insert hyphen)) + (call-interactively #'self-insert-command))) + (h-after-h + (call-interactively #'self-insert-command)) + (t (insert hyphen)))))) +;; Cater for Delete Selection mode +(put 'LaTeX-babel-insert-hyphen 'delete-selection t) + +(defcustom LaTeX-enable-toolbar t + "Enable LaTeX tool bar." + :group 'TeX-tool-bar + :type 'boolean) + +(defun LaTeX-maybe-install-toolbar () + "Conditionally install tool bar buttons for LaTeX mode. +Install tool bar if `LaTeX-enable-toolbar' and `tool-bar-mode' +are non-nil." + (when (and LaTeX-enable-toolbar tool-bar-mode) + ;; Defined in `tex-bar.el': + (LaTeX-install-toolbar))) + +;;; Error Messages + +(defconst LaTeX-error-description-list + '(("\\(?:Package Preview Error\\|Preview\\):.*" . + "The `auctex' option to `preview' should not be applied manually. +If you see this error message outside of a preview run, either +you did something too clever, or AUCTeX something too stupid.") + + ("Bad \\\\line or \\\\vector argument.*" . + "The first argument of a \\line or \\vector command, which specifies the +slope, is illegal\.") + + ("Bad math environment delimiter.*" . + "TeX has found either a math-mode-starting command such as \\[ or \\( +when it is already in math mode, or else a math-mode-ending command +such as \\) or \\] while in LR or paragraph mode. The problem is caused +by either unmatched math mode delimiters or unbalanced braces\.") + + ("Bad use of \\\\\\\\.*" . + "A \\\\ command appears between paragraphs, where it makes no sense. This +error message occurs when the \\\\ is used in a centering or flushing +environment or else in the scope of a centering or flushing +declaration.") + + ("\\\\begin{[^ ]*} ended by \\\\end{[^ ]*}." . + "LaTeX has found an \\end command that doesn't match the corresponding +\\begin command. You probably misspelled the environment name in the +\\end command, have an extra \\begin, or else forgot an \\end.") + + ("Can be used only in preamble." . + "LaTeX has encountered, after the \\begin{document}, one of the +following commands that should appear only in the preamble: +\\documentclass, \\nofiles, \\includeonly, \\makeindex, or +\\makeglossary. The error is also caused by an extra \\begin{document} +command.") + + ("Command name [^ ]* already used.*" . + "You are using \\newcommand, \\newenvironment, \\newlength, \\newsavebox, +or \\newtheorem to define a command or environment name that is +already defined, or \\newcounter to define a counter that already +exists. (Defining an environment named gnu automatically defines the +command \\gnu.) You'll have to choose a new name or, in the case of +\\newcommand or \\newenvironment, switch to the \\renew ... command.") + + ("Counter too large." . + "1. Some object that is numbered with letters, probably an item in a +enumerated list, has received a number greater than 26. Either you're +making a very long list or you've been resetting counter values. + +2. Footnotes are being ``numbered'' with letters or footnote symbols +and LaTeX has run out of letters or symbols. This is probably caused +by too many \\thanks commands.") + + ("Environment [^ ]* undefined." . + "LaTeX has encountered a \\begin command for a nonexistent environment. +You probably misspelled the environment name. ") + + ("Float(s) lost." . + "You put a figure or table environment or a \\marginpar command inside a +parbox---either one made with a minipage environment or \\parbox +command, or one constructed by LaTeX in making a footnote, figure, +etc. This is an outputting error, and the offending environment or +command may be quite a way back from the point where LaTeX discovered +the problem. One or more figures, tables, and/or marginal notes have +been lost, but not necessarily the one that caused the error.") + + ("Illegal character in array arg." . + "There is an illegal character in the argument of an array or tabular +environment, or in the second argument of a \\multicolumn command.") + + ("Missing \\\\begin{document}." . + "LaTeX produced printed output before encountering a \\begin{document} +command. Either you forgot the \\begin{document} command or there is +something wrong in the preamble. The problem may be a stray character +or an error in a declaration---for example, omitting the braces around +an argument or forgetting the \\ in a command name.") + + ("Missing p-arg in array arg.*" . + "There is a p that is not followed by an expression in braces in the +argument of an array or tabular environment, or in the second argument +of a \\multicolumn command.") + + ("Missing @-exp in array arg." . + "There is an @ character not followed by an @-expression in the +argument of an array or tabular environment, or in the second argument +of a \\multicolumn command.") + + ("No such counter." . + "You have specified a nonexistent counter in a \\setcounter or +\\addtocounter command. This is probably caused by a simple typing +error. However, if the error occurred while a file with the extension +aux is being read, then you probably used a \\newcounter command +outside the preamble.") + + ("Not in outer par mode." . + "You had a figure or table environment or a \\marginpar command in math +mode or inside a parbox.") + + ("\\\\pushtabs and \\\\poptabs don't match." . + "LaTeX found a \\poptabs with no matching \\pushtabs, or has come to the +\\end{tabbing} command with one or more unmatched \\pushtabs commands.") + + ("Something's wrong--perhaps a missing \\\\item." . + "The most probable cause is an omitted \\item command in a list-making +environment. It is also caused by forgetting the argument of a +thebibliography environment.") + + ("Tab overflow." . + "A \\= command has exceeded the maximum number of tab stops that LaTeX +permits.") + + ("There's no line here to end." . + "A \\newline or \\\\ command appears between paragraphs, where it makes no +sense. If you're trying to ``leave a blank line'', use a \\vspace +command.") + + ("This may be a LaTeX bug." . + "LaTeX has become thoroughly confused. This is probably due to a +previously detected error, but it is possible that you have found an +error in LaTeX itself. If this is the first error message produced by +the input file and you can't find anything wrong, save the file and +contact the person listed in your Local Guide.") + + ("Too deeply nested." . + "There are too many list-making environments nested within one another. +How many levels of nesting are permitted may depend upon what computer +you are using, but at least four levels are provided, which should be +enough.") + + ("Too many unprocessed floats." . + "While this error can result from having too many \\marginpar commands +on a page, a more likely cause is forcing LaTeX to save more figures +and tables than it has room for. When typesetting its continuous +scroll, LaTeX saves figures and tables separately and inserts them as +it cuts off pages. This error occurs when LaTeX finds too many figure +and/or table environments before it is time to cut off a page, a +problem that is solved by moving some of the environments farther +towards the end of the input file. The error can also be caused by a +``logjam''---a figure or table that cannot be printed causing others +to pile up behind it, since LaTeX will not print figures or tables out +of order. The jam can be started by a figure or table that either is +too large to fit on a page or won't fit where its optional placement +argument says it must go. This is likely to happen if the argument +does not contain a p option.") + + ("Undefined tab position." . + "A \\>, \\+, \\-, or \\< command is trying to go to a nonexistent tab +position---one not defined by a \\= command.") + + ("\\\\< in mid line." . + "A \\< command appears in the middle of a line in a tabbing environment. +This command should come only at the beginning of a line.") + + ("Double subscript." . + "There are two subscripts in a row in a mathematical +formula---something like x_{2}_{3}, which makes no sense.") + + ("Double superscript." . + "There are two superscripts in a row in a mathematical +formula---something like x^{2}^{3}, which makes no sense.") + + ("Extra alignment tab has been changed to \\\\cr." . + "There are too many separate items (column entries) in a single row of +an array or tabular environment. In other words, there were too many & +'s before the end of the row. You probably forgot the \\\\ at the end of +the preceding row.") + + ("Extra \\}, or forgotten \\$." . + "The braces or math mode delimiters don't match properly. You probably +forgot a {, \\[, \\(, or $.") + + ("Font [^ ]* not loaded: Not enough room left." . + "The document uses more fonts than TeX has room for. If different parts +of the document use different fonts, then you can get around the +problem by processing it in parts.") + + ("I can't find file `.*'." . + "TeX can't find a file that it needs. If the name of the missing file +has the extension tex, then it is looking for an input file that you +specified---either your main file or another file inserted with an +\\input or \\include command. If the missing file has the extension sty +, then you have specified a nonexistent document style or style +option.") + + ("Illegal parameter number in definition of .*" . + "This is probably caused by a \\newcommand, \\renewcommand, +\\newenvironment, or \\renewenvironment command in which a # is used +incorrectly. A # character, except as part of the command name \\#, +can be used only to indicate an argument parameter, as in #2, which +denotes the second argument. This error is also caused by nesting one +of the above four commands inside another, or by putting a parameter +like #2 in the last argument of a \\newenvironment or \\renewenvironment +command.") + + ("Illegal unit of measure ([^ ]* inserted)." . + "If you just got a + + ! Missing number, treated as zero. + +error, then this is part of the same problem. If not, it means that +LaTeX was expecting a length as an argument and found a number +instead. The most common cause of this error is writing 0 instead of +something like 0in for a length of zero, in which case typing return +should result in correct output. However, the error can also be caused +by omitting a command argument.") + + ("Misplaced alignment tab character \\&." . + "The special character &, which should be used only to separate items +in an array or tabular environment, appeared in ordinary text. You +probably meant to type \\&.") + + ("Missing control sequence inserted." . + "This is probably caused by a \\newcommand, \\renewcommand, \\newlength, +or \\newsavebox command whose first argument is not a command name.") + + ("Missing number, treated as zero." . + "This is usually caused by a LaTeX command expecting but not finding +either a number or a length as an argument. You may have omitted an +argument, or a square bracket in the text may have been mistaken for +the beginning of an optional argument. This error is also caused by +putting \\protect in front of either a length command or a command such +as \\value that produces a number.") + + ("Missing [{}] inserted." . + "TeX has become confused. The position indicated by the error locator +is probably beyond the point where the incorrect input is.") + + ("Missing \\$ inserted." . + "TeX probably found a command that can be used only in math mode when +it wasn't in math mode. Remember that unless stated otherwise, all +all the commands of Section 3.3 in LaTeX Book (Lamport) can be used +only in math mode. TeX is not in math mode when it begins processing +the argument of a box-making command, even if that command is inside a +math environment. This error also occurs if TeX encounters a blank +line when it is in math mode.") + + ("Not a letter." . + "Something appears in the argument of a \\hyphenation command that +doesn't belong there.") + + ("Paragraph ended before [^ ]* was complete." . + "A blank line occurred in a command argument that shouldn't contain +one. You probably forgot the right brace at the end of an argument.") + + ("\\\\[^ ]*font [^ ]* is undefined .*" . + "These errors occur when an uncommon font is used in math mode---for +example, if you use a \\sc command in a formula inside a footnote, +calling for a footnote-sized small caps font. This problem is solved +by using a \\load command.") + + ("Font .* not found." . + "You requested a family/series/shape/size combination that is totally +unknown. There are two cases in which this error can occur: + 1) You used the \\size macro to select a size that is not available. + 2) If you did not do that, go to your local `wizard' and + complain fiercely that the font selection tables are corrupted!") + + ("TeX capacity exceeded, sorry .*" . + "TeX has just run out of space and aborted its execution. Before you +panic, remember that the least likely cause of this error is TeX not +having the capacity to process your document. It was probably an +error in your input file that caused TeX to run out of room. The +following discussion explains how to decide whether you've really +exceeded TeX's capacity and, if so, what to do. If the problem is an +error in the input, you may have to use the divide and conquer method +described previously to locate it. LaTeX seldom runs out of space on a +short input file, so if running it on the last few pages before the +error indicator's position still produces the error, then there's +almost certainly something wrong in the input file. + +The end of the error indicator tells what kind of space TeX ran out +of. The more common ones are listed below, with an explanation of +their probable causes. + +buffer size +=========== +Can be caused by too long a piece of text as the argument +of a sectioning, \\caption, \\addcontentsline, or \\addtocontents +command. This error will probably occur when the \\end{document} is +being processed, but it could happen when a \\tableofcontents, +\\listoffigures, or \\listoftables command is executed. To solve this +problem, use a shorter optional argument. Even if you're producing a +table of contents or a list of figures or tables, such a long entry +won't help the reader. + +exception dictionary +==================== +You have used \\hyphenation commands to give TeX +more hyphenation information than it has room for. Remove some of the +less frequently used words from the \\hyphenation commands and insert +\\- commands instead. + +hash size +========= +Your input file defines too many command names and/or uses +too many cross-ref- erencing labels. + +input stack size +================ +This is probably caused by an error in a command +definition. For example, the following command makes a circular +definition, defining \\gnu in terms of itself: + + \\newcommand{\\gnu}{a \\gnu} % This is wrong! + +When TeX encounters this \\gnu command, it will keep chasing its tail +trying to figure out what \\gnu should produce, and eventually run out +of ``input stack''. + +main memory size +================ +This is one kind of space that TeX can run out of when processing a +short file. There are three ways you can run TeX out of main memory +space: (1) defining a lot of very long, complicated commands, (2) +making an index or glossary and having too many \\index or \\glossary +commands on a single page, and (3) creating so complicated a page of +output that TeX can't hold all the information needed to generate it. +The solution to the first two problems is obvious: define fewer +commands or use fewer \\index and \\glossary commands. The third problem +is nastier. It can be caused by large tabbing, tabular, array, and +picture environments. TeX's space may also be filled up with figures +and tables waiting for a place to go. To find out if you've really +exceeded TeX's capacity in this way, put a \\clearpage command in your +input file right before the place where TeX ran out of room and try +running it again. If it doesn't run out of room with the \\clearpage +command there, then you did exceed TeX's capacity. If it still runs +out of room, then there's probably an error in your file. If TeX is +really out of room, you must give it some help. Remember that TeX +processes a complete paragraph before deciding whether to cut the +page. Inserting a \\newpage command in the middle of the paragraph, +where TeX should break the page, may save the day by letting TeX write +the current page before processing the rest of the paragraph. (A +\\pagebreak command won't help.) If the problem is caused by +accumulated figures and tables, you can try to prevent them from +accumulating---either by moving them further towards the end of the +document or by trying to get them to come out sooner. If you are +still writing the document, simply add a \\clearpage command and forget +about the problem until you're ready to produce the final version. +Changes to the input file are likely to make the problem go away. + +pool size +========= +You probably used too many cross-ref-erencing \\labels and/or defined +too many new command names. More precisely, the labels and command +names that you define have too many characters, so this problem can be +solved by using shorter names. However, the error can also be caused +by omitting the right brace that ends the argument of either a counter +command such as \\setcounter, or a \\newenvironment or \\newtheorem +command. + +save size +========= +This occurs when commands, environments, and the scopes of +declarations are nested too deeply---for example, by having the +argument of a \\multiput command contain a picture environment that in +turn has a \\footnotesize declaration whose scope contains a \\multiput +command containing a ....") + + ("Text line contains an invalid character." . + "The input contains some strange character that it shouldn't. A mistake +when creating the file probably caused your text editor to insert this +character. Exactly what could have happened depends upon what text +editor you used. If examining the input file doesn't reveal the +offending character, consult the Local Guide for suggestions.") + + ("Undefined control sequence." . + "TeX encountered an unknown command name. You probably misspelled the +name. If this message occurs when a LaTeX command is being processed, +the command is probably in the wrong place---for example, the error +can be produced by an \\item command that's not inside a list-making +environment. The error can also be caused by a missing \\documentclass +command.") + + ("Use of [^ ]* doesn't match its definition." . + "It's probably one of the picture-drawing commands, and you have used +the wrong syntax for specifying an argument. If it's \\@array that +doesn't match its definition, then there is something wrong in an +@-expression in the argument of an array or tabular +environment---perhaps a fragile command that is not \\protect'ed.") + + ("You can't use `macro parameter character \\#' in [^ ]* mode." . + "The special character # has appeared in ordinary text. You probably +meant to type \\#.") + + ("Overfull \\\\hbox .*" . + "Because it couldn't find a good place for a line break, TeX put more +on this line than it should.") + + ("Overfull \\\\vbox .*" . + "Because it couldn't find a good place for a page break, TeX put more +on the page than it should. ") + + ("Underfull \\\\hbox .*" . + "Check your output for extra vertical space. If you find some, it was +probably caused by a problem with a \\\\ or \\newline command---for +example, two \\\\ commands in succession. This warning can also be +caused by using the sloppypar environment or \\sloppy declaration, or +by inserting a \\linebreak command.") + + ("Underfull \\\\vbox .*" . + "TeX could not find a good place to break the page, so it produced a +page without enough text on it. ") + + ;; New list items should be placed here + ;; + ;; ("err-regexp" . "context") + ;; + ;; the err-regexp item should match anything + + (".*" . "No help available")) ; end definition + "Help messages for errors in LaTeX mode. +Used as buffer local value of `TeX-error-description-list-local'. +See its doc string for detail.") + +;;; Mode + +(defgroup LaTeX-macro nil + "Special support for LaTeX macros in AUCTeX." + :prefix "TeX-" + :group 'LaTeX + :group 'TeX-macro) + +(defcustom TeX-arg-cite-note-p nil + "If non-nil, ask for optional note in citations." + :type 'boolean + :group 'LaTeX-macro) + +(defcustom TeX-arg-footnote-number-p nil + "If non-nil, ask for optional number in footnotes." + :type 'boolean + :group 'LaTeX-macro) + +(defcustom TeX-arg-item-label-p nil + "If non-nil, always ask for optional label in items. +Otherwise, only ask in description environments." + :type 'boolean + :group 'LaTeX-macro) + +(defcustom TeX-arg-right-insert-p t + "If non-nil, always insert automatically the corresponding \\right. +This happens when \\left is inserted." + :type 'boolean + :group 'LaTeX-macro) + +(defcustom LaTeX-mode-hook nil + "A hook run in LaTeX mode buffers." + :type 'hook + :group 'LaTeX) + +(TeX-abbrev-mode-setup latex-mode) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.drv\\'" . latex-mode) t) ;; append to the end of `auto-mode-alist' to give higher priority to Guix/Nix's derivation modes + +;; HeVeA files (LaTeX -> HTML converter: http://hevea.inria.fr/) +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.hva\\'" . latex-mode)) + +(declare-function LaTeX-preview-setup "preview") + +;;;###autoload +(defun TeX-latex-mode () + ;; FIXME: Use `define-derived-mode'. + "Major mode in AUCTeX for editing LaTeX files. +See info under AUCTeX for full documentation. + +Special commands: +\\{LaTeX-mode-map} + +Entering LaTeX mode calls the value of `text-mode-hook', +then the value of `TeX-mode-hook', and then the value +of `LaTeX-mode-hook'." + (interactive) + (LaTeX-common-initialization) + (setq TeX-base-mode-name "LaTeX") + (setq major-mode 'latex-mode) + (setq TeX-command-default "LaTeX") + (setq TeX-sentinel-default-function #'TeX-LaTeX-sentinel) + (add-hook 'tool-bar-mode-hook #'LaTeX-maybe-install-toolbar nil t) + (LaTeX-maybe-install-toolbar) + ;; Set the value of `LaTeX-using-Biber' based on the local value of + ;; `LaTeX-biblatex-use-Biber'. This should be run within + ;; `TeX-update-style-hook' before toolbarx-refresh, otherwise the bibliography + ;; button could be wrongly set. + (add-hook 'TeX-update-style-hook + (lambda () + (if (local-variable-p 'LaTeX-biblatex-use-Biber (current-buffer)) + (setq LaTeX-using-Biber LaTeX-biblatex-use-Biber))) + nil t) + + ;; Run style hooks associated with class options. + (add-hook 'TeX-update-style-hook + (lambda () + (let ((TeX-style-hook-dialect :classopt) + ;; Don't record class option names in + ;; `TeX-active-styles'. + (TeX-active-styles nil)) + (apply #'TeX-run-style-hooks + (apply #'append + (mapcar #'cdr LaTeX-provided-class-options))))) + nil t) + (run-mode-hooks 'text-mode-hook 'TeX-mode-hook 'LaTeX-mode-hook) + (when (fboundp 'LaTeX-preview-setup) + (LaTeX-preview-setup)) + (TeX-set-mode-name) + ;; Defeat filladapt + (if (and (boundp 'filladapt-mode) + filladapt-mode) + (turn-off-filladapt-mode)) + (when (< 25 emacs-major-version) + ;; Set up flymake backend, see latex-flymake.el + (add-hook 'flymake-diagnostic-functions #'LaTeX-flymake nil t))) + +(TeX-abbrev-mode-setup doctex-mode) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.dtx\\'" . doctex-mode)) + +;;;###autoload +(define-derived-mode docTeX-mode TeX-latex-mode "docTeX" + "Major mode in AUCTeX for editing .dtx files derived from `LaTeX-mode'. +Runs `LaTeX-mode', sets a few variables and +runs the hooks in `docTeX-mode-hook'." + :abbrev-table doctex-mode-abbrev-table + (setq major-mode 'doctex-mode) + (set (make-local-variable 'LaTeX-insert-into-comments) t) + (set (make-local-variable 'LaTeX-syntactic-comments) t) + (setq TeX-default-extension docTeX-default-extension) + ;; Make filling and indentation aware of DocStrip guards. + (setq paragraph-start (concat paragraph-start "\\|%<") + paragraph-separate (concat paragraph-separate "\\|%<") + TeX-comment-start-regexp "\\(?:%\\(?:<[^>]+>\\)?\\)") + (setq TeX-base-mode-name "docTeX") + (TeX-set-mode-name) + (funcall TeX-install-font-lock)) + +;;This is actually a mess: to fit the scheme properly, our derived +;;mode definition would have had to be made for TeX-doctex-mode in the +;;first place, but then we could not have used define-derived-mode, or +;;all mode-specific variables would have gotten non-AUCTeX names. +;;This solution has the advantage that documentation strings are +;;provided in the autoloads, and has the disadvantage that docTeX-mode +;;is not aliased to doctex-mode (not even when the AUCTeX version is +;;disabled) as would be normal for our scheme. + +;;;###autoload +(defalias 'TeX-doctex-mode #'docTeX-mode) + +(defcustom docTeX-clean-intermediate-suffixes + TeX-clean-default-intermediate-suffixes + "List of regexps matching suffixes of files to be deleted. +The regexps will be anchored at the end of the file name to be matched, +that is, you do _not_ have to cater for this yourself by adding \\\\\\=' or $." + :type '(repeat regexp) + :group 'TeX-command) + +(defcustom docTeX-clean-output-suffixes TeX-clean-default-output-suffixes + "List of regexps matching suffixes of files to be deleted. +The regexps will be anchored at the end of the file name to be matched, +that is, you do _not_ have to cater for this yourself by adding \\\\\\=' or $." + :type '(repeat regexp) + :group 'TeX-command) + +(defcustom LaTeX-clean-intermediate-suffixes + (append TeX-clean-default-intermediate-suffixes + ;; These are extensions of files created by makeglossaries. + '("\\.acn" "\\.acr" "\\.alg" "\\.glg" "\\.ist")) + "List of regexps matching suffixes of files to be deleted. +The regexps will be anchored at the end of the file name to be matched, +that is, you do _not_ have to cater for this yourself by adding \\\\\\=' or $." + :type '(repeat regexp) + :group 'TeX-command) + +(defcustom LaTeX-clean-output-suffixes TeX-clean-default-output-suffixes + "List of regexps matching suffixes of files to be deleted. +The regexps will be anchored at the end of the file name to be matched, +that is, you do _not_ have to cater for this yourself by adding \\\\\\=' or $." + :type '(repeat regexp) + :group 'TeX-command) + +(defun LaTeX--after-math-macro-prefix-p () + "Return non-nil if point is after a macro prefix in math mode. +Also sets `match-data' so that group 1 is the already typed +prefix. + +For example, in $a + \\a| - 17$ with | denoting point, the +function would return non-nil and `(match-string 1)' would return +\"a\" afterwards." + (and (texmathp) + (TeX-looking-at-backward "\\\\\\([a-zA-Z]*\\)"))) + +(defun LaTeX-common-initialization () + "Common initialization for LaTeX derived modes." + (VirTeX-common-initialization) + (set-syntax-table LaTeX-mode-syntax-table) + (set (make-local-variable 'indent-line-function) #'LaTeX-indent-line) + + (setq local-abbrev-table latex-mode-abbrev-table) + + ;; Filling + (set (make-local-variable 'paragraph-ignore-fill-prefix) t) + (set (make-local-variable 'fill-paragraph-function) #'LaTeX-fill-paragraph) + (set (make-local-variable 'adaptive-fill-mode) nil) + + (or LaTeX-largest-level + (setq LaTeX-largest-level (LaTeX-section-level "section"))) + + (setq TeX-header-end LaTeX-header-end + TeX-trailer-start LaTeX-trailer-start) + (set (make-local-variable 'TeX-style-hook-dialect) TeX-dialect) + + (require 'outline) + (set (make-local-variable 'outline-level) #'LaTeX-outline-level) + (set (make-local-variable 'outline-regexp) (LaTeX-outline-regexp t)) + (when (boundp 'outline-heading-alist) + (setq outline-heading-alist + (mapcar (lambda (x) + (cons (concat "\\" (nth 0 x)) (nth 1 x))) + LaTeX-section-list))) + + (setq-local TeX-auto-full-regexp-list + (delete-dups (append LaTeX-auto-regexp-list + ;; Prevent inadvertent destruction + ;; of `plain-TeX-auto-regexp-list'. + (copy-sequence + plain-TeX-auto-regexp-list)))) + + (LaTeX-set-paragraph-start) + (setq paragraph-separate + (concat + "[ \t]*%*[ \t]*\\(" + "\\$\\$" ; Plain TeX display math + "\\|$\\)")) + + (setq TeX-verbatim-p-function #'LaTeX-verbatim-p) + (setq TeX-search-forward-comment-start-function + #'LaTeX-search-forward-comment-start) + (set (make-local-variable 'TeX-search-files-type-alist) + LaTeX-search-files-type-alist) + + (setq-local beginning-of-defun-function #'LaTeX-find-matching-begin) + (setq-local end-of-defun-function #'LaTeX-find-matching-end) + + (LaTeX-indent-commands-regexp-make) + + (set (make-local-variable 'LaTeX-item-list) '(("description" . LaTeX-item-argument) + ("thebibliography" . LaTeX-item-bib) + ("array" . LaTeX-item-array) + ("tabular" . LaTeX-item-array) + ("tabular*" . LaTeX-item-tabular*))) + + (setq TeX-complete-list + (append '(("\\\\cite\\[[^]\n\r\\%]*\\]{\\([^{}\n\r\\%,]*\\)" + 1 LaTeX-bibitem-list "}") + ("\\\\cite{\\([^{}\n\r\\%,]*\\)" 1 LaTeX-bibitem-list "}") + ("\\\\cite{\\([^{}\n\r\\%]*,\\)\\([^{}\n\r\\%,]*\\)" + 2 LaTeX-bibitem-list) + ("\\\\nocite{\\([^{}\n\r\\%,]*\\)" 1 LaTeX-bibitem-list "}") + ("\\\\nocite{\\([^{}\n\r\\%]*,\\)\\([^{}\n\r\\%,]*\\)" + 2 LaTeX-bibitem-list) + ("\\\\[Rr]ef{\\([^{}\n\r\\%,]*\\)" 1 LaTeX-label-list "}") + ("\\\\eqref{\\([^{}\n\r\\%,]*\\)" 1 LaTeX-label-list "}") + ("\\\\pageref{\\([^{}\n\r\\%,]*\\)" 1 LaTeX-label-list "}") + ("\\\\\\(index\\|glossary\\){\\([^{}\n\r\\%]*\\)" + 2 LaTeX-index-entry-list "}") + ("\\\\begin{\\([A-Za-z]*\\)" 1 LaTeX-environment-list-filtered "}") + ("\\\\end{\\([A-Za-z]*\\)" 1 LaTeX-environment-list-filtered "}") + ("\\\\renewcommand\\*?{\\\\\\([A-Za-z]*\\)" + 1 TeX-symbol-list-filtered "}") + ("\\\\renewenvironment\\*?{\\([A-Za-z]*\\)" + 1 LaTeX-environment-list-filtered "}") + ("\\\\\\(this\\)?pagestyle{\\([A-Za-z]*\\)" + 2 LaTeX-pagestyle-list "}") + (LaTeX--after-math-macro-prefix-p + 1 (lambda () + (append (mapcar #'cadr LaTeX-math-list) + (mapcar #'cadr LaTeX-math-default))) + (if TeX-insert-braces "{}"))) + TeX-complete-list)) + + (LaTeX-add-environments + '("document" LaTeX-env-document) + '("enumerate" LaTeX-env-item) + '("itemize" LaTeX-env-item) + '("list" LaTeX-env-list) + '("trivlist" LaTeX-env-item) + '("picture" LaTeX-env-picture) + '("tabular" LaTeX-env-array) + '("tabular*" LaTeX-env-tabular*) + '("array" LaTeX-env-array) + '("eqnarray" LaTeX-env-label) + '("equation" LaTeX-env-label) + '("minipage" LaTeX-env-minipage) + + ;; The following have no special support, but are included in + ;; case the auto files are missing. + + "sloppypar" "tabbing" "verbatim" "verbatim*" + "flushright" "flushleft" "displaymath" "math" "quote" "quotation" + "center" "titlepage" "verse" "eqnarray*" + + ;; The following are not defined in latex.el, but in a number of + ;; other style files. I'm to lazy to copy them to all the + ;; corresponding .el files right now. + + ;; This means that AUCTeX will complete e.g. + ;; ``thebibliography'' in a letter, but I guess we can live with + ;; that. + + '("description" LaTeX-env-item) + '("figure" LaTeX-env-figure) + '("figure*" LaTeX-env-figure) + '("table" LaTeX-env-figure) + '("table*" LaTeX-env-figure) + '("thebibliography" LaTeX-env-bib) + '("theindex" LaTeX-env-item)) + + ;; `latex.ltx' defines `plain' and `empty' pagestyles + (LaTeX-add-pagestyles "plain" "empty") + + ;; `latex.ltx' defines the following counters + (LaTeX-add-counters "page" "equation" "enumi" "enumii" "enumiii" + "enumiv" "footnote" "mpfootnote") + + (LaTeX-add-lengths "arraycolsep" "arrayrulewidth" "baselineskip" "baselinestretch" + "bibindent" "columnsep" "columnseprule" "columnwidth" "doublerulesep" + "evensidemargin" "linewidth" "oddsidemargin" "paperwidth" + "paperheight" "parindent" "parskip" "tabcolsep" + "textheight" "textwidth" "topmargin" "unitlength") + + (TeX-add-symbols + '("addtocounter" TeX-arg-counter "Value") + '("alph" TeX-arg-counter) + '("arabic" TeX-arg-counter) + '("fnsymbol" TeX-arg-counter) + '("newcounter" TeX-arg-define-counter + [ TeX-arg-counter "Within counter" ]) + '("roman" TeX-arg-counter) + '("setcounter" TeX-arg-counter "Value") + '("usecounter" TeX-arg-counter) + '("value" TeX-arg-counter) + '("stepcounter" TeX-arg-counter) + '("refstepcounter" TeX-arg-counter) + '("label" TeX-arg-define-label) + '("pageref" TeX-arg-ref) + '("ref" TeX-arg-ref) + ;; \Ref and \labelformat are part of kernel with LaTeX 2019-10-01: + '("Ref" TeX-arg-ref) + '("labelformat" TeX-arg-counter t) + ;; \footref is part of kernel with LaTeX 2021-06-01: + '("footref" TeX-arg-ref) + '("newcommand" TeX-arg-define-macro [ TeX-arg-define-macro-arguments ] t) + '("renewcommand" TeX-arg-macro [ TeX-arg-define-macro-arguments ] t) + '("newenvironment" TeX-arg-define-environment + [ "Number of arguments"] t t) + '("renewenvironment" TeX-arg-environment + [ "Number of arguments"] t t) + '("providecommand" TeX-arg-define-macro [ TeX-arg-define-macro-arguments ] t) + '("providecommand*" TeX-arg-define-macro [ TeX-arg-define-macro-arguments ] t) + '("newcommand*" TeX-arg-define-macro [ TeX-arg-define-macro-arguments ] t) + '("renewcommand*" TeX-arg-macro [ TeX-arg-define-macro-arguments ] t) + '("newenvironment*" TeX-arg-define-environment + [ "Number of arguments"] t t) + '("renewenvironment*" TeX-arg-environment + [ "Number of arguments"] t t) + '("newtheorem" TeX-arg-define-environment + [ TeX-arg-environment "Numbered like" ] + t [ (TeX-arg-eval progn (if (eq (save-excursion + (backward-char 2) + (preceding-char)) ?\]) + () + (TeX-arg-counter t "Within counter")) + "") ]) + '("newfont" TeX-arg-define-macro t) + '("circle" "Diameter") + '("circle*" "Diameter") + '("dashbox" "Dash Length" TeX-arg-size + [ TeX-arg-corner ] t) + '("frame" t) + '("framebox" (TeX-arg-conditional + (string-equal (LaTeX-current-environment) "picture") + (TeX-arg-size [ TeX-arg-corner ] t) + ([ "Length" ] [ TeX-arg-lr ] t))) + '("line" (TeX-arg-pair "X slope" "Y slope") "Length") + '("linethickness" "Dimension") + '("makebox" (TeX-arg-conditional + (string-equal (LaTeX-current-environment) "picture") + (TeX-arg-size [ TeX-arg-corner ] t) + ([ "Length" ] [ TeX-arg-lr ] t))) + '("multiput" + TeX-arg-coordinate + (TeX-arg-pair "X delta" "Y delta") + "Number of copies" + t) + '("oval" TeX-arg-size [ TeX-arg-corner "Portion" ]) + '("put" TeX-arg-coordinate t) + '("savebox" TeX-arg-savebox + (TeX-arg-conditional + (string-equal (LaTeX-current-environment) "picture") + (TeX-arg-size [ TeX-arg-corner ] t) + ([ "Length" ] [ TeX-arg-lr ] t))) + '("shortstack" [ TeX-arg-lr ] t) + '("vector" (TeX-arg-pair "X slope" "Y slope") "Length") + '("cline" "Span `i-j'") + '("multicolumn" "Columns" "Format" t) + '("item" + (TeX-arg-conditional (or TeX-arg-item-label-p + (string-equal (LaTeX-current-environment) + "description")) + ([ "Item label" ]) + ()) + (TeX-arg-literal " ")) + '("bibitem" [ "Bibitem label" ] TeX-arg-define-cite) + '("cite" + (TeX-arg-conditional TeX-arg-cite-note-p ([ "Note" ]) ()) + TeX-arg-cite) + '("nocite" TeX-arg-cite) + '("bibliographystyle" TeX-arg-bibstyle) + '("bibliography" TeX-arg-bibliography) + '("newblock" (TeX-arg-literal " ")) + '("footnote" + (TeX-arg-conditional TeX-arg-footnote-number-p ([ "Number" ]) nil) + t) + '("footnotetext" + (TeX-arg-conditional TeX-arg-footnote-number-p ([ "Number" ]) nil) + t) + '("footnotemark" + (TeX-arg-conditional TeX-arg-footnote-number-p ([ "Number" ]) nil)) + '("newlength" (TeX-arg-define-length "Length macro")) + '("setlength" (TeX-arg-length "Length macro" nil "\\") + (TeX-arg-length "Length value")) + '("addtolength" (TeX-arg-length "Length macro" nil "\\") + (TeX-arg-length "Length to add")) + '("settowidth" (TeX-arg-length "Length macro" nil "\\") "Text") + '("settoheight" (TeX-arg-length "Length macro" nil "\\") "Text") + '("settodepth" (TeX-arg-length "Length macro" nil "\\") "Text") + '("\\" [ "Space" ]) + '("\\*" [ "Space" ]) + '("hyphenation" t) + '("linebreak" [ "How much [0 - 4]" ]) + '("nolinebreak" [ "How much [0 - 4]" ]) + '("nopagebreak" [ "How much [0 - 4]" ]) + '("pagebreak" [ "How much [0 - 4]" ]) + '("stackrel" t nil) + '("frac" t nil) + '("lefteqn" t) + '("overbrace" t) + '("overline" t) + '("overleftarrow" t) + '("overrightarrow" t) + '("sqrt" [ "Root" ] t) + '("underbrace" t) + '("underline" t) + '("acute" t) '("grave" t) '("ddot" t) '("tilde" t) '("bar" t) + '("breve" t) '("check" t) '("hat" t) '("vec" t) '("dot" t) + '("widetilde" t) '("widehat" t) + '("author" LaTeX-arg-author) + '("date" TeX-arg-date) + '("thanks" t) + '("title" t) + '("pagenumbering" (TeX-arg-eval + completing-read "Numbering style: " + '(("arabic") ("roman") ("Roman") ("alph") ("Alph")))) + '("pagestyle" TeX-arg-pagestyle) + '("markboth" t nil) + '("markright" t) + '("thispagestyle" TeX-arg-pagestyle) + '("addvspace" TeX-arg-length) + '("fbox" t) + '("hspace*" TeX-arg-length) + '("hspace" TeX-arg-length) + '("mbox" t) + '("newsavebox" TeX-arg-define-savebox) + '("parbox" + [TeX-arg-tb nil center] + [TeX-arg-length "Height"] + [TeX-arg-tb "Inner position" stretch] + (TeX-arg-length "Width") + t) + '("raisebox" "Raise" [ "Height above" ] [ "Depth below" ] t) + '("rule" [ "Raise" ] "Width" "Thickness") + '("sbox" TeX-arg-savebox t) + '("usebox" TeX-arg-savebox) + '("vspace*" TeX-arg-length) + '("vspace" TeX-arg-length) + '("documentstyle" TeX-arg-document) + '("include" (TeX-arg-input-file "File" t)) + '("includeonly" t) + '("input" TeX-arg-input-file) + '("addcontentsline" + (TeX-arg-eval completing-read "File: " '(("toc") ("lof") ("lot"))) + (TeX-arg-eval completing-read "Numbering style: " LaTeX-section-list) t) + '("addtocontents" + (TeX-arg-eval completing-read "File: " '(("toc") ("lof") ("lot"))) t) + '("typeout" t) + '("typein" [ TeX-arg-define-macro ] t) + '("verb" TeX-arg-verb) + '("verb*" TeX-arg-verb) + '("extracolsep" t) + '("index" TeX-arg-index) + '("glossary" TeX-arg-index) + '("numberline" "Section number" "Heading") + '("caption" t) + '("marginpar" [ "Left margin text" ] "Text") + '("left" TeX-arg-insert-braces) + ;; The following 4 macros are not specific to amsmath. + '("bigl" TeX-arg-insert-braces) + '("Bigl" TeX-arg-insert-braces) + '("biggl" TeX-arg-insert-braces) + '("Biggl" TeX-arg-insert-braces) + + '("langle" TeX-arg-insert-right-brace-maybe) + '("lceil" TeX-arg-insert-right-brace-maybe) + '("lfloor" TeX-arg-insert-right-brace-maybe) + + ;; These have no special support, but are included in case the + ;; auto files are missing. + + "TeX" "LaTeX" + "samepage" "newline" + "smallskip" "medskip" "bigskip" "fill" "stretch" + "thinspace" "negthinspace" "enspace" "enskip" "quad" "qquad" + "nonumber" "centering" "raggedright" + "raggedleft" "kill" "pushtabs" "poptabs" "protect" "arraystretch" + "hline" "vline" "cline" "thinlines" "thicklines" "and" "makeindex" + "makeglossary" "reversemarginpar" "normalmarginpar" + "raggedbottom" "flushbottom" "sloppy" "fussy" "newpage" + "clearpage" "cleardoublepage" "twocolumn" "onecolumn" + + "maketitle" "tableofcontents" "listoffigures" "listoftables" + '("tiny" -1) '("scriptsize" -1) '("footnotesize" -1) '("small" -1) + '("normalsize" -1) '("large" -1) '("Large" -1) '("LARGE" -1) '("huge" -1) + '("Huge" -1) + '("oldstylenums" "Numbers") + ;; The next macro is provided by LaTeX2e 2020-02-02 release: + '("legacyoldstylenums" "Numbers") + "pounds" "copyright" + "hfil" "hfill" "vfil" "vfill" "hrulefill" "dotfill" + "indent" "noindent" "today" + "appendix" + "dots" + "makeatletter" "makeatother" "jobname") + + (when (string-equal LaTeX-version "2e") + (LaTeX-add-environments + '("filecontents" LaTeX-env-contents) + '("filecontents*" LaTeX-env-contents)) + + (TeX-add-symbols + '("enlargethispage" (TeX-arg-length nil "1.0\\baselineskip")) + '("enlargethispage*" (TeX-arg-length nil "1.0\\baselineskip")) + '("tabularnewline" [ TeX-arg-length ]) + '("suppressfloats" [ TeX-arg-tb "Suppress floats position" ]) + '("ensuremath" "Math commands") + '("textsuperscript" "Text") + '("textsubscript" "Text") + '("textcircled" "Text") + '("mathring" t) + '("MakeUppercase" t) + '("MakeLowercase" t) + '("chaptermark" "Text") + '("sectionmark" "Text") + '("subsectionmark" "Text") + '("subsubsectionmark" "Text") + '("paragraphmark" "Text") + '("subparagraphmark" "Text") + + "LaTeXe" + "listfiles" "frontmatter" "mainmatter" "backmatter" + "leftmark" "rightmark" + "textcompwordmark" "textvisiblespace" "textemdash" "textendash" + "textexclamdown" "textquestiondown" "textquotedblleft" + "textquotedblright" "textquoteleft" "textquoteright" + "textbackslash" "textbar" "textless" "textgreater" + "textasciicircum" "textasciitilde" + + ;; With the advent of LaTeX2e release 2020-02-02, all symbols + ;; provided by textcomp.sty are available out of the box by the + ;; kernel. The next block is moved here from textcomp.el: + "capitalgrave" ; Type: Accent -- Slot: 0 + "capitalacute" ; Type: Accent -- Slot: 1 + "capitalcircumflex" ; Type: Accent -- Slot: 2 + "capitaltilde" ; Type: Accent -- Slot: 3 + "capitaldieresis" ; Type: Accent -- Slot: 4 + "capitalhungarumlaut" ; Type: Accent -- Slot: 5 + "capitalring" ; Type: Accent -- Slot: 6 + "capitalcaron" ; Type: Accent -- Slot: 7 + "capitalbreve" ; Type: Accent -- Slot: 8 + "capitalmacron" ; Type: Accent -- Slot: 9 + "capitaldotaccent" ; Type: Accent -- Slot: 10 + "textquotestraightbase" ; Type: Symbol -- Slot: 13 + "textquotestraightdblbase" ; Type: Symbol -- Slot: 18 + "texttwelveudash" ; Type: Symbol -- Slot: 21 + "textthreequartersemdash" ; Type: Symbol -- Slot: 22 + "textcapitalcompwordmark" ; Type: Symbol -- Slot: 23 + "textleftarrow" ; Type: Symbol -- Slot: 24 + "textrightarrow" ; Type: Symbol -- Slot: 25 + "t" ; Type: Accent -- Slot: 26 + "capitaltie" ; Type: Accent -- Slot: 27 + "newtie" ; Type: Accent -- Slot: 28 + "capitalnewtie" ; Type: Accent -- Slot: 29 + "textascendercompwordmark" ; Type: Symbol -- Slot: 31 + "textblank" ; Type: Symbol -- Slot: 32 + "textdollar" ; Type: Symbol -- Slot: 36 + "textquotesingle" ; Type: Symbol -- Slot: 39 + "textasteriskcentered" ; Type: Symbol -- Slot: 42 + "textdblhyphen" ; Type: Symbol -- Slot: 45 + "textfractionsolidus" ; Type: Symbol -- Slot: 47 + "textzerooldstyle" ; Type: Symbol -- Slot: 48 + "textoneoldstyle" ; Type: Symbol -- Slot: 49 + "texttwooldstyle" ; Type: Symbol -- Slot: 50 + "textthreeoldstyle" ; Type: Symbol -- Slot: 51 + "textfouroldstyle" ; Type: Symbol -- Slot: 52 + "textfiveoldstyle" ; Type: Symbol -- Slot: 53 + "textsixoldstyle" ; Type: Symbol -- Slot: 54 + "textsevenoldstyle" ; Type: Symbol -- Slot: 55 + "texteightoldstyle" ; Type: Symbol -- Slot: 56 + "textnineoldstyle" ; Type: Symbol -- Slot: 57 + "textlangle" ; Type: Symbol -- Slot: 60 + "textminus" ; Type: Symbol -- Slot: 61 + "textrangle" ; Type: Symbol -- Slot: 62 + "textmho" ; Type: Symbol -- Slot: 77 + "textbigcircle" ; Type: Symbol -- Slot: 79 + "textohm" ; Type: Symbol -- Slot: 87 + "textlbrackdbl" ; Type: Symbol -- Slot: 91 + "textrbrackdbl" ; Type: Symbol -- Slot: 93 + "textuparrow" ; Type: Symbol -- Slot: 94 + "textdownarrow" ; Type: Symbol -- Slot: 95 + "textasciigrave" ; Type: Symbol -- Slot: 96 + "textborn" ; Type: Symbol -- Slot: 98 + "textdivorced" ; Type: Symbol -- Slot: 99 + "textdied" ; Type: Symbol -- Slot: 100 + "textleaf" ; Type: Symbol -- Slot: 108 + "textmarried" ; Type: Symbol -- Slot: 109 + "textmusicalnote" ; Type: Symbol -- Slot: 110 + "texttildelow" ; Type: Symbol -- Slot: 126 + "textdblhyphenchar" ; Type: Symbol -- Slot: 127 + "textasciibreve" ; Type: Symbol -- Slot: 128 + "textasciicaron" ; Type: Symbol -- Slot: 129 + "textacutedbl" ; Type: Symbol -- Slot: 130 + "textgravedbl" ; Type: Symbol -- Slot: 131 + "textdagger" ; Type: Symbol -- Slot: 132 + "textdaggerdbl" ; Type: Symbol -- Slot: 133 + "textbardbl" ; Type: Symbol -- Slot: 134 + "textperthousand" ; Type: Symbol -- Slot: 135 + "textbullet" ; Type: Symbol -- Slot: 136 + "textcelsius" ; Type: Symbol -- Slot: 137 + "textdollaroldstyle" ; Type: Symbol -- Slot: 138 + "textcentoldstyle" ; Type: Symbol -- Slot: 139 + "textflorin" ; Type: Symbol -- Slot: 140 + "textcolonmonetary" ; Type: Symbol -- Slot: 141 + "textwon" ; Type: Symbol -- Slot: 142 + "textnaira" ; Type: Symbol -- Slot: 143 + "textguarani" ; Type: Symbol -- Slot: 144 + "textpeso" ; Type: Symbol -- Slot: 145 + "textlira" ; Type: Symbol -- Slot: 146 + "textrecipe" ; Type: Symbol -- Slot: 147 + "textinterrobang" ; Type: Symbol -- Slot: 148 + "textinterrobangdown" ; Type: Symbol -- Slot: 149 + "textdong" ; Type: Symbol -- Slot: 150 + "texttrademark" ; Type: Symbol -- Slot: 151 + "textpertenthousand" ; Type: Symbol -- Slot: 152 + "textpilcrow" ; Type: Symbol -- Slot: 153 + "textbaht" ; Type: Symbol -- Slot: 154 + "textnumero" ; Type: Symbol -- Slot: 155 + "textdiscount" ; Type: Symbol -- Slot: 156 + "textestimated" ; Type: Symbol -- Slot: 157 + "textopenbullet" ; Type: Symbol -- Slot: 158 + "textservicemark" ; Type: Symbol -- Slot: 159 + "textlquill" ; Type: Symbol -- Slot: 160 + "textrquill" ; Type: Symbol -- Slot: 161 + "textcent" ; Type: Symbol -- Slot: 162 + "textsterling" ; Type: Symbol -- Slot: 163 + "textcurrency" ; Type: Symbol -- Slot: 164 + "textyen" ; Type: Symbol -- Slot: 165 + "textbrokenbar" ; Type: Symbol -- Slot: 166 + "textsection" ; Type: Symbol -- Slot: 167 + "textasciidieresis" ; Type: Symbol -- Slot: 168 + "textcopyright" ; Type: Symbol -- Slot: 169 + "textordfeminine" ; Type: Symbol -- Slot: 170 + "textcopyleft" ; Type: Symbol -- Slot: 171 + "textlnot" ; Type: Symbol -- Slot: 172 + "textcircledP" ; Type: Symbol -- Slot: 173 + "textregistered" ; Type: Symbol -- Slot: 174 + "textasciimacron" ; Type: Symbol -- Slot: 175 + "textdegree" ; Type: Symbol -- Slot: 176 + "textpm" ; Type: Symbol -- Slot: 177 + "texttwosuperior" ; Type: Symbol -- Slot: 178 + "textthreesuperior" ; Type: Symbol -- Slot: 179 + "textasciiacute" ; Type: Symbol -- Slot: 180 + "textmu" ; Type: Symbol -- Slot: 181 + "textparagraph" ; Type: Symbol -- Slot: 182 + "textperiodcentered" ; Type: Symbol -- Slot: 183 + "textreferencemark" ; Type: Symbol -- Slot: 184 + "textonesuperior" ; Type: Symbol -- Slot: 185 + "textordmasculine" ; Type: Symbol -- Slot: 186 + "textsurd" ; Type: Symbol -- Slot: 187 + "textonequarter" ; Type: Symbol -- Slot: 188 + "textonehalf" ; Type: Symbol -- Slot: 189 + "textthreequarters" ; Type: Symbol -- Slot: 190 + "texteuro" ; Type: Symbol -- Slot: 191 + "texttimes" ; Type: Symbol -- Slot: 214 + "textdiv" ; Type: Symbol -- Slot: 246 + '("textcircled" 1) ; Type: Command -- Slot: N/A + '("capitalcedilla" 1) ; Type: Command -- Slot: N/A + '("capitalogonek" 1) ; Type: Command -- Slot: N/A + + "rmfamily" "sffamily" "ttfamily" + '("mdseries" -1) '("bfseries" -1) + '("itshape" -1) '("slshape" -1) + '("upshape" -1) '("scshape" -1) + '("eminnershape" -1) + ;; The next 3 were added to LaTeX kernel with 2020-02-02 release: + '("sscshape" -1) '("swshape" -1) '("ulcshape" -1) + ;; These are for the default settings: + "sscdefault" "swdefault" "ulcdefault" + ;; This macro is for `spaced small caps'. Currently, only some + ;; commercial fonts offer this. It should be moved into + ;; `LaTeX-font-list' once it is needed more frequently. + '("textssc" t) + ;; User level reset macros: + '("normalfont" -1) '("normalshape" -1) + + ;; LaTeX hook macros: + '("AddToHook" TeX-arg-hook [ "Label" ] t) + '("RemoveFromHook" TeX-arg-hook [ "Label" ]) + '("AddToHookNext" TeX-arg-hook t) + + ;; Added in LaTeX 2021-11-15 + '("counterwithin" + [TeX-arg-eval completing-read + (TeX-argument-prompt t nil "Format") + '("\\arabic" "\\roman" "\\Roman" "\\alph" "\\Alph")] + (TeX-arg-counter) + (TeX-arg-counter "Within counter")) + '("counterwithin*" + [TeX-arg-eval completing-read + (TeX-argument-prompt t nil "Format") + '("\\arabic" "\\roman" "\\Roman" "\\alph" "\\Alph")] + (TeX-arg-counter) + (TeX-arg-counter "Within counter")) + + '("counterwithout" + [TeX-arg-eval completing-read + (TeX-argument-prompt t nil "Format") + '("\\arabic" "\\roman" "\\Roman" "\\alph" "\\Alph")] + (TeX-arg-counter) + (TeX-arg-counter "Within counter")) + '("counterwithout*" + [TeX-arg-eval completing-read + (TeX-argument-prompt t nil "Format") + '("\\arabic" "\\roman" "\\Roman" "\\alph" "\\Alph")] + (TeX-arg-counter) + (TeX-arg-counter "Within counter")))) + + (TeX-run-style-hooks "LATEX") + + (make-local-variable 'TeX-font-list) + (make-local-variable 'TeX-font-replace-function) + (if (string-equal LaTeX-version "2") + () + (setq TeX-font-list LaTeX-font-list) + (setq TeX-font-replace-function #'TeX-font-replace-macro) + (TeX-add-symbols + '("newcommand" TeX-arg-define-macro + [ TeX-arg-define-macro-arguments ] t) + '("renewcommand" TeX-arg-macro + [ TeX-arg-define-macro-arguments ] t) + '("providecommand" TeX-arg-define-macro + [ TeX-arg-define-macro-arguments ] t) + '("providecommand*" TeX-arg-define-macro + [ TeX-arg-define-macro-arguments ] t) + '("newcommand*" TeX-arg-define-macro + [ TeX-arg-define-macro-arguments ] t) + '("renewcommand*" TeX-arg-macro + [ TeX-arg-define-macro-arguments ] t) + '("newenvironment" TeX-arg-define-environment + [ TeX-arg-define-macro-arguments ] t t) + '("renewenvironment" TeX-arg-environment + [ TeX-arg-define-macro-arguments ] t t) + '("usepackage" LaTeX-arg-usepackage) + '("RequirePackage" LaTeX-arg-usepackage) + '("ProvidesPackage" (TeX-arg-file-name-sans-extension "Package name") + [ TeX-arg-conditional (y-or-n-p "Insert version? ") + ([ TeX-arg-version ]) nil]) + '("ProvidesClass" (TeX-arg-file-name-sans-extension "Class name") + [ TeX-arg-conditional (y-or-n-p "Insert version? ") + ([ TeX-arg-version ]) nil]) + '("ProvidesFile" (TeX-arg-file-name "File name") + [ TeX-arg-conditional (y-or-n-p "Insert version? ") + ([ TeX-arg-version ]) nil ]) + '("documentclass" TeX-arg-document))) + + (TeX-add-style-hook "latex2e" + ;; Use new fonts for `\documentclass' documents. + (lambda () + (setq TeX-font-list LaTeX-font-list) + (setq TeX-font-replace-function #'TeX-font-replace-macro) + (run-hooks 'LaTeX2e-hook)) + TeX-dialect) + + (TeX-add-style-hook "latex2" + ;; Use old fonts for `\documentstyle' documents. + (lambda () + (setq TeX-font-list (default-value 'TeX-font-list)) + (setq TeX-font-replace-function + (default-value 'TeX-font-replace-function)) + (run-hooks 'LaTeX2-hook)) + TeX-dialect) + + ;; There must be something better-suited, but I don't understand the + ;; parsing properly. -- dak + (TeX-add-style-hook "pdftex" #'TeX-PDF-mode-on :classopt) + (TeX-add-style-hook "pdftricks" #'TeX-PDF-mode-on :classopt) + (TeX-add-style-hook "pst-pdf" #'TeX-PDF-mode-on :classopt) + (TeX-add-style-hook "dvips" + (lambda () + ;; Leave at user's choice whether to disable + ;; `TeX-PDF-mode' or not. + (setq TeX-PDF-from-DVI "Dvips")) + :classopt) + ;; This is now done in style/pstricks.el because it prevents other + ;; pstricks style files from being loaded. + ;; (TeX-add-style-hook "pstricks" 'TeX-PDF-mode-off) + (TeX-add-style-hook "psfrag" #'TeX-PDF-mode-off :classopt) + (TeX-add-style-hook "dvipdf" #'TeX-PDF-mode-off :classopt) + (TeX-add-style-hook "dvipdfm" #'TeX-PDF-mode-off :classopt) + (TeX-add-style-hook "dvipdfmx" + (lambda () + (TeX-PDF-mode-on) + ;; XeLaTeX normally don't use dvipdfmx + ;; explicitly. + (unless (eq TeX-engine 'xetex) + (setq TeX-PDF-from-DVI "Dvipdfmx"))) + :classopt) + ;; (TeX-add-style-hook "DVIoutput" 'TeX-PDF-mode-off) + ;; + ;; Well, DVIoutput indicates that we want to run PDFTeX and expect to + ;; get DVI output. Ugh. + (TeX-add-style-hook "ifpdf" (lambda () + (TeX-PDF-mode-on) + (TeX-PDF-mode-off)) + :classopt) + ;; ifpdf indicates that we cater for either. So calling both + ;; functions will make sure that the default will get used unless the + ;; user overrode it. + + (set (make-local-variable 'imenu-create-index-function) + #'LaTeX-imenu-create-index-function) + + (use-local-map LaTeX-mode-map) + + ;; Initialization of `add-log-current-defun-function': + (set (make-local-variable 'add-log-current-defun-function) + #'TeX-current-defun-name) + + ;; Set LaTeX-specific help messages for error so that it's available + ;; in `TeX-help-error'. + (setq-local TeX-error-description-list-local + LaTeX-error-description-list)) + +(defun LaTeX-imenu-create-index-function () + "Imenu support function for LaTeX." + (TeX-update-style) + (let (entries + (regexp (LaTeX-outline-regexp))) + (goto-char (point-max)) + (while (re-search-backward regexp nil t) + (let* ((name (LaTeX-outline-name)) + (level (make-string (1- (LaTeX-outline-level)) ?\ )) + (label (concat level level name)) + (mark (make-marker))) + (set-marker mark (point)) + (set-text-properties 0 (length label) nil label) + (setq entries (cons (cons label mark) entries)))) + entries)) + +(defvar LaTeX-builtin-opts + '("12pt" "11pt" "10pt" "twocolumn" "twoside" "draft") + "Built in options for LaTeX standard styles.") + +(defun LaTeX-209-to-2e () + "Make a stab at changing 2.09 doc header to 2e style." + (interactive) + (TeX-home-buffer) + (let (optstr optlist 2eoptlist 2epackages docline docstyle) + (goto-char (point-min)) + (if + (search-forward-regexp + "\\\\documentstyle\\[\\([^]]*\\)\\]{\\([^}]*\\)}" + (point-max) t) + (setq optstr (TeX-match-buffer 1) + docstyle (TeX-match-buffer 2) + optlist (split-string optstr ",")) + (if (search-forward-regexp + "\\\\documentstyle{\\([^}]*\\)}" + (point-max) t) + (setq docstyle (TeX-match-buffer 1)) + (error "No documentstyle defined"))) + (beginning-of-line 1) + (setq docline (point)) + (insert "%%%") + (while optlist + (if (member (car optlist) LaTeX-builtin-opts) + (setq 2eoptlist (cons (car optlist) 2eoptlist)) + (setq 2epackages (cons (car optlist) 2epackages))) + (setq optlist (cdr optlist))) + ;;(message (format "%S %S" 2eoptlist 2epackages)) + (goto-char docline) + (forward-line 1) + (insert "\\documentclass") + (if 2eoptlist + (insert "[" + (mapconcat (lambda (x) x) + (nreverse 2eoptlist) ",") "]")) + (insert "{" docstyle "}\n") + (if 2epackages + (insert "\\usepackage{" + (mapconcat (lambda (x) x) + (nreverse 2epackages) "}\n\\usepackage{") "}\n")) + (if (equal docstyle "slides") + (progn + (goto-char (point-min)) + (while (re-search-forward "\\\\blackandwhite{" nil t) + (replace-match "\\\\input{" nil nil))))) + (TeX-normal-mode nil)) + +(defun LaTeX-env-beginning-pos-col () + "Return a cons: (POINT . COLUMN) for current environment's beginning." + (save-excursion + (LaTeX-find-matching-begin) + (cons (point) (current-column)))) + +(defun LaTeX-hanging-ampersand-position (&optional pos col) + "Return indent column for a hanging ampersand (that is, ^\\s-*&). +When you know the position and column of the beginning of the +current environment, supply them as optional arguments POS and +COL for efficiency." + (cl-destructuring-bind + (beg-pos . beg-col) + (if pos + (cons pos col) + (LaTeX-env-beginning-pos-col)) + (let ((cur-pos (point))) + (save-excursion + (if (and (search-backward "\\\\" beg-pos t) + ;; Give up if the found "\\" belongs to an inner env. + (= beg-pos + (save-excursion + (LaTeX-find-matching-begin) + (point)))) + ;; FIXME: This `how-many' fails to count correctly if + ;; there is an inner env with "&" but without "\\", e.g. + ;; \begin{pmatrix} + ;; a & b + ;; \end{pmatrix} + (let ((cur-idx (how-many "[^\\]&" (point) cur-pos))) + (goto-char beg-pos) + ;; FIXME: This regex search fails if there is an inner + ;; env with "&" in it. + (if (re-search-forward "[^\\]&" cur-pos t (+ 1 cur-idx)) + (- (current-column) 1) + ;; If the above searchs fails, i.e. no "&" found, + ;; (- (current-column) 1) returns -1, which is wrong. + ;; So we use a fallback (+ 2 beg-col) whenever this + ;; happens: + (+ 2 beg-col))) + (+ 2 beg-col)))))) + +(defun LaTeX-indent-tabular () + "Return indent column for the current tabular-like line." + (cl-destructuring-bind + (beg-pos . beg-col) + (LaTeX-env-beginning-pos-col) + (let ((tabular-like-end-regex + (format "\\\\end{%s}" + (regexp-opt + (let (out) + (mapc (lambda (x) + (when (eq (cadr x) #'LaTeX-indent-tabular) + (push (car x) out))) + LaTeX-indent-environment-list) + out))))) + (cond ((looking-at tabular-like-end-regex) + beg-col) + + ((looking-at "\\\\\\\\") + (+ 2 beg-col)) + + ((looking-at "&") + (LaTeX-hanging-ampersand-position beg-pos beg-col)) + + (t + (+ 2 + (let ((any-col + (save-excursion + (when + (catch 'found + ;; Search "\\" or "&" which belongs to + ;; the current env, not an inner env. + (while (re-search-backward + "\\\\\\\\\\|[^\\]&" beg-pos t) + (let ((p (point))) + (when (= beg-pos + (progn + (LaTeX-find-matching-begin) + (point))) + ;; It belongs to the current env. + ;; Go to target position and exit + ;; the loop. + (goto-char (1+ p)) + (throw 'found t) + ;; Otherwise it belongs to an + ;; inner env, so continue the + ;; loop. + )))) + ;; If we found "&", then use its column as + ;; `any-col'. Else, `any-col' will be nil. + (if (= ?& (char-after)) + (current-column)))))) + (or any-col + beg-col)))))))) + +;; Utilities: + +(defmacro LaTeX-check-insert-macro-default-style (&rest body) + "Check for values of `TeX-insert-macro-default-style' and `current-prefix-arg'. +This is a utility macro with code taken from +`TeX-parse-arguments'. It should be used inside more complex +function within AUCTeX style files where optional and mandatory +arguments are queried and inserted. For examples, check the +functions `TeX-arg-color' (style/color.el) or +`LaTeX-arg-bicaption-bicaption' (style/bicaption.el)." + `(unless (if (eq TeX-insert-macro-default-style 'show-all-optional-args) + (equal current-prefix-arg '(4)) + (or + (and (eq TeX-insert-macro-default-style 'show-optional-args) + (equal current-prefix-arg '(4))) + (and (eq TeX-insert-macro-default-style 'mandatory-args-only) + (null (equal current-prefix-arg '(4)))) + TeX-last-optional-rejected)) + ,@body)) + +(defun LaTeX-extract-key-value-label (&optional key num) + "Return a regexp string to match a label in an optional argument. +The optional KEY is a string which is the name of the key in the +key=value, default is \"label\". NUM is an integer for an +explicitly numbered group construct, useful when adding items to +`reftex-label-regexps'. + +As an extra feature, the key can be the symbol `none' where the +entire matching for the key=value is skipped. The regexp then is +useful for skipping complex optional arguments. It should be +wrapped in \\(?:...\\)? then." + ;; The regexp produced here is ideally in sync with the complex one + ;; in `reftex-label-regexps'. + (concat + ;; Match the opening [ and the following chars + "\\[[^][]*" + ;; Allow nested levels of chars enclosed in braces + "\\(?:{[^}{]*" + "\\(?:{[^}{]*" + "\\(?:{[^}{]*}[^}{]*\\)*" + "}[^}{]*\\)*" + "}[^][]*\\)*" + ;; If KEY is the symbol none, don't look for any key=val: + (unless (eq key 'none) + (concat "\\<" + ;; Match the key, default is label + (or key "label") + ;; Optional spaces + "[[:space:]]*=[[:space:]]*" + ;; Match the value; braces around the value are optional + "{?\\(" + ;; Cater for NUM which sets the regexp group + (when (and num (integerp num)) + (concat "?" (number-to-string num) ":")) + ;; One of these chars terminates the value + "[^] ,}\r\n\t%]+" + ;; Close the group + "\\)}?")) + ;; We are done. Just search until the next closing bracket + "[^]]*\\]")) + +(provide 'latex) + +;;; latex.el ends here -- cgit v1.2.1