Problema: manipulación de cadenas con enlaces dentro

Problema: manipulación de cadenas con enlaces dentro

He definido un nuevo comando \openintroal que invoco en cada capítulo de mi trabajo. Este comando básicamente construye una oración letrina, como la imagen a continuación (no se moleste con el estilo del texto):

\openintro{This is a working test}

ingrese la descripción de la imagen aquí

Utilizo algunos comandos del xstringpaquete para cortar/dividir el texto para que coincida con el efecto deseado con lettrine. Sin embargo, recibo algunos errores cuando lo uso \ref{label}dentro del comando.

\openintro{This is a NOT working test due to~\ref{mylabel}}

El problema está relacionado con el hyperrefpaquete, con enlaces habilitados. El comando \StrBeforepresenta algunos errores al enfrentarse a un enlace en la cadena. Si lo desactivo hyperref, no hay problema al usarlo \ref. Pero necesito usar hyperref. ¿Tiene alguna sugerencia para resolver este problema? Gracias.

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}

Y el error:

! 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.

Respuesta1

La expansión de \ref...conduce al error. Sin embargo, xstringconoce la \noexpandargmacro, impidiendo la expansión del argumento de la cadena de entrada principal a xstringmacros, pero después de la primera operación la expansión debe habilitarse nuevamente, usando \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}

ingrese la descripción de la imagen aquí

Respuesta2

Me parece demasiado complicado. ¿Por qué se \StrBeforeprocesan etc.? ¿Por qué necesitas letrineel paquete? Puedes hacer lo mismo con esto:

\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}

Muchos problemas ocurren porque la gente no sabe que las cosas se pueden hacer de manera más simple.

Editar: debido al comentario de David, modifiqué la \openitroAdefinición para que el comportamiento sea similar al uso de letrine para textos con más líneas.

Respuesta3

Estoy respondiendo mi propia pregunta usando parte del código proporcionado por @wipet y lettrine (ya que es más fácil manipular el estilo del texto). En lugar de utilizar toda la manipulación de cadenas de mi primera pregunta, simplemente uso el siguiente código (que reemplaza el código completo \newcommand{\openintro}):

\def\openintro#1{\openintroA #1 \end}
\def\openintroA#1#2 #3 #4\end{%
      \lettrine{#1}{#2~#3}~\textit{#4}%
}

Una vez más, debo agradecer a @ChristianHupfer, @wipet y @DavidCarlisle por la ayuda.

información relacionada