1

Short: Is there a way to prevent \xspace from inserting white space if it is at the beginning of a line?

Long: I have defined several formatting macros for use in normal text. One of these (\indoubt) is normally used inside of text to insert annotations. In the normal context, there should be just one space between the preceding word and the output of this macro, so I used \unskip\xspace at the beginning of this macro. However, I also want to display a list of all formatting macros that are actually used in the document -- using the same macro to output some sample text. (I could manually write this text without \xspace, but that is error prone because I would have to remember to change the example text if I ever change the formatting in the macro.) In this list, \xspace is right at the beginning of the line. Is there a way to get rid of it in this place?

Here is an MWE:

\documentclass{article}

\usepackage{xspace}
\usepackage{xifthen}
\usepackage{etoolbox}

\makeatletter
\newcommand\addmacro[1]{%
    \write\@auxout{\noexpand\@writefile{macros}{#1\newline}}%
}
\newcommand\printmacros{%
    \section*{Meaning of formats}%
    \@starttoc{macros}%
}
\makeatother

% Once a formatting macro has been used, set the corresponding flag to TRUE
% and write self-formatted explanation to legend
\newcommand{\checkflag}[2]{%
    \providebool{flag#1}%
    \ifbool{flag#1}
        {}
        {\global\booltrue{flag#1}%
         \addmacro{#2}%
        }%
}

% Express doubt if unsure about a word in the text
\newcommand{\indoubt}[1]{%
    \checkflag{indoubt}{\protect\indoubt{Macro with leading xspace}}%
    \ifthenelse{\equal{#1}{}}
        {\unskip{\textbf{\xspace[?]\xspace}}}
        {\unskip{\textbf{\xspace[#1]\xspace}}}%
    }

\newcommand{\simple}[1]{%
    \checkflag{simple}{\simple{Just a plain formatting directive.}}%
    \textsc{#1\xspace}%
}

\setlength{\parindent}{0pt}

\begin{document}
\printmacros
\section{Test}
This is some textt\indoubt{Wrong spelling?}~\dots \simple{More text.}
\end{document}
  • What's the reason for so much braces and for \xspace[? – egreg Oct 18 '17 at 17:16
  • The opinion of the package author (not me): Don't use \xspace. My opinion: Don't use \xspace especially not in this context. Preceding a macro with \xspace just seems wrong to me. Just leave a space between the macro (\indoubt) and the preceding word. – Skillmon Oct 18 '17 at 17:19
  • 2
    Insert the space with some command (\myoptionalspace) and redefine this command in your \printmacros command to do nothing. – Ulrike Fischer Oct 18 '17 at 17:21
  • @egreg In this case, "[…]" is not meant as an argument to \xspace! I just want to annotate some words in the text, like this: "This is a sonett [looks German -- in English it's spelled 'sonnet'.] by Shakespeare.", with braces marking the insertions as not belonging to the original. – Andreas Oct 18 '17 at 17:23
  • 1
    there should never be a macro "with a leading xspace" the only possible place xspace has any use at all is the very last token of a macro definition, fro a macro with no arguments. – David Carlisle Oct 18 '17 at 18:01
4

The point of \xspace even if you decide to ignore its drawbacks is to add space after a command with no arguments, if the command is not followed by punctuation.

It is no use at all with a command with arguments because

 blah blah \foo{argument} blah

the space after \foo{argument} unlike the space after \foo is just a normal space and appears in the output with no special handling.

Using the \xspace command at any place other than the last token of a definition never does anything useful as in such a case you always know what the next token is so the lookahead and testing that xspace does is not useful. {\xspace[... is just a slow way to do { [...

I'm not totally sure what you wanted, but perhaps

\documentclass{article}

\usepackage{xifthen}
\usepackage{etoolbox}

\makeatletter
\newcommand\addmacro[1]{%
    \write\@auxout{\noexpand\@writefile{macros}{#1\par}}%\newline is badness10000 "infinitely bad"
}
\newcommand\printmacros{%
    \section*{Meaning of formats}%
    \@starttoc{macros}%
}
\makeatother

% Once a formatting macro has been used, set the corresponding flag to TRUE
% and write self-formatted explanation to legend
\newcommand{\checkflag}[2]{%
    \providebool{flag#1}%
    \ifbool{flag#1}%
        {}%
        {\global\booltrue{flag#1}%
         \addmacro{#2}%
        }%
}

% Express doubt if unsure about a word in the text
\newcommand{\indoubt}[1]{%
    \ifhmode\unskip\space\fi
    \checkflag{indoubt}{\protect\indoubt{Macro with leading xspace}}%
    \ifthenelse{\equal{#1}{}}%
        {\textbf{[?]}}%
        {\textbf{[#1]}}%
    }

\newcommand{\simple}[1]{%
    \checkflag{simple}{\simple{Just a plain formatting directive.}}%
    \textsc{#1}%
}

\setlength{\parindent}{0pt}

\begin{document}
\printmacros
\section{Test}
This is some textt\indoubt{Wrong spelling?}~\dots \simple{More text.}
\end{document}
  • Thank you very much, this does exactly what I want to achieve here! – Andreas Oct 19 '17 at 12:19
  • OK, after looking for the meaning of \space in "TeX by Topic", which I just discovered yesterday, I understand that this is what I've always been looking for: insert a space anywhere except at the start of a line! Thus, I could have used {\unskip\space{\textbf{[#1]}}} in my definition of \indoubt all along (although \ifhmode … is much more elegant). {\unskip\textbf{\space[#1]}} would not work, however, because it would be local to \textbf{} -- and \textbf{}, not \space would be the first token at the start of a line. Have I got that right? – Andreas Oct 19 '17 at 12:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.