9

I created some kind of switch statement with a help of \ifthenelse command. Now, I would like to pass its output to another command. In my example I want to colorize each sentence with a color specified by a number. My code is:

\documentclass{article}

\usepackage{ifthen}
\usepackage{color}

\newcommand{\num}{1}

 \newcommand{\mySwitch}[1]{
 \ifthenelse{#1=1}{red}{        % color no 1 is red
 \ifthenelse{#1=2}{blue}{}}}    % color no 2 is blue ... and so on 

\begin{document}

\color{\mySwitch{\num}}
\mySwitch{\num} is the color no \num.

\renewcommand{\num}{2}
\color{\mySwitch{\num}}
\mySwitch{\num} is the color no \num.

\end{document}

I would like to obtain something like this:

enter image description here

but the result of compilation is:

enter image description here

What is more, I keep getting a number of errors from which the first one is

Missing \endcsname inserted \color{\NoToColor{\num}}.

I suppose the proper solution should have something to do with \expandafter command but simply putting

 \expandafter\color\expandafter{\mySwitch{\num}} 

gives no results. I must be missing something but I can't get it to work and I can't find any similar example. Please give some hints.

2
  • Welcome to TeX.SX! You need a fully expandable token list as the argument to \color, which unfortunately \ifthenelse isn't.
    – egreg
    Jul 21, 2014 at 21:01
  • Since you know you're dealing with number comparisons, instead of an \ifthenelse{#1=X}{<true>}{<false>}, you can use \ifnum#1=X <true> \else <false> \fi construction.
    – Werner
    Jul 21, 2014 at 21:05

2 Answers 2

4

We need expanable switch statement. When egreg use \ExplSyntaxOn ... \ExplSyntaxOff then I can use NormalTeXSyntaxOn ... NormalTeXSynatxOff in my example, because NormalTeXSyntax is more natural than whatever else syntax. It is syntax of TeX program itself. If you know this syntax well then you needn't to know any other syntax.

I hope that somebody will understand me...

\documentclass{article}
\usepackage{color}

% NormalTeXSyntaxON
\def\setcase#1 {\expandafter\def\csname col:#1\endcsname}
\def\mySwitch#1{\expandafter\ifx\csname col:#1\endcsname\relax \coldefault 
                \else \csname col:#1\endcsname\fi}

\def\coldefault {black}    
\setcase 1      {red} 
\setcase 2      {blue}  
\setcase word   {green}

% NormalTeXSyntaxOff

\begin{document}

\newcommand\num{1}
\color{\mySwitch{\num}}
\mySwitch{\num} is the color no \num.

\renewcommand\num{2}
\color{\mySwitch{\num}}
\mySwitch{\num} is the color no \num.

\renewcommand\num{word}
\color{\mySwitch{\num}}
\mySwitch{\num} is the color no \num.

\end{document}

I mean that the accepted solution here is overkilled. The \usepackage{xparse} used in this solution reads 24 files with 16648 lines in total but my solution needs only three lines without any aditional packages. The effect of both solutions are the same. But people tend to select more complicated solutions here. Unfortunatelly.

6
  • Of course the \str_case:onF method allows any string to be used, not only numbers. In this particular case I can't see any advantage: my code is even more compact than yours, because it relies on a powerful base.
    – egreg
    Jul 22, 2014 at 14:33
  • @egreg If the author of the question needs to convert strings to strings (i.e. to implement a dictionary) then we have commands \csname and \endcsname in the NormalTeXSyntaxOn. The most powerfull base is the TeX itself. Anothers stuff is only derived from this base.
    – wipet
    Jul 22, 2014 at 15:30
  • I know very well that one can use simple macros; but why reinventing the wheel each time?
    – egreg
    Jul 22, 2014 at 15:59
  • @egreg Because if peole know very well how the wheel is done and they use these basis not only as black-box then 95 % questioins here at tex.sx.com lose a sense.
    – wipet
    Jul 22, 2014 at 16:11
  • @wipet I fully agree with your argumentation. The simpler solution the better. But why did you delete the first solution? And what was the difference between deleted solution and the one you left. I mean the difference for a common LaTeX user as me. Jul 23, 2014 at 10:34
8

The argument to \color (when called without the optional color space argument) must directly expand to a string of characters, which should be a color name (or a tint specification if xcolor is used).

There are several expandable switch statement available. I suggest one using expl3:

\documentclass{article}
\usepackage{xparse}
\usepackage{color}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\mySwitch}{m}
 {
  \martino_switch:n { #1 }
 }

\cs_new:Npn \martino_switch:n #1
 {
  \str_case:onF { #1 } % expand once the argument
   {
    {1}{red}
    {2}{blue}
   }
   {black} % none of the above
 }
\ExplSyntaxOff

\begin{document}

\newcommand{\test}{1}

\textcolor{\mySwitch{\test}}{Some text}

\renewcommand{\test}{2}
\textcolor{\mySwitch{\test}}{Some text}

\end{document}

enter image description here

As you see, adding new cases is quite easy.

The strings are not limited to numbers:

\documentclass{article}
\usepackage{xparse}
\usepackage{color}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\mySwitch}{m}
 {
  \martino_switch:n { #1 }
 }

\cs_new:Npn \martino_switch:n #1
 {
  \str_case:onF { #1 } % expand once the argument
   {
    {1}{red}
    {2}{blue}
    {zot}{yellow}
   }
   {black} % none of the above
 }
\ExplSyntaxOff

\begin{document}

\newcommand{\test}{1}

\textcolor{\mySwitch{\test}}{Some text}

\renewcommand{\test}{2}
\textcolor{\mySwitch{\test}}{Some text}

\renewcommand{\test}{zot}
\textcolor{\mySwitch{\test}}{Some text}

\renewcommand{\test}{blurb}
\textcolor{\mySwitch{\test}}{Some text}

\end{document}

enter image description here

2
  • It seems that the second piece of your code is the same as the first one. Maybe a second with the lost of concentration. Maybe due to my joke about TeXnormalSyntaxOn...
    – wipet
    Jul 22, 2014 at 15:48
  • @wipet Thanks for noting; I just forgot a pbcopy<colstr.tex, so I pasted the same version that I used for preparing the new example.
    – egreg
    Jul 22, 2014 at 15:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .