[Tex/LaTex] When is it good practice to use \unskip

spacingtex-core

One sees in source2e the command \unskip used in various places. My understanding in general terms is that the macro is the equivalent of \ignorespacesbehind.

Where would it be recommended to use \unskip?

MWE for experimentation:

\documentclass{article}
\usepackage{lipsum}
\begin{document}
\lipsum[1]
\def\test{\leavevmode \unskip test  }
\def\testa{\leavevmode test\ignorespaces  }

\test testing  \test 

\testa testing  \testa test
\end{document}

Best Answer

In addition to @Josephs's points, things to be aware of:

  • \unskip acts on horizontal and vertical space, so it will remove vertical space if used between paragraphs.

  • Unlike \ignorespaces which affects the conversion between input characters and tokens, \unskip works on the actual lists inside boxes, after all tokenisation and commands have been executed.

  • \unskip can not be used in outer vertical mode: Once an item has been added to the main vertical list of a page it can not be removed. So while in a minipage you can remove preceding vertical space with \unskip, on the main page you have to use \vskip-\lastskip to back up over the previous skip rather than actually removing it. This leaves breakable glue so you may also need to inject some \penalties to prevent page breaking.


Consider:

\documentclass{article}

\showoutput
\begin{document}

\setbox0\vbox{

\hbox{g}

\vskip 10pt

\hbox{b}
}

\showbox0


\setbox2\vbox{

\hbox{g}

\vskip 10pt

\unskip\nobreak\hbox{b}
}

\showbox2

\setbox4\vbox{

\hbox{g}

\vskip 10pt

\vskip-\lastskip\nobreak\hbox{b}
}

\showbox2


\hbox{g}

\vskip 10pt

\unskip\nobreak\hbox{b}


\stop

Box 0 is

\vbox(26.30554+0.0)x5.55557
.\hbox(4.30554+1.94444)x5.00002
..\OT1/cmr/m/n/10 g
.\glue 10.0
.\glue(\baselineskip) 3.11111
.\hbox(6.94444+0.0)x5.55557
..\OT1/cmr/m/n/10 b

But suppose (as in box 2) That the code adding b needs to remove space above, it could use \unskip which literally removes it, resulting in

\vbox(16.30554+0.0)x5.55557
.\hbox(4.30554+1.94444)x5.00002
..\OT1/cmr/m/n/10 g
.\penalty 10000
.\glue(\baselineskip) 3.11111
.\hbox(6.94444+0.0)x5.55557
..\OT1/cmr/m/n/10 b

If instead of removing it, negative space is added to compensate as n box 4 then you get

\vbox(16.30554+0.0)x5.55557
.\hbox(4.30554+1.94444)x5.00002
..\OT1/cmr/m/n/10 g
.\glue 10.0
.\glue -10.0
.\penalty 10000
.\glue(\baselineskip) 3.11111
.\hbox(6.94444+0.0)x5.55557
..\OT1/cmr/m/n/10 b

This looks the same but if the penalty was not 10000 then it would be a feasible breakpoint at that position, which means that if the list was unboxed the end of the first part would have depth 0 rather than the depth of g which can have subtle (or not so subtle) affects on positioning that are hard to correct (or at least hard to remember to correct).

So the issues surrounding \unskip are a lot simpler than the vskip-\lastskip combination, however if you are not in a box, you don't have a choice, as the last version on the main page produces:

! You can't use `\unskip' in vertical mode.
l.46 \unskip
Related Question