Latex 命令存在检查条件

Latex 命令存在检查条件

如何检查条件,如果\commandtwo在 tex 文件中出现,\commandone \if条件应该是过程,否则\else 条件应该是过程?如何制定条件?

注意:\commandtwo{XXX}在 之后的 tex 文件中可能会出现或不会出现,但和的\begin{document}定义在序言中。\def\commandone#1{#1}\def\commandtwo#1{#1}\def\commandthree#1{#1}

MWE文件如下:

\documentclass{book}

\makeatletter
%\commandtwo present in the file \if condition should be process if not presented in the file \else condition should be process
\def\commandone#1{\ifx\@ScndArg\@empty{\Huge#1}\else{\tiny#1}\fi}

\def\commandtwo#1{\def\@ScndArg{#1}#1}

\def\commandthree#1{#1}
\makeatother

\begin{document}

\commandone{AAA}

\commandtwo{BBB}

\commandthree{CCC}

\end{document}

答案1

由于\commandtwo可能出现 \commandone,您需要考虑使用 来.aux存储将在二次编译中使用的内容。下面\commandtwo写入将在下一次编译时读取的\gdef\commandtwopresent{}内容.aux。即使它被定义为空,它也可以用于通过\ifcsname...进行条件处理\endcsname

在此处输入图片描述

\documentclass{article}

\makeatletter
%\commandtwo present in the file \if condition should be process if not presented in the file \else condition should be process
\def\commandone#1{\ifcsname commandtwopresent\endcsname {\Huge#1}\else{\tiny#1}\fi}

\def\commandtwo#1{%
  \immediate\write\@auxout{\gdef\string\commandtwopresent{}}%
  #1}

\def\commandthree#1{#1}
\makeatother

\begin{document}

\commandone{AAA}

\commandtwo{BBB}

\commandthree{CCC}

\end{document}

答案2

Werner 建议通过 .aux 文件定义宏,定义的宏指示是否在之前的 LaTeX 运行中\commandtwo执行过。

根据这个建议,我提供了一种变体,其中写一个交叉引用标签,其结果是“真”或“假”,并且可以在\csname..\endcsname产生\iftrue或的表达式中使用\iffalse

这种变体的优点是,如果由于某些内容发生变化而必须重新编译,则会通过控制台和 .log 文件通知您,因为更改伴随着所述交叉引用标签的更改,而交叉引用标签的更改由 LaTeX 内核跟踪。

这种变体的一个缺点是,需要额外的包,即包尽头,需要在正确的时间点挂接以写入所述交叉引用标签。

\documentclass{book}
\usepackage{atveryend}
%\usepackage{hyperref}

