I'll start with a little background info. Maybe it will help find an alternative solution.
I have made a few macros for simple indented lists, text-editor-efficient (just add or remove an x
to change indentation). All this by changing \leftskip
, which just worked. But then I decided to save some space by attaching the description text \descr
to the item before it – without ending a paragraph but still I want the continuation of this description to have a larger indentation. The code below does this wrong. \desc
in fact increases indentation of the paragraph it is appended to.
Here's my current code. I'm using LaTeX, although it may not look like it:
\newdimen\ListSkip\ListSkip=1cm
\def\nox{\par\bigskip\leftskip=0pt\normalsize\rm\relax}
\def\x{\par\leftskip=0pt\Large\rm\bfseries\relax}
\def\xx{\par\leftskip=1\ListSkip\normalsize\rm\bfseries\relax}
\def\xxx{\par\leftskip=2\ListSkip\normalsize\rm\relax}
\def\desc{\quad\leftskip=3\ListSkip\footnotesize\sf\relax}
\x First Chapter.
\xx A few words from our sponsor.
\xx Theory of ABC explained in detail.
\xxx The scientifical world just a few years back.
\xxx First important discovery.
\desc Here I will describe how professor Humblegoat made the miraculous discovery of the relation behind this theory while he was electroshocked in his bathtub.
\xxx Ground-breaking changes in physical concepts.
\nox Normal text again here.
This renders as:
The problem is, that First important discovery is now more indented than The scientifical world… \leftskip
obviously isn't the right tool to use in \desc
. If instead of it I use \hangindent=1\ListSkip\hangafter=1
the result is correct but how do I know the current line in a paragraph that I can use in \hangafter
?
Best Answer
The simple answer is: you can't. TeX doesn't know which element of a paragraph falls onto which line before it is actually breaking the paragraph into line and that happens on when it counters the
\par
command or an empty line that finishes the paragraph. However, by that time all macro processing within the paragraphs has taken place and thus this information is not available to the macro processing.Thus, if the the material before the description is more than one line, e.g.
then there is no way to detect this if it all happens in a single paragraph. And there is another problem with this setup: you change the
\baselineskip
midway as you are changing the font size for the description. But again TeX only looks once at the\baselineskip
for a paragraph (when it hits\par
). Thus your first two lines would already be in the smaller baselineskip but with a larger font.So having said all this, there is a sneaky way to make it work: split the material in two paragraphs and ensure that the second one has the right kind of indentation on its first line. The trick is to use a math display feature which allows us to obtain the length lof the last line preceding the display. So at begin of
\desc
we interrupt the current paragraph with a math display, record the size of the precious line. Then back up by whatever space the empty display has added to the page. Then set up producing the new paragraph and continue.The fairly horrible code for this looks as follows:
If we apply this definition to the example (with the extra line after
\xxx First ...
) we get the following result:which should be the expected result.
What happens behind the scence can be seen if one looks at the generated material on the final page (via
\showoutput
). The relevant portion here is:You can see the various penalties and skips that are added by the display (and the empty box representing the display) and the kerns and skips that got added to counter balance this. You also see the different baselineskips due to the different font sizes.
One final comment:
Splitting a paragraph this way can have side effects, especially if such code is imbedded into the LaTeX machinery, which has its own set of peculiarities around paragraph handling (like internally redefining
\everpar
in places, etc.). Thus one need to be careful and one has to be prepared to dig into the LaTeX2e kernel code in case of trouble.One general side effect worth mentioning is the following: the last line of a paragraph when broken by TeX is always set without any stretch while lines in the middle of a paragraph may be set somewhat loose or tight depending on the circumstances. This means that artificially splitting the paragraph in this manner reduces the options TeX has to find optimal line breaks and may alter the paragraph even if otherwise everything would be kept the same (i.e., no margin changes and so on). In particular the last line of the first paragraph and the first line of the last paragraph will not necessarily have the same "looseness", the latter might be set very loose or tight while the former always has spaces at their natural width.