在数学模式下通过宏激活字符

在数学模式下通过宏激活字符

我正在尝试使字符在数学模式下处于活动状态,但似乎无法通过最基本的示例。我想定义一个传递的宏:

  1. 使角色活跃和

  2. 一旦遇到该宏就应该执行的宏。

下面的 MNWE 尝试制作=+!激活并对其进行颜色编码。期望的输出是这些字符被着色数学模式因此,输入

a=+b $c=+4+d+3!$ e=+f

产量:

在此处输入图片描述

角色在哪里不是在数学模式之外改变(前导a=+b和尾随 e=+f)。

笔记:

  • 宏中有一个单独但相关的问题(因为它是在活动字符的上下文中)\MyPlus来检测二进制加法+与一元正数+。 也许这应该是一个单独的问题?

相关问题:

代码(不起作用):

\documentclass{article}
\usepackage{mathtools}
\usepackage{xparse}
\usepackage{xcolor}

\NewDocumentCommand{\MakeActiveChar}{%
    m% char to make active
    m% code to execute for this character
}{%
    \catcode`\#1=13\relax%
    \def#1{#2}%
}%

\let\OldEqual=
\newcommand*{\MyEqual}[1][green]{\mathrel{\textcolor{#1}{\OldEqual}}}%

\let\OldPlus+
\newcommand*{\MyPlus}[1][blue]{%
    %\catcode`\+=12% reset catcode so we can use it (not needed with \OldPlus?)
    %% Perhaps this if-then construct should be a separate question?
    %% if binary addition operator
        \mathbin{\textcolor{#1}{\OldPlus}}%
    %% if unary positive operator
    %%  \mathrel{\textcolor{red}{\OldPlus}}%
}%

\let\OldFactorial!
\newcommand*{\MyFactorial}{\textcolor{brown}{\OldFactorial}}%

\everymath{%
    \MakeActiveChar{=}{\MyEqual}%
    \MakeActiveChar{+}{\MyPlus}%
    \MakeActiveChar{!}{\MyFactorial}%
}%

\begin{document}
The ``math'' outside here is just to test that characters are active \emph{only} in math mode:

a=+b $c=+4+d+3!$ e=+f 
\end{document}

答案1

amsmath如果在定义主体中加载;则必须小心声明,\std{<char>}在需要旧含义的地方使用。

\documentclass{article}
\usepackage{amsmath}
\usepackage{xcolor,etoolbox}

\makeatletter
\newcommand{\DeclareMathActive}[2]{%
  % #1 is the character, #2 is the definition
  \expandafter\edef\csname keep@#1@code\endcsname{\mathchar\the\mathcode`#1 }
  \begingroup\lccode`~=`#1\relax
  \lowercase{\endgroup\def~}{#2}%
  \AtBeginDocument{\mathcode`#1="8000 }%
}

\newcommand{\std}[1]{\csname keep@#1@code\endcsname}
\patchcmd{\newmcodes@}{\mathcode`\-\relax}{\std@minuscode\relax}{}{\ddt}
\AtBeginDocument{\edef\std@minuscode{\the\mathcode`-}}
\makeatother


\DeclareMathActive{+}{\mathbin{\textcolor{blue}{\std{+}}}}
\DeclareMathActive{!}{\mathclose{\textcolor{brown}{\std{!}}}}
\DeclareMathActive{-}{\mathbin{\textcolor{red}{\hat{\std{-}}}}}

\begin{document}

a=+b $c=+4+d+3!-1$ e=+f

\end{document}

\let\OldPlus=+

在此处输入图片描述

对于 Unicode 引擎(xelatexlualatex),补丁必须以不同的方式完成。这是一个适用于所有引擎的版本。

\documentclass{article}
\usepackage{amsmath}
\usepackage{xcolor,etoolbox}
\usepackage{iftex}

\makeatletter
\newcommand{\DeclareMathActive}[2]{%
  % #1 is the character, #2 is the definition
  \expandafter\edef\csname keep@#1@code\endcsname{\mathchar\the\mathcode`#1 }
  \begingroup\lccode`~=`#1\relax
  \lowercase{\endgroup\def~}{#2}%
  \AtBeginDocument{\mathcode`#1="8000 }%
}

\newcommand{\std}[1]{\csname keep@#1@code\endcsname}
\iftutex
  \patchcmd{\newmcodes@}{\Umathcodenum `\-\relax}{\std@minuscode\relax}{}{\ddt}
\else
  \patchcmd{\newmcodes@}{\mathcode`\-\relax}{\std@minuscode\relax}{}{\ddt}
\fi
\AtBeginDocument{\edef\std@minuscode{\the\mathcode`-}}
\makeatother


\DeclareMathActive{+}{\mathbin{\textcolor{blue}{\std{+}}}}
\DeclareMathActive{!}{\mathclose{\textcolor{brown}{\std{!}}}}
\DeclareMathActive{-}{\mathbin{\textcolor{red}{\hat{\std{-}}}}}

\begin{document}

a=+b $c=+4+d+3!-1$ e=+f

\end{document}

答案2

您可以定义\mathdef声明符然后使用它:

\input opmac \localcolor

\def\mathdef#1{\mathcode`#1="8000 \bgroup \lccode`~=`#1\lowercase{\egroup\def~}}

\mathdef +{\mathbin{\Red\mathchar`+}}
\mathdef ={\mathrel{\Green\mathchar`=}}

aha + $a+b+c=d$

\bye

这里\input opmac仅用于设置颜色等\Red\Green如果您使用另一个宏来设置颜色,那么只需使用\def\mathdef...宏中的第二行。

答案3

有几个问题:

\MakeActiveChar这样做\def#1{#2}是不允许的,因为#1是非活动字符。下面是另一种方法诀窍\lowercase

\NewDocumentCommand\MakeActiveChar{mm}
  {\begingroup\lccode`\~=`#1\lowercase{\endgroup\def~}{#2}%
   \catcode`#1=12 \mathcode`#1="8000 }

除此之外,你还缺少=一个\let。第一个等号是可选的,所以\let\a=\b是正确的,但是,当你想让 to 时,等号是必需的,=因为如果不是,它将被视为可选的,所以

\let\originalequal=

应该

\let\originalequal==

最后一部分是通过在数学模式下激活一个字符,然后执行时\newcommand\plus{\mathbin{\originalplus}}您会得到一个类似的无限循环\def\a{\a},因此您需要使用例如\mathchar`\+\mathchar`+来代替。

完整的解决方案

\documentclass{article}
\usepackage{mathtools}
\usepackage{xparse}
\usepackage{xcolor}

\NewDocumentCommand\MakeActiveChar{mm}
  {\begingroup\lccode`\~=`#1\lowercase{\endgroup\def~}{#2}%
   \catcode`#1=12 \mathcode`#1="8000 }

\newcommand*\mathcolor[2]{\begingroup\color{#1}#2\endgroup}

\newcommand*\equal[1][green]{\mathrel{\mathcolor{#1}{\mathchar`\=}}}
\newcommand*\plus[1][blue]{\mathbin{\mathcolor{#1}{\mathchar`\+}}}
\newcommand*\factorial{\mathord{\mathcolor{brown}{\mathchar`\!}}}

\everymath{%
  \MakeActiveChar{=}{\equal}%
  \MakeActiveChar{+}{\plus}%
  \MakeActiveChar{!}{\factorial}%
}

\begin{document}
The ``math'' outside here is just to test that characters are active \emph{only} in math mode:

a=+b $c=+4+d+3!$ e=+f 
\end{document}

顺便说一下,我定义是\mathcolor因为与/一起\textcolor工作创建一个\bgroup\egroup订单原子。

相关内容