# Macro that ignores the next dot character if its expansion ends with dot character

In short, I want the following ...

\def\foo{??????????????}

\def\bar{bar}
A \foo-foo, a \foo, and a \foo came into a \foo. Says the \foo: Why the \foo?

\def\bar{baz.}
A \foo-foo, a \foo, and a \foo came into a \foo. Says the \foo: Why the \foo?


... to produce the following output:

A bar-foo, a bar, and a bar came into a bar. Says the bar: Why the bar?

A baz.-foo, a baz., and a baz. came into a baz. Says the baz.: Why the baz.?


That is, I want \foo to be equivalent to \bar but to prevent printing a double dot .. if \bar ends with .and the next character is also ..

So far, I manage to do this only with \bar doing some bookkeeping (e.g. \def\bar{bar\endswithpointfalse} vs.\def\bar{baz.\endswithpointtrue} (and \let\foo\bar, i.e., no further wrapping needed) and replacing \foo. with \foo\ifendswithpoint\else.\fi), but that is tedious in more complicated cases or impossible if \bar is third party. As there is apparently no such thing as \lastchar, I wonder if any other trick without such bookkeeping is possible?

• Not sure I fully understnad, but it you use \usepackage{xspace} and \def\foo{\bar\xspace} you should get the desired results. – Peter Grill Nov 17 at 9:21

Here is a solution that works for your example. It uses \IfEndWith from package xstring to check if \bar ends with ., and it uses \ltx@ifnextchar@nospace from package ltxcmds to check if the next character is a .. If both are true, it skips the next character using \def\ignorenext#1{}. Note that I had to rename \foo to \foo/ to avoid problems with skipping whitespace as per this answer.

\documentclass{article}
\usepackage{xstring}
\usepackage{ltxcmds}

\def\ignorenext#1{}

\makeatletter
\def\foo/{\bar\IfEndWith{\bar}{.}{\ltx@ifnextchar@nospace.{\ignorenext}{}}{}}
\makeatother

\begin{document}
\def\bar{baz}
A \foo/-foo, a \foo/, and a \foo/ came into a \foo/. Says the \foo/: Why the \foo/?

\def\bar{baz.}
A \foo/-foo, a \foo/, and a \foo/ came into a \foo/. Says the \foo/: Why the \foo/?
\end{document}


You can use the fact that the period has a very distinctive space factor code.

Here I loaded also amsthm because it redefines \frenchspacing to keep distinctive space factors for punctuation characters, while not allowing extended spacing.

Possibly gobbling a period is only activated when the space factor code is the same as the period's.

\documentclass{article}
\usepackage{amsthm}
\usepackage{xspace}

\makeatletter
\newcommand{\possibly@gobble@period}{%
\ifnum\spacefactor=\sfcode.
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\@ifnextchar{.}{\@gobble}{\xspace}}%
{\xspace}%
}
\newcommand{\foo}{\baz\possibly@gobble@period}
\makeatother

\newcommand{\baz}{baz}

\begin{document}

A \foo-foo, a \foo, and a \foo came into a \foo. Says the \foo: Why the \foo?

\renewcommand{\baz}{baz.}

A \foo-foo, a \foo, and a \foo came into a \foo. Says the \foo: Why the \foo?

\frenchspacing

A \foo-foo, a \foo, and a \foo came into a \foo. Says the \foo: Why the \foo?

\end{document}
`