0

We often find ourselves using nonzero stretch and shrink parts in \hskip and \mskip, typically 50% of the natural space value, e.g., \hskip.1em plus.05em minus.05em or \mskip1mu plus.5mu minus.5mu. How do we automate the computation of the half? In other words, we need something like

\documentclass{standalone}
\newcommand{\mSkipWithHalfStretchAndHalfShrink}[1]{\mskip#1 plus.5#1 minus.5#1}% 50 per cent of the argument after plus and minus. The argument may be any integer or floating-point number.
\showoutput
\begin{document}
\(a\mSkipWithHalfStretchAndHalfShrink{20mu}b\)% expected to expand to \(a\mskip20mu plus10mu minus10mu b\)
\end{document}

Unfortunately, this produces the stretch and shrink parts of around 0.28–0.29 regardless of the integer argument. Moreover, using a decimal point in the argument, such as in \(a\mSkipWithHalfStretchAndHalfShrink{1.5mu}b\), throws an error. We also tried stuff such as \mskip#1 plus\ratio{#1}{2} minus\ratio{#1}{2} using the calc package, however, without success.

3 Answers3

2

The following code shows what we can do simply at TeX primitive level:

\def\hskipflex{\afterassignment\hskipflexA\dimen0=}
\def\hskipflexA{\hskip\dimen0 plus.5\dimen0 minus.5\dimen0 \relax}

\def\mskipflex{\afterassignment\mskipflexA\muskip0=} \def\mskipflexA{\mskip 1\muskip0 plus.5\muskip0 minus.5\muskip0 \relax}

$x\mskipflex 10mu y$ %% does \mskip 10mu plus5mu minus5mu

a\hskipflex 1em b %% does \hskip 1em plus.5em minus.5em

\bye

wipet
  • 74,238
1

I've never used such specifications, let alone “often”, to be honest.

Here's the way:

\NewDocumentCommand{\hspaceflex}{sm}{%
  \IfBooleanTF{#1}{\hspace}{\hspace*}%
  {#2 plus \dimeval{#2/2} minus \dimeval{#2/2}}%
}

% there's no user level interface to \muskip_eval:n (yet) \ExplSyntaxOn \cs_if_exist:NF \muskipeval { \cs_new_eq:NN \muskipeval \muskip_eval:n } \ExplSyntaxOff

\NewDocumentCommand{\mspaceflex}{m}{% \mspace{#1 plus \muskipeval{#1/2} minus \muskipeval{#1/2}}% }

You call them as

\hspaceflex{1em}
\hspaceflex*{1em}
\mspaceflex{4mu}

Note that \mspace requires amsmath.

egreg
  • 1,121,712
0

Like this. With \muexpr.

\documentclass{standalone}
\newcommand{\mSkipWithHalfStretchAndHalfShrink}[1]{\mskip#1 plus .5\muexpr#1\relax minus.5\muexpr#1\relax\relax}% 50 per cent of the argument after plus and minus. The argument may be any integer or floating-point number.
\showoutput
\begin{document}
\(a\mSkipWithHalfStretchAndHalfShrink{20mu}b\)
\(a\mskip20mu plus10mu minus10mu b\)
\end{document}

The documentation is technically in etex_man, although in order to understand what is going on you need to understand the notations in the TeXbook really well.

By the way, it's recommended to add \relax to terminate a dimension expression explicitly. See exercise 27.4 in the book (although it seems safe in this case because minus is the last one already). Here I add two because of the nesting.

user202729
  • 7,143
  • Similar question but with dimexpr: https://tex.stackexchange.com/questions/11346/doing-maths-with-distance-values-in-latex-source-code/11347#11347 -- muexpr is less used. I can find https://tex.stackexchange.com/questions/77820/creating-implication-and-equivalence-symbols-of-intermediate-length/77825#77825 https://tex.stackexchange.com/questions/75247/adaptive-ldots-with-no-spacing/75300#75300 that uses muexpr like that but I assume it's to remove the glue parts instead. – user202729 Sep 16 '22 at 17:28