LaTeX 中的条件“如果在另一个命令中”

LaTeX 中的条件“如果在另一个命令中”

我想定义一个 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 中,你应该使用\itshapeand\bfseries而不是\itand \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- 只需删除第一行。)

相关内容