Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I am trying to define a function Lettrine from the lettrine one. I did it here successfully, but I need to add an optional argument to be able to use more lettrine features like ante:

\documentclass{article}
\usepackage{lettrine}

\def\eqifcase #1#2#3{\eqifcaseA #1#2#1{#3}\end }

\def\eqifcaseA #1#2#3{\ifx #1#2\eqifcaseDo{#3}\fi \eqifcaseA #1}

\def\eqifcaseDo #1\fi #2\end{\fi #1}

\def\LettrineX #1#2{\vspace{-4ex}\lettrine[lines=1,findent=-0.1em
    \ifx\dummy#2\dummy\empty\else,#2\fi%
    ]{#1}{}}
\newcommand*{\Lettrine}[2][x]{\LettrineX{#2}{#1}}

\begin{document}\thispagestyle{empty}
\section{section 1}
\Lettrine[ante=«]{P}owerfull macro ! »
\section{section 2}
\Lettrine{P}owerfull macro !

\end{document}

It does not compile, with the error:

$ pdflatex MWE_lettrine_command7.tex 
This is pdfTeX, Version 3.1415926-2.5-1.40.14 (TeX Live 2013)
 restricted \write18 enabled.
entering extended mode
(./MWE_lettrine_command7.tex
LaTeX2e <2011/06/27>
Babel <3.9f> and hyphenation patterns for 15 languages loaded.
(/usr/share/texmf-dist/tex/latex/base/article.cls
Document Class: article 2007/10/19 v1.4h Standard LaTeX document class
(/usr/share/texmf-dist/tex/latex/base/size10.clo))
(/usr/share/texmf-dist/tex/latex/lettrine/lettrine.sty
(/usr/share/texmf-dist/tex/latex/graphics/keyval.sty)
Loading lettrine.cfg
(/etc/texmf/tex/latex/lettrine.d/lettrine.cfg)) (./MWE_lettrine_command7.aux))
! Incomplete \ifx; all text was ignored after line 17.
<inserted text> 
                \fi 
<*> MWE_lettrine_command7.tex

If I add a \expandafter before lettrine, it changes nothing, but I am a newbbie for this kind of stuff. If I comment the \ifx line of code, it does compile and work.

The following \ifx MWE reproduces the same kind of architecture with the ifx expression inside an optional argument in a demonstration function. It compiles and works successfully:

\documentclass{article}
\usepackage{lettrine}

\newcommand*{\Test}[2][xxx]{option=#1; argument=#2}

\def\testX #1#2{%
  \Test[\ifx\dummy#2\dummy\empty\else,#2\fi]{#1}%
}

\newcommand*{\test}[2][]{\testX{#2}{#1}}

\begin{document}\thispagestyle{empty}
With one argument:  "\test{MAIN-ARG---ONLY-ONE}"\par
With two arguments: "\test[OPTION=2]{MAIN-ARG}"
\end{document}

Result: enter image description here

I have quite no more hair at trying to figure out what I am doing wrong. Any idea please?

share|improve this question

3 Answers 3

up vote 8 down vote accepted

The code contains this in inside a key value list:

\ifx\dummy#2\dummy\empty\else,#2\fi

The first element in the list is (assuming #2 does not contain ,):

\ifx\dummy#2\dummy\empty\else

The next is

#2\fi

The \ifx construct is divided at the comma by the key value parser.

The following implementation expands the options partially to get a valid key value option list:

\documentclass{article}
\usepackage{lettrine}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\def\eqifcase #1#2#3{\eqifcaseA #1#2#1{#3}\end }

\def\eqifcaseA #1#2#3{\ifx #1#2\eqifcaseDo{#3}\fi \eqifcaseA #1}

\def\eqifcaseDo #1\fi #2\end{\fi #1}

\newcommand*{\Lettrine}[2][]{%
  \vspace{-4ex}%
  \edef\LettrineNext{%
    \noexpand\lettrine[%
      lines=1,
      findent=%
        \eqifcase {#2}{{P}{-0.8em}{T}{-0.6em}}{-0.1em},%
      \unexpanded{#1}%
    ]%
  }%
  \LettrineNext{\textit{#2}}{}%
}

\begin{document}\thispagestyle{empty}
\section{section 1}
\Lettrine[ante=«]{P}owerfull macro ! »
\section{section 2}
\Lettrine{P}owerfull macro !
\end{document}

Result

New implementation to support additional features

  • The capital letter can be hidden inside a macro, e.g. \dropCap.

  • The letter can consist of more than one token, e.g. D'.

Macro \DeclareFindents configures the gap lengths:

\DeclareFindents{-0.1em}{
  P=-0.8em,
  T=-0.6em,
  D'=-1em,
}

The first argument is the default value. Then a key value lists follows; the key is the letter (also several tokens are possible) and the value the gap length for this letter.

Package kvsetkeys provides the frame work for a configurable key value parser that compares the list entries with the actual letter. Both the keys and the letters are run through \protected@edef to expand macros such as \dropCap.

Example file:

\documentclass{article}
\usepackage{lettrine}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\usepackage{kvsetkeys}

\makeatletter
\newcommand*{\DeclareFindents}[2]{%
  \def\findent@default{#1}%
  \def\findent@list{#2}%
}
\DeclareFindents{0pt}{}% initializing

\newcommand*{\findent@set}[1]{%
  \protected@edef\findent@letter{#1}%
  \let\findent@value\findent@default
  \expandafter\kv@parse\expandafter{\findent@list}{%
    \protected@edef\kv@key{\kv@key}%
    \ifx\findent@letter\kv@key
      \let\findent@value\kv@value
      \kv@break
    \fi
    \@gobbletwo % key and value arguments are not needed
  }%
}
\newcommand*{\Lettrine}[2][]{%
  \vspace{-4ex}%
  \findent@set{#2}%
  \edef\LettrineNext{%
    \noexpand\lettrine[%
      lines=1,
      findent=\findent@value,
      \unexpanded{#1}%
    ]%
  }%
  \LettrineNext{\textit{#2}}{}%
}
\makeatother

\DeclareFindents{-0.1em}{
  P=-0.8em,
  T=-0.6em,
  D'=-1em,
}
\begin{document}\thispagestyle{empty}
\section{section 1}
\Lettrine[ante=«]{P}owerfull macro ! »
\section{section 2}
\Lettrine{P}owerfull macro !
\section{section 3}
\Lettrine{D'}Artagnan and his friends.
\section{section 4}
\newcommand*{\dropCap}{D'}
\Lettrine\dropCap Artangan does not drop his friends.
\end{document}

Result

share|improve this answer
    
Thanks for your help Heiko Oberdiek. First of all, I have updated my post since the second MWE was badly designed, but it does not change the problem, only makes thinks clearer. Next, considering the beginning of your analysis, the , in the ifx was not intended to separate list items, but to be a standard character in the output. The MWE shows it works I think. But I have to go deeper in your explanations. See you soon. –  lalebarde May 21 at 13:58
1  
@lalebarde: A key value parser usually does not expand the list, it first splits the list at commas, then it takes an entry and splits it at a equal sign, if it exists. Then the option/key code will process the value and very likely expand it. That means, you can often use code that expands to one key or one value, but you can have code that expands to a key value pair or more than one entry in a key value list. –  Heiko Oberdiek May 21 at 14:03
    
thanks for your explanations, I have to study that in details. Anyway, your design is far cleaner than mine and works ! –  lalebarde May 21 at 14:08
    
For further features, I need to introduce, say to simplify: \def\dropCap{#2}, and then use \dropCap instead of #2 inside \eqifcase {#2}{{P}{-0.8em}{T}{-0.6em}}{-0.1em}. Surprizingly, the default is trigged instead of the P case. If I add --\dropCap-- somewhere, it is outputed in the pdf as --P-- though ! Any idea please? –  lalebarde May 21 at 17:37
    
My need now is to be able to call \Lettrine{D'} - note the apostrophe added in the argument. It works with lettrine, but fails to compile here. It seems that \eqifcase requires to eval arguments of the same length? –  lalebarde May 21 at 17:43

This is not an answer, but more of comment: I am a bit perplexed at your use of \lettrine with key lines=1, with empty second argument. I looked a bit at lettrine package, the height of the lettrine in the default case lines=2 and also for lines=1 is computed to be exactly the baselineskip plus the height of lowercase x in small caps. In this way, with lines=2 the top of the lettrine matches the top of the lower case small caps letters completing the first word of the paragraph. If you don't use the second argument, and do not use small caps, there will be a mismatch.

But you are with lines=1. One could argue then that one should not take into account the height of small caps x, as this would be very arbitrary, and just set the height of the lettrine to be one or two baselineskips or perhaps 1.5 baselineskip. One may question why use the \lettrine command if it is to be with \lines=1.

It is possible to load the package and use it in a devious way to re-use its computation of the correct font size giving a given height to the lettrine. We could do it directly but perhaps the document will have some use for \lettrine with lines>1...

lettrine

\documentclass{article}
% LET'S NOT FORGET TO ALLOW EXTRA SIZES!:
\usepackage[T1]{fontenc}
\usepackage{lettrine}
\usepackage{lmodern}

% http://tex.stackexchange.com/a/179403/4686
\def\eqifcase #1#2#3{\eqifcaseA #1#2#1{#3}\end }
\def\eqifcaseA #1#2#3{\ifx #1#2\eqifcaseDo{#3}\fi \eqifcaseA #1}
\def\eqifcaseDo #1\fi #2\end{\fi #1}


\makeatletter
% The .5\baselineskip and 1.5\baselineskip should be customized
\def\Lettrine #1{\vspace{.5\baselineskip}%
               {\def\Lettrine@height {\setlength{\L@height}{1.5\baselineskip}}%
                  \renewcommand\LettrineFontHook{\itshape}%
                  \noindent\LettrineFont #1}% <-\smash{#1} possible
                  \kern\eqifcase % whatever is wished and here we
                  % actually don't need an expandable eqifcase anymore
                  % but as we have it handy we can use it here after \kern
                  {#1}{{P}{-0.4em}{T}{-0.5em}{D}{-0.2em}}{-0.1em}\relax
                }
\makeatother               

\begin{document}

\section{section 1}


\lettrine[lines=2]{P}{owerful} macro ! Various parameters are
provided to control the size and layout of the dropped capital and match
the requirements described in the books.\hrulefill\par\nointerlineskip

\Lettrine{P}owerful macro ! \smash{\rule{1pt}{2\baselineskip}} Various parameters are
provided to control the size and layout of the dropped capital and match
the requirements described in the books


\section{section 2}

\Lettrine{D}efault.  \smash{\rule{1pt}{1.5\baselineskip}} The letter glyph
extends a bit above its box. Various parameters are
provided to control the size and layout of the dropped capital and match
the requirements described in the books

\section{section 3}

\Lettrine{T}his is nice!  \smash{\rule{1pt}{1.5\baselineskip}} The letter glyph
extends a bit above its box. Various parameters are
provided to control the size and layout of the dropped capital and match
the requirements described in the books

\end{document}
share|improve this answer
    
if I understand you right, you argue I don't need the lettrine package for the rendering I am seeking for. You are certainly right, but I want to be able to change the lettrine rendering for different editions of the same book. In your example, if you use directly lettrine like in your section 1, with lines=1, you have too much space between the dropped capital and the next letter, plus I don't know from the lettrine package documentation how to use the second argument without small caps. BTW, I think this comment might belong to the other post. –  lalebarde May 21 at 15:01
1  
see \LettrineTextFont in the lettrine documentation. –  jfbu May 21 at 15:03
    
To illustrate what you said, \renewcommand{\LettrineTextFont}{} then \lettrine[lines=1]{\textit{P}}{owerfull} original lettrine macro and \huge\textit{P}\normalsize owerfull without any lettrine macro produce the same thing. Concerning the lettrine package internals, it is said in the doc that Instead of giving optional parameters to the \lettrine command, it is possible to set them on a per character basis in a second configuration file, but I could not find examples nor instructions. –  lalebarde May 21 at 15:53
    
@lalebarde just to say that one important thing lettrine does is to set (and compute first, this is where some measurement has to be done) the font size in order for the lettrine to have a specific height: this may coincide with what \huge gives, but only coincidentally. Besides with lines>2 the normal size changing commands do not give big enough characters. I do see the point of using a custom \Lettrine doing \lettrine with lines=1, as long as the document has some use for lines>1. Else, I believe it would be better to do the job by oneself, without lettrine package. –  jfbu May 21 at 19:15
    
I loaded lmodern else fonts will not scale beyond a certain size. An alternative is fix-cm which enables such arbitrary scaling with Computer Modern. –  jfbu May 22 at 8:11

This is a failing solution to try to apply what egreg learnt me here to get the \Lettrine{D'}Artagnan capability, sticking to Heiko Oberdiek 's first solution (indentation overlay is intentional, --first letter-- also):

enter image description here

\documentclass{article}
\usepackage{lettrine}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\def\eqifcase #1#2#3{\eqifcaseA #1#2#1{#3}\end }

\def\eqifcaseA #1#2#3{\ifx #1#2\eqifcaseDo{#3}\fi \eqifcaseA #1}

\def\eqifcaseDo #1\fi #2\end{\fi #1}

\usepackage{fp,stringstrings}

\makeatletter
\def\extract@first#1#2\@nil{#1}
\newcommand*{\Lettrine}[2][]{%
  \vspace{-4ex}%
  \def\dropCap{\extract@first#2\@empty\@nil}%
  \FPset\myindent\expandafter\eqifcase {\dropCap}{{D}{-1em}{P}{-0.6em}{T}{-0.6em}}{-0.1em}%
  % later more operations with \myindent
  \edef\LettrineNext{%
    \noexpand\lettrine[%
      lines=1,
      findent=\myindent,%
      %findent=%
      %  \expandafter\eqifcase {\dropCap}{{D}{-1em}{P}{-0.6em}{T}{-0.6em}}{-0.1em},%
      \unexpanded{#1}%
    ]%
  }%
  \LettrineNext{\textit{#2}}{---\dropCap---}%
}
\makeatother
\renewcommand{\LettrineTextFont}{}

\begin{document}\thispagestyle{empty}
\section{section 1}
\Lettrine[ante=«]{P}owerfull macro ! »
\section{section 2}
\Lettrine{P}owerfull macro !
\section{section 3}
\Lettrine{D'}Artagnan and his friends.

\end{document}

\myindent takes always the default value -0.1em. Any clue please?

share|improve this answer
    
it would be better to edit your question. \edef\dropCap{\extract@first#2\@empty\@nil}\edef\myindent{\expandafter\eqifcase‌​\expandafter{\dropCap}{{D}{-1em}{P}{-0.6em}{T}{-0.6em}}{-0.1em}}\edef\LettrineNex‌​t{\noexpand\lettrine[lines=1,findent=\myindent,\unexpanded{#1}]% besides if you want to see really the size that lettrine package tries to achieve you must enable scaling of the fonts, \RequirePackage{type1ec} before the \documentclass. Or \usepackage{lmodern} –  jfbu May 22 at 15:53
    
Using lettrine package with lines=1 is quite limitative: the size of the lettrine is chosen as if lines=2 and can't be changed easily if not hacking like I proposed in my answers to your questions. If you don't use lettrine package you have total freedom is setting up the size of the lettrines as you like. –  jfbu May 22 at 15:57
    
"it would be better to edit your question." I meant by that you should edit your initial post rather than use an auto-answer to discuss your partial advances in solving the problem. –  jfbu May 22 at 16:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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