2

What it says on the tin.

In case it isn't clear enough, what I would like is for $...$ to be typeset as \smash{$...$}, except \smash also affects horizontal spacing (see the question I linked to below) and I'd like it to only affect vertical spacing.

In other words, I'd like some preamble code that does two things:

  1. Make \smash only affect vertical spacing.
  2. Treat all instances of $...$ as \smash{$...$}.

(This question very specifically requests both vertical and horizontal smashing of inline maths, so mine is not a duplicate of it.)

Rain
  • 194
  • 1
    Please clarify what you mean by "smash". – Mico May 07 '22 at 07:28
  • No solution is without limitations (or enormous effort to patch all the commands), but making $ active should work reasonably well. – user202729 May 07 '22 at 07:30
  • @user202729 What do you mean by "making $ active"? – Rain May 07 '22 at 07:36
  • @Mico Done. Hope that's clearer. – Rain May 07 '22 at 07:37
  • Catcode is a long topic, read e.g. TeXbook if you want to learn programming in TeX. See https://tex.stackexchange.com/q/536188/250119 and the questions linked from it for an example what can be done (you still need to know TeX programming to adapt however) – user202729 May 07 '22 at 07:53
  • 4
    There are other ways of preserving baseline spacing, if that is your real intention here. As always a small complete test document would help. Of course in gneral this should never be needed, the point of inline math is to lay out the math in a way that does not disturb the line spacing. – David Carlisle May 07 '22 at 07:53
  • @DavidCarlisle That's my intention, yes. I avoid tall maths (like fractions) inline because I hate it when the line height is altered and it just looks ugly, but sometimes I'll need to write something like $\vec{E}=\vec{E}_0\,e^{ikz}$ inline and then I have to smash that so the line where that occurs doesn't become taller than the other lines in the text. But then either I need to smash every instance of inline maths (i.e. whenever I mention a variable inline) or the horizontal spacing is different in smashed instances and non-smashed instances of inline maths. – Rain May 07 '22 at 08:31
  • 1
    by default the example you show would not disturb the line spacing, so there is something you are not telling us about your setup. While disturbing the spacing is typographically bad, it's not as bad as overprinting the line above (which is what you get with no warning from \smash ) so the real fix is to fix whatever settings you have that is causing the original issue. See this, \baselineskip not \lineskip used so even spacing – David Carlisle May 07 '22 at 08:42
  • 1
    \documentclass{article} \showoutput \showboxdepth=3 \begin{document} aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$ aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$ aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$ aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$ aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$ aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$ aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$ \end{document} – David Carlisle May 07 '22 at 08:43
  • In inline math mode, you should consider replacing e^{ikz} with \exp(ikz). – Mico May 07 '22 at 08:52
  • @DavidCarlisle It does disturb the line spacing. Here's a slightly worse example (notice how the vertical spacing between the second and third vertical bars is larger): \documentclass{article}\usepackage{amsmath}\begin{document}\noindent$|$\\$|$\\$|\vec{E}^{\,\text{t}}=\vec{E}^{\,\text{t}}_0\,e^{ikz}$\\$|$\\$|$\\$|$\\\end{document} – Rain May 07 '22 at 09:12
  • After re-reading your and David Carlisle's observations several times, I've come to suspect that you not only (as you proclaim yourself) "hate the Computer Modern font family with a fiery passion", but that you've also set an unreasonably small value for \baselineskip for whichever font you are using at present. For most most fonts (other than blackletter), setting \baselineskip to 120% of the nominal font size is usually considered fine; if the nominal font size is 10pt, this may be achieved by executing \fontsize{10}{12}\selectfont. Please do tell us which font family you employ. – Mico May 07 '22 at 13:45
  • @Mico I'm using Calluna at 11 pt, and I set \baselineskip to 105% of the nominal font size. Here's an example of what my text looks like: https://cdn.discordapp.com/attachments/480051867443920906/972726785391329342/unknown.png – Rain May 08 '22 at 05:09
  • @Rain - What strikes me immediately -- and not in a good way -- about the screen shot you provide is that the x-height of the math font would appear to be noticeably smaller than that of the text font. Which math font is that, by the way? Have you tried increasing \baelineship by another 5%? – Mico May 08 '22 at 05:42
  • The mathfont is also Calluna, just italic. That was a conscious and intentional choice on my part; I like my font and my mathfont to look consistent. Re the x-height, they look the same to me (the red rectangles in https://cdn.discordapp.com/attachments/480051867443920906/972768680746307645/unknown.png are the same height; if anything, the mathfont x-height looks slightly larger to me because of the curved corners), unless I've completely misunderstood what x-height means. – Rain May 08 '22 at 08:10
  • Re increasing \baselineskip further, just tested and I need another 10%, which makes the line spacing slightly larger than I'd like, but thanks for the suggestion. (Incidentally, if it matters at all, I just realised that the relevant line in my preamble is \linespread{1.05}, not something that explicitly contains \baselineskip. – Rain May 08 '22 at 08:12
  • Question solved? :) If yes, consider accepting one of the answers. – Dr. Manuel Kuehner Dec 04 '22 at 18:02
  • 1
    @Dr.ManuelKuehner I haven't actually had time to play with LuaLaTeX to see whether I can implement Mico's solution without anything else breaking, so, unfortunately, the answer is "soon (TM)". Sorry to David and Mico! – Rain Jan 04 '23 at 01:58

