Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I want to write in the preamble of a LaTeX document code that should be take into account by different compilers when the document is typeset. There are fragments that should be used:

  • only by xelatex
  • only by lualatex
  • only by xelatex or lualatex
  • only by pdflatex

I am using the packages ifxetex and ifluatex that provide the commands \ifxetex and \ifluatex, respectively.

How can I logically combine these commands in a disjunction (or operation)?

The code would be something like:

\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

Any help?

share|improve this question

5 Answers 5

up vote 21 down vote accepted
\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
share|improve this answer
    
Sorry, but \ifxetexorluatex will not distinguish between XeTeX and LuaTeX - which Romildo wants. –  Martin Schröder Mar 10 '12 at 23:40
7  
@MartinSchröder Of course it won't, how could it? For XeTeX or LuaTeX specific code, \ifxetex and \ifluatex can still be used; where's the problem? Romildo wanted a conditional to distinguish between (XeTeX or LuaTeX) and pdfTeX. –  egreg Mar 10 '12 at 23:46
3  
A safer version of the catcode trick (only if \scantokens is available) is \begingroup\catcode94=7\catcode0=9\catcode30=12\catcode48=12\everyeof{\noexpand‌​}\expandafter\endgroup\if\scantokens{^^^^0000}??\xetexorluatextrue\else\xetexorlu‌​atexfalse\fi. –  Bruno Le Floch Mar 11 '12 at 10:49

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.

share|improve this answer

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}
share|improve this answer
2  
Won't this approach fail if the tex file happens to be compiled under a TeX format other than pdflatex, xelatex, or lualatex? –  Mico Mar 11 '12 at 3:14
    
@Mico The OP only wanted to check for this, but in general it wouldn't, provided your code is common to all, otherwise you build more checks \ifvtex etc... –  Yiannis Lazarides Mar 11 '12 at 3:59
1  
IIRC, \ifpdf checks the output mode not the engine, so it is true for pdftex or luatex in pdf mode and false otherwise. –  Khaled Hosny Mar 11 '12 at 5:26
    
@KhaledHosny The example compiles correctly for the pdfLaTeX, LuaLaTeX and XeLaTeX. It will fail in all other cases due to the documentclass{}. –  Yiannis Lazarides Mar 11 '12 at 5:40
3  
lualatex '\RequirePackage{ifpdf}\show\ifpdf' produces \ifpdf=\iftrue –  egreg Mar 11 '12 at 9:26

probably I'd advise going with @egreg's answer but an alternative way of combining \if conditionals (which essentially isthe way \ifthenelse \OR works) is shown as follows, using \ifA and \ifB as it works generally not for the engine tests.

\newif\ifA
\newif\ifB

\Atrue\Btrue\typeout{true true}

\if!\ifA!\else\ifB!\else?\fi\fi

\typeout{A or B}

\else

\typeout {neither A nor B}

\fi

\Atrue\Bfalse\typeout{true false}

\if!\ifA!\else\ifB!\else?\fi\fi

\typeout{A or B}

\else

\typeout {neither A nor B}

\fi


\Afalse\Btrue\typeout{false true}

\if!\ifA!\else\ifB!\else?\fi\fi

\typeout{A or B}

\else

\typeout {neither A nor B}

\fi

\Afalse\Bfalse\typeout{false false}

\if!\ifA!\else\ifB!\else?\fi\fi

\typeout{A or B}

\else

\typeout {neither A nor B}

\fi



\stop
share|improve this answer
    
What is the meaning of the characters ! and ? that appear in \if!\ifA!\else\ifB!\else?\fi\fi? –  Romildo Mar 11 '12 at 11:33
    
any two characters will do so long as they are not the same. If for example ifA is true and ifB is false \ifA!\else\ifB!\else?\fi\fi expands to ! so the outer \if is \if!! which is true. By adjusting which characters are returned you can make other logical connectives such as and or exclusive or –  David Carlisle Mar 11 '12 at 11:36

For the fun of it, possibly the shortest way:

\documentclass{article}
\usepackage{ifxetex,ifluatex}
\begin{document}

hello

\ifx\ifxetex\ifluatex\else
   xetex or luatex is true
\fi

\end{document}

Indeed, xetex and luatex are mutually exclusive. If the two conditionals coïncide, this must be because both are false. So the opposite is that one of the two is true, which was what was asked for.


As pointed out by egreg in a comment, this construction can not be used as is inside other conditionals (in case it ends up in the skipped branch). This alternative formulation does not have this defect:

\expandafter\ifx\csname ifxetex\expandafter\endcsname \csname ifluatex\endcsname\else 
xetex or luatex is true\fi
share|improve this answer
    
Hehe, I particularly like this one, very clever! (Unless someone comes up with a luaxetex engine, of course...) –  Daniel Oct 22 '13 at 21:49
    
@Daniel I would be more scared by an egreglisle mix... –  jfbu Oct 22 '13 at 21:51
    
This is nice, of course, but it can't be used in conditional text, if it belongs to the skipped over branch. Probably it should be used in the preamble to set a new conditional. –  egreg Feb 13 at 18:42
    
@egreg \ifx\ifxetex\ifluatex\else xetex or luatex is true \fi\@gobbletwo \fi \fi should do it but this is less simple. –  jfbu Feb 14 at 17:30
    
@egreg or perhaps \expandafter\ifx\csname ifxetex\expandafter\endcsname \csname ifluatex\endcsname\else xetex or luatex is true\fi. –  jfbu Feb 14 at 17:34

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.