自定义 \if 命令来检查多个条件

自定义 \if 命令来检查多个条件

我正在为我所在学院的本科和硕士论文创建一个文档类。它几乎已经准备就绪,并符合今年的官方要求。但是,未来情况可能会发生变化:例如,管理层可能会突然更改标题页布局或做类似的事情。因此,我想向我的课程添加版本选项,如下所示:

\documentclass[v2018]{physvsuThesis}

借助这些选项,我计划保留向后兼容性,同时能够根据需要纳入新的要求。

但是,我不知道如何以方便的方式管理这些条件。使用纯 TeX\newif似乎不是一个可行的选择。我能想到的唯一解决方案是推出我的自定义命令来实现条件逻辑,如下所示:

\DeclareOption{v2018}{\setVersion{2018}}
\DeclareOption{v2019}{\setVersion{2019}}
...

\ifVersion{2018, 2019} % logical OR
  ...
\fi

我如何实现该\ifVersion命令以便它可以检查多个条件并且即使嵌套也能工作?

答案1

一行代码expl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
% this assumes that \classversion contains the version

\NewDocumentCommand{\ifVersion}{mmO{}}
 {% #1 is a list of items of the form {year,...}
  % #2 is the code to execute in case of a match
  % #3 (optional) is the code to use in case of no match
  \str_if_in:nVTF { #1 } \classversion { #2 } { #3 }
 }
\prg_generate_conditional_variant:Nnn \str_if_in:nn { nV } { T, F, TF }
\ExplSyntaxOff

\def\classversion{2018} % emulate what the class does

\begin{document}

\ifVersion{2018}{Version 2018}[Not version 2018]

\ifVersion{2017,2018}{This is 2017 or 2018}

\ifVersion{2016}{Nothing} $\leftarrow$ nothing

\ifVersion{2016}{Nothing}[Not 2016]

\ifVersion{2016,2017}{Nothing} $\leftarrow$ nothing

\end{document}

在此处输入图片描述

答案2

expl3使用with 的简单实现\if ... \fi

\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\str_new:N\g_my_version_str
\NewDocumentCommand\setVersion{ m }{
  \str_gset:Nn \g_my_version_str { #1 }
}
\NewDocumentCommand\ifVersion{ m }{
  \clist_if_in:nVTF { #1 } {\g_my_version_str} {\iftrue} {\iffalse}
}
\ExplSyntaxOff
\begin{document}
\setVersion{2018}
\ifVersion{2017, 2018}
+1\\
\fi
\ifVersion{2017, 2015}
+2\\
\fi
\end{document}

这会导致嵌套条件出现问题,因为 TeX 不将其\ifVersion视为\if命令,因此\else/\fi解析在未评估的上下文中不同步。

相反,最好将条件命令作为参数传递:

\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\str_new:N\g_my_version_str
\NewDocumentCommand\setVersion{ m }{
  \str_gset:Nn \g_my_version_str { #1 }
}
\NewDocumentCommand\ifVersion{ m }{
  \clist_if_in:nVTF { #1 } {\g_my_version_str}
}
\ExplSyntaxOff
\begin{document}
\setVersion{2018}
\ifVersion{2017, 2018}{+1}{Not +1}
\ifVersion{2017, 2015}{+2}{Not +2}
\end{document}

答案3

不用任何包你也可以做到这一点:

\documentclass{article}

\makeatletter
\newcommand{\setVersion}[1]{\def\fire@version{#1}}

\setVersion{2018-06-08}

\newcommand{\ifVersion}[1]{\ifnum\numexpr#1>0
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}

\newcommand\IS[1]{%
  \if0\expandafter\pdfstrcmp\expandafter{\fire@version}{#1}%
    \expandafter1%
  \else
    \expandafter0%
  \fi}

\newcommand\ISNOT[1]{%
  \if0\expandafter\pdfstrcmp\expandafter{\fire@version}{#1}%
    \expandafter0%
  \else
    \expandafter1%
  \fi}

\newcommand\AND[2]{(#1*#2)}

\newcommand\OR[2]{(#1+#2-#1*#2)}

\newcommand\NOT[1]{(1-#1)}

\makeatother

\begin{document}

\ifVersion
{\AND{\OR{\OR{\IS{v1}}{\IS{v2}}}{\IS{2018-06-08}}}{\ISNOT{2017-05-11}}}
{YES}
{NO}
% YES

\ifVersion
{\OR{\OR{\OR{\IS{v1}}{\IS{v2}}}{\IS{2018-06-08}}}{\IS{2017-05-11}}}
{YES}
{NO}
% YES

\ifVersion
{\AND{\OR{\OR{\IS{v1}}{\IS{v2}}}{\IS{2018-06-08}}}{\IS{2017-05-11}}}
{YES}
{NO}
% NO

\end{document}

使用上述解决方案是\pdfstrcmp因为我不想假设版本号仅仅是数字。

在此处输入图片描述

以上内容可以嵌套,没有问题。

现在,为了更方便的中缀表示法,你可以使用 xintexpr它提供了\xintifboolexpr和函数 以及bool()togl()查看文档。这将允许您bool()在任意复杂的逻辑表达式中组合(与 )TeX 条件。

答案4

也许有点过头了,但可以通过迭代来完成。例如使用pgfforxstring

\documentclass{article}
\usepackage{xstring}
\usepackage{pgffor}
\newif\ifIsInList

% #1: haystack
% #2: needle
% #3: action if found in list
% #4: action if not found in list
\gdef\isin#1#2#3#4{
    \global\IsInListfalse%
    \def\needle{#2}%
    \def\haystack{#1}%
    \makeatletter\IfInteger{\needle}{}{\@latex@error{ISIN: Can't look for list item that is not numeric!}{}\bye\stop}\makeatother%
    \IfInteger{\haystack}{%
        \ifnum\haystack=\needle\relax%
            #3%
        \else%
            #4%
        \fi%
    }{%
        \foreach \pp in {#1}{%
                \ifnum\pp=\needle\relax%
                    \global\IsInListtrue%
                    #3%
                \fi%
            }%
        \ifIsInList\else%
            #4%
        \fi%
    }%
}
\begin{document}
%\isin{Comma Separated List}{Look for}{If found}{If not found}
\isin{2011,2012}{2011}{2011 is in the list!}{2011 is not in the list}%
\isin{2011,2012}{2013}{2013 is in the list!}{2013 is not in the list}
\end{document}

xstring不是严格需要的——只是为了在第一个参数是整数时捕获错误,并确保第二个参数是整数。

相关内容