\makeatletter
\AfterLastShipout{%
  \immediate\write\@auxout{\string\newlabel{CommandTwoUsed}{\CommandTwoUsed}}%
}%
\newcommand\CommandTwoUsed{false}
\AtBeginDocument{%
  \expandafter\newcommand
  \expandafter\CheckWhetherCommandTwoUsed
  \expandafter{%
    \csname if\@ifundefined{r@CommandTwoUsed}{false}{\r@CommandTwoUsed}\endcsname
    \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  }%
}%
\newcommand\commandtwo[1]{\gdef\CommandTwoUsed{true}#1}
\newcommand\commandone[1]{\CheckWhetherCommandTwoUsed{{\Huge#1}}{{\tiny#1}}}
\newcommand\commandthree[1]{#1}
\makeatother

\begin{document}

\commandone{AAA}

\commandtwo{BBB}

\commandthree{CCC}

\end{document}

在此处输入图片描述

答案3

短语“\commandtwo存在于文件中”中的“存在”到底是什么意思?

\input假设有问题的 .tex-input-file(或通过或处理的其他文件\include,属于有问题的文档?)包含
\verb|\commandtwo...| 和/或
% This is a comment containing \commandtwo

\commandtwo在这种情况下,存在于文件中的条件会得到满足吗?

如果您只想知道是否\commandtwo已经执行/尚未执行,同时假设\@ScndArg除了执行之外没有其他定义方法\commandtwo,那么您可以检查是否\@ScndArg已定义/未定义。

沃纳 (Werner) 已经在他的回答中展示了如何在\ifcsname..\endcsnameε-TeX 扩展可用的情况下做到这一点。

为了好玩,您可以通过检查\meaning该标记的 是否包含短语“未定义”来测试宏参数是否具有第一个标记(即未定义的控制序列)。这样就不需要依赖任何 TeX 扩展的可用性:

\errorcontextlines=10000
\documentclass{article}

\makeatletter
%%=============================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo, \UD@Exchange,  \UD@CheckWhetherNull,
%%    \UD@stopromannumeral
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@Exchange[2]{#2#1}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}%
  {\expandafter\UD@stopromannumeral\UD@firstoftwo}%
}%
%%=============================================================================
%% Check whether brace-balanced argument has a first token which is an
%% undefined control sequence.
%% (Only with undefined control sequences the \meaning has the leading phrase
%% "undefined"; besides this \meaning never delivers no tokens at all)
%%.............................................................................
%% \CheckWhetherLeadingUndefined{<Argument which is to be checked>}%
%%                              {<Tokens to be delivered in case <argument
%%                                 which is to be checked> has a 1st token 
%%                                 which is undefined>}%
%%                              {<Tokens to be delivered in case <argument
%%                                which is to be checked> does not have a 1st
%%                                token which is undefined>}%
\begingroup
\def\CheckWhetherLeadingUndefined#1{%
  \endgroup
  \newcommand\CheckWhetherLeadingUndefined[1]{%
    \romannumeral\expandafter\UD@secondoftwo\expandafter{\expandafter{%
    \string##1X}\expandafter\UD@firstoftwo\expandafter{\expandafter
    \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{%
       % Let's nest things into \UD@firstoftwo{...}{} to make sure they are nested in braces
       % and thus do not disturb when the test is carried out within \halign/\valign:
       \expandafter\UD@firstoftwo\expandafter{%
         \expandafter\expandafter\expandafter\UD@stopromannumeral
         \romannumeral\expandafter\UD@secondoftwo
         \string{\expandafter\UD@CheckWhetherLeadingUndefinedB\expandafter.\meaning##1X#1}{}%
       }{}%
    }%
  }%
  \@ifdefinable\UD@CheckWhetherLeadingUndefinedB{%
    \long\def\UD@CheckWhetherLeadingUndefinedB##1#1{%
      \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}##1}%
      {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
      {\expandafter\expandafter\expandafter\UD@stopromannumeral
       \expandafter\expandafter\expandafter}%
       \expandafter\UD@secondoftwo\expandafter{\string}%
    }%
  }%
}%
\escapechar=-1\relax
\expandafter\CheckWhetherLeadingUndefined\expandafter{\string\undefined}%
\makeatother

\begin{document}

\medskip\hrule\medskip

The sequence \verb|abc|
\CheckWhetherLeadingUndefined{abc}{does have}{does not have}
a leading token which is an undefined control sequence.

\medskip\hrule\medskip

The sequence \verb|\TeX abc|
\CheckWhetherLeadingUndefined{\TeX abc}{does have}{does not have}
a leading token which is an undefined control sequence.

\medskip\hrule\medskip

The empty sequence 
\CheckWhetherLeadingUndefined{}{does have}{does not have}
a leading token which is an undefined control sequence.

\medskip\hrule\medskip

The blank sequence  \verb*| |
\CheckWhetherLeadingUndefined{ }{does have}{does not have}
a leading token which is an undefined control sequence.

\medskip\hrule\medskip

The sequence  \verb|\else|
\CheckWhetherLeadingUndefined{\else}{does have}{does not have}
a leading token which is an undefined control sequence.

\medskip\hrule\medskip

The sequence \verb|{\UnDefIneD} abc|
\CheckWhetherLeadingUndefined{{\UnDefIneD} abc}{does have}{does not have}
a leading token which is an undefined control sequence.

\medskip\hrule\medskip

The sequence \verb|{}\UnDefIneD abc|
\CheckWhetherLeadingUndefined{{}\UnDefIneD abc}{does have}{does not have}
a leading token which is an undefined control sequence.

\medskip\hrule\medskip

The sequence \verb*| \UnDefIneD abc|
\CheckWhetherLeadingUndefined{ \UnDefIneD abc}{does have}{does not have}
a leading token which is an undefined control sequence.

\medskip\hrule\medskip

The sequence \verb|\UnDefIneD \fi \csname abc|
\CheckWhetherLeadingUndefined{\UnDefIneD \fi \csname abc}{does have}{does not have}
a leading token which is an undefined control sequence.

\medskip\hrule\medskip

The sequence \verb|\UnDefIneD abc|
\CheckWhetherLeadingUndefined{\UnDefIneD abc}{does have}{does not have}
a leading token which is an undefined control sequence.

\medskip\hrule\medskip

\end{document}

在此处输入图片描述

另一种方法是,在 verbatim-catcode-régime 下重新读取整个相关输入文件,通过分隔参数检查是否\commandtwo存在该短语。但是,如果注释包含该短语,则可以避免这种情况。如果输入文件 A 和输入文件 B 都属于同一文档,并且输入文件 A 在处理输入文件 B 之前被处理,则在输入文件 B 中,这也可以通过输入文件 A 包含\let\foobar=\commandtwo和输入文件 B 包含来避免\foobar这种情况,而不是\commandtwo

因此,我不会详细阐述这一点,除非您发表评论表明尽管这种方法存在缺点,但您仍对其感兴趣。

相关内容