Combining \ifxetex and \ifluatex with the logical OR operation
\usepackage{ifxetex,ifluatex}
\newif\ifxetexorluatex
\ifxetex
\xetexorluatextrue
\else
\ifluatex
\xetexorluatextrue
\else
\xetexorluatexfalse
\fi
\fi
Now \ifxetexorluatex
will do what you want. For instance, for loading fontspec
and setting input normalization:
\ifxetexorluatex
\usepackage{fontspec}
\setmainfont{TeX Gyre Pagella}
\else
\usepackage[T1]{fontenc}
\usepackage{tgpagella}
\fi
\ifxetex
\XeTeXinputnormalization=1
\fi
A different implementation, just for fun, is
\newif\ifxetexorluatex
\begingroup\catcode94=7 \catcode0=9 % ASCII 94 is ^
\def\empty{}\def\next{^^^^0000}\expandafter\endgroup
\ifx\next\empty\xetexorluatextrue\else\xetexorluatexfalse\fi
It exploits the fact that the XeTeX and LuaTeX engines have the ^^^^
convention for inputting character with their Unicode point. If the engine is Unicode aware, ^^^^0000
counts as a unique token which, by the assignment \catcode0=9
is ignored, so that \next
expands to nothing and is equivalent to \empty
. In case an 8-bit engine is used, the expansion of \next
would contain six tokens (^^^
counts as one, then ^0000
) and \ifx
will follow the "false" path.
Another way of doing it, without defining an \ifxetexorluatex
conditional, is to say
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi>0
% code for XeTeX or LuaTeX
\else
% code for pdfLaTeX
\fi
There must be no space between 0
and \ifxetex
and between 1
and \fi
. This exploits the fact that TeX expands tokens when looking for numbers. So if one of the two inner conditionals is true, the engine will see 01
, which is greater than zero. If both are false it will see 0
.
So a shorter way to set \ifxetexorluatex
can be
\newif\ifxetexorluatex % a new conditional starts as false
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi>0
\xetexorluatextrue
\fi
A much more general implementation using 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}
Running from the shell the following commands
> pdflatex engines >> engines.out
> xelatex engines >> engines.out
> lualatex engines >> engines.out
> platex engines >> engines.out
results in the following engines.out
file (edited to show only the relevant parts)
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) )
[...]
A different solution, with perhaps a better syntax, at the expense of expandability (until we will have e
-expansion available).
\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}
The output is the same as before.
In such situations, the generic \ifboolexpr
wrapper provided by the etoolbox
package comes in handy:
\usepackage{etoolbox,ifxetex,ifluatex}
\ifboolexpr{bool{xetex} or bool{luatex}}{%
<true-code>%
}{%
<false-code>%
}
The bool operator that works with the \ifboolexpr
syntax to perform boolean tests operates on all primitive style TeX conditionals. Note that it omits the \if
prefix of the original \ifxetex
and \ifluatex
commands.
Sometimes this sort of issue is easier to solve by changing the order of checking things.
\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}