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.

Is there a neat way to remove all instances of the text \mypath../ from the input, using TeX's text processing capabilities? The ifthen approach below works, but seems to be a bit heavyweight. Also, I'm looking for a solution that would work before the \documentclass command:

\documentclass{scrartcl}
\usepackage{ifthen}

\newcommand{\mypath}[3]{%
  \ifthenelse{\equal{#1#2#3}{../}}{}{#1#2#3}%
}

\begin{document}
  Gobble: \mypath../

  Don't gobble: \mypath.ab
\end{document}
share|improve this question
add comment

1 Answer

up vote 7 down vote accepted

Here's an expandable way:

\long\def\mypath#1#2#3{\mypathaux../#1#2#3../}
\long\def\mypathaux../#1../{%
  \if\relax\detokenize{#1}\relax
    \expandafter\mypathgobble
  \else
    #1
  \fi}
\long\def\mypathgobble#1#2#3{}

The macro \mypath absorbes the next three tokens and calls \mypathaux in a curious way; let's see the two main cases:

  1. \mypath../ becomes \mypathaux../../../

  2. \mypath xyz becomes \mypathaux../xyz../

The macro \mypathaux has only one argument, all tokens that go from the first occurrence of ../ to the second occurrence. In case 1 there's nothing between the two occurrences, so #1 is empty. In case 2, #1 is xyz.

The macro now tests whether #1 is empty (it's a slick trick by H. Oberdiek); if it is, it calls \mypathgobble that swallows the ../ that remain on the main token list; otherwise it just returns #1.

A similar way that gets rid also of the \fi after #1, which might be needed in some situations is

\makeatletter
\newcommand\mypath[3]{\@mypath../#1#2#3../}
\long\def\@mypath../#1../{%
  \if\relax\detokenize{#1}\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi\@gobblethree{#1}}
\providecommand\@gobblethree[3]{}
\makeatother

This uses features from the LaTeX kernel, while the former macros don't.

Let's see the two cases. With \mypath xyz we get

\@mypath../xyz../

and the test returns false, so we're left with

\expandafter\@secondoftwo\fi\@gobblethree{xyz}

where \expandafter acts on \fi (it simply disappears), leaving

\@secondoftwo\@gobblethree{xyz}

so \@secondoftwo finally produces xyz. In the case of \mypath../ we get

\@mypath../../../

and the test returns true; this leaves

\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi\@gobblethree{}../

(only the first two ../ disappear as part of the pattern matching). The first \expandafter acts on \else which causes everything up to the matching \fi to disappear:

\@firstoftwo\@gobblethree{}../

and now we get

\@gobblethree../

which leaves nothing.

share|improve this answer
    
Thank you for your edits. Still, I wonder what happens to the third ../ in \mypath../--> \@mypath../../../ after it has been matched to \@mypath../../ with #1 empty. –  krlmlr Sep 11 '12 at 4:49
    
@user946850 In the case you mention, the first pair of ../ disappears as part of the action of \@mypath and the third because \@gobblethree is called. I'll add something. –  egreg Sep 11 '12 at 7:37
    
That makes it perfectly clear. Here's the link to the question/answer that explains \expandafter: tex.stackexchange.com/q/451/8057 –  krlmlr Sep 11 '12 at 11:41
add comment

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.