我正在尝试使字符在数学模式下处于活动状态,但似乎无法通过最基本的示例。我想定义一个传递的宏:
使角色活跃和
一旦遇到该宏就应该执行的宏。
下面的 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 引擎(xelatex
或lualatex
),补丁必须以不同的方式完成。这是一个适用于所有引擎的版本。
\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
订单原子。