Generating dummy text programatically using TeX/LaTeX

As part of an attempt to debug another problem, I have a need for a TeX/LaTeX command that generates some dummy text in place. I know of lipsum and blindtext, but they are not what they want. What I have in mind is a command that takes the following arguments: a string (s) and integers (k and n), and produces k occurrences of s per line (no spaces) for n lines. I think this should be possible, even if one has to drop down to TeX to do it. After all, TeX is a text processing Turing complete programming language. Unfortunately, my knowledge of TeX could fit on a postage stamp with space left over, so I'm asking on this forum.

-
If you have no spaces between s, TeX cannot justify the line because there is nothing stretchable in it. Do you want the text left- or right-aligned? And what to do if the line overfills? –  Andrey Vihrov Aug 8 '11 at 9:23
@Audrey: 1) Ok, lets allow spaces 2) left aligned, though can't one have it do whatever the local default is? I mean, when one normally writes text in a TeX document, one does not need to specify alignment 3) Dunno. let it wrap around? –  Faheem Mitha Aug 8 '11 at 9:45
If by "wrap around" you mean that the text should continue on the next line, then what is the purpose of initially having k occurrences per line? –  Andrey Vihrov Aug 8 '11 at 9:51
@Andrey: Well, the assumption is that the user could reduce k or the length of the string if necessary. To be clear, I mean the text should continue on the next line, and then break. SO you get one complete line of text on line 1, then the overflow text from line 1 on line2, then the second repeated line of text comes on line 3 and so on. –  Faheem Mitha Aug 8 '11 at 9:55

The simplest way IMHO to do it is to use \foreach provided by the pgffor package. There is also the lower level \loop\ifnum\j<\k ... \repeat loop which could also be used. However, you need to wrap the inner loop in a group to mask the inner \repeat.

As Andrey already stated there are the open question about how to handle line breaks exactly. I simply use a \\ here, but you might need something else instead, dependent on the exact application. However, the principle usage of the loops is the same.

\documentclass{article}

\usepackage{pgffor}

\newcommand\dummytext[3]{%
\foreach \n in {1,...,#3} {%
\foreach \k in {1,...,#2} {%
#1%
}%
\\
}%
}

\begin{document}

\dummytext{HelloWorld}{5}{10}% 10 lines of 5x 'HelloWorld'

\end{document}

-
That works, thanks. However, I think you need #3-1, not #3, and #2-1 not #2. Or starting with 1 will work. In your example you get 11 lines of 6x, not 10 lines of 5x. –  Faheem Mitha Aug 8 '11 at 9:51
Yes, indeed. My fault. It should be 1 of course not 0. –  Martin Scharrer Aug 8 '11 at 10:10

And a Plain TeX-style solution using \loop\repeat:

\documentclass{article}

\makeatletter
\newcommand{\dummy@line}[2]{%
\begingroup
\@tempcnta=#2
\loop\ifnum\@tempcnta>0
#1\space
\repeat
\endgroup}
\newcommand{\dummytext}[3]{%
\begingroup
\@tempcnta=#3
\par\noindent
\loop\ifnum\@tempcnta>0
\dummy@line{#1}{#2}\\
\repeat
\par
\endgroup}
\makeatother

\begin{document}

\dummytext{abc}{3}{3}

\end{document}

-
Dumb question, but this function can be used in a LaTeX document even though it is plain TeX, right? –  Faheem Mitha Aug 8 '11 at 9:57
@Faheem Mitha: It is a LaTeX document: try compiling it as usual. LaTeX includes much code from Plain TeX. –  Andrey Vihrov Aug 8 '11 at 10:00
Yes, so it is. Sorry. I did say it was a dumb question... –  Faheem Mitha Aug 8 '11 at 14:06
@Faheem Mitha: You should not apologize for asking questions. Everyone does it in order to learn. –  Andrey Vihrov Aug 8 '11 at 14:09

You mentioned already blindtext. My first thought was, why not using it? You need only to redefine \blindtext@text to get your string. The other values are optional parameters for \Blindtext.

Unfortunately the missing spaces need also a redefiniton of \blindtext. If you allow spaces (see comments to your question), then just delete the redefiniton of \blindtext.

Below is an example.

\documentclass[11pt, a4paper,english]{article}
\usepackage{babel}
\usepackage{blindtext}
\begin{document}
\makeatletter
%Define text s
\renewcommand\blindtext@text{ab}
\renewcommand\blindtext@parstart{}%since blindtext version 2.0
%remove spaces
\renewcommand{\blindtext}[1][\value{blindtext}]{%
\blind@checklanguage
\blind@countxx=1 %
\loop
\blindtext@text%    here was a \
\repeat
}
\makeatother

%5 lines
%7repetions
\Blindtext[5][7]

\end{document}

-

Using LaTeX3 it's almost a one liner; the \dummy_endline: macro makes sure that a paragraph is terminated after each line; of course, if the copies of the string fill more than a line, they will be wrapped. If you don't care about Underfull \hbox messages, put \linebreak in place of \dummy_endline:.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\dummy}{m m m}
{
\prg_replicate:nn { #3 }
{
\prg_replicate:nn { #2 } { #1 \hfill } \dummy_endline:
}
}
\cs_new:Npn \dummy_endline:
{ { \parfillskip=0pt\par } }

\ExplSyntaxOff

\begin{document}

\setlength{\parindent}{0pt}

\dummy{HelloWorld!}{5}{10}

\end{document}

-
Still using TeX Live 2009, which doesn't seem to have xparse. Yes, I know 2009 is antediluvian. –  Faheem Mitha Jan 12 '12 at 5:45