3

Is it possible to truncate the name of a chapter to - let's say - 20 characters and adding \ldots to it? So that it fits into the space of the tabs shown here?

Harald
  • 761

2 Answers2

6

I mean that better than to set fixed number of characters is to set the maximal dimension of printed text. I suggest the macro \striptext to dimen {text} which outputs the text in the macro \striptextout. The text in \striptextout fits to the hypothetical box of the given width. Other characters (if they exist) are ignored.

For example \striptext to2cm {foo foo bar bar} defines \striptextout as a macro foo foo bar b. Or \striptext to1cm {foo foo bar bar} outputs to foo fo. Or \striptext to30cm {foo foo bar bar} behaves like \def\striptextout{foo foo bar bar}.

\def\striptext to#1 #2{\def\striptextout{}\def\tmp{#1}\striptextA #2\relax\end}
\def\striptextA{\futurelet\next\striptextB}
\def\striptextB{\ifx\next\relax \expandafter \skiptoend
   \else \ifx\next\spacetoken
             \edef\striptextoutA{\striptextout\space}%
             \def\next{\afterassignment\striptextD \let\next= }%
         \else \def\next{\striptextC}%
   \fi   \fi
   \next
}
\def\striptextC#1{\edef\striptextoutA{\striptextout#1}\striptextD}
\def\striptextD{\setbox0=\hbox{\striptextoutA}%
   \ifdim\wd0>\tmp\relax \expandafter \skiptoend
   \else \let\striptextout=\striptextoutA \expandafter \striptextA
   \fi
}
\def\skiptoend#1\end{}
\edef\tmp{\let\noexpand\spacetoken= \space}\tmp

\striptext to1cm {foo foo bar bar}
\message{:::: \striptextout}

\bye

How it works: We need to get token per token from given text, cummulate it to \striptextout and do the measurement of the text in \striptextout repeatedly. The main problem is that TeX cannot simply get the space to the parameter #1. This is the rason why the macro is more complicated. First we test by \futurelet\next if the \next is space token. If it is true then we need to remove spacetoken from input stream by \let\next= (watch the space after equal sign, this first space is ignored by \let primitive and second space is taken from input stream). After \let is done the measurement in \striptextD is processed. The given width is stored in the \tmp macro. If the next token isn't spacetoken then this token is normaly taken by #1 of \striptextC. The masurement in \striptextD is processed ordinarily: the text is stored to \box0 and width \wd0 is compared with \tmp. The \relax here is important because expansion of \ifdim condition have to be closed before next \expandafter. The loop is repeated here by next call of \striptextoutA. The \striptoend macro ignores the rest of input stream to the \end separator. This is executed when we are finished.

Notice about the usage of \striptext: the space after dimen and before {text} is required. If you need to make more common macro (without to clause) in the form

\striptext{dimen}{text}

then simply write \def\striptext#1#2{...} (without space between #1 and #2.

wipet
  • 74,238
2

ConTeXt provides two macros to achieve this.

  1. \doboundtext
  2. \limitatetext

The user interface of both commands is:

\command {text to be limited} {width} {append}

where the first argument can be arbitrary TeX code, the second argument can be arbitrary TeX dimen, and the third argument can be arbitrary TeX code.

The \doboundtext macro is similar to the \striptex macro defined by @wipet; it typesets the content in a box, and then truncates the box. A drawback of this approach is that the text does not hyphenate.

The \limitatetext macro is more robust and allows for the text to break across lines. It also when reading the file, for example

\limitatetext{\input ward \relax}{6cm}{\unknown}

gives

enter image description here

The \limitatetext has another version, that allows you to pick some material from the end as well. For example:

\limitatetext{\input ward \relax}{6cm,2cm}{\unknown}

gives

enter image description here

See supp-box.mkiv for implementation details.

Aditya
  • 62,301
  • @ Aditya; Thanks a lot. I like the the feature picking also the end of the text and will have a try to implement this in PDFLaTex – Harald Jun 10 '14 at 04:21