我想在 LaTeX 文档的序言中写入代码,这些代码应该被不同的编译器在排版文档时考虑。应该使用以下片段:
- 仅限 xelatex
- 仅限 lualatex
- 仅由 xelatex 或 lualatex 提供
- 仅由 pdflatex 提供
我正在使用ifxetex
和ifluatex
分别提供命令\ifxetex
和\ifluatex
。
我怎样才能在析取(or
操作)中逻辑地组合这些命令?
代码如下:
\ifxetex
% code used only by xetex
\else
\ifluatex
% code used only by luatex
\fi
\fi
\ifxetex OR \ifluatex % I do not know how to express this conditional <--------
% code used by both xetex and luatex
\else
% code used by other (pdflatex, say)
\fi
有什么帮助吗?
答案1
\usepackage{ifxetex,ifluatex}
\newif\ifxetexorluatex
\ifxetex
\xetexorluatextrue
\else
\ifluatex
\xetexorluatextrue
\else
\xetexorluatexfalse
\fi
\fi
现在\ifxetexorluatex
就可以做你想做的事了。例如,加载fontspec
和设置输入规范化:
\ifxetexorluatex
\usepackage{fontspec}
\setmainfont{TeX Gyre Pagella}
\else
\usepackage[T1]{fontenc}
\usepackage{tgpagella}
\fi
\ifxetex
\XeTeXinputnormalization=1
\fi
为了好玩,还有一个不同的实现,
\newif\ifxetexorluatex
\begingroup\catcode94=7 \catcode0=9 % ASCII 94 is ^
\def\empty{}\def\next{^^^^0000}\expandafter\endgroup
\ifx\next\empty\xetexorluatextrue\else\xetexorluatexfalse\fi
它利用了 XeTeX 和 LuaTeX 引擎使用^^^^
Unicode 点输入字符的惯例。如果引擎支持 Unicode,则^^^^0000
被视为唯一标记,而赋值\catcode0=9
会被忽略,因此\next
会扩展为零,相当于\empty
。如果使用 8 位引擎, 的扩展\next
将包含六个标记(^^^
算作一个,然后^0000
),\ifx
并将遵循“错误”路径。
另一种不定义条件的方法\ifxetexorluatex
是
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi>0
% code for XeTeX or LuaTeX
\else
% code for pdfLaTeX
\fi
必须有不0
和之间\ifxetex
以及1
和之间的空格\fi
。这利用了 TeX 在查找数字时会扩展标记的事实。因此,如果两个内部条件之一为真,则引擎将看到01
,它大于零。如果两者都为假,它将看到0
。
因此,设置的一个更短的方法\ifxetexorluatex
可以是
\newif\ifxetexorluatex % a new conditional starts as false
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi>0
\xetexorluatextrue
\fi
使用 的更通用的实现expl3
。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_eq:NN \pdftexengine \sys_if_engine_pdftex_p:
\cs_new_eq:NN \xetexengine \sys_if_engine_xetex_p:
\cs_new_eq:NN \luatexengine \sys_if_engine_luatex_p:
\cs_new_eq:NN \ptexengine \sys_if_engine_ptex_p:
\cs_new_eq:NN \uptexengine \sys_if_engine_uptex_p:
\NewExpandableDocumentCommand{\ifengineTF}{mmm}
{
\bool_if:nTF { #1 } { #2 } { #3 }
}
\ExplSyntaxOff
\begin{document}
\ifengineTF{\pdftexengine}
{\typeout{pdf}}
{\typeout{not pdf}}
\ifengineTF{\xetexengine || \luatexengine}
{\typeout{either xe or lua}}
{\typeout{neither xe nor lua}}
\ifengineTF{\pdftexengine || \xetexengine || \luatexengine}
{\typeout{pdf or xe or lua}}
{\typeout{ptex or uptex}}
\end{document}
从 shell 运行以下命令
> pdflatex engines >> engines.out
> xelatex engines >> engines.out
> lualatex engines >> engines.out
> platex engines >> engines.out
生成以下engines.out
文件(已编辑,仅显示相关部分)
This is pdfTeX, Version 3.14159265-2.6-1.40.19 (TeX Live 2018) (preloaded format=pdflatex)
restricted \write18 enabled.
entering extended mode
(./engines.tex
[...]
pdf
neither xe nor lua
pdf or xe or lua
[...]
This is XeTeX, Version 3.14159265-2.6-0.99999 (TeX Live 2018) (preloaded format=xelatex)
restricted \write18 enabled.
entering extended mode
(./engines.tex
[...]
not pdf
either xe or lua
pdf or xe or lua
[...]
This is LuaTeX, Version 1.07.0 (TeX Live 2018)
restricted system commands enabled.
(./engines.tex
[...]
not pdf
either xe or lua
pdf or xe or lua
[...]
This is e-pTeX, Version 3.14159265-p3.8.1-180226-2.6 (utf8.euc) (TeX Live 2018) (preloaded format=platex)
restricted \write18 enabled.
entering extended mode
(./engines.tex
[...]
not pdf
neither xe nor lua
ptex or uptex
(./engines.aux) )
[...]
一种不同的解决方案,可能具有更好的语法,但以牺牲可扩展性为代价(直到我们有可用e
的-expansion)。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\ifengineTF}{mmm}
{
\bool_if:xTF
{
\clist_map_function:nN { #1 } \__egreg_predicate:f \c_true_bool
}
{ #2 } { #3 }
}
\cs_generate_variant:Nn \bool_if:nTF { x }
\cs_new:Nn \__egreg_predicate:n
{
\use:c { sys_if_engine_#1_p: } ||
}
\cs_generate_variant:Nn \__egreg_predicate:n { f }
\ExplSyntaxOff
\begin{document}
\ifengineTF{pdftex}
{\typeout{pdf}}
{\typeout{not pdf}}
\ifengineTF{xetex,luatex}
{\typeout{either xe or lua}}
{\typeout{neither xe nor lua}}
\ifengineTF{pdftex,xetex,luatex}
{\typeout{pdf or xe or lua}}
{\typeout{ptex or uptex}}
\end{document}
输出与以前相同。
答案2
在这种情况下\ifboolexpr
,etoolbox
包派上用场了:
\usepackage{etoolbox,ifxetex,ifluatex}
\ifboolexpr{bool{xetex} or bool{luatex}}{%
<true-code>%
}{%
<false-code>%
}
与执行布尔测试的语法配合使用的 bool 运算符\ifboolexpr
可对所有原始样式的 TeX 条件进行操作。请注意,它省略了\if
原始\ifxetex
and\ifluatex
命令的前缀。
答案3
有时,通过改变检查顺序,这类问题会更容易解决。
\documentclass{article}
\usepackage{ifpdf,ifluatex,ifxetex}
\begin{document}
\ifpdf
I am in pdf
\else
common code for lualatex and xelatex
\ifluatex ... \fi
\ifxetex ... \fi
\fi
\end{document}
答案4
为了好玩,可能是最短的路:
\documentclass{article}
\usepackage{ifxetex,ifluatex}
\begin{document}
hello
\ifx\ifxetex\ifluatex\else
xetex or luatex is true
\fi
\end{document}
确实,xetex
和luatex
是互相排斥的。如果两个条件一致,那一定是因为两者都是假的。所以相反的情况是,两者之一为真,这正是所要求的。
正如评论中指出的那样egreg
,这种构造不能在其他条件语句中原样使用(以防它最终进入跳过的分支)。这种替代表述没有这个缺陷:
\expandafter\ifx\csname ifxetex\expandafter\endcsname \csname ifluatex\endcsname\else
xetex or luatex is true\fi