2

I would like to build a macro converting the contents of its parameter to bold, whether be it text, inline equations or displayed equations. (I use an arrow for vectors, so this is not a problem.) I have therefore defined the following macro:

\def\makebold#1{{\bfseries\mathversion{bold}#1}}

The problem is that, if #1ends with a displayed equation, a horizontal space is added in front of the next line, as in the following:

\par\noindent Text1:
\makebold{one has \[x=y.\]}
Text2.

"Text2" is shifted by one space to the right with respect to "Text1". I can get rid of this space if I define \makebold in this way:

\def\makebold#1{{\bfseries\mathversion{bold}#1}\ignorespaces}

The problem now is that legitimate spaces are removed too, as in the following example, in front of "Text2":

Text1: \makebold{one has $x=y$.} Text2.

So, how can I know if the macro parameter ends with a displayed equation? I have tried to test for a \belowdisplayskip or a \belowdisplayshortskip with a \lastskip (as in Add \par only if last paragraph did not end with displayed math and Remove excess space at end), but this works only if I insert \par after #1, and in case 2 above, I don't want to leave the horizontal mode. I have also tried to set \postdisplaypenalty to some magic value and to test if this value is inserted, but it doesn't work either.

@campa I know that I can insert a % after \makebold{...} if it ends with a displayed equation, but I often forget to do it. Here is a file you can compile:

\documentclass{article}
\usepackage{amsmath}
\def\makeboldfirst#1{{\bfseries\mathversion{bold}#1}}
\def\makeboldsecond#1{{\bfseries\mathversion{bold}#1}\ignorespaces}
\begin{document}

\par\noindent Text1:
\makeboldfirst{one has \[x=y.\]}
Text2. % Unwanted space before "text2".

Text1: \makeboldfirst{one has $x=y$.} Text2. % OK.

\par\noindent Text1:
\makeboldsecond{one has \[x=y.\]}
Text2. % OK

Text1: \makeboldsecond{one has $x=y$.} Text2. % Space disappears before "Text2".

Environment display math test: \makeboldsecond{\begin{align*}x=y\end{align*}} Text

\end{document}
Hood Chatham
  • 5,467
Michel Fioc
  • 1,257
  • 9
  • 14
  • Thanks for the update. Side comment: pinging a user with @name works only in comments, not in questions or answers. – campa Feb 08 '18 at 13:33

1 Answers1

1

This handles display math indicated with \[\] and with a given set of environments. If you want to \ignorespaces whenever the argument ends in any environment it would be a little easier. The command \declaredisplayenvs takes a comma separated list of environment names that you want to handle separately.

\makeatletter
\long\def\ifendswithdisplay#1{\ifendswithdisplay@#1\@nil\]\@nil\@nilb}
\long\def\ifendswithdisplay@#1\]\@nil#2\@nilb{%
    \ifx&#2&%
        \expandafter\@secondoftwo
    \else
        \expandafter\@firstoftwo
    \fi
}

\long\def\ifendswithdisplayenv#1{\ifendswithdisplayenv@#1\@nil\end{}\@nil\@nilb}
\long\def\ifendswithdisplayenv@#1\end#2{%
    \@ifnextchar\@nil{%
        \ifendswithdisplayenv@@{#2}
    }{%
        \ifendswithdisplayenv@
    }%
}

\long\def\ifendswithdisplayenv@@#1#2\@nilb{%
    \@ifundefined{displayenv?#1}{%
        \@secondoftwo
    }{%
        \@firstoftwo
    }%
}

\def\declaredisplayenvs#1{\declaredisplayenvs@#1,\@nil}
\def\declaredisplayenvs@#1,{%
    \expandafter\let\csname displayenv?#1\endcsname\empty
    \@ifnextchar\@nil{\@gobble}{\declaredisplayenvs@}
}
\makeatother

% Specify here a comma separated list of the environments you want handled
\declaredisplayenvs{align*,align}

\long\def\makebold#1{{\bfseries\mathversion{bold}#1}\ifendswithdisplay{#1}{\ignorespaces}{\ifendswithdisplayenv{#1}{\ignorespaces}{}}}

A full example:

\documentclass{article}
\usepackage{amsmath}

\makeatletter
\def\ifendswithdisplay#1{\ifendswithdisplay@#1\@nil\]\@nil\@nilb}
\def\ifendswithdisplay@#1\]\@nil#2\@nilb{%
    \ifx&#2&%
        \expandafter\@secondoftwo
    \else
        \expandafter\@firstoftwo
    \fi
}

\def\ifendswithdisplayenv#1{\ifendswithdisplayenv@#1\@nil\end{}\@nil\@nilb}
\def\ifendswithdisplayenv@#1\end#2{%
    \@ifnextchar\@nil{%
        \ifendswithdisplayenv@@{#2}
    }{%
        \ifendswithdisplayenv@
    }%
}

\def\ifendswithdisplayenv@@#1#2\@nilb{%
    \@ifundefined{displayenv?#1}{%
        \@secondoftwo
    }{%
        \@firstoftwo
    }%
}

\def\declaredisplayenvs#1{\declaredisplayenvs@#1,\@nil}
\def\declaredisplayenvs@#1,{%
    \expandafter\let\csname displayenv?#1\endcsname\empty
    \@ifnextchar\@nil{\@gobble}{\declaredisplayenvs@}
}
\makeatother

\declaredisplayenvs{align*,align}

\def\makebold#1{{\bfseries\mathversion{bold}#1}\ifendswithdisplay{#1}{\ignorespaces}{\ifendswithdisplayenv{#1}{\ignorespaces}{}}}

\parindent=0pt
\begin{document}
Text1:
\makebold{one has \[x=y.\]}
Text2. % Unwanted space before "text2".

Text1: \makebold{one has $x=y$.} Text2. % OK.

Text1:
\makebold{one has \[x=y.\]}
Text2. % OK

Text1: \makebold{one has $x=y$.} Text2. % Space disappears before "Text2".


Text1: \makebold{one has \begin{align*}x=y.\end{align*}} 
Text2. 

Text1: \makebold{one has \begin{align*}x=y.\end{align*}} Text2. 


Text1: \makebold{one has \begin{align}x=y.\end{align}} 
Text2. 

Text1: \makebold{one has \begin{align}x=y.\end{align}} Text2. 
\end{document} 
Hood Chatham
  • 5,467
  • Interesting try, but this will work only for \[...\]. I would like to have a solution also for environments such as equation, equation*, align, etc. Generalizing \ifendswithdisplay for all these cases does not seem practical. – Michel Fioc Feb 08 '18 at 14:10
  • Updated to handle a set of environments. I also edited your example include an environment case, since you gave no indication before that you wanted that case too. – Hood Chatham Feb 08 '18 at 15:13
  • I have tested it and it works very well. I have waited a little in case another simpler solution would arise (involving for instance some e-TeX primitive such as \lastnodetype). I prefixed all the \def with \long since the parameter may contain some \par. You may want to edit your answer to take into account this case. – Michel Fioc Feb 09 '18 at 13:58
  • There might be some simpler way using lualatex, but I don't think e-tex can provide any help here. This is only ~30 lines of code, which I guess is a lot to express such a simple check, but it could be a lot worse. – Hood Chatham Feb 09 '18 at 14:37
  • Edited to add \longs as you suggested. – Hood Chatham Feb 09 '18 at 14:39