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.

4
  • You can look in the direction of ifthen, or did I understand you wrong? Jul 20, 2022 at 15:23
  • 1
    well you can easily define such a test, but it looks like a rather curious interface. I would never expect a command called \myalert to gobble its argument. Jul 20, 2022 at 15:28
  • @UlrikeFischer and Oleg, thank you. I managed to use the ifthen package for this. My ALERT command was rather an example, but my use is not too far from that (at least mechanically).
    – kloop
    Jul 20, 2022 at 15:42

3 Answers 3

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}
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

3
  • 2
    never do \edef on a user input. Jul 20, 2022 at 15:34
  • You are right, it should work with \def as well. Jul 20, 2022 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} Jul 21, 2022 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.

You must log in to answer this question.

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