7

I have a feeling this is another of my questions that is going to be a "Duh!!" kind of answer, but I can't seem to figure out how to do this properly: I want to put a wrapper around a macro that uses \xspace, but behaves differently upon the first use of the macro. The following does not quite produce the correct result upon first use, and leaves an extra space:

enter image description here

I'd prefer to have all the formatting controlled by one macro: \NameStyle, but am open to options.

Code:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{xcolor}
\usepackage{xspace}

\newtoggle{FirstUseOfNameStyle}%
\toggletrue{FirstUseOfNameStyle}%

\newcommand*{\NameStyle}[1]{\textit{#1}\xspace}%
\newcommand*{\NameStyleForFirstUse}[1]{\textcolor{red}{\NameStyle{#1}}}%

\newcommand*{\Name}[1]{%
    \iftoggle{FirstUseOfNameStyle}{%
        \NameStyleForFirstUse{#1}%
        \global\togglefalse{FirstUseOfNameStyle}
    }{%
        \NameStyle{#1}%
    }%
}%

\begin{document}
The first name is \Name{Peter}.

The name \Name{Peter},  also known as some other name.

The name \Name{Peter} Grill is well known in TeX circles.
\end{document}
2
  • 3
    The problem is a spurious space after \global\togglefalse{FirstUseOfNameStyle}. But what should \xspace do? It's completely useless, of course.
    – egreg
    Commented May 20, 2012 at 2:35
  • @GonzaloMedina It was a very particular question and a particular situation: the immediate answer was easy and I was awake in the middle of the night because of an earthquake.
    – egreg
    Commented May 20, 2012 at 9:17

2 Answers 2

6

First of all there's a spurious space in your code, the one on the

\global\togglefalse{FirstUseOfNameStyle}

line.

Second: \xspace does nothing there, for a space after \Name{Peter} won't be gobbled anyway. The macro \xspace is only (dubiously) useful for macros without arguments.

If your aim is to define a macro that acts similarly to the "acronym resolver macros", then you can do it quite easily:

\makeatletter
\newcommand{\Name}[1]{%
  \ifcsname peter@\detokenize{#1}\endcsname
    \textit{#1}%
  \else
    \textcolor{red}{\textit{#1}}%
    \global\expandafter\let\csname peter@\detokenize{#1}\endcsname\@empty
  \fi
}
\makeatother

(Don't use this in "fragile contexts" such as section titles and captions that would trigger the "first appearance" in unwanted places; it can be corrected, if needed.)

So the first appearance of \Name{Peter} will print the name in red, as it will the first appearance of \Name{egreg}.

You can alias a call of \Name{Peter} by saying

\newcommand{\peter}{\Name{Peter}\xspace}

and here \xspace would do its job.

5

egreg has pointed out the problem and the needless \xspace in your solution. But I still find your solution inefficient. The following solution is copied from ltxtools2 package.

\documentclass{article}
\usepackage{catoptions}
\usepackage{xspace}
\makeatletter
\robust@def*\newname#1#2{%
  \ifescapedTF{#1}{%
    \edef\cpt@tempa{\cptgobblescape#1}%
  }{%
     \edef\cpt@tempa{#1}%
  }%
  \cptexpanded{\cpt@testopt{\cpt@newname{\cpt@tempa}{#2}}}{}%
}
\robust@def*\cpt@newname#1#2[#3]{%
  \csn@def{#1long}{#2\xspace}%
  \ifblankTF{#3}{%
    \csn@def{#1first}{#2\xspace}%
  }{%
    \csn@def{#1short}{#3\xspace}%
    \csn@def{#1first}{#2~(#3)\xspace}%
  }%
  \expandafter\@ifdefinable\csname#1\endcsname\relax
  \csn@def{#1}{%
    \ifnamedefTF{newname@#1}{%
      \usename{#1short}%
    }{%
      \csn@def{newname@#1}{}%
      \usename{#1first}%
    }%
  }%
}
\makeatother

\newname\peter{Peter Gill}[Peter]
\newname\pics{Production and Inventory Control Society}[PICS]

\begin{document}
\noindent
\peter said it. \peter did it. It was brought here by \peter. 
It was taken there by \peterlong, and not \petershort.

What connects \TeX\ with \pics? \pics deals with turning raw materials into 
finished goods that \peter buys from the shops.
\end{document}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .