% \iffalse % !TEX encoding = UTF-8 Unicode % !TEX TS-program = pdflatex % % % %% mathcommand.dtx %% %% Copyright (C) 2019-2021 by Thomas Colcombet %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3 %% of this license or (at your option) any later version. %% The latest version of this license is in %% %% http://www.latex-project.org/lppl.txt %% %% and version 1.3 or later is part of all distributions of LaTeX %% version 2005/12/01 or later. %% %% This work has the LPPL maintenance status ‘maintained’. %% %% The Current Maintainer of this work is Thomas Colcombet. %% %% This work consists of the files %% mathcommand.dtx, mathcommand.ins, and makefile, %% and the derived files %% mathcommand.sty and readme.md. %% % \fi % % \iffalse %\usepackage{expl3} %\ProvidesExplPackage{mathcommand}{2021/06/07}{1.04}{} %<*driver> \documentclass{ltxdoc} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{paralist} \usepackage[svgnames]{xcolor} \usepackage{expl3} \usepackage{mathcommand} \usepackage[hidelinks]{hyperref} \usepackage[quotation,scope,notion,electronic]{knowledge} \usepackage{enumitem} \CheckSum{0} \changes{1.01}{2019/05/12}{Initial version} % \changes{1.02}{2019/07/03}{Bug correction} % \changes{1.03}{2019/12/06}{added disabling commands} % \changes{1.04}{2021/06/05}{correction with respect to modification of xparse package} % \GetFileInfo{mathcommand.sty} % \DoNotIndex{} \edef\mathcommandversiondate{\fileversion--\filedate} \newcommand\smallcode[1]{\colorbox{Honeydew}{\texttt{#1}}} \newsavebox{\fminipagebox} \NewDocumentEnvironment{cminipage}{m O{\fboxsep}} {\par\kern#2\noindent\begin{lrbox}{\fminipagebox} \begin{minipage}{#1}\ignorespaces} {\end{minipage}\end{lrbox}% \makebox[#1]{% \kern\dimexpr-\fboxsep-\fboxrule\relax \colorbox{Honeydew}{\usebox{\fminipagebox}}% \kern\dimexpr-\fboxsep-\fboxrule\relax}\par\kern#2} \NewDocumentEnvironment{fminipage}{m O{\fboxsep}} {\par\kern#2\noindent\begin{lrbox}{\fminipagebox} \begin{minipage}{#1}\ignorespaces} {\end{minipage}\end{lrbox}% \makebox[#1]{% \kern\dimexpr-\fboxsep-\fboxrule\relax \fbox{\usebox{\fminipagebox}}% \kern\dimexpr-\fboxsep-\fboxrule\relax}\par\kern#2\relax} \newenvironment{code}[1][12.4cm] {\par \noindent \cminipage{#1}% \tt }{% \endcminipage% \par } % This is a hack. Introducing Hyphenation everywhere in a sequence of token. % Otherwise the macro names tend to always exceed lines. % It should be improved in order to always require at least--say--3 symbols before % and after the hyphenation. \ExplSyntaxOn \cs_new:Nn\tl_fragilize:n {\__tl_fragilize:N#1\q_stop} \cs_new:Nn\__tl_fragilize:N {\token_if_eq_meaning:NNTF#1\q_stop {}{#1 \-\__tl_fragilize:N}} \cs_set_eq:NN\textfragilize\tl_fragilize:n \cs_new:Npn\Robustdisplay#1 {\exp_args:Nx\textfragilize{\robustdisplay{#1}}} \ExplSyntaxOff \let\cs\undefined \knowledgenewvariant\cs {namespace=cs, default style={autoref link,cs}, unknown style=cs unknown, unknown style cont=cs unknown, unknown warning=false, unknown diagnose=true, suggestion=cs, PDF string={\detokenize{#1}}} \knowledgestyle{cs}{wrap=\Robustdisplay,typewriter,up,md,color=NavyBlue} \knowledgestyle{cs unknown}{wrap=\Robustdisplay,typewriter,up,md,color=black} \knowledgenewvariant\csintro {namespace=cs, auto knowledge={autoref,scope=document,also now}, default style={autoref target,csintro}, unknown style=csintro unknown, unknown style cont=csintro unknown, unknown warning=false, unknown diagnose=false, PDF string = {\detokenize{#1}}} \knowledgestyle{csintro}{wrap=\Robustdisplay,typewriter,up,md,color=blue} \knowledgestyle{csintro unknown}{wrap=\Robustdisplay,typewriter,up,md,color=black} \knowledgenewvariant\csreintro {namespace=cs, default style=csintro, unknown style=csintro unknown, unknown style cont=csintro unknown, PDF string = {\Robustdisplay{#1}}} \newenvironment{commandlist} {\begin{description}[font=\normalfont, nosep, itemindent=-2cm, leftmargin=0cm, topsep=2.5mm]} {\end{description}} \knowledgedirective{doc notion} {autoref,style=doc notion,intro style=intro doc notion} \knowledgestyle{doc notion}{color=DarkBlue} \knowledgestyle{intro doc notion}{color=blue,emphasize} \knowledgedirective{package}{style=package} \knowledgestyle{package}{typewriter,color=black} \knowledge{xparse}{package,url = {https://www.ctan.org/pkg/xparse}} \knowledge{knowledge}{package,url = {https://www.ctan.org/pkg/knowledge}} \knowledge{xcolor}{package,url = {https://www.ctan.org/pkg/xcolor}} \knowledge{amsfonts}{package,url = {https://www.ctan.org/pkg/amsfonts}} \knowledge{amssymb}{package,url = {https://www.ctan.org/pkg/amssymb}} \knowledge{mathcommand}{package} \knowledge{math variant}{doc notion} \knowledge{text variant}{doc notion} \knowledge{PIE}[PIEs]{doc notion} \knowledge{PIE command}[PIE commands]{doc notion} \knowledge{notion} | Disabling | deactivated | Deactivating \knowledge{notion} | disabled=warning \knowledge{notion} | disabled=error \knowledge{notion} | disabled=silent \begin{document} \title{The \texttt{mathcommand} package for \LaTeX\\ {\small[version \mathcommandversiondate]}} \author{Thomas Colcombet} \maketitle \begin{abstract} \noindent The "mathcommand" package provides functionalities for defining macros \begin{compactenum} \item that have different behaviors depending on whether in math or text mode, \item that absorb Primes, Indices and Exponents (PIE) as extra parameters usable in the code, \item offers some iteration facilities for defining macros with similar code, \item and deactivating macros. \end{compactenum} The primary objective of this package is to be used together with the "knowledge" package for a proper handling of mathematical notations. \end{abstract} \section{History of the package} \begin{compactdesc} \item[2019-05-12] First version of the package. V1.01 on CTAN, \item[2019-05-14] New macros \cs\IfEmptyTF, \cs\GetExponent, and \cs\GetIndex. \item[2019-07-03] Corrects bug of functions declaring PIE's issuing an error when already existing. Version 1.02 on CTAN. \item[2019-12-06] Added disabling commands, and package options. Version 1.03 on CTAN. \item[2021-06-07] Corrected code that was broken due to an update in "xparse". Version 1.04 on CTAN. \end{compactdesc} \section{Defining text and math commands} The principle is that the package will maintain, for a macro \cs{\macro}, two concurrent version of the code: a ""math variant"" (technically it is stored in a macro \verb|\Math macro|) and a ""text variant"" (technically stored in a macro \verb|\Text macro|\footnote{These cannot be used accidentally by the user since these control sequences contain a space.}). The macro \cs{\macro} itself will execute one or the other depending on whether it is executed in math or text mode. Note that all the macros are non-expandable for avoiding problems with mathematics that would be sent, for instance, to the table of contents. The list of commands is described at the end of the section. For instance after executing: \begin{code} \cs{\newmathcommand}\cs\macro[1]\{\cs\mathit\{math\}\verb.^.\cs\mathrm\{code\}\verb._.\{(\#1)\}\}\\ \cs{\newtextcommand}\cs\macro[1]\{text code (\#1)\} \end{code} \noindent when executing \cs{\macro} in math mode, the math code will be executed, and in text mode similarly: \newmathcommand\toto[1]{\mathit{math}^{\mathrm{code}}_{(#1)}} \newtextcommand\toto[1]{text code (#1)} \begin{center} \smallcode{\cs\macro\{a\}} yields~`\toto{a}' \qquad while \smallcode{\$\cs\macro\{a\}\$} yields `$\toto{a}$'. \end{center} If the macro \cs{\macro} already exists, it is stored under the name \cs{\LaTeXmacro}, and then everything happens as if it had already been defined both in math and text mode. This is useful for redefining known macros. For instance \cs{\c} is a convenient way to producing cedillas in \LaTeX, as in \smallcode{\cs\c\ a} which yields `\c a'. However, one may want \cs{\c} to reprensent a variable $c$ in math mode. This is done using, e.g.: \begin{code}[5cm] \cs{\renewmathcommand}\cs\c\{c\} \end{code} \renewmathcommand\c{c} \noindent Then, the macro \cs{\c} still works in text mode, and using~\cs{\c} in math mode does display simply~`$\c$'. The name of the macros offered by the "mathcommand" package are mere adaptations of the standard macros of \LaTeX\ and of the package "xparse"\footnote{The package "xparse" offers a very convenient way to define macros with complicated parameter signatures.}. Their syntax is the same (in particular in terms of parameter definitions): \begin{commandlist} \itemAP[\csintro{\newmathcommand}] is similar to \cs{\newcommand} and creates a "math variant", \itemAP[\csintro{\newtextcommand}] is similar to \cs{\newcommand} and creates a "text variant", \itemAP[\csintro{\renewmathcommand}] is similar to \cs{\renewcommand} and creates a "math variant", \itemAP[\csintro{\renewtextcommand}] is similar to \cs{\renewcommand} and creates a "text variant", \itemAP[\csintro{\declaremathcommand}] is similar to \cs{\newcommand} but defines the macro even if it exists before; it creates a "math variant", \itemAP[\csintro{\declaretextcommand}] is similar to \cs{\newcommand} but defines the macro even if it exists before; it creates a "text variant", \itemAP[\csintro{\NewDocumentMathCommand}] is like \cs{\NewDocumentCommand} of the "xparse" package, but creates a "math variant", \itemAP[\csintro{\NewDocumentTextCommand}] is like \cs{\NewDocumentCommand} of the "xparse" package, but creates a "text variant", \itemAP[\csintro{\RenewDocumentMathCommand}] is like \cs{\RenewDocumentCommand} of the "xparse" package, but creates a "math variant", \itemAP[\csintro{\RenewDocumentTextCommand}] is like \cs{\RenewDocumentCommand} of the "xparse" package, but creates a "text variant", \itemAP[\csintro{\DeclareDocumentMathCommand}] is like \cs{\DeclareDocumentCommand} of the "xparse" package, but creates a "math variant", \itemAP[\csintro{\DeclareDocumentTextCommand}] is like \cs{\DeclareDocumentCommand} of the "xparse" package, but creates a "text variant", \itemAP[\csintro{\ProvideDocumentMathCommand}] is like \cs{\ProvideDocumentCommand} of the "xparse" package, but creates a "math variant", \itemAP[\csintro{\ProvideDocumentTextCommand}] is like \cs{\ProvideDocumentCommand} of the "xparse" package, but creates a "text variant". \end{commandlist} The package offers also the following commands: \begin{commandlist} \itemAP[\csintro{\declarecommand}] which is similar to \cs{\newcommand} but defines the macro even if it exists before, \itemAP[\csintro{\storecommand}\texttt{[optional-prefix]}\texttt{\cs\macro}] which copies the content of the macro \cs\macro\ to \verb|\optional-prefixmacro|. By default, the optional prefix is \verb|LaTeX|. (Hence, it does what is automatically made by commands such as \cs\declarecommand). \end{commandlist} \section{Defining Prime/Indices/Exponents absorbing commands (PIE commands)} Another feature offered by the "mathcommand" package is to permit the definitions of macros that would absorb the primes, subscript and superscript that follow them. \AP The three pieces of information are abbreviated as ""PIE"" (for ``Primes-Indices-Exponents''). This terminology serves as a help for remembering the order prime-index-exponent. \AP A ""PIE command"" is similar to a normal macro/command, but for the fact that the "PIEs" that follow are absorbed and can be used in the macro as three extra parameters. The list of macros usable for for defining "PIE commands" can be found at the end of this section. This is best explained through an example. After writing: \begin{code} \cs\newcommandPIE\cs\macro[1]\{([\#1]\#3)\#2\#4\} \end{code} \noindent one obtains that \newcommandPIE\macrob[1]{([#1]#3)#2#4} \begin{center} \smallcode{\$\cs\macro\{A\}\_2'\$} yields $\macrob{A}_2'$\ . \end{center} Indeed, in the body of the definition of \cs{macro}, \texttt{\#1} represents the normal parameter of the command, while the three following parameters (\texttt{\#2},\texttt{\#3},\texttt{\#4} in this case) contain respectively the primes (either empty or a sequence of $'$ symbols), the index (either empty if there is no subscript or of the form \verb"_{index}" if there is an index), and the exponent (either empty if there is no superscript or of the form \verb"^{exponent}" if there is one). In the case of the above definition, the index (parameter \texttt{\#3}) is written inside the parenthesis, while primes and exponents are put outside. The are furthermore some helper functions: \begin{commandlist} \itemAP[\csintro\IfEmptyTF] takes a string and two codes, and expands to the first one if the string is empty, and the second otherwise, \itemAP[\csintro{\GetIndex}] takes a string that is an index as in "PIE commands", and expands to its content: it maps the empty string to the empty string, and strings of the form \verb|_{sthg}| to \verb|sthg|, \itemAP[\csintro{\GetExponent}] takes a string that is an exponent as in "PIE commands", and expands to its content: it maps the empty string to the empty string, and strings of the form \verb|^{sthg}| to \verb|sthg|. \end{commandlist} For instance: \begin{code} \cs\newmathcommandPIE\cs\F\{\#2F\#1\cs\IfEmptyTF\{\#3\}\{\}\{\verb.^.\{(\cs\GetExponent\{\#3\})\}\}\} \end{code} \newmathcommandPIE\F{#2F#1\IfEmptyTF{#3}{}{^{(\GetExponent{#3})}}} \noindent displays \verb|$\F_2^3$| as `$\F_2^3$': the index is placed before, and the exponent is surrounded by parentheses. \paragraph{List of macros of defining "PIE commands".} Once more, appart from the specificity of "PIE commands", the syntax is as the original corresponding commands these are based on. \begin{commandlist} \itemAP[\csintro{\newcommandPIE}] is similar to \cs\newcommand\ (but defines a non-expandable macro) \itemAP[\csintro{\renewcommandPIE}] is similar to \cs\renewcommand\ (but defines a non-expandable macro) \itemAP[\csintro{\declarecommandPIE}] is similar to \cs\newcommand\ and works even if the macro already exists (and defines a non-expandable macro) \itemAP[\csintro{\NewDocumentCommandPIE}] is similar to \cs\NewDocumentCommand\ of the "xparse" package, \itemAP[\csintro{\RenewDocumentCommandPIE}] is similar to \cs\RenewDocumentCommand\ of the "xparse" package, \itemAP[\csintro{\DeclareDocumentCommandPIE}] is similar to \cs\DeclareDocumentCommand\ of the "xparse" package, \itemAP[\csintro{\ProvideDocumentCommandPIE}] is similar to \cs\ProvideDocumentCommand\ of the "xparse" package. \end{commandlist} Finally, a bunch of macros are used to define "math variants" that are "PIE commands": \begin{commandlist} \itemAP[\csintro{\newmathcommandPIE}] is like \cs{\newcommandPIE} and creates a "math variant", \itemAP[\csintro{\renewmathcommandPIE}] is like \cs{\renewcommandPIE} and creates a "math variant", \itemAP[\csintro{\declaremathcommandPIE}] is like \cs{\declarecommandPIE} and creates a "math variant", \itemAP[\csintro{\NewDocumentMathCommandPIE}] is like \cs{\NewDocumentCommandPIE}, but creates a "math variant", \itemAP[\csintro{\RenewDocumentMathCommandPIE}] is like \cs{\RenewDocumentCommandPIE}, but creates a "math variant", \itemAP[\csintro{\DeclareDocumentMathCommandPIE}] is like \cs{\DeclareDocumentCommandPIE}, but creates a "math variant", \itemAP[\csintro{\ProvideDocumentMathCommandPIE}] is like \cs{\ProvideDocumentCommandPIE}, but creates a "math variant", \end{commandlist} \section{Looping for defining commands} \begin{scope}\label{LoopCommands} \knowledge{list on which to iterate}{doc notion} \knowledge{name 1}{doc notion} \knowledge{name 2}{doc notion} \knowledge{name 7}{doc notion} \knowledge{code}{doc notion} The "mathcommand" package offer also some capabilities for automatically defining multiple similar macros. This is done using only one command:\AP \begin{center} \csintro{\LoopCommands}\{"list on which to iterate"\}["name 1"]["name 2"]\dots["name 7"]\{"code@@LoopCommands"\} \end{center} \AP The ""list on which to iterate"" is a list of letters or braced sequences of letters. \AP the ""name 1"", ""name 2"" up to ""name 7"" optional parameters are expandable pieces of code that are to be evaluated and then converted into control sequences; they may use the extra parameter~\texttt{\#1}. \AP Finally, ""code"" is the code to be executed that can use the parameters~\texttt{\#1}, \texttt{\#2}, up to~\texttt{\#8}. The result of executing this macro is that each of the letters or sequences of letters in the "list on which to iterate" will be taken one after the other. For each of them, the "code" is executed, taking as value of the parameter~\texttt{\#1} the element in the list, and as parameters~\texttt{\#2} to~\texttt{\#8} control sequences constructed from the evaluation of "name 1" up to "name 7" (using as parameters~\texttt{\#1} the element of the sequence). For instance, imagine one easily wants to denote vectors simply as `\cs\vx' instead of `\cs\vec~x' or `\cs\vec\{x\}', it is sufficient to write: \begin{code}[9cm] \cs\LoopCommands\{abcdefghijklmnopqrstuvwxyz\}[v\#1]\\ \indent~~~~\{\cs\newcommand\#2\{\cs\vec~\#1\}\} \end{code} \noindent It will result in the successive execution of \smallcode{\cs\newcommand\cs\va\{\cs\vec~a\}} and so on up to \smallcode{\cs\newcommand\cs\vz\{\cs\vec~z\}}. Note also that the "list on which to iterate" is automatically expanded, and if a non-expandable control sequence is met, then it is replaced by its the text defining the control sequence. Hence using \texttt{\{\cs\alpha\cs\beta\}} is equivalent to \texttt{\{\{alpha\}\{beta\}\}}. Some extra remarks may be helpful: \begin{itemize} \item As usual in \TeX/\LaTeX, the "code" may have to use its own internal parameters, for instance for defining macros: such parameters should use double \texttt{\#}'s, i.e., \texttt{\#\#1}, \texttt{\#\#2} up to \texttt{\#\#9}. \LoopCommands{abcdefghijklmnopqrstuvwxyz}[o#1] {\declarecommandPIE#2{\overline{#1##2}##1##3}} For instance: \begin{code}[10cm] \cs\LoopCommands\{abcdefghijklmnopqrstuvwxyz\}[o\#1]\\ \indent~~~~\{\cs\declarecommandPIE\#2\{\cs\overline\{\#1\#\#2\}\#\#1\#\#3\} \end{code} \noindent will result in \cs\ou\ to be declared as the "PIE command" defined with as main body \texttt{\cs\overline\{u\#2\}\#1\#3} (note the translation of parameters, which is the standard way to proceed for \TeX). In our case {\tt \cs\ou\_1\verb.^.2} yields `$\ou_1^2$' (the subscript gets to be inside the bar, and the superscript and primes outside), and so on... \item When defining multiple commands, some may already exist. To avoid conflicts, one should use the `declare' version of the defining commands. These will work independently of the context. Is it also good to define only the "math variants" using the appropriate commands of the package. \itemAP The following strings are predefined for the user to loop on: \begin{asparaitem} \itemAP[\csintro\lettersUppercase] stands for \texttt{\lettersUppercase} \itemAP[\csintro\lettersLowercase] stands for \texttt{\lettersLowercase} \itemAP[\csintro\lettersAll] stands for \texttt{\lettersAll}. \itemAP[\csintro\lettersGreekLowercase] stands for $\lettersGreekLowercase$. \itemAP[\csintro\lettersGreekUppercase] stands for $\lettersGreekUppercase$. \itemAP[\csintro\lettersGreekAll] stands for $\lettersGreekAll$. \end{asparaitem} \end{itemize} \end{scope} Hence, for instance: \begin{code}[10cm] \cs\LoopCommands\cs\lettersUppercase[bb\#1]\\ \indent~~~~~~\{\cs\newmathcommand\#2\{\cs\mathbb \#1\}\}\\ \cs\LoopCommands\cs\lettersGreekLowercase[\#1][LaTeX\#1]\\ \indent~~~~~~\{\cs\renewmathcommand\#2\{\cs\textcolor\{blue\}\{\#3\}\} \end{code} \noindent configures the macros \cs\bbA, \dots, \cs\bbZ\ to display the letters in blackboard bold alphabet (e.g. with the "amsfonts" package), and the lowercase greek letters \cs\alpha,\dots\ to be displayed in blue (with the "xcolor" package loaded). Note in the last case the use of the third parameter for accessing the macros \cs\LaTeXalpha,\dots\ that are automatically generated by the \cs\renewmathcommand\ macro. \section{Disabling command} The package "mathcommand" has some facilities for deactivating commands, and suggesting replacements. This can be useful when working with coauthors and help them using the same macros. "Disabling" a command is achieved using \AP \begin{center} \csintro{\disablecommand}\{sequence of control sequences\} \end{center} The result of this command is that the control sequences appearing in the sequence are "deactivated". \AP ""Deactivating"" a macro~\cs\macro\ means that: \begin{itemize} \item The original macro is stored as \cs\LaTeXmacro, and thus can still be used. \item Using \cs\macro\ now displays an error message explaining that it has been disabled, that~\cs\LaTeXmacro\ can be used instead, and also provides a list suggestions of replacement that are defined by the command \cs\suggestcommand. \end{itemize} However, be careful: disabling a command which is used in the system or in the the style may cause problems. Hence, it is possible to disable all math symbols but macros like \cs\dagger\ would yield problem if used in footnotes or for the affiliation of the authors. \AP The syntax of~\cs\suggestcommand\ is as follows: \begin{center} \csintro{\suggestcommand}\cs\macro\{suggestion to be displayed when~\cs\macro\ is used\} \end{center} For instance: \begin{code}%[10cm] \cs\disablecommand\{\cs\leq\cs\geq\}\\ \cs\suggestcommand\{\cs\leq\}\{Use the better looking \cs\leqslant.\}\\ \cs\suggestcommand\{\cs\geq\}\{Use the better looking \cs\geqslant.\} \end{code} Now, executing \cs\leq\ yields: \begin{verbatim} ./filename.tex:linenumber: Package mathcommand Error: (mathcommand) The command \geq is disabled. Instead: (mathcommand) Use \LaTeXgeq for the original macro. (mathcommand) Use the better looking \geqslant . \end{verbatim} \section{Options} \AP Options can be triggered either when the package is loaded, or using: \begin{center} \csintro\mathcommandconfigure\{option list\} \end{center} The available options are: \begin{itemize} \item ""disabled=error"" makes "disabled" commands produce errors, \item ""disabled=warning"" makes "disabled" commands produce warnings, \item ""disabled=silent"" makes "disabled" commands work as before being disabled (useful when including code that cannot be modified). \end{itemize} \newpage \DocInput{mathcommand.dtx} \end{document} % % \fi % % % %%%%%%%%%% % % \section{Implementation} % \label{section:code} % % \subsection{README.md} % %<*readme> % \begin{macrocode} This directory contains the package name: mathcommand license: LaTeX Project Public License version 1.3 or above version: v1.04 date: 2021/06/07 author: Thomas Colcombet mail: thomas.colcombet@irif.fr web: https://www.ctan.org/pkg/mathcommand Purpose: The mathcommand package provides functionalities for defining macros: - that have different behaviors depending on whether in math or text mode, - absorb Primes, Indices, Exponents (PIE) following LaTeX notations and have them as extra parameters usable in the code. The primary objective of this code is to be used together with the knowledge package for a proper handling of mathematical notations. Install: It is sufficient to have the file mathcommand.sty accessible by LaTeX. It can be produced by `make mathcommand.sty' if necessary. The documentation is in the file mathcommand.pdf. Content of the file mathcommand-ctan.zip: - README.md: this file generated while compiling mathcommand.ins, - mathcommand.sty: the package file (generated using mathcommand.ins) - mathcommand.pdf: the user documentation (generated by compiling mathcommand.dtx) - makefile: the makefile. Use 'make all' to generate mathcommand.sty and mathcommand.pdf. It can also: clean the directory, make zip version of the sources, or ready for CTAN. - mathcommand.ins: is the file generating mathcommand.sty and README.md from mathcommand.dtx (using docstrip). - mathcommand.dtx: code and documentation. % \end{macrocode} % % \subsection{Code preparation} %<*package> % \begin{macrocode} \NeedsTeXFormat{LaTeX2e}[1994/06/01] \RequirePackage{expl3,l3keys2e} \RequirePackage{etoolbox} \RequirePackage{xparse} \ExplSyntaxOn \bool_if_exist:NTF\mathcommand_package_loaded_bool \endinput {\bool_new:N\mathcommand_package_loaded_bool \bool_set_true:N\mathcommand_package_loaded_bool} % \end{macrocode} % \subsection{Absorbing primes, indices and exponents (PIE)} % \subsubsection{Parsing pies} % We start by defining the code used to absorb "PIEs" from the input stream. % The main function defined in this context is % \begin{quote}\AP % \csintro{\__mathcommand_absorb_PIE:nw} % \end{quote} % which takes some code as first parameter, then absorbs primes, indices and exponents, % and finally reinserts the code in the input stream, followed with three braces containing % respectively the primes, the index, and the exponent. % % \AP % It works by storing the code to be executed in \csintro{\__mathcommand_absorb_finished_tl}, % preparing \csintro{\__mathcommand_primes_tl}, \csintro{\__mathcommand_index_t}, % and \csintro{\__mathcommand_exponent_tl} to contain the "PIEs". % Then the core of the parsing is performed by \csintro{\__mathcommand_absorb:w}. % \begin{macrocode} \cs_new:Npn\__mathcommand_absorb_PIE:nw#1{ \tl_set:Nn\__mathcommand_absorb_finished_tl{#1} \tl_set:Nn\__mathcommand_primes_tl{} \tl_set:Nn\__mathcommand_index_tl{} \tl_set:Nn\__mathcommand_exponent_tl{} \__mathcommand_absorb:w } % \end{macrocode} % \AP % When the parsing is finished, \csintro{\__mathcommand_absorb_finished:} is % executed, which inserts the original code stored in \cs{\__mathcommand_absorb_finished_tl} % followed by the "PIEs" in the input stream. % \begin{macrocode} \cs_new:Nn\__mathcommand_absorb_finished:{ \exp_args:NV\__mathcommand_absorb_finished_:\__mathcommand_exponent_tl } \cs_new:Nn\__mathcommand_absorb_finished_:{ \exp_args:NV\__mathcommand_absorb_finished__:\__mathcommand_index_tl } \cs_new:Nn\__mathcommand_absorb_finished__:{ \exp_args:NV\__mathcommand_absorb_finished_tl\__mathcommand_primes_tl } % \end{macrocode} % \begin{macrocode} \cs_new:Npn\peek_subscript_remove:TFw {\peek_charcode_remove:NTF _} \cs_new:Npn\peek_superscript_remove:TFw {\peek_charcode_remove:NTF ^} \cs_new:Npn\peek_prime_remove:TFw {\peek_charcode_remove:NTF '} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_absorb_add_prime:{ \tl_put_right:Nn\__mathcommand_primes_tl{'} } % \end{macrocode} % \begin{macrocode} \ExplSyntaxOff \expandafter\def\csname g_tmpa_tl\endcsname{_} \ExplSyntaxOn \cs_new:Nx\__mathcommand_absorb_add_index_after:Nn{ \exp_not:N\tl_set:Nn\exp_not:N\__mathcommand_index_tl {\g_tmpa_tl{#2}} #1 } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_absorb_add_exponent_after:Nn{ \tl_set:Nn\__mathcommand_exponent_tl{^{#2}} #1 } % \end{macrocode} % \begin{macrocode} \cs_new:Npn\__mathcommand_absorb:w{ \peek_prime_remove:TFw {\__mathcommand_absorb_add_prime: \__mathcommand_absorb_p:w} \__mathcommand_absorb_:w} \cs_new:Npn\__mathcommand_absorb_:w{ \peek_subscript_remove:TFw {\__mathcommand_absorb_add_index_after:Nn \__mathcommand_absorb_i:w} \__mathcommand_absorb__:w} \cs_new:Npn\__mathcommand_absorb__:w{ \peek_superscript_remove:TFw {\__mathcommand_absorb_add_exponent_after:Nn \__mathcommand_absorb_e:w} \__mathcommand_absorb_finished:} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\__mathcommand_absorb_p:w{ \peek_prime_remove:TFw {\__mathcommand_absorb_add_prime: \__mathcommand_absorb_p:w} \__mathcommand_absorb_p_:w} \cs_new:Npn\__mathcommand_absorb_p_:w{ \peek_subscript_remove:TFw {\__mathcommand_absorb_add_index_after:Nn \__mathcommand_absorb_pi:w} \__mathcommand_absorb_finished:} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\__mathcommand_absorb_pi:w{ \peek_prime_remove:TFw {\__mathcommand_absorb_add_prime: \__mathcommand_absorb_pi:w} \__mathcommand_absorb_finished:} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\__mathcommand_absorb_e:w{ \peek_subscript_remove:TFw {\__mathcommand_absorb_add_index_after:Nn \__mathcommand_absorb_finished:} \__mathcommand_absorb_finished:} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\__mathcommand_absorb_i:w{ \peek_prime_remove:TFw {\__mathcommand_absorb_add_prime: \__mathcommand_absorb_pi:w} \__mathcommand_absorb_i_:w} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\__mathcommand_absorb_i_:w{ \peek_superscript_remove:TFw {\__mathcommand_absorb_add_exponent_after:Nn \__mathcommand_absorb_finished:} \__mathcommand_absorb_finished:} % \end{macrocode} % %\subsubsection{Definition of high level commands} % % \begin{macrocode} \NewDocumentCommand\newcommandPIE{ m o o m }{ \__mathcommand_check_definable:nNT {#1} \newcommandPIE { \cs_if_exist:NTF #1 { \__kernel_msg_error:nnxx { mathcommand } { command-already-defined } { \use:nnn \token_to_str:N #1 { } } { \token_to_str:N \newcommandPIE } } { \__mathcommand_declarecommandPIE:Nnnn #1{#2}{#3}{#4} } } } \NewDocumentCommand\renewcommandPIE{ m o o m }{ \__mathcommand_check_definable:nNT {#1} \renewcommandPIE { \cs_if_exist:NTF #1 { \__mathcommand_declarecommandPIE:Nnnn #1{#2}{#3}{#4} } { \__kernel_msg_error:nnxx { mathcommand } { command-not-yet-defined } { \use:nnn \token_to_str:N #1 { } } { \token_to_str:N \renewcommandPIE } } } } \NewDocumentCommand\declarecommandPIE{ m o o m }{ \__mathcommand_check_definable:nNT {#1} \declarecommandPIE { \__mathcommand_declarecommandPIE:Nnnn #1{#2}{#3}{#4} } } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_declarecommandPIE:Nnnn{ \use:x{ \exp_not:N\__mathcommand_declarePIE_generic:Nnnn \exp_not:N#1 {\IfNoValueTF{#2}{0}{#2}} {\cs_if_exist:NTF#1 {\exp_not:N\renewrobustcmd} {\exp_not:N\newrobustcmd} \exp_not:N#1 \IfNoValueTF{#2}{}{[#2]} \IfNoValueTF{#3}{}{[{\exp_not:n{#3}}]}} {\exp_not:n{#4}} }} % \end{macrocode} % \begin{macrocode} \cs_new_protected:Npn\NewDocumentCommandPIE#1#2#3{ \__mathcommand_check_definable:nNT {#1} \NewDocumentCommandPIE { \cs_if_exist:NTF #1 { \__kernel_msg_error:nnxx { mathcommand } { command-already-defined } { \use:nnn \token_to_str:N #1 { } } { \token_to_str:N \NewDocumentCommandPIE } } { \__mathcommand_DeclareDocumentCommandPIE:Nnn #1 {#2} {#3} } } } % \end{macrocode} % \begin{macrocode} \cs_new_protected:Npn\RenewDocumentCommandPIE#1#2#3{ \__mathcommand_check_definable:nNT {#1} \RenewDocumentCommandPIE { \cs_if_exist:NTF #1 { \__mathcommand_DeclareDocumentCommandPIE:Nnn #1 {#2} {#3} } { \__kernel_msg_error:nnxx { mathcommand } { command-not-yet-defined } { \use:nnn \token_to_str:N #1 { } } { \token_to_str:N \RenewDocumentCommandPIE } } } } % \end{macrocode} % \begin{macrocode} \cs_new_protected:Npn\DeclareDocumentCommandPIE#1#2#3{ \__mathcommand_check_definable:nNT {#1} \DeclareDocumentCommandPIE { \__mathcommand_DeclareDocumentCommandPIE:Nnn #1 {#2} {#3} } } % \end{macrocode} % \begin{macrocode} \cs_new_protected:Npn\ProvideDocumentCommandPIE#1#2#3{ \__mathcommand_check_definable:nNT {#1} \ProvideDocumentCommandPIE { \cs_if_exist:NTF #1{} { \__mathcommand_DeclareDocumentCommandPIE:Nnn #1 {#2} {#3} } } } % \end{macrocode} % \begin{macrocode} \cs_set:Nn\__mathcommand_DeclareDocumentCommandPIE:Nnn{ \group_begin: \DeclareDocumentCommand#1{#2}{} \int_gset_eq:NN\g_tmpa_int\l__xparse_current_arg_int \group_end: \__mathcommand_declarePIE_generic:Nnnn #1 {\g_tmpa_int} {\DeclareDocumentCommand#1{#2}} {#3} } % \end{macrocode} % Control token, number parameters, defining command, code % \begin{macrocode} \cs_new:Nn\__mathcommand_declarePIE_generic:Nnnn{ \int_compare:nNnTF{#2}>{6} {\PackageError{mathcommand} {At~most~6~parameters~in~PIE~commands~when~defining~`\token_to_str:N#1'} {PIE~commands~(mathcommand~package)~do~not~accept~more~than~six~parameters.}} {\int_case:nn{#2} {{0} {\cs_set:cpn{\cs_to_str:N#1~PIE~code}##1##2##3} {1} {\cs_set:cpn{\cs_to_str:N#1~PIE~code}##1##2##3##4} {2} {\cs_set:cpn{\cs_to_str:N#1~PIE~code}##1##2##3##4##5} {3} {\cs_set:cpn{\cs_to_str:N#1~PIE~code}##1##2##3##4##5##6} {4} {\cs_set:cpn{\cs_to_str:N#1~PIE~code}##1##2##3##4##5##6##7} {5} {\cs_set:cpn{\cs_to_str:N#1~PIE~code}##1##2##3##4##5##6##7##8} {6} {\cs_set:cpn{\cs_to_str:N#1~PIE~code}##1##2##3##4##5##6##7##8##9}} {#4} \use:x{ \exp_not:n{#3} {\exp_not:N\__mathcommand_absorb_PIE:nw {\exp_not:c{\cs_to_str:N#1~PIE~code} \int_case:nn{#2} {{0}{} {1}{\exp_not:n{{##1}}} {2}{\exp_not:n{{##1}{##2}}} {3}{\exp_not:n{{##1}{##2}{##3}}} {4}{\exp_not:n{{##1}{##2}{##3}{##4}}} {5}{\exp_not:n{{##1}{##2}{##3}{##4}{##5}}} {6}{\exp_not:n{{##1}{##2}{##3}{##4}{##5}{##6}}}}}}} } } % \end{macrocode} % % % \subsubsection{Auxiliary functions} % % % \begin{macrocode} \def\lettersUppercase{ABCDEFGHIJKLMNOPQRSTUVWXYZ} \def\lettersLowercase{abcdefghijklmnopqrstuvwxyz} \xdef\lettersAll{\lettersLowercase\lettersUppercase} \def\lettersGreekLowercase{\alpha\beta\gamma\delta\epsilon\varepsilon\zeta\eta\theta\vartheta\iota\kappa\lambda\mu\nu\xi\pi\varpi\rho\varrho\sigma\varsigma\tau\upsilon\phi\varphi\chi\psi\omega} \def\lettersGreekUppercase{\Gamma\Delta\Theta\Lambda\Xi\Pi\Sigma\Upsilon\Phi\Psi\Omega} \xdef\lettersGreekAll{\lettersGreekLowercase\lettersGreekUppercase} % \end{macrocode} % % \begin{macrocode} \cs_set_eq:NN\IfEmptyTF\tl_if_empty:nTF % \end{macrocode} % \begin{macrocode} \cs_new:Npn\EmptyContent#1{ \tl_if_empty:nTF{#1}{{}}{ \__mathcommand_EmptyContent:w #1*\end_marker: } } \cs_new:Npn\__mathcommand_EmptyContent:w #1#2\end_marker:{ #1* } % \end{macrocode} % \begin{macrocode} \cs_new:Npn\GetExponent#1{ \tl_if_empty:nTF{#1}{}{ \__mathcommand_GetIndexOrExponent:w #1\__end_marker__ } } \cs_new:Npn\GetIndex#1{ \tl_if_empty:nTF{#1}{}{ \__mathcommand_GetIndexOrExponent:w #1\__end_marker__ } } \cs_new:Npn\__mathcommand_GetIndexOrExponent:w #1#2#3\__end_marker__{ #2 } % \end{macrocode} % % % \subsection{Separating math and text macros} % % % \begin{macrocode} \tl_const:Nn\__mathcommand_prefix_math_tl{Math~} \tl_const:Nn\__mathcommand_prefix_text_tl{Text~} \tl_const:Nn\__mathcommand_prefix_store_tl{LaTeX} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_to_mathtl:N{\__mathcommand_prefix_math_tl\cs_to_str:N#1} \cs_new:Nn\__mathcommand_to_texttl:N{\__mathcommand_prefix_text_tl\cs_to_str:N#1} \cs_new:Nn\__mathcommand_to_storetl:N{\__mathcommand_prefix_store_tl\cs_to_str:N#1} \cs_new:Nn\__mathcommand_coretl:N {\expandafter\__command_coretl:w\string#1\end_mark} \cs_new:Npn\__command_coretl:w#1~#2\end_mark{#2} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\__mathcommand_if_exist:NTF {\cs_if_exist:NTF} \cs_new:Npn\__mathcommand_if_exist_math:NTF#1 {\cs_if_exist:cTF{\__mathcommand_to_mathtl:N#1}} \cs_new:Npn\__mathcommand_if_exist_text:NTF#1 {\cs_if_exist:cTF{\__mathcommand_to_texttl:N#1}} \cs_new:Npn\__mathcommand_if_exist_text_or_math:NTF#1 {\__mathcommand_if_exist_math:NTF#1 \use_i:nn{\__mathcommand_if_exist_text:NTF#1}} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_error_if_exist_math:NF{ \cs_if_exist:cTF{\__mathcommand_to_mathtl:N#1} {\exp_args:Nnx\PackageError{} {Command~`\token_to_str:N#1'~already~exists~in~math~mode} {} }{#2} } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_error_if_exist_text:NF{ \cs_if_exist:cTF{\__mathcommand_to_texttl:N#1} {\exp_args:Nnx\PackageError{} {Command~`\token_to_str:N#1'~already~exists~in~text~mode} {} }{#2} } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_error_if_not_exist_math:NF{ \cs_if_exist:cTF{\__mathcommand_to_mathtl:N#1} {#2} {\exp_args:Nnx\PackageError{} {Command~`\token_to_str:N#1'~does~not~exist~in~math~mode} {} } } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_error_if_not_exist_text:NF{ \cs_if_exist:cTF{\__mathcommand_to_texttl:N#1} {#2} {\exp_args:Nnx\PackageError{} {Command~`\token_to_str:N#1'~does~not~exist~in~text~mode} {} } } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_error_unknownmath:N{ \exp_args:Nnx\PackageError{} {Command~`\token_to_str:c{\__mathcommand_coretl:N #1}'~does~not~exist~in~math~mode} {} } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_error_unknowntext:N{ \exp_args:Nnx\PackageError{} {Command~`\token_to_str:c{\__mathcommand_coretl:N #1}'~does~not~exist~in~text~mode} {} } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_try_math:N{ \cs_if_exist:NTF#1#1{\__mathcommand_error_unknownmath:N#1} } \cs_new:Nn\__mathcommand_try_text:N{ \cs_if_exist:NTF#1#1{\__mathcommand_error_unknowntext:N#1} } % \end{macrocode} % \AP % The macro \csintro{\__mathcommand_create_fork:N} takes a control sequence, % and creates the forking code that executes either the math branch of the text branch. % If this forking code is already present, the command does nothing. % However, if some macro was already associated with this control sequence, then % it is copied to the "math variant", the "text variant" as well as the stored. % \begin{macrocode} \cs_set:Nn\__mathcommand_create_fork:N{ \let\__mathcommand_tmp_cs\undefined \exp_args:NNx \cs_new_protected:Npn\__mathcommand_tmp_cs{ \exp_not:N\mode_if_math:TF {\exp_not:N\__mathcommand_try_math:N\exp_not:c{\__mathcommand_to_mathtl:N#1}} {\exp_not:N\__mathcommand_try_text:N\exp_not:c{\__mathcommand_to_texttl:N#1}} } \cs_if_exist:NTF#1{ \cs_if_eq:NNTF#1\__mathcommand_tmp_cs { } { \cs_set_eq:cN{\__mathcommand_to_storetl:N#1}#1 \cs_set_eq:cN{\__mathcommand_to_mathtl:N#1}#1 \cs_set_eq:cN{\__mathcommand_to_texttl:N#1}#1 \cs_set_eq:NN#1\__mathcommand_tmp_cs } }{ \cs_set_eq:NN#1\__mathcommand_tmp_cs } } % \end{macrocode} % \subsection{Definition of the high level commands} % \begin{macrocode} \NewDocumentCommand\declarecommand{m}{ \__mathcommand_check_definable:nNT {#1} \declarecommand { \cs_if_exist:NTF#1 {\renewcommand#1} {\newcommand#1} } } \newrobustcmd\storecommand[2][\__mathcommand_prefix_store_tl]{ \__mathcommand_check_definable:nNT {#2} \storecommand { \cs_if_exist:NTF#2{ \cs_set_eq:cN{#1\cs_to_str:N#2}#2 } { \PackageError{mathcommand} {The~command~`\token_to_str:N#2'~does~not~exist~(in~\token_to_str:N\storecommand)} {} } } } \NewDocumentCommand\NewDocumentMathCommand{m}{ \__mathcommand_check_definable:nNT {#1} \NewDocumentMathCommand { \__mathcommand_create_fork:N#1 \__mathcommand_error_if_exist_math:NF#1 {\exp_args:Nc\DeclareDocumentCommand{\__mathcommand_to_mathtl:N#1}} } } \NewDocumentCommand\NewDocumentTextCommand{m}{ \__mathcommand_check_definable:nNT {#1} \NewDocumentTextCommand { \__mathcommand_create_fork:N#1 \__mathcommand_error_if_exist_text:NF#1 {\exp_args:Nc\DeclareDocumentCommand{\__mathcommand_to_texttl:N#1}} } } \NewDocumentCommand\newmathcommand{m}{ \__mathcommand_check_definable:nNT {#1} \newmathcommand { \__mathcommand_create_fork:N#1 \__mathcommand_error_if_exist_math:NF#1 {\exp_args:Nc\newcommand{\__mathcommand_to_mathtl:N#1}} } } \NewDocumentCommand\newtextcommand{m}{ \__mathcommand_check_definable:nNT {#1} \newtextcommand { \__mathcommand_create_fork:N#1 \__mathcommand_error_if_exist_text:NF#1 {\exp_args:Nc\newcommand{\__mathcommand_to_texttl:N#1}} } } \NewDocumentCommand\RenewDocumentMathCommand{m}{ \__mathcommand_check_definable:nNT {#1} \RenewDocumentMathCommand { \__mathcommand_create_fork:N#1 \__mathcommand_error_if_not_exist_math:NF#1 {\exp_args:Nc\DeclareDocumentCommand{\__mathcommand_to_mathtl:N#1}} } } \NewDocumentCommand\RenewDocumentTextCommand{m}{ \__mathcommand_check_definable:nNT {#1} \RenewDocumentMathCommand { \__mathcommand_create_fork:N#1 \__mathcommand_error_if_not_exist_text:NF#1 {\exp_args:Nc\DeclareDocumentCommand{\__mathcommand_to_texttl:N#1}} } } \NewDocumentCommand\renewmathcommand{m}{ \__mathcommand_check_definable:nNT {#1} \renewmathcommand { \__mathcommand_create_fork:N#1 \__mathcommand_error_if_not_exist_math:NF#1 {\exp_args:Nc\renewcommand{\__mathcommand_to_mathtl:N#1}} } } \NewDocumentCommand\renewtextcommand{m}{ \__mathcommand_check_definable:nNT {#1} \renewtextcommand { \__mathcommand_create_fork:N#1 \__mathcommand_error_if_not_exist_text:NF#1 {\exp_args:Nc\renewcommand{\__mathcommand_to_texttl:N#1}} } } \NewDocumentCommand\declaremathcommand{m}{ \__mathcommand_check_definable:nNT {#1} \renewmathcommand { \__mathcommand_create_fork:N#1 \exp_args:Nc\declarecommand{\__mathcommand_to_mathtl:N#1} } } \NewDocumentCommand\declaretextcommand{m}{ \__mathcommand_check_definable:nNT {#1} \renewtextcommand { \__mathcommand_create_fork:N#1 \exp_args:Nc\declarecommand{\__mathcommand_to_texttl:N#1} } } \NewDocumentCommand\DeclareDocumentMathCommand{m}{ \__mathcommand_check_definable:nNT {#1} \DeclareDocumentMathCommand { \__mathcommand_create_fork:N#1 \exp_args:Nc\DeclareDocumentCommand{\__mathcommand_to_mathtl:N#1} } } \NewDocumentCommand\DeclareDocumentTextCommand{m}{ \__mathcommand_check_definable:nNT {#1} \DeclareDocumentTextCommand { \__mathcommand_create_fork:N#1 \exp_args:Nc\DeclareDocumentCommand{\__mathcommand_to_texttl:N#1} } } \NewDocumentCommand\ProvideDocumentMathCommand{mmm}{ \__mathcommand_check_definable:nNT {#1} \ProvideDocumentMathCommand { \__mathcommand_create_fork:N#1 \exp_args:Nc\ProvideDocumentCommand{\__mathcommand_to_mathtl:N#1}{#2}{#3} } } \NewDocumentCommand\ProvideDocumentTextCommand{m}{ \__mathcommand_check_definable:nNT {#1} \ProvideDocumentTextCommand { \__mathcommand_create_fork:N#1 \exp_args:Nc\ProvideDocumentCommand{\__mathcommand_to_texttl:N#1} } } % \end{macrocode} % % \subsection{Definition of the high level combined commands} % % \begin{macrocode} \NewDocumentCommand\NewDocumentMathCommandPIE{m}{ \__mathcommand_check_definable:nNT {#1} \NewDocumentMathCommandPIE { \__mathcommand_create_fork:N#1 \__mathcommand_error_if_exist_math:NF#1 {\exp_args:Nc\DeclareDocumentCommandPIE{\__mathcommand_to_mathtl:N#1}} } } \NewDocumentCommand\newmathcommandPIE{m}{ \__mathcommand_check_definable:nNT {#1} \newmathcommandPiE { \__mathcommand_create_fork:N#1 \__mathcommand_error_if_exist_math:NF#1 {\exp_args:Nc\newcommandPIE{\__mathcommand_to_mathtl:N#1}} } } \NewDocumentCommand\RenewDocumentMathCommandPIE{m}{ \__mathcommand_check_definable:nNT {#1} \RenewDocumentMathCommandPIE { \__mathcommand_create_fork:N#1 \__mathcommand_error_if_not_exist_math:NF#1 {\exp_args:Nc\DeclareDocumentCommandPIE{\__mathcommand_to_mathtl:N#1}} } } \NewDocumentCommand\renewmathcommandPIE{m}{ \__mathcommand_check_definable:nNT {#1} \renewmathcommandPIE { \__mathcommand_create_fork:N#1 \__mathcommand_error_if_not_exist_math:NF#1 {\exp_args:Nc\renewcommandPIE{\__mathcommand_to_mathtl:N#1}} } } \NewDocumentCommand\DeclareDocumentMathCommandPIE{m}{ \__mathcommand_check_definable:nNT {#1} \DeclareDocumentMathCommand { \__mathcommand_create_fork:N#1 \exp_args:Nc\DeclareDocumentCommand{\__mathcommand_to_mathtl:N#1} } } \NewDocumentCommand\declaremathcommandPIE{m}{ \__mathcommand_check_definable:nNT {#1} \declaremathcommandPIE { \__mathcommand_create_fork:N#1 \exp_args:Nc\declarecommandPIE{\__mathcommand_to_mathtl:N#1} } } \NewDocumentCommand\ProvideDocumentMathCommandPIE{mmm}{ \__mathcommand_check_definable:nNT {#1} \ProvideDocumentMathCommandPIE { \__mathcommand_create_fork:N#1 \exp_args:Nc\ProvideDocumentCommandPIE{\__mathcommand_to_mathtl:N#1}{#2}{#3} } } % \end{macrocode} % % \subsection{Looping for command definitions} % % % \begin{macrocode} \NewDocumentCommand\LoopCommands{ m ooooooo m }{ \IfNoValueTF{#2} {\cs_set:Nn\__tmp_two:n{\exp_not:c{##1}}} {\cs_set:Nn\__tmp_two:n{\exp_not:c{#2}}} \IfNoValueTF{#3} {\cs_set:Nn\__tmp_three:n{\exp_not:c{##1}}} {\cs_set:Nn\__tmp_three:n{\exp_not:c{#3}}} \IfNoValueTF{#4} {\cs_set:Nn\__tmp_four:n{\exp_not:c{##1}}} {\cs_set:Nn\__tmp_four:n{\exp_not:c{#4}}} \IfNoValueTF{#5} {\cs_set:Nn\__tmp_five:n{\exp_not:c{##1}}} {\cs_set:Nn\__tmp_five:n{\exp_not:c{#5}}} \IfNoValueTF{#6} {\cs_set:Nn\__tmp_six:n{\exp_not:c{##1}}} {\cs_set:Nn\__tmp_six:n{\exp_not:c{#6}}} \IfNoValueTF{#7} {\cs_set:Nn\__tmp_seven:n{\exp_not:c{##1}}} {\cs_set:Nn\__tmp_seven:n{\exp_not:c{#7}}} \IfNoValueTF{#8} {\cs_set:Nn\__tmp_eight:n{\exp_not:c{##1}}} {\cs_set:Nn\__tmp_eight:n{\exp_not:c{#8}}} % \cs_gset:Nn\g_tmpb_cs:nnnnnnnn{#9} % \cs_gset:Nn\g_tmpa_cs:n{ \tl_set:Nn\l_tmpa_tl{##1} \use:x{ \exp_not:N\g_tmpb_cs:nnnnnnnn {\l_tmpa_tl} \__tmp_two:n{\l_tmpa_tl} \__tmp_three:n{\l_tmpa_tl} \__tmp_four:n{\l_tmpa_tl} \__tmp_five:n{\l_tmpa_tl} \__tmp_six:n{\l_tmpa_tl} \__tmp_seven:n{\l_tmpa_tl} \__tmp_eight:n{\l_tmpa_tl}} } \exp_args:Nx\tl_map_inline:nn{#1} {\tl_if_blank:nTF{##1} {} {\g_tmpa_cs:n{\__mathcommand_getbasename:n{##1}}} } } \cs_new:Nn\__mathcommand_getbasename:n{ \tl_if_single:nTF{#1}{ \token_if_cs:NTF#1 {\cs_to_str:N#1} {#1} }{#1} } % \end{macrocode} % % \subsection{Deactivating macros} % % \begin{macrocode} \bool_new:N\__mathcommand_disabled_error_bool \bool_set_true:N\__mathcommand_disabled_error_bool \bool_new:N\__mathcommand_disabled_suggest_original_bool \bool_set_true:N\__mathcommand_disabled_suggest_original_bool \bool_new:N\__mathcommand_force_enabled_bool \bool_set_false:N\__mathcommand_force_enabled_bool % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_to_disabled_help_tl:N {mathcommand_disabled_help_\cs_to_str:N#1_tl} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__mathcommand_error:nn { \msg_new:nnn{mathcommand}{#1}{#2} \msg_error:nn{mathcommand}{#1} } \cs_new:Nn\__mathcommand_dc_error:n { \msg_new:nnn{mathcommand}{disabled~command}{#1} \msg_error:nn{mathcommand}{disabled~command} } \cs_new:Nn\__mathcommand_dc_warning:n { \msg_set:nnn{mathcommand}{disabled~command}{#1} \msg_warning:nn{mathcommand}{disabled~command} } \cs_new:Nn\mathcommand_disabled_error:N { \bool_if:NTF\__mathcommand_disabled_error_bool {\exp_args:Nx\__mathcommand_dc_error:n} {\exp_args:Nx\__mathcommand_dc_warning:n} {\exp_not:n{\\The~command~\string#1~is~disabled.~Instead:\\ } \bool_if:NT\__mathcommand_disabled_suggest_original_bool {Use~\exp_not:c{\__mathcommand_to_storetl:N#1} for~the~original~macro.} \exp_not:v{\__mathcommand_to_disabled_help_tl:N#1}} } % \end{macrocode} % \begin{macrocode} \msg_new:nnn{mathcommand}{unknown~command} {\\The~control~sequence~#1 is~not~defined \\Origin~macro:~#2} % \end{macrocode} % \begin{macrocode} \NewDocumentCommand\disablecommand{m}{ \tl_map_function:nN{#1}\mathcommand_disablecommand:N } \cs_new:Nn\mathcommand_disablecommand:N { \cs_if_exist:NTF#1{ \__mathcommand_check_definable:nNT#1\disablecommand {\tl_if_exist:cTF{\__mathcommand_to_disabled_help_tl:N#1} {} {\storecommand#1 \tl_new:c{\__mathcommand_to_disabled_help_tl:N#1} \renewcommand#1 {\bool_if:NF \__mathcommand_force_enabled_bool {\mathcommand_disabled_error:N#1} \use:c{\__mathcommand_to_storetl:N#1}}} } }{ \msg_error:nnnn{mathcommand}{unknown~command}{#1}{\disablecommand} } } % \end{macrocode} % \begin{macrocode} \NewDocumentCommand\suggestcommand{mm} { \cs_if_exist:NTF#1{ \cs_if_exist:cTF{\__mathcommand_to_disabled_help_tl:N#1}{ \tl_put_right:cx{\__mathcommand_to_disabled_help_tl:N#1}{\exp_not:N\\\tl_to_str:n{#2}} }{ \__mathcommand_error:nn{command~not~disabled} {\\\string\suggestcommand :~Command~#1~has~not~been~disabled.} } } { \__mathcommand_error:nn{unknown~command} {\\\string\suggestcommand :~Unknown~command~#1.} } } % \end{macrocode} % % \subsection{Options} % % \begin{macrocode} \keys_define:nn { mathcommand }{ disabled .multichoice:, disabled / silent .code:n = {\bool_set_true:N\__mathcommand_force_enabled_bool }, disabled / error .code:n = {\bool_set_false:N\__mathcommand_force_enabled_bool \bool_set_true:N\__mathcommand_disabled_error_bool}, disabled / warning .code:n = {\bool_set_false:N\__mathcommand_force_enabled_bool \bool_set_false:N\__mathcommand_disabled_error_bool}, } \ProcessKeysOptions { mathcommand } % Parses the option list \NewDocumentCommand\mathcommandconfigure{ m } {\keys_set:nn{ mathcommand}{ #1} } % \end{macrocode} % % \subsection{Testing control sequence for definition} % This part of the code is an import of a previous version of xparse (Frank Mittelbach, Chris Rowley, David Carlisle, The LaTeX Project). It is done in a very ugly hack: the code is copied and past, and \texttt{mathcommand} substituted to \texttt{xparse} wherever necessary. % \begin{macrocode} \cs_new_protected:Npn \__mathcommand_check_definable:nNT #1 { \tl_trim_spaces_apply:nN {#1} \__mathcommand_check_definable_aux:nN } \group_begin: \char_set_catcode_active:n { `? } \cs_new_protected:Npn \__mathcommand_check_definable_aux:nN #1#2 { \group_begin: \tl_if_single_token:nTF {#1} { \int_set:Nn \tex_escapechar:D { 92 } \exp_args:Nx \tl_if_empty:nTF { \exp_args:No \str_tail:n { \token_to_str:N #1 } } { \exp_args:Nx \char_set_lccode:nn { ` \str_head:n {#1} } { `? } \tex_lowercase:D { \tl_if_eq:nnTF {#1} } { ? } { \group_end: \use_iii:nnn } { \group_end: \use_i:nnn } } { \group_end: \use_iii:nnn } } { \group_end: \use_ii:nnn } { \__kernel_msg_error:nnxx { mathcommand } { not-definable } { \tl_to_str:n {#1} } { \token_to_str:N #2 } } { \__kernel_msg_error:nnxx { mathcommand } { not-one-token } { \tl_to_str:n {#1} } { \token_to_str:N #2 } } } \group_end: % \end{macrocode} % \subsection{Closure} % \begin{macrocode} \ExplSyntaxOff % \end{macrocode} % % \end{document}