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 command \mycom{} which takes 1 argument. The command should perform a test on the argument and do something accordingly. For simple arguments, I can use \ifthenelse, but I need to consider more general arguments, e.g. containing commands or environments. The following MWE follows a solution for a more robust string test, which was given in this post:

\documentclass{article}
\makeatletter
\newcommand{\strtest}[2]{%
\ifnum\pdfstrcmp{#1}{#2}=\z@
  \expandafter\@firstoftwo
\else
  \expandafter\@secondoftwo
\fi}
\makeatother

\newcommand{\mycom}[1]{%
\strtest{#1}{}%
{content :  empty}%
{content : #1}%
}

\begin{document}
\mycom{}

\mycom{coucou}
\end{document}

This works. But if i try to call \mycom{\textbf{coucou}}, then the compilation fails.

share|improve this question
    
Ah, now I see! The quoted answer tells you that this test works only for simple strings, and suggests a way to cope with more complicated input. –  egreg Feb 6 '12 at 15:49

2 Answers 2

up vote 6 down vote accepted

The \pdfstrcmp primitive fully expands its argument. Thus things go wrong with macros that cannot be expanded, which includes \textbf. You can prevent this using the \unexpanded primitive:

\newcommand{\strtest}[2]{%
  \ifnum\pdfstrcmp{\unexpanded{#1}}{\unexpanded{#2}}=\z@
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
share|improve this answer
    
BTW, if you want this to work cross-engine, you should load the pdftexcmds package and use \pdf@strcmp, which deals with the fact that XeTeX calls the primitive \strcmp and LuaTeX requires it is implemented in Lua. –  Joseph Wright Feb 6 '12 at 16:06
    
Would you prefer \unexpanded or \detokenize in this case? –  egreg Feb 6 '12 at 16:09
    
@egreg We've used \unexpanded in LaTeX3, as the idea is to prevent expansion rather than turn into a string per se (which happens anyway). That I know of, there is no technical reason to prefer one approach over another. –  Joseph Wright Feb 6 '12 at 16:16
    
So I guess this can be closed as a duplicate, as your answer is already included in mine. –  egreg Feb 6 '12 at 16:19
1  
@egreg, Joseph, there is one technical reason to prefer \unexpanded: it is slightly more efficient since we move around less tokens: \pdfstrcmp converts the tl to a string internally, rather than having to first produce character tokens. For instance, \edef\x{\exp_not:c{\prg_replicate:nn{100000}x}} \edef\x{\prg_replicate:nn{1000}\x} \str_if_eq:xxTF{\tl_to_str:N\x}{}{}{} blows up when trying to build a string with 100002000 tokens, whereas using \exp_not:o works fine. –  Bruno Le Floch Feb 6 '12 at 18:39

I want to show an alternative. Based on the LaTeX3 engine one approach is:

\documentclass{article}
\usepackage{xparse,expl3,}
\ExplSyntaxOn

\NewDocumentCommand{ \mycom } { m } {
 \tl_if_empty:nTF { #1 }
   {content:~empty}
   {content:~#1}
}
\ExplSyntaxOff
\begin{document}
\mycom{}

\mycom{coucou}

\mycom{\textbf{coucou}}
\end{document}

Base on the comments question you can compare strings with:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\mystringcase}{  m }
  {
    \prg_case_str:nnn { #1 }
         {
          { a }  { Your~string~\textbf{a} }
          { b }  { Your~string~\textbf{b} }
          { c }  { Your~string~\textbf{c} }
         }       
         { Not~in~list }
  }
\ExplSyntaxOff
\begin{document}
\mystringcase{a}

\mystringcase{b}

\mystringcase{d}
\end{document}
share|improve this answer
    
Why not use \tl_if_empty:nTF? –  Joseph Wright Feb 6 '12 at 16:35
    
@JosephWright: Because of the Argument #1 I don't know the contents and I want to avoid unwanted expansion. –  Marco Daniel Feb 6 '12 at 16:46
    
\tl_fi_empty:nTF does no expansion, and is therefore safe with any input. –  Joseph Wright Feb 6 '12 at 17:05
    
@JosephWright: Thanks. I changed it. –  Marco Daniel Feb 6 '12 at 17:26

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.