我正在为我所在学院的本科和硕士论文创建一个文档类。它几乎已经准备就绪,并符合今年的官方要求。但是,未来情况可能会发生变化:例如,管理层可能会突然更改标题页布局或做类似的事情。因此,我想向我的课程添加版本选项,如下所示:
\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
也许有点过头了,但可以通过迭代来完成。例如使用pgffor
和xstring
:
\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
不是严格需要的——只是为了在第一个参数是整数时捕获错误,并确保第二个参数是整数。