2 Answers2

5

By default the example shown will fit within the line spacing so no \smash is needed

\documentclass{article}
\showoutput
\showboxdepth=3
\begin{document}
aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\vec{E}=\vec{E}_0\,e^{ikz}$
\end{document}

Produces

enter image description here

and the log confirms \baselineskip (rather than \lineskip) is used.

...\hbox(9.67221+1.49998)x345.0, glue set 0.34198 []
...\penalty 150
...\glue(\baselineskip) 0.8278
...\hbox(9.67221+1.49998)x345.0, glue set 0.45447 []
...\penalty 150
...\glue(\baselineskip) 0.8278
...\hbox(9.67221+1.49998)x345.0, glue set 9.86978fil []

For a larger expression

\documentclass{article}
\showoutput
\showboxdepth=3
\begin{document}
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
\end{document}

You get

enter image description here

and the log confirms TeX gave up using \baselineskip:

...\hbox(10.17732+4.9484)x345.0, glue set 0.26582 []
...\penalty 150
...\glue(\lineskip) 1.0
...\hbox(10.17732+4.9484)x345.0, glue set 0.15062 []
...\glue(\lineskip) 1.0
...\hbox(10.17732+4.9484)x345.0, glue set 0.28621 []
...\penalty 150
...\glue(\lineskip) 1.0
...\hbox(10.17732+4.9484)x345.0, glue set 282.19075fil []

You can set \lineskiplimit so that baseline space is preserved even if the lines do not fit:

\documentclass{article}
\showoutput
\showboxdepth=3
\setlength\lineskiplimit{-\maxdimen}
\begin{document}
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
aaa bbb ccc ddd ee $\frac{X^2}{Y_3}=\frac{X^2}{Y_3}_0\,e^{ikz}$
\end{document}

This produces

enter image description here

and log

...\hbox(10.17732+4.9484)x345.0, glue set 0.26582 []
...\penalty 150
...\glue(\baselineskip) -3.12572
...\hbox(10.17732+4.9484)x345.0, glue set 0.15062 []
...\glue(\baselineskip) -3.12572
...\hbox(10.17732+4.9484)x345.0, glue set 0.28621 []
...\penalty 150
...\glue(\baselineskip) -3.12572
...\hbox(10.17732+4.9484)x345.0, glue set 282.19075fil []

Showing that baseline spacing preservd even if that forces negative space between lines.

The cure here is worse than the problem though, over-printed illegible text is typographically worse than uneven line space.

