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.

There is a description on how to check whether the argument of a macro is empty in What does \ifx\\#1\\ stand for?

Unfortunately, I can't get any of the examples there to work.

Among others, I have used the following code:

\documentclass{article}
\def\test#1.#2\\{%
  \ifx\\#2\\ 
    <no extension #2 is empty, because \\=\\>
  \else
    <extension is #2>
  \fi%
}
\begin{document}
\test myfile.tex
\test myfile
\end{document}

What is wrong with my code? What is the problem with my usage of the snippets?

Thanks in advance for your help.

share|improve this question
    
\test myfile does not match the macro definition because it must include a dot and `\\`. –  Christian Lindig Jan 4 '13 at 20:44

3 Answers 3

up vote 11 down vote accepted

There is no \\ delimiter in the code you're using, so the first argument can be found, but not the second and the file ends during the search for \\.

In other words, with your definition of \test the first argument ends with the first period (at brace level 0), the second at the first appearance of \\ which isn't there.

Moreover, in the second call there is no period, so the first argument can't be found.

You have to do it more cautiously; something like this:

\def\test#1{\xtest#1.\\}

\def\xtest#1.#2\\{%
  \ifx\\#2\\%
    \typeout{<no extension>}%
  \else
    \typeout{<extension is \removedot#2\\>}
  \fi}

\def\removedot#1.\\{#1}

and call it as

\test{file.tex}
\test{file}

Let's see the various cases:

\test{file.tex}

becomes

\xtest file.tex.\\

which results in assigning

#1 = file, #2 = tex.

The final dot will be removed by \removedot.

The call

\test{file}

will become

\xtest file.\\

resulting in

#1 = file, #2 = <empty>

as desired.


A perhaps easier parsing can be obtained with the help of xparse:

\usepackage{xparse}
\NewDocumentCommand{\test}{>{\SplitArgument{1}{.}}m}{\xtest #1}
\NewDocumentCommand{\xtest}{mm}
 {%
  \IfNoValueTF{#2}
   {\typeout{No extension}}
   {\typeout{Extension is #2}}%
 }

This spares from the \removedot postprocessing.

share|improve this answer

LaTeX includes a filename parser:

enter image description here

\documentclass{article}
\makeatletter
\def\test#1{%
\filename@parse{#1}%
\ifx\filename@ext\relax
#1 has no extension%
\else
the extension of #1 is \filename@ext
\fi}

\makeatother

\begin{document}
\test{myfile.tex}

\test{myfile}
\end{document}
share|improve this answer
\documentclass{article}
\usepackage{libertine}
\makeatletter
\def\test#1{\expandafter\test@i#1..\@nil}
\def\test@i#1.#2.#3\@nil{%
  \ifx\relax#2\relax 
    <no extension #2 is empty, because \string\relax=\string\relax>
  \else
    <extension is #2>
  \fi}
\makeatletter
\begin{document}
\test{myfile.tex}
\test{myfile}

\def\TEST{myfile.sty}
\test{\TEST}
\end{document}

if you do not want to put the argument into braces (what should be the preferred way) you can use something like

\def\test#1/{\expandafter\test@i#1..\@nil}
...

\test foo.bar/
\test foo/
share|improve this answer

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.