3

How can I test for a not defined boolean?

I want to have

\usepackage{xr-hyper}
\usepackage{hyperref}

\providebool{is_single_book}
\booltrue{is_single_book}

in my main.tex and in each of the chapter TeX files.

if not defined is_single_book
  \externaldocument{volume1}[http://mybook.com/volume1.pdf]
fi

So when I compile the entire book, \externaldocument{volume1}[http://mybook.com/volume1.pdf] isn't executed.

It doesn't have to be a boolean if something else is simpler or doesn't require an extra package.

  • Why do you want "is not defined" rather than "true" and "false"? Does a package specify that boolean? – TeXnician Aug 16 '18 at 11:06
  • 3
    So you essentially want a three-way switch: boolean undefined, boolean true and boolean false? Or can you simplify this to a simple two-valued logic with a true and false boolean? Since you use etoolbox commands you can use \ifcsundef{ifis_single_book}{<undef>}{<def>} to check if the boolean is_single_book is undefined. Note that \providebool makes sure the boolean is defined, so \ifcsundef{ifis_single_book} will execute the false branch. – moewe Aug 16 '18 at 11:06
6

While you could check if a bool is defined by using \ifcsundef{if...} (see comment from moewe), it looks as if you actually want a boolean which is always false if you are in a chapter tex file.

This can be archived by using \providebool, which defines the bool as false, iff is is not defined already:

Use

\newbool{is_single_book}
\booltrue{is_single_book}

in your main file and

\providebool{is_single_book}
\ifbool{is_single_book}{}{%
  \externaldocument{volume1}[http://mybook.com/volume1.pdf]%
}

in your chapter files.

Even better would be to use toggles. They are almost the same but avoid name clashes and provide slightly better performance:

To use them, insert

\newtoggle{is_single_book}
\toggletrue{is_single_book}

in your main file and

\providetoggle{is_single_book}
\iftoggle{is_single_book}{}{%
  \externaldocument{volume1}[http://mybook.com/volume1.pdf]%
}

in the chapters.

  • +1 for toggles. – moewe Aug 16 '18 at 11:28
  • Something seams to be wrong for the chapters part. \externaldocument{volume1}[http://mybook.com/volume1.pdf] isn't being executed. Is is_single_book true or fasle right after \providetoggle{is_single_book}? – Sandra Schlichting Aug 16 '18 at 12:34
  • \externaldocument{volume1}[http://mybook.com/volume1.pdf] should be executed if is_single_book is false or undefined. – Sandra Schlichting Aug 16 '18 at 12:37
6

\providebool and \booltrue makes me think you are using etoolbox.

etoolbox booleans are just a thin wrapper around TeX's \newif.

That means that \newbool{<name>} defines \if<name>, so you can check if a boolean is defined by checking if \if<name> is defined.

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{etoolbox}

\newcommand*{\ifboolundef}[1]{\ifcsundef{if#1}}

\newcommand*{\sabooleantest}[1]{%
  bool \ttfamily{#1} is
  \ifboolundef{#1}
    {undefined}
    {\ifbool{#1}
       {true}
       {false}}}

\begin{document}
\sabooleantest{flobbel}

\newbool{globbel}
\boolfalse{globbel}
\sabooleantest{globbel}

\newbool{hobbel}
\booltrue{hobbel}
\sabooleantest{hobbel}
\end{document}

bool flobbel is undefined

bool globbel is false

bool hobbel is true

The question is whether you really need something that comes down to a three-valued logic. Is a two-valued boolean not enough?

If you want to avoid problems in case the boolean is undefined, you could just check if a macro is undefined or defined. This also has two states, but unlike with booleans there are no errors if the thing is not defined.

\newcommand*{\mybool}{}
\ifcsundef{\mybool}
  {not defined}
  {defined}

You could also define 'permissive toggles' that are false if they don't exist

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{etoolbox}

\newcommand*{\permissivetoggletrue}[1]{\csletcs{sa@ptogl@#1}{@empty}}
\newcommand*{\permissivetogglefalse}[1]{\csundef{sa@ptogl@#1}}
\newcommand*{\ifpermissivetoggle}[1]{\ifcsdef{sa@ptogl@#1}}

\begin{document}
flobbel
\ifpermissivetoggle{flobbel}
  {true}
  {false}

\permissivetoggletrue{globbel}
globbel
\ifpermissivetoggle{globbel}
  {true}
  {false}
\end{document}

This can also be done without etoolbox if you like those sort of things

\makeatletter
\newcommand*{\permissivetoggletrue}[1]{%
  \expandafter\let\csname sa@ptogl@#1\endcsname\@empty}
\newcommand*{\permissivetogglefalse}[1]{%
  \expandafter\let\csname sa@ptogl@#1\endcsname\@sa@undef}% this assumes \@sa@undef is undefined
\newcommand*{\ifpermissivetoggle}[1]{%
  \ifcsname sa@ptogl@#1\endcsname
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}
\makeatother
  • I were only using etoolbox for this one thing, so if this package can be avoided, then it would be much appreciated. – Sandra Schlichting Aug 16 '18 at 11:34
  • 2
    @SandraSchlichting Theoretically especially in my last two examples we could do away with etoolbox, but I would end up essentially copying (a bit of) code from that package, so why not load it? – moewe Aug 16 '18 at 11:38
  • I see. Good point. – Sandra Schlichting Aug 16 '18 at 11:42
0

It doesn't have to be a boolean, if something else is simpler or doesn't require an extra package.

I think \ifdefined and \def provide what you're looking for. You don't need an extra package or any definition.

In your main document, write

\def\isSingleBook{}

or, alternatively, \newcommand{\isSingleBook}{} or \providecommand{\isSingleBook}{}.

Then you can check with:

\ifdefined\isSingleBook
  %% you're in the book
\else
  %% you're not in the book
\fi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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