# how to create switch structure comparing strings in latex

I want to process options that get passed to a package with kvoptions.

The string is then saved in \bugs@errorlevel. I want to test if it contains one of [info, warning, error] and set a command accordingly.

I could think of setting a bool variable to false and test as long as it has been set true or remains false. That could be done by cascading if expressions.

Testing strings for being equal can for example be done with etoolbox's \ifstrequal or xstring's \IfStrEq. Both are of the \ifthen package type using brackets.

On the other hand a 'real' switch could be done with the package boolexpr. However in that case I need commands which return a pure bool expression, which neither of the above commands do. The sequence principle would be:

\switch
\case{6>1 \AND 6<=5}$\geq 1$ and $\leq 5$%
\case{3<10}$> 5$ and $< 10$%
\case{3>10}$\geq 10$%
\endswitch


However I do not now what to enter in the case structure for comparison of strings. In the end it should be something like

\switch
\case{\isequal{\bugs@errorlevel}{info}}
\renewcommand\tplbugs@BugAction[1]{\PackageInfo{templatebugs}{#1}{}}%
\case{\isequal{\bugs@errorlevel}{warning}}
\renewcommand\tplbugs@BugAction[1]{\PackageWarning{templatebugs}{#1}{}}%
\case{\isequal{\bugs@errorlevel}{error}}
\renewcommand\tplbugs@BugAction[1]{\PackageError{templatebugs}{#1}{}}%
\otherwise
\PackageError{templatebugs}{
\MessageBreak
value >\bugs@errorlevel< unkown \MessageBreak
possible values are: info,warning,error. \MessageBreak
}{}
\endswitch


but that code does not work, since \isequal does not exist.

-
It seems that etoolbox and boolexpr are not compatible. Is it the case for you ? –  Colas Oct 14 '11 at 11:18

In a similar vein to Andrey's answer, but sticking with a wrapper that works with boolexpr

\documentclass{article}
\usepackage{boolexpr,pdftexcmds,trace}
\makeatletter
\long\def\isequal#1#2{\pdf@strcmp{#1}{#2}}
\def\bugs@errorlevel{error}
\def\tplbugs@BugAction#1{}
\switch
\case{\isequal{\bugs@errorlevel}{info}}
\renewcommand\tplbugs@BugAction[1]{\PackageInfo{templatebugs}{#1}{}}%
\case{\isequal{\bugs@errorlevel}{warning}}
\renewcommand\tplbugs@BugAction[1]{\PackageWarning{templatebugs}{#1}{}}%
\case{\isequal{\bugs@errorlevel}{error}}
\renewcommand\tplbugs@BugAction[1]{\PackageError{templatebugs}{#1}{}}%
\otherwise
\PackageError{templatebugs}{
\MessageBreak
value >\bugs@errorlevel< unkown \MessageBreak
possible values are: info,warning,error. \MessageBreak
}{}
\endswitch
\show\tplbugs@BugAction

-

You can use the pdfTeX's primitive \pdfstrcmp. Quoting the pdfTeX manual:

This command compares two strings and expands to 0 if the strings are equal, to -1 if the first string ranks before the second, and to 1 otherwise.

Moreover, the package pdftexcmds provides a similar \pdf@strcmp command that works for all TeX engines.

So, the proof-of-concept code is:

\documentclass{article}

\usepackage{pdftexcmds}

\makeatletter
\newcommand{\switch}[1]{%
\ifnum\pdf@strcmp{#1}{info}=0
first%
\else\ifnum\pdf@strcmp{#1}{warning}=0
second%
\else\ifnum\pdf@strcmp{#1}{error}=0
third%
\else
unknown%
\fi\fi\fi}
\makeatother

\begin{document}

\switch{info}
\switch{warning}
\switch{error}
\switch{something}

\end{document}


If you want to go the old TeX way, you can use the \ifx conditional, which tests for equality of tokens. If the two following tokens after \ifx are macros, their parameter text and replacement text is compared.

\documentclass{article}

\def\infotext{info}
\def\warningtext{warning}
\def\errortext{error}
\newcommand{\switch}[1]{%
\begingroup
\def\tmp{#1}%
\ifx\tmp\infotext
first%
\else\ifx\tmp\warningtext
second%
\else\ifx\tmp\errortext
third%
\else
unknown%
\fi\fi\fi
\endgroup}

\begin{document}

\switch{info}
\switch{warning}
\switch{error}
\switch{something}

\end{document}



-
The problem with the \ifx approach is that it's not expandable. So it can't be used, for example, in boolexpr's \switch construction. –  Joseph Wright Sep 21 '11 at 19:17

An implementation with expl3:

\documentclass{article}
\usepackage{expl3}
\makeatletter
\def\bugs@errorlevel{info} % change for testing

\ExplSyntaxOn
\prg_case_str:onn { \bugs@errorlevel }
{
{info}    { \providecommand\tplbugs@BugAction[1]{\PackageInfo{templatebugs}{#1}} }
{warning} { \providecommand\tplbugs@BugAction[1]{\PackageWarning{templatebugs}{#1}} }
{error}   { \providecommand\tplbugs@BugAction[1]{\PackageError{templatebugs}{#1}} }
}
{
% set a default
\providecommand\tplbugs@BugAction[1]{\PackageError{templatebugs}{#1}}
% issue an error
\PackageError{templatebugs}
{
\MessageBreak
value~>\bugs@errorlevel<~unkown \MessageBreak
possible~values~are:~info,~warning,~error.
}
{
The~value~must~be~one~of~info',~warning',~or~error';
\MessageBreak