問題:內部有連結的字串操作

問題:內部有連結的字串操作

我定義了一個新命令\openintro,我在工作的每一章中都呼叫它。這個指令基本上建構了一個 lettrine 句子,如下圖所示(不要理會文字樣式):

\openintro{This is a working test}

在此輸入影像描述

我使用包的一些命令xstring來剪切/分割文本,以匹配 lettrine 所需的效果。但是,在\ref{label}命令內部使用時出現一些錯誤。

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

該問題與已啟用連結的包有關hyperref\StrBefore當面對字串中的連結時,該命令會出現一些錯誤。如果我禁用的話hyperref,使用時沒有問題\ref。但我需要使用hyperref.您對解決這個問題有什麼建議嗎?謝謝。

微量元素:

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

和錯誤:

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

答案1

的展開\ref...會導致錯誤。但是,xstring知道\noexpandarg宏,從而防止將主輸入字串的參數擴展為xstring宏,但在第一個操作之後必須再次啟用擴展,使用\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}

在此輸入影像描述

答案2

在我看來,這過於複雜了。為什麼會有\StrBefore等等處理?為什麼需要letrine包裹?您可以透過以下方式執行相同操作:

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

許多問題的發生是因為人們不知道事情可以做得更簡單。

編輯:由於 David 的評論,我修改了\openitroA定義,以便其行為類似於具有更多行的文本的 letrine 用法。

答案3

我正在回答我自己的問題,透過使用 @wipet 和 lettrine 提供的部分程式碼(因為操作文字樣式更容易)。我沒有使用第一個問題的整個字串操作,而是使用以下程式碼(替換整個\newcommand{\openintro}):

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

我要再次感謝@ChristianHupfer、@wipet 和@DavidCarlisle 的幫助。

相關內容