I try do define a macro \onoff, which alternatively prints "on" and "off" each time it's used. For example the sequence \onoff \onoff \onoff would print on off on

My first guess would be to use the following code:

\def\a{on}
\def\b{off}    
\newcommand\onoff{\a\def\c{\a}\def\a{\b}\def\b{\c}}

However this code doesn't work. Is there an elegant way to code this?

  • now I can reveal that you were quite close to a working solution: \def\onoff{\a\let\c\a\let\a\b\let\b\c} in your set-up works. – jfbu Mar 8 '15 at 21:27
  • @jfbu, in this simple case, I think that \edef would do as well. – LSpice Mar 9 '15 at 0:26
  • Laurent, I am sure that you know, but of course the problem is that \def\c{\a} says "define \c to expand to \a" (thus eventually to the future contents of \a), not "… to the (current) contents of \a". \let essentially says the latter. \edef expands macros at definition time rather than use time, which is why it would also work here. – LSpice Mar 9 '15 at 0:29
  • @LSpice yes, totally true. – jfbu Mar 9 '15 at 11:19
up vote 20 down vote accepted

One way

\documentclass{article}

\makeatletter
\def\@ONoff {on\let\onoff\@onOFF}
\def\@onOFF {off\let\onoff\@ONoff}
\let\onoff\@ONoff
\makeatother

\begin{document}

\onoff\onoff\onoff\onoff\onoff\onoff...

\end{document}

onoffonoffon

Another way (was a now deleted separate answer)

\documentclass{article}

\makeatletter
\def\onoff{\@onoff{on}{off}}
\def\@onoff #1#2{#1\def\onoff {\@onoff{#2}{#1}}}
\makeatother

\begin{document}\thispagestyle{empty}

\onoff\onoff\onoff\onoff\onoff\onoff...

\end{document}

onoffonoffon

A third way

\documentclass{article}

\makeatletter
\def\onoff {\onoroff{on\let\onoroff\@secondoftwo}{off\let\onoroff\@firstoftwo}}
\let\onoroff\@firstoftwo
\makeatother

\begin{document}

\onoff\onoff\onoff\onoff\onoff\onoff\onoff...

\onoff\onoff\onoff\onoff\onoff...

\end{document}

more on off

  • 2
    This is really clever :) Reminds me of heeeeeeeey.com – Sean Allred Mar 8 '15 at 20:11
  • This is the answer I was about to write. While there is a lot of other possibilities, this one is definitely the most TeXy. – Michael Le Barbier Grünewald Mar 8 '15 at 20:23
  • 1
    @SeanAllred I will adopt heeeeeeeey.com as a perfect alarm clock ... how many days before the asylum ? – jfbu Mar 8 '15 at 20:27
  • 1
    @jfbu Two weeks – max :) – Sean Allred Mar 8 '15 at 20:29

Using etoolbox and bools and the greatest TikZ-foo i have ever produced.

laurentOnOff

\documentclass{article}
\usepackage{etoolbox}
\usepackage{parskip}
\usepackage{tikz}
\newbool{volt}
\newcommand{\onoff}{%
    \ifbool{volt}{%
\boolfalse{volt}\candleOn\space ON}{%
    \booltrue{volt}\candleOff\space OFF}%
}
\newcommand{\candleOff}{\tikz \draw (0,0) rectangle
(.2,.8);}
\newcommand{\candleOn}{\begin{tikzpicture}\draw (0,0) rectangle
(.2,.8);\draw [fill=orange] (.1,.9) circle
[radius=.1];\end{tikzpicture}}
\begin{document}
\onoff\par
\onoff\par
\onoff\par
\onoff\par
\end{document}
  • What advantage to etoolbox's bools have (in functionality or readability) over the similar use of conditionals described by @egreg below (tex.stackexchange.com/a/232062/1169)? (Of course, egreg's answer doesn't include the stunning TikZ-foo. :-) ) – LSpice Mar 9 '15 at 0:24
  • 1
    The advantage of one solution over the other is a matter of taste, imho. etoolbox gives a bunch of higher-level commands, no need for @-catcode hackery in most cases. Features like the ones described in the answers here are mostly needed by class/package authors, users just the functionality of the end result (on/off). – Johannes_B Mar 9 '15 at 8:10

Use a conditional

\documentclass{article}

\newif\ifoff
\newcommand{\onoff}{%
  \relax\ifoff off\global\offfalse\else on\global\offtrue\fi
}

\begin{document}

\onoff

\onoff

\onoff

\end{document} 

or a counter

\documentclass{article}

\newcount\offcount
\newcommand{\onoff}{%
  \relax
  \ifodd\offcount
    \global\advance\offcount 1
    off%
  \else
    \global\advance\offcount -1
    on%
  \fi
}

\begin{document}

\onoff

\onoff

\onoff

\end{document}

In both cases, if you want only local redefinitions, remove \global.

Note the starting \relax, necessary if you want to use \onoff in tables.

An abstract version, with the help of etoolbox that makes things a bit easier with toggles (it could be realized with conditionals).

\documentclass{article}
\usepackage{etoolbox}

\newcommand{\newalternatingcommand}[3]{%
  \newcommand{#1}{%
    \iftoggle{\string#1}
      {#2\global\togglefalse{\string#1}}
      {#3\global\toggletrue{\string#1}}%
  }%
  \newtoggle{\string#1}%
  \toggletrue{\string#1}%
}

\newalternatingcommand{\onoff}{on}{off}

\begin{document}

\onoff

\onoff

\onoff

\end{document}
  • What's the advantage / feature of etoolbox's \iftoggle vs. \ifbool? – Manuel Mar 9 '15 at 10:11
  • @Manuel \iftoggle uses just one control sequence, while \ifbool uses three. But the advantage is mostly in the fact we can use \string#1 in the argument of \iftoggle and a simpler syntax for the two cases. – egreg Mar 9 '15 at 10:20

For example:

\def\onoffA{on\gdef\onoff{off\global\let\onoff=\onoffA}} \let\onoff=\onoffA

Test: \onoff, \onoff, \onoff, \onoff, \onoff, \onoff.

\bye

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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