# How do you change indentation in the middle of a paragraph?

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}

\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?

-
I'm really confused at what you're asking here. Unless your \xxx heading runs into a second line, \desc is always on the first line in a paragraph. And that isn't necessary information anyways, since \hangindent=1\ListSkip works just fine without \hangafter. –  rdhs Feb 22 '12 at 0:49
\xxx heading may be longer and run into the second line. That is why I don't assume that I can indent everything after the first line in the paragraph. –  Frg Feb 22 '12 at 8:14
perhaps the question title should be changed to something like "How do you change the \leftskip in the middle of a paragraph?" because this is really what it is about. –  Frank Mittelbach Feb 22 '12 at 13:20
You are right. I've updated the title now. –  Frg Feb 22 '12 at 17:20

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?

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.

\xxx First important discovery. And it takes more than a line in the document. Or perhaps more.
\desc Here I will describe how professor Humblegoat ...


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 \baselineskipfor 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:

\newdimen\lastlinewidth

\def\desc{%
\begingroup
\predisplaypenalty=10000
\postdisplaypenalty=10000
\abovedisplayskip=0pt
\abovedisplayshortskip=0pt
\belowdisplayskip=-\baselineskip
\belowdisplayshortskip=-\baselineskip
$$\global\lastlinewidth\predisplaysize \global\advance\lastlinewidth by -2em$$%
\endgroup
\footnotesize\sf\relax
\vskip-\baselineskip             % backup by the baselineskip about to come for the new text (depends on new font size!)
\vskip-\parskip                  % and the parskip being added
\noindent\kern\lastlinewidth     % start new paragraph for "description"
\leftskip=0pt                    % cancel any \leftskip
\hangindent=3\ListSkip           % but instead use \hangindent from the start
}


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:

....\OT1/cmr/m/n/10 m
....\OT1/cmr/m/n/10 o
....\OT1/cmr/m/n/10 r
....\OT1/cmr/m/n/10 e
....\OT1/cmr/m/n/10 .
....\penalty 10000
....\glue(\parfillskip) 0.0 plus 1.0fil
....\glue(\rightskip) 0.0
...\penalty 10000
...\glue(\abovedisplayskip) 0.0
...\glue(\baselineskip) 10.05556
...\hbox(0.0+0.0)x0.0, shifted 172.5, display
...\penalty 10000
...\glue(\belowdisplayskip) -12.0
...\glue -9.5
...\glue 0.0 plus -1.0
...\glue(\parskip) 0.0 plus 1.0
...\glue(\baselineskip) 3.94444
...\hbox(5.55556+1.55556)x345.0, glue set 0.09123
....\glue(\leftskip) 85.35823
....\kern 183.98907
....\kern -85.35823
....\glue 8.50012
....\OT1/cmss/m/n/8 H
....\OT1/cmss/m/n/8 e
....\OT1/cmss/m/n/8 r
....\OT1/cmss/m/n/8 e


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.

-
Thank you. Great answer. It solves my problem! –  Frg Feb 22 '12 at 17:19
I have extended your code a bit to fit my list even better and have put it in a separate answer. –  Frg Feb 22 '12 at 17:22

\leftskip works on the paragraph (as far as I understand). For your \desc you could use only the \quad or \hspace*{} or something to move it a bit to the right.

When you get to a new line within your description (text after \desc) it will not be left-aligned with the previous line, but that is caused by the normal indentation of the first line in a \par.

Does the following solve your problem?

\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\noindent\leftskip=2\ListSkip\normalsize\rm\relax}

-
Welcome to TeX.sx! A tip: You can use backticks  to mark your inline code as I did in my edit. –  Tobi Feb 22 '12 at 0:15
You don't have to sign with your name since it automatically appears in the lower right corner of your post. –  Tobi Feb 22 '12 at 0:15
Yes, I ended up doing so as a temporary measure. I'm still eager to know if it is even possible to increase indent on the fly, like I asked. –  Frg Feb 22 '12 at 0:27
This will not add any additional indentation to the lines within the description (as asked by the OP) and it also as the issue with the baselineskip as explained in my answer. –  Frank Mittelbach Feb 22 '12 at 13:02

Big thanks to Frank Mittelbach. This is exactly what I was after. The display math trick is really useful. I have adapted the code from Frank's answer to the needs of my list, so that descriptions work with all levels of indentation and are also spaced well when put in a new paragraph (then no trick is required, hence the added \ifhmode check in the command). I also moved from quad to using this list's standard indentation \ListSkip, in order to avoid different horizontal skips for different em-sizes. This is the updated code:

\newdimen\lastlinewidth
\newdimen\ListSkip\ListSkip=1cm
\def\nox{\par\bigskip\leftskip=0pt\normalsize\rm\relax}
\def\x{\par\noindent\leftskip=0pt\Large\rm\bfseries\relax}
\def\xx{\par\noindent\leftskip=1\ListSkip\normalsize\rm\bfseries\relax}
\def\xxx{\par\noindent\leftskip=2\ListSkip\normalsize\rm\relax}
\def\desc{\ifhmode
\begingroup\predisplaypenalty=10000 \postdisplaypenalty=10000
\abovedisplayskip=0pt \abovedisplayshortskip=0pt
\belowdisplayskip=-\baselineskip
\belowdisplayshortskip=-\baselineskip
$$\global\lastlinewidth\predisplaysize \global\advance\lastlinewidth by -2em$$%
\endgroup
\footnotesize\sf\relax
\vskip-\baselineskip    % backup by the baselineskip about to come for the new text (depends on new font size!)
\vskip-\parskip    % last unmodified line, rest is modified
\noindent\kern\lastlinewidth
\else
\noindent\advance\leftskip by \ListSkip\footnotesize\sf\relax    % in case we already were in a new paragraph
\fi
}

% Let's test it!
\x First Chapter. \desc Gotta start somewhere, right?
\xx Thanks to my family, friends and everybody else I barely know. \desc The usual crap.
\xx A few words from our sponsor. \desc Spam, spam, spam, lovely spam, spam, spam, spam, spam, spam bacon and eggs, spam, spam, spam, spam, spam, spam, spam, eggs, spam, spam, spam, spam, spam, spam, spam, spam, spam, spam, spam, spam, spam, spam, spam, spam!
\xx Theory of ABC explained in detail.
\xxx The scientifical world just a few years back. \desc Short description.
\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.
\xxx First important discovery. And it takes more than a line in the document. Or perhaps a lot more than that.
\desc Here I will describe how professor Humblegoat made the miraculous discovery of the relation behind this theory while he was electroshocked while taking a bath in his house.
\xxx Ground-breaking changes in physical concepts.

\desc Description explicitly placed in new paragraph.
\nox Normal text again here.


And the rendering which looks now exactly like I wanted:

Thanks again!

-
I wouldn't use \hangindentbut stay with setting \leftskip as the former will be reset if you have more than one paragraph –  Frank Mittelbach Feb 22 '12 at 17:35
I have updated the code to use only \leftskip. –  Frg Feb 22 '12 at 17:55
Also added \noindent to list items. –  Frg Feb 22 '12 at 18:00
Next, I'll add a check if \columnwidth - \lastlinewidth - \leftskip < \someminlength` and break the line if it is, to avoid description orphans sticking to the list item. I won't however modify the code posted here - no need to make it even more complicated. –  Frg Feb 22 '12 at 18:19