5

I want to create a command \points working in both math and text mode. Unfortunately I still have problems creating the correct (horizontal) spacing after several attempts. Here is my basic „setup“, where I am missing space before \points{3} inside math mode.

Code

\documentclass{article}

\usepackage{amsmath}
\usepackage{xparse}

\DeclareDocumentCommand \points { m } {\text{[#1\,P]}}

\begin{document}

Sentence end \points{1}. Between \points{2} words.

$x^2 + 9 = 0 \points{3}$

\end{document}

Result

Example

dawu
  • 1,648

3 Answers3

9

Math mode eats up spaces, so you have to enforce one.

You can change the macro to:

\NewDocumentCommand \points { m } {\ifmmode\ \fi\text{[#1\,P]}}

or enforce the space when using the command:

$x^2 + 9 = 0\ \points{3}$

but not both, otherwise you'll get two spaces.

Also, notice that I replaced, following @egreg's remark, \DeclareDocumentCommand by \NewDocumentCommand.

\DeclareDocumentCommand has a behavior akin to \def regarding already defined commands. It will create the command no matter what, so you may be replacing an already existing macro with this.

\NewDocumentCommand, on the other hand, is equivalent to LaTeX's \newcommand; it will check if the command being created already exists and, if it does, an error will appear.

  • 1
    You should add a \relax prior to \ifmmode, see for example here. – Skillmon Feb 01 '18 at 19:12
  • 1
    @Skillmon Not with a command defined with \NewDocumentCommand that also, by the way, is preferable to \DeclareDocumentCommand. – egreg Feb 02 '18 at 00:59
  • @egreg Can you point to a reference that explains why, please? – Phelype Oleinik Feb 02 '18 at 02:08
  • 1
    @PhelypeOleinik because a command created with \NewDocumentCommand or \DeclareDocumentCommand is \protected (which happens to be one of the working examples in David Carlisle's answer I linked to). I just forgot about that, my bad. Reference is the xparse documentation, section 0.7 (in the current version). – Skillmon Feb 02 '18 at 09:07
  • 1
    @PhelypeOleinik The \relax is needed for standard macros starting with \ifmmode, because math mode does not start in array cells until after TeX has checked for \omit (in LaTeX lingo, \multicolumn). For macros defined with \NewDocumentCommand, \RenewDocumentCommand and also \DeclareRobustCommand this is not needed, because they are already protected against this. – egreg Feb 02 '18 at 09:08
6
\documentclass{article}
\usepackage{amsmath}
\newcommand\points[1]{\ensuremath{\mathrel{[#1\,\mathrm{P}]}}}    
\begin{document}    
    Sentence end \points{1}. Between \points{2} words.

    $x^2 + 9 = 0 \points{3}$

\end{document}
4

If you add \ifmmode\text{\space} to the command, it will always insert a space in front if used in math mode. Also, I used \newcommand instead of \NewDocumentCommand since making a command that takes a single mandatory argument does not require the more advanced functionality of \NewDocumentCommand.

\documentclass{article}
\usepackage{amsmath}

\newcommand\points[1]{\relax\ifmmode\text{ }\fi\text{[#1\,P]}}

\begin{document}

Sentence end \points{1}. Between \points{2} words.

$x^2 + 9 = 0 \points{3}$

\end{document}
Hood Chatham
  • 5,467