Problema: manipulação de string com links dentro

Problema: manipulação de string com links dentro

Eu defini um novo comando \openintroque 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}

insira a descrição da imagem aqui

Eu uso alguns comandos do xstringpacote 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 hyperrefpacote, com links habilitados. O comando \StrBeforeapresenta 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 xstringconhece a \noexpandargmacro, evitando a expansão do argumento da string de entrada principal para xstringmacros, 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}

insira a descrição da imagem aqui

Responder2

Parece-me muito complicado. Por que existe o \StrBeforeprocessamento etc.? Por que você precisa letrinede 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 \openitroAdefiniçã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.

informação relacionada