NOTE: Real-world application added at end of post!
RE-REVISED to re-extend capability (and significantly condense the coding), as detailed here:
The following macros are introduced for left-aligned acrostics. Macros for mid-line acrostics are described later in this post.
\RAWacrostic{acrostic}
- to view acrostic in plain, unaltered mode
\SHOWacrostic[# acrostic chars]{acrostic}
- to view with acrostic highlighted (cap bold), unflushed.
\MEASUREacrostic[test width]{acrostic}
- to view natural widths of each line of the acrostic. With an optional length argument, it will tell you the interword spacing that will result from flushing the acrostic into the given length. Note: the width must be provided as a string, as in 200pt
or \the\textwidth
.
\FLUSHacrostic[width]{acrostic}
- to flush the acrostic into a paragraph. The width will be \textwidth
unless otherwise specified by the optional argument.
The macro \SHOWacrostic
takes an optional argument of how many of the initial characters to capitalize and make bold. The helper macro \accnt
is what capitalizes and makes those characters bold. \accnt
also looks to avoid highlighting initial punctuation, instead looking for letters. To see this feature, look in the output for the line containing ```Love not''` where the "L" and not the quotes are emboldened.
\MEASUREacrostic
may give guidance as to how to improve the lengths as well as what width to set the text in. \FLUSHacrostic
takes, as an optional argument, the width to set the text in. Of course, if you have large discrepancy of length in the lines of your acrostic, then it won't look so good.
Mid-line acrostics are also introduced [see more mentioned at end of this post].
EDITED to restore functionality lost to ravages of package upgrade.
\documentclass{article}
\usepackage{stackengine, stringstrings, calc}
\parskip 1em
\newcounter{index}
\def\stackalignment{l}
\def\stacktype{L}
\newcounter{nexttolast}
\newcounter{wordindex}
\newcounter{linegaps}
\newlength\natwidth
\newlength\extragapwidth
\newlength\spacewidth
\newsavebox{\verseline}
\sbox{\verseline}{-}
\setlength\spacewidth{\wd\verseline}
\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% The \getargsC macro mimics the behavior of the \getargs macro
% of the stringstrings package, but runs faster, and can handle
% arbitrary tokens. For the development of \getargsC, significant
% assistance was provided by David Carlisle, for which the author is
% most appreciative.
% http://tex.stackexchange.com/questions/101604/
% parsing-strings-containing-diacritical-marks-macros
%
\def\string@end{$\SaveHardspace}
\def\converttilde{F}
\newcounter{arg@index}
\newcounter{break@count}
\let\SaveHardspace~%%%
%
\def\getargsC#1{%
\if T\converttilde\def~{ }\else\catcode`~=12\fi
\protected@edef\the@string{#1}%
\setcounter{arg@index}{0}%
\lowercase{\expandafter\parse@Block\the@string} \string@end
\let~\SaveHardspace%
\catcode`~=13
}
%
\def\parse@Block#1 {%
\stepcounter{arg@index}%
\@namedef{arg\roman{arg@index}}{#1}%
\futurelet\tmp\parse@Block@}
%
\def\parse@Block@{%
\ifx\tmp\string@end\edef\narg{\thearg@index}\expandafter\@gobble
\else\expandafter\parse@Block\fi}
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand\@acrostic[3]{%
\def\quietstack{T}%
\getargsC{#2}%
\setcounter{nexttolast}{\narg}%
\addtocounter{nexttolast}{-1}%
\setcounter{index}{1}%
\if R#3\sbox{\stackedbox}{\argi}\else%
\if S#3\sbox{\stackedbox}{\@accnt{\argi}{#1}}\else%
\if M#3\if x#1\else(Ref: #1)\fi\sbox{\stackedbox}{\@measure{\argi}{#1}}\else%
\if F#3\sbox{\stackedbox}{\@fittowidth{\argi}{#1}}%
\fi\fi\fi\fi%
\whiledo{\value{index}<\value{nexttolast}}{%
\stepcounter{index}%
\edef\poemline{\csname arg\roman{index}\endcsname}%
\if R#3\stackon{\poemline}{\usebox{\stackedbox}}\else%
\if S#3\stackon{\@accnt{\poemline}{#1}}{\usebox{\stackedbox}}\else%
\if M#3\stackon{\@measure{\poemline}{#1}}{\usebox{\stackedbox}}\else%
\if F#3\stackon{\@fittowidth{\poemline}{#1}}{\usebox{\stackedbox}}%
\fi\fi\fi\fi%
}%
\stepcounter{index}%
\edef\poemline{\csname arg\roman{index}\endcsname}%
\if R#3\stackon{\poemline}{\usebox{\stackedbox}}\else%
\if S#3\stackon{\@accnt{\poemline}{#1}}{\usebox{\stackedbox}}\else%
\if M#3\stackon{\@measure{\poemline}{#1}}{\usebox{\stackedbox}}\else%
\if F#3\stackon{\poemline}{\usebox{\stackedbox}}%
\fi\fi\fi\fi%
\usebox{\stackedbox}%
\def\quietstack{F}%
}
\newcommand\RAWacrostic[2][1]{\@acrostic{#1}{#2}{R}}
\newcommand\SHOWacrostic[2][1]{\@acrostic{#1}{#2}{S}}
\newcommand\MEASUREacrostic[2][x]{\@acrostic{#1}{#2}{M}}
\newcommand\FLUSHacrostic[2][\textwidth]{\@acrostic{#1}{#2}{F}}
\newcommand\@MIDacrostic[3]{%
\getargsC{#2}%
\setcounter{nexttolast}{\narg}%
\addtocounter{nexttolast}{-1}%
\setcounter{index}{1}%
\if R#3\sbox{\stackedbox}{\argi}\else%
\if S#3\sbox{\stackedbox}{\argi}\else%
\if M#3\if x#1\else(Ref: #1)\fi\sbox{\stackedbox}{\@measure{\argi}{#1}+}%
\fi\fi\fi%
\whiledo{\value{index}<\value{nexttolast}}{%
\addtocounter{index}{2}%
\edef\poemline{\csname arg\roman{index}\endcsname}%
\if R#3\stackengine{\Lstackgap}{\poemline}{\usebox{\stackedbox}}{O}{r}{T}{F}{L}\else%
\if S#3\stackengine{\Lstackgap}{\poemline}{\usebox{\stackedbox}}{O}{r}{T}{F}{L}\else%
\if M#3\stackengine{\Lstackgap}{\@measure{\poemline}{#1}+}{\usebox{\stackedbox}}{O}{r}{T}{F}{L}%
\fi\fi\fi%
}%
\usebox{\stackedbox}%
\if R#3#1\fi%
\setcounter{index}{2}%
\if R#3\sbox{\stackedbox}{\argii}\else%
\if S#3\sbox{\stackedbox}{\@accnt{\argii}{#1}}\else%
\if M#3\sbox{\stackedbox}{\@measure{\argii}{#1}}%
\fi\fi\fi%
\whiledo{\value{index}<\narg}{%
\addtocounter{index}{2}%
\edef\poemline{\csname arg\roman{index}\endcsname}%
\if R#3\stackengine{\Lstackgap}{\poemline}{\usebox{\stackedbox}}{O}{l}{T}{F}{L}\else%
\if S#3\stackengine{\Lstackgap}{\@accnt{\poemline}{#1}}{\usebox{\stackedbox}}{O}{l}{T}{F}{L}\else%
\if M#3\stackengine{\Lstackgap}{\@measure{\poemline}{#1}}{\usebox{\stackedbox}}{O}{l}{T}{F}{L}%
\fi\fi\fi%
}%
\usebox{\stackedbox}%
}
\newcommand\RAWMIDacrostic[2][]{\@MIDacrostic{#1}{#2}{R}}
\newcommand\SHOWMIDacrostic[2][1]{\@MIDacrostic{#1}{#2}{S}}
\newcommand\MEASUREMIDacrostic[2][\textwidth]{\@MIDacrostic{x}{#2}{M}}
% HELPER ROUTINES
\newcommand\@fittowidth[2]{%
\getargsC{#1}%
\setcounter{wordindex}{1}%
\parbox[b]{#2}{%
\argi%
\whiledo{\value{wordindex} < \narg}{%
\stepcounter{wordindex}%
\hfill\csname arg\roman{wordindex}\endcsname%
}%
}%
}
\newcommand\@measure[2]{%
\sbox{\verseline}{#1}%
\setlength\natwidth{\wd\verseline}%
\the\natwidth%
\if x#2\else%
\getargsC{#1}%
\setcounter{linegaps}{\narg}%
\addtocounter{linegaps}{-1}%
\setlength\extragapwidth{(#2-\natwidth)/\thelinegaps+\spacewidth}%
(\the\extragapwidth)%
\fi%
}
\newcommand\@accnt[2]{%
\if T\ignorepunctuation%
\alphabetic[q]{#1}%
\substring[q]{\thestring}{1}{1}%
\edef\searchletter{\thestring}%
\whereischar[q]{#1}{\searchletter}%
\edef\searchletterloc{\theresult}%
\else%
\edef\searchletterloc{1}%
\fi%
\substring{#1}{1}{\searchletterloc-1}%
\substring[q]{#1}{\searchletterloc}{\searchletterloc+#2-1}%
\textbf{\caseupper{\thestring}}%
\substring{#1}{\searchletterloc+#2}{$}%
}
\def\ignorepunctuation{T}
\makeatother
\parindent 0in
\begin{document}
\SHOWacrostic{My very excellent mother just served us nachos}
tells us the planets:
\SHOWacrostic{Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune}
\def\months{%
{Janet was quite ill one day.}
{Febrile trouble came her way.}
{Martyr-like, she lay in bed;}
{Aproned nurses softly sped.}
{Maybe, said the leech judicial}
{Junket would be beneficial.}
{Juleps, too, though freely tried,}
{Augured ill, for Janet died.}
{Sepulchre was sadly made.}
{Octaves pealed and prayers were said.}
{Novices with ma'y a tear}
{Decorated Janet's bier.}}
\RAWacrostic[3]{\months}
~~
\SHOWacrostic[3]{\months}
\clearpage
\def\liz{%
{Elizabeth it is in vain you say}
{``love not'' thou sayest it in so sweet a way:}
{in vain those words from thee or L.E.L.}
{Zantippe's talents had enforced so well:}
{Ah! if that language from thy heart arise,}
{breath it less gently forth and veil thine eyes.}
{Endymion, recollect, when Luna tried}
{to cure his love was cured of all beside}
{his follie pride and passion for he died.}}
%
\RAWacrostic{\liz}
\SHOWacrostic{\liz}
\MEASUREacrostic{\liz}~~~~~
\MEASUREacrostic[185pt]{\liz}
The measuring algorithm assumes a natural space is the same width as a
hyphen, namely \the\spacewidth.
\FLUSHacrostic[185pt]{\liz} $\leftarrow$ verse set to 185pt width
\clearpage
\def\midway{%
{The programming } {language I am}
{trying to imagine } {at the moment,}
{I am told, is qui} {te fun to use,}
{as David Carlisl} {e spoke of in}
{a very a proli} {x manner.}}
\RAWMIDacrostic[\hspace{.1ex}\rule{.4ex}{4.7\baselineskip}\hspace{.1ex}]
{\midway}
\RAWMIDacrostic{\midway}
Measure:
\MEASUREMIDacrostic{\midway}
\SHOWMIDacrostic{\midway}
\def\ignorepunctuation{F}
\def\ode{%
{You~~~~} {\ \ \ \ are a}
{truly amaz} {ing woman:}
{with grace, } {laughter, fun.}
{And then y} {ou are seen}
{showing lo} {ve always.}
{I most } {especially}
{know } {you're}
{a h} {oney}
{b} {un} {} {!!}}
\RAWMIDacrostic{\ode}~~~~~
\SHOWMIDacrostic{\ode}
\end{document}
In this first image, I demonstrate how \SHOWacrostic
can be used with 1 or more letters in the acrostic (passed as an optional argument). Note how \SHOWacrostic
will capitalize and embolden the acrostic, as compared to the raw acrostic shown on the left.
In this image, I demonstrate more power for left-aligned acrostics. I first show the raw acrostic as entered with \RAWacrostic
. Then I show it revealed with \SHOWacrostic
. Then I measure it in two ways with \MEASUREacrostic
. If no optional argument is provided, it shows the natural length of each line. If a length string (use \the
if providing a macro) is provided as the optional argument, it shows the measurements, as before, but adds in parentheses the calculated interword spacing for each line, if the acrostic were to be flushed to the given width. These can be used to quantitatively gauge whether the gaps are too big or small. Finally, I set the acrostic to that flushed width with \FLUSHacrostic
.
Additionally,
\RAWMIDacrostic[divider]{acrostic}
\MEASUREMIDacrostic{acrostic}
and
\SHOWMIDacrostic[# acrostic chars]{acrostic}
have been added for mid-line acrostics. First, I show the acrostic with a rule dividing the two halves. This is the reason the acrostic itself must have left and not center alignment, because the acrostic is formed by butting the two (already stacked) halves together. Then I show the raw acrostic verse, with the message hidden. I then show the measurements of both halves of each line. Note, that since I don't (yet) provide flushing for mid-acrostics, I do not provide the means to compare these lengths to two test-widths. Lastly, I reveal the acrostic with \SHOWMIDacrostic
.
Making mid-acrostics flush to margins is an exercise left to the reader. ;^)
However, guys, here's where you need to take some close notes. Even without flushing for mid-line acrostics, you can make highly profitable use of the mid-acrostics. Think of your best girl, and compose her a verse, sure to melt her heart. I promise you, good things will follow.