System Macros/Branches and Decisions

From Wiki
Jump to navigation Jump to search

< Prev: Definitions & Assignments | Top: System Macros | Next: Loops and Recursion >


When Pragma ADE started using TeX in the late eighties, their first experiences with programming concerned a simple shell around LaTeX. The commands probably used most at Pragma ADE are the itemizing ones. One of those initial shell commands took care of an optional argument, that enabled the specification of the item symbol to be used. Without understanding anything they were able to locate a LaTeX macro that could be used to inspect the next character.

It is that macro that the ancester of the next one presented here. It executes one of two actions, dependant of the next character. Disturbing spaces and line endings, which are normally interpreted as spaces too, are skipped.

\doifnextcharelse {char} {then ...} {else ...}

\doifundefined, \doifdefined, etc.

The standard way of testing if a macro is defined is comparing its meaning with another undefined one, aptly named \undefined. To guarantee correct working of this set of macros, \undefined may never be defined by a user!

\doifundefined      {string}    {...}
\doifdefined        {string}    {...}
\doifundefinedelse  {string}    {then ...} {else ...}
\doifdefinedelse    {string}    {then ...} {else ...}
\doifalldefinedelse {commalist} {then ...} {else ...}

\doif, \doifnot, \doifelse

Programming in TeX differs from programming in procedural languages like Modula. This means that one --- well, let me speek for myself --- tries to do the things in the well known way. Therefore the next set of \ifthenelse commands were between the first ones we needed. A few years later, the opposite became true: when programming in Modula, I sometimes miss handy things like grouping, runtime redefinition, expansion etc. While Modula taught me to structure, TeX taught me to think recursive.

\doif     {string1} {string2} {...}
\doifnot  {string1} {string2} {...}
\doifelse {string1} {string2} {then ...}{else ...}

These macros test string equality of the (expanded) first two arguments.

\doifempty, \doifnotempty, \doifemptyelse

We complete our set of conditionals with:

\doifempty     {string} {...}
\doifnotempty  {string} {...}
\doifemptyelse {string} {then ...} {else ...}

This time, the string is not expanded. Remember to expand it yourself where needed.

\doifinset, \doifnotinset, \doifnotinsetelse

We can check if a string is present in a comma separated set of strings. Depending on the result, some action is taken.

\doifinset     {string} {string,...} {...}
\doifnotinset  {string} {string,...} {...}
\doifinsetelse {string} {string,...} {then ...} {else ...}

The second argument is the comma separated set of strings. If the first string expands 'empty', it is considered to be not in the set. The comma separated set is not expanded.

\doifcommon, \doifnotcommon, \doifnotcommon

Probably the most time consuming tests are those that test for overlap in sets of strings.

\doifcommon     {string,...} {string,...} {...}
\doifnotcommon  {string,...} {string,...} {...}
\doifcommonelse {string,...} {string,...} {then ...} {else ...}


The next comparison macro converts the arguments into expanded strings. This command can be used to compare for instance \jobname with a name stored in a macro.


We can check for the presence of a substring in a given sequence of characters.

\doifinstringelse {substring} {string} {then ...} {else ...}

The next alternative proved to be upto twice as fast on tasks like checking reserved words in pretty verbatim typesetting. This is mainly due to the fact that passing (expanded) strings is much slower that passing a macro.

\doifincsnameelse {substring} {\string} {then ...} {else ...}

Where \doifinstringelse does as much expansion as possible, the latter alternative does minimal (one level) expansion.


The next macro executes a command depending of the outcome of a test on numerals.It checks only the first character of string.

\doifnumberelse {string} {then ...} {else ...}

The macro accepts 123, abc, {}, \anumber and \the\count....

The definition of this macro is extremly ugly, or extremely beautiful, depending on how you feel about TeX macro expansion. It is the first of only a few that will actually appear in this series of articles, I promise.



A lot of ConTeXt commands take optional arguments, for instance:


Although a combined solution is possible, we prefer a seperation. The next command takes care of propper handling of such multi-faced commands.

\doifassignmentelse {...} {then ...} {else ...}

< Prev: Definitions & Assignments | Top: System Macros | Next: Loops & Recursion >