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

2
  • I think that you forgot the most basic tag: macro...
    – koleygr
    Feb 1, 2018 at 20:21
  • I’m not sure why you need the command in math mode to begin with.
    – egreg
    Feb 2, 2018 at 1:01

3 Answers 3

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.

5
  • 1
    You should add a \relax prior to \ifmmode, see for example here.
    – Skillmon
    Feb 1, 2018 at 19:12
  • 1
    @Skillmon Not with a command defined with \NewDocumentCommand that also, by the way, is preferable to \DeclareDocumentCommand.
    – egreg
    Feb 2, 2018 at 0:59
  • @egreg Can you point to a reference that explains why, please? Feb 2, 2018 at 2: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 2, 2018 at 9: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 2, 2018 at 9: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}
3
  • You should add a \relax prior to \ifmmode, see for example here.
    – Skillmon
    Feb 1, 2018 at 19:12
  • @Skillmon Thanks I've never thought of adding a defensive \relax before. Seems like good practice whenever you don't have control over what comes before your conditional. Feb 1, 2018 at 19:40
  • 1
    except when it isn't:-) Feb 1, 2018 at 23:26

You must log in to answer this question.

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