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}
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}
The conditional \ifx
does no expansion and it compares the next two tokens. So in your test it compares \myarg
with the first token in #1
.
Therefore the test will be always false, because #1
is the name of a section level counter.
Adding \expandafter
before \ifx
would not help, even adding braces around #1
:
\expandafter\ifx\myarg{#1}\mytest
would become
\ifx section\mytest
which returns false, as it compares s
with e
.
You could use \pdfstrcmp
(or, better, \pdf@strcmp
with the pdftexcmds
package):
\def\@seccntformat#1{%
\ifnum\pdf@strcmp{#1}{section}=\z@
Section % a space is wanted
\fi
\csname the#1\endcsname\quad}
Complete example:
\documentclass{article}
\usepackage{pdftexcmds}
\makeatletter
\def\@seccntformat#1{%
\ifnum\pdf@strcmp{#1}{section}=\z@
Section %
\fi
\csname the#1\endcsname\quad}
\makeatother
\begin{document}
\section{Foo} % Should be printed as "Section 1 Foo"
\subsection{Bar} % Should be printed as "1.1 Bar"
\end{document}
Note that the attempt of doing the comparison with \ifx
in the following way
\def\section@argument{section}
\def\@seccntformat#1{%
\def\@argument{#1}%
\ifx\@argument\section@argument
Section %
\fi
\csname the#1\endcsname\quad}
wouldn't work either. This is because \@seccntformat
is passed through an \edef
(in the form \protected@edef
), so we'd get an error
Undefined control sequence
for \@argument
. Adding \noexpand
in front of \@argument
wouldn't help, because the conditional is expanded during the \edef
. This instead would work
\def\section@argument{section}
\def\@seccntformat#1{%
\unexpanded{%
\def\@argument{#1}%
\ifx\@argument\section@argument
Section %
\fi
}
\csname the#1\endcsname\quad
}
because the argument to \unexpanded
is not changed during an \edef
, so it will be processed afterwards, when typesetting is involved.
Note that the \protected@edef
is necessary because we must get the expansion of \thesection
or \thesubsection
at the moment the macro \@seccntformat
is executed. An \unexpanded
free solution is possible, by hiding the part in a macro:
\def\section@argument{section}
\def\check@section#1{%
\def\@argument{#1}%
\ifx\@argument\section@argument
Section %
\fi
}
\def\@seccntformat#1{%
\noexpand\check@section{#1}%
\csname the#1\endcsname\quad}
Best Answer
\ifx
compares the meaning of the two following tokens without expanding them. So you're testing whether the tokenM
has the same meaning as\firstChar
and they don't, even if\def\firstChar{M}
has been issued, becauseM
is a character and\firstChar
is a macro.You have to expand
\firstChar
:But this wouldn't work with that string extraction, because
\firstChar
expands to instruction for extracting the first character, not to the first character. A better (and simpler) test isThis works also with an empty string. However, this will not work with multibyte UTF-8 characters, unless a UTF-8 savvy engine (XeLaTeX or LuaLaTeX) is used. Working with UTF-8 is much more difficult.
Complete example: