Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Is there a way to define a function \horizontallengthof returning the length of a piece of text in internal units? I would like to be able to use it anywhere where something of that sort is required, for example like p{\horizontallengthof{this particular piece of text}} (in a table specification) or \hspace{\horizontallengthof{this particular piece of text}}.


I am hesitant to post a particular use case, since I am interested in a generic solution instead of workarounds for particular situations. But here is one (with calc's \widthof standing in for \horizontallengthof):

\documentclass{article}
\usepackage{fixltx2e}
\usepackage{calc}

\begin{document}

\begin{tabular}{p{0em}@{\hspace{1.0em}\quad}l@{\qquad}l}
  \(\bullet\) & \(x = y\) & \(z = w\) \\
  \(\bullet\) & \(a = b\) & \(c = d\) \\
\end{tabular}

\begin{tabular}{p{\widthof{\(\bullet\)}}@{\hspace{1.0em}\quad}l@{\qquad}l}
  \(\bullet\) & \(x = y\) & \(z = w\) \\
  \(\bullet\) & \(a = b\) & \(c = d\) \\
\end{tabular}

\begin{tabular}{p{\widthof{\(\bullet\)}}@{\hspace{1.0em-\widthof{\(\bullet\)}}\quad}l@{\qquad}l}
  \(\bullet\) & \(x = y\) & \(z = w\) \\
  \(\bullet\) & \(a = b\) & \(c = d\) \\
\end{tabular}

\end{document}

With the suggestion to add fixltx2e, this compiles properly, but I'd like the second table to have the same appearance (spacing-wise) as the first one, while giving me no Overfull \hbox warnings. Table 3 is a failed attempt at achieving this.

One reason why I didn't initially post this is that I didn't want any potential workarounds to this distract from a general (and imho needed) solution.

share|improve this question
2  
\usepackage{calc} and then \hspace{\widthof{text}} –  egreg Feb 21 '13 at 11:08
1  
Hmm, if I try \documentclass{article} \usepackage{calc} \begin{document} a\hspace{\widthof{some text}}b \end{document}, I get a ! Missing number, treated as zero. error. –  Lover of Structure Feb 21 '13 at 11:25
1  
fragile command, moving argument add \usepackage{fixltx2e} and then \( is robust (or you could just use $ which is robust anyway) –  David Carlisle Feb 21 '13 at 11:52
1  
\begin{tabular}{l@{\qquad}l@{\qquad}l} \rlap{\(\bullet\)} & \(x = y\) & \(z = w\) \ \rlap{\(\bullet\)} & \(a = b\) & \(c = d\) \\end{tabular} –  egreg Feb 21 '13 at 12:34
1  
It shouldn't clash with any package, it is part of the core (but you don't need it for this anyway:-) –  David Carlisle Feb 21 '13 at 12:47

4 Answers 4

up vote 11 down vote accepted

Hmm arguably this is a calc and/or LaTeX bug.

using calc and \widthof would work in most of the places you mention (as in LaTeX2e such places explicitly changed to use \setlength internally so that they would work with calc. However \hspace appears to have escaped that conversion, the following patch fixes that.....

\documentclass{article}

\usepackage{calc} 

\makeatletter
\def\@hspace#1{\begingroup\setlength\dimen@{#1}\hskip\dimen@\endgroup}
\makeatother

\begin{document}

 a\hspace{\widthof{some text}}b 

\end{document}

The above answers the original question, but the later edits have clarified that this is not needed at all. \widthof is a relatively expensive operation and doing every row just to make space to insert the same text you measured is really just torturing your computer for no real gain. The formulation in the second table matches the version you gave in the first without the over full boxes and without measuring anything.

enter image description here

\documentclass{article}
\usepackage{fixltx2e}
\usepackage{calc}

\begin{document}

\begin{tabular}{p{0em}@{\hspace{1.0em}\quad}l@{\qquad}l}
  \(\bullet\) & \(x = y\) & \(z = w\) \\
  \(\bullet\) & \(a = b\) & \(c = d\) \\
\end{tabular}

\begin{tabular}{@{\hspace\tabcolsep\rlap{$\bullet$}\hspace{1.0em}\quad}l@{\qquad}l}
   \(x = y\) & \(z = w\) \\
   \(a = b\) & \(c = d\) \\
\end{tabular}

\end{document}
share|improve this answer
    
Since you're on the LaTeX team, should someone (eg me) still report a bug? To whom? (See this question of mine on meta about the reporting of bugs.) –  Lover of Structure Mar 1 '13 at 3:50
    
@LoverofStructure yes well you could report it, just type latex latexbug and follow the instructions. Not sure we'd change it (it is computationally very expensive and might break some non standard uses of hspace) but it could at least be documented. –  David Carlisle Mar 1 '13 at 8:27
    
Done. (I've used the webform instead.) –  Lover of Structure Mar 1 '13 at 12:15
    
To others: Please see egreg's answer, which also gets credit and complements this one. –  Lover of Structure Mar 2 '13 at 0:56
    
@LoverofStructure Thanks, the mail server had got stuck, we kicked it and the bug report is now listed as latex-project.org/cgi-bin/ltxbugs2html?pr=latex/4209 –  David Carlisle Mar 4 '13 at 10:40

calc patches some of the main LaTeX constructs so that an extended syntax is accepted. However, it doesn't do the same for \hspace.

The command \widthof can be used in \setlength and in the argument to \parbox, minipage and also in the p-column specifier.

You can get a version of \hspace that works with \widthof, but I wouldn't use it as a replacement.

\documentclass{article}
\usepackage{xparse,calc}
\newlength\Hspacelen
\NewDocumentCommand{\Hspace}{sm}
 {\setlength\Hspacelen{#2}%
  \IfBooleanTF{#1}
    {\hspace*{\Hspacelen}}
    {\hspace{\Hspacelen}}%
 }

\makeatletter
%\def\Hspace#1#{\@Hspace{#1}}
%\def\@Hspace#1#2{\setlength\@tempdima{#2}\hspace#1{\@tempdima}}
\makeatother

\begin{document}
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

a\Hspace{\widthof{text}}b

\Hspace*{\widthof{text}}ab
\end{document}

The commented version is a faster alternative.

However, since you probably don't want a space that disappears at page breaks, the faster method is to say

\leavevmode\hphantom{text}

Don't forget \leavevmode at the start of a paragraph; it's irrelevant if \hphantom is in the middle of a paragraph.

share|improve this answer
    
+1 I think you two found the "right" answer jointly (see comment thread to original question above). This was a very close call. You ultimately have more details on the actual question. It won't hurt for people to upvote yours equally. –  Lover of Structure Mar 2 '13 at 0:58

Does \wd works ?

E.g:

\newsavebox{\mymeasure} % only 1 time, in the preamble

Then:

\sbox{\mymeasure}{this particular piece of text}
X\hspace{\wd\mymeasure}X

So, to have just 1 command, in your preamble:

\newsavebox{\mymeasure}
\newcommand{\measure}[1]{\sbox{\mymeasure}{#1}\wd\mymeasure}

Usage:

X\hspace{\measure{this particular piece of texte}}X

share|improve this answer
    
No :-( Here is minimal example code: \documentclass{article} \begin{document} X\hspace{\wd\mbox{some text}}X \end{document} –  Lover of Structure Feb 21 '13 at 10:54
    
Ok, \wd seems to operate on box only; I have modified my answer –  Lionel MANSUY Feb 21 '13 at 10:59
    
Thanks for your efforts! Now if I try \documentclass{article} \newsavebox{\mymeasure} \newcommand{\measure}[1]{\sbox{\mymeasure}{#1}\wd\mymeasure} \begin{document} a\hspace{\measure{some text}}b \end{document}, that gives me a "Missing number, treated as zero." error. –  Lover of Structure Feb 21 '13 at 11:16
2  
@LoverofStructure Of course it doesn't work this way. Box assignment \sbox cannot be in expandable context, and TeX tries to expand everything when it is looking for dimensions. You would have to use the first option suggested by Lionel: place \sbox\mymeasure{some text} before the \hspace, and then use \hspace{\wd\mymeasure} –  yo' Feb 21 '13 at 12:22
1  
No, \hspace{#1}, as is, internally uses \kern#1. The macro \kern expands what follows as long as needed to get <number><unit>, expanding all \skip and \dimen (lengths) and \ht, \wd, \dp too (box measurements), then it continues looking for plus or minus part of the skip. Since \sbox is not expandable, \kern complains that it has not found the skip value yet and hit a non-expandable barrier. –  yo' Feb 21 '13 at 12:41

This is how I do it.

\documentclass{article}
\begin{document}
\newcommand\findwidth[1]{\setbox0\hbox{#1}\the\wd0}
This text is how long? \findwidth{This text is how long?}
\par\rule{\wd0}{1ex}
\end{document}
share|improve this answer
1  
LaTeX has a standard \settowidth command for saving the width of some known text in advance, The trick calc plays is to allow this to be used inline rather than boxing the text first. –  David Carlisle Feb 21 '13 at 12:36

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.