1

I have a simple macro that I want to define as

\newcommand{\myalert}[1]{\textcolor{red}{ALERT: #1}}

However, I want to have a conditional such that if #1 is one of two strings (say "noalert" and "null"), then the macro is instead equivalent to ignoring #1 and eating it up:

\newcommand{\myalert}[1]{}

I am not sure to what extent such conditionals are allowed in latex in defining commands.

kloop
  • 9,684

3 Answers3

7

Here is a possibility using \str_case:nnF:

\documentclass{article}
\usepackage{xcolor}

\ExplSyntaxOn

\NewDocumentCommand \myalert { m } { \str_case:nnF {#1} { { noalert } { } { null } { } } { \textcolor{red}{ALERT:~#1} } }

\ExplSyntaxOff

\begin{document}

\noindent \myalert{fire!}\ \myalert{water!}\ X\myalert{noalert}\myalert{null}X\ \myalert{earthquake!}

\end{document}

enter image description here

The same without the expl3 category codes, in case you are uncomfortable with them:

\documentclass{article}
\usepackage{xcolor}

\ExplSyntaxOn \cs_new_eq:NN \strcasennF \str_case:nnF \ExplSyntaxOff

\NewDocumentCommand \myalert { m } {% \strcasennF {#1} { {noalert} {} {null} {} } {\textcolor{red}{ALERT: #1}}% }

\begin{document}

\noindent \myalert{fire!}\ \myalert{water!}\ X\myalert{noalert}\myalert{null}X\ \myalert{earthquake!}

\end{document}

frougon
  • 24,283
  • 1
  • 32
  • 55
4

With pure (La)TeX:

\documentclass{article}
\usepackage{xcolor}

\newcommand{\myalert}[1]{% \def\compareA{#1}% \def\compareB{noalert}% \def\compareC{null}% \ifx\compareA\compareB\else% \ifx\compareA\compareC\else% \textcolor{red}{ALERT: #1}% \fi% \fi% }

\begin{document}

\myalert{hello}

\myalert{null}

\myalert{noalert}

\myalert{bye}

\end{document}

enter image description here

  • 2
    never do \edef on a user input. – Ulrike Fischer Jul 20 '22 at 15:34
  • You are right, it should work with \def as well. – Jasper Habicht Jul 20 '22 at 15:36
  • 2
    I suggest doing scratch-assignments for comparison only if this is needed. This way you can re-use one of the names of the scratch-macros which affects memory-consumption in TeX/LaTeX: \newcommand{\myalert}[1]{\def\compareA{#1}\def\compareB{noalert}\ifx\compareA\compareB\else\def\compareB{null}\ifx\compareA\compareB\else\textcolor{red}{ALERT: #1}\fi\fi} – Ulrich Diez Jul 21 '22 at 17:31
2

You did not specify what behavior you wish to have if things are wrapped in \MakeUppercase/\MakeLowercase/\uppercase/\lowercase.

If you are not comfortable with temporary macros and \ifx..\else..\fi for whatsoever reason and like "oldschool-coding", then you can, e.g., do this fully expandable by means of delimited arguments.

\makeatletter
%%=============================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo, \UD@CheckWhetherNull,
%%    \UD@CheckWhetherBlank
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{%
  \expandafter\UD@stopromannumeral\UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument is blank, i.e., is empty or consists of space tokens
%% only:
%%.............................................................................
%% -- Take advantage of the fact that TeX discards space tokens when
%%    "fetching" _un_delimited arguments: --
%% \UD@CheckWhetherBlank{<Argument which is to be checked>}%
%%                      {<Tokens to be delivered in case that
%%                        argument which is to be checked is blank>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked is not blank>}%
\newcommand\UD@CheckWhetherBlank[1]{%
  \romannumeral\expandafter\expandafter\expandafter\UD@secondoftwo
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo#1{}{}}%
}%
%%=============================================================================
\@ifdefinable\UD@GobbleToExclam{\long\def\UD@GobbleToExclam#1!{}}%
%
\newcommand\myalert[1]{%
  \UD@CheckWhetherBlank{#1}{% #1 is blank, i.e., either empty or space tokens only
  }{%  #1 is not blank
    \expandafter\UD@CheckWhetherNull\expandafter{\UD@GobbleToExclam#1!}{%
       \ForkNoalertNullElse
       !#1!null!{}% #1 = noalert
       !noalert!#1!{}% #1 = null
       !noalert!null!{\textcolor{red}{ALERT: #1}}% #1 s. th. else withhout !
       !!!!%
    }{\textcolor{red}{ALERT: #1}}% #1 s. th. else with !
  }%
}%
\@ifdefinable\ForkNoalertNullElse{\long\def\ForkNoalertNullElse#1!noalert!null!#2#3!!!!{#2}}%
\makeatother

\documentclass{article} \usepackage{xcolor} \colorlet{RED}{red}

\begin{document}

\begin{tabular}{ll} \textbf{Command}&\textbf{Result}\ \hline \verb|(\myalert{Some text})|&(\myalert{Some text})\ \verb|(\myalert{Some ! text})|&(\myalert{Some ! text})\ \verb|(\myalert{Some {more} text})|&(\myalert{Some {more} text})\ \verb|(\myalert{})|&(\myalert{})\ \verb|(\myalert{ })|&(\myalert{ })\ \verb|(\myalert{noalert})|&(\myalert{noalert})\ \verb|(\myalert{null})|&(\myalert{null})\ \verb|\MakeUppercase{(\myalert{Some text})}|&\MakeUppercase{(\myalert{Some text})}\ \verb|\MakeUppercase{(\myalert{null})}|&\MakeUppercase{(\myalert{null})}\ \verb|\uppercase{(\myalert{Some text})}|&\uppercase{(\myalert{Some text})}\ \verb|\uppercase{(\myalert{null})}|&\uppercase{(\myalert{null})} \end{tabular}

\end{document}

enter image description here

Notice the behavior when things are wrapped in \uppercase:
Uppercasing null yields NULL which is not the same as null, thus an alert-message with NULL as its argument is delivered.

Ulrich Diez
  • 28,770