;;; mathtools.el --- Style hook for the LaTeX package `mathtools'. -*- lexical-binding: t; -*- ;; Copyright (C) 2011-2020, 2022 Free Software Foundation, Inc. ;; Author: Mads Jensen ;; Created: 2011-02-13 ;; 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 adds support for `mathtools.sty' ;;; Comments: ;;; This package serves as a wrapper for amsmath, adding more features ;;; and fixing a few bugs in amsmath. The mathstyle argument for many ;;; of the macros is discussed at ;;; ;;; Code: ;; Needed for auto-parsing: (require 'tex) (require 'latex) ;; Silence the compiler: (declare-function font-latex-add-keywords "font-latex" (keywords class)) (defvar LaTeX-amsmath-package-options) ;; amsmath options which can be passed directly to mathtools are ;; appended in the style hook below (defvar LaTeX-mathtools-package-options '("fixamsmath" "donotfixamsmathbugs" "allowspaces" "disallowspaces" ;; Update 2013: We now make \(\) and \[\] robust (can be disabled ;; via nonrobust package option) "nonrobust") "Package options for the mathtools package.") (TeX-load-style "amsmath") (dolist (elt LaTeX-amsmath-package-options) (add-to-list 'LaTeX-mathtools-package-options elt)) (defvar LaTeX-mathtools-key-val-options '(("showonlyrefs") ("mathic" ("true" "false")) ("showmanualtags" ("true" "false")) ;; 3.4.1 Matrices ("smallmatrix-align" ("c" "l" "r")) ("smallmatrix-inner-space") ;; 3.4.2 The multlined environment ("firstline-afterskip") ("lastline-preskip") ("multlined-pos" ("c" "b" "t")) ("multlined-width") ;; 3.4.7 Centered \vdots ("shortvdotsadjustabove") ("shortvdotsadjustbelow") ;; 3.5 Intertext and short intertext ("original-intertext" ("true" "false")) ("original-shortintertext" ("true" "false")) ("above-intertext-sep") ("below-intertext-sep") ("above-shortintertext-sep") ("below-shortintertext-sep") ;; 3.7.2 Vertically centered colon ("centercolon" ("true" "false")) ;; 4.2 Left sub/superscripts ("prescript-sub-format") ("prescript-sup-format") ("prescript-arg-format")) "Options for the \\mathtoolsset command.") ;; Setup for \newtagform (TeX-auto-add-type "mathtools-newtagform" "LaTeX") (defvar LaTeX-mathtools-newtagform-regexp '("\\\\newtagform{\\([^}]+\\)}" 1 LaTeX-auto-mathtools-newtagform) "Matches the first argument of \\newtagform from mathtools package.") ;; Setup for \DeclarePairedDelimiter(X)?: (TeX-auto-add-type "mathtools-DeclarePairedDelimiter" "LaTeX") (defvar LaTeX-mathtools-DeclarePairedDelimiter-regexp `(,(concat "\\\\DeclarePairedDelimiter\\(?:X\\|XPP\\)?" "{?" "\\\\\\([a-zA-Z]+\\)" "}?" "\\(?:\\[\\([0-9]+\\)\\]\\)?") (1 2) LaTeX-auto-mathtools-DeclarePairedDelimiter) "Match the arguments of \\DeclarePairedDelimiterX? from mathtools package.") ;; Setup for \newgathered (TeX-auto-add-type "mathtools-newgathered" "LaTeX") (defvar LaTeX-mathtools-newgathered-regexp '("\\\\newgathered{\\([^}]+\\)}" 1 LaTeX-auto-mathtools-newgathered) "Matches the first argument of \\newgathered from mathtools package.") (defun LaTeX-mathtools-auto-prepare () "Clear various variables for mathtools package before parsing." (setq LaTeX-auto-mathtools-newtagform nil LaTeX-auto-mathtools-DeclarePairedDelimiter nil LaTeX-auto-mathtools-newgathered nil)) (defun LaTeX-mathtools-auto-cleanup () "Process the parsed elements for mathtools package." (when (LaTeX-mathtools-DeclarePairedDelimiter-list) (dolist (delim (LaTeX-mathtools-DeclarePairedDelimiter-list)) (let ((cmd (car delim)) (arg (cadr delim))) (TeX-add-symbols `(,cmd [ LaTeX-mathtools-arg-mathsize-completion ] ,(if (string= arg "") 1 (string-to-number arg))) `(,(concat cmd "*") ,(if (string= arg "") 1 (string-to-number arg))))))) (when (LaTeX-mathtools-newgathered-list) (dolist (env (mapcar #'car (LaTeX-mathtools-newgathered-list))) (LaTeX-add-environments env) (add-to-list 'LaTeX-item-list `(,env . LaTeX-item-equation) t) (add-to-list 'LaTeX-label-alist `(,env . LaTeX-amsmath-label) t) (when (fboundp 'reftex-add-label-environments) (reftex-add-label-environments `((,env ?e nil nil t))))))) (add-hook 'TeX-auto-prepare-hook #'LaTeX-mathtools-auto-prepare t) (add-hook 'TeX-auto-cleanup-hook #'LaTeX-mathtools-auto-cleanup t) (add-hook 'TeX-update-style-hook #'TeX-auto-parse t) (defun LaTeX-mathtools-arg-mathstyle-completion (optional) "Query and insert mathstyle argument to various commands. If OPTIONAL, insert it as optional argument in brackets." (TeX-argument-insert (completing-read (TeX-argument-prompt optional nil (concat "Math style: " TeX-esc) t) '("displaystyle" "textstyle" "scriptstyle" "scriptscriptstyle")) optional TeX-esc)) (defun LaTeX-mathtools-arg-mathsize-completion (optional) "Query and insert math size argument to various commands. If OPTIONAL, insert it as optional argument in brackets." (TeX-argument-insert (completing-read (TeX-argument-prompt optional nil (concat "Size command: " TeX-esc) t) '("big" "Big" "bigg" "Bigg")) optional TeX-esc)) (defun LaTeX-mathtools-arg-declarepaireddelimiter (optional &optional X) "Query and insert various \\DeclarePairedDelimiter macros from mathtools package." (let ((cmd (TeX-read-string (concat "Command: " TeX-esc))) (arg (when X (TeX-read-string (TeX-argument-prompt t nil "Number of arguments"))))) (TeX-add-symbols `(,cmd [ LaTeX-mathtools-arg-mathsize-completion ] ,(if X ;; This is no precaution, arg has to be > 0 (string-to-number arg) 1)) `(,(concat cmd "*") ,(if X (string-to-number arg) 1))) (LaTeX-add-mathtools-DeclarePairedDelimiters `(,cmd ,(if X arg ""))) (TeX-argument-insert cmd optional TeX-esc) (when arg (insert (concat LaTeX-optop arg LaTeX-optcl))))) (defun LaTeX-mathtools-env-multlined (env) "Query and insert two optional arguments for ENV multlined. If both arguments are given, insert them in brackets. If only a width is given, insert it prefixed with a pair of empty brackets." (let ((pos (TeX-read-string (TeX-argument-prompt t nil "Position (t, b or c (default))"))) (width (completing-read (TeX-argument-prompt t nil "Width") (mapcar (lambda (x) (concat TeX-esc (car x))) (LaTeX-length-list))))) (LaTeX-insert-environment env (cond (;; both arguments (and pos (not (string= pos "")) width (not (string= width ""))) (format "[%s][%s]" pos width)) (;; pos not empty, width empty (and pos (not (string= pos "")) (string= width "")) (format "[%s]" pos)) (;; pos empty, width not (and (string= pos "") width (not (string= width ""))) (format "[][%s]" width)) (t nil))))) (defun LaTeX-mathtools-env-cases (env) "Insert various cases ENVs incl. an ampersand from mathtools package." (LaTeX-insert-environment env) (save-excursion (insert ?&))) (defun LaTeX-mathtools-item-cases () "Insert contents to terminate a line in multi-line cases environment. Put line break macro on the last line. Next, insert an ampersand." (end-of-line 0) (just-one-space) (TeX-insert-macro "\\") (forward-line 1) (save-excursion (insert ?&))) (TeX-add-style-hook "mathtools" (lambda () ;; Add mathtools to parser (TeX-auto-add-regexp LaTeX-mathtools-newtagform-regexp) (TeX-auto-add-regexp LaTeX-mathtools-DeclarePairedDelimiter-regexp) (TeX-auto-add-regexp LaTeX-mathtools-newgathered-regexp) ;; "default" is pre-defined (LaTeX-add-mathtools-newtagforms "default") ;; mathtools requires amsmath, as some bugs in amsmath are fixed (TeX-run-style-hooks "amsmath") (LaTeX-add-environments ;; 3.4.1 Matrices '("matrix*" [ "Vertical alignment (l, r or c (default))" ]) '("pmatrix*" [ "Vertical alignment (l, r or c (default))" ]) '("bmatrix*" [ "Vertical alignment (l, r or c (default))" ]) '("Bmatrix*" [ "Vertical alignment (l, r or c (default))" ]) '("vmatrix*" [ "Vertical alignment (l, r or c (default))" ]) '("Vmatrix*" [ "Vertical alignment (l, r or c (default))" ]) '("smallmatrix*" [ "Vertical alignment (l, r or c (default))" ]) '("psmallmatrix") '("psmallmatrix*" [ "Vertical alignment (l, r or c (default))" ]) '("bsmallmatrix") '("bsmallmatrix*" [ "Vertical alignment (l, r or c (default))" ]) '("Bsmallmatrix") '("Bsmallmatrix*" [ "Vertical alignment (l, r or c (default))" ]) '("vsmallmatrix") '("vsmallmatrix*" [ "Vertical alignment (l, r or c (default))" ]) '("Vsmallmatrix") '("Vsmallmatrix*" [ "Vertical alignment (l, r or c (default))" ]) ;; 3.4.2 The multlined environment '("multlined" LaTeX-mathtools-env-multlined) ;; 3.4.3 More cases -like environments '("dcases" LaTeX-mathtools-env-cases) '("dcases*" LaTeX-mathtools-env-cases) '("rcases" LaTeX-mathtools-env-cases) '("rcases*" LaTeX-mathtools-env-cases) '("drcases" LaTeX-mathtools-env-cases) '("drcases*" LaTeX-mathtools-env-cases) '("cases*" LaTeX-mathtools-env-cases) ;; 4.4 Spreading equations '("spreadlines" "Spacing between lines") ;; 4.5 Gathered environments '("lgathered" ["Vertical position (t or b)"]) '("rgathered" ["Vertical position (t or b)"])) (TeX-add-symbols '("mathtoolsset" (TeX-arg-key-val LaTeX-mathtools-key-val-options)) ;; 3.1.1 A complement to \smash, \llap, and \rlap '("mathllap" [ LaTeX-mathtools-arg-mathstyle-completion ] t) '("mathrlap" [ LaTeX-mathtools-arg-mathstyle-completion ] t) '("mathclap" [ LaTeX-mathtools-arg-mathstyle-completion ] t) '("mathmakebox" [ (TeX-arg-length "Width") ] [ "Position" ] 1) '("clap" 1) '("mathmbox" 1) ;; 3.1.2 Forcing a cramped style '("cramped" [ LaTeX-mathtools-arg-mathstyle-completion ] 1) '("crampedllap" [ LaTeX-mathtools-arg-mathstyle-completion ] t) '("crampedrlap" [ LaTeX-mathtools-arg-mathstyle-completion ] t) '("crampedclap" [ LaTeX-mathtools-arg-mathstyle-completion ] t) ;; 3.1.3 Smashing an operator '("smashoperator" [ "Position (l, r or lr (default)" ] 1) ;; 3.1.4 Adjusting the limits of operators '("adjustlimits" t (TeX-arg-literal "_") nil nil (TeX-arg-literal "_") nil) ;; 3.1.5 Swapping space above AMS display math environments '("SwapAboveDisplaySkip" 0) ;; 3.2.1 The appearance of tags '("newtagform" (TeX-arg-eval (lambda () (let ((newtag (TeX-read-string (TeX-argument-prompt nil nil "Name")))) (LaTeX-add-mathtools-newtagforms newtag) (format "%s" newtag)))) [ "Inner format" ] "Left" "Right") '("renewtagform" (TeX-arg-eval completing-read (TeX-argument-prompt nil nil "Name") (LaTeX-mathtools-newtagform-list)) [ "Inner format" ] "Left" "Right") '("usetagform" (TeX-arg-eval completing-read (TeX-argument-prompt nil nil "Name") (LaTeX-mathtools-newtagform-list))) ;; 3.2.2 Showing only referenced tags '("refeq" TeX-arg-ref) '("noeqref" TeX-arg-ref) ;; 3.3.1 Arrow-like symbols '("xleftrightarrow" ["Below"] "Above") '("xLeftarrow" ["Below"] "Above") '("xRightarrow" ["Below"] "Above") '("xLeftrightarrow" ["Below"] "Above") '("xhookleftarrow" ["Below"] "Above") '("xhookrightarrow" ["Below"] "Above") '("xmapsto" ["Below"] "Above") '("xrightharpoondown" ["Below"] "Above") '("xrightharpoonup" ["Below"] "Above") '("xleftharpoondown" ["Below"] "Above") '("xleftharpoonup" ["Below"] "Above") '("xrightleftharpoons" ["Below"] "Above") '("xleftrightharpoons" ["Below"] "Above") ;; 3.3.2 Braces and brackets '("underbracket" [ (TeX-arg-length "Rule thickness") ] [ (TeX-arg-length "Bracket height") ] t) '("overbracket" [ (TeX-arg-length "Rule thickness") ] [ (TeX-arg-length "Bracket height") ] t) '("underbrace" 1) '("overbrace" 1) '("LaTeXunderbrace" 1) '("LaTeXoverbrace" 1) ;; 3.4.2 '("shoveleft" [ (TeX-arg-length "Dimension") ] 1) '("shoveright" [ (TeX-arg-length "Dimension") ] 1) ;; 3.4.4 '("MoveEqLeft" [ "Number" ]) ;; 3.4.5 Boxing a single line in an alignment '("Aboxed" 1) ;; 3.4.6 Adding arrows between lines in an alignment '("ArrowBetweenLines" [ TeX-arg-macro ] ) '("ArrowBetweenLines*" [ TeX-arg-macro ] ) ;; 3.4.7 Centered \vdots '("vdotswithin" "Symbol") '("shortvdotswithin" "Symbol") '("shortvdotswithin*" "Symbol") '("MTFlushSpaceAbove") '("MTFlushSpaceBelow") ;; 3.5 Intertext and short intertext ;; don't understand t, but intertext in amsmath.el uses it '("shortintertext" t) ;; 3.6 Paired delimiters '("DeclarePairedDelimiter" LaTeX-mathtools-arg-declarepaireddelimiter "Left delimiter" "Right delimiter") '("DeclarePairedDelimiterX" (LaTeX-mathtools-arg-declarepaireddelimiter t) "Left delimiter" "Right delimiter" t) '("DeclarePairedDelimiterXPP" (LaTeX-mathtools-arg-declarepaireddelimiter t) "Pre-code" "Left delimiter" "Right delimiter" 2) '("delimsize" 0) ;; 3.6.1 Expert use '("reDeclarePairedDelimiterInnerWrapper" (TeX-arg-eval (lambda () (let ((cmd (completing-read (concat "Command: " TeX-esc) (mapcar #'car (LaTeX-mathtools-DeclarePairedDelimiter-list))))) (concat TeX-esc cmd)))) (TeX-arg-eval completing-read "star or nostar: " '("star" "nostar")) t) ;; 3.7.1 Left and right parentheses '("lparen" TeX-arg-insert-right-brace-maybe) '("rparen") ;; 3.7.2 Vertically centered colon "vcentcolon" "ordinarycolon" "coloneqq" "Coloneqq" "coloneq" "Coloneq" "eqqcolon" "Eqqcolon" "eqcolon" "Eqcolon" "colonapprox" "Colonapprox" "colonsim" "Colonsim" "dblcolon" ;; 3.7.3 A few missing symbols "nuparrow" "ndownarrow" "bigtimes" ;; 4.2 Left sub/superscripts '("prescript" "Below" "Above" t) ;; 4.3 Declaring math sizes '("DeclareMathSizes" 4) ;; 4.5 Gathered environments '("newgathered" (TeX-arg-eval (lambda () (let ((env (TeX-read-string (TeX-argument-prompt nil nil "Name")))) (LaTeX-add-environments env) (LaTeX-add-mathtools-newgathereds env) (add-to-list 'LaTeX-item-list `(,env . LaTeX-item-equation) t) (add-to-list 'LaTeX-label-alist `(,env . LaTeX-amsmath-label) t) (format "%s" env)))) 3) '("renewgathered" (TeX-arg-eval completing-read (TeX-argument-prompt nil nil "Name") (LaTeX-mathtools-newgathered-list)) 3) ;; 4.6 Split fractions '("splitfrac" 2) '("splitdfrac" 2)) ;; Append delimiters to `TeX-braces-association' ;; 3.7.1 Left and right parentheses (make-local-variable 'TeX-braces-association) (add-to-list 'TeX-braces-association '("\\lparen" . "\\rparen") t) (setq LaTeX-item-list (append '(("multlined" . LaTeX-item-equation) ("lgathered" . LaTeX-item-equation) ("rgathered" . LaTeX-item-equation) ;; FIXME: The entry for spreadlines seems dubious. ("spreadlines" . LaTeX-item-equation) ("matrix*" . LaTeX-item-equation) ("pmatrix*" . LaTeX-item-equation) ("bmatrix*" . LaTeX-item-equation) ("Bmatrix*" . LaTeX-item-equation) ("vmatrix*" . LaTeX-item-equation) ("Vmatrix*" . LaTeX-item-equation) ("smallmatrix*" . LaTeX-item-equation) ("psmallmatrix" . LaTeX-item-equation) ("psmallmatrix*" . LaTeX-item-equation) ("bsmallmatrix" . LaTeX-item-equation) ("bsmallmatrix*" . LaTeX-item-equation) ("Bsmallmatrix" . LaTeX-item-equation) ("Bsmallmatrix*" . LaTeX-item-equation) ("vsmallmatrix" . LaTeX-item-equation) ("vsmallmatrix*" . LaTeX-item-equation) ("Vsmallmatrix" . LaTeX-item-equation) ("Vsmallmatrix*" . LaTeX-item-equation) ("dcases" . LaTeX-mathtools-item-cases) ("dcases*" . LaTeX-mathtools-item-cases) ("rcases" . LaTeX-mathtools-item-cases) ("rcases*" . LaTeX-mathtools-item-cases) ("drcases" . LaTeX-mathtools-item-cases) ("drcases*" . LaTeX-mathtools-item-cases) ("cases*" . LaTeX-mathtools-item-cases)) LaTeX-item-list)) (setq LaTeX-label-alist (append '(("lgathered" . LaTeX-amsmath-label) ("rgathered" . LaTeX-amsmath-label) ("multlined" . LaTeX-amsmath-label)) LaTeX-label-alist)) ;; RefTeX support: Add env's with `reftex-add-label-environments' (when (fboundp 'reftex-add-label-environments) (let ((envs '(("lgathered" ?e nil nil t) ("rgathered" ?e nil nil t) ("multlined" ?e nil nil t)))) (dolist (env envs) (reftex-add-label-environments `(,env))))) ;; Fontification (when (and (featurep 'font-latex) (eq TeX-install-font-lock 'font-latex-setup)) (font-latex-add-keywords '(("mathtoolsset" "{") ("newtagform" "{[{{") ("renewtagform" "{[{{") ("DeclarePairedDelimiter" "|{\\{{") ("DeclarePairedDelimiterX" "|{\\[{{{") ("DeclarePairedDelimiterXPP" "|{\\[{{{{{") ("reDeclarePairedDelimiterInnerWrapper" "|{\\{{") ("DeclareMathSizes" "{{{{") ("newgathered" "{{{{") ("renewgathered" "{{{{")) 'function) (font-latex-add-keywords '(("usetagform" "{")) 'variable) (font-latex-add-keywords '(("refeq" "{") ("noeqref" "{")) 'reference))) TeX-dialect) ;;; mathtools.el ends here