This is (I think) the effect that you wanted, by asking for \smash to be applied everywhere but in practice it is better not to do this and just apply \smash conditionally in places where you know there is no over-printing (because a tall item on this line is not aligned with a deep descender on the line above so that you can overlap the bounding boxes without overlapping text)

David Carlisle
  • 757,742
  • Thanks for the answer. That does fix my problem with inline maths, but it messes with equations (at least with align, haven't tested other environments: compare \documentclass{article}\usepackage{amsmath}\setlength\lineskiplimit{-\maxdimen}\begin{document}\noindent$|$\\$|$\\$|\vec{E}^{\,\text{t}}=\vec{E}^{\,\text{t}}_0\,e^{ikz}$\\$|$\\$|$\\$|$\\\begin{align}1+1=2\end{align}Hello.\end{document} to that same code without the \setlength\lineskiplimit{-\maxdimen} bit. – Rain May 07 '22 at 09:18
  • Re applying \smash on a case-by-case basis where I know there aren't any deep descenders causing illegible text, I'd much rather avoid illegible text on a case-by-case basis by rewording the problematic text or moving the problematic maths to an align environment if rewording isn't possible. it's just less work for me that way. – Rain May 07 '22 at 09:21
  • You could patch align to reset lineskiplimit locally @Rain – David Carlisle May 07 '22 at 09:25
  • Ooh, that could work! I'll look into it. – Rain May 07 '22 at 09:39
  • 3
    @Rain re "less work" there must be something wrong with your document settings if this comes up often at all. Setting lineskip limit or globally smash will give overprinting with no warning so is much more fragile than allowing the default spacing when you can always mechanically check the log for instances of \lineskip and adjust as needed. But your default baseline space should be large enough to hold your standard line text, it seems you have it set too small. I would never use the setting I show here for a document to be published. – David Carlisle May 07 '22 at 10:30
3

Additional comment, prompted by the some of the OP's comments: If your document contains a lot of inline math material -- not that there's anything wrong with that! -- you may want to preemptively increase the value of \baselineskip. If the default value of \baselineskip for the font you employ is "120% of the nominal font size" and if the nominal font size is 10pt, you could execute

\fontsize{10}{13}\selectfont

for the document as a whole, in order to avoid most, if not almost all, instances of \lineskip having to be increased beyond \baselineskip. For sure, the case of \vec{E} forcing an increase in \lineskip would no longer be relevant.

The suggestion to increase \baselineskip preemptively is by no means arbitrary or hackish. For instance, in the preface of the book Concrete Mathematics by Graham, Knuth, and Patashnik -- which (unsurprisingly) contains a lot of inline math material, the Concrete Roman text font (an "Egyptienne" of slab-serif variant of Computer Modern), and the "Euler" math font -- the authors discussed that by increasing the value of \baselineskip from 12pt to 13pt, they immediately got rid of almost all cases of inline math forcing an increase in \lineskip. If a typographic solution prompted by inline math considerations is good enough for Knuth and his co-authors, you may want to see if it "works" for you too, right?

By the way, the \fontsize{10}{13}\selectfont approach increases the value of \baselineskip everywhere, including for document elements, such as tabular-like environments, for which no increase in \baselinskip may be needed or desired. To keep tables nice and compact, you could choose -- as an alternative to running \fontsize{10}{13}\selectfont -- to load the setspace package (with the option nodisplayskipstretch) and issue the instruction \setstretch{1.0833} in the preamble. Note that a factor of 1.083 is still barely a third of what the \onehalfspacing directive would entail.


Here's a LuaLaTeX-based solution. To acitivate it, execute \SmashOn; to deactivate it, execute \SmashOff. When \SmashOn is executed, the Lua function smash is assigned to LuaTeX's process_input_buffer callback, where it acts as a preprocessor on the input stream, i.e., it does its stuff before TeX starts its own processing of the input material. The "stuff" it does is to replace all instances of $...$, with \smash{$...%}, just as you require.

There are (at least) three limitations to this approach, the first of which should be the most relevant one in practice.

  1. The inline math material is assumed to be all on one line -- no line breaks allowed. No exception.

  2. You mustn't use $$ to initiate and terminate display math mode. This shouldn't be much of a constraint at all, though, as you should never be using $$ in a LaTeX document. See Why is \[ ... \] preferable to $$ ... $$? for a longer discussion of this subject.

  3. You don't use \$ to display dollar symbols. If you do, be sure to run \SmashOff before the instance(s) of \$ -- and \SmashOn to reactivate the Lua function if and when needed -- or replace the instances of \$ with \textdollar.

That said, I can't imagine a compelling use case for wanting to (vertically) smash all inline math material. If you require it, you're almost certainly doing something wrong. If you have instances of e^{ikz} in inline math mode, consider replacing them with \exp(ikz). Your readers will actually be grateful for you if you did this.


enter image description here

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{amsmath}  % for '\dfrac' macro
\usepackage{lipsum}   % filler text
\usepackage{luacode}  % for 'luacode' env.
\begin{luacode}
   function smash ( s )
     return ( s:gsub ( "%b$$" , "\\smash{%1}" ) )
   end
\end{luacode}
\newcommand\SmashOn{\directlua{luatexbase.add_to_callback (
   "process_input_buffer", smash, "smash" )}}
\newcommand\SmashOff{\directlua{luatexbase.remove_from_callback (
   "process_input_buffer", "smash" )}}

\begin{document} \hrule % draw line to illustrate width of textblock \lipsum[1][1-5] $\dfrac{\dfrac{v}{v}}{\dfrac{w}{x}}$ \lipsum[1][5-8] \hrule \SmashOn % activate the Lua function \lipsum[1][1-5] $\dfrac{\dfrac{v}{v}}{\dfrac{w}{x}}$ \lipsum[1][5-8] \hrule \SmashOff % deactivate the Lua function \lipsum[1][1-5] $\dfrac{\dfrac{v}{v}}{\dfrac{w}{x}}$ \lipsum[1][5-8] \hrule \end{document}

Mico
  • 506,678
  • this does apply \smash though so doesn't do what is asked, which is avoid the boxing which affects the horizonal spacing. – David Carlisle May 07 '22 at 08:53
  • Thanks for your answer. Will this work in XeLaTeX? Does something like XeLuaLaTeX even exist? (: – Rain May 07 '22 at 09:23
  • @Mico Re your limitations: 1. I've used \relpenalty=99999 and \binoppenalty=99999 for years because I hate line breaks in the middle of inline maths so no worries there. 2. I use align environments anyway. Never used \[...\] or `$$...$$`` in my life. 3. I write theoretical-physics and maths text, so I've never needed to typeset a dollar sign in a TeX document and I can't imagine ever needing to do so. So no problem there. Thanks for pointing those out anyway, though. – Rain May 07 '22 at 09:27
  • 1
    @Rain no his wouldn't work in xelatex (but there are very few documents that need xetex features and can not use luatex instead) – David Carlisle May 07 '22 at 09:28
  • The problem isn't really the exponential, but the vector arrow on top of the uppercase letter (or tall lowercase letter, such as k, which I also often use). – Rain May 07 '22 at 09:28
  • @DavidCarlisle I use XeLaTeX for font reasons (I hate Computer Modern with fiery passion). Haven't been able to get that to work without the Xe bit. – Rain May 07 '22 at 09:29
  • 3
    @Rain there are no fonts that you can use with xetex that you can not use with luatex. – David Carlisle May 07 '22 at 09:30
  • Thanks; when I get some free time I'll play around with LuaTeX. It isn't an engine I'm familiar with, so I'll have to see whether anything breaks. – Rain May 07 '22 at 09:39
  • @DavidCarlisle - I had asked the OP to clarify what “smashing” entailed, and OP edited the posting to clarify that the argument should be \smashed. Maybe the customer isn’t always right… – Mico May 07 '22 at 09:56
  • @Mico oh certainly, first rule of tex support is never believe the OP:-) but since the question says "Make \smash only affect vertical spacing." you might want to mention that you havn't addressed that part. – David Carlisle May 07 '22 at 10:25
  • @DavidCarlisle - Are we looking at the same thong? IMNSHO, the middle of the three paragraphs in my answer -- which is the only one for which the Lua funtion is acitive -- very much affects the line spacing. – Mico May 07 '22 at 11:05
  • @Mico yes it affects vertical spacing but the question is mainly (as I read it) about how to make \smash only affect vertical spacing. The standard definition uses an \hbox so freezes all horizontal space making it wider on tight lines and narrower on loose lines. That does not show here as you just have a fraction so no horizontal space in the math. but would affect the space around = in the original example – David Carlisle May 07 '22 at 11:15
  • @Mico this might be a partial answer to an issue I've been having with line spacing too. Could you perhaps also use the luacode to auto smash all letters in the text with descenders e.g. p, q, g etc. ? If so, could you please add the code showing how to do this? – wrb98 Oct 30 '23 at 14:51
  • 1
    @wrb98 - You could replace ( s:gsub ( "%b$$" , "\\smash{%1}" ) with ( s:gsub ( "([gpqy])" , "\\smash{%1}" ). Note that you will have to use \SmashOff ahead of any and all control words, so as to avoid a macro such as \go being "processed". Note also that with this approach, any kerning pairs involving the four characters would be ignored. If that's a problem, give ( s:gsub ( "(%a+)" , "\\smash[b]{%1}" ) a try. (%a is Lua's "magic character" to match any letter, and + means "one or more repetitions".) Remark: you'll need to load the amsmath package for the [b] option. – Mico Oct 30 '23 at 15:40
  • That's great! Is there a way to combine the two cases rather than replace one? – wrb98 Oct 30 '23 at 16:08
  • @wrb98 - I'm afraid I don't understand what you mean by "combine the two cases". To me, the two substitutions -- s:gsub ( "([gpqy])" , "\\smash{%1}" ) and s:gsub ( "(%a+)" , "\\smash[b]{%1}" ) -- are mutually exclusive. I don't think they can be combined meaningfully. – Mico Oct 30 '23 at 16:11
  • Oh, sorry. To clarify: I meant combining smashing the letters in the text with descenders and whatever is in $$ (math) – wrb98 Oct 30 '23 at 16:20
  • @wrb98 - Thanks for providing this clarification. Short answer: "It's possible." Slightly longer answer: First, change return ( s:gsub ( "%b$$" , "\\smash{%1}" ) ) to s = s:gsub ( "%b$$" , "\\smash{%1}" ). Second, add two more lines to the Lua smash function: s = s:gsub ( "(%a+)" , "\\smash[b]{%1}" ) and return s. – Mico Oct 30 '23 at 16:27
  • Ok, so I have \begin{luacode} function smash ( s ) s = s:gsub ( "%b$$" , "\smash{%1}" ) s = s:gsub ( "(%a+)" , "\smash[b]{%1}" ) return s end \end{luacode}, but this seems to be giving me the error "! Missing $ inserted. $ l.42 {\smash[b]{mt} -\smash[b]{LatinModernRoman}.\smash[b]{cfg}}[2021/02/21 \..." – wrb98 Oct 30 '23 at 16:39
  • @wrb98 - After thinking about the issue, I realize that the suggestion I made is sadly not going to work, since it's going to keep \SmashOff from working properly. Sorry for wasting your time. – Mico Oct 30 '23 at 17:22
  • Is there any other way to achieve the desired effect of automatically smashing all descenders and math in $$? – wrb98 Oct 30 '23 at 17:30
  • @wrb98 - There probably is, but it almost certainly exceeds my Lua-related programming skills. May I suggest you post a new query? That way, others may have a chance at answering you query. – Mico Oct 30 '23 at 17:33