4

I am encountering some weird behavior and errors when manipulating strings inside of \lettrine arguments: the code either doesn't compile or produces unexpected results. On top of that, it is font-related, e.g., some things work with regular fonts, but fail with some other fonts, such as most of fonts here: https://tug.org/FontCatalogue/otherfonts.html#initials

Any insight into this issue and advice on how one could fix this would be highly appreciated!

Here is a typical example:

\documentclass{article}

\usepackage{times,lettrine,Eileen,coolstr,stringstrings,xstring}

%\renewcommand*{\LettrineFontHook}{\Eileenfamily}   %%% Eileen fancy drop letter WTF?

\newcommand*{\first}[1]{\substring{#1}{1}{1}}       %%% stringstrings version
%\newcommand*{\first}[1]{\substr{#1}{1}{1}}         %%% coolstr version DOES NOT WORK AT ALL
%\newcommand*{\first}[1]{\StrLeft{#1}{1}}           %%% xstring version DOES NOT WORK AT ALL

\begin{document}


\lettrine{\first{Whaaat}}{hat} the duck?            %%% DOES NOT WORK AS INTENDED WITH EILEEN

\vspace{3em}

\lettrine{\first{What}}{hat} the duck?              %%% DOES NOT WORK AT ALL WITH EILEEN

\end{document}
  • 1
    I understand your goals and they are noble. However, when I wanted to use lettrine (and had no time), I just defined \newcommand{\flx}[2]{\lettrine[lines=4,realheight=true]{#1}{\textsc{#2}}} and did the separation in first letter and remaning part myself. You use lettrine once per chapter, it's not that much work. – Oleg Lobachev Sep 20 at 19:26
  • 1
    Oleg: thanks for responding, however, this would not work for me, as the presented piece of code is just for illustration purposes. My actual code does the parsing automatically and has to extract first letters from words on its own. I've accepted Steven B. Segletes' answer, as not only it fixes the problem, but also teaches some TeX programming :) Thank you, Steven! – Iiro Ullin Sep 20 at 19:45
4

I recommend, in a case like this, doing it with raw TeX, without parsing packages.

\documentclass{article}
\usepackage{times,lettrine,Eileen}
\def\firstaux#1#2\relax{{#1}{#2}}
\newcommand\flettrine[1]{\expandafter\lettrine\firstaux#1\relax}
\begin{document}
\flettrine{What} the duck?\bigskip

\renewcommand*{\LettrineFontHook}{\Eileenfamily}
\flettrine{What} the duck?
\end{document}

enter image description here

If you wanted to use stringstrings for other reasons (more complex manipulations, for example), I would use \substring to store the result in \thestring, and then pass \thestring on to \lettrine, in this fashion:

\documentclass{article}
\usepackage{times,lettrine,Eileen,coolstr,stringstrings,xstring}
\newcommand*{\first}[1]{\substring[q]{#1}{1}{1}}       %%% stringstrings version
\newcommand\flettrine[2]{\first{#1}\lettrine{\thestring}{#2}}
\begin{document}
\flettrine{Whaaat}{hat} the duck?            %%% DOES NOT WORK AS INTENDED WITH EILEEN

\vspace{3em}
\renewcommand*{\LettrineFontHook}{\Eileenfamily}   %%% Eileen fancy drop letter WTF?

\flettrine{What}{hat} the duck?              %%% DOES NOT WORK AT ALL WITH EILEEN
\end{document}
3

With expl3 it's really easy:

\documentclass{article}

\usepackage{newtxtext,lettrine,Eileen,xparse}

\renewcommand*{\LettrineFontHook}{\Eileenfamily}   %%% Eileen fancy drop letter WTF?

\ExplSyntaxOn
\NewDocumentCommand{\IiroLettrine}{O{}m}
 {
  \lettrine[#1]{\tl_range:nnn { #2 } { 1 } { 1 }}{\tl_range:nnn { #2 } { 2 } { -1 } }
 }
\ExplSyntaxOff

\begin{document}

\IiroLettrine{What} the duck?

\end{document}

The problem with your code is that \StrLeft{#1}{1} doesn't produce the first letter, but the set of instructions for printing it, but \lettrine wants just a letter (after expansion).

The \tl_range:nnn function is fully expandable, so it makes no problem to \lettrine. With \tl_range:nnn { #1 } { 1 } { 1 } the first item in the argument is delivered; with \tl_range:nnn { #1 } { 2 } { -1 } the remaining items are produced (the negative second number means “up to the last item”).

enter image description here

Since small caps are needed, it's better to use newtxtext that provides real small caps, instead of the faked ones you get with times.

You can do it also with xstring, using its trailing optional argument feature:

\documentclass{article}

\usepackage{newtxtext,lettrine,Eileen,xstring}

\renewcommand*{\LettrineFontHook}{\Eileenfamily}   %%% Eileen fancy drop letter WTF?

\newcommand{\IiroLettrine}[2][]{%
  \StrLeft{#2}{1}[\firstletter]%
  \StrGobbleLeft{#2}{1}[\otherletters]%
  \lettrine[#1]{\firstletter}{\otherletters}%
 }

\begin{document}

\IiroLettrine{What} the duck?

\end{document}

In both cases I kept the optional argument to \lettrine available in \IiroLettrine.

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.