1

I have a macro that is purely functional (e.g. only defines other macros), and I want to be able to invoke this inline without any new paragraphs or blank spaces being typeset.

\documentclass{article}
\begin{document}
\def\test{
  \gdef\a{1}

\gdef\b{1} }

Hello {\test} world! \end{document}

output_1

Following this, I was able to remove all \pars generated by blank lines.

\documentclass{article}
\begin{document}
\def\test{
  \gdef\a{1}

\gdef\b{1} }

Hello {\let\par\relax\test} world! \end{document}

output_2

However, this results in a few spaces where the macro is called.

Is there a way to, more generally, suppress all typesetting within a group?

If not, is there a way to suppress all spaces within a group as well?

rish987
  • 155

4 Answers4

3

Don't add spaces in your \test macro.

% nullprob.tex  SE 561601
\documentclass{article}
\begin{document}
\def\test{%
  \gdef\a{1}%
%
  \gdef\b{1}%
}

Hello {\test}world! \end{document}

Peter Wilson
  • 28,066
  • 1
    This would work, but I'm keeping my \defs in an external file which I \input. It would be pretty inconvenient to have to do this on every line. – rish987 Sep 06 '20 at 16:39
2

(\a and \b are already defined by the LaTeX-kernel. Better not to override these definitions. Therefore in the example below I used \A and \B instead.)

You can

  • switch to \nullfont for neutralizing the typesetting of character-tokens
  • redefine \par to do nothing:

 

\documentclass{article}
\makeatletter
\newcommand\bspesphackgroup[1]{\@bsphack{\nullfont\let\par=\empty#1}\@esphack}%
\makeatother
\begin{document}
\def\test{
  \gdef\A{1}

\gdef\B{1} }

Hello World!

Hello \bspesphackgroup{\test} World! \end{document}

enter image description here

But this will not prevent tpesetting in general.

E.g., a \kern or \vskip or \hskip or \hrule or \vrule will be carried out and have a visible effect. Besides this font-switching-commands inside \test may override \nullfont:

\documentclass{article}
\makeatletter
\newcommand\bspesphackgroup[1]{\@bsphack{\nullfont\let\par=\empty#1}\@esphack}%
\makeatother
\begin{document}
\def\test{
  \gdef\A{1}

\gdef\B{1}

\let\par=\endgraf \par\vskip 2cm

\leavevmode\vrule width 2cm height 2cm\relax

\normalfont This is disturbing!

}

Hello World!

Hello \bspesphackgroup{\test} World! \end{document}

enter image description here

Ulrich Diez
  • 28,770
1

(\a and \b are already defined by the LaTeX-kernel. Better not to override these definitions. Therefore in the example below I used \A and \B instead.)

The problem seems to be that within the ⟨definition text⟩ of \test control-word-tokens \par and space-tokens come into being in places where they should not come into being.

In case the definitions nested inside the definiton of \test (i.e., the definition of \A and the definition of \B) don't contain linebreaks that should yield space-tokens or \par-tokens you can temporarily have \endlinechar denote the %-character which has category-code 14 (comment) instead of having it denote the return-character which has category code 5 (end of line) and therefore—depending on the state of TeX's reading apparatus—either yields no token at all or yields a space-token or yields the control-word-token \par:

\documentclass{article}

\begingroup \makeatletter \endlinechar=`%\relax @firstofone{% \endgroup \def\test{ \def\A{1}

\def\B{1}

} }

\show\test

\begin{document} Hello world!

\show\A \show\B

Hello \test world!

\show\A \show\B \end{document}

enter image description here

The console-output reveals that in the ⟨definition text⟩ of \test there are neither \par-tokens nor space-tokens between/behind the ⟨definition texts⟩ of \A and \B:

> \test=macro:
->\def \A {1}\def \B {1}.
l.15 \show\test

? (./test.aux) > \A=undefined. l.20 \show\A

? > \B=undefined. l.21 \show\B

? > \A=macro: ->1. l.25 \show\A

? > \B=macro: ->1. l.26 \show\B

?

Ulrich Diez
  • 28,770
0

I was able to effectively disable spaces, referencing page 76 of the TeXbook.

I did this by setting \spacefactor=10000 and \xspaceskip=0.0001pt for a fixed-width negligible space, and removing the space after my grouping.

\documentclass{article}
\begin{document}
\def\test{
  \gdef\a{1}

\gdef\b{1} }

Hello {\spacefactor=10000\xspaceskip=0.0001pt\let\par\relax\test}world! \end{document}

output_1

This does seem like a bit of a workaround, so if anyone knows of a better solution please let me know!

Edit:

I created the macros \bnosp and \enosp that allow me to truly embed such a macro inline, without the need for \gdef. \bnosp saves the value of \spacefactor, \xspaceskip and \par before changing them to the values above and invoking the macro, then \enosp resets them to their original values.

\documentclass{article}
\begin{document}
\def\test{
  \def\a{1}

\def\b{1} }

\def\bnosp{\edef\xspaceskiporig{\the\xspaceskip}\edef\spacefactororig{\the\spacefactor}\let\parorig\par\spacefactor=10000\xspaceskip=0.00001pt\let\par\relax} \def\enosp{\spacefactor=\spacefactororig\xspaceskip=\xspaceskiporig\let\par\parorig}

Hello \bnosp \test \enosp world!

\a\ \b \end{document}

output_2

rish987
  • 155