我正在开发一个必须同时在 TeXlive 2009(Ubuntu,因此更新 TeXlive 是不可能的)和更高版本上运行的软件包,如果我们使用 TeXlive 2010 或更高版本,我希望能够将 fontspec 与 LuaLaTeX 一起使用,但\RequirePackage{fontspec}[2008/08/10]
(Ubuntu 的 TeXlive 2009 附带一个fontspec.sty
from 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
以使第一次运行结束。