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 am trying to capture punctuation marks and I have a number of macros, two of which are shown in the minimal below:

\documentclass{article}
\usepackage[english]{babel}
\def\isColon#1{%
\ifx:#1
    colon!
\else
   Not a colon!
\fi}

\def\isPeriod#1{%
\ifx.#1
   Period!
\else
   Not a period!
\fi}

\begin{document}
\isColon:

\isPeriod.
\end{document}

If the babel language is changed to [french,english] the colon is not captured, as babel makes it active. What modifications are required to the isColon macro to work in both cases?

share|improve this question

3 Answers 3

up vote 6 down vote accepted

I'd use \if:

\documentclass{article}
\usepackage[english]{babel}
\def\isColon#1{%
\if:\noexpand#1%
    colon!
\else
   Not a colon!
\fi}

\def\isPeriod#1{%
\if.\noexpand#1%
   Period!
\else
   Not a period!
\fi}

\begin{document}
\isColon:

\isPeriod.
\end{document}

Another alternative would be \pdfstrcmp, but that is probably overkill here.

share|improve this answer
    
Note: The TeX \if test is used much less often than \ifx, but as it compares two character codes it is idea here. The \pdfstrcmp primitive, available in pdfTeX, XeTeX (as \strcmp) and in LuaTeX (using a small piece of Lua) does a general character-based comparison, and is therefore useful in cases where you have two strings and want to ignore category codes. –  Joseph Wright Dec 26 '10 at 19:07
\documentclass{article}
\usepackage[english,french]{babel}
\shorthandon{:}
\def\isColon#1{%
  \ifx:#1
    colon!
  \else
     Not a colon!
  \fi}%

\def\isPeriod#1{%
\ifx.#1
   Period!
\else
   Not a period!
\fi}

\begin{document}
\isColon: \isColon;

\isPeriod.
\end{document}
share|improve this answer
1  
This solution is not expandable: while this was not requested in the question, I think it's often useful to do it if possible. –  Joseph Wright Dec 26 '10 at 9:41
1  
@Joseph: true, I changed the code –  Herbert Dec 26 '10 at 10:15

The problem is that outside of the macro, : is a macro expanding to \active@prefix :\normal@char: , but inside the macro, : is just the character :. I believe this is because Babel registers the catcode changes with \AtBeginDocument; moving the macro definition after \begin{document} works just fine. I also found that simply changing \ifx to \if worked fine without moving the macro definition. But I think the cleanest solution (though a slightly specific one) is probably to change :'s catcode to active for the definition of \isColon:

\catcode`\:=\active
\def\isColon#1{%
\ifx:#1
    colon!
\else
   Not a colon!
\fi}
\catcode`\:=12

Edit: In case : has its catcode changed by something else, you ought to use this version instead:

\begingroup
  \catcode`\:=\active
  \gdef\isColon#1{%
    \ifx:#1
      colon!%
    \else
      Not a colon!%
    \fi}
\endgroup

This resets the catcode of : to whatever it was before, not simply to 12.

share|improve this answer
1  
@Antal: you are taking an incompatibility risk here when reverting : to catcode 12: maybe its catcode was changed by some other package. For these cases, I believe that it is better to put \begingroup before the catcode change, and \endgroup instead of reverting the catcode. Then we also need to change \def by \gdef. –  Bruno Le Floch Jan 14 '11 at 12:50
    
You're definitely right. I try to remember to do that, but not always with success. –  Antal S-Z Jan 14 '11 at 21:16
    
@Bruno,@Antal: you can also do the same without a catcode change and without a \gdef thanks to a lccode trick: \begingroup\lccode`\~=`\:\lowercase{\endgroup\def\isColon#1{\ifx~#1 colon!\else Not a colon!\fi}} –  Philippe Goutet Jan 14 '11 at 22:25
    
@Philippe: I've never seen that before—how does it work? –  Antal S-Z Jan 15 '11 at 4:18
2  
@Antal: with the \lccode change, \lowercase replaces ~ with : but doesn't change the catcode, so you obtain a : with catcode 13. More details in tex.stackexchange.com/questions/7359 –  Philippe Goutet Jan 15 '11 at 9:43

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.