我想定义一个 LaTeX (!) 命令,如果它出现在另一个命令的范围内,它将改变其行为。类似:
\newcommand{\aaa}[1]{#1}
\newcommand{\bbb}[1] IF WITHIN \aaa{} >>> {\it #1}
ELSE> {\bf #1}
抱歉,对于“代码”,但我不知道从哪里开始寻找它或如何正确地表述我的问题。
例如,
\bbb{sometext}
印刷:一些文本
尽管
\aaa{\bbb{sometext}}
印刷:一些文本
我所能找到的只是几年前的一个类似问题:检测是否在 \section 内答案是使用 ConTeXt 中的“模式”,但这对我来说是不可能的,因为我需要非常具体的包,因此只能使用 LaTeX。
答案1
\bbb
编辑以反映 Jonas 的有益见解,即原始方法(设置 0/1)可以通过重复调用内部来欺骗\aaa
。因此,我转换为类似的计数器方法,这样计数器值就可以反映嵌套的深度。
\documentclass{article}
\newcounter{inaaa}
\newcommand{\aaa}[1]{\stepcounter{inaaa}#1\addtocounter{inaaa}{-1}}
\newcommand{\bbb}[1]{%
\ifnum\value{inaaa}=0\textbf{#1}\else\relax\textit{#1}\fi}
\begin{document}
\bbb{sometext}
\aaa{\bbb{sometext} text}
\aaa{\aaa{\bbb{foo}}\bbb{bar}}
\end{document}
答案2
您可以使用\newif
命令来定义新的(非常低级的)条件和改变条件测试的命令:
\documentclass{article}
\newif\ifinsideaaa
\newcommand{\aaa}[1]{%
\insideaaatrue
#1%
\insideaaafalse
}
\newcommand{\bbb}[1]{
\ifinsideaaa
{\itshape #1}%
\else
{\bfseries #1}%
\fi
}
\begin{document}
\bbb{Some text outside of \texttt{\string\aaa}}
\aaa{\bbb{Some text inside of \texttt{\string\aaa}}}
\end{document}
定义的新命令\newif\if<foo>
是:
\if<foo>
:要使用的条件检查\if<foo> ... \else ... \fi
,\<foo>true
:将条件设置为 True 的命令,以及\<foo>false
:将条件设置为 false 的命令。
附注:在 LaTeX 中,你应该使用\itshape
and\bfseries
而不是\it
and \bf
。后者已经过时了。
答案3
\if..
只要可能,我就会尽量避免使用 TeX 原语。
\documentclass{article}
\makeatletter
\newcommand\My@CheckWhetherinAAA{}
\newcommand\My@SetInAAATrue{\let\My@CheckWhetherinAAA=\@firstoftwo}
\newcommand\My@SetInAAAFalse{\let\My@CheckWhetherinAAA=\@secondoftwo}
\global\My@SetInAAAFalse
\newcommand{\aaa}[1]{%
\My@CheckWhetherinAAA{#1}%
{\My@SetInAAATrue#1\My@SetInAAAFalse}%
}%
\newcommand{\bbb}[1]{%
\My@CheckWhetherinAAA{\textit}%
{\textbf}%
{#1}%
}
%
% The result of the following is the same but LaTeX has to shuffle
% around more tokens:
%
% \newcommand{\bbb}[1]{%
% \My@CheckWhetherinAAA{\textit{#1}}%
% {\textbf{#1}}%
% }%
%
\makeatother
\begin{document}
\bbb{some text}
\aaa{\bbb{some text}}
\aaa{\aaa{\bbb{some text}} \aaa{\bbb{some more text}}}
\begingroup \aaa{\aaa{\bbb{some text}} \endgroup\aaa{\bbb{some more text}}}
\bbb{some text}
\end{document}
采用这种方法,构成论据的标记\aaa
就会加倍并被吞噬。
可以通过定义另一个辅助宏来避免这种情况:
\documentclass{article}
\makeatletter
\newcommand\My@CheckWhetherinAAA{}
\newcommand\My@SetInAAATrue{\let\My@CheckWhetherinAAA=\@firstoftwo}
\newcommand\My@SetInAAAFalse{\let\My@CheckWhetherinAAA=\@secondoftwo}
\newcommand\My@SetAAAconditions[1]{\My@SetInAAATrue#1\My@SetInAAAFalse}%
\global\My@SetInAAAFalse
\newcommand{\aaa}[1]{%
\My@CheckWhetherinAAA{\@firstofone}%
{\My@SetAAAconditions}%
{#1}%
}%
\newcommand{\bbb}[1]{%
\My@CheckWhetherinAAA{\textit}%
{\textbf}%
{#1}%
}
%
% The result of the following is the same but LaTeX has to shuffle
% around more tokens:
%
% \newcommand{\bbb}[1]{%
% \My@CheckWhetherinAAA{\textit{#1}}%
% {\textbf{#1}}%
% }%
%
\makeatother
\begin{document}
\bbb{some text}
\aaa{\bbb{some text}}
\aaa{\aaa{\bbb{some text}} \aaa{\bbb{some more text}}}
\begingroup \aaa{\aaa{\bbb{some text}} \endgroup\aaa{\bbb{some more text}}}
\bbb{some text}
\end{document}
答案4
锡拉库萨的答案\aaa
如果在其自身内使用则可能会失败,如下例所示:
\aaa{
\aaa{\bbb{foo}}
\bbb{bar}}
这将使富 酒吧代替富 酒吧。
乌尔里希和接受的答案没有这个缺点,而且是很好的解决方案,特别是如果你想\bbb
同时定义两个版本。一个更快捷、更简单的方法,也可以像上面的例子一样运行,就是让局部\aaa
重新定义\bbb
,如下Teepeemm 评论了:
\newcommand{\bbb}[1]{\textbf{#1}}
\newcommand{\aaa}[1]{\bgroup\def\bbb##1{\textit{##1}}#1\egroup}
第二行中的double##
是必要的,因为它是另一个定义内的定义。
(顺便说一下,如果\bbb
只应在内部定义,则此方法也很有用\aaa
- 只需删除第一行。)