我想重新&
定义命令我尝试去适应这^
在环境中重新定义但无法使其工作的代码。
\documentclass[]{article}
\begin{document}
\newcommand{\myampersand}{?}
% https://tex.stackexchange.com/a/392770/82912
\begingroup%
\catcode`&=\active%
\gdef\redefineampersand{\def&{\myampersand}}%
\endgroup%
\begingroup%
\catcode`&=\active%
\redefineampersand%
a & b
\endgroup%
\newenvironment{newampersandenv}{%
\catcode`&=\active%
\redefineampersand%
}{}
\begin{newampersandenv}
a & b
\end{newampersandenv}
% I would like to do this but it doesn't work:
\newcommand{\newampersandcmd}[1]{
\begin{newampersandenv}
#1
\end{newampersandenv}
}
%\newampersandcmd{a & b} % Misplaced alignment tab character &. \newampersandcmd{a & b}
% I tried to write it another way but none of those work:
\newcommand{\testa}{
\begin{newampersandenv}
a & b
\end{newampersandenv}
}
%\testa % Misplaced alignment tab character &. \testa
\newcommand{\testb}{
\catcode`&=\active%
\redefineampersand%
a & b
}
%\testb % Misplaced alignment tab character &. \testb
\newcommand{\testc}{
\catcode`&=\active%
\redefineampersand%
\begingroup
a & b
\endgroup
}
%\testc % Misplaced alignment tab character &. \testc
\newcommand{\testd}{
\begingroup
\catcode`&=\active%
\redefineampersand%
a & b
\endgroup
}
%\testd % Misplaced alignment tab character &. \testd
\end{document}
答案1
这将起作用:
\documentclass[]{article}
\begin{document}
\newcommand{\myampersand}{?}
% https://tex.stackexchange.com/a/392770/82912
\begingroup%
\catcode`&=\active%
\gdef\redefineampersand{\def&{\myampersand}}%
\endgroup%
\begingroup%
\catcode`&=\active%
\redefineampersand%
a & b
\endgroup%
\newenvironment{newampersandenv}{%
\catcode`&=\active%
\redefineampersand%
}{}
\begin{newampersandenv}
a & b
\end{newampersandenv}
% I would like to do this but it doesn't work:
\def\newampersandcmd{%
\begin{newampersandenv}%
\@newampersandcmd%
}
\def\@newampersandcmd#1{%
#1%
\end{newampersandenv}%
}
\newampersandcmd{a & b}
% I tried to write it another way but none of those work:
\begingroup
\catcode`&=\active
\gdef\testa{%
\begin{newampersandenv}%
a & b%
\end{newampersandenv}%
}
\endgroup
\testa
\begingroup
\catcode`&=\active
\gdef\testb{%
\redefineampersand%
a & b%
}
\endgroup
\testb
\end{document}
发生的事情是 TeX 生效的规则不同读命令(IE执行\newcommand
s),以及 TeX 的规则执行定义的命令。
例如,我们使用这个宏:
\newcommand{\testa}{%
\catcode`&=\active
a & b%
}
当 TeX读它将\newcommand
输入转换为标记列表,并且每个标记都分配了一个cat
类别code
。但catcode
分配的 s 是读取命令时有效的 s,因此a & b
将被转换为catcode
s 11 10 4 10 11
,分别为字母、空格、对齐制表符、空格和字母。但\catcode
&=\active was never executed when TeX was reading the command, so the
&` 仍然是对齐制表符。
当 TeX 执行此命令时,它会将 的 改为catcode
,&
然后用s\active
写入标记列表。从定义时到执行时,标记的 并没有改变。a & b
catcode
11 10 4 10 11
catcode
但是,如果你移动catcode
更改外部命令定义:
\catcode`&=\active
\newcommand{\testa}{%
a & b%
}
TeX 将a & b
使用catcode
s读取,从现在开始每次使用11 10 13 10 11
宏时,这些将是TeX 将使用的 s,独立于使用命令时有效的 s。\testa
catcode
catcode
\makeatletter
这就是和起作用的原因\makeatother
。当您定义名称中带有 的“内部” LaTeX 命令时@
,例如:
\makeatletter
\def\wrappermacro{%
\my@m@cr@withm@ny@@@@%
}
\def\my@m@cr@withm@ny@@@@{hello}
\makeatother
在执行命令时,的更改catcode
为@
11
定义不久后又改回12
。当您使用 时\wrappermacro
,\my@m@cr@withm@ny@@@@
不会出现问题,因为catcode
当时有效的定义时间才是最重要的。
答案2
我的最终目标是找到一种方法来构建一个宏\makearraysfake
,使其\makearraysfake[?]{\begin{array}{ll}a&b\end{array}}
行为与 完全相同a?b
。换句话说,我想删除所有数组,并通过将内容与中间的某个给定分隔符连接起来来合并所有单元格(在一行上)。以下代码执行此操作。
(我的用例是使用 LyX 并使用数组来允许在某些枚举中放置任意数量的参数,但我不喜欢数组添加的空格。)
\documentclass{article}
\usepackage{xparse}
\usepackage{amsmath}
\usepackage{etoolbox}
% Define global versions of \newcommand and \renewcommand
% https://tex.stackexchange.com/a/51750/82912
\makeatletter
\def\gnewcommand{\g@star@or@long\gnew@command}
\def\grenewcommand{\g@star@or@long\grenew@command}
\def\g@star@or@long#1{%
\@ifstar{\let\l@ngrel@x\global#1}{\def\l@ngrel@x{\long\global}#1}}
\def\gnew@command#1{\@testopt{\@gnewcommand#1}0}
\def\@gnewcommand#1[#2]{%
\kernel@ifnextchar [{\@gxargdef#1[#2]}%
{\@argdef#1[#2]}}
\let\@gxargdef\@xargdef
\patchcmd{\@gxargdef}{\def}{\gdef}{}{}
\let\grenew@command\renew@command
\patchcmd{\grenew@command}{\new@command}{\gnew@command}{}{}
\makeatother
% This macro is used to apply the trick of https://tex.stackexchange.com/a/422603/82912
\newcommand{\identityendgroup}[1]{%
#1%
\endgroup%
}%
% The \makearraysfake command takes two arguments and returns the second one where arrays are removed (but their content remains) and ampersands are replaced by the first argument.
\begingroup%
\catcode`&=\active%
\gnewcommand{\makearraysfake}[1][]{
\begingroup%
\catcode`&=\active%
\def&{#1}%
\renewenvironment{array}[2][]{}{}%
\identityendgroup%
}%
\gnewcommand{\makeampersandactive}{
\begingroup%
\catcode`&=\active%
\def&{}%
\identityendgroup%
}
\endgroup%
\begin{document}
It prevents the errors when \& is used in the second argument, and replaces it by the first argument:
$$
%\boxed{a&b} % Misplaced alignment tab character &. $$\boxed{a&b}
%\not=
\makearraysfake[b]{\boxed{a&c}}
=
\boxed{abc}
$$
It removes the spaces added by array:
$$
\boxed{
\begin{array}{ll}
a&c
\end{array}
}
\not=
\makearraysfake[]{
\boxed{
\begin{array}{ll}
a&b
\end{array}
}
}
=
\boxed{ab}
$$
It can be used in other macros, provided that they are placed in a \textbackslash makeampersandactive macro:
\newcommand{\identity}[1]{#1}
$$
\makeampersandactive{
\identity{
\makearraysfake[]{
\boxed{
\begin{array}{ll}
a&b
\end{array}
}
}
}
}
$$
\end{document}