如何向宏中添加单个花括号?

如何向宏中添加单个花括号?

我尝试\textit{abc}这样创作:

\documentclass{article}
\makeatletter

\def\test{}

\catcode123=12 % change cat code of "{" to "other"
\g@addto@macro\test{
\catcode123=1  % restore the cat code

\g@addto@macro\test{abc}

\catcode125=12 % change cat code of "}" to "other"
\g@addto@macro\test}
\catcode125=2  % restore the cat code

\begin{document}
    \test
\end{document}

但是,发布\test不会打印斜体abc。我该如何实现我想要做的事情?

答案1

您可以使用以下模式来构建宏的替换文本。基本思想是不直接构建最终结果,而是首先创建一个命令序列,当它在 中完全展开时产生最终结果\edef。要构建序列,您可以使用\g@addto@macro宏,并在算法进行时添加材料。

以下是需要为各个方面添加的序列模式(见这个答案有关括号模式的解释):

  • 添加宏名:\noexpand\macroname
  • 添加不应展开的一般材料:\unexpanded{...}
  • 添加左括号:{\iffalse}\fi
  • 添加右括号:\iffalse{\fi}
  • 所有不可扩展的材料或\protect'ed宏都可以直接使用

从这些模式我们可以构建您的问题中提到的宏:

\documentclass{article}
\makeatletter

\def\test{}

\g@addto@macro\test{\noexpand\textit}
\g@addto@macro\test{{\iffalse}\fi}
\g@addto@macro\test{abc}
\g@addto@macro\test{\iffalse{\fi}}

%\show\test
\edef\test{\test}
%\show\test

\begin{document}
    \test
\end{document}

如果取消注释\show此示例中的调用,则可以看到之前的宏定义

> \test=macro:
->\noexpand \textit {\iffalse }\fi abc\iffalse {\fi }.

扩展后

> \test=macro:
->\textit {abc}.

答案2

尽管expl3的正则表达式引擎(由 加载regexpatch)是一款出色的工具(我的工作职责就是推销expl3),但在这种情况下,这就像是用猎枪打苍蝇一样 :-)

您可以使用宏来定义另一个宏来实现相同的效果。 宏的简单定义\MakeItalic\def\MakeItalic#1{\edef#1{\noexpand\textit{#1}}}\noexpand会确保\textit不会在 内部爆炸(如果您使用 ,则\edef可以省略)。 将是您的宏\noexpand\protected@edef#1包含 abc,其将扩展为abc

更强大的定义\MakeItalic需要 e-TeX(您使用的是 LaTeX,因此无论如何这都是默认设置):

\newcommand{\MakeItalic}[1]{%
  \edef#1{\noexpand\textit{\unexpanded\expandafter{#1}}}}

与之前版本的不同之处在于,#1我们不会完全展开 ,而是仅使用 展开一次\unexpanded\expandafter{#1}。这可确保如果您的\test宏包含其他宏或活动字符,它不会爆炸。

测试文档:

\documentclass{article}
\newcommand{\MakeItalic}[1]{%
  \edef#1{\noexpand\textit{\unexpanded\expandafter{#1}}}}
% Complicated definition of \test
\def\test{abc}
% Add \textit{...}
\MakeItalic\test
\begin{document}
\texttt{\meaning\test} = \test
\end{document}

生成:

在此处输入图片描述

答案3

其中一个答案可能是这样的:

\documentclass{article}
\usepackage{regexpatch}

\def\test{abc}
\regexpatchcmd{\test}{.*}{\c{textit}\cB\{\0\cE\}}{}{}

\begin{document}
    \test
\end{document}

变体:

\documentclass{article}
\usepackage{regexpatch}
\makeatletter

\def\test{\textit XXX}
\g@addto@macro\test{abc}
\g@addto@macro\test{XXX}

\regexpatchcmd{\test}{XXX(.*)XXX}{\cB\{\1\cE\}}{}{}

\begin{document}
    \test
\end{document}

相关内容