Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I have a macro which holds some text value, e.g. \macro{some text}. If it is empty, I would like for nothing to appear in the document, but it has some content of any kind which would produce text displayed in the document, I would like a message to appear, "Text: some text".

  • \macro{} would be considered empty.
  • \def\somedata{}, \macro{\somedata} would be considered empty.
  • \macro{0} would be considered not empty.

I have tried making a TeX conditional which can check if the value is not empty, but nothing I tried works, e.g.:

\ifx #1 {}
\else
    Text: #1
\fi

\ifx#1{}
\else
    Text: #1
\fi

\ifx #1 \nil
\else
    Text: #1
\fi

\ifx#1!=""
\else
    Text: #1
\fi

What is the correct syntax for creating a conditional in plain TeX with checks if a value is not empty?

share|improve this question
    
Please, tell more clearly if "emptyness" is referred to the absence of tokens or to "no printed output": for instance, what should \mymacro{\empty} return? –  egreg Apr 24 '12 at 8:21
    
Empty means no printed output. \mymacro{\empty} should be considered empty. \mymacro{} should also be considered empty. –  Village Apr 24 '12 at 8:35
1  
Please, edit the question, then: as it stands you're asking how to test for an "empty argument" which is a very different thing. –  egreg Apr 24 '12 at 8:44

4 Answers 4

up vote 27 down vote accepted

(1) Tests for empty token list as input

You can try

\def\temp{#1\unskip}\ifx\temp\empty
  <EMPTY>%
\else
  <NON EMPTY>%
\fi

If you know that a token, say \hfuzz, will not appear in #1, then

\ifx\hfuzz#1\hfuzz
  <EMPTY>%
\else
  <NON EMPTY>%
\fi

This, differently from the previous test, is expandable.

The safest test uses e-TeX:

\if\relax\detokenize{#1}\relax
  <EMPTY>%
\else
  <NON EMPTY>%
\fi

Using this last one shouldn't be a problem, but be warned that it doesn't work with "Knuth TeX".

Comments

You should know also that \ifx compares the two tokens that follow it and has no = sign. Similarly, \if compares the two tokens that follow it, but after having done complete expansion.

So, how does the last test work? With \detokenize{#1} the argument is transformed into a sequence of characters of category code 12, none of which is \if-equivalent to \relax. Thus with empty #1 the test would compare \relax with \relax and so return True; with #1 non empty, say abc, the code would be

\if\relax abc\relax<EMPTY>\else<NOT EMPTY>\fi

and the comparison between \relax and a returns False, so only the <NOT EMPTY> code would remain.

(2) Test for no printed output

In order to test for no printed output you can't have an expandable test:

\setbox0=\hbox{#1\unskip}\ifdim\wd0=0pt
  <EMPTY>%
\else
  <NOT EMPTY>%
\fi

This assumes that #1 doesn't contain vertical material, such as \vfill. Remove the \unskip if also "space output" should be considered. However, this can go wrong when \mymacro{\hskip1pt\hskip1pt} is called; it mostly depends on what you expect to go in the argument how to cope with limit cases.

share|improve this answer
    
if there is a space between the braces in your second case, the width will be nonzero (although the output will not be visible in many contexts). better to use \ignorespaces and/or \unskip to get rid of such spaces. –  barbara beeton Apr 24 '12 at 14:55
    
In your first test, the definition of \temp should not contain that \unskip token—which makes the test always fail. A definition similar to \toks0={#1}\edef\temp{\the\toks0}` will also deal with the case where #1 contains numerical argument tokens while \def would croak and fail. (Hey how did you get that token there? Ok, it's a corner case!) –  Michael Grünewald Nov 5 '13 at 7:12

The etoolbox package offers \ifdefempty (and its cousin \ifcsempty for control sequence names):

\documentclass{article}

\usepackage{etoolbox}

\def\mymacroA{}
\def\mymacroB{ }
\def\mymacroC{E}
\def\mymacroD{ E }

\begin{document}

\ifdefempty{\mymacroA}{YES}{NO}\par
\ifdefempty{\mymacroB}{YES}{NO}\par
\ifdefempty{\mymacroC}{YES}{NO}\par
\ifdefempty{\mymacroD}{YES}{NO}

\end{document}

Note that like the ifmtarg package commands pointed out by Werner, but unlike Caramdir's \ifx test, \ifdefempty will expand to "true" for macro arguments consisting of at least one space and nothing else.

share|improve this answer

Use the ifmtarg package:

enter image description here

\documentclass{article}
\usepackage{ifmtarg}% http://ctan.org/pkg/ifmtarg
\makeatletter
\newcommand{\isempty}[1]{%
  \@ifmtarg{#1}{YES}{NO}}
\newcommand{\isnotempty}[1]{%
  \@ifnotmtarg{#1}{YES}}
\makeatother
\begin{document}
\verb|\isempty{}   |: \isempty{} \par
\verb|\isempty{ }  |: \isempty{ } \par
\verb|\isempty{E}  |: \isempty{E} \par
\verb|\isempty{ E }|: \isempty{ E }

\bigskip

\verb|\isnotempty{}   |: \isnotempty{} \par
\verb|\isnotempty{ }  |: \isnotempty{ } \par
\verb|\isnotempty{E}  |: \isnotempty{E} \par
\verb|\isnotempty{ E }|: \isnotempty{ E }

\end{document}

It defines \@ifmtarg{<stuff>}{<true>}{<false>} and \@ifnotmtarg{<stuff>}{<true>}.

share|improve this answer
3  
Note that \isempty{\empty} will output "NO". This may or may not be what the OP wants. –  Stephan Lehmke Apr 24 '12 at 4:34

One way is to do:

\makeatletter
\def\test#1{%
    \def\tmp{#1}%
    \ifx\tmp\@empty%
        Nothing here!%
    \else%
        You passed: \texttt{#1}.%
    \fi%
}
\makeatother

Here \@empty is defined by LaTeX as \def\@empty{}.

share|improve this answer
2  
\test{\empty} will give "You passed: .". AFAICS the author wants to test a macro for emptiness. –  Stephan Lehmke Apr 24 '12 at 4:37

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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