![如何向宏中添加单个花括号?](https://linux22.com/image/401132/%E5%A6%82%E4%BD%95%E5%90%91%E5%AE%8F%E4%B8%AD%E6%B7%BB%E5%8A%A0%E5%8D%95%E4%B8%AA%E8%8A%B1%E6%8B%AC%E5%8F%B7%EF%BC%9F.png)
我尝试\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}