如果包太旧,是否可以中止加载?

如果包太旧,是否可以中止加载?

我正在开发一个必须同时在 TeXlive 2009(Ubuntu,因此更新 TeXlive 是不可能的)和更高版本上运行的软件包,如果我们使用 TeXlive 2010 或更高版本,我希望能够将 fontspec 与 LuaLaTeX 一起使用,但\RequirePackage{fontspec}[2008/08/10](Ubuntu 的 TeXlive 2009 附带一个fontspec.styfrom 2008/08/09)仍然尝试加载,并且 date 参数只能使 LaTeX 发出警告,说它太旧了 - 在因为它里面有fontspec.sty错误而抛出错误之后。fontspec.sty\RequireXeTeX

如果包太旧,有没有办法中止加载,或者我必须做一些疯狂的事情,包括(暂时)重新定义\ProvidesPackage。我已经想出了下面的例子,但我会用更合理的东西代替它:

\listfiles
\documentclass{article}
%\usepackage{trace}
\def\XID#1{\begingroup\ifdefined #1\aftergroup#1\fi\endgroup}
\XID\traceon
\let\OPP\ProvidesPackage
\def\ProvidesPackage#1[#2/#3]{%
  \let\ProvidesPackage\OPP
  \let\OPP\undefined
  \begingroup
    \ifnum #2 < 2009 % if fontspec is older than 2009, abort
      \aftergroup\endinput
      \XID\traceoff
    \fi
  \endgroup
  \XID\traceoff
  \ProvidesPackage#1[#2/#3]}

\usepackage{fontspec}
\ifdefined\setmainfont
  \message{^^J*** \string\setmainfont\space defined! ***^^J}
\else
  \message{^^J*** \string\setmainfont\space not defined! ***^^J}
\fi
\begin{document}
\end{document}

编辑:经过一些相当激烈的黑客攻击后,我想出了这个更短更明智的替代方案:

\documentclass{minimal}
\makeatletter
\def\IfNewer#1#2#3#4{% we chain into #5 if true and #6 if false using \@{first,second}oftwo.
  \begingroup %that we might forget the craziness that is to follow...
  \def\NeedsTeXFormat##1{\@ifnextchar[\relax\relax}
  % This is rather brittle and should probably use \@ifnextchar[
  \def\ProvidesPackage##1[##2/##3/##4 ##5]{%
    \newif\if@goahead % defaults to false, obviously.
    % Ugly test, but it works
    \ifnum ##2 < #2 % Year too old
    \else\ifnum ##2 = #2\ifnum ##3 < #3 % Year OK, month too old
    \else\ifnum ##2 = #2\ifnum ##3 = #3\ifnum ##4 < #4 % Year & month OK, day too old
    \else 
      \@goaheadtrue
    \fi\fi\fi\fi\fi\fi
    \endinput}
  \input #1.sty % use TeX's \input to avoid #1.sty being in \listfiles
  \if@goahead
    \endgroup % \if@goahead and our redifinitions disappear in a puff of logic.
    \expandafter\@firstoftwo
  \else
    \endgroup
    \expandafter\@secondoftwo
  \fi}
\makeatother
\IfNewer{fontspec}{2010}{01}{01}
  {\message{^^J*** New enough! ***^^J}}
  {\message{^^J*** Too old! ***^^J}}
\begin{document}
\end{document}

答案1

在查看了相关的 LaTeX 核心代码后,我没有看到除了重新定义之外的任何其他方法\ProvidesPackage。这是最早知道版本的地方。但是,我会尽可能重用现有的宏以保持兼容性。

以下代码读取两个参数,将它们提供给原始参数,然后正常检查包版本,必要时中止加载。请注意,包版本号仍然被定义(全局!)并且之后也可以使用。您应该将其设置为如图\relax所示,以将包标记为未加载。

\documentclass{article}

\makeatletter

\let\origProvidesPackage\ProvidesPackage
\def\ProvidesPackage#1{%
    \@testopt{\@ProvidesPackage{#1}}{}%
}
\def\@ProvidesPackage#1[#2]{%
    \let\ProvidesPackage\origProvidesPackage
    \ifx\\#2\\
        \ProvidesPackage{#1}%
    \else
        \ProvidesPackage{#1}[#2]%
    \fi
    \@ifpackagelater{fontspec}{2008/08/10}{%
    }{%
        \endinput
    }%
}


\usepackage{fontspec}
\@ifpackagelater{fontspec}{2008/08/10}{%
    \expandafter\let\csname [email protected]\endcsname\relax%   Mark package as not loaded; this must be after `\usepackage` because of internal LaTeX core code.
}{}%

\makeatother


\begin{document}


\end{document}

答案2

抱歉,我不明白这个问题——沃纳向我解释了一下。

好的,你加载了包,你可以检查它的版本,例如

\@ifpackagelater{amsmath}{1999/12/20}{\typeout{OK}}{\typeout{BAD}}

看看这个例子:

\documentclass{article}
\RequirePackage{amsmath}
\makeatletter
\@ifpackagelater{amsmath}{1999/12/20}{\typeout{OK}}{\typeout{BAD}}
\@ifpackagelater{amsmath}{2013/12/20}{\typeout{OK}}{\typeout{BAD}}
\makeatother

\begin{document}
Text
\end{document}

这里的问题是,你需要先加载包,然后才能知道它的版本。如果你想要终止旧发行版的编译,那么这是可以的,但否则可能会带来问题。

在评论中我建议将包是否正确写入一个特殊文件,并在下次运行之前检查它,然后再加载包。可能首先需要重新定义\RequreXeTeX以使第一次运行结束。

相关内容