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}
  • Thanks for the update. Side comment: pinging a user with @name works only in comments, not in questions or answers. – campa Feb 8 '18 at 13:33
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} 
  • 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 8 '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 8 '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 9 '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 9 '18 at 14:37
  • Edited to add \longs as you suggested. – Hood Chatham Feb 9 '18 at 14:39

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.