[texhax] Finding the widest string

Stephen Hicks sdh33 at cornell.edu
Tue May 4 08:37:43 CEST 2010


Here's a minimally different fix:

========
\documentclass[12pt,a5paper]{article}

\def\Format#1{{\itshape\tiny #1}}

\newbox\Box
\newdimen\WidthOther

\def\Widest#1#2(#3){%   dimension (the result)    formatter    list of strings
 \def\EndList{\EndList}%
 \def\xWidest##1,{%
   \def\temp{##1}%
   \ifx\temp\EndList
   \else
     \setbox\Box\hbox{#2{##1}}%
     \WidthOther=\wd\Box
     \ifdim#1<\WidthOther
       #1=\WidthOther
     \else
     \fi
     \expandafter\xWidest
   \fi
 }%
 \xWidest#3,\EndList,%
}

\begin{document}

\newdimen\mydim
\Widest{\mydim}{\Format}(Good,morning,world)
\the\mydim

\end{document}
========

You had three bugs and one almost-bug.

1. the syntax of \setbox is \setbox<number>=<box>, where <number> is
\Box, = is optional, and <box> is \hbox{...}.  Note that there is no
extra brace here.  So it needs to go \setbox\Box\hbox{...} or
\setbox\Box=\hbox{...} but not \setbox\Box{\hbox{...}}

2. When \xWidest picks up "\EndList", it does not get expanded.
Here's the trace (set \tracingmacros=1 and check the log file):
  \xWidest #1,-> (snip)
  #1<-\EndList
So when you \def\temp{#1}, you end up with
  \temp=macro: ->\EndList
but
  \EndList=macro: ->xxx
so \ifx\temp\EndList will be false even in this case.
The quick and dirty solution is to \def\EndList{\EndList} so that (a)
\temp is the same as \EndList, and (b) no normal text input can end
the list.

3. The newline after "\EndList," will cause unwanted space if you
happen to be in horizontal mode.

4. Your \newbox and \newdimen are inside your macro.  I was surprised
it compiled at all, since plain TeX forbids this by declaring all the
\newX macros as \outer.  But just because LaTeX allows this doesn't
mean it's good practice - you don't want to allocate new box and dimen
registers every time anyone calls the macro!

Other than that, your code looks great!  If you're interested, here's
how I might have written the same macro:

========
\makeatletter
\def\wid at helper#1,{%
  \def\wid at arg{#1}%
  \ifx\wid at arg\wid at end
    \let\wid at next\relax
  \else
    \setbox\z@\hbox{\wid at fmt{#1}}%
    \ifdim\wd\z@>\dimen@
      \dimen@\wd\z@
    \fi
  \fi
  \wid at next
}
\def\Widest#1#2(#3){\begingroup
  \dimen@\z@
  \def\wid at end{\wid at end}%
  \def\wid at fmt{#2}%
  \let\wid at next\wid at helper
  \wid at next#3,\wid at end,%
  \expandafter\endgroup\expandafter#1\the\dimen@\relax
}
\makeatother
========

A few things in particular to notice: first, avoiding nested
definitions makes it easier to read; second, I wrap everything in a
\begingroup...\endgroup to keep the scope clean.  It's a very strange
case, but the following
  \Widest{\mydim}{\Format}(\@firstofone{\Widest\mydim\Format(aaaaaa)})
will cause wrong behavior without the local scope.

Keep up the haxing!
steve

2010/5/3 José Romildo Malaquias <j.romildo at gmail.com>:
> Hello.
>
> Given a list of strings, I have to find the widest one.
>
> I have tried to implement a macro for that, but it does not work. Any help is welcome.
>
>
>
> \documentclass[12pt,a5paper]{article}
>
> \def\Format#1{{\itshape\tiny #1}}
>
> \def\Widest#1#2(#3){%   dimension (the result)    formatter    list of strings
>  \def\EndList{xxx}%
>  \newbox\Box
>  \newdimen\WidthOther
>  \def\xWidest##1,{%
>    \def\temp{##1}%
>    \ifx\temp\EndList
>    \else
>      \setbox\Box{\hbox{#2{##1}}}%
>      \WidthOther=\wd\Box
>      \ifdim#1<\WidthOther
>        #1=\WidthOther
>      \else
>      \fi
>      \expandafter\xWidest
>    \fi
>  }%
>  \xWidest#3,\EndList,
> }
>
> \begin{document}
>
> \newdimen\mydim
> \Widest{\mydim}{\Format}(Good,morning,world)
> \the\mydim
>
> \end{document}
>
>
> Regards,
>
> Romildo
> _______________________________________________
> TeX FAQ: http://www.tex.ac.uk/faq
> Mailing list archives: http://tug.org/pipermail/texhax/
> More links: http://tug.org/begin.html
>
> Automated subscription management: http://tug.org/mailman/listinfo/texhax
> Human mailing list managers: postmaster at tug.org
>



More information about the texhax mailing list