23

I need to format extremely long strings of text. I would like to be able to specify their width, and have them wrap, with or without some special symbol to indicate that the line is wrapped. The problem is, however, that these strings do not contain any spaces. Here's an example of what I would like:

\foo{2in}
{17823941237490812347123904712389407123408917234890123748912034712985712389012351}

So I would like to get an hbox containing this long number, but spanning several lines, so that I get a rectangle 2in wide.

Does anyone know of a package/trick/macro that does this?

lockstep
  • 250,273

5 Answers5

18

You may try the seqsplit package.

  • 2
    Nice! There was bound to be a package that does it; I'd never heard of seqsplit before. For completeness I add a compilable example in a separate answer (hope you don't mind). – Hendrik Vogt Nov 30 '10 at 13:10
  • I tend to give the user some credit for basic intelligence. The package is very easy to handle. In case of problems I'm sure we will see follow-ups. – Thorsten Donig Dec 01 '10 at 17:02
  • 4
    Agreed, it's very easy. Nevertheless, if one has time to post it, then some code for copy and paste is always nice. (By the way, if you had used "@Hendrik" in your comment, then I'd found it much earlier.) – Hendrik Vogt Dec 13 '10 at 19:03
  • Just click the envelope symbol on the left of your name at the top of the page when logged in to get new replies. Furthermore I know when it is suggestive to post code. Trying to rule others how to post is not a good idea. – Thorsten Donig Dec 17 '10 at 22:25
  • 4
    Just found your comment. (Again, as I said, if you had used "@Hendrik", then I'd found it much earlier. I do know about the (now gone) envelope and the inbox, but they rely on the use of "@"!) Concerning posting code: I'm not trying to rule others, I'm just suggesting that it's nice to post code. I've actually upvoted your answer a long time ago since it is very useful (and my suggestion was about how to make it even more useful). – Hendrik Vogt Mar 17 '11 at 09:36
13

Something along these lines perhaps:

\def\breaknumberanywhere{\hskip0pt\futurelet\next\breaknumberi}
\def\breaknumberi{\ifcat\next9\expandafter\breaknumberii\fi}
\def\breaknumberii#1{#1\breaknumberanywhere}

\def\foo#1#2{\vtop{\hsize=#1\rightskip=0pt plus 1fil \leftskip=0pt
  \noindent\breaknumberanywhere#2}}

Here is a long number:
\foo{2in}
{17823941237490812347123904712389407123408917234890123748912034712985712389012351}
\bye

(Edited to become a minimal working example, as requested in a comment. LaTeXifization left to the interested reader. I also set \leftskip in order to make \foo a bit more robust.)

  • Nice! Could you make an MWE out of that? One possible simplification: Replace \discretionary{}{}{} with \hskip0pt or \hspace{0pt}. (I just wanted to post an answer, too, but mine was very inefficient.) – Hendrik Vogt Nov 29 '10 at 18:42
  • I've been looking for a good example that explains \futurelet; this might be it. – Matthew Leingang Nov 29 '10 at 18:59
  • @Hendrik: What is an MWE? – Harald Hanche-Olsen Nov 29 '10 at 19:07
  • @Harald: Oops, sorry: Minimal working example, i.e., a code that compiles as is. – Hendrik Vogt Nov 29 '10 at 19:13
  • Okay, MWE provided. Nobody said I couln't use plain TeX. Oh, and I changed the \discretionary into \hskip. Good suggestion; thanks. – Harald Hanche-Olsen Nov 29 '10 at 19:27
  • This is great! Thanks! But is the vertical size wrong? For example, if you wrap it with $\left( \foo{2in}{1234...} \right)$ then the parenthesis are way taller than the actual text. I'm not even sure what is the reason for the lager height of the box. – Mayer Goldberg Nov 29 '10 at 19:37
  • That comes from the use of \vtop. If you want to use this in math, you should probably use \vcenter instead. I just went with \vtop because I had no idea where and how you were going to use it. – Harald Hanche-Olsen Nov 29 '10 at 19:53
  • Hello Again:

    Here is how I used Harald's macro:

    \font\breaknumberfont=cmsy10 \def\breaknumberanywhere{\discretionary{{\breaknumberfont{\char105}}}{}{}\futurelet\next\breaknumberi} \def\breaknumberi{\ifcat\next9\expandafter \breaknumberii\fi} \def\breaknumberii#1{#1\breaknumberanywhere} \def\longnumber#1#2{\left{\vcenter{\hsize=#1\rightskip=0pt plus 5pt \noindent\breaknumberanywhere#2}\right}}

    – Mayer Goldberg Dec 01 '10 at 09:40
  • Can breakanywhere be modified to just break when the total of all the character boxes =\linewidth? – Jonathan Komar Jun 23 '16 at 09:14
  • @macmadness86 One can certainly make a macro to do that, but it's sufficiently different that I can't easily answer the question here. You might wish to make it a new question. Basically, you would collect digits one by one, measure the width of the collected string so far, and then insert a break when the threshold is reached, then start over with the remaining digits. – Harald Hanche-Olsen Jun 23 '16 at 18:12
  • @HaraldHanche-Olsen Thanks! Actually, I found a way to achieve that for any character. For reference, see this question: http://tex.stackexchange.com/questions/316329/how-can-i-make-latex-to-recognize-spaces-in-my-macro-catcode-10 – Jonathan Komar Jun 24 '16 at 05:23
  • I tried using this solution in the case of using an \href with a long \url but I couldn't get pdflatex to compile on overleaf. Any ideas on this? – Steven Jun 18 '23 at 09:15
13

Thorsten told you what package to use; just for completeness I give a compilable example:

\documentclass{article}
\usepackage{seqsplit}
\newcommand\foo[2]{%
    \begin{minipage}{#1}
    \seqsplit{#2}
    \end{minipage}
    }
\begin{document}
\foo{2in}
{17823941237490812347123904712389407123408917234890123748912034712985712389012351}
\end{document}
Hendrik Vogt
  • 37,935
  • I tried using this solution in the case of using an \href with a long \url but I couldn't get pdflatex to compile on overleaf. Any ideas on this? – Steven Jun 18 '23 at 09:15
6

A general solution with expl3; the command \foo has an optional argument that can be any character or box to mark the splitting point. With varwidth we round the box width to what is really necessary.

\documentclass{article}
\usepackage{varwidth}
\usepackage{xparse}

\setlength{\parindent}{0pt} % just for the example

\ExplSyntaxOn

\NewDocumentCommand{\foo}{ O{} m m } { % some setup for the particular problem \begin{varwidth}[t]{#2} % some padding on the right \skip_set:Nn \rightskip { 0pt plus .5em } % just in case \skip_set:Nn \leftskip { 0pt } % a strut to set the first row height \strut

% the main routine \mayer_foo:nnn { #1 } { #2 } { #3 }

% finish off with a strut (attached from the last digit) \strut \end{varwidth} }

\seq_new:N \l_mayer_input_seq

\cs_new_protected:Npn \mayer_foo:nnn #1 #2 #3 { % split the input into pieces \seq_set_split:Nnn \l_mayer_input_seq { } { #3 }

% between any two pieces insert a discretionary \seq_use:Nn \l_mayer_input_seq { \discretionary{#1}{}{} } }

\ExplSyntaxOff

\begin{document}

\rule{2in}{0.4pt}

\foo{2in} {17823941237490812347123904712389407123408917234890123748912034712985712389012351}

\foo[-]{2in} {17823941237490812347123904712389407123408917234890123748912034712985712389012351}

\foo[*]{2in} {17823941237490812347123904712389407123408917234890123748912034712985712389012351}

\bigskip The box doesn't take more than the stated space\ (but it can be slightly less wide)

\medskip

\fbox{\foo{2in} {17823941237490812347123904712389407123408917234890123748912034712985712389012351}}

\end{document}

enter image description here

For completeness, a version where the normal text width is used, without boxing.

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\foo}{ O{} m } {% #1 = discretionary, #2 = number to split \mayer_foo:nn { #1 } { #2 } }

\cs_new_protected:Nn \mayer_foo:nn { \tl_map_inline:nn { #2 } { ##1 \nobreak\hspace{0pt plus 0.1pt}\discretionary{#1}{}{} } }

\ExplSyntaxOff

\begin{document}

\noindent \foo{ 17823 94123 74908 12347 12390 47123 89407 12340 89172 34890 12374 89120 34712 98571 23890 12351 12374 89120 34712 98571 17823 94123 74908 12347 12390 47123 89407 12340 89172 34890 12374 89120 34712 98571 23890 12351 12374 89120 34712 98571 17823 94123 74908 12347 12390 47123 89407 12340 89172 34890 12374 89120 34712 98571 23890 12351 12374 89120 34712 98571 }

\noindent \foo[-]{ 17823 94123 74908 12347 12390 47123 89407 12340 89172 34890 12374 89120 34712 98571 23890 12351 12374 89120 34712 98571 17823 94123 74908 12347 12390 47123 89407 12340 89172 34890 12374 89120 34712 98571 23890 12351 12374 89120 34712 98571 17823 94123 74908 12347 12390 47123 89407 12340 89172 34890 12374 89120 34712 98571 23890 12351 12374 89120 34712 98571 }

\noindent \foo[\hbox{$*$}]{ 17823 94123 74908 12347 12390 47123 89407 12340 89172 34890 12374 89120 34712 98571 23890 12351 12374 89120 34712 98571 17823 94123 74908 12347 12390 47123 89407 12340 89172 34890 12374 89120 34712 98571 23890 12351 12374 89120 34712 98571 17823 94123 74908 12347 12390 47123 89407 12340 89172 34890 12374 89120 34712 98571 23890 12351 12374 89120 34712 98571 }

\end{document}

enter image description here

The example shows that if the discretionary to be used is something more complex than a character, it should be enclosed in \hbox.

egreg
  • 1,121,712
  • I tried using this solution in the case of using an \href with a long \url but I couldn't get pdflatex to compile on overleaf. Any ideas on this? – Steven Jun 18 '23 at 09:31
  • @Steven Did you see https://tex.stackexchange.com/q/54946/4427 ? – egreg Jun 18 '23 at 09:35
  • Thanks for pointing that out. I took a look and I have tried using thexurl package, but it did not solve my issue. If you are interested, I have posted a MWE here: https://tex.stackexchange.com/questions/688829/wrapping-long-url-hyperlinks-that-contain-no-spaces-within-a-table?noredirect=1#comment1709052_688829 – Steven Jun 18 '23 at 10:03
4

This is a very old post. I am adding one solution, thinking that this answer may be helpful for any one who arrives here:

\documentclass{article}
\begin{document}

\makeatletter
\def\foo#1#2{%
  \parbox{#1}{\strut\@tfor\xx:=#2\do{%
    \xx\linebreak[0]%
  }\strut}%
}

\foo{2in}
{17823941237490812347123904712389407123408917234890123748912034712985712389012351}

\foo{3in}
{17823941237490812347123904712389407123408917234890123748912034712985712389012351}
\end{document}
Jagath
  • 4,287
  • I tried using this solution in the case of using an \href with a long \url but I couldn't get pdflatex to compile on overleaf. Any ideas on this? – Steven Jun 18 '23 at 09:14
  • @Steven Not until you minimize the example. – egreg Jun 18 '23 at 10:09