4

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

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

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 1 '18 at 19:12
  • 1
    @Skillmon Not with a command defined with \NewDocumentCommand that also, by the way, is preferable to \DeclareDocumentCommand. – egreg Feb 2 '18 at 0:59
  • @egreg Can you point to a reference that explains why, please? – Phelype Oleinik Feb 2 '18 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 '18 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 '18 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}
  • You should add a \relax prior to \ifmmode, see for example here. – Skillmon Feb 1 '18 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. – Hood Chatham Feb 1 '18 at 19:40
  • 1
    except when it isn't:-) – David Carlisle Feb 1 '18 at 23:26

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.