
Eu defini um novo comando \openintro
que chamo a cada capítulo do meu trabalho. Este comando basicamente constrói uma frase letrina, como na imagem abaixo (não se preocupe com o estilo do texto):
\openintro{This is a working test}
Eu uso alguns comandos do xstring
pacote para cortar/dividir o texto para combinar com o efeito desejado com lettrine. No entanto, estou recebendo alguns erros ao usar \ref{label}
o comando interno.
\openintro{This is a NOT working test due to~\ref{mylabel}}
O problema está relacionado ao hyperref
pacote, com links habilitados. O comando \StrBefore
apresenta alguns erros ao se deparar com um link na string. Se eu desabilitar hyperref
, não há problema ao usar \ref
. Mas preciso usar hyperref
. Você tem alguma sugestão para resolver esse problema? Obrigado.
MWE:
\documentclass[12pt]{book}
\usepackage{xstring,lettrine}
\usepackage[pagebackref]{hyperref}
\hypersetup{
linktoc=all,
colorlinks=true,
allcolors=red
}%
\newcommand{\openintro}[1]{%
\def\firsttwowords{}%
\def\firstword{}%
\def\firstwordsplit{}%
\def\secondword{}%
\def\firstletter{}%
\def\remainingtext{}%
\def\charcount{}%
\StrBefore[2]{#1}{ }[\firsttwowords]% get the first two words
\StrBefore[1]{\firsttwowords}{ }[\firstword]% get the first word
\StrGobbleLeft{\firstword}{1}[\firstwordsplit]% del the first letter of first word
\StrBehind[1]{\firsttwowords}{ }[\secondword]% get only the second word
\StrLeft{#1}{1}[\firstletter]% get the first letter of first word
\StrLen{\firsttwowords}[\charcount]% count the number of characters of first two words
\StrGobbleLeft{#1}{\charcount}[\remainingtext]% del the number of characters on the left of the whole sentence
\lettrine{\firstletter}{\firstwordsplit~\secondword}~\textit{\remainingtext}\\[1PC]%
}%
\begin{document}
\chapter{test}
\openintro{This is a NOT working test due to~\ref{mylabel}}
\section{Hi there}\label{mylabel}
\end{document}
E o erro:
! Use of \@xs@StrBefore@@ doesn't match its definition.
\@ifnextchar ... \reserved@d =#1\def \reserved@a {
#2}\def \reserved@b {#3}\f...
l.36 ...s a NOT working test due to~\ref{mylabel}}
! Argument of \@firstoftwo has an extra }.
<inserted text>
\par
l.36 ...s a NOT working test due to~\ref{mylabel}}
Runaway argument?
! Paragraph ended before \@firstoftwo was complete.
Responder1
A expansão de \ref...
leva ao erro. Porém, o xstring
conhece a \noexpandarg
macro, evitando a expansão do argumento da string de entrada principal para xstring
macros, mas após a primeira operação a expansão deve ser habilitada novamente, utilizando \expandarg
.
\documentclass[12pt]{book}
\usepackage{xstring,lettrine}
\usepackage[pagebackref]{hyperref}
\hypersetup{
linktoc=all,
colorlinks=true,
allcolors=red
}%
\newcommand{\openintro}[1]{%
\def\firsttwowords{}%
\def\firstword{}%
\def\firstwordsplit{}%
\def\secondword{}%
\def\firstletter{}%
\def\remainingtext{}%
\def\charcount{}%
\noexpandarg%
\StrBefore[2]{#1}{ }[\firsttwowords]% get the first two words
\expandarg% Now expand again
\StrBefore[1]{\firsttwowords}{ }[\firstword]% get the first word
\StrGobbleLeft{\firstword}{1}[\firstwordsplit]% del the first letter of first word
\StrBehind[1]{\firsttwowords}{ }[\secondword]% get only the second word
\StrLeft{#1}{1}[\firstletter]% get the first letter of first word
\StrLen{\firsttwowords}[\charcount]% count the number of characters of first two words
\StrGobbleLeft{#1}{\charcount}[\remainingtext]% del the number of characters on the left of the whole sentence
\lettrine{\firstletter}{\firstwordsplit~\secondword}~\textit{\remainingtext}\\[1PC]%
}%
\begin{document}
\chapter{test}
\openintro{This is a NOT working test due to~\ref{mylabel}}
\section{Hi there}\label{mylabel}
\end{document}
Responder2
Parece-me muito complicado. Por que existe o \StrBefore
processamento etc.? Por que você precisa letrine
de pacote? Você pode fazer o mesmo com isto:
\documentclass[12pt]{book}
\usepackage[pagebackref]{hyperref}
\hypersetup{
linktoc=all,
colorlinks=true,
allcolors=red
}%
\def\openintro#1{\openintroA #1 \end}
\def\openintroA#1#2 #3 #4\end{\par
\setbox0=\hbox{\fontsize{27}{27}\selectfont#1\/}%
\hangindent=\wd0 \advance\hangindent by0pt \hangafter=-2
\noindent \hskip-\hangindent\vbox to0pt{\kern-6pt\box0\vss}%
{\uppercase{#2 #3} \it#4\unskip}%
\medskip
}
\begin{document}
\chapter{test}
\openintro{This is a working test due to~\ref{mylabel}}
\section{Hi there}\label{mylabel}
\end{document}
Muitos problemas ocorrem porque as pessoas não sabem que as coisas podem ser feitas de forma mais simples.
Editar: Devido ao comentário de David modifiquei a \openitroA
definição para que o comportamento seja semelhante ao uso letrine para textos com mais linhas.
Responder3
Estou respondendo minha própria pergunta, usando parte do código fornecido por @wipet e lettrine (já que é mais fácil manipular o estilo do texto). Em vez de usar toda a manipulação de string da minha primeira pergunta, apenas uso o seguinte código (que substitui o inteiro \newcommand{\openintro}
):
\def\openintro#1{\openintroA #1 \end}
\def\openintroA#1#2 #3 #4\end{%
\lettrine{#1}{#2~#3}~\textit{#4}%
}
Mais uma vez, devo agradecer a @ChristianHupfer, @wipet e @DavidCarlisle pela ajuda.