代码重新定义 & 符号在命令中停止工作

代码重新定义 & 符号在命令中停止工作

我想重新&定义命令我尝试去适应^在环境中重新定义但无法使其工作的代码。

\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执行\newcommands),以及 TeX 的规则执行定义的命令。

例如,我们使用这个宏:

\newcommand{\testa}{%
  \catcode`&=\active
  a & b%
}

当 TeX它将\newcommand输入转换为标记列表,并且每个标记都分配了一个cat类别code。但catcode分配的 s 是读取命令时有效的 s,因此a & b将被转换为catcodes 11 10 4 10 11,分别为字母、空格、对齐制表符、空格和字母。但\catcode&=\active was never executed when TeX was reading the command, so the&` 仍然是对齐制表符。

当 TeX 执行此命令时,它会将 的 改为catcode&然后用s\active写入标记列表。从定义时到执行时,标记的 并没有改变。a & bcatcode11 10 4 10 11catcode

但是,如果你移动catcode更改外部命令定义:

\catcode`&=\active
\newcommand{\testa}{%
  a & b%
}

TeX 将a & b使用catcodes读取,从现在开始每次使用11 10 13 10 11宏时,这些将是TeX 将使用的 s,独立于使用命令时有效的 s。\testacatcodecatcode

\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}

相关内容