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 want to create a macro for times of days, as follows:

\newcommand{\pmtime}{a.m.\xspace}

The problem is that LaTeX thinks that the last period in a.m. denotes the end of a sentence, hence the space produced by \xspace is too large.

\newcommand{\amtime}{a.m.\ }

The above is not helpful either, since a regular size space is now added, even when the macro does in fact occur at the end of a sentence.

I read about \@ifnextchar and tried the following:

\newcommand{\amtime}{a.m.\@ifnextchar.{}{\ }}

This expands to a.m.ifnextchar. in the text (in this case the macro is not followed by a period.

share|improve this question
add comment

3 Answers 3

up vote 9 down vote accepted

Because the letters a and m are lowercase, TeX does not think a.m. is an abbreviation. \@ afterwards resets the space factor and TeX does not insert a larger space (see egreg's comment).

\@ifnextchar has @ ("at") in its name, thus the pair \makeatletter and \makeatother should be used (unless it is used in a package or class file). Then @ has the catcode letter and can be part of a command name (see Werner's comment).

\@ifnextchar has the side effect of removing a following spaces, therefore the example below uses \ltx@ifnextchar@nospace of package ltxcmds that keeps a following space intact. As \@ifnextchar also \ltx@ifnextchar@nospace has three arguments, the token that is looked for (here the dot). If a dot is following, then \@gobble removes the dot to avoid to consecutive dots. \xspace is only needed for the case, that the next token is not a dot (the third argument for \ltx@ifnextchar@nospace).

\documentclass{article}
\usepackage{xspace}
\usepackage{ltxcmds}[2011/04/14]
\makeatletter
\newcommand{\amtime}{%
  a.m.\@%
  \ltx@ifnextchar@nospace.\@gobble\xspace
}
\newcommand{\pmtime}{%
  p.m.\@%
  \ltx@ifnextchar@nospace.\@gobble\xspace
}
\makeatother

\begin{document}
  7\amtime, 8\amtime and 9\amtime.
\end{document}

Result

share|improve this answer
add comment

The \@ifnextchar business is already taken care of by \xspace, if you use it. You just need to announce TeX that the period is not ending a sentence and the command \@ is just for that:

\usepackage{xspace}
\newcommand{\amtime}{\,a.m.\@\xspace}

will have the correct spacing. Notice \, to slightly detach "a.m." from the number preceding it (and this space will never be used for a line break).

However, I usually advice against \xspace: it's really not so difficult to remember writing \amtime{} in cases when a space is needed after it.

Why don't you try with

\newcommand{\amtime}{\,\textsc{am}}

that avoids periods?

share|improve this answer
add comment

Your use of \@ and \@ifnextchar unfortunately didn't throw an error, since \@ is a valid control sequence. The following is probably what you wanted to achieve with your use of \@ifnextchar:

enter image description here

\documentclass{article}
\usepackage{xspace}% http://ctan.org/pkg/xspace
\makeatletter
\newcommand{\amtime}{a.m.\@ifnextchar.{}{\ }}
\makeatother
\begin{document}
It is 8a.m. at the moment. \par
It is 8a.m.\xspace at the moment. \par
It is 8a.m.\ at the moment. \par
It is 8\amtime at the moment.
\end{document}

Note the use of \makeatletter and \makeatother. See What do \makeatletter and \makeatother do?.

However, it's easier to just use

It is 8a.m.\@ at the moment.

In the event that you might be using the macro as

It is 8\amtime, time to rise from bed.

the spacing will be incorrect. You could nest conditionals for checking the punctuation following \amtime:

\newcommand{\amtime}{a.m.\@ifnextchar.{}{\@ifnextchar,{}{\ }}}

However, this soon becomes clumsy. egreg's answer (using \@\xspace) provides a more elegant and encompassing alternative.

share|improve this answer
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.