24

I think about hiding a message in a LaTeX document. I would like to do so by using the first characters in each line of the first paragraph to spell out a message.

For example, to spell out "Never Gonna Give You Up", the output text could say the following.

Nobel archers were commissioned by the earl to face an
encountered army of likewise seasoned soldiers of 
very prestigious families. Each archer was known to hit
every target with high precision. But in some very
rare cases, ...

(Spare me to come up with more nonsense, but you get the message.)

How can I do this while maintaining the justification of the text (assuming that I have sufficiently many words per line)?

I am using the standard report format.

22

Since the first-letter arrangement heavily influences the line-breaking, it is assumed that this is done manually. As such, I'm assuming you're okay with adding a \\ at the end of each line, similar to how one would initiate a new row in a tabular. With this in mind, the following might be a starting point:

enter image description here

\documentclass{article}

\usepackage{collcell,environ}

\newlength{\maxlinewidth}
\newcommand{\stretchcell}[1]{\makebox[\maxlinewidth][s]{#1}}

\NewEnviron{rickroll}[1][\relax]{%
  \settowidth{\maxlinewidth}{%
  \begin{tabular}{@{}l@{}}
    \BODY
  \end{tabular}}%
  \ifx#1\relax\else\setlength{\maxlinewidth}{#1}\fi%
  \begin{tabular}{@{}>{\collectcell\stretchcell}l<{\endcollectcell}@{}}
    \BODY\hfill
  \end{tabular}%
}

\begin{document}

\noindent
\begin{tabular}{@{}l@{}}
Nobel archers were commissioned by the earl to face an \\
encountered army of likewise seasoned soldiers of \\
very prestigious families. Each archer was known to hit \\
every target with high precision. But in some very \\
rare cases, \ldots
\end{tabular}

\noindent
\begin{rickroll}
Nobel archers were commissioned by the earl to face an \\
encountered army of likewise seasoned soldiers of \\
very prestigious families. Each archer was known to hit \\
every target with high precision. But in some very \\
rare cases, \ldots
\end{rickroll}

\end{document}

The idea behind the above suggestion is that you set each row of a tabular inside a \makebox[<width>][s]{<stuff>}, since this will [s]tretch the space between words to fit <stuff> within <width>. The <width> is determined as the widest line within the rickroll.

We measure the width of the longest line and then set the text. As such, we process the contents twice which is easiest when using environ.

Limitations:

  1. Since the paragraph is set in a tabular, you can't break it across the page boundary.

  2. Each paragraph has to be managed separately.

You can set multiple paragraphs in the same rickroll, but the same limitation in (1) would hold. Setting multiple paragraphs would require manually setting the paragraph separation using something like \\[\parskip]. Additionally one would need an \hfill on each line that you don't want to spread out.

  • I don't understand why you're using a tabular. You lose the possibility of paragraph breaks and page breaks, and I can't see what you're gaining. – Gilles 'SO- stop being evil' Aug 18 '16 at 14:21
  • @Gilles: I want to capture the length of the widest line. – Werner Aug 18 '16 at 16:25
12

Not an answer to what you're actually asking, but you can have quite fun with the package accsupp:

\documentclass{article}
\usepackage{accsupp}
\begin{document}
\thispagestyle{empty}
\BeginAccSupp{ActualText={We're no strangers to love  ^^J
You know the rules and so do I                        ^^J
A full commitment's what I'm thinking of              ^^J
You wouldn't get this from any other guy              ^^J
                                                      ^^J
I just wanna tell you how I'm feeling                 ^^J
Gotta make you understand                             ^^J
                                                      ^^J
Never gonna give you up                               ^^J
Never gonna let you down                              ^^J
Never gonna run around and desert you                 ^^J
Never gonna make you cry                              ^^J
Never gonna say goodbye                               ^^J
Never gonna tell a lie and hurt you}}%
This is a text you for some reason would like to copy. %
Only problem is that this text (and not the secret lyrics) % 
is copied if the pdf is opened with sumatraPDF. Acrobat %
reader copies the hidden text but doesn't allow me to mark %
all this dummy text. 
\EndAccSupp{}
\end{document}

This gives a text that, when copied, displays the "Never gonna give you up"-lyrics: Result

As I indicated, it doesn't work perfectly and different viewers seem to handle it differently. Have fun :)

7

If you want to have line breaks with justification, just use the \break command instead of the more popular \\. A space before \break would show up, so put \unskip before it to cancel the space.

\documentclass[a4paper]{article}
\newcommand{\breakwithjustification}{\unskip\break}
\let\B\breakwithjustification
\begin{document}
\setlength{\parindent}{0pt}
Nobel archers were commissioned by the earl to face an \B
encountered army of likewise seasoned soldiers of \B
very prestigious families. Each archer was known to hit \B
every target with high precision. But in some very \B
rare cases, ...
\end{document}

This is obvious in the source and annoying to type. So let's make the newlines in the source translate to line breaks in the output.

I'll build on the standard command \obeylines, which turns every line break in the source into a paragraph break. We don't want a paragraph break because the lines wouldn't be justified. Instead, we'll make the newline invoke \breakwithjustification.

With \obeylines, a blank newline in the source turns into a blank line in the output. I'll make it cause a paragraph break instead, as in normal TeX typesetting.

\documentclass[a4paper]{article}
\pagestyle{empty}
\newcommand{\breakwithjustification}{\unskip\break}
\let\B\breakwithjustification
\newenvironment{obeylineswithjustification}{%
  \def\par{%
    %% Do nothing in vertical mode, i.e. at the beginning of a paragraph
    \ifhmode%
      %% Have we just had a mandatory line break?
      \ifnum\lastpenalty>-10000 %
        %% Insert a mandatory line break.
        \unskip\break%
      \else%
        %% We just had a mandatory line break. Cancel it and end the paragraph.
        \unpenalty%
        \hfil%
        \endgraf%
      \fi%
    \fi}%
  \obeylines%
}{%
  \par%
}
\begin{document}
\setlength{\parindent}{0pt}
\setlength{\parskip}{1ex}

Ragged-left is casually kept:

Nobel archers were commissioned by the earl to face an \\
encountered army of likewise seasoned soldiers of \\
very prestigious families. Each archer was known to hit \\
every target with high precision. But in some very \\
rare cases, ...

Rather obtrusive left-right lineup:

Nobel archers were commissioned by the earl to face an \B
encountered army of likewise seasoned soldiers of \B
very prestigious families. Each archer was known to hit \B
every target with high precision. But in some very \B
rare cases, ...

Here's a paragraph that's typeset normally, for comparison. This paragraph is
justified at both margins (except for the last line which is flush left). The
line breaks fall wherever they like. The next paragraphs respect the line
breaks and paragraph breaks in the source.

\begin{obeylineswithjustification}
Nobel archers were commissioned by the earl to face an
encountered army of likewise seasoned soldiers of
very prestigious families. Each archer was known to hit
every target with high precision. But in some very
rare cases, ...

See how in this environment, a line break in the source translates into
a line break in the output. This way you can get
your desired output in a nonobtrusive way.



Nobel archers were commissioned by the earl to face an
encountered army of likewise seasoned soldiers of
very prestigious families. Each archer was known to hit
every target with high precision. But in some very
rare cases, ...
\end{obeylineswithjustification}
The End.
\end{document}

output of the previous document

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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